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

📄 eap.c

📁 WLAN无线网络管理的最新程序
💻 C
📖 第 1 页 / 共 4 页
字号:
	if (eapol_get_bool(sm, EAPOL_eapRestart) &&	    eapol_get_bool(sm, EAPOL_portEnabled))		SM_ENTER_GLOBAL(EAP, INITIALIZE);	else if (!eapol_get_bool(sm, EAPOL_portEnabled) || sm->force_disabled)		SM_ENTER_GLOBAL(EAP, DISABLED);	else if (sm->num_rounds > EAP_MAX_AUTH_ROUNDS) {		/* RFC 4137 does not place any limit on number of EAP messages		 * in an authentication session. However, some error cases have		 * ended up in a state were EAP messages were sent between the		 * peer and server in a loop (e.g., TLS ACK frame in both		 * direction). Since this is quite undesired outcome, limit the		 * total number of EAP round-trips and abort authentication if		 * this limit is exceeded.		 */		if (sm->num_rounds == EAP_MAX_AUTH_ROUNDS + 1) {			wpa_msg(sm->msg_ctx, MSG_INFO, "EAP: more than %d "				"authentication rounds - abort",				EAP_MAX_AUTH_ROUNDS);			sm->num_rounds++;			SM_ENTER_GLOBAL(EAP, FAILURE);		}	} else switch (sm->EAP_state) {	case EAP_INITIALIZE:		SM_ENTER(EAP, IDLE);		break;	case EAP_DISABLED:		if (eapol_get_bool(sm, EAPOL_portEnabled) &&		    !sm->force_disabled)			SM_ENTER(EAP, INITIALIZE);		break;	case EAP_IDLE:		/*		 * The first three transitions are from RFC 4137. The last two		 * are local additions to handle special cases with LEAP and		 * PEAP server not sending EAP-Success in some cases.		 */		if (eapol_get_bool(sm, EAPOL_eapReq))			SM_ENTER(EAP, RECEIVED);		else if ((eapol_get_bool(sm, EAPOL_altAccept) &&			  sm->decision != DECISION_FAIL) ||			 (eapol_get_int(sm, EAPOL_idleWhile) == 0 &&			  sm->decision == DECISION_UNCOND_SUCC))			SM_ENTER(EAP, SUCCESS);		else if (eapol_get_bool(sm, EAPOL_altReject) ||			 (eapol_get_int(sm, EAPOL_idleWhile) == 0 &&			  sm->decision != DECISION_UNCOND_SUCC) ||			 (eapol_get_bool(sm, EAPOL_altAccept) &&			  sm->methodState != METHOD_CONT &&			  sm->decision == DECISION_FAIL))			SM_ENTER(EAP, FAILURE);		else if (sm->selectedMethod == EAP_TYPE_LEAP &&			 sm->leap_done && sm->decision != DECISION_FAIL &&			 sm->methodState == METHOD_DONE)			SM_ENTER(EAP, SUCCESS);		else if (sm->selectedMethod == EAP_TYPE_PEAP &&			 sm->peap_done && sm->decision != DECISION_FAIL &&			 sm->methodState == METHOD_DONE)			SM_ENTER(EAP, SUCCESS);		break;	case EAP_RECEIVED:		duplicate = (sm->reqId == sm->lastId) && sm->rxReq;		if (sm->workaround && duplicate &&		    os_memcmp(sm->req_md5, sm->last_md5, 16) != 0) {			/*			 * RFC 4137 uses (reqId == lastId) as the only			 * verification for duplicate EAP requests. However,			 * this misses cases where the AS is incorrectly using			 * the same id again; and unfortunately, such			 * implementations exist. Use MD5 hash as an extra			 * verification for the packets being duplicate to			 * workaround these issues.			 */			wpa_printf(MSG_DEBUG, "EAP: AS used the same Id again,"				   " but EAP packets were not identical");			wpa_printf(MSG_DEBUG, "EAP: workaround - assume this "				   "is not a duplicate packet");			duplicate = 0;		}		/*		 * Two special cases below for LEAP are local additions to work		 * around odd LEAP behavior (EAP-Success in the middle of		 * authentication and then swapped roles). Other transitions		 * are based on RFC 4137.		 */		if (sm->rxSuccess && sm->decision != DECISION_FAIL &&		    (sm->reqId == sm->lastId ||		     eap_success_workaround(sm, sm->reqId, sm->lastId)))			SM_ENTER(EAP, SUCCESS);		else if (sm->methodState != METHOD_CONT &&			 ((sm->rxFailure &&			   sm->decision != DECISION_UNCOND_SUCC) ||			  (sm->rxSuccess && sm->decision == DECISION_FAIL &&			   (sm->selectedMethod != EAP_TYPE_LEAP ||			    sm->methodState != METHOD_MAY_CONT))) &&			 (sm->reqId == sm->lastId ||			  eap_success_workaround(sm, sm->reqId, sm->lastId)))			SM_ENTER(EAP, FAILURE);		else if (sm->rxReq && duplicate)			SM_ENTER(EAP, RETRANSMIT);		else if (sm->rxReq && !duplicate &&			 sm->reqMethod == EAP_TYPE_NOTIFICATION &&			 sm->allowNotifications)			SM_ENTER(EAP, NOTIFICATION);		else if (sm->rxReq && !duplicate &&			 sm->selectedMethod == EAP_TYPE_NONE &&			 sm->reqMethod == EAP_TYPE_IDENTITY)			SM_ENTER(EAP, IDENTITY);		else if (sm->rxReq && !duplicate &&			 sm->selectedMethod == EAP_TYPE_NONE &&			 sm->reqMethod != EAP_TYPE_IDENTITY &&			 sm->reqMethod != EAP_TYPE_NOTIFICATION)			SM_ENTER(EAP, GET_METHOD);		else if (sm->rxReq && !duplicate &&			 sm->reqMethod == sm->selectedMethod &&			 sm->methodState != METHOD_DONE)			SM_ENTER(EAP, METHOD);		else if (sm->selectedMethod == EAP_TYPE_LEAP &&			 (sm->rxSuccess || sm->rxResp))			SM_ENTER(EAP, METHOD);		else			SM_ENTER(EAP, DISCARD);		break;	case EAP_GET_METHOD:		if (sm->selectedMethod == sm->reqMethod)			SM_ENTER(EAP, METHOD);		else			SM_ENTER(EAP, SEND_RESPONSE);		break;	case EAP_METHOD:		if (sm->ignore)			SM_ENTER(EAP, DISCARD);		else			SM_ENTER(EAP, SEND_RESPONSE);		break;	case EAP_SEND_RESPONSE:		SM_ENTER(EAP, IDLE);		break;	case EAP_DISCARD:		SM_ENTER(EAP, IDLE);		break;	case EAP_IDENTITY:		SM_ENTER(EAP, SEND_RESPONSE);		break;	case EAP_NOTIFICATION:		SM_ENTER(EAP, SEND_RESPONSE);		break;	case EAP_RETRANSMIT:		SM_ENTER(EAP, SEND_RESPONSE);		break;	case EAP_SUCCESS:		break;	case EAP_FAILURE:		break;	}}static Boolean eap_sm_allowMethod(struct eap_sm *sm, int vendor,				  EapType method){	struct wpa_ssid *config = eap_get_config(sm);	if (!wpa_config_allowed_eap_method(config, vendor, method)) {		wpa_printf(MSG_DEBUG, "EAP: configuration does not allow: "			   "vendor %u method %u", vendor, method);		return FALSE;	}	if (eap_sm_get_eap_methods(vendor, method))		return TRUE;	wpa_printf(MSG_DEBUG, "EAP: not included in build: "		   "vendor %u method %u", vendor, method);	return FALSE;}static u8 * eap_sm_build_expanded_nak(struct eap_sm *sm, int id, size_t *len,				      const struct eap_method *methods,				      size_t count){	struct wpa_ssid *config = eap_get_config(sm);	struct eap_hdr *resp;	u8 *pos;	int found = 0;	const struct eap_method *m;	wpa_printf(MSG_DEBUG, "EAP: Building expanded EAP-Nak");	/* RFC 3748 - 5.3.2: Expanded Nak */	*len = sizeof(struct eap_hdr) + 8;	resp = os_malloc(*len + 8 * (count + 1));	if (resp == NULL)		return NULL;	resp->code = EAP_CODE_RESPONSE;	resp->identifier = id;	pos = (u8 *) (resp + 1);	*pos++ = EAP_TYPE_EXPANDED;	WPA_PUT_BE24(pos, EAP_VENDOR_IETF);	pos += 3;	WPA_PUT_BE32(pos, EAP_TYPE_NAK);	pos += 4;	for (m = methods; m; m = m->next) {		if (sm->reqVendor == m->vendor &&		    sm->reqVendorMethod == m->method)			continue; /* do not allow the current method again */		if (wpa_config_allowed_eap_method(config, m->vendor,						  m->method)) {			wpa_printf(MSG_DEBUG, "EAP: allowed type: "				   "vendor=%u method=%u",				   m->vendor, m->method);			*pos++ = EAP_TYPE_EXPANDED;			WPA_PUT_BE24(pos, m->vendor);			pos += 3;			WPA_PUT_BE32(pos, m->method);			pos += 4;			(*len) += 8;			found++;		}	}	if (!found) {		wpa_printf(MSG_DEBUG, "EAP: no more allowed methods");		*pos++ = EAP_TYPE_EXPANDED;		WPA_PUT_BE24(pos, EAP_VENDOR_IETF);		pos += 3;		WPA_PUT_BE32(pos, EAP_TYPE_NONE);		pos += 4;		(*len) += 8;	}	resp->length = host_to_be16(*len);	return (u8 *) resp;}static u8 * eap_sm_buildNak(struct eap_sm *sm, int id, size_t *len){	struct wpa_ssid *config = eap_get_config(sm);	struct eap_hdr *resp;	u8 *pos;	int found = 0, expanded_found = 0;	size_t count;	const struct eap_method *methods, *m;	wpa_printf(MSG_DEBUG, "EAP: Building EAP-Nak (requested type %u "		   "vendor=%u method=%u not allowed)", sm->reqMethod,		   sm->reqVendor, sm->reqVendorMethod);	methods = eap_peer_get_methods(&count);	if (methods == NULL)		return NULL;	if (sm->reqMethod == EAP_TYPE_EXPANDED)		return eap_sm_build_expanded_nak(sm, id, len, methods, count);	/* RFC 3748 - 5.3.1: Legacy Nak */	*len = sizeof(struct eap_hdr) + 1;	resp = os_malloc(*len + count + 1);	if (resp == NULL)		return NULL;	resp->code = EAP_CODE_RESPONSE;	resp->identifier = id;	pos = (u8 *) (resp + 1);	*pos++ = EAP_TYPE_NAK;	for (m = methods; m; m = m->next) {		if (m->vendor == EAP_VENDOR_IETF && m->method == sm->reqMethod)			continue; /* do not allow the current method again */		if (wpa_config_allowed_eap_method(config, m->vendor,						  m->method)) {			if (m->vendor != EAP_VENDOR_IETF) {				if (expanded_found)					continue;				expanded_found = 1;				*pos++ = EAP_TYPE_EXPANDED;			} else				*pos++ = m->method;			(*len)++;			found++;		}	}	if (!found) {		*pos = EAP_TYPE_NONE;		(*len)++;	}	wpa_hexdump(MSG_DEBUG, "EAP: allowed methods",		    ((u8 *) (resp + 1)) + 1, found);	resp->length = host_to_be16(*len);	return (u8 *) resp;}static void eap_sm_processIdentity(struct eap_sm *sm, const u8 *req){	const struct eap_hdr *hdr = (const struct eap_hdr *) req;	const u8 *pos = (const u8 *) (hdr + 1);	pos++;	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_STARTED		"EAP authentication started");	/*	 * RFC 3748 - 5.1: Identity	 * Data field may contain a displayable message in UTF-8. If this	 * includes NUL-character, only the data before that should be	 * displayed. Some EAP implementasitons may piggy-back additional	 * options after the NUL.	 */	/* TODO: could save displayable message so that it can be shown to the	 * user in case of interaction is required */	wpa_hexdump_ascii(MSG_DEBUG, "EAP: EAP-Request Identity data",			  pos, be_to_host16(hdr->length) - 5);}#ifdef PCSC_FUNCSstatic int eap_sm_imsi_identity(struct eap_sm *sm, struct wpa_ssid *ssid){	int aka = 0;	char imsi[100];	size_t imsi_len;	struct eap_method_type *m = ssid->eap_methods;	int i;	imsi_len = sizeof(imsi);	if (scard_get_imsi(sm->scard_ctx, imsi, &imsi_len)) {		wpa_printf(MSG_WARNING, "Failed to get IMSI from SIM");		return -1;	}	wpa_hexdump_ascii(MSG_DEBUG, "IMSI", (u8 *) imsi, imsi_len);	for (i = 0; m && (m[i].vendor != EAP_VENDOR_IETF ||			  m[i].method != EAP_TYPE_NONE); i++) {		if (m[i].vendor == EAP_VENDOR_IETF &&		    m[i].method == EAP_TYPE_AKA) {			aka = 1;			break;		}	}	os_free(ssid->identity);	ssid->identity = os_malloc(1 + imsi_len);	if (ssid->identity == NULL) {		wpa_printf(MSG_WARNING, "Failed to allocate buffer for "			   "IMSI-based identity");		return -1;	}	ssid->identity[0] = aka ? '0' : '1';	os_memcpy(ssid->identity + 1, imsi, imsi_len);	ssid->identity_len = 1 + imsi_len;	return 0;}#endif /* PCSC_FUNCS */static int eap_sm_get_scard_identity(struct eap_sm *sm, struct wpa_ssid *ssid){#ifdef PCSC_FUNCS	if (scard_set_pin(sm->scard_ctx, ssid->pin)) {		/*		 * Make sure the same PIN is not tried again in order to avoid		 * blocking SIM.		 */		os_free(ssid->pin);		ssid->pin = NULL;		wpa_printf(MSG_WARNING, "PIN validation failed");		eap_sm_request_pin(sm);		return -1;	}	return eap_sm_imsi_identity(sm, ssid);#else /* PCSC_FUNCS */	return -1;#endif /* PCSC_FUNCS */}/** * eap_sm_buildIdentity - Build EAP-Identity/Response for the current network * @sm: Pointer to EAP state machine allocated with eap_sm_init() * @id: EAP identifier for the packet * @len: Pointer to a variable that will be set to the length of the response * @encrypted: Whether the packet is for encrypted tunnel (EAP phase 2) * Returns: Pointer to the allocated EAP-Identity/Response packet or %NULL on * failure * * This function allocates and builds an EAP-Identity/Response packet for the * current network. The caller is responsible for freeing the returned data. */u8 * eap_sm_buildIdentity(struct eap_sm *sm, int id, size_t *len,			  int encrypted){	struct wpa_ssid *config = eap_get_config(sm);	struct eap_hdr *resp;	u8 *pos;	const u8 *identity;	size_t identity_len;	if (config == NULL) {		wpa_printf(MSG_WARNING, "EAP: buildIdentity: configuration "			   "was not available");		return NULL;	}	if (sm->m && sm->m->get_identity &&	    (identity = sm->m->get_identity(sm, sm->eap_method_priv,					    &identity_len)) != NULL) {		wpa_hexdump_ascii(MSG_DEBUG, "EAP: using method re-auth "				  "identity", identity, identity_len);	} else if (!encrypted && config->anonymous_identity) {		identity = config->anonymous_identity;		identity_len = config->anonymous_identity_len;		wpa_hexdump_ascii(MSG_DEBUG, "EAP: using anonymous identity",				  identity, identity_len);	} else {		identity = config->identity;		identity_len = config->identity_len;		wpa_hexdump_ascii(MSG_DEBUG, "EAP: using real identity",				  identity, identity_len);	}	if (identity == NULL) {		wpa_printf(MSG_WARNING, "EAP: buildIdentity: identity "			   "configuration was not available");		if (config->pcsc) {			if (eap_sm_get_scard_identity(sm, config) < 0)				return NULL;			identity = config->identity;			identity_len = config->identity_len;			wpa_hexdump_ascii(MSG_DEBUG, "permanent identity from "					  "IMSI", identity, identity_len);		} else {			eap_sm_request_identity(sm);			return NULL;		}	}	*len = sizeof(struct eap_hdr) + 1 + identity_len;	resp = os_malloc(*len);	if (resp == NULL)		return NULL;	resp->code = EAP_CODE_RESPONSE;	resp->identifier = id;	resp->length = host_to_be16(*len);	pos = (u8 *) (resp + 1);	*pos++ = EAP_TYPE_IDENTITY;	os_memcpy(pos, identity, identity_len);	return (u8 *) resp;}static void eap_sm_processNotify(struct eap_sm *sm, const u8 *req){	const struct eap_hdr *hdr = (const struct eap_hdr *) req;	const u8 *pos;	char *msg;	size_t i, msg_len;	pos = (const u8 *) (hdr + 1);	pos++;	msg_len = be_to_host16(hdr->length);	if (msg_len < 5)		return;	msg_len -= 5;	wpa_hexdump_ascii(MSG_DEBUG, "EAP: EAP-Request Notification data",			  pos, msg_len);	msg = os_malloc(msg_len + 1);	if (msg == NULL)		return;	for (i = 0; i < msg_len; i++)		msg[i] = isprint(pos[i]) ? (char) pos[i] : '_';	msg[msg_len] = '\0';	wpa_msg(sm->msg_ctx, MSG_INFO, "%s%s",		WPA_EVENT_EAP_NOTIFICATION, msg);	os_free(msg);}static u8 * eap_sm_buildNotify(int id, size_t *len){	struct eap_hdr *resp;	u8 *pos;	wpa_printf(MSG_DEBUG, "EAP: Generating EAP-Response Notification");	*len = sizeof(struct eap_hdr) + 1;	resp = os_malloc(*len);	if (resp == NULL)		return NULL;	resp->code = EAP_CODE_RESPONSE;	resp->identifier = id;	resp->length = host_to_be16(*len);	pos = (u8 *) (resp + 1);	*pos = EAP_TYPE_NOTIFICATION;	return (u8 *) resp;}static void eap_sm_parseEapReq(struct eap_sm *sm, const u8 *req, size_t len){	const struct eap_hdr *hdr;	size_t plen;	const u8 *pos;	sm->rxReq = sm->rxResp = sm->rxSuccess = sm->rxFailure = FALSE;	sm->reqId = 0;	sm->reqMethod = EAP_TYPE_NONE;	sm->reqVendor = EAP_VENDOR_IETF;	sm->reqVendorMethod = EAP_TYPE_NONE;	if (req == NULL || len < sizeof(*hdr))		return;	hdr = (const struct eap_hdr *) req;	plen = be_to_host16(hdr->length);	if (plen > len) {		wpa_printf(MSG_DEBUG, "EAP: Ignored truncated EAP-Packet "

⌨️ 快捷键说明

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