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

📄 eap_fast.c

📁 一个Linux下无线网卡的设置工具
💻 C
📖 第 1 页 / 共 4 页
字号:
	for (i = 0; i < len; i++) {		*pos += snprintf(*pos, *buf + *buf_len - *pos,				 "%02x", data[i]);	}	*pos += snprintf(*pos, *buf + *buf_len - *pos, "\n");	if (txt) {		*pos += snprintf(*pos, *buf + *buf_len - *pos,				 "%s-txt=", field);		for (i = 0; i < len; i++) {			*pos += snprintf(*pos, *buf + *buf_len - *pos,					 "%c", data[i]);		}		*pos += snprintf(*pos, *buf + *buf_len - *pos, "\n");	}}static int eap_fast_save_pac(struct eap_sm *sm, struct eap_fast_data *data,			     const char *pac_file){	FILE *f;	struct eap_fast_pac *pac;	int count = 0;	char *buf, *pos;	size_t buf_len;	if (pac_file == NULL)		return -1;	buf_len = 1024;	pos = buf = malloc(buf_len);	if (buf == NULL)		return -1;	pos += snprintf(pos, buf + buf_len - pos, "%s\n", pac_file_hdr);	pac = data->pac;	while (pac) {		pos += snprintf(pos, buf + buf_len - pos, "START\n");		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);		pos += snprintf(pos, buf + buf_len - pos, "END\n");		count++;		pac = pac->next;		if (buf == NULL) {			wpa_printf(MSG_DEBUG, "EAP-FAST: No memory for PAC "				   "data");			return -1;		}	}	if (strncmp(pac_file, "blob://", 7) == 0) {		struct wpa_config_blob *blob;		blob = malloc(sizeof(*blob));		if (blob == NULL) {			free(buf);			return -1;		}		memset(blob, 0, sizeof(*blob));		blob->data = (u8 *) buf;		blob->len = pos - buf;		buf = NULL;		blob->name = strdup(pac_file + 7);		if (blob->name == NULL) {			wpa_config_free_blob(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);			free(buf);			return -1;		}		fprintf(f, "%s", buf);		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 = malloc(sizeof(*data));	if (data == NULL)		return NULL;	memset(data, 0, sizeof(*data));	data->fast_version = EAP_FAST_VERSION;	if (config && config->phase1) {		if (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;		u8 method, *methods = NULL, *_methods;		size_t num_methods = 0;		start = buf = strdup(config->phase2);		if (buf == NULL) {			eap_fast_deinit(sm, data);			return NULL;		}		while (start && *start != '\0') {			pos = strstr(start, "auth=");			if (pos == NULL)				break;			if (start != pos && *(pos - 1) != ' ') {				start = pos + 5;				continue;			}			start = pos + 5;			pos = strchr(start, ' ');			if (pos)				*pos++ = '\0';			method = eap_get_phase2_type(start);			if (method == EAP_TYPE_NONE) {				wpa_printf(MSG_ERROR, "EAP-FAST: Unsupported "					   "Phase2 method '%s'", start);			} else {				num_methods++;				_methods = realloc(methods, num_methods);				if (_methods == NULL) {					free(methods);					free(buf);					eap_fast_deinit(sm, data);					return NULL;				}				methods = _methods;				methods[num_methods - 1] = method;			}			start = pos;		}		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",		    data->phase2_types, data->num_phase2_types);	data->phase2_type = 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);	free(data->phase2_types);	free(data->key_block_a);	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);	}	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 = 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");		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_sm *sm,			       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);	wpa_printf(MSG_DEBUG, "EAP-FAST: Phase 2 Request: Nak type=%d", *pos);	wpa_hexdump(MSG_DEBUG, "EAP-FAST: Allowed Phase2 EAP types",		    data->phase2_types, data->num_phase2_types);	*resp_len = sizeof(struct eap_hdr) + 1 + data->num_phase2_types;	*resp = malloc(*resp_len);	if (*resp == NULL)		return -1;	resp_hdr = (struct eap_hdr *) (*resp);	resp_hdr->code = EAP_CODE_RESPONSE;	resp_hdr->identifier = hdr->identifier;	resp_hdr->length = host_to_be16(*resp_len);	pos = (u8 *) (resp_hdr + 1);	*pos++ = EAP_TYPE_NAK;	memcpy(pos, data->phase2_types, data->num_phase2_types);	return 0;}static int eap_fast_derive_msk(struct eap_sm *sm, struct eap_fast_data *data){	u8 isk[32];	u8 imck[60];	if (data->key_block_a == NULL)		return -1;	memset(isk, 0, sizeof(isk));	sha1_t_prf(data->key_block_a->session_key_seed,		   sizeof(data->key_block_a->session_key_seed),		   "Inner Methods Compound Keys",		   isk, sizeof(isk), imck, sizeof(imck));	sha1_t_prf(imck, 40, "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);	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)) {		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 = malloc(seed_len);	if (seed == NULL)		return -1;	memcpy(seed, server_random, server_random_len);	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));	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;	u8 *out;	int block_size;	if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys))		return NULL;	block_size = tls_connection_get_keyblock_size(sm->ssl_ctx, data->conn);	if (block_size < 0)		return NULL;	out = malloc(block_size + len);	rnd = malloc(keys.client_random_len + keys.server_random_len);	if (out == NULL || rnd == NULL) {		free(out);		free(rnd);		return NULL;	}	memcpy(rnd, keys.server_random, keys.server_random_len);	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)) {		free(rnd);		free(out);		return NULL;	}	free(rnd);	memmove(out, out + block_size, len);	return out;}static void eap_fast_derive_key_auth(struct eap_sm *sm,				     struct eap_fast_data *data){	free(data->key_block_a);	data->key_block_a = (struct eap_fast_key_block_auth *)		eap_fast_derive_key(sm, &data->ssl, "key expansion",				    sizeof(*data->key_block_a));	if (data->key_block_a == NULL) {		wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to derive "			   "session_key_seed");		return;	}	wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: session_key_seed",			data->key_block_a->session_key_seed,			sizeof(data->key_block_a->session_key_seed));}static void eap_fast_derive_key_provisioning(struct eap_sm *sm,					     struct eap_fast_data *data){	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;	}	wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: session_key_seed",			data->key_block_p->session_key_seed,			sizeof(data->key_block_p->session_key_seed));	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,				   const struct eap_hdr *req,				   struct eap_hdr *hdr,				   u8 **resp, size_t *resp_len){	size_t len = be_to_host16(hdr->length);	u8 *pos;	struct eap_method_ret iret;	if (len <= sizeof(struct eap_hdr)) {		wpa_printf(MSG_INFO, "EAP-FAST: too short "

⌨️ 快捷键说明

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