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 "crypto/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 u8 *g_wpa_anonymous_identity;
46 int g_wpa_anonymous_identity_len;
47 u8 *g_wpa_username;
48 int g_wpa_username_len;
49 const u8 *g_wpa_client_cert;
50 int g_wpa_client_cert_len;
51 const u8 *g_wpa_private_key;
52 int g_wpa_private_key_len;
53 const u8 *g_wpa_private_key_passwd;
54 int g_wpa_private_key_passwd_len;
55 const u8 *g_wpa_ca_cert;
56 int g_wpa_ca_cert_len;
57 u8 *g_wpa_password;
58 int g_wpa_password_len;
59 u8 *g_wpa_new_password;
60 int g_wpa_new_password_len;
61 char *g_wpa_ttls_phase2_type;
62 char *g_wpa_phase1_options;
63 u8 *g_wpa_pac_file;
64 int g_wpa_pac_file_len;
65 bool g_wpa_suiteb_certification;
66 #ifdef CONFIG_MBEDTLS_CERTIFICATE_BUNDLE
67 bool g_wpa_default_cert_bundle;
68 int (*esp_crt_bundle_attach_fn)(void *conf);
69 #endif
70 
71 void eap_peer_config_deinit(struct eap_sm *sm);
72 void eap_peer_blob_deinit(struct eap_sm *sm);
73 void eap_deinit_prev_method(struct eap_sm *sm, const char *txt);
74 
75 #ifdef EAP_PEER_METHOD
76 static struct eap_method *eap_methods = NULL;
77 static struct eap_method_type *config_methods;
78 
eap_peer_get_eap_method(int vendor,EapType method)79 const struct eap_method * eap_peer_get_eap_method(int vendor, EapType method)
80 {
81 	struct eap_method *m;
82 	for (m = eap_methods; m; m = m->next) {
83 		if (m->vendor == vendor && m->method == method)
84 			return m;
85 	}
86 	return NULL;
87 }
88 
eap_peer_get_methods(size_t * count)89 const struct eap_method * eap_peer_get_methods(size_t *count)
90 {
91 	int c = 0;
92 	struct eap_method *m;
93 
94 	for (m = eap_methods; m; m = m->next)
95 		c++;
96 
97 	*count = c;
98 	return eap_methods;
99 }
100 
101 /**
102  * eap_config_allowed_method - Check whether EAP method is allowed
103  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
104  * @config: EAP configuration
105  * @vendor: Vendor-Id for expanded types or 0 = IETF for legacy types
106  * @method: EAP type
107  * Returns: 1 = allowed EAP method, 0 = not allowed
108  */
eap_config_allowed_method(struct eap_sm * sm,struct eap_peer_config * config,int vendor,u32 method)109 static int eap_config_allowed_method(struct eap_sm *sm,
110 				     struct eap_peer_config *config,
111 				     int vendor, u32 method)
112 {
113 	int i;
114 	struct eap_method_type *m;
115 
116 	if (config == NULL || config->eap_methods == NULL)
117 		return 1;
118 
119 	m = config->eap_methods;
120 	for (i = 0; m[i].vendor != EAP_VENDOR_IETF ||
121 		     m[i].method != EAP_TYPE_NONE; i++) {
122 		if (m[i].vendor == vendor && m[i].method == method)
123 			return 1;
124 	}
125 	return 0;
126 }
127 
eap_peer_get_type(const char * name,int * vendor)128 EapType eap_peer_get_type(const char *name, int *vendor)
129 {
130 	struct eap_method *m;
131 	for (m = eap_methods; m; m = m->next) {
132 		if (os_strcmp(m->name, name) == 0) {
133 			*vendor = m->vendor;
134 			return m->method;
135 		}
136 	}
137 	*vendor = EAP_VENDOR_IETF;
138 	return EAP_TYPE_NONE;
139 }
140 
141 
142 /**
143  * eap_allowed_method - Check whether EAP method is allowed
144  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
145  * @vendor: Vendor-Id for expanded types or 0 = IETF for legacy types
146  * @method: EAP type
147  * Returns: 1 = allowed EAP method, 0 = not allowed
148  */
eap_allowed_method(struct eap_sm * sm,int vendor,u32 method)149 int eap_allowed_method(struct eap_sm *sm, int vendor, u32 method)
150 {
151 	return eap_config_allowed_method(sm, eap_get_config(sm), vendor,
152 					 method);
153 }
154 
155 
156 static int
eap_allowed_phase2_type(int vendor,int type)157 eap_allowed_phase2_type(int vendor, int type)
158 {
159 	if (vendor != EAP_VENDOR_IETF)
160 		return 0;
161 	return type != EAP_TYPE_PEAP && type != EAP_TYPE_TTLS &&
162 		type != EAP_TYPE_FAST;
163 }
164 
eap_get_phase2_type(const char * name,int * vendor)165 u32 eap_get_phase2_type(const char *name, int *vendor)
166 {
167 	int v;
168 	u8 type = eap_peer_get_type(name, &v);
169 	if (eap_allowed_phase2_type(v, type)) {
170 		*vendor = v;
171 		return type;
172 	}
173 	*vendor = EAP_VENDOR_IETF;
174 	return EAP_TYPE_NONE;
175 }
176 
eap_get_phase2_types(struct eap_peer_config * config,size_t * count)177 struct eap_method_type * eap_get_phase2_types(struct eap_peer_config *config,
178 		     size_t *count)
179 {
180 	struct eap_method_type *buf;
181 	u32 method;
182 	int vendor;
183 	size_t mcount;
184 	const struct eap_method *methods, *m;
185 
186 	methods = eap_peer_get_methods(&mcount);
187 	if (methods == NULL)
188 		return NULL;
189 	*count = 0;
190 	buf = os_malloc(mcount * sizeof(struct eap_method_type));
191 	if (buf == NULL)
192 		return NULL;
193 
194 	for (m = methods; m; m = m->next) {
195 		vendor = m->vendor;
196 		method = m->method;
197 		if (eap_allowed_phase2_type(vendor, method)) {
198 			if (vendor == EAP_VENDOR_IETF &&
199 			    method == EAP_TYPE_TLS && config &&
200 			    config->private_key2 == NULL)
201 				continue;
202 			buf[*count].vendor = vendor;
203 			buf[*count].method = method;
204 			(*count)++;
205 		}
206 	}
207 
208 	return buf;
209 }
210 
eap_peer_method_alloc(int vendor,EapType method,const char * name)211 struct eap_method * eap_peer_method_alloc(int vendor, EapType method,
212 		      const char *name)
213 {
214 	struct eap_method *eap;
215 	eap = (struct eap_method *)os_zalloc(sizeof(*eap));
216 	if (eap == NULL)
217 		return NULL;
218 	eap->vendor = vendor;
219 	eap->method = method;
220 	eap->name = name;
221 	return eap;
222 }
223 
eap_peer_method_free(struct eap_method * method)224 void eap_peer_method_free(struct eap_method *method)
225 {
226 	os_free(method);
227 }
228 
eap_peer_method_register(struct eap_method * method)229 int eap_peer_method_register(struct eap_method *method)
230 {
231 	struct eap_method *m, *last = NULL;
232 
233 	if (method == NULL || method->name == NULL)
234 		return -1;
235 	for (m = eap_methods; m; m = m->next) {
236 		if (m->vendor == method->vendor &&
237 		    m->method == method->method &&
238 		    os_strcmp(m->name, method->name))
239 			return -2;
240 		last = m;
241 	}
242 	if (last)
243 		last->next = method;
244 	else
245 		eap_methods = method;
246 	return 0;
247 }
248 
eap_peer_unregister_methods(void)249 void eap_peer_unregister_methods(void)
250 {
251 	struct eap_method *m;
252 	while (eap_methods) {
253 		m = eap_methods;
254 		eap_methods = eap_methods->next;
255 
256 		if (m->free)
257 			m->free(m);
258 		else
259 			eap_peer_method_free(m);
260 	}
261 }
262 
263 
264 
eap_sm_allowMethod(struct eap_sm * sm,int vendor,EapType method)265 bool eap_sm_allowMethod(struct eap_sm *sm, int vendor,
266 				  EapType method)
267 {
268 	if (!eap_allowed_method(sm, vendor, method)) {
269 		wpa_printf(MSG_DEBUG, "EAP: configuration does not allow: "
270 			   "vendor %u method %u", vendor, method);
271 		return FALSE;
272 	}
273 	if (eap_peer_get_eap_method(vendor, method))
274 		return TRUE;
275 	wpa_printf(MSG_DEBUG, "EAP: not included in build: "
276 		   "vendor %u method %u", vendor, method);
277 	return FALSE;
278 }
279 
eap_peer_register_methods(void)280 int eap_peer_register_methods(void)
281 {
282 	int ret = 0;
283 
284 #ifdef EAP_MD5
285 	if (ret == 0)
286 		ret = eap_peer_md5_register();
287 #endif
288 
289 #ifdef EAP_TLS
290 	if (ret == 0)
291 		ret = eap_peer_tls_register();
292 #endif
293 
294 #ifdef EAP_MSCHAPv2
295 	if (ret == 0)
296 		ret = eap_peer_mschapv2_register();
297 #endif
298 
299 #ifdef EAP_FAST
300 	if (ret == 0)
301 		ret = eap_peer_fast_register();
302 #endif
303 
304 #ifdef EAP_PEAP
305 	if (ret == 0)
306 		ret = eap_peer_peap_register();
307 #endif
308 
309 #ifdef EAP_TTLS
310 	if (ret == 0)
311 		ret = eap_peer_ttls_register();
312 #endif
313 
314 	return ret;
315 }
316 
eap_deinit_prev_method(struct eap_sm * sm,const char * txt)317 void eap_deinit_prev_method(struct eap_sm *sm, const char *txt)
318 {
319 	if (sm->m == NULL || sm->eap_method_priv == NULL)
320 		return;
321 	sm->m->deinit(sm, sm->eap_method_priv);
322 	sm->eap_method_priv = NULL;
323 	sm->m = NULL;
324 }
325 
eap_sm_set_scard_pin(struct eap_sm * sm,struct eap_peer_config * conf)326 static int eap_sm_set_scard_pin(struct eap_sm *sm,
327 				struct eap_peer_config *conf)
328 {
329 	return -1;
330 }
331 
eap_sm_get_scard_identity(struct eap_sm * sm,struct eap_peer_config * conf)332 static int eap_sm_get_scard_identity(struct eap_sm *sm,
333 				     struct eap_peer_config *conf)
334 {
335 	return -1;
336 }
337 
338 
339 /**
340  * eap_sm_buildIdentity - Build EAP-Identity/Response for the current network
341  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
342  * @id: EAP identifier for the packet
343  * @encrypted: Whether the packet is for encrypted tunnel (EAP phase 2)
344  * Returns: Pointer to the allocated EAP-Identity/Response packet or %NULL on
345  * failure
346  *
347  * This function allocates and builds an EAP-Identity/Response packet for the
348  * current network. The caller is responsible for freeing the returned data.
349  */
eap_sm_buildIdentity(struct eap_sm * sm,int id,int encrypted)350 struct wpabuf * eap_sm_buildIdentity(struct eap_sm *sm, int id, int encrypted)
351 {
352 	struct eap_peer_config *config = eap_get_config(sm);
353 	struct wpabuf *resp;
354 	const u8 *identity;
355 	size_t identity_len;
356 
357 	if (config == NULL) {
358 		wpa_printf(MSG_ERROR, "EAP: buildIdentity: configuration "
359 			   "was not available");
360 		return NULL;
361 	}
362 
363 	if (sm->m && sm->m->get_identity &&
364 	    (identity = sm->m->get_identity(sm, sm->eap_method_priv,
365 					    &identity_len)) != NULL) {
366 		wpa_hexdump_ascii(MSG_DEBUG, "EAP: using method re-auth "
367 				  "identity", identity, identity_len);
368 	} else if (!encrypted && config->anonymous_identity) {
369 		identity = config->anonymous_identity;
370 		identity_len = config->anonymous_identity_len;
371 		wpa_hexdump_ascii(MSG_DEBUG, "EAP: using anonymous identity",
372 				  identity, identity_len);
373 	} else {
374 		identity = config->identity;
375 		identity_len = config->identity_len;
376 		wpa_hexdump_ascii(MSG_DEBUG, "EAP: using real identity",
377 				  identity, identity_len);
378 	}
379 
380 	if (identity == NULL) {
381 		wpa_printf(MSG_ERROR, "EAP: buildIdentity: identity "
382 			   "configuration was not available");
383 		if (config->pcsc) {
384 			if (eap_sm_get_scard_identity(sm, config) < 0)
385 				return NULL;
386 			identity = config->identity;
387 			identity_len = config->identity_len;
388 			wpa_hexdump_ascii(MSG_DEBUG, "permanent identity from "
389 					  "IMSI", identity, identity_len);
390 		} else {
391 			eap_sm_request_identity(sm);
392 			return NULL;
393 		}
394 	} else if (config->pcsc) {
395 		if (eap_sm_set_scard_pin(sm, config) < 0)
396 			return NULL;
397 	}
398 
399 	resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, identity_len,
400 			     EAP_CODE_RESPONSE, id);
401 	if (resp == NULL)
402 		return NULL;
403 
404 	wpabuf_put_data(resp, identity, identity_len);
405 
406 	return resp;
407 }
408 
409 
eap_sm_build_identity_resp(struct eap_sm * sm,u8 id,int encrypted)410 struct wpabuf * eap_sm_build_identity_resp(struct eap_sm *sm, u8 id, int encrypted)
411 {
412 	const u8 *identity;
413 	size_t identity_len;
414 	struct wpabuf *eap_buf = NULL;
415 	struct eap_peer_config *config = eap_get_config(sm);
416 
417 	if (config == NULL) {
418         wpa_printf(MSG_ERROR, "EAP: Build Identity Resp-> configuration was not available");
419 		return NULL;
420 	}
421 
422 	if (sm->m && sm->m->get_identity) {
423 		identity = sm->m->get_identity(sm,
424 					sm->eap_method_priv,
425 					&identity_len);
426 	} else if (!encrypted && config->anonymous_identity) {
427 		identity = config->anonymous_identity;
428 		identity_len = config->anonymous_identity_len;
429 	} else {
430 		identity = config->identity;
431 		identity_len = config->identity_len;
432 	}
433 
434 	if (identity == NULL) {
435         wpa_printf(MSG_ERROR, "EAP: Build Identity Resp-> identity was not available");
436 		return NULL;
437 	}
438 
439 	eap_buf = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY,
440 				identity_len, EAP_CODE_RESPONSE, id);
441 	if (!eap_buf) {
442         return NULL;
443     }
444 
445 	wpabuf_put_data(eap_buf, identity, identity_len);
446 	return eap_buf;
447 }
448 
eap_sm_build_nak(struct eap_sm * sm,EapType type,u8 id)449 struct wpabuf * eap_sm_build_nak(struct eap_sm *sm, EapType type, u8 id)
450 {
451 	size_t count = 0;
452 	int found = 0;
453 	struct wpabuf *resp;
454 	const struct eap_method *methods, *m;
455 
456 	methods = eap_peer_get_methods(&count);
457 	if (methods == NULL)
458 		return NULL;
459 
460 	if (type == EAP_TYPE_EXPANDED) {
461 		/*Build Expanded NAK*/
462 		resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_EXPANDED,
463 				     8 + 8 * (count + 1), EAP_CODE_RESPONSE, id);
464 		if (resp == NULL)
465 			return NULL;
466 		wpabuf_put_be24(resp, EAP_VENDOR_IETF);
467 		wpabuf_put_be32(resp, EAP_TYPE_NAK);
468 	} else {
469 		resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_NAK,
470 				     sizeof(struct eap_hdr) + 1 + count + 1,
471 				     EAP_CODE_RESPONSE, id);
472 		if (resp == NULL)
473 			return NULL;
474 		wpabuf_put(resp, 0);
475 	}
476 
477 	for (m = methods; m; m = m->next) {
478 		//do not propose insecure unencapsulated MSCHAPv2 as Phase 1 Method
479 		if(m->vendor == EAP_VENDOR_IETF && m->method == EAP_TYPE_MSCHAPV2)
480 			continue;
481 
482 		//do not propose EAP_TYPE_TLS if no client cert/key are configured
483 		if(m->vendor == EAP_VENDOR_IETF && m->method == EAP_TYPE_TLS) {
484 			struct eap_peer_config *config = eap_get_config(sm);
485 			if (config == NULL || config->private_key == 0 || config->client_cert == 0)
486 				continue;
487 		}
488 
489 		if (type == EAP_TYPE_EXPANDED) {
490 			wpabuf_put_u8(resp, EAP_TYPE_EXPANDED);
491 			wpabuf_put_be24(resp, m->vendor);
492 			wpabuf_put_be32(resp, m->method);
493 		} else
494 			wpabuf_put_u8(resp, m->method);
495 		found++;
496 	}
497 	if (!found) {
498 		if (type == EAP_TYPE_EXPANDED) {
499 			wpabuf_put_u8(resp, EAP_TYPE_EXPANDED);
500 			wpabuf_put_be24(resp, EAP_VENDOR_IETF);
501 			wpabuf_put_be32(resp, EAP_TYPE_NONE);
502 		} else
503 			wpabuf_put_u8(resp, EAP_TYPE_NONE);
504 	}
505 	eap_update_len(resp);
506 	return resp;
507 }
508 #endif
509 
eap_peer_config_init(struct eap_sm * sm,const u8 * private_key_passwd,int private_key_passwd_len)510 int eap_peer_config_init(
511 	struct eap_sm *sm, const u8 *private_key_passwd,
512 	int private_key_passwd_len)
513 {
514 	if (!sm)
515 		return -1;
516 
517 	sm->config.anonymous_identity = NULL;
518 	sm->config.identity = NULL;
519 	sm->config.password = NULL;
520 	sm->config.new_password = NULL;
521 
522 	sm->config.private_key_passwd = private_key_passwd;
523 	sm->config.client_cert = (u8 *)sm->blob[0].name;
524 	sm->config.private_key = (u8 *)sm->blob[1].name;
525 	sm->config.ca_cert = (u8 *)sm->blob[2].name;
526 	sm->config.ca_path = NULL;
527 
528 	sm->config.fragment_size = 1400; /* fragment size */
529 
530 	sm->config.pac_file = (char *) "blob://";
531 
532 	/* anonymous identity */
533 	if (g_wpa_anonymous_identity && g_wpa_anonymous_identity_len > 0) {
534 	    sm->config.anonymous_identity_len = g_wpa_anonymous_identity_len;
535 	    sm->config.anonymous_identity = (u8 *)os_zalloc(sm->config.anonymous_identity_len);
536 	    if (sm->config.anonymous_identity == NULL)
537 		    return -2;
538 	    os_memcpy(sm->config.anonymous_identity, g_wpa_anonymous_identity, g_wpa_anonymous_identity_len);
539 	}
540 
541 	/* Configre identity */
542 	if (g_wpa_username && g_wpa_username_len > 0) {
543 		sm->config.identity_len = g_wpa_username_len;
544 		sm->config.identity = (u8 *)os_zalloc(sm->config.identity_len);
545 		if (sm->config.identity == NULL) {
546 			return -2;
547 		}
548 		os_memcpy(sm->config.identity, g_wpa_username, g_wpa_username_len);
549 	}
550 
551 	if (g_wpa_password && g_wpa_password_len) {
552 		sm->config.password_len = g_wpa_password_len;
553 		sm->config.password = (u8 *)os_zalloc(sm->config.password_len);
554 		if (sm->config.password == NULL)
555 			return -2;
556 		os_memcpy(sm->config.password, g_wpa_password, sm->config.password_len);
557 	}
558 
559 	if (g_wpa_new_password && g_wpa_new_password_len) {
560 		sm->config.new_password_len = g_wpa_new_password_len;
561 		sm->config.new_password = (u8 *)os_zalloc(sm->config.new_password_len);
562 		if (sm->config.new_password == NULL)
563 			return -2;
564 		os_memcpy(sm->config.new_password, g_wpa_new_password,
565 			  sm->config.new_password_len);
566 	}
567 
568 	if (g_wpa_ttls_phase2_type) {
569 		sm->config.phase2 = g_wpa_ttls_phase2_type;
570 	} else {
571 		/* set default config phase2 mode as MSCHAPV2 */
572 		sm->config.phase2 = "auth=MSCHAPV2";
573 	}
574 
575 	if (g_wpa_suiteb_certification) {
576 		sm->config.flags |= TLS_CONN_SUITEB;
577 	}
578 
579 #ifdef CONFIG_MBEDTLS_CERTIFICATE_BUNDLE
580 	if (g_wpa_default_cert_bundle) {
581 		sm->config.flags |= TLS_CONN_USE_DEFAULT_CERT_BUNDLE;
582 	}
583 #endif
584 	/* To be used only for EAP-FAST */
585 	if (g_wpa_phase1_options) {
586 		sm->config.phase1 = g_wpa_phase1_options;
587 	}
588 
589 	/* Allow methods with correct configuration only */
590 	size_t mcount;
591 	int allowed_method_count = 0;
592 	const struct eap_method *methods;
593 
594 	if (!config_methods) {
595 		methods = eap_peer_get_methods(&mcount);
596 		if (methods == NULL) {
597 			wpa_printf(MSG_ERROR, "EAP: Set config init: EAP methods not registered.");
598 			return -1;
599 		}
600 
601 		// Allocate a buffer large enough to accomodate all the registered methods.
602 		config_methods = os_malloc(mcount * sizeof(struct eap_method_type));
603 		if (config_methods == NULL) {
604 			wpa_printf(MSG_ERROR, "EAP: Set config init: Out of memory, set configured methods failed");
605 			return -1;
606 		}
607 
608 		if (g_wpa_username) {
609 			//set EAP-PEAP
610 			config_methods[allowed_method_count].vendor = EAP_VENDOR_IETF;
611 			config_methods[allowed_method_count++].method = EAP_TYPE_PEAP;
612 			//set EAP-TTLS
613 			config_methods[allowed_method_count].vendor = EAP_VENDOR_IETF;
614 			config_methods[allowed_method_count++].method = EAP_TYPE_TTLS;
615 		}
616 		if (g_wpa_private_key) {
617 			//set EAP-TLS
618 			config_methods[allowed_method_count].vendor = EAP_VENDOR_IETF;
619 			config_methods[allowed_method_count++].method = EAP_TYPE_TLS;
620 		}
621 #ifdef EAP_FAST
622 		if (g_wpa_pac_file) {
623 			//set EAP-FAST
624 			config_methods[allowed_method_count].vendor = EAP_VENDOR_IETF;
625 			config_methods[allowed_method_count++].method = EAP_TYPE_FAST;
626 		}
627 #endif
628 		// Terminate the allowed method list
629 		config_methods[allowed_method_count].vendor = EAP_VENDOR_IETF;
630 		config_methods[allowed_method_count++].method = EAP_TYPE_NONE;
631 		// Set the allowed methods to config
632 		sm->config.eap_methods = config_methods;
633 	}
634 	return 0;
635 
636 }
637 
eap_peer_config_deinit(struct eap_sm * sm)638 void eap_peer_config_deinit(struct eap_sm *sm)
639 {
640 	if (!sm)
641 		return;
642 
643 	os_free(sm->config.anonymous_identity);
644 	os_free(sm->config.identity);
645 	os_free(sm->config.password);
646 	os_free(sm->config.new_password);
647 	os_free(sm->config.eap_methods);
648 	os_bzero(&sm->config, sizeof(struct eap_peer_config));
649 	config_methods = NULL;
650 }
651 
eap_peer_blob_init(struct eap_sm * sm)652 int eap_peer_blob_init(struct eap_sm *sm)
653 {
654 	int i, ret;
655 
656 	if (!sm)
657 		return -1;
658 
659 	if (g_wpa_client_cert && g_wpa_client_cert_len) {
660 		sm->blob[0].name = (char *)os_zalloc(BLOB_NAME_LEN+1);
661 		if (sm->blob[0].name == NULL) {
662 			ret = -2;
663 			goto _out;
664 		}
665 		os_strlcpy(sm->blob[0].name, CLIENT_CERT_NAME, BLOB_NAME_LEN+1);
666 		sm->blob[0].len = g_wpa_client_cert_len;
667 		sm->blob[0].data = g_wpa_client_cert;
668 	}
669 
670 	if (g_wpa_private_key && g_wpa_private_key_len) {
671 		sm->blob[1].name = (char *)os_zalloc(BLOB_NAME_LEN+1);
672 		if (sm->blob[1].name == NULL) {
673 			ret = -2;
674 			goto _out;
675 		}
676 		os_strlcpy(sm->blob[1].name, PRIVATE_KEY_NAME, BLOB_NAME_LEN+1);
677 		sm->blob[1].len = g_wpa_private_key_len;
678 		sm->blob[1].data = g_wpa_private_key;
679 	}
680 
681 	if (g_wpa_ca_cert && g_wpa_ca_cert_len) {
682 		sm->blob[2].name = (char *)os_zalloc(BLOB_NAME_LEN+1);
683 		if (sm->blob[2].name == NULL) {
684 			ret = -2;
685 			goto _out;
686 		}
687 		os_strlcpy(sm->blob[2].name, CA_CERT_NAME, BLOB_NAME_LEN+1);
688 		sm->blob[2].len = g_wpa_ca_cert_len;
689 		sm->blob[2].data = g_wpa_ca_cert;
690 	}
691 
692 	if (g_wpa_pac_file && g_wpa_pac_file_len) {
693 		sm->blob[3].name = (char *)os_zalloc(sizeof(char) * 8);
694 		if (sm->blob[3].name == NULL) {
695 			ret = -2;
696 			goto _out;
697 		}
698 		os_strlcpy(sm->blob[3].name, "blob://", 8);
699 		sm->blob[3].len = g_wpa_pac_file_len;
700 		sm->blob[3].data = g_wpa_pac_file;
701 	}
702 
703 	return 0;
704 _out:
705 	for (i = 0; i < BLOB_NUM; i++) {
706 		if (sm->blob[i].name) {
707 			os_free(sm->blob[i].name);
708 			sm->blob[i].name = NULL;
709 		}
710 	}
711 	os_bzero(&sm->blob[0], sizeof(struct wpa_config_blob)*BLOB_NUM);
712 
713 	return ret;
714 }
715 
716 #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)717 static void eap_sm_request(struct eap_sm *sm, enum wpa_ctrl_req_type field,
718 			   const char *msg, size_t msglen)
719 {
720 	struct eap_peer_config *config;
721 
722 	if (sm == NULL)
723 		return;
724 	config = eap_get_config(sm);
725 	if (config == NULL)
726 		return;
727 
728 	switch (field) {
729 	case WPA_CTRL_REQ_EAP_IDENTITY:
730 		config->pending_req_identity++;
731 		break;
732 	case WPA_CTRL_REQ_EAP_PASSWORD:
733 		config->pending_req_password++;
734 		break;
735 	case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
736 		config->pending_req_new_password++;
737 		break;
738 	case WPA_CTRL_REQ_EAP_PIN:
739 		config->pending_req_pin++;
740 		break;
741 	case WPA_CTRL_REQ_EAP_PASSPHRASE:
742 		config->pending_req_passphrase++;
743 		break;
744 	default:
745 		return;
746 	}
747 
748 }
749 #else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
750 #define eap_sm_request(sm, type, msg, msglen) do { } while (0)
751 #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
752 
eap_sm_get_method_name(struct eap_sm * sm)753 const char * eap_sm_get_method_name(struct eap_sm *sm)
754 {
755 	if (sm->m == NULL)
756 		return "UNKNOWN";
757 	return sm->m->name;
758 }
759 
760 
761 /**
762  * eap_sm_request_identity - Request identity from user (ctrl_iface)
763  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
764  *
765  * EAP methods can call this function to request identity information for the
766  * current network. This is normally called when the identity is not included
767  * in the network configuration. The request will be sent to monitor programs
768  * through the control interface.
769  */
eap_sm_request_identity(struct eap_sm * sm)770 void eap_sm_request_identity(struct eap_sm *sm)
771 {
772 	eap_sm_request(sm, WPA_CTRL_REQ_EAP_IDENTITY, NULL, 0);
773 }
774 
775 
776 /**
777  * eap_sm_request_password - Request password from user (ctrl_iface)
778  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
779  *
780  * EAP methods can call this function to request password information for the
781  * current network. This is normally called when the password is not included
782  * in the network configuration. The request will be sent to monitor programs
783  * through the control interface.
784  */
eap_sm_request_password(struct eap_sm * sm)785 void eap_sm_request_password(struct eap_sm *sm)
786 {
787 	eap_sm_request(sm, WPA_CTRL_REQ_EAP_PASSWORD, NULL, 0);
788 }
789 
790 
791 /**
792  * eap_sm_request_new_password - Request new password from user (ctrl_iface)
793  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
794  *
795  * EAP methods can call this function to request new password information for
796  * the current network. This is normally called when the EAP method indicates
797  * that the current password has expired and password change is required. The
798  * request will be sent to monitor programs through the control interface.
799  */
eap_sm_request_new_password(struct eap_sm * sm)800 void eap_sm_request_new_password(struct eap_sm *sm)
801 {
802 	eap_sm_request(sm, WPA_CTRL_REQ_EAP_NEW_PASSWORD, NULL, 0);
803 }
804 
805 
eap_peer_blob_deinit(struct eap_sm * sm)806 void eap_peer_blob_deinit(struct eap_sm *sm)
807 {
808 	int i;
809 	for (i = 0; i < BLOB_NUM; i++) {
810 		if (sm->blob[i].name) {
811 			os_free(sm->blob[i].name);
812 			sm->blob[i].name = NULL;
813 		}
814 	}
815 	os_bzero(&sm->blob[0], sizeof(struct wpa_config_blob)*BLOB_NUM);
816 
817 	sm->config.client_cert = NULL;
818 	sm->config.private_key = NULL;
819 	sm->config.ca_cert = NULL;
820 	sm->config.pac_file = NULL;
821 }
822 
eap_sm_abort(struct eap_sm * sm)823 void eap_sm_abort(struct eap_sm *sm)
824 {
825 	wpabuf_free(sm->lastRespData);
826 	sm->lastRespData = NULL;
827 }
828 
829 /**
830  * eap_get_config - Get current network configuration
831  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
832  * Returns: Pointer to the current network configuration or %NULL if not found
833  *
834  * EAP peer methods should avoid using this function if they can use other
835  * access functions, like eap_get_config_identity() and
836  * eap_get_config_password(), that do not require direct access to
837  * struct eap_peer_config.
838  */
eap_get_config(struct eap_sm * sm)839 struct eap_peer_config * eap_get_config(struct eap_sm *sm)
840 {
841 	return &sm->config;
842 }
843 
844 
845 /**
846  * eap_get_config_identity - Get identity from the network configuration
847  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
848  * @len: Buffer for the length of the identity
849  * Returns: Pointer to the identity or %NULL if not found
850  */
eap_get_config_identity(struct eap_sm * sm,size_t * len)851 const u8 * eap_get_config_identity(struct eap_sm *sm, size_t *len)
852 {
853 	struct eap_peer_config *config = eap_get_config(sm);
854 	if (config == NULL)
855 		return NULL;
856 	*len = config->identity_len;
857 	return config->identity;
858 }
859 
860 
861 /**
862  * eap_get_config_password - Get password from the network configuration
863  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
864  * @len: Buffer for the length of the password
865  * Returns: Pointer to the password or %NULL if not found
866  */
eap_get_config_password(struct eap_sm * sm,size_t * len)867 const u8 * eap_get_config_password(struct eap_sm *sm, size_t *len)
868 {
869 	struct eap_peer_config *config = eap_get_config(sm);
870 	if (config == NULL)
871 		return NULL;
872 	*len = config->password_len;
873 	return config->password;
874 }
875 
876 
877 /**
878  * eap_get_config_password2 - Get password from the network configuration
879  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
880  * @len: Buffer for the length of the password
881  * @hash: Buffer for returning whether the password is stored as a
882  * NtPasswordHash instead of plaintext password; can be %NULL if this
883  * information is not needed
884  * Returns: Pointer to the password or %NULL if not found
885  */
eap_get_config_password2(struct eap_sm * sm,size_t * len,int * hash)886 const u8 * eap_get_config_password2(struct eap_sm *sm, size_t *len, int *hash)
887 {
888 	struct eap_peer_config *config = eap_get_config(sm);
889 	if (config == NULL)
890 		return NULL;
891 
892 	*len = config->password_len;
893 	if (hash)
894 		*hash = !!(config->flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH);
895 	return config->password;
896 }
897 
898 
899 /**
900  * eap_get_config_new_password - Get new password from network configuration
901  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
902  * @len: Buffer for the length of the new password
903  * Returns: Pointer to the new password or %NULL if not found
904  */
eap_get_config_new_password(struct eap_sm * sm,size_t * len)905 const u8 * eap_get_config_new_password(struct eap_sm *sm, size_t *len)
906 {
907 	struct eap_peer_config *config = eap_get_config(sm);
908 	if (config == NULL)
909 		return NULL;
910 	*len = config->new_password_len;
911 	return config->new_password;
912 }
913 
914 
eap_copy_buf(u8 ** dst,size_t * dst_len,const u8 * src,size_t src_len)915 static int eap_copy_buf(u8 **dst, size_t *dst_len,
916 			     const u8 *src, size_t src_len)
917 {
918 	if (src) {
919 		*dst = os_memdup(src, src_len);
920 		if (*dst == NULL)
921 			return -1;
922 		*dst_len = src_len;
923 	}
924 	return 0;
925 }
926 
927 
928 /**
929  * eap_set_config_blob - Set or add a named configuration blob
930  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
931  * @blob: New value for the blob
932  *
933  * Adds a new configuration blob or replaces the current value of an existing
934  * blob.
935  */
eap_set_config_blob(struct eap_sm * sm,struct wpa_config_blob * blob)936 void eap_set_config_blob(struct eap_sm *sm, struct wpa_config_blob *blob)
937 {
938     if (!sm)
939         return;
940 
941     if (eap_copy_buf((u8 **)&sm->blob[3].data, (size_t *)&sm->blob[3].len, blob->data, blob->len) < 0) {
942 		wpa_printf(MSG_ERROR, "EAP: Set config blob: Unable to modify the configuration blob");
943     }
944 }
945 
946 
947 /**
948  * eap_get_config_blob - Get a named configuration blob
949  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
950  * @name: Name of the blob
951  * Returns: Pointer to blob data or %NULL if not found
952  */
eap_get_config_blob(struct eap_sm * sm,const char * name)953 const struct wpa_config_blob * eap_get_config_blob(struct eap_sm *sm,
954 						   const char *name)
955 {
956 	int i;
957 
958 	if (!sm)
959 		return NULL;
960 
961 	for (i = 0; i < BLOB_NUM; i++) {
962 		if (sm->blob[i].name == NULL)
963 			continue;
964 		if (os_strncmp(name, sm->blob[i].name, BLOB_NAME_LEN) == 0) {
965 			return &sm->blob[i];
966 		}
967 	}
968 	return NULL;
969 }
970