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

📄 eap.c

📁 RADIUS 服务器介绍 RADIUS服务器支持标准的RADIUS协议
💻 C
📖 第 1 页 / 共 2 页
字号:
	eap_packet = (eap_packet_t *)reply->packet;	memcpy(&eap_len, &(eap_packet->length), sizeof(uint16_t));	len = eap_len = ntohs(eap_len);	ptr = (unsigned char *)eap_packet;	do {		if (eap_len > 253) {			len = 253;			eap_len -= 253;		} else {			len = eap_len;			eap_len = 0;		}		/* 		 * create a value pair & append it to the request reply list		 * This memory gets freed up when request is freed up		 */		eap_msg = paircreate(PW_EAP_MESSAGE, PW_TYPE_OCTETS);		memcpy(eap_msg->strvalue, ptr, len);		eap_msg->length = len;		pairadd(&(request->reply->vps), eap_msg);		ptr += len;		eap_msg = NULL;	} while (eap_len);	/*	 *	EAP-Message is always associated with	 *	Message-Authenticator but not vice-versa.	 *	 *	Don't add a Message-Authenticator if it's already	 *	there.	 */	vp = pairfind(request->reply->vps, PW_MESSAGE_AUTHENTICATOR);	if (!vp) {		vp = paircreate(PW_MESSAGE_AUTHENTICATOR, PW_TYPE_OCTETS);		memset(vp->strvalue, 0, AUTH_VECTOR_LEN);		vp->length = AUTH_VECTOR_LEN;		pairadd(&(request->reply->vps), vp);	}	/*	 * Generate State, only if it not Identity request	 */ 	if ((eap_packet->code == PW_EAP_REQUEST) &&	    (eap_packet->data[0] >= PW_EAP_MD5)) {		vp = generate_state();		pairadd(&(request->reply->vps), vp);	}			/* Set request reply code, but only if it's not already set. */	if (!request->reply->code) switch(reply->code) {	case PW_EAP_RESPONSE:	case PW_EAP_SUCCESS:		request->reply->code = PW_AUTHENTICATION_ACK;		break;	case PW_EAP_FAILURE:		request->reply->code = PW_AUTHENTICATION_REJECT;		break;	case PW_EAP_REQUEST:		request->reply->code = PW_ACCESS_CHALLENGE;		break;	default:		/* Should never enter here */		radlog(L_ERR, "rlm_eap: reply code %d is unknown, Rejecting the request.", reply->code);		request->reply->code = PW_AUTHENTICATION_REJECT;		break;	}	return 0;}/* * Radius criteria, EAP-Message is invalid without Message-Authenticator * For EAP_START, send Access-Challenge with EAP Identity request. */int eap_start(REQUEST *request){	VALUE_PAIR *vp;	VALUE_PAIR *eap_msg;	EAP_DS *eapstart;	eap_msg = pairfind(request->packet->vps, PW_EAP_MESSAGE);	if (eap_msg == NULL) {		radlog(L_ERR, "rlm_eap: EAP-Message not found");		return EAP_NOOP;	}	/*	 *  http://www.freeradius.org/rfc/rfc2869.html#EAP-Message	 */	vp = pairfind(request->packet->vps, PW_MESSAGE_AUTHENTICATOR);	if (!vp) {		radlog(L_ERR, "rlm_eap: EAP-Message without Message-Authenticator: Ignoring the request due to RFC 2869 Section 5.13 requirements");		return EAP_NOOP;	}	if ((eap_msg->strvalue[0] == 0) ||	    (eap_msg->strvalue[0] > PW_EAP_MAX_TYPES)) {		DEBUG2("  rlm_eap: Unknown EAP packet");	} else {		DEBUG2("  rlm_eap: EAP packet type %s id %d length %d",		       eap_types[eap_msg->strvalue[0]],		       eap_msg->strvalue[1],		       (eap_msg->strvalue[2] << 8) | eap_msg->strvalue[3]);	}	/*	 *	If we've been configured to proxy, do nothing.	 *	 *	Note that we don't check if the realm is local.	 *	We figure that anyone bright enough to add	 *	Proxy-To-Realm is bright enough to NOT do so	 *	when it's a local realm.	 */	if (pairfind(request->config_items, PW_PROXY_TO_REALM) != NULL) {	  	return EAP_NOOP;	}	/*	 *	Not a start message.  Don't start anything.	 *	 *	Later EAP messages are longer than the 'start' message,	 *	so this function returns 'no start found', so that	 *	the rest of the EAP code can use the State attribute	 *	to match this EAP-Message to an ongoing conversation.	 */	if (eap_msg->length != EAP_START) {		DEBUG2("  rlm_eap: EAP Start not found");		return EAP_NOTFOUND;	}	DEBUG2("  rlm_eap: Got EAP_START message");	if ((eapstart = eap_ds_alloc()) == NULL) {		DEBUG2("  rlm_eap: EAP Start failed in allocation");		return EAP_FAIL;	}	/*	 *	Hmm... why isn't this taken from the eap_msg?	 */	eapstart->request->code = PW_EAP_REQUEST;	eapstart->request->type.type = PW_EAP_IDENTITY;	eap_compose(request, eapstart);	eap_ds_free(&eapstart);	return EAP_FOUND;}/* * compose EAP FAILURE packet in EAP-Message */void eap_fail(REQUEST *request, EAP_DS *eap_ds){	eap_ds->request->code = PW_EAP_FAILURE;	eap_compose(request, eap_ds);}/* * compose EAP SUCCESS packet in EAP-Message */void eap_success(REQUEST *request, EAP_DS *eap_ds){	eap_ds->request->code = PW_EAP_SUCCESS;	eap_compose(request, eap_ds);}/* * Basic EAP packet verfications & validations */int eap_validation(eap_packet_t *eap_packet){	uint16_t len;	memcpy(&len, eap_packet->length, sizeof(uint16_t));	len = ntohs(len);	/* High level EAP packet checks */	if ((len <= EAP_HEADER_LEN) || 	    ((eap_packet->code != PW_EAP_RESPONSE) && 	     (eap_packet->code != PW_EAP_REQUEST)) ||	    (eap_packet->data[0] <= 0) ||	    (eap_packet->data[0] > PW_EAP_MAX_TYPES)) {		radlog(L_AUTH, "rlm_eap: Incorrect EAP Message, "				"Ignoring the packet");		return EAP_INVALID;	}	/* we don't expect notification, but we send it */	if (eap_packet->data[0] == PW_EAP_NOTIFICATION) {		radlog(L_AUTH, "rlm_eap: Got NOTIFICATION, "				"Ignoring the packet");		return EAP_INVALID;	}	return EAP_VALID;}/* *  Get the user Identity if at all it is available with us. */VALUE_PAIR *eap_useridentity(EAP_HANDLER *list, eap_packet_t *eap_packet, unsigned char id[]){	char *un;	VALUE_PAIR *username;	EAP_HANDLER *handler;	if ((un = eap_identity(eap_packet)) != NULL) {		username = pairmake("User-Name", un, T_OP_EQ);		free(un);		return username;	}	/* Get the handler from the list, if present */	handler = eaplist_findhandler(list, id);	if (handler)		return pairmake("User-Name", handler->identity, T_OP_EQ);	return NULL;}/* *  Get the user Identity only from EAP-Identity packets */char *eap_identity(eap_packet_t *eap_packet){	int size;	uint16_t len;	char *identity;	if ((eap_packet == NULL) ||		(eap_packet->code != PW_EAP_RESPONSE) ||		(eap_packet->data[0] != PW_EAP_IDENTITY)) {		return NULL;	}	memcpy(&len, eap_packet->length, sizeof(uint16_t));	len = ntohs(len);	if ((len <= 5) || (eap_packet->data[1] == 0x00)) {		radlog(L_ERR, "rlm_eap: UserIdentity Unknown ");		return NULL;	}	size = len - 5;	identity = (char *)malloc(size + 1);	if (identity == NULL) {		radlog(L_ERR, "rlm_eap: out of memory");		return NULL;	}	memcpy(identity, &eap_packet->data[1], size);	identity[size] = '\0';	return identity;}/* * Create our Request-Response data structure with the eap packet */static EAP_DS *eap_buildds(eap_packet_t **eap_packet_p){	EAP_DS *eap_ds = NULL;	eap_packet_t	*eap_packet = NULL;	int typelen;	uint16_t len;	eap_packet = *eap_packet_p;	if (eap_packet == NULL) {		return NULL;	}	if ((eap_ds = eap_ds_alloc()) == NULL) {		return NULL;	}	eap_ds->response->packet = (unsigned char *)eap_packet;        eap_ds->response->code = eap_packet->code;        eap_ds->response->id = eap_packet->id;        eap_ds->response->type.type = eap_packet->data[0];	memcpy(&len, eap_packet->length, sizeof(uint16_t));	len = ntohs(len);	eap_ds->response->length = len;	/* First byte in eap_packet->data is *EAP-Type* */	/*	 * First 5 bytes, in eap, are code+id+length(2)+type	 * The rest is TypeData	 * skip *type* while getting typedata from data	 */	typelen = len - 5/*code+id+length+type*/;	if (typelen > 0) {		/*		 * Since packet contians the complete eap_packet, 		 * typedata will be a ptr in packet to its typedata		 */		eap_ds->response->type.data = eap_ds->response->packet + 5/*code+id+length+type*/;		eap_ds->response->type.length = typelen;	} else {		eap_ds->response->type.length = 0;		eap_ds->response->type.data = NULL;	}	*eap_packet_p = NULL;	return eap_ds;}/* * If identity response then create a fresh handler & fill the identity * else handler MUST be in our list, get that. * This handler creation cannot fail * * username contains REQUEST->username which might have been stripped. * identity contains the one sent in EAP-Identity response */EAP_HANDLER *eap_handler(EAP_HANDLER **list, eap_packet_t **eap_packet_p, REQUEST *request){	EAP_HANDLER	*handler = NULL;	unsigned char	*unique;	eap_packet_t	*eap_packet = NULL;	eap_packet = *eap_packet_p;	if (eap_validation(eap_packet) == EAP_INVALID) {		return NULL;	}	/*	 * EAP_HANDLER MUST be found in the list if it is not EAP-Identity response	 */	if (eap_packet->data[0] != PW_EAP_IDENTITY) {		unique = eap_regenerateid(request, eap_packet->id);		if (unique == NULL) {			return NULL;		}		handler = eaplist_isreply(list, unique);		free(unique);		unique = NULL;		if (handler == NULL) {			/* Either send EAP_Identity or EAP-Fail */			radlog(L_ERR, "rlm_eap: Either EAP-request timed out OR"				" EAP-response to an unknown EAP-request");			return NULL;		}	} else {		handler = eap_handler_alloc();		if (handler == NULL) {			radlog(L_ERR, "rlm_eap: out of memory");			return NULL;		}		handler->id = NULL;		handler->prev_eapds = NULL;		handler->eap_ds = NULL;		handler->configured = NULL;		handler->opaque = NULL;		handler->free_opaque = NULL;		handler->next = NULL;		handler->identity = eap_identity(eap_packet);		if (handler->identity == NULL) {			radlog(L_ERR, "rlm_eap: Identity Unknown, authentication failed");			eap_handler_free(&handler);			return NULL;		}		/* Get the User-Name */		if (request->username == NULL) {			handler->username = pairmake("User-Name", handler->identity, T_OP_EQ);		} else {			handler->username = paircopy(request->username);		}		/* No User-Name, No authentication */		/*		if (handler->username == NULL) {			radlog(L_ERR, "rlm_eap: Unknown User, authentication failed");			eap_handler_free(&handler);			return NULL;		}		*/		/*		 * Always get the configured values, for each user.		 * to pass it to the specific EAP-Type		 *		 * No Configured information found for a user, means		 * there is no such user in the database.		 *		 * Every user should have, atleast, one item configured		 * This is required for Authentication purpose.		 */		handler->configured = paircopy(request->config_items);		if (handler->configured == NULL) {			DEBUG2("  rlm_eap: No configured information for this user");			/*			 * FIXME: If there is no config info then			 * config_items should provide the same username			 * if the user is present in the database.			 */			/*			eap_handler_free(&handler);			return NULL;			*/		}	}	handler->eap_ds = eap_buildds(eap_packet_p);	if (handler->eap_ds == NULL) {		eap_handler_free(&handler);		return NULL;	}	handler->timestamp = time(NULL);	handler->reply_vps = &(request->reply->vps);	handler->request = request; /* LEAP needs this */	return handler;}/* * Regenerate the ID to match the ID stored in the list. * This ID is created based on the NAS, State & EAP-Response */unsigned char *eap_regenerateid(REQUEST *request, unsigned char response_id){	VALUE_PAIR 	*state = NULL;	unsigned char	*id = NULL;	state = pairfind(request->packet->vps, PW_STATE);	if (state == NULL) {		DEBUG2("  rlm_eap: NO State Attribute found: Cannot match EAP packet to any existing conversation.");		return NULL;	}	if (verify_state(state) != 0) {		radlog(L_ERR, "rlm_eap: State verification failed.");		return NULL;	}	id = (unsigned char *)malloc(1/*Length*/ + 1/*Id*/ + state->length + sizeof(request->packet->src_ipaddr));	if (id == NULL) {		radlog(L_ERR, "rlm_eap: out of memory");		return NULL;	}	/*	 * Generate unique-id to check for the reply 	 * id = Length + ID + State + Client IP Address	 *	 *  Note that we do NOT use NAS-IP-Address, or NAS-Identifier,	 *  as they may lie to us!	 */	id[0] = (1 + 1 + state->length + sizeof(request->packet->src_ipaddr)) & 0xFF;	memcpy(id+1, &response_id, sizeof(unsigned char));	memcpy(id+2, state->strvalue, state->length);	memcpy(id+2+state->length, &request->packet->src_ipaddr,	       sizeof(request->packet->src_ipaddr));	return id;}/* * Generate the ID that is used as the search criteria in the list. * This ID is created based on the NAS, State & EAP-Request */unsigned char *eap_generateid(REQUEST *request, unsigned char response_id){	VALUE_PAIR 	*state = NULL;	unsigned char	*id = NULL;	state = pairfind(request->reply->vps, PW_STATE);	if (state == NULL) {		DEBUG2("  rlm_eap: NO State Attribute found.  Cannot match the EAP packet to any existing conversation.");		return NULL;	}	id = (unsigned char *)malloc(1/*Length*/ + 1/*Id*/ + state->length + sizeof(request->packet->src_ipaddr));	if (id == NULL) {		radlog(L_ERR, "rlm_eap: out of memory");		return NULL;	}	/*	 * Generate unique-id to check for the reply 	 * id = Length + ID + State + Client IP Address	 *	 *  Note that we do NOT use NAS-IP-Address, or NAS-Identifier,	 *  as they may lie to us!	 */	id[0] = (1 + 1 + state->length + sizeof(request->packet->src_ipaddr)) & 0xFF;	memcpy(id+1, &response_id, sizeof(unsigned char));	memcpy(id+2, state->strvalue, state->length);	memcpy(id+2+state->length, &request->packet->src_ipaddr,               sizeof(request->packet->src_ipaddr));	return id;}

⌨️ 快捷键说明

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