]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - contrib/wpa_supplicant/config.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / contrib / wpa_supplicant / config.c
1 /*
2  * WPA Supplicant / Configuration parser and common functions
3  * Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14
15 #include "includes.h"
16
17 #include "common.h"
18 #include "wpa.h"
19 #include "sha1.h"
20 #include "eapol_sm.h"
21 #include "eap.h"
22 #include "l2_packet.h"
23 #include "config.h"
24
25
26 /*
27  * Structure for network configuration parsing. This data is used to implement
28  * a generic parser for each network block variable. The table of configuration
29  * variables is defined below in this file (ssid_fields[]).
30  */
31 struct parse_data {
32         /* Configuration variable name */
33         char *name;
34
35         /* Parser function for this variable */
36         int (*parser)(const struct parse_data *data, struct wpa_ssid *ssid,
37                       int line, const char *value);
38
39         /* Writer function (i.e., to get the variable in text format from
40          * internal presentation). */
41         char * (*writer)(const struct parse_data *data, struct wpa_ssid *ssid);
42
43         /* Variable specific parameters for the parser. */
44         void *param1, *param2, *param3, *param4;
45
46         /* 0 = this variable can be included in debug output and ctrl_iface
47          * 1 = this variable contains key/private data and it must not be
48          *     included in debug output unless explicitly requested. In
49          *     addition, this variable will not be readable through the
50          *     ctrl_iface.
51          */
52         int key_data;
53 };
54
55
56 static char * wpa_config_parse_string(const char *value, size_t *len)
57 {
58         if (*value == '"') {
59                 char *pos;
60                 value++;
61                 pos = os_strrchr(value, '"');
62                 if (pos == NULL || pos[1] != '\0')
63                         return NULL;
64                 *pos = '\0';
65                 *len = os_strlen(value);
66                 return os_strdup(value);
67         } else {
68                 u8 *str;
69                 size_t tlen, hlen = os_strlen(value);
70                 if (hlen & 1)
71                         return NULL;
72                 tlen = hlen / 2;
73                 str = os_malloc(tlen + 1);
74                 if (str == NULL)
75                         return NULL;
76                 if (hexstr2bin(value, str, tlen)) {
77                         os_free(str);
78                         return NULL;
79                 }
80                 str[tlen] = '\0';
81                 *len = tlen;
82                 return (char *) str;
83         }
84 }
85
86
87 static int wpa_config_parse_str(const struct parse_data *data,
88                                 struct wpa_ssid *ssid,
89                                 int line, const char *value)
90 {
91         size_t res_len, *dst_len;
92         char **dst, *tmp;
93
94         tmp = wpa_config_parse_string(value, &res_len);
95         if (tmp == NULL) {
96                 wpa_printf(MSG_ERROR, "Line %d: failed to parse %s '%s'.",
97                            line, data->name,
98                            data->key_data ? "[KEY DATA REMOVED]" : value);
99                 return -1;
100         }
101
102         if (data->key_data) {
103                 wpa_hexdump_ascii_key(MSG_MSGDUMP, data->name,
104                                       (u8 *) tmp, res_len);
105         } else {
106                 wpa_hexdump_ascii(MSG_MSGDUMP, data->name,
107                                   (u8 *) tmp, res_len);
108         }
109
110         if (data->param3 && res_len < (size_t) data->param3) {
111                 wpa_printf(MSG_ERROR, "Line %d: too short %s (len=%lu "
112                            "min_len=%ld)", line, data->name,
113                            (unsigned long) res_len, (long) data->param3);
114                 os_free(tmp);
115                 return -1;
116         }
117
118         if (data->param4 && res_len > (size_t) data->param4) {
119                 wpa_printf(MSG_ERROR, "Line %d: too long %s (len=%lu "
120                            "max_len=%ld)", line, data->name,
121                            (unsigned long) res_len, (long) data->param4);
122                 os_free(tmp);
123                 return -1;
124         }
125
126         dst = (char **) (((u8 *) ssid) + (long) data->param1);
127         dst_len = (size_t *) (((u8 *) ssid) + (long) data->param2);
128         os_free(*dst);
129         *dst = tmp;
130         if (data->param2)
131                 *dst_len = res_len;
132
133         return 0;
134 }
135
136
137 static int is_hex(const u8 *data, size_t len)
138 {
139         size_t i;
140
141         for (i = 0; i < len; i++) {
142                 if (data[i] < 32 || data[i] >= 127)
143                         return 1;
144         }
145         return 0;
146 }
147
148
149 static char * wpa_config_write_string_ascii(const u8 *value, size_t len)
150 {
151         char *buf;
152
153         buf = os_malloc(len + 3);
154         if (buf == NULL)
155                 return NULL;
156         buf[0] = '"';
157         os_memcpy(buf + 1, value, len);
158         buf[len + 1] = '"';
159         buf[len + 2] = '\0';
160
161         return buf;
162 }
163
164
165 static char * wpa_config_write_string_hex(const u8 *value, size_t len)
166 {
167         char *buf;
168
169         buf = os_zalloc(2 * len + 1);
170         if (buf == NULL)
171                 return NULL;
172         wpa_snprintf_hex(buf, 2 * len + 1, value, len);
173
174         return buf;
175 }
176
177
178 static char * wpa_config_write_string(const u8 *value, size_t len)
179 {
180         if (value == NULL)
181                 return NULL;
182
183         if (is_hex(value, len))
184                 return wpa_config_write_string_hex(value, len);
185         else
186                 return wpa_config_write_string_ascii(value, len);
187 }
188
189
190 static char * wpa_config_write_str(const struct parse_data *data,
191                                    struct wpa_ssid *ssid)
192 {
193         size_t len;
194         char **src;
195
196         src = (char **) (((u8 *) ssid) + (long) data->param1);
197         if (*src == NULL)
198                 return NULL;
199
200         if (data->param2)
201                 len = *((size_t *) (((u8 *) ssid) + (long) data->param2));
202         else
203                 len = os_strlen(*src);
204
205         return wpa_config_write_string((const u8 *) *src, len);
206 }
207
208
209 static int wpa_config_parse_int(const struct parse_data *data,
210                                 struct wpa_ssid *ssid,
211                                 int line, const char *value)
212 {
213         int *dst;
214
215         dst = (int *) (((u8 *) ssid) + (long) data->param1);
216         *dst = atoi(value);
217         wpa_printf(MSG_MSGDUMP, "%s=%d (0x%x)", data->name, *dst, *dst);
218
219         if (data->param3 && *dst < (long) data->param3) {
220                 wpa_printf(MSG_ERROR, "Line %d: too small %s (value=%d "
221                            "min_value=%ld)", line, data->name, *dst,
222                            (long) data->param3);
223                 *dst = (long) data->param3;
224                 return -1;
225         }
226
227         if (data->param4 && *dst > (long) data->param4) {
228                 wpa_printf(MSG_ERROR, "Line %d: too large %s (value=%d "
229                            "max_value=%ld)", line, data->name, *dst,
230                            (long) data->param4);
231                 *dst = (long) data->param4;
232                 return -1;
233         }
234
235         return 0;
236 }
237
238
239 static char * wpa_config_write_int(const struct parse_data *data,
240                                    struct wpa_ssid *ssid)
241 {
242         int *src;
243         char *value;
244
245         src = (int *) (((u8 *) ssid) + (long) data->param1);
246
247         value = os_malloc(20);
248         if (value == NULL)
249                 return NULL;
250         os_snprintf(value, 20, "%d", *src);
251         value[20 - 1] = '\0';
252         return value;
253 }
254
255
256 static int wpa_config_parse_bssid(const struct parse_data *data,
257                                   struct wpa_ssid *ssid, int line,
258                                   const char *value)
259 {
260         if (hwaddr_aton(value, ssid->bssid)) {
261                 wpa_printf(MSG_ERROR, "Line %d: Invalid BSSID '%s'.",
262                            line, value);
263                 return -1;
264         }
265         ssid->bssid_set = 1;
266         wpa_hexdump(MSG_MSGDUMP, "BSSID", ssid->bssid, ETH_ALEN);
267         return 0;
268 }
269
270
271 static char * wpa_config_write_bssid(const struct parse_data *data,
272                                      struct wpa_ssid *ssid)
273 {
274         char *value;
275
276         if (!ssid->bssid_set)
277                 return NULL;
278
279         value = os_malloc(20);
280         if (value == NULL)
281                 return NULL;
282         os_snprintf(value, 20, MACSTR, MAC2STR(ssid->bssid));
283         value[20 - 1] = '\0';
284         return value;
285 }
286
287
288 static int wpa_config_parse_psk(const struct parse_data *data,
289                                 struct wpa_ssid *ssid, int line,
290                                 const char *value)
291 {
292         if (*value == '"') {
293                 const char *pos;
294                 size_t len;
295
296                 value++;
297                 pos = os_strrchr(value, '"');
298                 if (pos)
299                         len = pos - value;
300                 else
301                         len = os_strlen(value);
302                 if (len < 8 || len > 63) {
303                         wpa_printf(MSG_ERROR, "Line %d: Invalid passphrase "
304                                    "length %lu (expected: 8..63) '%s'.",
305                                    line, (unsigned long) len, value);
306                         return -1;
307                 }
308                 wpa_hexdump_ascii_key(MSG_MSGDUMP, "PSK (ASCII passphrase)",
309                                       (u8 *) value, len);
310                 if (ssid->passphrase && os_strlen(ssid->passphrase) == len &&
311                     os_memcmp(ssid->passphrase, value, len) == 0)
312                         return 0;
313                 ssid->psk_set = 0;
314                 os_free(ssid->passphrase);
315                 ssid->passphrase = os_malloc(len + 1);
316                 if (ssid->passphrase == NULL)
317                         return -1;
318                 os_memcpy(ssid->passphrase, value, len);
319                 ssid->passphrase[len] = '\0';
320                 return 0;
321         }
322
323         if (hexstr2bin(value, ssid->psk, PMK_LEN) ||
324             value[PMK_LEN * 2] != '\0') {
325                 wpa_printf(MSG_ERROR, "Line %d: Invalid PSK '%s'.",
326                            line, value);
327                 return -1;
328         }
329
330         os_free(ssid->passphrase);
331         ssid->passphrase = NULL;
332
333         ssid->psk_set = 1;
334         wpa_hexdump_key(MSG_MSGDUMP, "PSK", ssid->psk, PMK_LEN);
335         return 0;
336 }
337
338
339 static char * wpa_config_write_psk(const struct parse_data *data,
340                                    struct wpa_ssid *ssid)
341 {
342         if (ssid->passphrase)
343                 return wpa_config_write_string_ascii(
344                         (const u8 *) ssid->passphrase,
345                         os_strlen(ssid->passphrase));
346
347         if (ssid->psk_set)
348                 return wpa_config_write_string_hex(ssid->psk, PMK_LEN);
349
350         return NULL;
351 }
352
353
354 static int wpa_config_parse_proto(const struct parse_data *data,
355                                   struct wpa_ssid *ssid, int line,
356                                   const char *value)
357 {
358         int val = 0, last, errors = 0;
359         char *start, *end, *buf;
360
361         buf = os_strdup(value);
362         if (buf == NULL)
363                 return -1;
364         start = buf;
365
366         while (*start != '\0') {
367                 while (*start == ' ' || *start == '\t')
368                         start++;
369                 if (*start == '\0')
370                         break;
371                 end = start;
372                 while (*end != ' ' && *end != '\t' && *end != '\0')
373                         end++;
374                 last = *end == '\0';
375                 *end = '\0';
376                 if (os_strcmp(start, "WPA") == 0)
377                         val |= WPA_PROTO_WPA;
378                 else if (os_strcmp(start, "RSN") == 0 ||
379                          os_strcmp(start, "WPA2") == 0)
380                         val |= WPA_PROTO_RSN;
381                 else {
382                         wpa_printf(MSG_ERROR, "Line %d: invalid proto '%s'",
383                                    line, start);
384                         errors++;
385                 }
386
387                 if (last)
388                         break;
389                 start = end + 1;
390         }
391         os_free(buf);
392
393         if (val == 0) {
394                 wpa_printf(MSG_ERROR,
395                            "Line %d: no proto values configured.", line);
396                 errors++;
397         }
398
399         wpa_printf(MSG_MSGDUMP, "proto: 0x%x", val);
400         ssid->proto = val;
401         return errors ? -1 : 0;
402 }
403
404
405 static char * wpa_config_write_proto(const struct parse_data *data,
406                                      struct wpa_ssid *ssid)
407 {
408         int first = 1, ret;
409         char *buf, *pos, *end;
410
411         pos = buf = os_zalloc(10);
412         if (buf == NULL)
413                 return NULL;
414         end = buf + 10;
415
416         if (ssid->proto & WPA_PROTO_WPA) {
417                 ret = os_snprintf(pos, end - pos, "%sWPA", first ? "" : " ");
418                 if (ret < 0 || ret >= end - pos)
419                         return buf;
420                 pos += ret;
421                 first = 0;
422         }
423
424         if (ssid->proto & WPA_PROTO_RSN) {
425                 ret = os_snprintf(pos, end - pos, "%sRSN", first ? "" : " ");
426                 if (ret < 0 || ret >= end - pos)
427                         return buf;
428                 pos += ret;
429                 first = 0;
430         }
431
432         return buf;
433 }
434
435
436 static int wpa_config_parse_key_mgmt(const struct parse_data *data,
437                                      struct wpa_ssid *ssid, int line,
438                                      const char *value)
439 {
440         int val = 0, last, errors = 0;
441         char *start, *end, *buf;
442
443         buf = os_strdup(value);
444         if (buf == NULL)
445                 return -1;
446         start = buf;
447
448         while (*start != '\0') {
449                 while (*start == ' ' || *start == '\t')
450                         start++;
451                 if (*start == '\0')
452                         break;
453                 end = start;
454                 while (*end != ' ' && *end != '\t' && *end != '\0')
455                         end++;
456                 last = *end == '\0';
457                 *end = '\0';
458                 if (os_strcmp(start, "WPA-PSK") == 0)
459                         val |= WPA_KEY_MGMT_PSK;
460                 else if (os_strcmp(start, "WPA-EAP") == 0)
461                         val |= WPA_KEY_MGMT_IEEE8021X;
462                 else if (os_strcmp(start, "IEEE8021X") == 0)
463                         val |= WPA_KEY_MGMT_IEEE8021X_NO_WPA;
464                 else if (os_strcmp(start, "NONE") == 0)
465                         val |= WPA_KEY_MGMT_NONE;
466                 else if (os_strcmp(start, "WPA-NONE") == 0)
467                         val |= WPA_KEY_MGMT_WPA_NONE;
468                 else {
469                         wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'",
470                                    line, start);
471                         errors++;
472                 }
473
474                 if (last)
475                         break;
476                 start = end + 1;
477         }
478         os_free(buf);
479
480         if (val == 0) {
481                 wpa_printf(MSG_ERROR,
482                            "Line %d: no key_mgmt values configured.", line);
483                 errors++;
484         }
485
486         wpa_printf(MSG_MSGDUMP, "key_mgmt: 0x%x", val);
487         ssid->key_mgmt = val;
488         return errors ? -1 : 0;
489 }
490
491
492 static char * wpa_config_write_key_mgmt(const struct parse_data *data,
493                                         struct wpa_ssid *ssid)
494 {
495         char *buf, *pos, *end;
496         int ret;
497
498         pos = buf = os_zalloc(50);
499         if (buf == NULL)
500                 return NULL;
501         end = buf + 50;
502
503         if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
504                 ret = os_snprintf(pos, end - pos, "%sWPA-PSK",
505                                   pos == buf ? "" : " ");
506                 if (ret < 0 || ret >= end - pos) {
507                         end[-1] = '\0';
508                         return buf;
509                 }
510                 pos += ret;
511         }
512
513         if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
514                 ret = os_snprintf(pos, end - pos, "%sWPA-EAP",
515                                   pos == buf ? "" : " ");
516                 if (ret < 0 || ret >= end - pos) {
517                         end[-1] = '\0';
518                         return buf;
519                 }
520                 pos += ret;
521         }
522
523         if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
524                 ret = os_snprintf(pos, end - pos, "%sIEEE8021X",
525                                   pos == buf ? "" : " ");
526                 if (ret < 0 || ret >= end - pos) {
527                         end[-1] = '\0';
528                         return buf;
529                 }
530                 pos += ret;
531         }
532
533         if (ssid->key_mgmt & WPA_KEY_MGMT_NONE) {
534                 ret = os_snprintf(pos, end - pos, "%sNONE",
535                                   pos == buf ? "" : " ");
536                 if (ret < 0 || ret >= end - pos) {
537                         end[-1] = '\0';
538                         return buf;
539                 }
540                 pos += ret;
541         }
542
543         if (ssid->key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
544                 ret = os_snprintf(pos, end - pos, "%sWPA-NONE",
545                                   pos == buf ? "" : " ");
546                 if (ret < 0 || ret >= end - pos) {
547                         end[-1] = '\0';
548                         return buf;
549                 }
550                 pos += ret;
551         }
552
553         return buf;
554 }
555
556
557 static int wpa_config_parse_cipher(int line, const char *value)
558 {
559         int val = 0, last;
560         char *start, *end, *buf;
561
562         buf = os_strdup(value);
563         if (buf == NULL)
564                 return -1;
565         start = buf;
566
567         while (*start != '\0') {
568                 while (*start == ' ' || *start == '\t')
569                         start++;
570                 if (*start == '\0')
571                         break;
572                 end = start;
573                 while (*end != ' ' && *end != '\t' && *end != '\0')
574                         end++;
575                 last = *end == '\0';
576                 *end = '\0';
577                 if (os_strcmp(start, "CCMP") == 0)
578                         val |= WPA_CIPHER_CCMP;
579                 else if (os_strcmp(start, "TKIP") == 0)
580                         val |= WPA_CIPHER_TKIP;
581                 else if (os_strcmp(start, "WEP104") == 0)
582                         val |= WPA_CIPHER_WEP104;
583                 else if (os_strcmp(start, "WEP40") == 0)
584                         val |= WPA_CIPHER_WEP40;
585                 else if (os_strcmp(start, "NONE") == 0)
586                         val |= WPA_CIPHER_NONE;
587                 else {
588                         wpa_printf(MSG_ERROR, "Line %d: invalid cipher '%s'.",
589                                    line, start);
590                         os_free(buf);
591                         return -1;
592                 }
593
594                 if (last)
595                         break;
596                 start = end + 1;
597         }
598         os_free(buf);
599
600         if (val == 0) {
601                 wpa_printf(MSG_ERROR, "Line %d: no cipher values configured.",
602                            line);
603                 return -1;
604         }
605         return val;
606 }
607
608
609 static char * wpa_config_write_cipher(int cipher)
610 {
611         char *buf, *pos, *end;
612         int ret;
613
614         pos = buf = os_zalloc(50);
615         if (buf == NULL)
616                 return NULL;
617         end = buf + 50;
618
619         if (cipher & WPA_CIPHER_CCMP) {
620                 ret = os_snprintf(pos, end - pos, "%sCCMP",
621                                   pos == buf ? "" : " ");
622                 if (ret < 0 || ret >= end - pos) {
623                         end[-1] = '\0';
624                         return buf;
625                 }
626                 pos += ret;
627         }
628
629         if (cipher & WPA_CIPHER_TKIP) {
630                 ret = os_snprintf(pos, end - pos, "%sTKIP",
631                                   pos == buf ? "" : " ");
632                 if (ret < 0 || ret >= end - pos) {
633                         end[-1] = '\0';
634                         return buf;
635                 }
636                 pos += ret;
637         }
638
639         if (cipher & WPA_CIPHER_WEP104) {
640                 ret = os_snprintf(pos, end - pos, "%sWEP104",
641                                   pos == buf ? "" : " ");
642                 if (ret < 0 || ret >= end - pos) {
643                         end[-1] = '\0';
644                         return buf;
645                 }
646                 pos += ret;
647         }
648
649         if (cipher & WPA_CIPHER_WEP40) {
650                 ret = os_snprintf(pos, end - pos, "%sWEP40",
651                                   pos == buf ? "" : " ");
652                 if (ret < 0 || ret >= end - pos) {
653                         end[-1] = '\0';
654                         return buf;
655                 }
656                 pos += ret;
657         }
658
659         if (cipher & WPA_CIPHER_NONE) {
660                 ret = os_snprintf(pos, end - pos, "%sNONE",
661                                   pos == buf ? "" : " ");
662                 if (ret < 0 || ret >= end - pos) {
663                         end[-1] = '\0';
664                         return buf;
665                 }
666                 pos += ret;
667         }
668
669         return buf;
670 }
671
672
673 static int wpa_config_parse_pairwise(const struct parse_data *data,
674                                      struct wpa_ssid *ssid, int line,
675                                      const char *value)
676 {
677         int val;
678         val = wpa_config_parse_cipher(line, value);
679         if (val == -1)
680                 return -1;
681         if (val & ~(WPA_CIPHER_CCMP | WPA_CIPHER_TKIP | WPA_CIPHER_NONE)) {
682                 wpa_printf(MSG_ERROR, "Line %d: not allowed pairwise cipher "
683                            "(0x%x).", line, val);
684                 return -1;
685         }
686
687         wpa_printf(MSG_MSGDUMP, "pairwise: 0x%x", val);
688         ssid->pairwise_cipher = val;
689         return 0;
690 }
691
692
693 static char * wpa_config_write_pairwise(const struct parse_data *data,
694                                         struct wpa_ssid *ssid)
695 {
696         return wpa_config_write_cipher(ssid->pairwise_cipher);
697 }
698
699
700 static int wpa_config_parse_group(const struct parse_data *data,
701                                   struct wpa_ssid *ssid, int line,
702                                   const char *value)
703 {
704         int val;
705         val = wpa_config_parse_cipher(line, value);
706         if (val == -1)
707                 return -1;
708         if (val & ~(WPA_CIPHER_CCMP | WPA_CIPHER_TKIP | WPA_CIPHER_WEP104 |
709                     WPA_CIPHER_WEP40)) {
710                 wpa_printf(MSG_ERROR, "Line %d: not allowed group cipher "
711                            "(0x%x).", line, val);
712                 return -1;
713         }
714
715         wpa_printf(MSG_MSGDUMP, "group: 0x%x", val);
716         ssid->group_cipher = val;
717         return 0;
718 }
719
720
721 static char * wpa_config_write_group(const struct parse_data *data,
722                                      struct wpa_ssid *ssid)
723 {
724         return wpa_config_write_cipher(ssid->group_cipher);
725 }
726
727
728 static int wpa_config_parse_auth_alg(const struct parse_data *data,
729                                      struct wpa_ssid *ssid, int line,
730                                      const char *value)
731 {
732         int val = 0, last, errors = 0;
733         char *start, *end, *buf;
734
735         buf = os_strdup(value);
736         if (buf == NULL)
737                 return -1;
738         start = buf;
739
740         while (*start != '\0') {
741                 while (*start == ' ' || *start == '\t')
742                         start++;
743                 if (*start == '\0')
744                         break;
745                 end = start;
746                 while (*end != ' ' && *end != '\t' && *end != '\0')
747                         end++;
748                 last = *end == '\0';
749                 *end = '\0';
750                 if (os_strcmp(start, "OPEN") == 0)
751                         val |= WPA_AUTH_ALG_OPEN;
752                 else if (os_strcmp(start, "SHARED") == 0)
753                         val |= WPA_AUTH_ALG_SHARED;
754                 else if (os_strcmp(start, "LEAP") == 0)
755                         val |= WPA_AUTH_ALG_LEAP;
756                 else {
757                         wpa_printf(MSG_ERROR, "Line %d: invalid auth_alg '%s'",
758                                    line, start);
759                         errors++;
760                 }
761
762                 if (last)
763                         break;
764                 start = end + 1;
765         }
766         os_free(buf);
767
768         if (val == 0) {
769                 wpa_printf(MSG_ERROR,
770                            "Line %d: no auth_alg values configured.", line);
771                 errors++;
772         }
773
774         wpa_printf(MSG_MSGDUMP, "auth_alg: 0x%x", val);
775         ssid->auth_alg = val;
776         return errors ? -1 : 0;
777 }
778
779
780 static char * wpa_config_write_auth_alg(const struct parse_data *data,
781                                         struct wpa_ssid *ssid)
782 {
783         char *buf, *pos, *end;
784         int ret;
785
786         pos = buf = os_zalloc(30);
787         if (buf == NULL)
788                 return NULL;
789         end = buf + 30;
790
791         if (ssid->auth_alg & WPA_AUTH_ALG_OPEN) {
792                 ret = os_snprintf(pos, end - pos, "%sOPEN",
793                                   pos == buf ? "" : " ");
794                 if (ret < 0 || ret >= end - pos) {
795                         end[-1] = '\0';
796                         return buf;
797                 }
798                 pos += ret;
799         }
800
801         if (ssid->auth_alg & WPA_AUTH_ALG_SHARED) {
802                 ret = os_snprintf(pos, end - pos, "%sSHARED",
803                                   pos == buf ? "" : " ");
804                 if (ret < 0 || ret >= end - pos) {
805                         end[-1] = '\0';
806                         return buf;
807                 }
808                 pos += ret;
809         }
810
811         if (ssid->auth_alg & WPA_AUTH_ALG_LEAP) {
812                 ret = os_snprintf(pos, end - pos, "%sLEAP",
813                                   pos == buf ? "" : " ");
814                 if (ret < 0 || ret >= end - pos) {
815                         end[-1] = '\0';
816                         return buf;
817                 }
818                 pos += ret;
819         }
820
821         return buf;
822 }
823
824
825 #ifdef IEEE8021X_EAPOL
826 static int wpa_config_parse_eap(const struct parse_data *data,
827                                 struct wpa_ssid *ssid, int line,
828                                 const char *value)
829 {
830         int last, errors = 0;
831         char *start, *end, *buf;
832         struct eap_method_type *methods = NULL, *tmp;
833         size_t num_methods = 0;
834
835         buf = os_strdup(value);
836         if (buf == NULL)
837                 return -1;
838         start = buf;
839
840         while (*start != '\0') {
841                 while (*start == ' ' || *start == '\t')
842                         start++;
843                 if (*start == '\0')
844                         break;
845                 end = start;
846                 while (*end != ' ' && *end != '\t' && *end != '\0')
847                         end++;
848                 last = *end == '\0';
849                 *end = '\0';
850                 tmp = methods;
851                 methods = os_realloc(methods,
852                                      (num_methods + 1) * sizeof(*methods));
853                 if (methods == NULL) {
854                         os_free(tmp);
855                         os_free(buf);
856                         return -1;
857                 }
858                 methods[num_methods].method = eap_get_type(
859                         start, &methods[num_methods].vendor);
860                 if (methods[num_methods].vendor == EAP_VENDOR_IETF &&
861                     methods[num_methods].method == EAP_TYPE_NONE) {
862                         wpa_printf(MSG_ERROR, "Line %d: unknown EAP method "
863                                    "'%s'", line, start);
864                         wpa_printf(MSG_ERROR, "You may need to add support for"
865                                    " this EAP method during wpa_supplicant\n"
866                                    "build time configuration.\n"
867                                    "See README for more information.");
868                         errors++;
869                 } else if (methods[num_methods].vendor == EAP_VENDOR_IETF &&
870                            methods[num_methods].method == EAP_TYPE_LEAP)
871                         ssid->leap++;
872                 else
873                         ssid->non_leap++;
874                 num_methods++;
875                 if (last)
876                         break;
877                 start = end + 1;
878         }
879         os_free(buf);
880
881         tmp = methods;
882         methods = os_realloc(methods, (num_methods + 1) * sizeof(*methods));
883         if (methods == NULL) {
884                 os_free(tmp);
885                 return -1;
886         }
887         methods[num_methods].vendor = EAP_VENDOR_IETF;
888         methods[num_methods].method = EAP_TYPE_NONE;
889         num_methods++;
890
891         wpa_hexdump(MSG_MSGDUMP, "eap methods",
892                     (u8 *) methods, num_methods * sizeof(*methods));
893         ssid->eap_methods = methods;
894         return errors ? -1 : 0;
895 }
896
897
898 static char * wpa_config_write_eap(const struct parse_data *data,
899                                    struct wpa_ssid *ssid)
900 {
901         int i, ret;
902         char *buf, *pos, *end;
903         const struct eap_method_type *eap_methods = ssid->eap_methods;
904         const char *name;
905
906         if (eap_methods == NULL)
907                 return NULL;
908
909         pos = buf = os_zalloc(100);
910         if (buf == NULL)
911                 return NULL;
912         end = buf + 100;
913
914         for (i = 0; eap_methods[i].vendor != EAP_VENDOR_IETF ||
915                      eap_methods[i].method != EAP_TYPE_NONE; i++) {
916                 name = eap_get_name(eap_methods[i].vendor,
917                                     eap_methods[i].method);
918                 if (name) {
919                         ret = os_snprintf(pos, end - pos, "%s%s",
920                                           pos == buf ? "" : " ", name);
921                         if (ret < 0 || ret >= end - pos)
922                                 break;
923                         pos += ret;
924                 }
925         }
926
927         end[-1] = '\0';
928
929         return buf;
930 }
931 #endif /* IEEE8021X_EAPOL */
932
933
934 static int wpa_config_parse_wep_key(u8 *key, size_t *len, int line,
935                                     const char *value, int idx)
936 {
937         char *buf, title[20];
938
939         buf = wpa_config_parse_string(value, len);
940         if (buf == NULL) {
941                 wpa_printf(MSG_ERROR, "Line %d: Invalid WEP key %d '%s'.",
942                            line, idx, value);
943                 return -1;
944         }
945         if (*len > MAX_WEP_KEY_LEN) {
946                 wpa_printf(MSG_ERROR, "Line %d: Too long WEP key %d '%s'.",
947                            line, idx, value);
948                 os_free(buf);
949                 return -1;
950         }
951         os_memcpy(key, buf, *len);
952         os_free(buf);
953         os_snprintf(title, sizeof(title), "wep_key%d", idx);
954         wpa_hexdump_key(MSG_MSGDUMP, title, key, *len);
955         return 0;
956 }
957
958
959 static int wpa_config_parse_wep_key0(const struct parse_data *data,
960                                      struct wpa_ssid *ssid, int line,
961                                      const char *value)
962 {
963         return wpa_config_parse_wep_key(ssid->wep_key[0],
964                                         &ssid->wep_key_len[0], line,
965                                         value, 0);
966 }
967
968
969 static int wpa_config_parse_wep_key1(const struct parse_data *data,
970                                      struct wpa_ssid *ssid, int line,
971                                      const char *value)
972 {
973         return wpa_config_parse_wep_key(ssid->wep_key[1],
974                                         &ssid->wep_key_len[1], line,
975                                         value, 1);
976 }
977
978
979 static int wpa_config_parse_wep_key2(const struct parse_data *data,
980                                      struct wpa_ssid *ssid, int line,
981                                      const char *value)
982 {
983         return wpa_config_parse_wep_key(ssid->wep_key[2],
984                                         &ssid->wep_key_len[2], line,
985                                         value, 2);
986 }
987
988
989 static int wpa_config_parse_wep_key3(const struct parse_data *data,
990                                      struct wpa_ssid *ssid, int line,
991                                      const char *value)
992 {
993         return wpa_config_parse_wep_key(ssid->wep_key[3],
994                                         &ssid->wep_key_len[3], line,
995                                         value, 3);
996 }
997
998
999 static char * wpa_config_write_wep_key(struct wpa_ssid *ssid, int idx)
1000 {
1001         if (ssid->wep_key_len[idx] == 0)
1002                 return NULL;
1003         return wpa_config_write_string(ssid->wep_key[idx],
1004                                        ssid->wep_key_len[idx]);
1005 }
1006
1007
1008 static char * wpa_config_write_wep_key0(const struct parse_data *data,
1009                                         struct wpa_ssid *ssid)
1010 {
1011         return wpa_config_write_wep_key(ssid, 0);
1012 }
1013
1014
1015 static char * wpa_config_write_wep_key1(const struct parse_data *data,
1016                                         struct wpa_ssid *ssid)
1017 {
1018         return wpa_config_write_wep_key(ssid, 1);
1019 }
1020
1021
1022 static char * wpa_config_write_wep_key2(const struct parse_data *data,
1023                                         struct wpa_ssid *ssid)
1024 {
1025         return wpa_config_write_wep_key(ssid, 2);
1026 }
1027
1028
1029 static char * wpa_config_write_wep_key3(const struct parse_data *data,
1030                                         struct wpa_ssid *ssid)
1031 {
1032         return wpa_config_write_wep_key(ssid, 3);
1033 }
1034
1035
1036 /* Helper macros for network block parser */
1037
1038 #ifdef OFFSET
1039 #undef OFFSET
1040 #endif /* OFFSET */
1041 /* OFFSET: Get offset of a variable within the wpa_ssid structure */
1042 #define OFFSET(v) ((void *) &((struct wpa_ssid *) 0)->v)
1043
1044 /* STR: Define a string variable for an ASCII string; f = field name */
1045 #define _STR(f) #f, wpa_config_parse_str, wpa_config_write_str, OFFSET(f)
1046 #define STR(f) _STR(f), NULL, NULL, NULL, 0
1047 #define STR_KEY(f) _STR(f), NULL, NULL, NULL, 1
1048
1049 /* STR_LEN: Define a string variable with a separate variable for storing the
1050  * data length. Unlike STR(), this can be used to store arbitrary binary data
1051  * (i.e., even nul termination character). */
1052 #define _STR_LEN(f) _STR(f), OFFSET(f ## _len)
1053 #define STR_LEN(f) _STR_LEN(f), NULL, NULL, 0
1054 #define STR_LEN_KEY(f) _STR_LEN(f), NULL, NULL, 1
1055
1056 /* STR_RANGE: Like STR_LEN(), but with minimum and maximum allowed length
1057  * explicitly specified. */
1058 #define _STR_RANGE(f, min, max) _STR_LEN(f), (void *) (min), (void *) (max)
1059 #define STR_RANGE(f, min, max) _STR_RANGE(f, min, max), 0
1060 #define STR_RANGE_KEY(f, min, max) _STR_RANGE(f, min, max), 1
1061
1062 #define _INT(f) #f, wpa_config_parse_int, wpa_config_write_int, \
1063         OFFSET(f), (void *) 0
1064
1065 /* INT: Define an integer variable */
1066 #define INT(f) _INT(f), NULL, NULL, 0
1067
1068 /* INT_RANGE: Define an integer variable with allowed value range */
1069 #define INT_RANGE(f, min, max) _INT(f), (void *) (min), (void *) (max), 0
1070
1071 /* FUNC: Define a configuration variable that uses a custom function for
1072  * parsing and writing the value. */
1073 #define _FUNC(f) #f, wpa_config_parse_ ## f, wpa_config_write_ ## f, \
1074         NULL, NULL, NULL, NULL
1075 #define FUNC(f) _FUNC(f), 0
1076 #define FUNC_KEY(f) _FUNC(f), 1
1077
1078 /*
1079  * Table of network configuration variables. This table is used to parse each
1080  * network configuration variable, e.g., each line in wpa_supplicant.conf file
1081  * that is inside a network block.
1082  *
1083  * This table is generated using the helper macros defined above and with
1084  * generous help from the C pre-processor. The field name is stored as a string
1085  * into .name and for STR and INT types, the offset of the target buffer within
1086  * struct wpa_ssid is stored in .param1. .param2 (if not NULL) is similar
1087  * offset to the field containing the length of the configuration variable.
1088  * .param3 and .param4 can be used to mark the allowed range (length for STR
1089  * and value for INT).
1090  *
1091  * For each configuration line in wpa_supplicant.conf, the parser goes through
1092  * this table and select the entry that matches with the field name. The parser
1093  * function (.parser) is then called to parse the actual value of the field.
1094  *
1095  * This kind of mechanism makes it easy to add new configuration parameters,
1096  * since only one line needs to be added into this table and into the
1097  * struct wpa_ssid definition if the new variable is either a string or
1098  * integer. More complex types will need to use their own parser and writer
1099  * functions.
1100  */
1101 static const struct parse_data ssid_fields[] = {
1102         { STR_RANGE(ssid, 0, MAX_SSID_LEN) },
1103         { INT_RANGE(scan_ssid, 0, 1) },
1104         { FUNC(bssid) },
1105         { FUNC_KEY(psk) },
1106         { FUNC(proto) },
1107         { FUNC(key_mgmt) },
1108         { FUNC(pairwise) },
1109         { FUNC(group) },
1110         { FUNC(auth_alg) },
1111 #ifdef IEEE8021X_EAPOL
1112         { FUNC(eap) },
1113         { STR_LEN(identity) },
1114         { STR_LEN(anonymous_identity) },
1115         { STR_RANGE_KEY(eappsk, EAP_PSK_LEN_MIN, EAP_PSK_LEN_MAX) },
1116         { STR_LEN(nai) },
1117         { STR_LEN_KEY(password) },
1118         { STR(ca_cert) },
1119         { STR(ca_path) },
1120         { STR(client_cert) },
1121         { STR(private_key) },
1122         { STR_KEY(private_key_passwd) },
1123         { STR(dh_file) },
1124         { STR(subject_match) },
1125         { STR(altsubject_match) },
1126         { STR(ca_cert2) },
1127         { STR(ca_path2) },
1128         { STR(client_cert2) },
1129         { STR(private_key2) },
1130         { STR_KEY(private_key2_passwd) },
1131         { STR(dh_file2) },
1132         { STR(subject_match2) },
1133         { STR(altsubject_match2) },
1134         { STR(phase1) },
1135         { STR(phase2) },
1136         { STR(pcsc) },
1137         { STR_KEY(pin) },
1138         { STR(engine_id) },
1139         { STR(key_id) },
1140         { INT(engine) },
1141         { INT(eapol_flags) },
1142 #endif /* IEEE8021X_EAPOL */
1143         { FUNC_KEY(wep_key0) },
1144         { FUNC_KEY(wep_key1) },
1145         { FUNC_KEY(wep_key2) },
1146         { FUNC_KEY(wep_key3) },
1147         { INT(wep_tx_keyidx) },
1148         { INT(priority) },
1149 #ifdef IEEE8021X_EAPOL
1150         { INT(eap_workaround) },
1151         { STR(pac_file) },
1152         { INT(fragment_size) },
1153 #endif /* IEEE8021X_EAPOL */
1154         { INT_RANGE(mode, 0, 1) },
1155         { INT_RANGE(proactive_key_caching, 0, 1) },
1156         { INT_RANGE(disabled, 0, 1) },
1157         { STR(id_str) },
1158 #ifdef CONFIG_IEEE80211W
1159         { INT_RANGE(ieee80211w, 0, 2) },
1160 #endif /* CONFIG_IEEE80211W */
1161         { INT_RANGE(peerkey, 0, 1) },
1162         { INT_RANGE(mixed_cell, 0, 1) },
1163         { INT_RANGE(frequency, 0, 10000) }
1164 };
1165
1166 #undef OFFSET
1167 #undef _STR
1168 #undef STR
1169 #undef STR_KEY
1170 #undef _STR_LEN
1171 #undef STR_LEN
1172 #undef STR_LEN_KEY
1173 #undef _STR_RANGE
1174 #undef STR_RANGE
1175 #undef STR_RANGE_KEY
1176 #undef _INT
1177 #undef INT
1178 #undef INT_RANGE
1179 #undef _FUNC
1180 #undef FUNC
1181 #undef FUNC_KEY
1182 #define NUM_SSID_FIELDS (sizeof(ssid_fields) / sizeof(ssid_fields[0]))
1183
1184
1185 /**
1186  * wpa_config_add_prio_network - Add a network to priority lists
1187  * @config: Configuration data from wpa_config_read()
1188  * @ssid: Pointer to the network configuration to be added to the list
1189  * Returns: 0 on success, -1 on failure
1190  *
1191  * This function is used to add a network block to the priority list of
1192  * networks. This must be called for each network when reading in the full
1193  * configuration. In addition, this can be used indirectly when updating
1194  * priorities by calling wpa_config_update_prio_list().
1195  */
1196 int wpa_config_add_prio_network(struct wpa_config *config,
1197                                 struct wpa_ssid *ssid)
1198 {
1199         int prio;
1200         struct wpa_ssid *prev, **nlist;
1201
1202         /*
1203          * Add to an existing priority list if one is available for the
1204          * configured priority level for this network.
1205          */
1206         for (prio = 0; prio < config->num_prio; prio++) {
1207                 prev = config->pssid[prio];
1208                 if (prev->priority == ssid->priority) {
1209                         while (prev->pnext)
1210                                 prev = prev->pnext;
1211                         prev->pnext = ssid;
1212                         return 0;
1213                 }
1214         }
1215
1216         /* First network for this priority - add a new priority list */
1217         nlist = os_realloc(config->pssid,
1218                            (config->num_prio + 1) * sizeof(struct wpa_ssid *));
1219         if (nlist == NULL)
1220                 return -1;
1221
1222         for (prio = 0; prio < config->num_prio; prio++) {
1223                 if (nlist[prio]->priority < ssid->priority)
1224                         break;
1225         }
1226
1227         os_memmove(&nlist[prio + 1], &nlist[prio],
1228                    (config->num_prio - prio) * sizeof(struct wpa_ssid *));
1229
1230         nlist[prio] = ssid;
1231         config->num_prio++;
1232         config->pssid = nlist;
1233
1234         return 0;
1235 }
1236
1237
1238 /**
1239  * wpa_config_update_prio_list - Update network priority list
1240  * @config: Configuration data from wpa_config_read()
1241  * Returns: 0 on success, -1 on failure
1242  *
1243  * This function is called to update the priority list of networks in the
1244  * configuration when a network is being added or removed. This is also called
1245  * if a priority for a network is changed.
1246  */
1247 static int wpa_config_update_prio_list(struct wpa_config *config)
1248 {
1249         struct wpa_ssid *ssid;
1250         int ret = 0;
1251
1252         os_free(config->pssid);
1253         config->pssid = NULL;
1254         config->num_prio = 0;
1255
1256         ssid = config->ssid;
1257         while (ssid) {
1258                 ssid->pnext = NULL;
1259                 if (wpa_config_add_prio_network(config, ssid) < 0)
1260                         ret = -1;
1261                 ssid = ssid->next;
1262         }
1263
1264         return ret;
1265 }
1266
1267
1268 /**
1269  * wpa_config_free_ssid - Free network/ssid configuration data
1270  * @ssid: Configuration data for the network
1271  *
1272  * This function frees all resources allocated for the network configuration
1273  * data.
1274  */
1275 void wpa_config_free_ssid(struct wpa_ssid *ssid)
1276 {
1277         os_free(ssid->ssid);
1278         os_free(ssid->passphrase);
1279 #ifdef IEEE8021X_EAPOL
1280         os_free(ssid->eap_methods);
1281         os_free(ssid->identity);
1282         os_free(ssid->anonymous_identity);
1283         os_free(ssid->eappsk);
1284         os_free(ssid->nai);
1285         os_free(ssid->password);
1286         os_free(ssid->ca_cert);
1287         os_free(ssid->ca_path);
1288         os_free(ssid->client_cert);
1289         os_free(ssid->private_key);
1290         os_free(ssid->private_key_passwd);
1291         os_free(ssid->dh_file);
1292         os_free(ssid->subject_match);
1293         os_free(ssid->altsubject_match);
1294         os_free(ssid->ca_cert2);
1295         os_free(ssid->ca_path2);
1296         os_free(ssid->client_cert2);
1297         os_free(ssid->private_key2);
1298         os_free(ssid->private_key2_passwd);
1299         os_free(ssid->dh_file2);
1300         os_free(ssid->subject_match2);
1301         os_free(ssid->altsubject_match2);
1302         os_free(ssid->phase1);
1303         os_free(ssid->phase2);
1304         os_free(ssid->pcsc);
1305         os_free(ssid->pin);
1306         os_free(ssid->engine_id);
1307         os_free(ssid->key_id);
1308         os_free(ssid->otp);
1309         os_free(ssid->pending_req_otp);
1310         os_free(ssid->pac_file);
1311         os_free(ssid->new_password);
1312 #endif /* IEEE8021X_EAPOL */
1313         os_free(ssid->id_str);
1314         os_free(ssid);
1315 }
1316
1317
1318 /**
1319  * wpa_config_free - Free configuration data
1320  * @config: Configuration data from wpa_config_read()
1321  *
1322  * This function frees all resources allocated for the configuration data by
1323  * wpa_config_read().
1324  */
1325 void wpa_config_free(struct wpa_config *config)
1326 {
1327         struct wpa_config_blob *blob, *prevblob;
1328         struct wpa_ssid *ssid, *prev = NULL;
1329         ssid = config->ssid;
1330         while (ssid) {
1331                 prev = ssid;
1332                 ssid = ssid->next;
1333                 wpa_config_free_ssid(prev);
1334         }
1335
1336         blob = config->blobs;
1337         prevblob = NULL;
1338         while (blob) {
1339                 prevblob = blob;
1340                 blob = blob->next;
1341                 wpa_config_free_blob(prevblob);
1342         }
1343
1344         os_free(config->ctrl_interface);
1345         os_free(config->ctrl_interface_group);
1346         os_free(config->opensc_engine_path);
1347         os_free(config->pkcs11_engine_path);
1348         os_free(config->pkcs11_module_path);
1349         os_free(config->driver_param);
1350         os_free(config->pssid);
1351         os_free(config);
1352 }
1353
1354
1355 #ifdef IEEE8021X_EAPOL
1356 /**
1357  * wpa_config_allowed_eap_method - Check whether EAP method is allowed
1358  * @ssid: Pointer to configuration data
1359  * @vendor: Vendor-Id for expanded types or 0 = IETF for legacy types
1360  * @method: EAP type
1361  * Returns: 1 = allowed EAP method, 0 = not allowed
1362  */
1363 int wpa_config_allowed_eap_method(struct wpa_ssid *ssid, int vendor,
1364                                   u32 method)
1365 {
1366         int i;
1367         struct eap_method_type *m;
1368
1369         if (ssid == NULL || ssid->eap_methods == NULL)
1370                 return 1;
1371
1372         m = ssid->eap_methods;
1373         for (i = 0; m[i].vendor != EAP_VENDOR_IETF ||
1374                      m[i].method != EAP_TYPE_NONE; i++) {
1375                 if (m[i].vendor == vendor && m[i].method == method)
1376                         return 1;
1377         }
1378         return 0;
1379 }
1380 #endif /* IEEE8021X_EAPOL */
1381
1382
1383 /**
1384  * wpa_config_get_network - Get configured network based on id
1385  * @config: Configuration data from wpa_config_read()
1386  * @id: Unique network id to search for
1387  * Returns: Network configuration or %NULL if not found
1388  */
1389 struct wpa_ssid * wpa_config_get_network(struct wpa_config *config, int id)
1390 {
1391         struct wpa_ssid *ssid;
1392
1393         ssid = config->ssid;
1394         while (ssid) {
1395                 if (id == ssid->id)
1396                         break;
1397                 ssid = ssid->next;
1398         }
1399
1400         return ssid;
1401 }
1402
1403
1404 /**
1405  * wpa_config_add_network - Add a new network with empty configuration
1406  * @config: Configuration data from wpa_config_read()
1407  * Returns: The new network configuration or %NULL if operation failed
1408  */
1409 struct wpa_ssid * wpa_config_add_network(struct wpa_config *config)
1410 {
1411         int id;
1412         struct wpa_ssid *ssid, *last = NULL;
1413
1414         id = -1;
1415         ssid = config->ssid;
1416         while (ssid) {
1417                 if (ssid->id > id)
1418                         id = ssid->id;
1419                 last = ssid;
1420                 ssid = ssid->next;
1421         }
1422         id++;
1423
1424         ssid = os_zalloc(sizeof(*ssid));
1425         if (ssid == NULL)
1426                 return NULL;
1427         ssid->id = id;
1428         if (last)
1429                 last->next = ssid;
1430         else
1431                 config->ssid = ssid;
1432
1433         wpa_config_update_prio_list(config);
1434
1435         return ssid;
1436 }
1437
1438
1439 /**
1440  * wpa_config_remove_network - Remove a configured network based on id
1441  * @config: Configuration data from wpa_config_read()
1442  * @id: Unique network id to search for
1443  * Returns: 0 on success, or -1 if the network was not found
1444  */
1445 int wpa_config_remove_network(struct wpa_config *config, int id)
1446 {
1447         struct wpa_ssid *ssid, *prev = NULL;
1448
1449         ssid = config->ssid;
1450         while (ssid) {
1451                 if (id == ssid->id)
1452                         break;
1453                 prev = ssid;
1454                 ssid = ssid->next;
1455         }
1456
1457         if (ssid == NULL)
1458                 return -1;
1459
1460         if (prev)
1461                 prev->next = ssid->next;
1462         else
1463                 config->ssid = ssid->next;
1464
1465         wpa_config_update_prio_list(config);
1466         wpa_config_free_ssid(ssid);
1467         return 0;
1468 }
1469
1470
1471 /**
1472  * wpa_config_set_network_defaults - Set network default values
1473  * @ssid: Pointer to network configuration data
1474  */
1475 void wpa_config_set_network_defaults(struct wpa_ssid *ssid)
1476 {
1477         ssid->proto = DEFAULT_PROTO;
1478         ssid->pairwise_cipher = DEFAULT_PAIRWISE;
1479         ssid->group_cipher = DEFAULT_GROUP;
1480         ssid->key_mgmt = DEFAULT_KEY_MGMT;
1481 #ifdef IEEE8021X_EAPOL
1482         ssid->eapol_flags = DEFAULT_EAPOL_FLAGS;
1483         ssid->eap_workaround = DEFAULT_EAP_WORKAROUND;
1484         ssid->fragment_size = DEFAULT_FRAGMENT_SIZE;
1485 #endif /* IEEE8021X_EAPOL */
1486 }
1487
1488
1489 /**
1490  * wpa_config_set - Set a variable in network configuration
1491  * @ssid: Pointer to network configuration data
1492  * @var: Variable name, e.g., "ssid"
1493  * @value: Variable value
1494  * @line: Line number in configuration file or 0 if not used
1495  * Returns: 0 on success, -1 on failure
1496  *
1497  * This function can be used to set network configuration variables based on
1498  * both the configuration file and management interface input. The value
1499  * parameter must be in the same format as the text-based configuration file is
1500  * using. For example, strings are using double quotation marks.
1501  */
1502 int wpa_config_set(struct wpa_ssid *ssid, const char *var, const char *value,
1503                    int line)
1504 {
1505         size_t i;
1506         int ret = 0;
1507
1508         if (ssid == NULL || var == NULL || value == NULL)
1509                 return -1;
1510
1511         for (i = 0; i < NUM_SSID_FIELDS; i++) {
1512                 const struct parse_data *field = &ssid_fields[i];
1513                 if (os_strcmp(var, field->name) != 0)
1514                         continue;
1515
1516                 if (field->parser(field, ssid, line, value)) {
1517                         if (line) {
1518                                 wpa_printf(MSG_ERROR, "Line %d: failed to "
1519                                            "parse %s '%s'.", line, var, value);
1520                         }
1521                         ret = -1;
1522                 }
1523                 break;
1524         }
1525         if (i == NUM_SSID_FIELDS) {
1526                 if (line) {
1527                         wpa_printf(MSG_ERROR, "Line %d: unknown network field "
1528                                    "'%s'.", line, var);
1529                 }
1530                 ret = -1;
1531         }
1532
1533         return ret;
1534 }
1535
1536
1537 /**
1538  * wpa_config_get - Get a variable in network configuration
1539  * @ssid: Pointer to network configuration data
1540  * @var: Variable name, e.g., "ssid"
1541  * Returns: Value of the variable or %NULL on failure
1542  *
1543  * This function can be used to get network configuration variables. The
1544  * returned value is a copy of the configuration variable in text format, i.e,.
1545  * the same format that the text-based configuration file and wpa_config_set()
1546  * are using for the value. The caller is responsible for freeing the returned
1547  * value.
1548  */
1549 char * wpa_config_get(struct wpa_ssid *ssid, const char *var)
1550 {
1551         size_t i;
1552
1553         if (ssid == NULL || var == NULL)
1554                 return NULL;
1555
1556         for (i = 0; i < NUM_SSID_FIELDS; i++) {
1557                 const struct parse_data *field = &ssid_fields[i];
1558                 if (os_strcmp(var, field->name) == 0)
1559                         return field->writer(field, ssid);
1560         }
1561
1562         return NULL;
1563 }
1564
1565
1566 /**
1567  * wpa_config_get_no_key - Get a variable in network configuration (no keys)
1568  * @ssid: Pointer to network configuration data
1569  * @var: Variable name, e.g., "ssid"
1570  * Returns: Value of the variable or %NULL on failure
1571  *
1572  * This function can be used to get network configuration variable like
1573  * wpa_config_get(). The only difference is that this functions does not expose
1574  * key/password material from the configuration. In case a key/password field
1575  * is requested, the returned value is an empty string or %NULL if the variable
1576  * is not set or "*" if the variable is set (regardless of its value). The
1577  * returned value is a copy of the configuration variable in text format, i.e,.
1578  * the same format that the text-based configuration file and wpa_config_set()
1579  * are using for the value. The caller is responsible for freeing the returned
1580  * value.
1581  */
1582 char * wpa_config_get_no_key(struct wpa_ssid *ssid, const char *var)
1583 {
1584         size_t i;
1585
1586         if (ssid == NULL || var == NULL)
1587                 return NULL;
1588
1589         for (i = 0; i < NUM_SSID_FIELDS; i++) {
1590                 const struct parse_data *field = &ssid_fields[i];
1591                 if (os_strcmp(var, field->name) == 0) {
1592                         char *res = field->writer(field, ssid);
1593                         if (field->key_data) {
1594                                 if (res && res[0]) {
1595                                         wpa_printf(MSG_DEBUG, "Do not allow "
1596                                                    "key_data field to be "
1597                                                    "exposed");
1598                                         os_free(res);
1599                                         return os_strdup("*");
1600                                 }
1601
1602                                 os_free(res);
1603                                 return NULL;
1604                         }
1605                         return res;
1606                 }
1607         }
1608
1609         return NULL;
1610 }
1611
1612
1613 /**
1614  * wpa_config_update_psk - Update WPA PSK based on passphrase and SSID
1615  * @ssid: Pointer to network configuration data
1616  *
1617  * This function must be called to update WPA PSK when either SSID or the
1618  * passphrase has changed for the network configuration.
1619  */
1620 void wpa_config_update_psk(struct wpa_ssid *ssid)
1621 {
1622         pbkdf2_sha1(ssid->passphrase,
1623                     (char *) ssid->ssid, ssid->ssid_len, 4096,
1624                     ssid->psk, PMK_LEN);
1625         wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1626                         ssid->psk, PMK_LEN);
1627         ssid->psk_set = 1;
1628 }
1629
1630
1631 /**
1632  * wpa_config_get_blob - Get a named configuration blob
1633  * @config: Configuration data from wpa_config_read()
1634  * @name: Name of the blob
1635  * Returns: Pointer to blob data or %NULL if not found
1636  */
1637 const struct wpa_config_blob * wpa_config_get_blob(struct wpa_config *config,
1638                                                    const char *name)
1639 {
1640         struct wpa_config_blob *blob = config->blobs;
1641
1642         while (blob) {
1643                 if (os_strcmp(blob->name, name) == 0)
1644                         return blob;
1645                 blob = blob->next;
1646         }
1647         return NULL;
1648 }
1649
1650
1651 /**
1652  * wpa_config_set_blob - Set or add a named configuration blob
1653  * @config: Configuration data from wpa_config_read()
1654  * @blob: New value for the blob
1655  *
1656  * Adds a new configuration blob or replaces the current value of an existing
1657  * blob.
1658  */
1659 void wpa_config_set_blob(struct wpa_config *config,
1660                          struct wpa_config_blob *blob)
1661 {
1662         wpa_config_remove_blob(config, blob->name);
1663         blob->next = config->blobs;
1664         config->blobs = blob;
1665 }
1666
1667
1668 /**
1669  * wpa_config_free_blob - Free blob data
1670  * @blob: Pointer to blob to be freed
1671  */
1672 void wpa_config_free_blob(struct wpa_config_blob *blob)
1673 {
1674         if (blob) {
1675                 os_free(blob->name);
1676                 os_free(blob->data);
1677                 os_free(blob);
1678         }
1679 }
1680
1681
1682 /**
1683  * wpa_config_remove_blob - Remove a named configuration blob
1684  * @config: Configuration data from wpa_config_read()
1685  * @name: Name of the blob to remove
1686  * Returns: 0 if blob was removed or -1 if blob was not found
1687  */
1688 int wpa_config_remove_blob(struct wpa_config *config, const char *name)
1689 {
1690         struct wpa_config_blob *pos = config->blobs, *prev = NULL;
1691
1692         while (pos) {
1693                 if (os_strcmp(pos->name, name) == 0) {
1694                         if (prev)
1695                                 prev->next = pos->next;
1696                         else
1697                                 config->blobs = pos->next;
1698                         wpa_config_free_blob(pos);
1699                         return 0;
1700                 }
1701                 prev = pos;
1702                 pos = pos->next;
1703         }
1704
1705         return -1;
1706 }
1707
1708
1709 /**
1710  * wpa_config_alloc_empty - Allocate an empty configuration
1711  * @ctrl_interface: Control interface parameters, e.g., path to UNIX domain
1712  * socket
1713  * @driver_param: Driver parameters
1714  * Returns: Pointer to allocated configuration data or %NULL on failure
1715  */
1716 struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface,
1717                                            const char *driver_param)
1718 {
1719         struct wpa_config *config;
1720
1721         config = os_zalloc(sizeof(*config));
1722         if (config == NULL)
1723                 return NULL;
1724         config->eapol_version = DEFAULT_EAPOL_VERSION;
1725         config->ap_scan = DEFAULT_AP_SCAN;
1726         config->fast_reauth = DEFAULT_FAST_REAUTH;
1727
1728         if (ctrl_interface)
1729                 config->ctrl_interface = os_strdup(ctrl_interface);
1730         if (driver_param)
1731                 config->driver_param = os_strdup(driver_param);
1732
1733         return config;
1734 }
1735
1736
1737 #ifndef CONFIG_NO_STDOUT_DEBUG
1738 /**
1739  * wpa_config_debug_dump_networks - Debug dump of configured networks
1740  * @config: Configuration data from wpa_config_read()
1741  */
1742 void wpa_config_debug_dump_networks(struct wpa_config *config)
1743 {
1744         int prio;
1745         struct wpa_ssid *ssid;
1746
1747         for (prio = 0; prio < config->num_prio; prio++) {
1748                 ssid = config->pssid[prio];
1749                 wpa_printf(MSG_DEBUG, "Priority group %d",
1750                            ssid->priority);
1751                 while (ssid) {
1752                         wpa_printf(MSG_DEBUG, "   id=%d ssid='%s'",
1753                                    ssid->id,
1754                                    wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
1755                         ssid = ssid->pnext;
1756                 }
1757         }
1758 }
1759 #endif /* CONFIG_NO_STDOUT_DEBUG */