⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 eap_fast.c

📁 WLAN无线网络管理的最新程序
💻 C
📖 第 1 页 / 共 4 页
字号:
			     const char *pac_file){	FILE *f;	struct eap_fast_pac *pac;	int count = 0, ret;	char *buf, *pos;	size_t buf_len;	if (pac_file == NULL)		return -1;	buf_len = 1024;	pos = buf = os_malloc(buf_len);	if (buf == NULL)		return -1;	ret = os_snprintf(pos, buf + buf_len - pos, "%s\n", pac_file_hdr);	if (ret < 0 || ret >= buf + buf_len - pos) {		os_free(buf);		return -1;	}	pos += ret;	pac = data->pac;	while (pac) {		ret = os_snprintf(pos, buf + buf_len - pos, "START\n");		if (ret < 0 || ret >= buf + buf_len - pos) {			os_free(buf);			return -1;		}		pos += ret;		eap_fast_write(&buf, &pos, &buf_len, "PAC-Key", pac->pac_key,			       EAP_FAST_PAC_KEY_LEN, 0);		eap_fast_write(&buf, &pos, &buf_len, "PAC-Opaque",			       pac->pac_opaque, pac->pac_opaque_len, 0);		eap_fast_write(&buf, &pos, &buf_len, "PAC-Info", pac->pac_info,			       pac->pac_info_len, 0);		eap_fast_write(&buf, &pos, &buf_len, "A-ID", pac->a_id,			       pac->a_id_len, 0);		eap_fast_write(&buf, &pos, &buf_len, "I-ID", pac->i_id,			       pac->i_id_len, 1);		eap_fast_write(&buf, &pos, &buf_len, "A-ID-Info",			       pac->a_id_info, pac->a_id_info_len, 1);		if (buf == NULL) {			wpa_printf(MSG_DEBUG, "EAP-FAST: No memory for PAC "				   "data");			return -1;		}		ret = os_snprintf(pos, buf + buf_len - pos, "END\n");		if (ret < 0 || ret >= buf + buf_len - pos) {			os_free(buf);			return -1;		}		pos += ret;		count++;		pac = pac->next;	}	if (os_strncmp(pac_file, "blob://", 7) == 0) {		struct wpa_config_blob *blob;		blob = os_zalloc(sizeof(*blob));		if (blob == NULL) {			os_free(buf);			return -1;		}		blob->data = (u8 *) buf;		blob->len = pos - buf;		buf = NULL;		blob->name = os_strdup(pac_file + 7);		if (blob->name == NULL) {			os_free(blob->data);			os_free(blob);			return -1;		}		eap_set_config_blob(sm, blob);	} else {		f = fopen(pac_file, "w");		if (f == NULL) {			wpa_printf(MSG_INFO, "EAP-FAST: Failed to open PAC "				   "file '%s' for writing", pac_file);			os_free(buf);			return -1;		}		fprintf(f, "%s", buf);		os_free(buf);		fclose(f);	}	wpa_printf(MSG_DEBUG, "EAP-FAST: wrote %d PAC entries into '%s'",		   count, pac_file);	return 0;}static void * eap_fast_init(struct eap_sm *sm){	struct eap_fast_data *data;	struct wpa_ssid *config = eap_get_config(sm);	data = os_zalloc(sizeof(*data));	if (data == NULL)		return NULL;	data->fast_version = EAP_FAST_VERSION;	if (config && config->phase1) {		if (os_strstr(config->phase1, "fast_provisioning=1")) {			data->provisioning_allowed = 1;			wpa_printf(MSG_DEBUG, "EAP-FAST: Automatic PAC "				   "provisioning is allowed");		}	}	if (config && config->phase2) {		char *start, *pos, *buf;		struct eap_method_type *methods = NULL, *_methods;		u8 method;		size_t num_methods = 0;		start = buf = os_strdup(config->phase2);		if (buf == NULL) {			eap_fast_deinit(sm, data);			return NULL;		}		while (start && *start != '\0') {			int vendor;			pos = os_strstr(start, "auth=");			if (pos == NULL)				break;			if (start != pos && *(pos - 1) != ' ') {				start = pos + 5;				continue;			}			start = pos + 5;			pos = os_strchr(start, ' ');			if (pos)				*pos++ = '\0';			method = eap_get_phase2_type(start, &vendor);			if (vendor == EAP_VENDOR_IETF &&			    method == EAP_TYPE_NONE) {				wpa_printf(MSG_ERROR, "EAP-FAST: Unsupported "					   "Phase2 method '%s'", start);			} else {				num_methods++;				_methods = os_realloc(					methods,					num_methods * sizeof(*methods));				if (_methods == NULL) {					os_free(methods);					os_free(buf);					eap_fast_deinit(sm, data);					return NULL;				}				methods = _methods;				methods[num_methods - 1].vendor = vendor;				methods[num_methods - 1].method = method;			}			start = pos;		}		os_free(buf);		data->phase2_types = methods;		data->num_phase2_types = num_methods;	}	if (data->phase2_types == NULL) {		data->phase2_types =			eap_get_phase2_types(config, &data->num_phase2_types);	}	if (data->phase2_types == NULL) {		wpa_printf(MSG_ERROR, "EAP-FAST: No Phase2 method available");		eap_fast_deinit(sm, data);		return NULL;	}	wpa_hexdump(MSG_DEBUG, "EAP-FAST: Phase2 EAP types",		    (u8 *) data->phase2_types,		    data->num_phase2_types * sizeof(struct eap_method_type));	data->phase2_type.vendor = EAP_VENDOR_IETF;	data->phase2_type.method = EAP_TYPE_NONE;	if (eap_tls_ssl_init(sm, &data->ssl, config)) {		wpa_printf(MSG_INFO, "EAP-FAST: Failed to initialize SSL.");		eap_fast_deinit(sm, data);		return NULL;	}	/* The local RADIUS server in a Cisco AP does not seem to like empty	 * fragments before data, so disable that workaround for CBC.	 * TODO: consider making this configurable */	tls_connection_enable_workaround(sm->ssl_ctx, data->ssl.conn);	if (eap_fast_load_pac(sm, data, config->pac_file) < 0) {		eap_fast_deinit(sm, data);		return NULL;	}	if (data->pac == NULL && !data->provisioning_allowed) {		wpa_printf(MSG_INFO, "EAP-FAST: No PAC configured and "			   "provisioning disabled");		eap_fast_deinit(sm, data);		return NULL;	}	return data;}static void eap_fast_deinit(struct eap_sm *sm, void *priv){	struct eap_fast_data *data = priv;	struct eap_fast_pac *pac, *prev;	if (data == NULL)		return;	if (data->phase2_priv && data->phase2_method)		data->phase2_method->deinit(sm, data->phase2_priv);	os_free(data->phase2_types);	os_free(data->key_block_p);	eap_tls_ssl_deinit(sm, &data->ssl);	pac = data->pac;	prev = NULL;	while (pac) {		prev = pac;		pac = pac->next;		eap_fast_free_pac(prev);	}	os_free(data);}static int eap_fast_encrypt(struct eap_sm *sm, struct eap_fast_data *data,			    int id, const u8 *plain, size_t plain_len,			    u8 **out_data, size_t *out_len){	int res;	u8 *pos;	struct eap_hdr *resp;	/* TODO: add support for fragmentation, if needed. This will need to	 * add TLS Message Length field, if the frame is fragmented. */	resp = os_malloc(sizeof(struct eap_hdr) + 2 + data->ssl.tls_out_limit);	if (resp == NULL)		return 0;	resp->code = EAP_CODE_RESPONSE;	resp->identifier = id;	pos = (u8 *) (resp + 1);	*pos++ = EAP_TYPE_FAST;	*pos++ = data->fast_version;	res = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn,				     plain, plain_len,				     pos, data->ssl.tls_out_limit);	if (res < 0) {		wpa_printf(MSG_INFO, "EAP-FAST: Failed to encrypt Phase 2 "			   "data");		os_free(resp);		return 0;	}	*out_len = sizeof(struct eap_hdr) + 2 + res;	resp->length = host_to_be16(*out_len);	*out_data = (u8 *) resp;	return 0;}static int eap_fast_phase2_nak(struct eap_fast_data *data,			       struct eap_hdr *hdr,			       u8 **resp, size_t *resp_len){	struct eap_hdr *resp_hdr;	u8 *pos = (u8 *) (hdr + 1);	size_t i;	/* TODO: add support for expanded Nak */	wpa_printf(MSG_DEBUG, "EAP-FAST: Phase 2 Request: Nak type=%d", *pos);	wpa_hexdump(MSG_DEBUG, "EAP-FAST: Allowed Phase2 EAP types",		    (u8 *) data->phase2_types,		    data->num_phase2_types * sizeof(struct eap_method_type));	*resp_len = sizeof(struct eap_hdr) + 1;	*resp = os_malloc(*resp_len + data->num_phase2_types);	if (*resp == NULL)		return -1;	resp_hdr = (struct eap_hdr *) (*resp);	resp_hdr->code = EAP_CODE_RESPONSE;	resp_hdr->identifier = hdr->identifier;	pos = (u8 *) (resp_hdr + 1);	*pos++ = EAP_TYPE_NAK;	for (i = 0; i < data->num_phase2_types; i++) {		if (data->phase2_types[i].vendor == EAP_VENDOR_IETF &&		    data->phase2_types[i].method < 256) {			(*resp_len)++;			*pos++ = data->phase2_types[i].method;		}	}	resp_hdr->length = host_to_be16(*resp_len);	return 0;}static int eap_fast_derive_msk(struct eap_fast_data *data){	/* Derive EAP Master Session Keys (section 5.4) */	sha1_t_prf(data->simck, EAP_FAST_SIMCK_LEN,		   "Session Key Generating Function", (u8 *) "", 0,		   data->key_data, EAP_FAST_KEY_LEN);	wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Derived key (MSK)",			data->key_data, EAP_FAST_KEY_LEN);	sha1_t_prf(data->simck, EAP_FAST_SIMCK_LEN,		   "Extended Session Key Generating Function",		   (u8 *) "", 0, data->emsk, EAP_EMSK_LEN);	wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Derived key (EMSK)",			data->emsk, EAP_EMSK_LEN);	data->success = 1;	return 0;}static int eap_fast_set_tls_master_secret(struct eap_sm *sm,					  struct eap_fast_data *data,					  const u8 *tls, size_t tls_len){	struct tls_keys keys;	u8 master_secret[48], *seed;	const u8 *server_random;	size_t seed_len, server_random_len;	if (data->tls_master_secret_set || !data->current_pac ||	    tls_connection_get_keys(sm->ssl_ctx, data->ssl.conn, &keys) ||	    keys.client_random == NULL) {		return 0;	}	wpa_hexdump(MSG_DEBUG, "EAP-FAST: client_random",		    keys.client_random, keys.client_random_len);	/* TLS master secret is needed before TLS library has processed this	 * message which includes both ServerHello and an encrypted handshake	 * message, so we need to parse server_random from this message before	 * passing it to TLS library.	 *	 * Example TLS packet header:	 * (16 03 01 00 2a 02 00 00 26 03 01 <32 bytes server_random>)	 * Content Type: Handshake: 0x16	 * Version: TLS 1.0 (0x0301)	 * Lenghth: 42 (0x002a)	 * Handshake Type: Server Hello: 0x02	 * Length: 38 (0x000026)	 * Version TLS 1.0 (0x0301)	 * Random: 32 bytes	 */	if (tls_len < 43 || tls[0] != 0x16 ||	    tls[1] != 0x03 || tls[2] != 0x01 ||	    tls[5] != 0x02 || tls[9] != 0x03 || tls[10] != 0x01) {		wpa_hexdump(MSG_DEBUG, "EAP-FAST: unrecognized TLS "			    "ServerHello", tls, tls_len);		return -1;	}	server_random = tls + 11;	server_random_len = 32;	wpa_hexdump(MSG_DEBUG, "EAP-FAST: server_random",		    server_random, server_random_len);	seed_len = keys.client_random_len + server_random_len;	seed = os_malloc(seed_len);	if (seed == NULL)		return -1;	os_memcpy(seed, server_random, server_random_len);	os_memcpy(seed + server_random_len,		  keys.client_random, keys.client_random_len);	wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: T-PRF seed", seed, seed_len);	wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: PAC-Key",			data->current_pac->pac_key, EAP_FAST_PAC_KEY_LEN);	/* master_secret = T-PRF(PAC-Key, "PAC to master secret label hash", 	 * server_random + client_random, 48) */	sha1_t_prf(data->current_pac->pac_key, EAP_FAST_PAC_KEY_LEN,		   "PAC to master secret label hash",		   seed, seed_len, master_secret, sizeof(master_secret));	os_free(seed);	wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: TLS pre-master-secret",			master_secret, sizeof(master_secret));	data->tls_master_secret_set = 1;	return tls_connection_set_master_key(sm->ssl_ctx, data->ssl.conn,					     master_secret,					     sizeof(master_secret));}static u8 * eap_fast_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,				char *label, size_t len){	struct tls_keys keys;	u8 *rnd = NULL, *out;	int block_size;	block_size = tls_connection_get_keyblock_size(sm->ssl_ctx, data->conn);	if (block_size < 0)		return NULL;	out = os_malloc(block_size + len);	if (out == NULL)		return NULL;	if (tls_connection_prf(sm->ssl_ctx, data->conn, label, 1, out,			       block_size + len) == 0) {		os_memmove(out, out + block_size, len);		return out;	}	if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys))		goto fail;	rnd = os_malloc(keys.client_random_len + keys.server_random_len);	if (rnd == NULL)		goto fail;	os_memcpy(rnd, keys.server_random, keys.server_random_len);	os_memcpy(rnd + keys.server_random_len, keys.client_random,		  keys.client_random_len);	wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: master_secret for key "			"expansion", keys.master_key, keys.master_key_len);	if (tls_prf(keys.master_key, keys.master_key_len,		    label, rnd, keys.client_random_len +		    keys.server_random_len, out, block_size + len))		goto fail;	os_free(rnd);	os_memmove(out, out + block_size, len);	return out;fail:	os_free(rnd);	os_free(out);	return NULL;}static void eap_fast_derive_key_auth(struct eap_sm *sm,				     struct eap_fast_data *data){	u8 *sks;	/* draft-cam-winget-eap-fast-05.txt:	 * 5.1 EAP-FAST Authentication Phase 1: Key Derivations	 * Extra key material after TLS key_block: session_ket_seed[40]	 */	sks = eap_fast_derive_key(sm, &data->ssl, "key expansion",				  EAP_FAST_SKS_LEN);	if (sks == NULL) {		wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to derive "			   "session_key_seed");		return;	}	/*	 * draft-cam-winget-eap-fast-05.txt, 5.2:	 * S-IMCK[0] = session_key_seed	 */	wpa_hexdump_key(MSG_DEBUG,			"EAP-FAST: session_key_seed (SKS = S-IMCK[0])",			sks, EAP_FAST_SKS_LEN);	data->simck_idx = 0;	os_memcpy(data->simck, sks, EAP_FAST_SIMCK_LEN);	os_free(sks);}static void eap_fast_derive_key_provisioning(struct eap_sm *sm,					     struct eap_fast_data *data){	os_free(data->key_block_p);	data->key_block_p = (struct eap_fast_key_block_provisioning *)		eap_fast_derive_key(sm, &data->ssl, "key expansion",				    sizeof(*data->key_block_p));	if (data->key_block_p == NULL) {		wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to derive key block");		return;	}	/*	 * draft-cam-winget-eap-fast-05.txt, 5.2:	 * S-IMCK[0] = session_key_seed	 */	wpa_hexdump_key(MSG_DEBUG,			"EAP-FAST: session_key_seed (SKS = S-IMCK[0])",			data->key_block_p->session_key_seed,			sizeof(data->key_block_p->session_key_seed));	data->simck_idx = 0;	os_memcpy(data->simck, data->key_block_p->session_key_seed,		  EAP_FAST_SIMCK_LEN);	wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: server_challenge",			data->key_block_p->server_challenge,			sizeof(data->key_block_p->server_challenge));	wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: client_challenge",			data->key_block_p->client_challenge,			sizeof(data->key_block_p->client_challenge));}static void eap_fast_derive_keys(struct eap_sm *sm, struct eap_fast_data *data){	if (data->current_pac) {		eap_fast_derive_key_auth(sm, data);	} else {		eap_fast_derive_key_provisioning(sm, data);	}}static int eap_fast_phase2_request(struct eap_sm *sm,				   struct eap_fast_data *data,				   struct eap_method_ret *ret,				   struct eap_hdr *hdr,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -