~ubuntu-branches/ubuntu/oneiric/wpasupplicant/oneiric

« back to all changes in this revision

Viewing changes to eap_methods.c

  • Committer: Bazaar Package Importer
  • Author(s): Kel Modderman
  • Date: 2006-10-05 08:04:01 UTC
  • mfrom: (1.2.1 upstream) (2.1.14 edgy)
  • Revision ID: james.westby@ubuntu.com-20061005080401-myfwjtq7di70dyeo
* Update madwifi headers to latest SVN. (Closes: #388316)
* Remove failed attempt at action locking. [debian/functions.sh,
  debian/wpa_action.sh]
* Add hysteresis checking functions, to avoid "event loops" while
  using wpa-roam. [debian/functions.sh, debian/wpa_action.sh]
* Change of co-maintainer email address.
* Add ishex() function to functions.sh to determine wpa-psk value type in
  plaintext or hex. This effectively eliminates the need for the bogus and
  somewhat confusing wpa-passphrase contruct specific to our scripts and
  allows wpa-psk to work with either a 8 to 63 character long plaintext
  string or 64 character long hex string.
* Adjust README.modes to not refer to the redundant wpa-passphrase stuff.
* Add big fat NOTE about acceptable wpa-psk's to top of example gallery.
* Strip surrounding quotes from wpa-ssid if present, instead of just whining
  about them.
* Update email address in copyright blurb of functions.sh, ifupdown.sh and
  wpa_action.sh.  

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * EAP peer: Method registration
 
3
 * Copyright (c) 2004-2006, Jouni Malinen <jkmaline@cc.hut.fi>
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or modify
 
6
 * it under the terms of the GNU General Public License version 2 as
 
7
 * published by the Free Software Foundation.
 
8
 *
 
9
 * Alternatively, this software may be distributed under the terms of BSD
 
10
 * license.
 
11
 *
 
12
 * See README and COPYING for more details.
 
13
 */
 
14
 
 
15
#include "includes.h"
 
16
#ifdef CONFIG_DYNAMIC_EAP_METHODS
 
17
#include <dlfcn.h>
 
18
#endif /* CONFIG_DYNAMIC_EAP_METHODS */
 
19
 
 
20
#include "common.h"
 
21
#include "eap_i.h"
 
22
#include "eap_methods.h"
 
23
 
 
24
 
 
25
static struct eap_method *eap_methods = NULL;
 
26
 
 
27
 
 
28
/**
 
29
 * eap_sm_get_eap_methods - Get EAP method based on type number
 
30
 * @vendor: EAP Vendor-Id (0 = IETF)
 
31
 * @method: EAP type number
 
32
 * Returns: Pointer to EAP method or %NULL if not found
 
33
 */
 
34
const struct eap_method * eap_sm_get_eap_methods(int vendor, EapType method)
 
35
{
 
36
        struct eap_method *m;
 
37
        for (m = eap_methods; m; m = m->next) {
 
38
                if (m->vendor == vendor && m->method == method)
 
39
                        return m;
 
40
        }
 
41
        return NULL;
 
42
}
 
43
 
 
44
 
 
45
/**
 
46
 * eap_get_type - Get EAP type for the given EAP method name
 
47
 * @name: EAP method name, e.g., TLS
 
48
 * @vendor: Buffer for returning EAP Vendor-Id
 
49
 * Returns: EAP method type or %EAP_TYPE_NONE if not found
 
50
 *
 
51
 * This function maps EAP type names into EAP type numbers based on the list of
 
52
 * EAP methods included in the build.
 
53
 */
 
54
EapType eap_get_type(const char *name, int *vendor)
 
55
{
 
56
        struct eap_method *m;
 
57
        for (m = eap_methods; m; m = m->next) {
 
58
                if (strcmp(m->name, name) == 0) {
 
59
                        *vendor = m->vendor;
 
60
                        return m->method;
 
61
                }
 
62
        }
 
63
        *vendor = EAP_VENDOR_IETF;
 
64
        return EAP_TYPE_NONE;
 
65
}
 
66
 
 
67
 
 
68
/**
 
69
 * eap_get_name - Get EAP method name for the given EAP type
 
70
 * @vendor: EAP Vendor-Id (0 = IETF)
 
71
 * @type: EAP method type
 
72
 * Returns: EAP method name, e.g., TLS, or %NULL if not found
 
73
 *
 
74
 * This function maps EAP type numbers into EAP type names based on the list of
 
75
 * EAP methods included in the build.
 
76
 */
 
77
const char * eap_get_name(int vendor, EapType type)
 
78
{
 
79
        struct eap_method *m;
 
80
        for (m = eap_methods; m; m = m->next) {
 
81
                if (m->vendor == vendor && m->method == type)
 
82
                        return m->name;
 
83
        }
 
84
        return NULL;
 
85
}
 
86
 
 
87
 
 
88
/**
 
89
 * eap_get_names - Get space separated list of names for supported EAP methods
 
90
 * @buf: Buffer for names
 
91
 * @buflen: Buffer length
 
92
 * Returns: Number of characters written into buf (not including nul
 
93
 * termination)
 
94
 */
 
95
size_t eap_get_names(char *buf, size_t buflen)
 
96
{
 
97
        char *pos, *end;
 
98
        struct eap_method *m;
 
99
        int ret;
 
100
 
 
101
        if (buflen == 0)
 
102
                return 0;
 
103
 
 
104
        pos = buf;
 
105
        end = pos + buflen;
 
106
 
 
107
        for (m = eap_methods; m; m = m->next) {
 
108
                ret = snprintf(pos, end - pos, "%s%s",
 
109
                               m == eap_methods ? "" : " ", m->name);
 
110
                if (ret < 0 || ret >= end - pos)
 
111
                        break;
 
112
                pos += ret;
 
113
        }
 
114
        buf[buflen - 1] = '\0';
 
115
 
 
116
        return pos - buf;
 
117
}
 
118
 
 
119
 
 
120
/**
 
121
 * eap_get_names_as_string_array - Get supported EAP methods as string array
 
122
 * @len: Buffer for returning the number of items in array, not including %NULL
 
123
 * terminator. This parameter can be %NULL if the length is not needed.
 
124
 * Returns: A %NULL-terminated array of strings, or %NULL on error.
 
125
 *
 
126
 * This function returns the list of names for all supported EAP methods as an
 
127
 * array of strings. The caller must free the returned array items and the
 
128
 * array.
 
129
 */
 
130
char ** eap_get_names_as_string_array(size_t *num)
 
131
{
 
132
        struct eap_method *m;
 
133
        size_t array_len = 0;
 
134
        char **array;
 
135
        int i = 0;
 
136
 
 
137
        for (m = eap_methods; m; m = m->next)
 
138
                array_len++;
 
139
 
 
140
        array = wpa_zalloc(sizeof(char *) * (array_len + 1));
 
141
        if (array == NULL)
 
142
                return NULL;
 
143
 
 
144
        for (m = eap_methods; m; m = m->next)
 
145
                array[i++] = strdup(m->name);
 
146
        array[i] = NULL;
 
147
 
 
148
        if (num)
 
149
                *num = array_len;
 
150
 
 
151
        return array;
 
152
}
 
153
 
 
154
 
 
155
/**
 
156
 * eap_peer_get_methods - Get a list of enabled EAP peer methods
 
157
 * @count: Set to number of available methods
 
158
 * Returns: List of enabled EAP peer methods
 
159
 */
 
160
const struct eap_method * eap_peer_get_methods(size_t *count)
 
161
{
 
162
        int c = 0;
 
163
        struct eap_method *m;
 
164
 
 
165
        for (m = eap_methods; m; m = m->next)
 
166
                c++;
 
167
        
 
168
        *count = c;
 
169
        return eap_methods;
 
170
}
 
171
 
 
172
 
 
173
#ifdef CONFIG_DYNAMIC_EAP_METHODS
 
174
/**
 
175
 * eap_peer_method_load - Load a dynamic EAP method library (shared object)
 
176
 * @so: File path for the shared object file to load
 
177
 * Returns: 0 on success, -1 on failure
 
178
 */
 
179
int eap_peer_method_load(const char *so)
 
180
{
 
181
        void *handle;
 
182
        int (*dyn_init)(void);
 
183
        int ret;
 
184
 
 
185
        handle = dlopen(so, RTLD_LAZY);
 
186
        if (handle == NULL) {
 
187
                wpa_printf(MSG_ERROR, "EAP: Failed to open dynamic EAP method "
 
188
                           "'%s': %s", so, dlerror());
 
189
                return -1;
 
190
        }
 
191
 
 
192
        dyn_init = dlsym(handle, "eap_peer_method_dynamic_init");
 
193
        if (dyn_init == NULL) {
 
194
                dlclose(handle);
 
195
                wpa_printf(MSG_ERROR, "EAP: Invalid EAP method '%s' - no "
 
196
                           "eap_peer_method_dynamic_init()", so);
 
197
                return -1;
 
198
        }
 
199
 
 
200
        ret = dyn_init();
 
201
        if (ret) {
 
202
                dlclose(handle);
 
203
                wpa_printf(MSG_ERROR, "EAP: Failed to add EAP method '%s' - "
 
204
                           "ret %d", so, ret);
 
205
                return ret;
 
206
        }
 
207
 
 
208
        /* Store the handle for this shared object. It will be freed with
 
209
         * dlclose() when the EAP method is unregistered. */
 
210
        eap_methods->dl_handle = handle;
 
211
 
 
212
        wpa_printf(MSG_DEBUG, "EAP: Loaded dynamic EAP method: '%s'", so);
 
213
 
 
214
        return 0;
 
215
}
 
216
 
 
217
 
 
218
/**
 
219
 * eap_peer_method_unload - Unload a dynamic EAP method library (shared object)
 
220
 * @method: Pointer to the dynamically loaded EAP method
 
221
 * Returns: 0 on success, -1 on failure
 
222
 *
 
223
 * This function can be used to unload EAP methods that have been previously
 
224
 * loaded with eap_peer_method_load(). Before unloading the method, all
 
225
 * references to the method must be removed to make sure that no dereferences
 
226
 * of freed memory will occur after unloading.
 
227
 */
 
228
int eap_peer_method_unload(struct eap_method *method)
 
229
{
 
230
        struct eap_method *m, *prev;
 
231
        void *handle;
 
232
 
 
233
        m = eap_methods;
 
234
        prev = NULL;
 
235
        while (m) {
 
236
                if (m == method) {
 
237
                        prev = m;
 
238
                        break;
 
239
                }
 
240
                m = m->next;
 
241
        }
 
242
 
 
243
        if (m == NULL || m->dl_handle == NULL)
 
244
                return -1;
 
245
 
 
246
        if (prev)
 
247
                prev->next = m->next;
 
248
        else
 
249
                eap_methods = m->next;
 
250
 
 
251
        handle = m->dl_handle;
 
252
 
 
253
        if (m->free)
 
254
                m->free(m);
 
255
        else
 
256
                eap_peer_method_free(m);
 
257
 
 
258
        dlclose(handle);
 
259
 
 
260
        return 0;
 
261
}
 
262
#endif /* CONFIG_DYNAMIC_EAP_METHODS */
 
263
 
 
264
 
 
265
/**
 
266
 * eap_peer_method_alloc - Allocate EAP peer method structure
 
267
 * @version: Version of the EAP peer method interface (set to
 
268
 * EAP_PEER_METHOD_INTERFACE_VERSION)
 
269
 * @vendor: EAP Vendor-ID (EAP_VENDOR_*) (0 = IETF)
 
270
 * @method: EAP type number (EAP_TYPE_*)
 
271
 * name: Name of the method (e.g., "TLS")
 
272
 * Returns: Allocated EAP method structure or %NULL on failure
 
273
 *
 
274
 * The returned structure should be freed with eap_peer_method_free() when it
 
275
 * is not needed anymore.
 
276
 */
 
277
struct eap_method * eap_peer_method_alloc(int version, int vendor,
 
278
                                          EapType method, const char *name)
 
279
{
 
280
        struct eap_method *eap;
 
281
        eap = wpa_zalloc(sizeof(*eap));
 
282
        if (eap == NULL)
 
283
                return NULL;
 
284
        eap->version = version;
 
285
        eap->vendor = vendor;
 
286
        eap->method = method;
 
287
        eap->name = name;
 
288
        return eap;
 
289
}
 
290
 
 
291
 
 
292
/**
 
293
 * eap_peer_method_free - Free EAP peer method structure
 
294
 * @method: Method structure allocated with eap_peer_method_alloc()
 
295
 */
 
296
void eap_peer_method_free(struct eap_method *method)
 
297
{
 
298
        free(method);
 
299
}
 
300
 
 
301
 
 
302
/**
 
303
 * eap_peer_method_register - Register an EAP peer method
 
304
 * @method: EAP method to register
 
305
 * Returns: 0 on success, -1 on invalid method, or -2 if a matching EAP method
 
306
 * has already been registered
 
307
 *
 
308
 * Each EAP peer method needs to call this function to register itself as a
 
309
 * supported EAP method.
 
310
 */
 
311
int eap_peer_method_register(struct eap_method *method)
 
312
{
 
313
        struct eap_method *m, *last = NULL;
 
314
 
 
315
        if (method == NULL || method->name == NULL ||
 
316
            method->version != EAP_PEER_METHOD_INTERFACE_VERSION)
 
317
                return -1;
 
318
 
 
319
        for (m = eap_methods; m; m = m->next) {
 
320
                if ((m->vendor == method->vendor &&
 
321
                     m->method == method->method) ||
 
322
                    strcmp(m->name, method->name) == 0)
 
323
                        return -2;
 
324
                last = m;
 
325
        }
 
326
 
 
327
        if (last)
 
328
                last->next = method;
 
329
        else
 
330
                eap_methods = method;
 
331
 
 
332
        return 0;
 
333
}
 
334
 
 
335
 
 
336
/**
 
337
 * eap_peer_register_methods - Register statically linked EAP peer methods
 
338
 * Returns: 0 on success, -1 on failure
 
339
 *
 
340
 * This function is called at program initialization to register all EAP peer
 
341
 * methods that were linked in statically.
 
342
 */
 
343
int eap_peer_register_methods(void)
 
344
{
 
345
        int ret = 0;
 
346
 
 
347
#ifdef EAP_MD5
 
348
        if (ret == 0) {
 
349
                int eap_peer_md5_register(void);
 
350
                ret = eap_peer_md5_register();
 
351
        }
 
352
#endif /* EAP_MD5 */
 
353
 
 
354
#ifdef EAP_TLS
 
355
        if (ret == 0) {
 
356
                int eap_peer_tls_register(void);
 
357
                ret = eap_peer_tls_register();
 
358
        }
 
359
#endif /* EAP_TLS */
 
360
 
 
361
#ifdef EAP_MSCHAPv2
 
362
        if (ret == 0) {
 
363
                int eap_peer_mschapv2_register(void);
 
364
                ret = eap_peer_mschapv2_register();
 
365
        }
 
366
#endif /* EAP_MSCHAPv2 */
 
367
 
 
368
#ifdef EAP_PEAP
 
369
        if (ret == 0) {
 
370
                int eap_peer_peap_register(void);
 
371
                ret = eap_peer_peap_register();
 
372
        }
 
373
#endif /* EAP_PEAP */
 
374
 
 
375
#ifdef EAP_TTLS
 
376
        if (ret == 0) {
 
377
                int eap_peer_ttls_register(void);
 
378
                ret = eap_peer_ttls_register();
 
379
        }
 
380
#endif /* EAP_TTLS */
 
381
 
 
382
#ifdef EAP_GTC
 
383
        if (ret == 0) {
 
384
                int eap_peer_gtc_register(void);
 
385
                ret = eap_peer_gtc_register();
 
386
        }
 
387
#endif /* EAP_GTC */
 
388
 
 
389
#ifdef EAP_OTP
 
390
        if (ret == 0) {
 
391
                int eap_peer_otp_register(void);
 
392
                ret = eap_peer_otp_register();
 
393
        }
 
394
#endif /* EAP_OTP */
 
395
 
 
396
#ifdef EAP_SIM
 
397
        if (ret == 0) {
 
398
                int eap_peer_sim_register(void);
 
399
                ret = eap_peer_sim_register();
 
400
        }
 
401
#endif /* EAP_SIM */
 
402
 
 
403
#ifdef EAP_LEAP
 
404
        if (ret == 0) {
 
405
                int eap_peer_leap_register(void);
 
406
                ret = eap_peer_leap_register();
 
407
        }
 
408
#endif /* EAP_LEAP */
 
409
 
 
410
#ifdef EAP_PSK
 
411
        if (ret == 0) {
 
412
                int eap_peer_psk_register(void);
 
413
                ret = eap_peer_psk_register();
 
414
        }
 
415
#endif /* EAP_PSK */
 
416
 
 
417
#ifdef EAP_AKA
 
418
        if (ret == 0) {
 
419
                int eap_peer_aka_register(void);
 
420
                ret = eap_peer_aka_register();
 
421
        }
 
422
#endif /* EAP_AKA */
 
423
 
 
424
#ifdef EAP_FAST
 
425
        if (ret == 0) {
 
426
                int eap_peer_fast_register(void);
 
427
                ret = eap_peer_fast_register();
 
428
        }
 
429
#endif /* EAP_FAST */
 
430
 
 
431
#ifdef EAP_PAX
 
432
        if (ret == 0) {
 
433
                int eap_peer_pax_register(void);
 
434
                ret = eap_peer_pax_register();
 
435
        }
 
436
#endif /* EAP_PAX */
 
437
 
 
438
#ifdef EAP_SAKE
 
439
        if (ret == 0) {
 
440
                int eap_peer_sake_register(void);
 
441
                ret = eap_peer_sake_register();
 
442
        }
 
443
#endif /* EAP_SAKE */
 
444
 
 
445
#ifdef EAP_GPSK
 
446
        if (ret == 0) {
 
447
                int eap_peer_gpsk_register(void);
 
448
                ret = eap_peer_gpsk_register();
 
449
        }
 
450
#endif /* EAP_GPSK */
 
451
 
 
452
#ifdef EAP_VENDOR_TEST
 
453
        if (ret == 0) {
 
454
                int eap_peer_vendor_test_register(void);
 
455
                ret = eap_peer_vendor_test_register();
 
456
        }
 
457
#endif /* EAP_VENDOR_TEST */
 
458
 
 
459
        return ret;
 
460
}
 
461
 
 
462
 
 
463
/**
 
464
 * eap_peer_unregister_methods - Unregister EAP peer methods
 
465
 *
 
466
 * This function is called at program termination to unregister all EAP peer
 
467
 * methods.
 
468
 */
 
469
void eap_peer_unregister_methods(void)
 
470
{
 
471
        struct eap_method *m;
 
472
#ifdef CONFIG_DYNAMIC_EAP_METHODS
 
473
        void *handle;
 
474
#endif /* CONFIG_DYNAMIC_EAP_METHODS */
 
475
 
 
476
        while (eap_methods) {
 
477
                m = eap_methods;
 
478
                eap_methods = eap_methods->next;
 
479
 
 
480
#ifdef CONFIG_DYNAMIC_EAP_METHODS
 
481
                handle = m->dl_handle;
 
482
#endif /* CONFIG_DYNAMIC_EAP_METHODS */
 
483
 
 
484
                if (m->free)
 
485
                        m->free(m);
 
486
                else
 
487
                        eap_peer_method_free(m);
 
488
 
 
489
#ifdef CONFIG_DYNAMIC_EAP_METHODS
 
490
                if (handle)
 
491
                        dlclose(handle);
 
492
#endif /* CONFIG_DYNAMIC_EAP_METHODS */
 
493
        }
 
494
}