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

📄 eap.c

📁 最新的Host AP 新添加了许多pcmcia 的驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
	 * RFC 4137 require that reqId == lastId. In addition, it looks like	 * Ringmaster v2.1.2.0 would be using lastId + 2 in EAP-Success.	 *	 * Accept this kind of Id if EAP workarounds are enabled. These are	 * unauthenticated plaintext messages, so this should have minimal	 * security implications (bit easier to fake EAP-Success/Failure).	 */	if (sm->workaround && (reqId == ((lastId + 1) & 0xff) ||			       reqId == ((lastId + 2) & 0xff))) {		wpa_printf(MSG_DEBUG, "EAP: Workaround for unexpected "			   "identifier field in EAP Success: "			   "reqId=%d lastId=%d (these are supposed to be "			   "same)", reqId, lastId);		return 1;	}	wpa_printf(MSG_DEBUG, "EAP: EAP-Success Id mismatch - reqId=%d "		   "lastId=%d", reqId, lastId);	return 0;}/* * RFC 4137 - Appendix A.1: EAP Peer State Machine - State transitions */static void eap_peer_sm_step_idle(struct eap_sm *sm){	/*	 * 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);}static int eap_peer_req_is_duplicate(struct eap_sm *sm){	int duplicate;	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;	}	return duplicate;}static void eap_peer_sm_step_received(struct eap_sm *sm){	int duplicate = eap_peer_req_is_duplicate(sm);	/*	 * 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);}static void eap_peer_sm_step_local(struct eap_sm *sm){	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:		eap_peer_sm_step_idle(sm);		break;	case EAP_RECEIVED:		eap_peer_sm_step_received(sm);		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;	}}SM_STEP(EAP){	/* Global transitions */	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 {		/* Local transitions */		eap_peer_sm_step_local(sm);	}}static Boolean eap_sm_allowMethod(struct eap_sm *sm, int vendor,				  EapType method){	if (!eap_allowed_method(sm, vendor, method)) {		wpa_printf(MSG_DEBUG, "EAP: configuration does not allow: "			   "vendor %u method %u", vendor, method);		return FALSE;	}	if (eap_peer_get_eap_method(vendor, method))		return TRUE;	wpa_printf(MSG_DEBUG, "EAP: not included in build: "		   "vendor %u method %u", vendor, method);	return FALSE;}static struct wpabuf * eap_sm_build_expanded_nak(	struct eap_sm *sm, int id, const struct eap_method *methods,	size_t count){	struct wpabuf *resp;	int found = 0;	const struct eap_method *m;	wpa_printf(MSG_DEBUG, "EAP: Building expanded EAP-Nak");	/* RFC 3748 - 5.3.2: Expanded Nak */	resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_EXPANDED,			     8 + 8 * (count + 1), EAP_CODE_RESPONSE, id);	if (resp == NULL)		return NULL;	wpabuf_put_be24(resp, EAP_VENDOR_IETF);	wpabuf_put_be32(resp, EAP_TYPE_NAK);	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 (eap_allowed_method(sm, m->vendor, m->method)) {			wpa_printf(MSG_DEBUG, "EAP: allowed type: "				   "vendor=%u method=%u",				   m->vendor, m->method);			wpabuf_put_u8(resp, EAP_TYPE_EXPANDED);			wpabuf_put_be24(resp, m->vendor);			wpabuf_put_be32(resp, m->method);			found++;		}	}	if (!found) {		wpa_printf(MSG_DEBUG, "EAP: no more allowed methods");		wpabuf_put_u8(resp, EAP_TYPE_EXPANDED);		wpabuf_put_be24(resp, EAP_VENDOR_IETF);		wpabuf_put_be32(resp, EAP_TYPE_NONE);	}	eap_update_len(resp);	return resp;}static struct wpabuf * eap_sm_buildNak(struct eap_sm *sm, int id){	struct wpabuf *resp;	u8 *start;	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, methods, count);	/* RFC 3748 - 5.3.1: Legacy Nak */	resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_NAK,			     sizeof(struct eap_hdr) + 1 + count + 1,			     EAP_CODE_RESPONSE, id);	if (resp == NULL)		return NULL;	start = wpabuf_put(resp, 0);	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 (eap_allowed_method(sm, m->vendor, m->method)) {			if (m->vendor != EAP_VENDOR_IETF) {				if (expanded_found)					continue;				expanded_found = 1;				wpabuf_put_u8(resp, EAP_TYPE_EXPANDED);			} else				wpabuf_put_u8(resp, m->method);			found++;		}	}	if (!found)		wpabuf_put_u8(resp, EAP_TYPE_NONE);	wpa_hexdump(MSG_DEBUG, "EAP: allowed methods", start, found);	eap_update_len(resp);	return resp;}static void eap_sm_processIdentity(struct eap_sm *sm, const struct wpabuf *req){	const struct eap_hdr *hdr = wpabuf_head(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 eap_peer_config *conf){	int aka = 0;	char imsi[100];	size_t imsi_len;	struct eap_method_type *m = conf->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(conf->identity);	conf->identity = os_malloc(1 + imsi_len);	if (conf->identity == NULL) {		wpa_printf(MSG_WARNING, "Failed to allocate buffer for "			   "IMSI-based identity");		return -1;	}	conf->identity[0] = aka ? '0' : '1';	os_memcpy(conf->identity + 1, imsi, imsi_len);	conf->identity_len = 1 + imsi_len;	return 0;}#endif /* PCSC_FUNCS */static int eap_sm_set_scard_pin(struct eap_sm *sm,				struct eap_peer_config *conf){#ifdef PCSC_FUNCS	if (scard_set_pin(sm->scard_ctx, conf->pin)) {		/*		 * Make sure the same PIN is not tried again in order to avoid		 * blocking SIM.		 */		os_free(conf->pin);		conf->pin = NULL;		wpa_printf(MSG_WARNING, "PIN validation failed");		eap_sm_request_pin(sm);		return -1;	}	return 0;#else /* PCSC_FUNCS */	return -1;#endif /* PCSC_FUNCS */}static int eap_sm_get_scard_identity(struct eap_sm *sm,				     struct eap_peer_config *conf){#ifdef PCSC_FUNCS	if (eap_sm_set_scard_pin(sm, conf))		return -1;	return eap_sm_imsi_identity(sm, conf);#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_peer_sm_init() * @id: EAP identifier for the packet * @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. */struct wpabuf * eap_sm_buildIdentity(struct eap_sm *sm, int id, int encrypted){	struct eap_peer_config *config = eap_get_config(sm);	struct wpabuf *resp;	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;		}	} else if (config->pcsc) {		if (eap_sm_set_scard_pin(sm, config) < 0)			return NULL;	}	resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, identity_len,			     EAP_CODE_RESPONSE, id);	if (resp == NULL)		return NULL;	wpabuf_put_data(resp, identity, identity_len);	return resp;}static void eap_sm_processNotify(struct eap_sm *sm, const struct wpabuf *req){	const u8 *pos;	char *msg;	size_t i, msg_len;	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_NOTIFICATION, req,			       &msg_len);	if (pos == NULL)		return;	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] : '_';

⌨️ 快捷键说明

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