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