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

Generated by: LCOV version 1.10