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

Generated by: LCOV version 1.9