LCOV - code coverage report
Current view: top level - src/eap_peer - eap_fast_pac.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1393793999 Lines: 262 509 51.5 %
Date: 2014-03-02 Functions: 23 26 88.5 %
Branches: 120 294 40.8 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * EAP peer method: EAP-FAST PAC file processing
       3                 :            :  * Copyright (c) 2004-2006, 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                 :            : 
      11                 :            : #include "common.h"
      12                 :            : #include "eap_config.h"
      13                 :            : #include "eap_i.h"
      14                 :            : #include "eap_fast_pac.h"
      15                 :            : 
      16                 :            : /* TODO: encrypt PAC-Key in the PAC file */
      17                 :            : 
      18                 :            : 
      19                 :            : /* Text data format */
      20                 :            : static const char *pac_file_hdr =
      21                 :            :         "wpa_supplicant EAP-FAST PAC file - version 1";
      22                 :            : 
      23                 :            : /*
      24                 :            :  * Binary data format
      25                 :            :  * 4-octet magic value: 6A E4 92 0C
      26                 :            :  * 2-octet version (big endian)
      27                 :            :  * <version specific data>
      28                 :            :  *
      29                 :            :  * version=0:
      30                 :            :  * Sequence of PAC entries:
      31                 :            :  *   2-octet PAC-Type (big endian)
      32                 :            :  *   32-octet PAC-Key
      33                 :            :  *   2-octet PAC-Opaque length (big endian)
      34                 :            :  *   <variable len> PAC-Opaque data (length bytes)
      35                 :            :  *   2-octet PAC-Info length (big endian)
      36                 :            :  *   <variable len> PAC-Info data (length bytes)
      37                 :            :  */
      38                 :            : 
      39                 :            : #define EAP_FAST_PAC_BINARY_MAGIC 0x6ae4920c
      40                 :            : #define EAP_FAST_PAC_BINARY_FORMAT_VERSION 0
      41                 :            : 
      42                 :            : 
      43                 :            : /**
      44                 :            :  * eap_fast_free_pac - Free PAC data
      45                 :            :  * @pac: Pointer to the PAC entry
      46                 :            :  *
      47                 :            :  * Note that the PAC entry must not be in a list since this function does not
      48                 :            :  * remove the list links.
      49                 :            :  */
      50                 :          7 : void eap_fast_free_pac(struct eap_fast_pac *pac)
      51                 :            : {
      52                 :          7 :         os_free(pac->pac_opaque);
      53                 :          7 :         os_free(pac->pac_info);
      54                 :          7 :         os_free(pac->a_id);
      55                 :          7 :         os_free(pac->i_id);
      56                 :          7 :         os_free(pac->a_id_info);
      57                 :          7 :         os_free(pac);
      58                 :          7 : }
      59                 :            : 
      60                 :            : 
      61                 :            : /**
      62                 :            :  * eap_fast_get_pac - Get a PAC entry based on A-ID
      63                 :            :  * @pac_root: Pointer to root of the PAC list
      64                 :            :  * @a_id: A-ID to search for
      65                 :            :  * @a_id_len: Length of A-ID
      66                 :            :  * @pac_type: PAC-Type to search for
      67                 :            :  * Returns: Pointer to the PAC entry, or %NULL if A-ID not found
      68                 :            :  */
      69                 :         11 : struct eap_fast_pac * eap_fast_get_pac(struct eap_fast_pac *pac_root,
      70                 :            :                                        const u8 *a_id, size_t a_id_len,
      71                 :            :                                        u16 pac_type)
      72                 :            : {
      73                 :         11 :         struct eap_fast_pac *pac = pac_root;
      74                 :            : 
      75         [ +  + ]:         11 :         while (pac) {
      76 [ +  - ][ +  - ]:          3 :                 if (pac->pac_type == pac_type && pac->a_id_len == a_id_len &&
                 [ +  - ]
      77                 :          3 :                     os_memcmp(pac->a_id, a_id, a_id_len) == 0) {
      78                 :          3 :                         return pac;
      79                 :            :                 }
      80                 :          0 :                 pac = pac->next;
      81                 :            :         }
      82                 :         11 :         return NULL;
      83                 :            : }
      84                 :            : 
      85                 :            : 
      86                 :          4 : static void eap_fast_remove_pac(struct eap_fast_pac **pac_root,
      87                 :            :                                 struct eap_fast_pac **pac_current,
      88                 :            :                                 const u8 *a_id, size_t a_id_len, u16 pac_type)
      89                 :            : {
      90                 :            :         struct eap_fast_pac *pac, *prev;
      91                 :            : 
      92                 :          4 :         pac = *pac_root;
      93                 :          4 :         prev = NULL;
      94                 :            : 
      95         [ -  + ]:          4 :         while (pac) {
      96 [ #  # ][ #  # ]:          0 :                 if (pac->pac_type == pac_type && pac->a_id_len == a_id_len &&
                 [ #  # ]
      97                 :          0 :                     os_memcmp(pac->a_id, a_id, a_id_len) == 0) {
      98         [ #  # ]:          0 :                         if (prev == NULL)
      99                 :          0 :                                 *pac_root = pac->next;
     100                 :            :                         else
     101                 :          0 :                                 prev->next = pac->next;
     102         [ #  # ]:          0 :                         if (*pac_current == pac)
     103                 :          0 :                                 *pac_current = NULL;
     104                 :          0 :                         eap_fast_free_pac(pac);
     105                 :          0 :                         break;
     106                 :            :                 }
     107                 :          0 :                 prev = pac;
     108                 :          0 :                 pac = pac->next;
     109                 :            :         }
     110                 :          4 : }
     111                 :            : 
     112                 :            : 
     113                 :         20 : static int eap_fast_copy_buf(u8 **dst, size_t *dst_len,
     114                 :            :                              const u8 *src, size_t src_len)
     115                 :            : {
     116         [ +  - ]:         20 :         if (src) {
     117                 :         20 :                 *dst = os_malloc(src_len);
     118         [ -  + ]:         20 :                 if (*dst == NULL)
     119                 :          0 :                         return -1;
     120                 :         20 :                 os_memcpy(*dst, src, src_len);
     121                 :         20 :                 *dst_len = src_len;
     122                 :            :         }
     123                 :         20 :         return 0;
     124                 :            : }
     125                 :            : 
     126                 :            : 
     127                 :            : /**
     128                 :            :  * eap_fast_add_pac - Add a copy of a PAC entry to a list
     129                 :            :  * @pac_root: Pointer to PAC list root pointer
     130                 :            :  * @pac_current: Pointer to the current PAC pointer
     131                 :            :  * @entry: New entry to clone and add to the list
     132                 :            :  * Returns: 0 on success, -1 on failure
     133                 :            :  *
     134                 :            :  * This function makes a clone of the given PAC entry and adds this copied
     135                 :            :  * entry to the list (pac_root). If an old entry for the same A-ID is found,
     136                 :            :  * it will be removed from the PAC list and in this case, pac_current entry
     137                 :            :  * is set to %NULL if it was the removed entry.
     138                 :            :  */
     139                 :          4 : int eap_fast_add_pac(struct eap_fast_pac **pac_root,
     140                 :            :                      struct eap_fast_pac **pac_current,
     141                 :            :                      struct eap_fast_pac *entry)
     142                 :            : {
     143                 :            :         struct eap_fast_pac *pac;
     144                 :            : 
     145 [ +  - ][ -  + ]:          4 :         if (entry == NULL || entry->a_id == NULL)
     146                 :          0 :                 return -1;
     147                 :            : 
     148                 :            :         /* Remove a possible old entry for the matching A-ID. */
     149                 :          4 :         eap_fast_remove_pac(pac_root, pac_current,
     150                 :          8 :                             entry->a_id, entry->a_id_len, entry->pac_type);
     151                 :            : 
     152                 :            :         /* Allocate a new entry and add it to the list of PACs. */
     153                 :          4 :         pac = os_zalloc(sizeof(*pac));
     154         [ -  + ]:          4 :         if (pac == NULL)
     155                 :          0 :                 return -1;
     156                 :            : 
     157                 :          4 :         pac->pac_type = entry->pac_type;
     158                 :          4 :         os_memcpy(pac->pac_key, entry->pac_key, EAP_FAST_PAC_KEY_LEN);
     159         [ +  - ]:          4 :         if (eap_fast_copy_buf(&pac->pac_opaque, &pac->pac_opaque_len,
     160         [ +  - ]:          4 :                               entry->pac_opaque, entry->pac_opaque_len) < 0 ||
     161                 :          4 :             eap_fast_copy_buf(&pac->pac_info, &pac->pac_info_len,
     162         [ +  - ]:          4 :                               entry->pac_info, entry->pac_info_len) < 0 ||
     163                 :          4 :             eap_fast_copy_buf(&pac->a_id, &pac->a_id_len,
     164         [ +  - ]:          4 :                               entry->a_id, entry->a_id_len) < 0 ||
     165                 :          4 :             eap_fast_copy_buf(&pac->i_id, &pac->i_id_len,
     166         [ -  + ]:          4 :                               entry->i_id, entry->i_id_len) < 0 ||
     167                 :          4 :             eap_fast_copy_buf(&pac->a_id_info, &pac->a_id_info_len,
     168                 :          4 :                               entry->a_id_info, entry->a_id_info_len) < 0) {
     169                 :          0 :                 eap_fast_free_pac(pac);
     170                 :          0 :                 return -1;
     171                 :            :         }
     172                 :            : 
     173                 :          4 :         pac->next = *pac_root;
     174                 :          4 :         *pac_root = pac;
     175                 :            : 
     176                 :          4 :         return 0;
     177                 :            : }
     178                 :            : 
     179                 :            : 
     180                 :            : struct eap_fast_read_ctx {
     181                 :            :         FILE *f;
     182                 :            :         const char *pos;
     183                 :            :         const char *end;
     184                 :            :         int line;
     185                 :            :         char *buf;
     186                 :            :         size_t buf_len;
     187                 :            : };
     188                 :            : 
     189                 :         39 : static int eap_fast_read_line(struct eap_fast_read_ctx *rc, char **value)
     190                 :            : {
     191                 :            :         char *pos;
     192                 :            : 
     193                 :         39 :         rc->line++;
     194         [ -  + ]:         39 :         if (rc->f) {
     195         [ #  # ]:          0 :                 if (fgets(rc->buf, rc->buf_len, rc->f) == NULL)
     196                 :          0 :                         return -1;
     197                 :            :         } else {
     198                 :            :                 const char *l_end;
     199                 :            :                 size_t len;
     200         [ +  + ]:         39 :                 if (rc->pos >= rc->end)
     201                 :          3 :                         return -1;
     202                 :         36 :                 l_end = rc->pos;
     203 [ +  - ][ +  + ]:       1536 :                 while (l_end < rc->end && *l_end != '\n')
     204                 :       1500 :                         l_end++;
     205                 :         36 :                 len = l_end - rc->pos;
     206         [ -  + ]:         36 :                 if (len >= rc->buf_len)
     207                 :          0 :                         len = rc->buf_len - 1;
     208                 :         36 :                 os_memcpy(rc->buf, rc->pos, len);
     209                 :         36 :                 rc->buf[len] = '\0';
     210                 :         36 :                 rc->pos = l_end + 1;
     211                 :            :         }
     212                 :            : 
     213                 :         36 :         rc->buf[rc->buf_len - 1] = '\0';
     214                 :         36 :         pos = rc->buf;
     215         [ +  + ]:       1536 :         while (*pos != '\0') {
     216 [ +  - ][ -  + ]:       1500 :                 if (*pos == '\n' || *pos == '\r') {
     217                 :          0 :                         *pos = '\0';
     218                 :          0 :                         break;
     219                 :            :                 }
     220                 :       1500 :                 pos++;
     221                 :            :         }
     222                 :            : 
     223                 :         36 :         pos = os_strchr(rc->buf, '=');
     224         [ +  + ]:         36 :         if (pos)
     225                 :         27 :                 *pos++ = '\0';
     226                 :         36 :         *value = pos;
     227                 :            : 
     228                 :         39 :         return 0;
     229                 :            : }
     230                 :            : 
     231                 :            : 
     232                 :         15 : static u8 * eap_fast_parse_hex(const char *value, size_t *len)
     233                 :            : {
     234                 :            :         int hlen;
     235                 :            :         u8 *buf;
     236                 :            : 
     237         [ -  + ]:         15 :         if (value == NULL)
     238                 :          0 :                 return NULL;
     239                 :         15 :         hlen = os_strlen(value);
     240         [ -  + ]:         15 :         if (hlen & 1)
     241                 :          0 :                 return NULL;
     242                 :         15 :         *len = hlen / 2;
     243                 :         15 :         buf = os_malloc(*len);
     244         [ -  + ]:         15 :         if (buf == NULL)
     245                 :          0 :                 return NULL;
     246         [ -  + ]:         15 :         if (hexstr2bin(value, buf, *len)) {
     247                 :          0 :                 os_free(buf);
     248                 :          0 :                 return NULL;
     249                 :            :         }
     250                 :         15 :         return buf;
     251                 :            : }
     252                 :            : 
     253                 :            : 
     254                 :          7 : static int eap_fast_init_pac_data(struct eap_sm *sm, const char *pac_file,
     255                 :            :                                   struct eap_fast_read_ctx *rc)
     256                 :            : {
     257                 :          7 :         os_memset(rc, 0, sizeof(*rc));
     258                 :            : 
     259                 :          7 :         rc->buf_len = 2048;
     260                 :          7 :         rc->buf = os_malloc(rc->buf_len);
     261         [ -  + ]:          7 :         if (rc->buf == NULL)
     262                 :          0 :                 return -1;
     263                 :            : 
     264         [ +  - ]:          7 :         if (os_strncmp(pac_file, "blob://", 7) == 0) {
     265                 :            :                 const struct wpa_config_blob *blob;
     266                 :          7 :                 blob = eap_get_config_blob(sm, pac_file + 7);
     267         [ +  + ]:          7 :                 if (blob == NULL) {
     268                 :          4 :                         wpa_printf(MSG_INFO, "EAP-FAST: No PAC blob '%s' - "
     269                 :            :                                    "assume no PAC entries have been "
     270                 :            :                                    "provisioned", pac_file + 7);
     271                 :          4 :                         os_free(rc->buf);
     272                 :          4 :                         return -1;
     273                 :            :                 }
     274                 :          3 :                 rc->pos = (char *) blob->data;
     275                 :          3 :                 rc->end = (char *) blob->data + blob->len;
     276                 :            :         } else {
     277                 :          0 :                 rc->f = fopen(pac_file, "rb");
     278         [ #  # ]:          0 :                 if (rc->f == NULL) {
     279                 :          0 :                         wpa_printf(MSG_INFO, "EAP-FAST: No PAC file '%s' - "
     280                 :            :                                    "assume no PAC entries have been "
     281                 :            :                                    "provisioned", pac_file);
     282                 :          0 :                         os_free(rc->buf);
     283                 :          0 :                         return -1;
     284                 :            :                 }
     285                 :            :         }
     286                 :            : 
     287                 :          7 :         return 0;
     288                 :            : }
     289                 :            : 
     290                 :            : 
     291                 :          3 : static void eap_fast_deinit_pac_data(struct eap_fast_read_ctx *rc)
     292                 :            : {
     293                 :          3 :         os_free(rc->buf);
     294         [ -  + ]:          3 :         if (rc->f)
     295                 :          0 :                 fclose(rc->f);
     296                 :          3 : }
     297                 :            : 
     298                 :            : 
     299                 :          3 : static const char * eap_fast_parse_start(struct eap_fast_pac **pac)
     300                 :            : {
     301         [ -  + ]:          3 :         if (*pac)
     302                 :          0 :                 return "START line without END";
     303                 :            : 
     304                 :          3 :         *pac = os_zalloc(sizeof(struct eap_fast_pac));
     305         [ -  + ]:          3 :         if (*pac == NULL)
     306                 :          0 :                 return "No memory for PAC entry";
     307                 :          3 :         (*pac)->pac_type = PAC_TYPE_TUNNEL_PAC;
     308                 :          3 :         return NULL;
     309                 :            : }
     310                 :            : 
     311                 :            : 
     312                 :          3 : static const char * eap_fast_parse_end(struct eap_fast_pac **pac_root,
     313                 :            :                                        struct eap_fast_pac **pac)
     314                 :            : {
     315         [ -  + ]:          3 :         if (*pac == NULL)
     316                 :          0 :                 return "END line without START";
     317         [ -  + ]:          3 :         if (*pac_root) {
     318                 :          0 :                 struct eap_fast_pac *end = *pac_root;
     319         [ #  # ]:          0 :                 while (end->next)
     320                 :          0 :                         end = end->next;
     321                 :          0 :                 end->next = *pac;
     322                 :            :         } else
     323                 :          3 :                 *pac_root = *pac;
     324                 :            : 
     325                 :          3 :         *pac = NULL;
     326                 :          3 :         return NULL;
     327                 :            : }
     328                 :            : 
     329                 :            : 
     330                 :          3 : static const char * eap_fast_parse_pac_type(struct eap_fast_pac *pac,
     331                 :            :                                             char *pos)
     332                 :            : {
     333         [ -  + ]:          3 :         if (!pos)
     334                 :          0 :                 return "Cannot parse pac type";
     335                 :          3 :         pac->pac_type = atoi(pos);
     336 [ -  + ][ #  # ]:          3 :         if (pac->pac_type != PAC_TYPE_TUNNEL_PAC &&
     337         [ #  # ]:          0 :             pac->pac_type != PAC_TYPE_USER_AUTHORIZATION &&
     338                 :          0 :             pac->pac_type != PAC_TYPE_MACHINE_AUTHENTICATION)
     339                 :          0 :                 return "Unrecognized PAC-Type";
     340                 :            : 
     341                 :          3 :         return NULL;
     342                 :            : }
     343                 :            : 
     344                 :            : 
     345                 :          3 : static const char * eap_fast_parse_pac_key(struct eap_fast_pac *pac, char *pos)
     346                 :            : {
     347                 :            :         u8 *key;
     348                 :            :         size_t key_len;
     349                 :            : 
     350                 :          3 :         key = eap_fast_parse_hex(pos, &key_len);
     351 [ +  - ][ -  + ]:          3 :         if (key == NULL || key_len != EAP_FAST_PAC_KEY_LEN) {
     352                 :          0 :                 os_free(key);
     353                 :          0 :                 return "Invalid PAC-Key";
     354                 :            :         }
     355                 :            : 
     356                 :          3 :         os_memcpy(pac->pac_key, key, EAP_FAST_PAC_KEY_LEN);
     357                 :          3 :         os_free(key);
     358                 :            : 
     359                 :          3 :         return NULL;
     360                 :            : }
     361                 :            : 
     362                 :            : 
     363                 :          3 : static const char * eap_fast_parse_pac_opaque(struct eap_fast_pac *pac,
     364                 :            :                                               char *pos)
     365                 :            : {
     366                 :          3 :         os_free(pac->pac_opaque);
     367                 :          3 :         pac->pac_opaque = eap_fast_parse_hex(pos, &pac->pac_opaque_len);
     368         [ -  + ]:          3 :         if (pac->pac_opaque == NULL)
     369                 :          0 :                 return "Invalid PAC-Opaque";
     370                 :          3 :         return NULL;
     371                 :            : }
     372                 :            : 
     373                 :            : 
     374                 :          3 : static const char * eap_fast_parse_a_id(struct eap_fast_pac *pac, char *pos)
     375                 :            : {
     376                 :          3 :         os_free(pac->a_id);
     377                 :          3 :         pac->a_id = eap_fast_parse_hex(pos, &pac->a_id_len);
     378         [ -  + ]:          3 :         if (pac->a_id == NULL)
     379                 :          0 :                 return "Invalid A-ID";
     380                 :          3 :         return NULL;
     381                 :            : }
     382                 :            : 
     383                 :            : 
     384                 :          3 : static const char * eap_fast_parse_i_id(struct eap_fast_pac *pac, char *pos)
     385                 :            : {
     386                 :          3 :         os_free(pac->i_id);
     387                 :          3 :         pac->i_id = eap_fast_parse_hex(pos, &pac->i_id_len);
     388         [ -  + ]:          3 :         if (pac->i_id == NULL)
     389                 :          0 :                 return "Invalid I-ID";
     390                 :          3 :         return NULL;
     391                 :            : }
     392                 :            : 
     393                 :            : 
     394                 :          3 : static const char * eap_fast_parse_a_id_info(struct eap_fast_pac *pac,
     395                 :            :                                              char *pos)
     396                 :            : {
     397                 :          3 :         os_free(pac->a_id_info);
     398                 :          3 :         pac->a_id_info = eap_fast_parse_hex(pos, &pac->a_id_info_len);
     399         [ -  + ]:          3 :         if (pac->a_id_info == NULL)
     400                 :          0 :                 return "Invalid A-ID-Info";
     401                 :          3 :         return NULL;
     402                 :            : }
     403                 :            : 
     404                 :            : 
     405                 :            : /**
     406                 :            :  * eap_fast_load_pac - Load PAC entries (text format)
     407                 :            :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
     408                 :            :  * @pac_root: Pointer to root of the PAC list (to be filled)
     409                 :            :  * @pac_file: Name of the PAC file/blob to load
     410                 :            :  * Returns: 0 on success, -1 on failure
     411                 :            :  */
     412                 :          7 : int eap_fast_load_pac(struct eap_sm *sm, struct eap_fast_pac **pac_root,
     413                 :            :                       const char *pac_file)
     414                 :            : {
     415                 :            :         struct eap_fast_read_ctx rc;
     416                 :          7 :         struct eap_fast_pac *pac = NULL;
     417                 :          7 :         int count = 0;
     418                 :            :         char *pos;
     419                 :          7 :         const char *err = NULL;
     420                 :            : 
     421         [ -  + ]:          7 :         if (pac_file == NULL)
     422                 :          0 :                 return -1;
     423                 :            : 
     424         [ +  + ]:          7 :         if (eap_fast_init_pac_data(sm, pac_file, &rc) < 0)
     425                 :          4 :                 return 0;
     426                 :            : 
     427         [ -  + ]:          3 :         if (eap_fast_read_line(&rc, &pos) < 0) {
     428                 :            :                 /* empty file - assume it is fine to overwrite */
     429                 :          0 :                 eap_fast_deinit_pac_data(&rc);
     430                 :          0 :                 return 0;
     431                 :            :         }
     432         [ -  + ]:          3 :         if (os_strcmp(pac_file_hdr, rc.buf) != 0)
     433                 :          0 :                 err = "Unrecognized header line";
     434                 :            : 
     435 [ +  - ][ +  + ]:         36 :         while (!err && eap_fast_read_line(&rc, &pos) == 0) {
     436         [ +  + ]:         33 :                 if (os_strcmp(rc.buf, "START") == 0)
     437                 :          3 :                         err = eap_fast_parse_start(&pac);
     438         [ +  + ]:         30 :                 else if (os_strcmp(rc.buf, "END") == 0) {
     439                 :          3 :                         err = eap_fast_parse_end(pac_root, &pac);
     440                 :          3 :                         count++;
     441         [ -  + ]:         27 :                 } else if (!pac)
     442                 :          0 :                         err = "Unexpected line outside START/END block";
     443         [ +  + ]:         27 :                 else if (os_strcmp(rc.buf, "PAC-Type") == 0)
     444                 :          3 :                         err = eap_fast_parse_pac_type(pac, pos);
     445         [ +  + ]:         24 :                 else if (os_strcmp(rc.buf, "PAC-Key") == 0)
     446                 :          3 :                         err = eap_fast_parse_pac_key(pac, pos);
     447         [ +  + ]:         21 :                 else if (os_strcmp(rc.buf, "PAC-Opaque") == 0)
     448                 :          3 :                         err = eap_fast_parse_pac_opaque(pac, pos);
     449         [ +  + ]:         18 :                 else if (os_strcmp(rc.buf, "A-ID") == 0)
     450                 :          3 :                         err = eap_fast_parse_a_id(pac, pos);
     451         [ +  + ]:         15 :                 else if (os_strcmp(rc.buf, "I-ID") == 0)
     452                 :          3 :                         err = eap_fast_parse_i_id(pac, pos);
     453         [ +  + ]:         12 :                 else if (os_strcmp(rc.buf, "A-ID-Info") == 0)
     454                 :          3 :                         err = eap_fast_parse_a_id_info(pac, pos);
     455                 :            :         }
     456                 :            : 
     457         [ -  + ]:          3 :         if (pac) {
     458                 :          0 :                 err = "PAC block not terminated with END";
     459                 :          0 :                 eap_fast_free_pac(pac);
     460                 :            :         }
     461                 :            : 
     462                 :          3 :         eap_fast_deinit_pac_data(&rc);
     463                 :            : 
     464         [ -  + ]:          3 :         if (err) {
     465                 :          0 :                 wpa_printf(MSG_INFO, "EAP-FAST: %s in '%s:%d'",
     466                 :            :                            err, pac_file, rc.line);
     467                 :          0 :                 return -1;
     468                 :            :         }
     469                 :            : 
     470                 :          3 :         wpa_printf(MSG_DEBUG, "EAP-FAST: Read %d PAC entries from '%s'",
     471                 :            :                    count, pac_file);
     472                 :            : 
     473                 :          7 :         return 0;
     474                 :            : }
     475                 :            : 
     476                 :            : 
     477                 :         24 : static void eap_fast_write(char **buf, char **pos, size_t *buf_len,
     478                 :            :                            const char *field, const u8 *data,
     479                 :            :                            size_t len, int txt)
     480                 :            : {
     481                 :            :         size_t i, need;
     482                 :            :         int ret;
     483                 :            :         char *end;
     484                 :            : 
     485 [ +  - ][ +  - ]:         24 :         if (data == NULL || buf == NULL || *buf == NULL ||
         [ +  - ][ +  - ]
     486 [ +  - ][ -  + ]:         24 :             pos == NULL || *pos == NULL || *pos < *buf)
     487                 :          0 :                 return;
     488                 :            : 
     489                 :         24 :         need = os_strlen(field) + len * 2 + 30;
     490         [ +  + ]:         24 :         if (txt)
     491                 :          8 :                 need += os_strlen(field) + len + 20;
     492                 :            : 
     493         [ -  + ]:         24 :         if (*pos - *buf + need > *buf_len) {
     494                 :          0 :                 char *nbuf = os_realloc(*buf, *buf_len + need);
     495         [ #  # ]:          0 :                 if (nbuf == NULL) {
     496                 :          0 :                         os_free(*buf);
     497                 :          0 :                         *buf = NULL;
     498                 :          0 :                         return;
     499                 :            :                 }
     500                 :          0 :                 *pos = nbuf + (*pos - *buf);
     501                 :          0 :                 *buf = nbuf;
     502                 :          0 :                 *buf_len += need;
     503                 :            :         }
     504                 :         24 :         end = *buf + *buf_len;
     505                 :            : 
     506                 :         24 :         ret = os_snprintf(*pos, end - *pos, "%s=", field);
     507 [ +  - ][ -  + ]:         24 :         if (ret < 0 || ret >= end - *pos)
     508                 :          0 :                 return;
     509                 :         24 :         *pos += ret;
     510                 :         24 :         *pos += wpa_snprintf_hex(*pos, end - *pos, data, len);
     511                 :         24 :         ret = os_snprintf(*pos, end - *pos, "\n");
     512 [ +  - ][ -  + ]:         24 :         if (ret < 0 || ret >= end - *pos)
     513                 :          0 :                 return;
     514                 :         24 :         *pos += ret;
     515                 :            : 
     516         [ +  + ]:         24 :         if (txt) {
     517                 :          8 :                 ret = os_snprintf(*pos, end - *pos, "%s-txt=", field);
     518 [ +  - ][ -  + ]:          8 :                 if (ret < 0 || ret >= end - *pos)
     519                 :          0 :                         return;
     520                 :          8 :                 *pos += ret;
     521         [ +  + ]:         68 :                 for (i = 0; i < len; i++) {
     522                 :         60 :                         ret = os_snprintf(*pos, end - *pos, "%c", data[i]);
     523 [ +  - ][ -  + ]:         60 :                         if (ret < 0 || ret >= end - *pos)
     524                 :          0 :                                 return;
     525                 :         60 :                         *pos += ret;
     526                 :            :                 }
     527                 :          8 :                 ret = os_snprintf(*pos, end - *pos, "\n");
     528 [ +  - ][ -  + ]:          8 :                 if (ret < 0 || ret >= end - *pos)
     529                 :          0 :                         return;
     530                 :         24 :                 *pos += ret;
     531                 :            :         }
     532                 :            : }
     533                 :            : 
     534                 :            : 
     535                 :          4 : static int eap_fast_write_pac(struct eap_sm *sm, const char *pac_file,
     536                 :            :                               char *buf, size_t len)
     537                 :            : {
     538         [ +  - ]:          4 :         if (os_strncmp(pac_file, "blob://", 7) == 0) {
     539                 :            :                 struct wpa_config_blob *blob;
     540                 :          4 :                 blob = os_zalloc(sizeof(*blob));
     541         [ -  + ]:          4 :                 if (blob == NULL)
     542                 :          0 :                         return -1;
     543                 :          4 :                 blob->data = (u8 *) buf;
     544                 :          4 :                 blob->len = len;
     545                 :          4 :                 buf = NULL;
     546                 :          4 :                 blob->name = os_strdup(pac_file + 7);
     547         [ -  + ]:          4 :                 if (blob->name == NULL) {
     548                 :          0 :                         os_free(blob);
     549                 :          0 :                         return -1;
     550                 :            :                 }
     551                 :          4 :                 eap_set_config_blob(sm, blob);
     552                 :            :         } else {
     553                 :            :                 FILE *f;
     554                 :          0 :                 f = fopen(pac_file, "wb");
     555         [ #  # ]:          0 :                 if (f == NULL) {
     556                 :          0 :                         wpa_printf(MSG_INFO, "EAP-FAST: Failed to open PAC "
     557                 :            :                                    "file '%s' for writing", pac_file);
     558                 :          0 :                         return -1;
     559                 :            :                 }
     560         [ #  # ]:          0 :                 if (fwrite(buf, 1, len, f) != len) {
     561                 :          0 :                         wpa_printf(MSG_INFO, "EAP-FAST: Failed to write all "
     562                 :            :                                    "PACs into '%s'", pac_file);
     563                 :          0 :                         fclose(f);
     564                 :          0 :                         return -1;
     565                 :            :                 }
     566                 :          0 :                 os_free(buf);
     567                 :          0 :                 fclose(f);
     568                 :            :         }
     569                 :            : 
     570                 :          4 :         return 0;
     571                 :            : }
     572                 :            : 
     573                 :            : 
     574                 :          4 : static int eap_fast_add_pac_data(struct eap_fast_pac *pac, char **buf,
     575                 :            :                                  char **pos, size_t *buf_len)
     576                 :            : {
     577                 :            :         int ret;
     578                 :            : 
     579                 :          4 :         ret = os_snprintf(*pos, *buf + *buf_len - *pos,
     580                 :          4 :                           "START\nPAC-Type=%d\n", pac->pac_type);
     581 [ +  - ][ -  + ]:          4 :         if (ret < 0 || ret >= *buf + *buf_len - *pos)
     582                 :          0 :                 return -1;
     583                 :            : 
     584                 :          4 :         *pos += ret;
     585                 :          4 :         eap_fast_write(buf, pos, buf_len, "PAC-Key",
     586                 :          4 :                        pac->pac_key, EAP_FAST_PAC_KEY_LEN, 0);
     587                 :          4 :         eap_fast_write(buf, pos, buf_len, "PAC-Opaque",
     588                 :          4 :                        pac->pac_opaque, pac->pac_opaque_len, 0);
     589                 :          4 :         eap_fast_write(buf, pos, buf_len, "PAC-Info",
     590                 :          4 :                        pac->pac_info, pac->pac_info_len, 0);
     591                 :          4 :         eap_fast_write(buf, pos, buf_len, "A-ID",
     592                 :          4 :                        pac->a_id, pac->a_id_len, 0);
     593                 :          4 :         eap_fast_write(buf, pos, buf_len, "I-ID",
     594                 :          4 :                        pac->i_id, pac->i_id_len, 1);
     595                 :          4 :         eap_fast_write(buf, pos, buf_len, "A-ID-Info",
     596                 :          4 :                        pac->a_id_info, pac->a_id_info_len, 1);
     597         [ -  + ]:          4 :         if (*buf == NULL) {
     598                 :          0 :                 wpa_printf(MSG_DEBUG, "EAP-FAST: No memory for PAC "
     599                 :            :                            "data");
     600                 :          0 :                 return -1;
     601                 :            :         }
     602                 :          4 :         ret = os_snprintf(*pos, *buf + *buf_len - *pos, "END\n");
     603 [ +  - ][ -  + ]:          4 :         if (ret < 0 || ret >= *buf + *buf_len - *pos)
     604                 :          0 :                 return -1;
     605                 :          4 :         *pos += ret;
     606                 :            : 
     607                 :          4 :         return 0;
     608                 :            : }
     609                 :            : 
     610                 :            : 
     611                 :            : /**
     612                 :            :  * eap_fast_save_pac - Save PAC entries (text format)
     613                 :            :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
     614                 :            :  * @pac_root: Root of the PAC list
     615                 :            :  * @pac_file: Name of the PAC file/blob
     616                 :            :  * Returns: 0 on success, -1 on failure
     617                 :            :  */
     618                 :          4 : int eap_fast_save_pac(struct eap_sm *sm, struct eap_fast_pac *pac_root,
     619                 :            :                       const char *pac_file)
     620                 :            : {
     621                 :            :         struct eap_fast_pac *pac;
     622                 :          4 :         int ret, count = 0;
     623                 :            :         char *buf, *pos;
     624                 :            :         size_t buf_len;
     625                 :            : 
     626         [ -  + ]:          4 :         if (pac_file == NULL)
     627                 :          0 :                 return -1;
     628                 :            : 
     629                 :          4 :         buf_len = 1024;
     630                 :          4 :         pos = buf = os_malloc(buf_len);
     631         [ -  + ]:          4 :         if (buf == NULL)
     632                 :          0 :                 return -1;
     633                 :            : 
     634                 :          4 :         ret = os_snprintf(pos, buf + buf_len - pos, "%s\n", pac_file_hdr);
     635 [ +  - ][ -  + ]:          4 :         if (ret < 0 || ret >= buf + buf_len - pos) {
     636                 :          0 :                 os_free(buf);
     637                 :          0 :                 return -1;
     638                 :            :         }
     639                 :          4 :         pos += ret;
     640                 :            : 
     641                 :          4 :         pac = pac_root;
     642         [ +  + ]:          8 :         while (pac) {
     643         [ -  + ]:          4 :                 if (eap_fast_add_pac_data(pac, &buf, &pos, &buf_len)) {
     644                 :          0 :                         os_free(buf);
     645                 :          0 :                         return -1;
     646                 :            :                 }
     647                 :          4 :                 count++;
     648                 :          4 :                 pac = pac->next;
     649                 :            :         }
     650                 :            : 
     651         [ -  + ]:          4 :         if (eap_fast_write_pac(sm, pac_file, buf, pos - buf)) {
     652                 :          0 :                 os_free(buf);
     653                 :          0 :                 return -1;
     654                 :            :         }
     655                 :            : 
     656                 :          4 :         wpa_printf(MSG_DEBUG, "EAP-FAST: Wrote %d PAC entries into '%s'",
     657                 :            :                    count, pac_file);
     658                 :            : 
     659                 :          4 :         return 0;
     660                 :            : }
     661                 :            : 
     662                 :            : 
     663                 :            : /**
     664                 :            :  * eap_fast_pac_list_truncate - Truncate a PAC list to the given length
     665                 :            :  * @pac_root: Root of the PAC list
     666                 :            :  * @max_len: Maximum length of the list (>= 1)
     667                 :            :  * Returns: Number of PAC entries removed
     668                 :            :  */
     669                 :         11 : size_t eap_fast_pac_list_truncate(struct eap_fast_pac *pac_root,
     670                 :            :                                   size_t max_len)
     671                 :            : {
     672                 :            :         struct eap_fast_pac *pac, *prev;
     673                 :            :         size_t count;
     674                 :            : 
     675                 :         11 :         pac = pac_root;
     676                 :         11 :         prev = NULL;
     677                 :         11 :         count = 0;
     678                 :            : 
     679         [ +  + ]:         18 :         while (pac) {
     680                 :          7 :                 count++;
     681         [ -  + ]:          7 :                 if (count > max_len)
     682                 :          0 :                         break;
     683                 :          7 :                 prev = pac;
     684                 :          7 :                 pac = pac->next;
     685                 :            :         }
     686                 :            : 
     687 [ -  + ][ #  # ]:         11 :         if (count <= max_len || prev == NULL)
     688                 :         11 :                 return 0;
     689                 :            : 
     690                 :          0 :         count = 0;
     691                 :          0 :         prev->next = NULL;
     692                 :            : 
     693         [ #  # ]:          0 :         while (pac) {
     694                 :          0 :                 prev = pac;
     695                 :          0 :                 pac = pac->next;
     696                 :          0 :                 eap_fast_free_pac(prev);
     697                 :          0 :                 count++;
     698                 :            :         }
     699                 :            : 
     700                 :         11 :         return count;
     701                 :            : }
     702                 :            : 
     703                 :            : 
     704                 :          0 : static void eap_fast_pac_get_a_id(struct eap_fast_pac *pac)
     705                 :            : {
     706                 :            :         u8 *pos, *end;
     707                 :            :         u16 type, len;
     708                 :            : 
     709                 :          0 :         pos = pac->pac_info;
     710                 :          0 :         end = pos + pac->pac_info_len;
     711                 :            : 
     712         [ #  # ]:          0 :         while (pos + 4 < end) {
     713                 :          0 :                 type = WPA_GET_BE16(pos);
     714                 :          0 :                 pos += 2;
     715                 :          0 :                 len = WPA_GET_BE16(pos);
     716                 :          0 :                 pos += 2;
     717         [ #  # ]:          0 :                 if (pos + len > end)
     718                 :          0 :                         break;
     719                 :            : 
     720         [ #  # ]:          0 :                 if (type == PAC_TYPE_A_ID) {
     721                 :          0 :                         os_free(pac->a_id);
     722                 :          0 :                         pac->a_id = os_malloc(len);
     723         [ #  # ]:          0 :                         if (pac->a_id == NULL)
     724                 :          0 :                                 break;
     725                 :          0 :                         os_memcpy(pac->a_id, pos, len);
     726                 :          0 :                         pac->a_id_len = len;
     727                 :            :                 }
     728                 :            : 
     729         [ #  # ]:          0 :                 if (type == PAC_TYPE_A_ID_INFO) {
     730                 :          0 :                         os_free(pac->a_id_info);
     731                 :          0 :                         pac->a_id_info = os_malloc(len);
     732         [ #  # ]:          0 :                         if (pac->a_id_info == NULL)
     733                 :          0 :                                 break;
     734                 :          0 :                         os_memcpy(pac->a_id_info, pos, len);
     735                 :          0 :                         pac->a_id_info_len = len;
     736                 :            :                 }
     737                 :            : 
     738                 :          0 :                 pos += len;
     739                 :            :         }
     740                 :          0 : }
     741                 :            : 
     742                 :            : 
     743                 :            : /**
     744                 :            :  * eap_fast_load_pac_bin - Load PAC entries (binary format)
     745                 :            :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
     746                 :            :  * @pac_root: Pointer to root of the PAC list (to be filled)
     747                 :            :  * @pac_file: Name of the PAC file/blob to load
     748                 :            :  * Returns: 0 on success, -1 on failure
     749                 :            :  */
     750                 :          0 : int eap_fast_load_pac_bin(struct eap_sm *sm, struct eap_fast_pac **pac_root,
     751                 :            :                           const char *pac_file)
     752                 :            : {
     753                 :          0 :         const struct wpa_config_blob *blob = NULL;
     754                 :            :         u8 *buf, *end, *pos;
     755                 :          0 :         size_t len, count = 0;
     756                 :            :         struct eap_fast_pac *pac, *prev;
     757                 :            : 
     758                 :          0 :         *pac_root = NULL;
     759                 :            : 
     760         [ #  # ]:          0 :         if (pac_file == NULL)
     761                 :          0 :                 return -1;
     762                 :            : 
     763         [ #  # ]:          0 :         if (os_strncmp(pac_file, "blob://", 7) == 0) {
     764                 :          0 :                 blob = eap_get_config_blob(sm, pac_file + 7);
     765         [ #  # ]:          0 :                 if (blob == NULL) {
     766                 :          0 :                         wpa_printf(MSG_INFO, "EAP-FAST: No PAC blob '%s' - "
     767                 :            :                                    "assume no PAC entries have been "
     768                 :            :                                    "provisioned", pac_file + 7);
     769                 :          0 :                         return 0;
     770                 :            :                 }
     771                 :          0 :                 buf = blob->data;
     772                 :          0 :                 len = blob->len;
     773                 :            :         } else {
     774                 :          0 :                 buf = (u8 *) os_readfile(pac_file, &len);
     775         [ #  # ]:          0 :                 if (buf == NULL) {
     776                 :          0 :                         wpa_printf(MSG_INFO, "EAP-FAST: No PAC file '%s' - "
     777                 :            :                                    "assume no PAC entries have been "
     778                 :            :                                    "provisioned", pac_file);
     779                 :          0 :                         return 0;
     780                 :            :                 }
     781                 :            :         }
     782                 :            : 
     783         [ #  # ]:          0 :         if (len == 0) {
     784         [ #  # ]:          0 :                 if (blob == NULL)
     785                 :          0 :                         os_free(buf);
     786                 :          0 :                 return 0;
     787                 :            :         }
     788                 :            : 
     789         [ #  # ]:          0 :         if (len < 6 || WPA_GET_BE32(buf) != EAP_FAST_PAC_BINARY_MAGIC ||
           [ #  #  #  # ]
     790                 :          0 :             WPA_GET_BE16(buf + 4) != EAP_FAST_PAC_BINARY_FORMAT_VERSION) {
     791                 :          0 :                 wpa_printf(MSG_INFO, "EAP-FAST: Invalid PAC file '%s' (bin)",
     792                 :            :                            pac_file);
     793         [ #  # ]:          0 :                 if (blob == NULL)
     794                 :          0 :                         os_free(buf);
     795                 :          0 :                 return -1;
     796                 :            :         }
     797                 :            : 
     798                 :          0 :         pac = prev = NULL;
     799                 :          0 :         pos = buf + 6;
     800                 :          0 :         end = buf + len;
     801         [ #  # ]:          0 :         while (pos < end) {
     802         [ #  # ]:          0 :                 if (end - pos < 2 + 32 + 2 + 2)
     803                 :          0 :                         goto parse_fail;
     804                 :            : 
     805                 :          0 :                 pac = os_zalloc(sizeof(*pac));
     806         [ #  # ]:          0 :                 if (pac == NULL)
     807                 :          0 :                         goto parse_fail;
     808                 :            : 
     809                 :          0 :                 pac->pac_type = WPA_GET_BE16(pos);
     810                 :          0 :                 pos += 2;
     811                 :          0 :                 os_memcpy(pac->pac_key, pos, EAP_FAST_PAC_KEY_LEN);
     812                 :          0 :                 pos += EAP_FAST_PAC_KEY_LEN;
     813                 :          0 :                 pac->pac_opaque_len = WPA_GET_BE16(pos);
     814                 :          0 :                 pos += 2;
     815         [ #  # ]:          0 :                 if (pos + pac->pac_opaque_len + 2 > end)
     816                 :          0 :                         goto parse_fail;
     817                 :          0 :                 pac->pac_opaque = os_malloc(pac->pac_opaque_len);
     818         [ #  # ]:          0 :                 if (pac->pac_opaque == NULL)
     819                 :          0 :                         goto parse_fail;
     820                 :          0 :                 os_memcpy(pac->pac_opaque, pos, pac->pac_opaque_len);
     821                 :          0 :                 pos += pac->pac_opaque_len;
     822                 :          0 :                 pac->pac_info_len = WPA_GET_BE16(pos);
     823                 :          0 :                 pos += 2;
     824         [ #  # ]:          0 :                 if (pos + pac->pac_info_len > end)
     825                 :          0 :                         goto parse_fail;
     826                 :          0 :                 pac->pac_info = os_malloc(pac->pac_info_len);
     827         [ #  # ]:          0 :                 if (pac->pac_info == NULL)
     828                 :          0 :                         goto parse_fail;
     829                 :          0 :                 os_memcpy(pac->pac_info, pos, pac->pac_info_len);
     830                 :          0 :                 pos += pac->pac_info_len;
     831                 :          0 :                 eap_fast_pac_get_a_id(pac);
     832                 :            : 
     833                 :          0 :                 count++;
     834         [ #  # ]:          0 :                 if (prev)
     835                 :          0 :                         prev->next = pac;
     836                 :            :                 else
     837                 :          0 :                         *pac_root = pac;
     838                 :          0 :                 prev = pac;
     839                 :            :         }
     840                 :            : 
     841         [ #  # ]:          0 :         if (blob == NULL)
     842                 :          0 :                 os_free(buf);
     843                 :            : 
     844                 :          0 :         wpa_printf(MSG_DEBUG, "EAP-FAST: Read %lu PAC entries from '%s' (bin)",
     845                 :            :                    (unsigned long) count, pac_file);
     846                 :            : 
     847                 :          0 :         return 0;
     848                 :            : 
     849                 :            : parse_fail:
     850                 :          0 :         wpa_printf(MSG_INFO, "EAP-FAST: Failed to parse PAC file '%s' (bin)",
     851                 :            :                    pac_file);
     852         [ #  # ]:          0 :         if (blob == NULL)
     853                 :          0 :                 os_free(buf);
     854         [ #  # ]:          0 :         if (pac)
     855                 :          0 :                 eap_fast_free_pac(pac);
     856                 :          0 :         return -1;
     857                 :            : }
     858                 :            : 
     859                 :            : 
     860                 :            : /**
     861                 :            :  * eap_fast_save_pac_bin - Save PAC entries (binary format)
     862                 :            :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
     863                 :            :  * @pac_root: Root of the PAC list
     864                 :            :  * @pac_file: Name of the PAC file/blob
     865                 :            :  * Returns: 0 on success, -1 on failure
     866                 :            :  */
     867                 :          0 : int eap_fast_save_pac_bin(struct eap_sm *sm, struct eap_fast_pac *pac_root,
     868                 :            :                           const char *pac_file)
     869                 :            : {
     870                 :          0 :         size_t len, count = 0;
     871                 :            :         struct eap_fast_pac *pac;
     872                 :            :         u8 *buf, *pos;
     873                 :            : 
     874                 :          0 :         len = 6;
     875                 :          0 :         pac = pac_root;
     876         [ #  # ]:          0 :         while (pac) {
     877 [ #  # ][ #  # ]:          0 :                 if (pac->pac_opaque_len > 65535 ||
     878                 :          0 :                     pac->pac_info_len > 65535)
     879                 :          0 :                         return -1;
     880                 :          0 :                 len += 2 + EAP_FAST_PAC_KEY_LEN + 2 + pac->pac_opaque_len +
     881                 :          0 :                         2 + pac->pac_info_len;
     882                 :          0 :                 pac = pac->next;
     883                 :            :         }
     884                 :            : 
     885                 :          0 :         buf = os_malloc(len);
     886         [ #  # ]:          0 :         if (buf == NULL)
     887                 :          0 :                 return -1;
     888                 :            : 
     889                 :          0 :         pos = buf;
     890                 :          0 :         WPA_PUT_BE32(pos, EAP_FAST_PAC_BINARY_MAGIC);
     891                 :          0 :         pos += 4;
     892                 :          0 :         WPA_PUT_BE16(pos, EAP_FAST_PAC_BINARY_FORMAT_VERSION);
     893                 :          0 :         pos += 2;
     894                 :            : 
     895                 :          0 :         pac = pac_root;
     896         [ #  # ]:          0 :         while (pac) {
     897                 :          0 :                 WPA_PUT_BE16(pos, pac->pac_type);
     898                 :          0 :                 pos += 2;
     899                 :          0 :                 os_memcpy(pos, pac->pac_key, EAP_FAST_PAC_KEY_LEN);
     900                 :          0 :                 pos += EAP_FAST_PAC_KEY_LEN;
     901                 :          0 :                 WPA_PUT_BE16(pos, pac->pac_opaque_len);
     902                 :          0 :                 pos += 2;
     903                 :          0 :                 os_memcpy(pos, pac->pac_opaque, pac->pac_opaque_len);
     904                 :          0 :                 pos += pac->pac_opaque_len;
     905                 :          0 :                 WPA_PUT_BE16(pos, pac->pac_info_len);
     906                 :          0 :                 pos += 2;
     907                 :          0 :                 os_memcpy(pos, pac->pac_info, pac->pac_info_len);
     908                 :          0 :                 pos += pac->pac_info_len;
     909                 :            : 
     910                 :          0 :                 pac = pac->next;
     911                 :          0 :                 count++;
     912                 :            :         }
     913                 :            : 
     914         [ #  # ]:          0 :         if (eap_fast_write_pac(sm, pac_file, (char *) buf, len)) {
     915                 :          0 :                 os_free(buf);
     916                 :          0 :                 return -1;
     917                 :            :         }
     918                 :            : 
     919                 :          0 :         wpa_printf(MSG_DEBUG, "EAP-FAST: Wrote %lu PAC entries into '%s' "
     920                 :            :                    "(bin)", (unsigned long) count, pac_file);
     921                 :            : 
     922                 :          0 :         return 0;
     923                 :            : }

Generated by: LCOV version 1.9