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

📄 peap.c

📁 free radius编程。完成AAA的实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * peap.c  contains the interfaces that are called from eap * * Version:     $Id: peap.c,v 1.11 2004/03/12 18:23:14 aland Exp $ * *   This program is free software; you can redistribute it and/or modify *   it under the terms of the GNU General Public License as published by *   the Free Software Foundation; either version 2 of the License, or *   (at your option) any later version. * *   This program is distributed in the hope that it will be useful, *   but WITHOUT ANY WARRANTY; without even the implied warranty of *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *   GNU General Public License for more details. * *   You should have received a copy of the GNU General Public License *   along with this program; if not, write to the Free Software *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * *   Copyright 2003 Alan DeKok <aland@freeradius.org> */#include "eap_tls.h"#include "eap_peap.h"/* *	Send protected EAP-Failure * *       Result-TLV = Failure */static int eappeap_failure(EAP_HANDLER *handler, tls_session_t *tls_session){	uint8_t tlv_packet[11];	DEBUG2("  rlm_eap_peap: FAILURE");	tlv_packet[0] = PW_EAP_REQUEST;	tlv_packet[1] = handler->eap_ds->response->id +1;	tlv_packet[2] = 0;	tlv_packet[3] = 11;	/* length of this packet */	tlv_packet[4] = PW_EAP_TLV;	tlv_packet[5] = 0x80;	tlv_packet[6] = EAP_TLV_ACK_RESULT;	tlv_packet[7] = 0;	tlv_packet[8] = 2;	/* length of the data portion */	tlv_packet[9] = 0;	tlv_packet[10] = EAP_TLV_FAILURE;	record_plus(&tls_session->clean_in, tlv_packet, 11);	/*	 *	FIXME: Check the return code.	 */	tls_handshake_send(tls_session);	record_init(&tls_session->clean_in);	return 1;}/* *	Send protected EAP-Success * *       Result-TLV = Success */static int eappeap_success(EAP_HANDLER *handler, tls_session_t *tls_session){	uint8_t tlv_packet[11];	DEBUG2("  rlm_eap_peap: SUCCESS");	tlv_packet[0] = PW_EAP_REQUEST;	tlv_packet[1] = handler->eap_ds->response->id +1;	tlv_packet[2] = 0;	tlv_packet[3] = 11;	/* length of this packet */	tlv_packet[4] = PW_EAP_TLV;	tlv_packet[5] = 0x80;	/* mandatory AVP */	tlv_packet[6] = EAP_TLV_ACK_RESULT;	tlv_packet[7] = 0;	tlv_packet[8] = 2;	/* length of the data portion */	tlv_packet[9] = 0;	tlv_packet[10] = EAP_TLV_SUCCESS;	record_plus(&tls_session->clean_in, tlv_packet, 11);	/*	 *	FIXME: Check the return code.	 */	tls_handshake_send(tls_session);	record_init(&tls_session->clean_in);	return 1;}/* *	Verify the tunneled EAP message. */static int eapmessage_verify(const uint8_t *data, unsigned int data_len){	const eap_packet_t *eap_packet = (const eap_packet_t *) data;	uint8_t eap_type;	char identity[256];	if (!data || (data_len <= 1)) {		return 0;	}	eap_type = *data;	switch (eap_type) {	case PW_EAP_IDENTITY:		memcpy(identity, data + 1, data_len - 1);		identity[data_len - 1] = '\0';		DEBUG2("  rlm_eap_peap: Identity - %s", identity);		return 1;		break;		/*		 *	If the first byte of the packet is		 *	EAP-Response, and the EAP data is a TLV,		 *	then it looks OK...		 */	case PW_EAP_RESPONSE:		if (eap_packet->data[0] == PW_EAP_TLV) {			DEBUG2("  rlm_eap_peap: Received EAP-TLV response.");			return 1;		}		DEBUG2("  rlm_eap_peap: Got something weird.");		break;		/*		 *	We normally do Microsoft MS-CHAPv2 (26), versus		 *	Cisco MS-CHAPv2 (29).		 */	case PW_EAP_MSCHAPV2:	default:		DEBUG2("  rlm_eap_peap: EAP type %s",		       eaptype_type2name(eap_type,					 identity, sizeof(identity)));		return 1;		break;	}	return 0;}/* *	Convert a pseudo-EAP packet to a list of VALUE_PAIR's. */static VALUE_PAIR *eap2vp(EAP_DS *eap_ds,			  const uint8_t *data, unsigned int data_len){	VALUE_PAIR *vp = NULL;	/*	 *	Sanity check this...	 */	if (data_len + EAP_HEADER_LEN > MAX_STRING_LEN) {		radlog(L_ERR, "rlm_eap_peap: EAP Response packet is too large.  Code must be fixed to handle this.");		return NULL;	}	vp = paircreate(PW_EAP_MESSAGE, PW_TYPE_OCTETS);	if (!vp) {		DEBUG2("  rlm_eap_peap: Failure in creating VP");		return NULL;	}	/*	 *	Hand-build an EAP packet from the crap in PEAP version 0.	 */	vp->strvalue[0] = PW_EAP_RESPONSE;	vp->strvalue[1] = eap_ds->response->id;	vp->strvalue[2] = 0;	vp->strvalue[3] = EAP_HEADER_LEN + data_len;	memcpy(vp->strvalue + EAP_HEADER_LEN, data, data_len);	vp->length = EAP_HEADER_LEN + data_len;	return vp;}/* *	Convert a list of VALUE_PAIR's to an EAP packet, through the *	simple expedient of dumping the EAP message */static int vp2eap(tls_session_t *tls_session, VALUE_PAIR *vp){	if (vp->next != NULL) {		radlog(L_ERR, "rlm_eap_peap: EAP Request packet is too large.  Code must be fixed to handle this.");		return 0;	}	/*	 *	Skip the id, code, and length.  Just write the EAP	 *	type & data to the client.	 */#ifndef NDEBUG	if (debug_flag > 2) {		int i;		int total = vp->length - 4;		if (debug_flag > 0) for (i = 0; i < total; i++) {			if ((i & 0x0f) == 0) printf("  PEAP tunnel data out %04x: ", i);			printf("%02x ", vp->strvalue[i + 4]);			if ((i & 0x0f) == 0x0f) printf("\n");		}		if ((total & 0x0f) != 0) printf("\n");	}#endif	/*	 *	Send the EAP data, WITHOUT the header.	 */#if 1	record_plus(&tls_session->clean_in, vp->strvalue + EAP_HEADER_LEN,		vp->length - EAP_HEADER_LEN);#else	record_plus(&tls_session->clean_in, vp->strvalue, vp->length);#endif	tls_handshake_send(tls_session);	record_init(&tls_session->clean_in);	return 1;}/* *	See if there's a TLV in the response. */static int eappeap_check_tlv(const uint8_t *data){	const eap_packet_t *eap_packet = (const eap_packet_t *) data;	/*	 *	Look for success or failure.	 */	if ((eap_packet->code == PW_EAP_RESPONSE) &&	    (eap_packet->data[0] == PW_EAP_TLV)) {		if (data[10] == EAP_TLV_SUCCESS) {			return 1;		}		if (data[10] == EAP_TLV_FAILURE) {			DEBUG2("  rlm_eap_peap: Client rejected our response.  The password is probably incorrect.");			return 0;		}	}	return 0;}/* *	Use a reply packet to determine what to do. */static int process_reply(EAP_HANDLER *handler, tls_session_t *tls_session,			 REQUEST *request, RADIUS_PACKET *reply){	int rcode = RLM_MODULE_REJECT;	VALUE_PAIR *vp;	peap_tunnel_t *t = tls_session->opaque;#ifndef NDEBUG	if (debug_flag > 0) {		printf("  PEAP: Processing from tunneled session code %p %d\n",		       reply, reply->code);				for (vp = reply->vps; vp != NULL; vp = vp->next) {			putchar('\t');vp_print(stdout, vp);putchar('\n');		}	}#endif	switch (reply->code) {	case PW_AUTHENTICATION_ACK:		DEBUG2("  PEAP: Tunneled authentication was successful.");		t->status = PEAP_STATUS_SENT_TLV_SUCCESS;		eappeap_success(handler, tls_session);		rcode = RLM_MODULE_HANDLED;		/*		 *	If we've been told to use the attributes from		 *	the reply, then do so.		 *		 *	WARNING: This may leak information about the		 *	tunneled user!		 */		if (t->use_tunneled_reply) {			/*			 *	Clean up the tunneled reply.			 */			pairdelete(&reply->vps, PW_PROXY_STATE);			pairdelete(&reply->vps, PW_EAP_MESSAGE);			pairadd(&request->reply->vps, reply->vps);			reply->vps = NULL;		}		break;	case PW_AUTHENTICATION_REJECT:		DEBUG2("  PEAP: Tunneled authentication was rejected.");		t->status = PEAP_STATUS_SENT_TLV_FAILURE;		eappeap_failure(handler, tls_session);		rcode = RLM_MODULE_HANDLED;		break;	case PW_ACCESS_CHALLENGE:		DEBUG2("  PEAP: Got tunneled Access-Challenge");		/*		 *	Keep the State attribute, if necessary.		 *		 *	Get rid of the old State, too.		 */		pairfree(&t->state);		pairmove2(&t->state, &(reply->vps), PW_STATE);		/*		 *	PEAP takes only EAP-Message attributes inside		 *	of the tunnel.  Any Reply-Message in the		 *	Access-Challenge is ignored.		 */		vp = NULL;		pairmove2(&vp, &(reply->vps), PW_EAP_MESSAGE);		/*		 *	Handle the ACK, by tunneling any necessary reply		 *	VP's back to the client.		 */		if (vp) {			vp2eap(tls_session, vp);			pairfree(&vp);		}		rcode = RLM_MODULE_HANDLED;		break;	default:		DEBUG2("  PEAP: Unknown RADIUS packet type %d: rejecting tunneled user", reply->code);		rcode = RLM_MODULE_REJECT;		break;	}	return rcode;}/* *	Do post-proxy processing, */static int eappeap_postproxy(EAP_HANDLER *handler, void *data){	int rcode;	tls_session_t *tls_session = (tls_session_t *) data;	REQUEST *fake;	DEBUG2("  PEAP: Passing reply from proxy back into the tunnel.");	/*	 *	If there was a fake request associated with the proxied	 *	request, do more processing of it.	 */	fake = (REQUEST *) request_data_get(handler->request,					    handler->request->proxy,					    REQUEST_DATA_EAP_MSCHAP_TUNNEL_CALLBACK);		/*	 *	Do the callback, if it exists, and if it was a success.	 */	if (fake && (handler->request->proxy_reply->code == PW_AUTHENTICATION_ACK)) {		VALUE_PAIR *vp;		REQUEST *request = handler->request;		/*		 *	Terrible hacks.		 */		rad_assert(fake->packet == NULL);		fake->packet = request->proxy;		request->proxy = NULL;		rad_assert(fake->reply == NULL);		fake->reply = request->proxy_reply;		request->proxy_reply = NULL;		/*		 *	Perform a post-auth stage, which will get the EAP		 *	handler, too...		 */		fake->options &= ~RAD_REQUEST_OPTION_PROXY_EAP;		DEBUG2("  PEAP: Passing reply back for EAP-MS-CHAP-V2 %p %d",		       fake, fake->reply->code);		rcode = module_post_proxy(fake);		/*		 *	FIXME: If rcode returns fail, do something		 *	intelligent...		 */		DEBUG2("  POST-PROXY %d", rcode);		rcode = rad_postauth(fake);		DEBUG2("  POST-AUTH %d", rcode);#ifndef NDEBUG		if (debug_flag > 0) {			printf("  PEAP: Final reply from tunneled session code %d\n",			       fake->reply->code);						for (vp = fake->reply->vps; vp != NULL; vp = vp->next) {				putchar('\t');vp_print(stdout, vp);putchar('\n');			}		}#endif		/*		 *	Terrible hacks.		 */		request->proxy = fake->packet;		fake->packet = NULL;		request->proxy_reply = fake->reply;		fake->reply = NULL;		/*		 *	And we're done with this request.		 */		switch (rcode) {                case RLM_MODULE_FAIL:			request_free(&fake);			eaptls_fail(handler->eap_ds, 0);			return 0;			break;			                default:  /* Don't Do Anything */			DEBUG2(" PEAP: Got reply %d",			       request->proxy_reply->code);			break;		}		}	request_free(&fake);	/* robust if fake == NULL */	/*	 *	If there was no EAP-Message in the reply packet, then	 *	we know that we're supposed to re-run the "authenticate"	 *	stage, in order to get the right kind of handling...	 */	/*	 *	Process the reply from the home server.	 */	rcode = process_reply(handler, tls_session, handler->request,			      handler->request->proxy_reply);	/*	 *	The proxy code uses the reply from the home server as	 *	the basis for the reply to the NAS.  We don't want that,	 *	so we toss it, after we've had our way with it.	 */	pairfree(&handler->request->proxy_reply->vps);	switch (rcode) {	case RLM_MODULE_REJECT:		DEBUG2("  PEAP: Reply was rejected");		eaptls_fail(handler->eap_ds, 0);		return 0;	case RLM_MODULE_HANDLED:		DEBUG2("  PEAP: Reply was handled");		eaptls_request(handler->eap_ds, tls_session);		return 1;	case RLM_MODULE_OK:

⌨️ 快捷键说明

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