LCOV - code coverage report
Current view: top level - src/eap_peer - eap_methods.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1443382998 Lines: 84 92 91.3 %
Date: 2015-09-27 Functions: 10 10 100.0 %

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

Generated by: LCOV version 1.10