eap_methods.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. /*
  2. * EAP peer: Method registration
  3. * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
  4. *
  5. * This software may be distributed under the terms of the BSD license.
  6. * See README for more details.
  7. */
  8. #include "includes.h"
  9. #ifdef CONFIG_DYNAMIC_EAP_METHODS
  10. #include <dlfcn.h>
  11. #endif /* CONFIG_DYNAMIC_EAP_METHODS */
  12. #include "common.h"
  13. #include "eap_i.h"
  14. #include "eap_methods.h"
  15. static struct eap_method *eap_methods = NULL;
  16. /**
  17. * eap_peer_get_eap_method - Get EAP method based on type number
  18. * @vendor: EAP Vendor-Id (0 = IETF)
  19. * @method: EAP type number
  20. * Returns: Pointer to EAP method or %NULL if not found
  21. */
  22. const struct eap_method * eap_peer_get_eap_method(int vendor, EapType method)
  23. {
  24. struct eap_method *m;
  25. for (m = eap_methods; m; m = m->next) {
  26. if (m->vendor == vendor && m->method == method)
  27. return m;
  28. }
  29. return NULL;
  30. }
  31. /**
  32. * eap_peer_get_type - Get EAP type for the given EAP method name
  33. * @name: EAP method name, e.g., TLS
  34. * @vendor: Buffer for returning EAP Vendor-Id
  35. * Returns: EAP method type or %EAP_TYPE_NONE if not found
  36. *
  37. * This function maps EAP type names into EAP type numbers based on the list of
  38. * EAP methods included in the build.
  39. */
  40. EapType eap_peer_get_type(const char *name, int *vendor)
  41. {
  42. struct eap_method *m;
  43. for (m = eap_methods; m; m = m->next) {
  44. if (os_strcmp(m->name, name) == 0) {
  45. *vendor = m->vendor;
  46. return m->method;
  47. }
  48. }
  49. *vendor = EAP_VENDOR_IETF;
  50. return EAP_TYPE_NONE;
  51. }
  52. /**
  53. * eap_get_name - Get EAP method name for the given EAP type
  54. * @vendor: EAP Vendor-Id (0 = IETF)
  55. * @type: EAP method type
  56. * Returns: EAP method name, e.g., TLS, or %NULL if not found
  57. *
  58. * This function maps EAP type numbers into EAP type names based on the list of
  59. * EAP methods included in the build.
  60. */
  61. const char * eap_get_name(int vendor, EapType type)
  62. {
  63. struct eap_method *m;
  64. if (vendor == EAP_VENDOR_IETF && type == EAP_TYPE_EXPANDED)
  65. return "expanded";
  66. for (m = eap_methods; m; m = m->next) {
  67. if (m->vendor == vendor && m->method == type)
  68. return m->name;
  69. }
  70. return NULL;
  71. }
  72. /**
  73. * eap_get_names - Get space separated list of names for supported EAP methods
  74. * @buf: Buffer for names
  75. * @buflen: Buffer length
  76. * Returns: Number of characters written into buf (not including nul
  77. * termination)
  78. */
  79. size_t eap_get_names(char *buf, size_t buflen)
  80. {
  81. char *pos, *end;
  82. struct eap_method *m;
  83. int ret;
  84. if (buflen == 0)
  85. return 0;
  86. pos = buf;
  87. end = pos + buflen;
  88. for (m = eap_methods; m; m = m->next) {
  89. ret = os_snprintf(pos, end - pos, "%s%s",
  90. m == eap_methods ? "" : " ", m->name);
  91. if (ret < 0 || ret >= end - pos)
  92. break;
  93. pos += ret;
  94. }
  95. buf[buflen - 1] = '\0';
  96. return pos - buf;
  97. }
  98. /**
  99. * eap_get_names_as_string_array - Get supported EAP methods as string array
  100. * @num: Buffer for returning the number of items in array, not including %NULL
  101. * terminator. This parameter can be %NULL if the length is not needed.
  102. * Returns: A %NULL-terminated array of strings, or %NULL on error.
  103. *
  104. * This function returns the list of names for all supported EAP methods as an
  105. * array of strings. The caller must free the returned array items and the
  106. * array.
  107. */
  108. char ** eap_get_names_as_string_array(size_t *num)
  109. {
  110. struct eap_method *m;
  111. size_t array_len = 0;
  112. char **array;
  113. int i = 0, j;
  114. for (m = eap_methods; m; m = m->next)
  115. array_len++;
  116. array = os_zalloc(sizeof(char *) * (array_len + 1));
  117. if (array == NULL)
  118. return NULL;
  119. for (m = eap_methods; m; m = m->next) {
  120. array[i++] = os_strdup(m->name);
  121. if (array[i - 1] == NULL) {
  122. for (j = 0; j < i; j++)
  123. os_free(array[j]);
  124. os_free(array);
  125. return NULL;
  126. }
  127. }
  128. array[i] = NULL;
  129. if (num)
  130. *num = array_len;
  131. return array;
  132. }
  133. /**
  134. * eap_peer_get_methods - Get a list of enabled EAP peer methods
  135. * @count: Set to number of available methods
  136. * Returns: List of enabled EAP peer methods
  137. */
  138. const struct eap_method * eap_peer_get_methods(size_t *count)
  139. {
  140. int c = 0;
  141. struct eap_method *m;
  142. for (m = eap_methods; m; m = m->next)
  143. c++;
  144. *count = c;
  145. return eap_methods;
  146. }
  147. #ifdef CONFIG_DYNAMIC_EAP_METHODS
  148. /**
  149. * eap_peer_method_load - Load a dynamic EAP method library (shared object)
  150. * @so: File path for the shared object file to load
  151. * Returns: 0 on success, -1 on failure
  152. */
  153. int eap_peer_method_load(const char *so)
  154. {
  155. void *handle;
  156. int (*dyn_init)(void);
  157. int ret;
  158. handle = dlopen(so, RTLD_LAZY);
  159. if (handle == NULL) {
  160. wpa_printf(MSG_ERROR, "EAP: Failed to open dynamic EAP method "
  161. "'%s': %s", so, dlerror());
  162. return -1;
  163. }
  164. dyn_init = dlsym(handle, "eap_peer_method_dynamic_init");
  165. if (dyn_init == NULL) {
  166. dlclose(handle);
  167. wpa_printf(MSG_ERROR, "EAP: Invalid EAP method '%s' - no "
  168. "eap_peer_method_dynamic_init()", so);
  169. return -1;
  170. }
  171. ret = dyn_init();
  172. if (ret) {
  173. dlclose(handle);
  174. wpa_printf(MSG_ERROR, "EAP: Failed to add EAP method '%s' - "
  175. "ret %d", so, ret);
  176. return ret;
  177. }
  178. /* Store the handle for this shared object. It will be freed with
  179. * dlclose() when the EAP method is unregistered. */
  180. eap_methods->dl_handle = handle;
  181. wpa_printf(MSG_DEBUG, "EAP: Loaded dynamic EAP method: '%s'", so);
  182. return 0;
  183. }
  184. /**
  185. * eap_peer_method_unload - Unload a dynamic EAP method library (shared object)
  186. * @method: Pointer to the dynamically loaded EAP method
  187. * Returns: 0 on success, -1 on failure
  188. *
  189. * This function can be used to unload EAP methods that have been previously
  190. * loaded with eap_peer_method_load(). Before unloading the method, all
  191. * references to the method must be removed to make sure that no dereferences
  192. * of freed memory will occur after unloading.
  193. */
  194. int eap_peer_method_unload(struct eap_method *method)
  195. {
  196. struct eap_method *m, *prev;
  197. void *handle;
  198. m = eap_methods;
  199. prev = NULL;
  200. while (m) {
  201. if (m == method)
  202. break;
  203. prev = m;
  204. m = m->next;
  205. }
  206. if (m == NULL || m->dl_handle == NULL)
  207. return -1;
  208. if (prev)
  209. prev->next = m->next;
  210. else
  211. eap_methods = m->next;
  212. handle = m->dl_handle;
  213. if (m->free)
  214. m->free(m);
  215. else
  216. eap_peer_method_free(m);
  217. dlclose(handle);
  218. return 0;
  219. }
  220. #endif /* CONFIG_DYNAMIC_EAP_METHODS */
  221. /**
  222. * eap_peer_method_alloc - Allocate EAP peer method structure
  223. * @version: Version of the EAP peer method interface (set to
  224. * EAP_PEER_METHOD_INTERFACE_VERSION)
  225. * @vendor: EAP Vendor-ID (EAP_VENDOR_*) (0 = IETF)
  226. * @method: EAP type number (EAP_TYPE_*)
  227. * @name: Name of the method (e.g., "TLS")
  228. * Returns: Allocated EAP method structure or %NULL on failure
  229. *
  230. * The returned structure should be freed with eap_peer_method_free() when it
  231. * is not needed anymore.
  232. */
  233. struct eap_method * eap_peer_method_alloc(int version, int vendor,
  234. EapType method, const char *name)
  235. {
  236. struct eap_method *eap;
  237. eap = os_zalloc(sizeof(*eap));
  238. if (eap == NULL)
  239. return NULL;
  240. eap->version = version;
  241. eap->vendor = vendor;
  242. eap->method = method;
  243. eap->name = name;
  244. return eap;
  245. }
  246. /**
  247. * eap_peer_method_free - Free EAP peer method structure
  248. * @method: Method structure allocated with eap_peer_method_alloc()
  249. */
  250. void eap_peer_method_free(struct eap_method *method)
  251. {
  252. os_free(method);
  253. }
  254. /**
  255. * eap_peer_method_register - Register an EAP peer method
  256. * @method: EAP method to register
  257. * Returns: 0 on success, -1 on invalid method, or -2 if a matching EAP method
  258. * has already been registered
  259. *
  260. * Each EAP peer method needs to call this function to register itself as a
  261. * supported EAP method.
  262. */
  263. int eap_peer_method_register(struct eap_method *method)
  264. {
  265. struct eap_method *m, *last = NULL;
  266. if (method == NULL || method->name == NULL ||
  267. method->version != EAP_PEER_METHOD_INTERFACE_VERSION)
  268. return -1;
  269. for (m = eap_methods; m; m = m->next) {
  270. if ((m->vendor == method->vendor &&
  271. m->method == method->method) ||
  272. os_strcmp(m->name, method->name) == 0)
  273. return -2;
  274. last = m;
  275. }
  276. if (last)
  277. last->next = method;
  278. else
  279. eap_methods = method;
  280. return 0;
  281. }
  282. /**
  283. * eap_peer_unregister_methods - Unregister EAP peer methods
  284. *
  285. * This function is called at program termination to unregister all EAP peer
  286. * methods.
  287. */
  288. void eap_peer_unregister_methods(void)
  289. {
  290. struct eap_method *m;
  291. #ifdef CONFIG_DYNAMIC_EAP_METHODS
  292. void *handle;
  293. #endif /* CONFIG_DYNAMIC_EAP_METHODS */
  294. while (eap_methods) {
  295. m = eap_methods;
  296. eap_methods = eap_methods->next;
  297. #ifdef CONFIG_DYNAMIC_EAP_METHODS
  298. handle = m->dl_handle;
  299. #endif /* CONFIG_DYNAMIC_EAP_METHODS */
  300. if (m->free)
  301. m->free(m);
  302. else
  303. eap_peer_method_free(m);
  304. #ifdef CONFIG_DYNAMIC_EAP_METHODS
  305. if (handle)
  306. dlclose(handle);
  307. #endif /* CONFIG_DYNAMIC_EAP_METHODS */
  308. }
  309. }