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

📄 eap.c

📁 hostapd无线AP工具
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * hostapd / EAP Standalone Authenticator state machine * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */#include <stdlib.h>#include <stdio.h>#include <unistd.h>#include <netinet/in.h>#include <string.h>#include <sys/socket.h>#include "hostapd.h"#include "eloop.h"#include "sta_info.h"#include "eap_i.h"#define EAP_MAX_AUTH_ROUNDS 50extern const struct eap_method eap_method_identity;#ifdef EAP_MD5extern const struct eap_method eap_method_md5;#endif /* EAP_MD5 */#ifdef EAP_TLSextern const struct eap_method eap_method_tls;#endif /* EAP_TLS */#ifdef EAP_MSCHAPv2extern const struct eap_method eap_method_mschapv2;#endif /* EAP_MSCHAPv2 */#ifdef EAP_PEAPextern const struct eap_method eap_method_peap;#endif /* EAP_PEAP */#ifdef EAP_TLVextern const struct eap_method eap_method_tlv;#endif /* EAP_TLV */#ifdef EAP_GTCextern const struct eap_method eap_method_gtc;#endif /* EAP_GTC */#ifdef EAP_TTLSextern const struct eap_method eap_method_ttls;#endif /* EAP_TTLS */#ifdef EAP_SIMextern const struct eap_method eap_method_sim;#endif /* EAP_SIM */#ifdef EAP_PAXextern const struct eap_method eap_method_pax;#endif /* EAP_PAX */static const struct eap_method *eap_methods[] ={	&eap_method_identity,#ifdef EAP_MD5	&eap_method_md5,#endif /* EAP_MD5 */#ifdef EAP_TLS	&eap_method_tls,#endif /* EAP_TLS */#ifdef EAP_MSCHAPv2	&eap_method_mschapv2,#endif /* EAP_MSCHAPv2 */#ifdef EAP_PEAP	&eap_method_peap,#endif /* EAP_PEAP */#ifdef EAP_TTLS	&eap_method_ttls,#endif /* EAP_TTLS */#ifdef EAP_TLV	&eap_method_tlv,#endif /* EAP_TLV */#ifdef EAP_GTC	&eap_method_gtc,#endif /* EAP_GTC */#ifdef EAP_SIM	&eap_method_sim,#endif /* EAP_SIM */#ifdef EAP_PAX	&eap_method_pax,#endif /* EAP_PAX */};#define NUM_EAP_METHODS (sizeof(eap_methods) / sizeof(eap_methods[0]))const struct eap_method * eap_sm_get_eap_methods(int method){	int i;	for (i = 0; i < NUM_EAP_METHODS; i++) {		if (eap_methods[i]->method == method)			return eap_methods[i];	}	return NULL;}static void eap_user_free(struct eap_user *user);/* EAP state machines are described in draft-ietf-eap-statemachine-05.txt */static int eap_sm_calculateTimeout(struct eap_sm *sm, int retransCount,				   int eapSRTT, int eapRTTVAR,				   int methodTimeout);static void eap_sm_parseEapResp(struct eap_sm *sm, u8 *resp, size_t len);static u8 * eap_sm_buildSuccess(struct eap_sm *sm, int id, size_t *len);static u8 * eap_sm_buildFailure(struct eap_sm *sm, int id, size_t *len);static int eap_sm_nextId(struct eap_sm *sm, int id);static void eap_sm_Policy_update(struct eap_sm *sm, u8 *nak_list, size_t len);static EapType eap_sm_Policy_getNextMethod(struct eap_sm *sm);static int eap_sm_Policy_getDecision(struct eap_sm *sm);static Boolean eap_sm_Policy_doPickUp(struct eap_sm *sm, EapType method);/* Definitions for clarifying state machine implementation */#define SM_STATE(machine, state) \static void sm_ ## machine ## _ ## state ## _Enter(struct eap_sm *sm, \	int global)#define SM_ENTRY(machine, state) \if (!global || sm->machine ## _state != machine ## _ ## state) { \	sm->changed = TRUE; \	wpa_printf(MSG_DEBUG, "EAP: " #machine " entering state " #state); \} \sm->machine ## _state = machine ## _ ## state;#define SM_ENTER(machine, state) \sm_ ## machine ## _ ## state ## _Enter(sm, 0)#define SM_ENTER_GLOBAL(machine, state) \sm_ ## machine ## _ ## state ## _Enter(sm, 1)#define SM_STEP(machine) \static void sm_ ## machine ## _Step(struct eap_sm *sm)#define SM_STEP_RUN(machine) sm_ ## machine ## _Step(sm)static Boolean eapol_get_bool(struct eap_sm *sm, enum eapol_bool_var var){	return sm->eapol_cb->get_bool(sm->eapol_ctx, var);}static void eapol_set_bool(struct eap_sm *sm, enum eapol_bool_var var,			   Boolean value){	sm->eapol_cb->set_bool(sm->eapol_ctx, var, value);}static void eapol_set_eapReqData(struct eap_sm *sm,				 const u8 *eapReqData, size_t eapReqDataLen){	wpa_hexdump(MSG_MSGDUMP, "EAP: eapReqData -> EAPOL",		    sm->eapReqData, sm->eapReqDataLen);	sm->eapol_cb->set_eapReqData(sm->eapol_ctx, eapReqData, eapReqDataLen);}static void eapol_set_eapKeyData(struct eap_sm *sm,				 const u8 *eapKeyData, size_t eapKeyDataLen){	wpa_hexdump(MSG_MSGDUMP, "EAP: eapKeyData -> EAPOL",		    sm->eapKeyData, sm->eapKeyDataLen);	sm->eapol_cb->set_eapKeyData(sm->eapol_ctx, eapKeyData, eapKeyDataLen);}int eap_user_get(struct eap_sm *sm, const u8 *identity, size_t identity_len,		 int phase2){	struct eap_user *user;	if (sm == NULL || sm->eapol_cb == NULL ||	    sm->eapol_cb->get_eap_user == NULL)		return -1;	eap_user_free(sm->user);	sm->user = NULL;	user = malloc(sizeof(*user));	if (user == NULL)	    return -1;	memset(user, 0, sizeof(*user));	if (sm->eapol_cb->get_eap_user(sm->eapol_ctx, identity,				       identity_len, phase2, user) != 0) {		eap_user_free(user);		return -1;	}	sm->user = user;	sm->user_eap_method_index = 0;	return 0;}SM_STATE(EAP, DISABLED){	SM_ENTRY(EAP, DISABLED);	sm->num_rounds = 0;}SM_STATE(EAP, INITIALIZE){	SM_ENTRY(EAP, INITIALIZE);	sm->currentId = -1;	eapol_set_bool(sm, EAPOL_eapSuccess, FALSE);	eapol_set_bool(sm, EAPOL_eapFail, FALSE);	eapol_set_bool(sm, EAPOL_eapTimeout, FALSE);	free(sm->eapKeyData);	sm->eapKeyData = NULL;	sm->eapKeyDataLen = 0;	/* eapKeyAvailable = FALSE */	eapol_set_bool(sm, EAPOL_eapRestart, FALSE);	/* This is not defined in draft-ietf-eap-statemachine-05.txt, but	 * method state needs to be reseted here so that it does not remain in	 * success state when re-authentication starts. */	if (sm->m && sm->eap_method_priv) {		sm->m->reset(sm, sm->eap_method_priv);		sm->eap_method_priv = NULL;	}	sm->m = NULL;	sm->user_eap_method_index = 0;	if (sm->backend_auth) {		sm->currentMethod = EAP_TYPE_NONE;		/* parse rxResp, respId, respMethod */		eap_sm_parseEapResp(sm, sm->eapRespData, sm->eapRespDataLen);		if (sm->rxResp) {			sm->currentId = sm->respId;		}	}	sm->num_rounds = 0;}SM_STATE(EAP, PICK_UP_METHOD){	SM_ENTRY(EAP, PICK_UP_METHOD);	if (eap_sm_Policy_doPickUp(sm, sm->respMethod)) {		sm->currentMethod = sm->respMethod;		if (sm->m && sm->eap_method_priv) {			sm->m->reset(sm, sm->eap_method_priv);			sm->eap_method_priv = NULL;		}		sm->m = eap_sm_get_eap_methods(sm->currentMethod);		if (sm->m && sm->m->initPickUp) {			sm->eap_method_priv = sm->m->initPickUp(sm);			if (sm->eap_method_priv == NULL) {				wpa_printf(MSG_DEBUG, "EAP: Failed to "					   "initialize EAP method %d",					   sm->currentMethod);				sm->m = NULL;				sm->currentMethod = EAP_TYPE_NONE;			}		} else {			sm->m = NULL;			sm->currentMethod = EAP_TYPE_NONE;		}	}}SM_STATE(EAP, IDLE){	SM_ENTRY(EAP, IDLE);	sm->retransWhile = eap_sm_calculateTimeout(sm, sm->retransCount,						   sm->eapSRTT, sm->eapRTTVAR,						   sm->methodTimeout);}SM_STATE(EAP, RETRANSMIT){	SM_ENTRY(EAP, RETRANSMIT);	/* TODO: Is this needed since EAPOL state machines take care of	 * retransmit? */}SM_STATE(EAP, RECEIVED){	SM_ENTRY(EAP, RECEIVED);	/* parse rxResp, respId, respMethod */	eap_sm_parseEapResp(sm, sm->eapRespData, sm->eapRespDataLen);	sm->num_rounds++;}SM_STATE(EAP, DISCARD){	SM_ENTRY(EAP, DISCARD);	eapol_set_bool(sm, EAPOL_eapResp, FALSE);	eapol_set_bool(sm, EAPOL_eapNoReq, TRUE);}SM_STATE(EAP, SEND_REQUEST){	SM_ENTRY(EAP, SEND_REQUEST);	sm->retransCount = 0;	if (sm->eapReqData) {		eapol_set_eapReqData(sm, sm->eapReqData, sm->eapReqDataLen);		free(sm->lastReqData);		sm->lastReqData = sm->eapReqData;		sm->lastReqDataLen = sm->eapReqDataLen;		sm->eapReqData = NULL;		sm->eapReqDataLen = 0;		eapol_set_bool(sm, EAPOL_eapResp, FALSE);		eapol_set_bool(sm, EAPOL_eapReq, TRUE);	} else {		wpa_printf(MSG_INFO, "EAP: SEND_REQUEST - no eapReqData");		eapol_set_bool(sm, EAPOL_eapResp, FALSE);		eapol_set_bool(sm, EAPOL_eapReq, FALSE);		eapol_set_bool(sm, EAPOL_eapNoReq, TRUE);	}}SM_STATE(EAP, INTEGRITY_CHECK){	SM_ENTRY(EAP, INTEGRITY_CHECK);	if (sm->m->check) {		sm->ignore = sm->m->check(sm, sm->eap_method_priv,					  sm->eapRespData, sm->eapRespDataLen);	}}SM_STATE(EAP, METHOD_REQUEST){	SM_ENTRY(EAP, METHOD_REQUEST);	if (sm->m == NULL) {		wpa_printf(MSG_DEBUG, "EAP: method not initialized");		return;	}	sm->currentId = eap_sm_nextId(sm, sm->currentId);	wpa_printf(MSG_DEBUG, "EAP: building EAP-Request: Identifier %d",		   sm->currentId);	sm->lastId = sm->currentId;	free(sm->eapReqData);	sm->eapReqData = sm->m->buildReq(sm, sm->eap_method_priv,					 sm->currentId, &sm->eapReqDataLen);	if (sm->m->getTimeout)		sm->methodTimeout = sm->m->getTimeout(sm, sm->eap_method_priv);	else		sm->methodTimeout = 0;}SM_STATE(EAP, METHOD_RESPONSE){	SM_ENTRY(EAP, METHOD_RESPONSE);	sm->m->process(sm, sm->eap_method_priv, sm->eapRespData,		       sm->eapRespDataLen);	if (sm->m->isDone(sm, sm->eap_method_priv)) {		eap_sm_Policy_update(sm, NULL, 0);		free(sm->eapKeyData);		if (sm->m->getKey) {			sm->eapKeyData = sm->m->getKey(sm, sm->eap_method_priv,						       &sm->eapKeyDataLen);		} else {			sm->eapKeyData = NULL;			sm->eapKeyDataLen = 0;		}		sm->methodState = METHOD_END;	} else {		sm->methodState = METHOD_CONTINUE;	}}SM_STATE(EAP, PROPOSE_METHOD){	SM_ENTRY(EAP, PROPOSE_METHOD);	sm->currentMethod = eap_sm_Policy_getNextMethod(sm);	if (sm->m && sm->eap_method_priv) {		sm->m->reset(sm, sm->eap_method_priv);		sm->eap_method_priv = NULL;	}	sm->m = eap_sm_get_eap_methods(sm->currentMethod);	if (sm->m) {		sm->eap_method_priv = sm->m->init(sm);		if (sm->eap_method_priv == NULL) {			wpa_printf(MSG_DEBUG, "EAP: Failed to initialize EAP "				   "method %d", sm->currentMethod);			sm->m = NULL;			sm->currentMethod = EAP_TYPE_NONE;		}	}	if (sm->currentMethod == EAP_TYPE_IDENTITY ||	    sm->currentMethod == EAP_TYPE_NOTIFICATION)		sm->methodState = METHOD_CONTINUE;	else		sm->methodState = METHOD_PROPOSED;}SM_STATE(EAP, NAK){	struct eap_hdr *nak;	size_t len = 0;	u8 *pos, *nak_list = NULL;	SM_ENTRY(EAP, NAK);	if (sm->eap_method_priv) {		sm->m->reset(sm, sm->eap_method_priv);		sm->eap_method_priv = NULL;	}	sm->m = NULL;	nak = (struct eap_hdr *) sm->eapRespData;	if (nak && sm->eapRespDataLen > sizeof(*nak)) {		len = ntohs(nak->length);		if (len > sm->eapRespDataLen)			len = sm->eapRespDataLen;		pos = (u8 *) (nak + 1);		len -= sizeof(*nak);		if (*pos == EAP_TYPE_NAK) {			pos++;			len--;			nak_list = pos;		}	}	eap_sm_Policy_update(sm, nak_list, len);}SM_STATE(EAP, SELECT_ACTION){	SM_ENTRY(EAP, SELECT_ACTION);	sm->decision = eap_sm_Policy_getDecision(sm);}SM_STATE(EAP, TIMEOUT_FAILURE){	SM_ENTRY(EAP, TIMEOUT_FAILURE);	eapol_set_bool(sm, EAPOL_eapTimeout, TRUE);}SM_STATE(EAP, FAILURE){	SM_ENTRY(EAP, FAILURE);	free(sm->eapReqData);

⌨️ 快捷键说明

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