18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP peer method: EAP-FAST PAC file processing 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_config.h" 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_i.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_fast_pac.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* TODO: encrypt PAC-Key in the PAC file */ 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Text data format */ 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char *pac_file_hdr = 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "wpa_supplicant EAP-FAST PAC file - version 1"; 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Binary data format 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 4-octet magic value: 6A E4 92 0C 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 2-octet version (big endian) 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * <version specific data> 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * version=0: 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Sequence of PAC entries: 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 2-octet PAC-Type (big endian) 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 32-octet PAC-Key 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 2-octet PAC-Opaque length (big endian) 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * <variable len> PAC-Opaque data (length bytes) 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 2-octet PAC-Info length (big endian) 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * <variable len> PAC-Info data (length bytes) 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define EAP_FAST_PAC_BINARY_MAGIC 0x6ae4920c 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define EAP_FAST_PAC_BINARY_FORMAT_VERSION 0 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_fast_free_pac - Free PAC data 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pac: Pointer to the PAC entry 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Note that the PAC entry must not be in a list since this function does not 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * remove the list links. 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid eap_fast_free_pac(struct eap_fast_pac *pac) 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(pac->pac_opaque); 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(pac->pac_info); 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(pac->a_id); 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(pac->i_id); 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(pac->a_id_info); 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(pac); 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_fast_get_pac - Get a PAC entry based on A-ID 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pac_root: Pointer to root of the PAC list 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @a_id: A-ID to search for 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @a_id_len: Length of A-ID 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pac_type: PAC-Type to search for 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the PAC entry, or %NULL if A-ID not found 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eap_fast_pac * eap_fast_get_pac(struct eap_fast_pac *pac_root, 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *a_id, size_t a_id_len, 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 pac_type) 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_fast_pac *pac = pac_root; 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (pac) { 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pac->pac_type == pac_type && pac->a_id_len == a_id_len && 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(pac->a_id, a_id, a_id_len) == 0) { 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pac; 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pac = pac->next; 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_fast_remove_pac(struct eap_fast_pac **pac_root, 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_fast_pac **pac_current, 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *a_id, size_t a_id_len, u16 pac_type) 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_fast_pac *pac, *prev; 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pac = *pac_root; 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = NULL; 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (pac) { 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pac->pac_type == pac_type && pac->a_id_len == a_id_len && 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(pac->a_id, a_id, a_id_len) == 0) { 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (prev == NULL) 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pac_root = pac->next; 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev->next = pac->next; 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*pac_current == pac) 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pac_current = NULL; 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_fast_free_pac(pac); 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = pac; 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pac = pac->next; 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_fast_copy_buf(u8 **dst, size_t *dst_len, 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *src, size_t src_len) 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (src) { 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *dst = os_malloc(src_len); 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*dst == NULL) 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(*dst, src, src_len); 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *dst_len = src_len; 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_fast_add_pac - Add a copy of a PAC entry to a list 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pac_root: Pointer to PAC list root pointer 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pac_current: Pointer to the current PAC pointer 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @entry: New entry to clone and add to the list 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function makes a clone of the given PAC entry and adds this copied 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * entry to the list (pac_root). If an old entry for the same A-ID is found, 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * it will be removed from the PAC list and in this case, pac_current entry 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * is set to %NULL if it was the removed entry. 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_fast_add_pac(struct eap_fast_pac **pac_root, 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_fast_pac **pac_current, 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_fast_pac *entry) 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_fast_pac *pac; 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (entry == NULL || entry->a_id == NULL) 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Remove a possible old entry for the matching A-ID. */ 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_fast_remove_pac(pac_root, pac_current, 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->a_id, entry->a_id_len, entry->pac_type); 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Allocate a new entry and add it to the list of PACs. */ 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pac = os_zalloc(sizeof(*pac)); 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pac == NULL) 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pac->pac_type = entry->pac_type; 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pac->pac_key, entry->pac_key, EAP_FAST_PAC_KEY_LEN); 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_fast_copy_buf(&pac->pac_opaque, &pac->pac_opaque_len, 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->pac_opaque, entry->pac_opaque_len) < 0 || 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_fast_copy_buf(&pac->pac_info, &pac->pac_info_len, 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->pac_info, entry->pac_info_len) < 0 || 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_fast_copy_buf(&pac->a_id, &pac->a_id_len, 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->a_id, entry->a_id_len) < 0 || 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_fast_copy_buf(&pac->i_id, &pac->i_id_len, 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->i_id, entry->i_id_len) < 0 || 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_fast_copy_buf(&pac->a_id_info, &pac->a_id_info_len, 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->a_id_info, entry->a_id_info_len) < 0) { 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_fast_free_pac(pac); 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pac->next = *pac_root; 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pac_root = pac; 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eap_fast_read_ctx { 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt FILE *f; 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *pos; 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *end; 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int line; 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *buf; 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t buf_len; 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_fast_read_line(struct eap_fast_read_ctx *rc, char **value) 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *pos; 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rc->line++; 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rc->f) { 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (fgets(rc->buf, rc->buf_len, rc->f) == NULL) 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *l_end; 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rc->pos >= rc->end) 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l_end = rc->pos; 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (l_end < rc->end && *l_end != '\n') 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l_end++; 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = l_end - rc->pos; 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len >= rc->buf_len) 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = rc->buf_len - 1; 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(rc->buf, rc->pos, len); 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rc->buf[len] = '\0'; 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rc->pos = l_end + 1; 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rc->buf[rc->buf_len - 1] = '\0'; 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = rc->buf; 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (*pos != '\0') { 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*pos == '\n' || *pos == '\r') { 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos = '\0'; 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos++; 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = os_strchr(rc->buf, '='); 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos) 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = '\0'; 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *value = pos; 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_fast_parse_hex(const char *value, size_t *len) 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int hlen; 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf; 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (value == NULL) 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hlen = os_strlen(value); 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hlen & 1) 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = hlen / 2; 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = os_malloc(*len); 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hexstr2bin(value, buf, *len)) { 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return buf; 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_fast_init_pac_data(struct eap_sm *sm, const char *pac_file, 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_fast_read_ctx *rc) 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(rc, 0, sizeof(*rc)); 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rc->buf_len = 2048; 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rc->buf = os_malloc(rc->buf_len); 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rc->buf == NULL) 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strncmp(pac_file, "blob://", 7) == 0) { 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_config_blob *blob; 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt blob = eap_get_config_blob(sm, pac_file + 7); 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (blob == NULL) { 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-FAST: No PAC blob '%s' - " 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "assume no PAC entries have been " 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "provisioned", pac_file + 7); 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(rc->buf); 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rc->pos = (char *) blob->data; 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rc->end = (char *) blob->data + blob->len; 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rc->f = fopen(pac_file, "rb"); 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rc->f == NULL) { 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-FAST: No PAC file '%s' - " 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "assume no PAC entries have been " 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "provisioned", pac_file); 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(rc->buf); 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_fast_deinit_pac_data(struct eap_fast_read_ctx *rc) 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(rc->buf); 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rc->f) 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fclose(rc->f); 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * eap_fast_parse_start(struct eap_fast_pac **pac) 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*pac) 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "START line without END"; 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pac = os_zalloc(sizeof(struct eap_fast_pac)); 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*pac == NULL) 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "No memory for PAC entry"; 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (*pac)->pac_type = PAC_TYPE_TUNNEL_PAC; 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * eap_fast_parse_end(struct eap_fast_pac **pac_root, 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_fast_pac **pac) 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*pac == NULL) 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "END line without START"; 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*pac_root) { 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_fast_pac *end = *pac_root; 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (end->next) 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = end->next; 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end->next = *pac; 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pac_root = *pac; 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pac = NULL; 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * eap_fast_parse_pac_type(struct eap_fast_pac *pac, 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *pos) 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 33396be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt if (!pos) 33496be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt return "Cannot parse pac type"; 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pac->pac_type = atoi(pos); 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pac->pac_type != PAC_TYPE_TUNNEL_PAC && 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pac->pac_type != PAC_TYPE_USER_AUTHORIZATION && 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pac->pac_type != PAC_TYPE_MACHINE_AUTHENTICATION) 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "Unrecognized PAC-Type"; 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * eap_fast_parse_pac_key(struct eap_fast_pac *pac, char *pos) 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *key; 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t key_len; 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = eap_fast_parse_hex(pos, &key_len); 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key == NULL || key_len != EAP_FAST_PAC_KEY_LEN) { 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(key); 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "Invalid PAC-Key"; 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pac->pac_key, key, EAP_FAST_PAC_KEY_LEN); 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(key); 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * eap_fast_parse_pac_opaque(struct eap_fast_pac *pac, 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *pos) 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(pac->pac_opaque); 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pac->pac_opaque = eap_fast_parse_hex(pos, &pac->pac_opaque_len); 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pac->pac_opaque == NULL) 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "Invalid PAC-Opaque"; 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * eap_fast_parse_a_id(struct eap_fast_pac *pac, char *pos) 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(pac->a_id); 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pac->a_id = eap_fast_parse_hex(pos, &pac->a_id_len); 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pac->a_id == NULL) 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "Invalid A-ID"; 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * eap_fast_parse_i_id(struct eap_fast_pac *pac, char *pos) 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(pac->i_id); 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pac->i_id = eap_fast_parse_hex(pos, &pac->i_id_len); 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pac->i_id == NULL) 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "Invalid I-ID"; 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * eap_fast_parse_a_id_info(struct eap_fast_pac *pac, 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *pos) 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(pac->a_id_info); 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pac->a_id_info = eap_fast_parse_hex(pos, &pac->a_id_info_len); 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pac->a_id_info == NULL) 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "Invalid A-ID-Info"; 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_fast_load_pac - Load PAC entries (text format) 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pac_root: Pointer to root of the PAC list (to be filled) 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pac_file: Name of the PAC file/blob to load 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_fast_load_pac(struct eap_sm *sm, struct eap_fast_pac **pac_root, 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *pac_file) 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_fast_read_ctx rc; 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_fast_pac *pac = NULL; 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int count = 0; 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *pos; 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *err = NULL; 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pac_file == NULL) 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_fast_init_pac_data(sm, pac_file, &rc) < 0) 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 427a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (eap_fast_read_line(&rc, &pos) < 0) { 428a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt /* empty file - assume it is fine to overwrite */ 429a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt eap_fast_deinit_pac_data(&rc); 430a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return 0; 431a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 432a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (os_strcmp(pac_file_hdr, rc.buf) != 0) 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt err = "Unrecognized header line"; 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (!err && eap_fast_read_line(&rc, &pos) == 0) { 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strcmp(rc.buf, "START") == 0) 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt err = eap_fast_parse_start(&pac); 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (os_strcmp(rc.buf, "END") == 0) { 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt err = eap_fast_parse_end(pac_root, &pac); 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count++; 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (!pac) 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt err = "Unexpected line outside START/END block"; 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (os_strcmp(rc.buf, "PAC-Type") == 0) 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt err = eap_fast_parse_pac_type(pac, pos); 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (os_strcmp(rc.buf, "PAC-Key") == 0) 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt err = eap_fast_parse_pac_key(pac, pos); 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (os_strcmp(rc.buf, "PAC-Opaque") == 0) 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt err = eap_fast_parse_pac_opaque(pac, pos); 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (os_strcmp(rc.buf, "A-ID") == 0) 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt err = eap_fast_parse_a_id(pac, pos); 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (os_strcmp(rc.buf, "I-ID") == 0) 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt err = eap_fast_parse_i_id(pac, pos); 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (os_strcmp(rc.buf, "A-ID-Info") == 0) 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt err = eap_fast_parse_a_id_info(pac, pos); 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pac) { 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt err = "PAC block not terminated with END"; 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_fast_free_pac(pac); 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_fast_deinit_pac_data(&rc); 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (err) { 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-FAST: %s in '%s:%d'", 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt err, pac_file, rc.line); 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Read %d PAC entries from '%s'", 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count, pac_file); 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_fast_write(char **buf, char **pos, size_t *buf_len, 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *field, const u8 *data, 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len, int txt) 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i, need; 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *end; 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data == NULL || buf == NULL || *buf == NULL || 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos == NULL || *pos == NULL || *pos < *buf) 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt need = os_strlen(field) + len * 2 + 30; 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (txt) 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt need += os_strlen(field) + len + 20; 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*pos - *buf + need > *buf_len) { 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *nbuf = os_realloc(*buf, *buf_len + need); 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nbuf == NULL) { 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(*buf); 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *buf = NULL; 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos = nbuf + (*pos - *buf); 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *buf = nbuf; 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *buf_len += need; 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = *buf + *buf_len; 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(*pos, end - *pos, "%s=", field); 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0 || ret >= end - *pos) 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos += ret; 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos += wpa_snprintf_hex(*pos, end - *pos, data, len); 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(*pos, end - *pos, "\n"); 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0 || ret >= end - *pos) 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos += ret; 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (txt) { 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(*pos, end - *pos, "%s-txt=", field); 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0 || ret >= end - *pos) 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos += ret; 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < len; i++) { 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(*pos, end - *pos, "%c", data[i]); 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0 || ret >= end - *pos) 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos += ret; 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(*pos, end - *pos, "\n"); 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0 || ret >= end - *pos) 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos += ret; 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_fast_write_pac(struct eap_sm *sm, const char *pac_file, 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *buf, size_t len) 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strncmp(pac_file, "blob://", 7) == 0) { 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_config_blob *blob; 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt blob = os_zalloc(sizeof(*blob)); 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (blob == NULL) 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt blob->data = (u8 *) buf; 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt blob->len = len; 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = NULL; 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt blob->name = os_strdup(pac_file + 7); 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (blob->name == NULL) { 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(blob); 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_set_config_blob(sm, blob); 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt FILE *f; 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt f = fopen(pac_file, "wb"); 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (f == NULL) { 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-FAST: Failed to open PAC " 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "file '%s' for writing", pac_file); 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (fwrite(buf, 1, len, f) != len) { 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-FAST: Failed to write all " 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "PACs into '%s'", pac_file); 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fclose(f); 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fclose(f); 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_fast_add_pac_data(struct eap_fast_pac *pac, char **buf, 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char **pos, size_t *buf_len) 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(*pos, *buf + *buf_len - *pos, 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "START\nPAC-Type=%d\n", pac->pac_type); 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0 || ret >= *buf + *buf_len - *pos) 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos += ret; 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_fast_write(buf, pos, buf_len, "PAC-Key", 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pac->pac_key, EAP_FAST_PAC_KEY_LEN, 0); 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_fast_write(buf, pos, buf_len, "PAC-Opaque", 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pac->pac_opaque, pac->pac_opaque_len, 0); 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_fast_write(buf, pos, buf_len, "PAC-Info", 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pac->pac_info, pac->pac_info_len, 0); 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_fast_write(buf, pos, buf_len, "A-ID", 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pac->a_id, pac->a_id_len, 0); 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_fast_write(buf, pos, buf_len, "I-ID", 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pac->i_id, pac->i_id_len, 1); 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_fast_write(buf, pos, buf_len, "A-ID-Info", 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pac->a_id_info, pac->a_id_info_len, 1); 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*buf == NULL) { 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: No memory for PAC " 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "data"); 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(*pos, *buf + *buf_len - *pos, "END\n"); 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0 || ret >= *buf + *buf_len - *pos) 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos += ret; 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_fast_save_pac - Save PAC entries (text format) 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pac_root: Root of the PAC list 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pac_file: Name of the PAC file/blob 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_fast_save_pac(struct eap_sm *sm, struct eap_fast_pac *pac_root, 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *pac_file) 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_fast_pac *pac; 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret, count = 0; 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *buf, *pos; 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t buf_len; 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pac_file == NULL) 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf_len = 1024; 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf = os_malloc(buf_len); 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(pos, buf + buf_len - pos, "%s\n", pac_file_hdr); 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0 || ret >= buf + buf_len - pos) { 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += ret; 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pac = pac_root; 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (pac) { 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_fast_add_pac_data(pac, &buf, &pos, &buf_len)) { 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count++; 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pac = pac->next; 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_fast_write_pac(sm, pac_file, buf, pos - buf)) { 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Wrote %d PAC entries into '%s'", 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count, pac_file); 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_fast_pac_list_truncate - Truncate a PAC list to the given length 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pac_root: Root of the PAC list 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @max_len: Maximum length of the list (>= 1) 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Number of PAC entries removed 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtsize_t eap_fast_pac_list_truncate(struct eap_fast_pac *pac_root, 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t max_len) 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_fast_pac *pac, *prev; 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t count; 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pac = pac_root; 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = NULL; 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count = 0; 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (pac) { 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count++; 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (count > max_len) 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = pac; 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pac = pac->next; 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (count <= max_len || prev == NULL) 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count = 0; 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev->next = NULL; 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (pac) { 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = pac; 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pac = pac->next; 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_fast_free_pac(prev); 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count++; 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return count; 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_fast_pac_get_a_id(struct eap_fast_pac *pac) 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos, *end; 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 type, len; 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = pac->pac_info; 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = pos + pac->pac_info_len; 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (pos + 4 < end) { 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt type = WPA_GET_BE16(pos); 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = WPA_GET_BE16(pos); 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos + len > end) 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (type == PAC_TYPE_A_ID) { 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(pac->a_id); 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pac->a_id = os_malloc(len); 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pac->a_id == NULL) 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pac->a_id, pos, len); 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pac->a_id_len = len; 7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (type == PAC_TYPE_A_ID_INFO) { 7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(pac->a_id_info); 7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pac->a_id_info = os_malloc(len); 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pac->a_id_info == NULL) 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pac->a_id_info, pos, len); 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pac->a_id_info_len = len; 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += len; 7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_fast_load_pac_bin - Load PAC entries (binary format) 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pac_root: Pointer to root of the PAC list (to be filled) 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pac_file: Name of the PAC file/blob to load 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_fast_load_pac_bin(struct eap_sm *sm, struct eap_fast_pac **pac_root, 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *pac_file) 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_config_blob *blob = NULL; 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf, *end, *pos; 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len, count = 0; 7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_fast_pac *pac, *prev; 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pac_root = NULL; 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pac_file == NULL) 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strncmp(pac_file, "blob://", 7) == 0) { 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt blob = eap_get_config_blob(sm, pac_file + 7); 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (blob == NULL) { 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-FAST: No PAC blob '%s' - " 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "assume no PAC entries have been " 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "provisioned", pac_file + 7); 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = blob->data; 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = blob->len; 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = (u8 *) os_readfile(pac_file, &len); 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) { 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-FAST: No PAC file '%s' - " 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "assume no PAC entries have been " 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "provisioned", pac_file); 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len == 0) { 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (blob == NULL) 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len < 6 || WPA_GET_BE32(buf) != EAP_FAST_PAC_BINARY_MAGIC || 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_GET_BE16(buf + 4) != EAP_FAST_PAC_BINARY_FORMAT_VERSION) { 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-FAST: Invalid PAC file '%s' (bin)", 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pac_file); 7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (blob == NULL) 7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pac = prev = NULL; 7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf + 6; 8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = buf + len; 8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (pos < end) { 8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end - pos < 2 + 32 + 2 + 2) 8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto parse_fail; 8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pac = os_zalloc(sizeof(*pac)); 8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pac == NULL) 8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto parse_fail; 8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pac->pac_type = WPA_GET_BE16(pos); 8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pac->pac_key, pos, EAP_FAST_PAC_KEY_LEN); 8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += EAP_FAST_PAC_KEY_LEN; 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pac->pac_opaque_len = WPA_GET_BE16(pos); 8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos + pac->pac_opaque_len + 2 > end) 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto parse_fail; 8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pac->pac_opaque = os_malloc(pac->pac_opaque_len); 8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pac->pac_opaque == NULL) 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto parse_fail; 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pac->pac_opaque, pos, pac->pac_opaque_len); 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += pac->pac_opaque_len; 8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pac->pac_info_len = WPA_GET_BE16(pos); 8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos + pac->pac_info_len > end) 8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto parse_fail; 8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pac->pac_info = os_malloc(pac->pac_info_len); 8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pac->pac_info == NULL) 8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto parse_fail; 8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pac->pac_info, pos, pac->pac_info_len); 8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += pac->pac_info_len; 8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_fast_pac_get_a_id(pac); 8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count++; 8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (prev) 8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev->next = pac; 8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pac_root = pac; 8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = pac; 8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (blob == NULL) 8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Read %lu PAC entries from '%s' (bin)", 8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) count, pac_file); 8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtparse_fail: 8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-FAST: Failed to parse PAC file '%s' (bin)", 8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pac_file); 8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (blob == NULL) 8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pac) 8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_fast_free_pac(pac); 8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_fast_save_pac_bin - Save PAC entries (binary format) 8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() 8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pac_root: Root of the PAC list 8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pac_file: Name of the PAC file/blob 8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_fast_save_pac_bin(struct eap_sm *sm, struct eap_fast_pac *pac_root, 8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *pac_file) 8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len, count = 0; 8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_fast_pac *pac; 8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf, *pos; 8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = 6; 8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pac = pac_root; 8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (pac) { 8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pac->pac_opaque_len > 65535 || 8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pac->pac_info_len > 65535) 8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len += 2 + EAP_FAST_PAC_KEY_LEN + 2 + pac->pac_opaque_len + 8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2 + pac->pac_info_len; 8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pac = pac->next; 8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = os_malloc(len); 8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) 8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf; 8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE32(pos, EAP_FAST_PAC_BINARY_MAGIC); 8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 4; 8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(pos, EAP_FAST_PAC_BINARY_FORMAT_VERSION); 8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pac = pac_root; 8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (pac) { 8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(pos, pac->pac_type); 8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, pac->pac_key, EAP_FAST_PAC_KEY_LEN); 9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += EAP_FAST_PAC_KEY_LEN; 9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(pos, pac->pac_opaque_len); 9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, pac->pac_opaque, pac->pac_opaque_len); 9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += pac->pac_opaque_len; 9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(pos, pac->pac_info_len); 9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, pac->pac_info, pac->pac_info_len); 9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += pac->pac_info_len; 9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pac = pac->next; 9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count++; 9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_fast_write_pac(sm, pac_file, (char *) buf, len)) { 9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-FAST: Wrote %lu PAC entries into '%s' " 9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(bin)", (unsigned long) count, pac_file); 9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 924