eap_methods.c 11 KB

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