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

📄 ieee802_1x.c

📁 hostapd源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	/* TODO: should probably check MTU from driver config; 2304 is max for	 * IEEE 802.11, but use 1400 to avoid problems with too large packets	 */	if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_FRAMED_MTU, 1400)) {		printf("Could not add Framed-MTU\n");		goto fail;	}	if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT_TYPE,				       RADIUS_NAS_PORT_TYPE_IEEE_802_11)) {		printf("Could not add NAS-Port-Type\n");		goto fail;	}	snprintf(buf, sizeof(buf), "CONNECT 11Mbps 802.11b");	if (!radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO,				 (u8 *) buf, strlen(buf))) {		printf("Could not add Connect-Info\n");		goto fail;	}	if (eap && !radius_msg_add_eap(msg, eap, len)) {		printf("Could not add EAP-Message\n");		goto fail;	}	/* State attribute must be copied if and only if this packet is	 * Access-Request reply to the previous Access-Challenge */	if (sm->last_recv_radius && sm->last_recv_radius->hdr->code ==	    RADIUS_CODE_ACCESS_CHALLENGE) {		int res = radius_msg_copy_attr(msg, sm->last_recv_radius,					       RADIUS_ATTR_STATE);		if (res < 0) {			printf("Could not copy State attribute from previous "			       "Access-Challenge\n");			goto fail;		}		if (res > 0) {			HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,				      "  Copied RADIUS State Attribute\n");		}	}	radius_client_send(hapd->radius, msg, RADIUS_AUTH, sta->addr);	return; fail:	radius_msg_free(msg);	free(msg);}static char *eap_type_text(u8 type){	switch (type) {	case EAP_TYPE_IDENTITY: return "Identity";	case EAP_TYPE_NOTIFICATION: return "Notification";	case EAP_TYPE_NAK: return "Nak";	case EAP_TYPE_MD5: return "MD5-Challenge";	case EAP_TYPE_OTP: return "One-Time Password";	case EAP_TYPE_GTC: return "Generic Token Card";	case EAP_TYPE_TLS: return "TLS";	case EAP_TYPE_TTLS: return "TTLS";	case EAP_TYPE_PEAP: return "PEAP";	default: return "Unknown";	}}static void handle_eap_response(struct hostapd_data *hapd,				struct sta_info *sta, struct eap_hdr *eap,				u8 *data, size_t len){	u8 type;	struct eapol_state_machine *sm = sta->eapol_sm;	if (sm == NULL)		return;	if (eap->identifier != sm->currentId) {		hostapd_logger(hapd, sm->addr, HOSTAPD_MODULE_IEEE8021X,			       HOSTAPD_LEVEL_DEBUG,			       "EAP Identifier of the Response-Identity does "			       "not match (was %d, expected %d) - ignored",			       eap->identifier, sm->currentId);		return;	}	if (len < 1) {		printf("handle_eap_response: too short response data\n");		return;	}	eloop_cancel_timeout(ieee802_1x_eap_timeout, sta, NULL);	free(sm->last_eap_supp);	sm->last_eap_supp_len = sizeof(*eap) + len;	sm->last_eap_supp = (u8 *) malloc(sm->last_eap_supp_len);	if (sm->last_eap_supp == NULL) {		printf("Could not alloc memory for last EAP Response\n");		return;	}	memcpy(sm->last_eap_supp, eap, sizeof(*eap));	memcpy(sm->last_eap_supp + sizeof(*eap), data, len);	type = data[0];	data++;	len--;	hostapd_logger(hapd, sm->addr, HOSTAPD_MODULE_IEEE8021X,		       HOSTAPD_LEVEL_DEBUG, "received EAP packet (code=%d "		       "id=%d len=%d) from STA: EAP Response-%s (%d)",		       eap->code, eap->identifier, ntohs(eap->length),		       eap_type_text(type), type);	if (type == EAP_TYPE_IDENTITY) {		char *buf, *pos;		int i;		buf = malloc(4 * len + 1);		if (buf) {			pos = buf;			for (i = 0; i < len; i++) {				if (data[i] >= 32 && data[i] < 127)					*pos++ = data[i];				else {					snprintf(pos, 5, "{%02x}", data[i]);					pos += 4;				}			}			*pos = '\0';			hostapd_logger(hapd, sm->addr,				       HOSTAPD_MODULE_IEEE8021X,				       HOSTAPD_LEVEL_DEBUG,				       "STA identity '%s'", buf);			free(buf);		}		sm->rx_identity = TRUE;		sm->dot1xAuthEapolRespIdFramesRx++;		/* Save station identity for future RADIUS packets */		free(sm->identity);		sm->identity = malloc(len + 1);		if (sm->identity) {			memcpy(sm->identity, data, len);			sm->identity[len] = '\0';			sm->identity_len = len;		}	} else		sm->dot1xAuthEapolRespFramesRx++;	sm->eapolEap = TRUE;}/* Process incoming EAP packet from Supplicant */static void handle_eap(struct hostapd_data *hapd, struct sta_info *sta,		       u8 *buf, size_t len){	struct eap_hdr *eap;	u16 eap_len;	if (len < sizeof(*eap)) {		printf("   too short EAP packet\n");		return;	}	eap = (struct eap_hdr *) buf;	eap_len = ntohs(eap->length);	HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,		      "   EAP: code=%d identifier=%d length=%d",		      eap->code, eap->identifier, eap_len);	if (eap_len < sizeof(*eap)) {		printf("   Invalid EAP length\n");		return;	} else if (eap_len > len) {		printf("   Too short frame to contain this EAP packet\n");		return;	} else if (eap_len < len) {		printf("   Ignoring %lu extra bytes after EAP packet\n",		       (unsigned long) len - eap_len);	}	eap_len -= sizeof(*eap);	switch (eap->code) {	case EAP_CODE_REQUEST:		HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, " (request)\n");		return;	case EAP_CODE_RESPONSE:		HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, " (response)\n");		handle_eap_response(hapd, sta, eap, (u8 *) (eap + 1), eap_len);		break;	case EAP_CODE_SUCCESS:		HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, " (success)\n");		return;	case EAP_CODE_FAILURE:		HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, " (failure)\n");		return;	default:		HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, " (unknown code)\n");		return;	}}/* Process the EAPOL frames from the Supplicant */void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,			size_t len){	struct sta_info *sta;	struct ieee802_1x_hdr *hdr;	struct ieee802_1x_eapol_key *key;	u16 datalen;	struct rsn_pmksa_cache_entry *pmksa;	if (!hapd->conf->ieee802_1x && !hapd->conf->wpa)		return;	HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,		      "IEEE 802.1X: %lu bytes from " MACSTR "\n",		      (unsigned long) len, MAC2STR(sa));	sta = ap_get_sta(hapd, sa);	if (!sta) {		printf("   no station information available\n");		return;	}	if (len < sizeof(*hdr)) {		printf("   too short IEEE 802.1X packet\n");		return;	}	hdr = (struct ieee802_1x_hdr *) buf;	datalen = ntohs(hdr->length);	HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,		      "   IEEE 802.1X: version=%d type=%d length=%d\n",		      hdr->version, hdr->type, datalen);	if (len - sizeof(*hdr) < datalen) {		printf("   frame too short for this IEEE 802.1X packet\n");		if (sta->eapol_sm)			sta->eapol_sm->dot1xAuthEapLengthErrorFramesRx++;		return;	}	if (len - sizeof(*hdr) > datalen) {		HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,			      "   ignoring %lu extra octets after IEEE 802.1X "			      "packet\n",			      (unsigned long) len - sizeof(*hdr) - datalen);	}	if (sta->eapol_sm) {		sta->eapol_sm->dot1xAuthLastEapolFrameVersion = hdr->version;		sta->eapol_sm->dot1xAuthEapolFramesRx++;	}	key = (struct ieee802_1x_eapol_key *) (hdr + 1);	if (datalen >= sizeof(struct ieee802_1x_eapol_key) &&	    hdr->type == IEEE802_1X_TYPE_EAPOL_KEY &&	    (key->type == EAPOL_KEY_TYPE_WPA ||	     key->type == EAPOL_KEY_TYPE_RSN)) {		wpa_receive(hapd->wpa_auth, sta->wpa_sm, (u8 *) hdr,			    sizeof(*hdr) + datalen);		return;	}	if (!hapd->conf->ieee802_1x ||	    wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_PSK)		return;	if (!sta->eapol_sm) {		sta->eapol_sm = eapol_sm_alloc(hapd, sta);		if (!sta->eapol_sm)			return;	}	/* since we support version 1, we can ignore version field and proceed	 * as specified in version 1 standard [IEEE Std 802.1X-2001, 7.5.5] */	/* TODO: actually, we are not version 1 anymore.. However, Version 2	 * does not change frame contents, so should be ok to process frames	 * more or less identically. Some changes might be needed for	 * verification of fields. */	switch (hdr->type) {	case IEEE802_1X_TYPE_EAP_PACKET:		handle_eap(hapd, sta, (u8 *) (hdr + 1), datalen);		break;	case IEEE802_1X_TYPE_EAPOL_START:		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,			       HOSTAPD_LEVEL_DEBUG, "received EAPOL-Start "			       "from STA");		pmksa = wpa_auth_sta_get_pmksa(sta->wpa_sm);		if (pmksa) {			hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,				       HOSTAPD_LEVEL_DEBUG, "cached PMKSA "				       "available - ignore it since "				       "STA sent EAPOL-Start");			wpa_auth_sta_clear_pmksa(sta->wpa_sm, pmksa);		}		sta->eapol_sm->eapolStart = TRUE;		sta->eapol_sm->dot1xAuthEapolStartFramesRx++;		wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH_EAPOL);		break;	case IEEE802_1X_TYPE_EAPOL_LOGOFF:		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,			       HOSTAPD_LEVEL_DEBUG, "received EAPOL-Logoff "			       "from STA");		sta->acct_terminate_cause =			RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;		sta->eapol_sm->eapolLogoff = TRUE;		sta->eapol_sm->dot1xAuthEapolLogoffFramesRx++;		break;	case IEEE802_1X_TYPE_EAPOL_KEY:		HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "   EAPOL-Key\n");		if (!(sta->flags & WLAN_STA_AUTHORIZED)) {			printf("   Dropped key data from unauthorized "			       "Supplicant\n");			break;		}		break;	case IEEE802_1X_TYPE_EAPOL_ENCAPSULATED_ASF_ALERT:		HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,			      "   EAPOL-Encapsulated-ASF-Alert\n");		/* TODO: implement support for this; show data */		break;	default:		HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL,			      "   unknown IEEE 802.1X packet type\n");		sta->eapol_sm->dot1xAuthInvalidEapolFramesRx++;		break;	}	eapol_sm_step(sta->eapol_sm);}void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta){	struct rsn_pmksa_cache_entry *pmksa;	if (!hapd->conf->ieee802_1x ||	    wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_PSK)		return;	if (sta->eapol_sm == NULL) {		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,			       HOSTAPD_LEVEL_DEBUG, "start authentication");		sta->eapol_sm = eapol_sm_alloc(hapd, sta);		if (sta->eapol_sm == NULL) {			hostapd_logger(hapd, sta->addr,				       HOSTAPD_MODULE_IEEE8021X,				       HOSTAPD_LEVEL_INFO,				       "failed to allocate state machine");			return;		}	}	sta->eapol_sm->portEnabled = TRUE;	pmksa = wpa_auth_sta_get_pmksa(sta->wpa_sm);	if (pmksa) {		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,			       HOSTAPD_LEVEL_DEBUG,			       "PMK from PMKSA cache - skip IEEE 802.1X/EAP");		/* Setup EAPOL state machines to already authenticated state		 * because of existing PMKSA information in the cache. */		sta->eapol_sm->keyRun = TRUE;		sta->eapol_sm->keyAvailable = TRUE;		sta->eapol_sm->auth_pae_state = AUTH_PAE_AUTHENTICATING;		sta->eapol_sm->be_auth_state = BE_AUTH_SUCCESS;		sta->eapol_sm->authSuccess = TRUE;		if (sta->eapol_sm->eap)			eap_sm_notify_cached(sta->eapol_sm->eap);		pmksa_cache_to_eapol_data(pmksa, sta->eapol_sm);	} else		eapol_sm_step(sta->eapol_sm);}void ieee802_1x_free_radius_class(struct radius_class_data *class){	int i;	if (class == NULL)		return;	for (i = 0; i < class->count; i++)		free(class->attr[i].data);	free(class->attr);	class->attr = NULL;	class->count = 0;}int ieee802_1x_copy_radius_class(struct radius_class_data *dst,				 struct radius_class_data *src){	size_t i;	if (src->attr == NULL)		return 0;	dst->attr = wpa_zalloc(src->count * sizeof(struct radius_attr_data));	if (dst->attr == NULL)		return -1;	dst->count = 0;	for (i = 0; i < src->count; i++) {		dst->attr[i].data = malloc(src->attr[i].len);		if (dst->attr[i].data == NULL)			break;		dst->count++;		memcpy(dst->attr[i].data, src->attr[i].data, src->attr[i].len);		dst->attr[i].len = src->attr[i].len;	}	return 0;}void ieee802_1x_free_station(struct sta_info *sta){	struct eapol_state_machine *sm = sta->eapol_sm;	eloop_cancel_timeout(ieee802_1x_eap_timeout, sta, NULL);	if (sm == NULL)		return;	sta->eapol_sm = NULL;	if (sm->last_recv_radius) {		radius_msg_free(sm->last_recv_radius);		free(sm->last_recv_radius);	}	free(sm->last_eap_supp);	free(sm->last_eap_radius);	free(sm->identity);	ieee802_1x_free_radius_class(&sm->radius_class);	free(sm->eapol_key_sign);	free(sm->eapol_key_crypt);	eapol_sm_free(sm);}

⌨️ 快捷键说明

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