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 1393793999 Lines: 55 91 60.4 %
Date: 2014-03-02 Functions: 8 10 80.0 %
Branches: 34 66 51.5 %

           Branch data     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                 :        773 : const struct eap_method * eap_peer_get_eap_method(int vendor, EapType method)
      29                 :            : {
      30                 :            :         struct eap_method *m;
      31         [ +  - ]:      10240 :         for (m = eap_methods; m; m = m->next) {
      32 [ +  + ][ +  + ]:      10240 :                 if (m->vendor == vendor && m->method == method)
      33                 :        773 :                         return m;
      34                 :            :         }
      35                 :        773 :         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                 :        352 : EapType eap_peer_get_type(const char *name, int *vendor)
      49                 :            : {
      50                 :            :         struct eap_method *m;
      51         [ +  + ]:       4642 :         for (m = eap_methods; m; m = m->next) {
      52         [ +  + ]:       4640 :                 if (os_strcmp(m->name, name) == 0) {
      53                 :        350 :                         *vendor = m->vendor;
      54                 :        350 :                         return m->method;
      55                 :            :                 }
      56                 :            :         }
      57                 :          2 :         *vendor = EAP_VENDOR_IETF;
      58                 :        352 :         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                 :        679 : const char * eap_get_name(int vendor, EapType type)
      72                 :            : {
      73                 :            :         struct eap_method *m;
      74 [ +  - ][ -  + ]:        679 :         if (vendor == EAP_VENDOR_IETF && type == EAP_TYPE_EXPANDED)
      75                 :          0 :                 return "expanded";
      76         [ +  + ]:       3566 :         for (m = eap_methods; m; m = m->next) {
      77 [ +  + ][ +  + ]:       3558 :                 if (m->vendor == vendor && m->method == type)
      78                 :        671 :                         return m->name;
      79                 :            :         }
      80                 :        679 :         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                 :          0 : 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         [ #  # ]:          0 :         if (buflen == 0)
      98                 :          0 :                 return 0;
      99                 :            : 
     100                 :          0 :         pos = buf;
     101                 :          0 :         end = pos + buflen;
     102                 :            : 
     103         [ #  # ]:          0 :         for (m = eap_methods; m; m = m->next) {
     104         [ #  # ]:          0 :                 ret = os_snprintf(pos, end - pos, "%s%s",
     105                 :          0 :                                   m == eap_methods ? "" : " ", m->name);
     106 [ #  # ][ #  # ]:          0 :                 if (ret < 0 || ret >= end - pos)
     107                 :            :                         break;
     108                 :          0 :                 pos += ret;
     109                 :            :         }
     110                 :          0 :         buf[buflen - 1] = '\0';
     111                 :            : 
     112                 :          0 :         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                 :          0 : char ** eap_get_names_as_string_array(size_t *num)
     127                 :            : {
     128                 :            :         struct eap_method *m;
     129                 :          0 :         size_t array_len = 0;
     130                 :            :         char **array;
     131                 :          0 :         int i = 0, j;
     132                 :            : 
     133         [ #  # ]:          0 :         for (m = eap_methods; m; m = m->next)
     134                 :          0 :                 array_len++;
     135                 :            : 
     136                 :          0 :         array = os_zalloc(sizeof(char *) * (array_len + 1));
     137         [ #  # ]:          0 :         if (array == NULL)
     138                 :          0 :                 return NULL;
     139                 :            : 
     140         [ #  # ]:          0 :         for (m = eap_methods; m; m = m->next) {
     141                 :          0 :                 array[i++] = os_strdup(m->name);
     142         [ #  # ]:          0 :                 if (array[i - 1] == NULL) {
     143         [ #  # ]:          0 :                         for (j = 0; j < i; j++)
     144                 :          0 :                                 os_free(array[j]);
     145                 :          0 :                         os_free(array);
     146                 :          0 :                         return NULL;
     147                 :            :                 }
     148                 :            :         }
     149                 :          0 :         array[i] = NULL;
     150                 :            : 
     151         [ #  # ]:          0 :         if (num)
     152                 :          0 :                 *num = array_len;
     153                 :            : 
     154                 :          0 :         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                 :         43 : const struct eap_method * eap_peer_get_methods(size_t *count)
     164                 :            : {
     165                 :         43 :         int c = 0;
     166                 :            :         struct eap_method *m;
     167                 :            : 
     168         [ +  + ]:       1075 :         for (m = eap_methods; m; m = m->next)
     169                 :       1032 :                 c++;
     170                 :            :         
     171                 :         43 :         *count = c;
     172                 :         43 :         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                 :         96 : struct eap_method * eap_peer_method_alloc(int version, int vendor,
     280                 :            :                                           EapType method, const char *name)
     281                 :            : {
     282                 :            :         struct eap_method *eap;
     283                 :         96 :         eap = os_zalloc(sizeof(*eap));
     284         [ -  + ]:         96 :         if (eap == NULL)
     285                 :          0 :                 return NULL;
     286                 :         96 :         eap->version = version;
     287                 :         96 :         eap->vendor = vendor;
     288                 :         96 :         eap->method = method;
     289                 :         96 :         eap->name = name;
     290                 :         96 :         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                 :         96 : void eap_peer_method_free(struct eap_method *method)
     299                 :            : {
     300                 :         96 :         os_free(method);
     301                 :         96 : }
     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                 :         96 : int eap_peer_method_register(struct eap_method *method)
     314                 :            : {
     315                 :         96 :         struct eap_method *m, *last = NULL;
     316                 :            : 
     317 [ +  - ][ +  - ]:         96 :         if (method == NULL || method->name == NULL ||
                 [ -  + ]
     318                 :         96 :             method->version != EAP_PEER_METHOD_INTERFACE_VERSION)
     319                 :          0 :                 return -1;
     320                 :            : 
     321         [ +  + ]:       1200 :         for (m = eap_methods; m; m = m->next) {
     322 [ +  + ][ +  - ]:       1104 :                 if ((m->vendor == method->vendor &&
     323         [ -  + ]:       1104 :                      m->method == method->method) ||
     324                 :       1104 :                     os_strcmp(m->name, method->name) == 0)
     325                 :          0 :                         return -2;
     326                 :       1104 :                 last = m;
     327                 :            :         }
     328                 :            : 
     329         [ +  + ]:         96 :         if (last)
     330                 :         92 :                 last->next = method;
     331                 :            :         else
     332                 :          4 :                 eap_methods = method;
     333                 :            : 
     334                 :         96 :         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                 :          4 : 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         [ +  + ]:        100 :         while (eap_methods) {
     352                 :         96 :                 m = eap_methods;
     353                 :         96 :                 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         [ -  + ]:         96 :                 if (m->free)
     360                 :          0 :                         m->free(m);
     361                 :            :                 else
     362                 :         96 :                         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                 :          4 : }

Generated by: LCOV version 1.9