1 /*
2 * EAP peer state machines (RFC 4137)
3 * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
4 *
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
7 *
8 * This file implements the Peer State Machine as defined in RFC 4137. The used
9 * states and state transitions match mostly with the RFC. However, there are
10 * couple of additional transitions for working around small issues noticed
11 * during testing. These exceptions are explained in comments within the
12 * functions in this file. The method functions, m.func(), are similar to the
13 * ones used in RFC 4137, but some small changes have used here to optimize
14 * operations and to add functionality needed for fast re-authentication
15 * (session resumption).
16 */
17 #include <string.h>
18
19 #include "esp_err.h"
20
21 #include "utils/includes.h"
22 #include "utils/common.h"
23 #include "utils/wpa_debug.h"
24 #include "common/eapol_common.h"
25 #include "common/ieee802_11_defs.h"
26 #include "utils/state_machine.h"
27 #include "rsn_supp/wpa.h"
28
29 #include "crypto/crypto.h"
30 #include "crypto/sha256.h"
31
32 #include "utils/ext_password.h"
33 #include "tls/tls.h"
34 #include "eap_peer/eap_i.h"
35 #include "eap_peer/eap_config.h"
36 #include "eap_peer/eap.h"
37 #include "eap_peer/eap_tls.h"
38 #include "esp_wifi_driver.h"
39 #ifdef EAP_PEER_METHOD
40 #include "eap_peer/eap_methods.h"
41 #endif
42
43 #include "supplicant_opt.h"
44
45
46 void eap_peer_config_deinit(struct eap_sm *sm);
47 void eap_peer_blob_deinit(struct eap_sm *sm);
48 void eap_deinit_prev_method(struct eap_sm *sm, const char *txt);
49
50 #ifdef EAP_PEER_METHOD
51 static struct eap_method *eap_methods = NULL;
52
eap_peer_get_eap_method(int vendor,EapType method)53 const struct eap_method * eap_peer_get_eap_method(int vendor, EapType method)
54 {
55 struct eap_method *m;
56 for (m = eap_methods; m; m = m->next) {
57 if (m->vendor == vendor && m->method == method)
58 return m;
59 }
60 return NULL;
61 }
62
eap_peer_get_methods(size_t * count)63 const struct eap_method * eap_peer_get_methods(size_t *count)
64 {
65 int c = 0;
66 struct eap_method *m;
67
68 for (m = eap_methods; m; m = m->next)
69 c++;
70
71 *count = c;
72 return eap_methods;
73 }
74
eap_peer_get_type(const char * name,int * vendor)75 EapType eap_peer_get_type(const char *name, int *vendor)
76 {
77 struct eap_method *m;
78 for (m = eap_methods; m; m = m->next) {
79 if (os_strcmp(m->name, name) == 0) {
80 *vendor = m->vendor;
81 return m->method;
82 }
83 }
84 *vendor = EAP_VENDOR_IETF;
85 return EAP_TYPE_NONE;
86 }
87
88 static int
eap_allowed_phase2_type(int vendor,int type)89 eap_allowed_phase2_type(int vendor, int type)
90 {
91 if (vendor != EAP_VENDOR_IETF)
92 return 0;
93 return type != EAP_TYPE_PEAP && type != EAP_TYPE_TTLS &&
94 type != EAP_TYPE_FAST;
95 }
96
eap_get_phase2_type(const char * name,int * vendor)97 u32 eap_get_phase2_type(const char *name, int *vendor)
98 {
99 int v;
100 u8 type = eap_peer_get_type(name, &v);
101 if (eap_allowed_phase2_type(v, type)) {
102 *vendor = v;
103 return type;
104 }
105 *vendor = EAP_VENDOR_IETF;
106 return EAP_TYPE_NONE;
107 }
108
eap_get_phase2_types(struct eap_peer_config * config,size_t * count)109 struct eap_method_type * eap_get_phase2_types(struct eap_peer_config *config,
110 size_t *count)
111 {
112 struct eap_method_type *buf;
113 u32 method;
114 int vendor;
115 size_t mcount;
116 const struct eap_method *methods, *m;
117
118 methods = eap_peer_get_methods(&mcount);
119 if (methods == NULL)
120 return NULL;
121 *count = 0;
122 buf = os_malloc(mcount * sizeof(struct eap_method_type));
123 if (buf == NULL)
124 return NULL;
125
126 for (m = methods; m; m = m->next) {
127 vendor = m->vendor;
128 method = m->method;
129 if (eap_allowed_phase2_type(vendor, method)) {
130 if (vendor == EAP_VENDOR_IETF &&
131 method == EAP_TYPE_TLS && config &&
132 config->private_key2 == NULL)
133 continue;
134 buf[*count].vendor = vendor;
135 buf[*count].method = method;
136 (*count)++;
137 }
138 }
139
140 return buf;
141 }
142
eap_peer_method_alloc(int vendor,EapType method,const char * name)143 struct eap_method * eap_peer_method_alloc(int vendor, EapType method,
144 const char *name)
145 {
146 struct eap_method *eap;
147 eap = (struct eap_method *)os_zalloc(sizeof(*eap));
148 if (eap == NULL)
149 return NULL;
150 eap->vendor = vendor;
151 eap->method = method;
152 eap->name = name;
153 return eap;
154 }
155
eap_peer_method_free(struct eap_method * method)156 void eap_peer_method_free(struct eap_method *method)
157 {
158 os_free(method);
159 }
160
eap_peer_method_register(struct eap_method * method)161 int eap_peer_method_register(struct eap_method *method)
162 {
163 struct eap_method *m, *last = NULL;
164
165 if (method == NULL || method->name == NULL)
166 return -1;
167 for (m = eap_methods; m; m = m->next) {
168 if (m->vendor == method->vendor &&
169 m->method == method->method &&
170 os_strcmp(m->name, method->name))
171 return -2;
172 last = m;
173 }
174 if (last)
175 last->next = method;
176 else
177 eap_methods = method;
178 return 0;
179 }
180
eap_peer_unregister_methods(void)181 void eap_peer_unregister_methods(void)
182 {
183 struct eap_method *m;
184 while (eap_methods) {
185 m = eap_methods;
186 eap_methods = eap_methods->next;
187
188 if (m->free)
189 m->free(m);
190 else
191 eap_peer_method_free(m);
192 }
193 }
194
195
196
eap_peer_register_methods(void)197 int eap_peer_register_methods(void)
198 {
199 int ret = 0;
200
201 #ifdef EAP_MD5
202 if (ret == 0)
203 ret = eap_peer_md5_register();
204 #endif
205
206 #ifdef EAP_TLS
207 if (ret == 0)
208 ret = eap_peer_tls_register();
209 #endif
210
211 #ifdef EAP_MSCHAPv2
212 if (ret == 0)
213 ret = eap_peer_mschapv2_register();
214 #endif
215
216 #ifndef USE_MBEDTLS_CRYPTO
217 #ifdef EAP_FAST
218 if (ret == 0)
219 ret = eap_peer_fast_register();
220 #endif
221 #endif
222
223 #ifdef EAP_PEAP
224 if (ret == 0)
225 ret = eap_peer_peap_register();
226 #endif
227
228 #ifdef EAP_TTLS
229 if (ret == 0)
230 ret = eap_peer_ttls_register();
231 #endif
232
233 return ret;
234 }
235
eap_deinit_prev_method(struct eap_sm * sm,const char * txt)236 void eap_deinit_prev_method(struct eap_sm *sm, const char *txt)
237 {
238 if (sm->m == NULL || sm->eap_method_priv == NULL)
239 return;
240 sm->m->deinit(sm, sm->eap_method_priv);
241 sm->eap_method_priv = NULL;
242 sm->m = NULL;
243 }
244
eap_sm_set_scard_pin(struct eap_sm * sm,struct eap_peer_config * conf)245 static int eap_sm_set_scard_pin(struct eap_sm *sm,
246 struct eap_peer_config *conf)
247 {
248 return -1;
249 }
250
eap_sm_get_scard_identity(struct eap_sm * sm,struct eap_peer_config * conf)251 static int eap_sm_get_scard_identity(struct eap_sm *sm,
252 struct eap_peer_config *conf)
253 {
254 return -1;
255 }
256
257
258 /**
259 * eap_sm_buildIdentity - Build EAP-Identity/Response for the current network
260 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
261 * @id: EAP identifier for the packet
262 * @encrypted: Whether the packet is for encrypted tunnel (EAP phase 2)
263 * Returns: Pointer to the allocated EAP-Identity/Response packet or %NULL on
264 * failure
265 *
266 * This function allocates and builds an EAP-Identity/Response packet for the
267 * current network. The caller is responsible for freeing the returned data.
268 */
eap_sm_buildIdentity(struct eap_sm * sm,int id,int encrypted)269 struct wpabuf * eap_sm_buildIdentity(struct eap_sm *sm, int id, int encrypted)
270 {
271 struct eap_peer_config *config = eap_get_config(sm);
272 struct wpabuf *resp;
273 const u8 *identity;
274 size_t identity_len;
275
276 if (config == NULL) {
277 wpa_printf(MSG_ERROR, "EAP: buildIdentity: configuration "
278 "was not available");
279 return NULL;
280 }
281
282 if (sm->m && sm->m->get_identity &&
283 (identity = sm->m->get_identity(sm, sm->eap_method_priv,
284 &identity_len)) != NULL) {
285 wpa_hexdump_ascii(MSG_DEBUG, "EAP: using method re-auth "
286 "identity", identity, identity_len);
287 } else if (!encrypted && config->anonymous_identity) {
288 identity = config->anonymous_identity;
289 identity_len = config->anonymous_identity_len;
290 wpa_hexdump_ascii(MSG_DEBUG, "EAP: using anonymous identity",
291 identity, identity_len);
292 } else {
293 identity = config->identity;
294 identity_len = config->identity_len;
295 wpa_hexdump_ascii(MSG_DEBUG, "EAP: using real identity",
296 identity, identity_len);
297 }
298
299 if (identity == NULL) {
300 wpa_printf(MSG_ERROR, "EAP: buildIdentity: identity "
301 "configuration was not available");
302 if (config->pcsc) {
303 if (eap_sm_get_scard_identity(sm, config) < 0)
304 return NULL;
305 identity = config->identity;
306 identity_len = config->identity_len;
307 wpa_hexdump_ascii(MSG_DEBUG, "permanent identity from "
308 "IMSI", identity, identity_len);
309 } else {
310 eap_sm_request_identity(sm);
311 return NULL;
312 }
313 } else if (config->pcsc) {
314 if (eap_sm_set_scard_pin(sm, config) < 0)
315 return NULL;
316 }
317
318 resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, identity_len,
319 EAP_CODE_RESPONSE, id);
320 if (resp == NULL)
321 return NULL;
322
323 wpabuf_put_data(resp, identity, identity_len);
324
325 return resp;
326 }
327
328
eap_sm_build_identity_resp(struct eap_sm * sm,u8 id,int encrypted)329 struct wpabuf * eap_sm_build_identity_resp(struct eap_sm *sm, u8 id, int encrypted)
330 {
331 const u8 *identity;
332 size_t identity_len;
333 struct wpabuf *eap_buf = NULL;
334 struct eap_peer_config *config = eap_get_config(sm);
335
336 if (config == NULL) {
337 wpa_printf(MSG_ERROR, "EAP: Build Identity Resp-> configuration was not available\n");
338 return NULL;
339 }
340
341 if (sm->m && sm->m->get_identity) {
342 identity = sm->m->get_identity(sm,
343 sm->eap_method_priv,
344 &identity_len);
345 } else if (!encrypted && config->anonymous_identity) {
346 identity = config->anonymous_identity;
347 identity_len = config->anonymous_identity_len;
348 } else {
349 identity = config->identity;
350 identity_len = config->identity_len;
351 }
352
353 if (identity == NULL) {
354 wpa_printf(MSG_ERROR, "EAP: Build Identity Resp-> identity was not available\n");
355 return NULL;
356 }
357
358 eap_buf = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY,
359 identity_len, EAP_CODE_RESPONSE, id);
360 if (!eap_buf) {
361 return NULL;
362 }
363
364 wpabuf_put_data(eap_buf, identity, identity_len);
365 return eap_buf;
366 }
367
eap_sm_build_nak(struct eap_sm * sm,EapType type,u8 id)368 struct wpabuf * eap_sm_build_nak(struct eap_sm *sm, EapType type, u8 id)
369 {
370 size_t count = 0;
371 int found = 0;
372 struct wpabuf *resp;
373 const struct eap_method *methods, *m;
374
375 methods = eap_peer_get_methods(&count);
376 if (methods == NULL)
377 return NULL;
378
379 if (type == EAP_TYPE_EXPANDED) {
380 /*Build Expanded NAK*/
381 resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_EXPANDED,
382 8 + 8 * (count + 1), EAP_CODE_RESPONSE, id);
383 if (resp == NULL)
384 return NULL;
385 wpabuf_put_be24(resp, EAP_VENDOR_IETF);
386 wpabuf_put_be32(resp, EAP_TYPE_NAK);
387 } else {
388 resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_NAK,
389 sizeof(struct eap_hdr) + 1 + count + 1,
390 EAP_CODE_RESPONSE, id);
391 if (resp == NULL)
392 return NULL;
393 wpabuf_put(resp, 0);
394 }
395
396 for (m = methods; m; m = m->next) {
397 //do not propose insecure unencapsulated MSCHAPv2 as Phase 1 Method
398 if(m->vendor == EAP_VENDOR_IETF && m->method == EAP_TYPE_MSCHAPV2)
399 continue;
400
401 //do not propose EAP_TYPE_TLS if no client cert/key are configured
402 if(m->vendor == EAP_VENDOR_IETF && m->method == EAP_TYPE_TLS) {
403 struct eap_peer_config *config = eap_get_config(sm);
404 if (config == NULL || config->private_key == 0 || config->client_cert == 0)
405 continue;
406 }
407
408 if (type == EAP_TYPE_EXPANDED) {
409 wpabuf_put_u8(resp, EAP_TYPE_EXPANDED);
410 wpabuf_put_be24(resp, m->vendor);
411 wpabuf_put_be32(resp, m->method);
412 } else
413 wpabuf_put_u8(resp, m->method);
414 found++;
415 }
416 if (!found) {
417 if (type == EAP_TYPE_EXPANDED) {
418 wpabuf_put_u8(resp, EAP_TYPE_EXPANDED);
419 wpabuf_put_be24(resp, EAP_VENDOR_IETF);
420 wpabuf_put_be32(resp, EAP_TYPE_NONE);
421 } else
422 wpabuf_put_u8(resp, EAP_TYPE_NONE);
423 }
424 eap_update_len(resp);
425 return resp;
426 }
427 #endif
428
eap_peer_config_init(struct eap_sm * sm,const u8 * private_key_passwd,int private_key_passwd_len)429 int eap_peer_config_init(
430 struct eap_sm *sm, const u8 *private_key_passwd,
431 int private_key_passwd_len)
432 {
433 if (!sm)
434 return -1;
435
436 sm->config.anonymous_identity = NULL;
437 sm->config.identity = NULL;
438 sm->config.password = NULL;
439 sm->config.new_password = NULL;
440
441 sm->config.private_key_passwd = private_key_passwd;
442 sm->config.client_cert = (u8 *)sm->blob[0].name;
443 sm->config.private_key = (u8 *)sm->blob[1].name;
444 sm->config.ca_cert = (u8 *)sm->blob[2].name;
445 sm->config.ca_path = NULL;
446
447 sm->config.fragment_size = 1400; /* fragment size */
448
449 sm->config.pac_file = (char *) "blob://";
450
451 /* anonymous identity */
452 if (g_wpa_anonymous_identity && g_wpa_anonymous_identity_len > 0) {
453 sm->config.anonymous_identity_len = g_wpa_anonymous_identity_len;
454 sm->config.anonymous_identity = (u8 *)os_zalloc(sm->config.anonymous_identity_len);
455 if (sm->config.anonymous_identity == NULL)
456 return -2;
457 os_memcpy(sm->config.anonymous_identity, g_wpa_anonymous_identity, g_wpa_anonymous_identity_len);
458 }
459
460 /* Configre identity */
461 if (g_wpa_username && g_wpa_username_len > 0) {
462 sm->config.identity_len = g_wpa_username_len;
463 sm->config.identity = (u8 *)os_zalloc(sm->config.identity_len);
464 if (sm->config.identity == NULL) {
465 return -2;
466 }
467 os_memcpy(sm->config.identity, g_wpa_username, g_wpa_username_len);
468 }
469
470 if (g_wpa_password && g_wpa_password_len) {
471 sm->config.password_len = g_wpa_password_len;
472 sm->config.password = (u8 *)os_zalloc(sm->config.password_len);
473 if (sm->config.password == NULL)
474 return -2;
475 os_memcpy(sm->config.password, g_wpa_password, sm->config.password_len);
476 }
477
478 if (g_wpa_new_password && g_wpa_new_password_len) {
479 sm->config.new_password_len = g_wpa_new_password_len;
480 sm->config.new_password = (u8 *)os_zalloc(sm->config.new_password_len);
481 if (sm->config.new_password == NULL)
482 return -2;
483 os_memcpy(sm->config.new_password, g_wpa_new_password,
484 sm->config.new_password_len);
485 }
486
487 if (g_wpa_ttls_phase2_type) {
488 sm->config.phase2 = g_wpa_ttls_phase2_type;
489 } else {
490 /* set default config phase2 mode as MSCHAPV2 */
491 sm->config.phase2 = "auth=MSCHAPV2";
492 }
493
494 if (g_wpa_suiteb_certification) {
495 sm->config.flags = TLS_CONN_SUITEB;
496 }
497
498 /* To be used only for EAP-FAST */
499 if (g_wpa_phase1_options) {
500 sm->config.phase1 = g_wpa_phase1_options;
501 }
502 return 0;
503
504 }
505
eap_peer_config_deinit(struct eap_sm * sm)506 void eap_peer_config_deinit(struct eap_sm *sm)
507 {
508 if (!sm)
509 return;
510
511 os_free(sm->config.anonymous_identity);
512 os_free(sm->config.identity);
513 os_free(sm->config.password);
514 os_free(sm->config.new_password);
515 os_bzero(&sm->config, sizeof(struct eap_peer_config));
516 }
517
eap_peer_blob_init(struct eap_sm * sm)518 int eap_peer_blob_init(struct eap_sm *sm)
519 {
520 int i, ret;
521
522 if (!sm)
523 return -1;
524
525 if (g_wpa_client_cert && g_wpa_client_cert_len) {
526 sm->blob[0].name = (char *)os_zalloc(BLOB_NAME_LEN+1);
527 if (sm->blob[0].name == NULL) {
528 ret = -2;
529 goto _out;
530 }
531 os_strncpy(sm->blob[0].name, CLIENT_CERT_NAME, BLOB_NAME_LEN+1);
532 sm->blob[0].len = g_wpa_client_cert_len;
533 sm->blob[0].data = g_wpa_client_cert;
534 }
535
536 if (g_wpa_private_key && g_wpa_private_key_len) {
537 sm->blob[1].name = (char *)os_zalloc(BLOB_NAME_LEN+1);
538 if (sm->blob[1].name == NULL) {
539 ret = -2;
540 goto _out;
541 }
542 os_strncpy(sm->blob[1].name, PRIVATE_KEY_NAME, BLOB_NAME_LEN+1);
543 sm->blob[1].len = g_wpa_private_key_len;
544 sm->blob[1].data = g_wpa_private_key;
545 }
546
547 if (g_wpa_ca_cert && g_wpa_ca_cert_len) {
548 sm->blob[2].name = (char *)os_zalloc(BLOB_NAME_LEN+1);
549 if (sm->blob[2].name == NULL) {
550 ret = -2;
551 goto _out;
552 }
553 os_strncpy(sm->blob[2].name, CA_CERT_NAME, BLOB_NAME_LEN+1);
554 sm->blob[2].len = g_wpa_ca_cert_len;
555 sm->blob[2].data = g_wpa_ca_cert;
556 }
557
558 if (g_wpa_pac_file && g_wpa_pac_file_len) {
559 sm->blob[3].name = (char *)os_zalloc(sizeof(char) * 8);
560 if (sm->blob[3].name == NULL) {
561 ret = -2;
562 goto _out;
563 }
564 os_strncpy(sm->blob[3].name, "blob://", 8);
565 sm->blob[3].len = g_wpa_pac_file_len;
566 sm->blob[3].data = g_wpa_pac_file;
567 }
568
569 return 0;
570 _out:
571 for (i = 0; i < BLOB_NUM; i++) {
572 if (sm->blob[i].name) {
573 os_free(sm->blob[i].name);
574 sm->blob[i].name = NULL;
575 }
576 }
577 os_bzero(&sm->blob[0], sizeof(struct wpa_config_blob)*BLOB_NUM);
578
579 return ret;
580 }
581
582 #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
eap_sm_request(struct eap_sm * sm,enum wpa_ctrl_req_type field,const char * msg,size_t msglen)583 static void eap_sm_request(struct eap_sm *sm, enum wpa_ctrl_req_type field,
584 const char *msg, size_t msglen)
585 {
586 struct eap_peer_config *config;
587
588 if (sm == NULL)
589 return;
590 config = eap_get_config(sm);
591 if (config == NULL)
592 return;
593
594 switch (field) {
595 case WPA_CTRL_REQ_EAP_IDENTITY:
596 config->pending_req_identity++;
597 break;
598 case WPA_CTRL_REQ_EAP_PASSWORD:
599 config->pending_req_password++;
600 break;
601 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
602 config->pending_req_new_password++;
603 break;
604 case WPA_CTRL_REQ_EAP_PIN:
605 config->pending_req_pin++;
606 break;
607 case WPA_CTRL_REQ_EAP_PASSPHRASE:
608 config->pending_req_passphrase++;
609 break;
610 default:
611 return;
612 }
613
614 }
615 #else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
616 #define eap_sm_request(sm, type, msg, msglen) do { } while (0)
617 #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
618
eap_sm_get_method_name(struct eap_sm * sm)619 const char * eap_sm_get_method_name(struct eap_sm *sm)
620 {
621 if (sm->m == NULL)
622 return "UNKNOWN";
623 return sm->m->name;
624 }
625
626
627 /**
628 * eap_sm_request_identity - Request identity from user (ctrl_iface)
629 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
630 *
631 * EAP methods can call this function to request identity information for the
632 * current network. This is normally called when the identity is not included
633 * in the network configuration. The request will be sent to monitor programs
634 * through the control interface.
635 */
eap_sm_request_identity(struct eap_sm * sm)636 void eap_sm_request_identity(struct eap_sm *sm)
637 {
638 eap_sm_request(sm, WPA_CTRL_REQ_EAP_IDENTITY, NULL, 0);
639 }
640
641
642 /**
643 * eap_sm_request_password - Request password from user (ctrl_iface)
644 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
645 *
646 * EAP methods can call this function to request password information for the
647 * current network. This is normally called when the password is not included
648 * in the network configuration. The request will be sent to monitor programs
649 * through the control interface.
650 */
eap_sm_request_password(struct eap_sm * sm)651 void eap_sm_request_password(struct eap_sm *sm)
652 {
653 eap_sm_request(sm, WPA_CTRL_REQ_EAP_PASSWORD, NULL, 0);
654 }
655
656
657 /**
658 * eap_sm_request_new_password - Request new password from user (ctrl_iface)
659 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
660 *
661 * EAP methods can call this function to request new password information for
662 * the current network. This is normally called when the EAP method indicates
663 * that the current password has expired and password change is required. The
664 * request will be sent to monitor programs through the control interface.
665 */
eap_sm_request_new_password(struct eap_sm * sm)666 void eap_sm_request_new_password(struct eap_sm *sm)
667 {
668 eap_sm_request(sm, WPA_CTRL_REQ_EAP_NEW_PASSWORD, NULL, 0);
669 }
670
671
eap_peer_blob_deinit(struct eap_sm * sm)672 void eap_peer_blob_deinit(struct eap_sm *sm)
673 {
674 int i;
675 for (i = 0; i < BLOB_NUM; i++) {
676 if (sm->blob[i].name) {
677 os_free(sm->blob[i].name);
678 sm->blob[i].name = NULL;
679 }
680 }
681 os_bzero(&sm->blob[0], sizeof(struct wpa_config_blob)*BLOB_NUM);
682
683 sm->config.client_cert = NULL;
684 sm->config.private_key = NULL;
685 sm->config.ca_cert = NULL;
686 sm->config.pac_file = NULL;
687 }
688
eap_sm_abort(struct eap_sm * sm)689 void eap_sm_abort(struct eap_sm *sm)
690 {
691 wpabuf_free(sm->lastRespData);
692 sm->lastRespData = NULL;
693 }
694
695 /**
696 * eap_get_config - Get current network configuration
697 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
698 * Returns: Pointer to the current network configuration or %NULL if not found
699 *
700 * EAP peer methods should avoid using this function if they can use other
701 * access functions, like eap_get_config_identity() and
702 * eap_get_config_password(), that do not require direct access to
703 * struct eap_peer_config.
704 */
eap_get_config(struct eap_sm * sm)705 struct eap_peer_config * eap_get_config(struct eap_sm *sm)
706 {
707 return &sm->config;
708 }
709
710
711 /**
712 * eap_get_config_identity - Get identity from the network configuration
713 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
714 * @len: Buffer for the length of the identity
715 * Returns: Pointer to the identity or %NULL if not found
716 */
eap_get_config_identity(struct eap_sm * sm,size_t * len)717 const u8 * eap_get_config_identity(struct eap_sm *sm, size_t *len)
718 {
719 struct eap_peer_config *config = eap_get_config(sm);
720 if (config == NULL)
721 return NULL;
722 *len = config->identity_len;
723 return config->identity;
724 }
725
726
727 /**
728 * eap_get_config_password - Get password from the network configuration
729 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
730 * @len: Buffer for the length of the password
731 * Returns: Pointer to the password or %NULL if not found
732 */
eap_get_config_password(struct eap_sm * sm,size_t * len)733 const u8 * eap_get_config_password(struct eap_sm *sm, size_t *len)
734 {
735 struct eap_peer_config *config = eap_get_config(sm);
736 if (config == NULL)
737 return NULL;
738 *len = config->password_len;
739 return config->password;
740 }
741
742
743 /**
744 * eap_get_config_password2 - Get password from the network configuration
745 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
746 * @len: Buffer for the length of the password
747 * @hash: Buffer for returning whether the password is stored as a
748 * NtPasswordHash instead of plaintext password; can be %NULL if this
749 * information is not needed
750 * Returns: Pointer to the password or %NULL if not found
751 */
eap_get_config_password2(struct eap_sm * sm,size_t * len,int * hash)752 const u8 * eap_get_config_password2(struct eap_sm *sm, size_t *len, int *hash)
753 {
754 struct eap_peer_config *config = eap_get_config(sm);
755 if (config == NULL)
756 return NULL;
757
758 *len = config->password_len;
759 if (hash)
760 *hash = !!(config->flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH);
761 return config->password;
762 }
763
764
765 /**
766 * eap_get_config_new_password - Get new password from network configuration
767 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
768 * @len: Buffer for the length of the new password
769 * Returns: Pointer to the new password or %NULL if not found
770 */
eap_get_config_new_password(struct eap_sm * sm,size_t * len)771 const u8 * eap_get_config_new_password(struct eap_sm *sm, size_t *len)
772 {
773 struct eap_peer_config *config = eap_get_config(sm);
774 if (config == NULL)
775 return NULL;
776 *len = config->new_password_len;
777 return config->new_password;
778 }
779
780
eap_copy_buf(u8 ** dst,size_t * dst_len,const u8 * src,size_t src_len)781 static int eap_copy_buf(u8 **dst, size_t *dst_len,
782 const u8 *src, size_t src_len)
783 {
784 if (src) {
785 *dst = os_memdup(src, src_len);
786 if (*dst == NULL)
787 return -1;
788 *dst_len = src_len;
789 }
790 return 0;
791 }
792
793
794 /**
795 * eap_set_config_blob - Set or add a named configuration blob
796 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
797 * @blob: New value for the blob
798 *
799 * Adds a new configuration blob or replaces the current value of an existing
800 * blob.
801 */
eap_set_config_blob(struct eap_sm * sm,struct wpa_config_blob * blob)802 void eap_set_config_blob(struct eap_sm *sm, struct wpa_config_blob *blob)
803 {
804 if (!sm)
805 return;
806
807 if (eap_copy_buf((u8 **)&sm->blob[3].data, (size_t *)&sm->blob[3].len, blob->data, blob->len) < 0) {
808 wpa_printf(MSG_ERROR, "EAP: Set config blob: Unable to modify the configuration blob");
809 }
810 }
811
812
813 /**
814 * eap_get_config_blob - Get a named configuration blob
815 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
816 * @name: Name of the blob
817 * Returns: Pointer to blob data or %NULL if not found
818 */
eap_get_config_blob(struct eap_sm * sm,const char * name)819 const struct wpa_config_blob * eap_get_config_blob(struct eap_sm *sm,
820 const char *name)
821 {
822 int i;
823
824 if (!sm)
825 return NULL;
826
827 for (i = 0; i < BLOB_NUM; i++) {
828 if (sm->blob[i].name == NULL)
829 continue;
830 if (os_strncmp(name, sm->blob[i].name, BLOB_NAME_LEN) == 0) {
831 return &sm->blob[i];
832 }
833 }
834 return NULL;
835 }
836