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

📄 eap.c

📁 freeradius-server-2.1.3.tar.gz安装源文件
💻 C
📖 第 1 页 / 共 2 页
字号:
			return RLM_MODULE_HANDLED;		}		/* 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;		reply->code = PW_EAP_FAILURE;		rcode = RLM_MODULE_REJECT;		break;	}	return rcode;}/* * Radius criteria, EAP-Message is invalid without Message-Authenticator * For EAP_START, send Access-Challenge with EAP Identity request. */int eap_start(rlm_eap_t *inst, REQUEST *request){	VALUE_PAIR *vp, *proxy;	VALUE_PAIR *eap_msg;	eap_msg = pairfind(request->packet->vps, PW_EAP_MESSAGE);	if (eap_msg == NULL) {		RDEBUG2("No EAP-Message, not doing EAP");		return EAP_NOOP;	}	/*	 *	Look for EAP-Type = None (FreeRADIUS specific attribute)	 *	this allows you to NOT do EAP for some users.	 */	vp = pairfind(request->packet->vps, PW_EAP_TYPE);	if (vp && vp->vp_integer == 0) {		RDEBUG2("Found EAP-Message, but EAP-Type = None, so we're not doing EAP.");		return EAP_NOOP;	}	/*	 *	http://www.freeradius.org/rfc/rfc2869.html#EAP-Message	 *	 *	Checks for Message-Authenticator are handled by rad_recv().	 */	/*	 *	Check for a Proxy-To-Realm.  Don't get excited over LOCAL	 *	realms (sigh).	 */	proxy = pairfind(request->config_items, PW_PROXY_TO_REALM);	if (proxy) {		REALM *realm;		/*		 *	If it's a LOCAL realm, then we're not proxying		 *	to it.		 */		realm = realm_find(proxy->vp_strvalue);		if (realm && (realm->auth_pool == NULL)) {			proxy = NULL;		}	}	/*	 *	Check the length before de-referencing the contents.	 *	 *	Lengths of zero are required by the RFC for EAP-Start,	 *	but we've never seen them in practice.	 *	 *	Lengths of two are what we see in practice as	 *	EAP-Starts.	 */	if ((eap_msg->length == 0) || (eap_msg->length == 2)) {		EAP_DS *eap_ds;		EAP_HANDLER handler;		/*		 *	It's a valid EAP-Start, but the request		 *	was marked as being proxied.  So we don't		 *	do EAP, as the home server will do it.		 */		if (proxy) {		do_proxy:			RDEBUG2("Request is supposed to be proxied to Realm %s.  Not doing EAP.", proxy->vp_strvalue);			return EAP_NOOP;		}		RDEBUG2("Got EAP_START message");		if ((eap_ds = eap_ds_alloc()) == NULL) {			RDEBUG2("EAP Start failed in allocation");			return EAP_FAIL;		}		/*		 *	It's an EAP-Start packet.  Tell them to stop wasting		 *	our time, and give us an EAP-Identity packet.		 *		 *	Hmm... we should probably check the contents of the		 *	EAP-Start packet for something...		 */		eap_ds->request->code = PW_EAP_REQUEST;		eap_ds->request->type.type = PW_EAP_IDENTITY;		/*		 *	We don't have a handler, but eap_compose needs one,		 *	(for various reasons), so we fake it out here.		 */		memset(&handler, 0, sizeof(handler));		handler.request = request;		handler.eap_ds = eap_ds;		eap_compose(&handler);		eap_ds_free(&eap_ds);		return EAP_FOUND;	} /* end of handling EAP-Start */	/*	 *	The EAP packet header is 4 bytes, plus one byte of	 *	EAP sub-type.  Short packets are discarded, unless	 *	we're proxying.	 */	if (eap_msg->length < (EAP_HEADER_LEN + 1)) {		if (proxy) goto do_proxy;		RDEBUG2("Ignoring EAP-Message which is too short to be meaningful.");		return EAP_FAIL;	}	/*	 *	Create an EAP-Type containing the EAP-type	 *	from the packet.	 */	vp = paircreate(PW_EAP_TYPE, PW_TYPE_INTEGER);	if (vp) {		vp->vp_integer = eap_msg->vp_octets[4];		pairadd(&(request->packet->vps), vp);	}	/*	 *	If the request was marked to be proxied, do it now.	 *	This is done after checking for a valid length	 *	(which may not be good), and after adding the EAP-Type	 *	attribute.  This lets other modules selectively cancel	 *	proxying based on EAP-Type.	 */	if (proxy) goto do_proxy;	/*	 *	From now on, we're supposed to be handling the	 *	EAP packet.  We better understand it...	 */	/*	 *	We're allowed only a few codes.  Request, Response,	 *	Success, or Failure.	 */	if ((eap_msg->vp_octets[0] == 0) ||	    (eap_msg->vp_octets[0] > PW_EAP_MAX_CODES)) {		RDEBUG2("Unknown EAP packet");	} else {		RDEBUG2("EAP packet type %s id %d length %d",		       eap_codes[eap_msg->vp_octets[0]],		       eap_msg->vp_octets[1],		       eap_msg->length);	}	/*	 *	We handle request and responses.  The only other defined	 *	codes are success and fail.  The client SHOULD NOT be	 *	sending success/fail packets to us, as it doesn't make	 *	sense.	 */	if ((eap_msg->vp_octets[0] != PW_EAP_REQUEST) &&	    (eap_msg->vp_octets[0] != PW_EAP_RESPONSE)) {		RDEBUG2("Ignoring EAP packet which we don't know how to handle.");		return EAP_FAIL;	}	/*	 *	We've been told to ignore unknown EAP types, AND it's	 *	an unknown type.  Return "NOOP", which will cause the	 *	eap_authorize() to return NOOP.	 *	 *	EAP-Identity, Notification, and NAK are all handled	 *	internally, so they never have handlers.	 */	if ((eap_msg->vp_octets[4] >= PW_EAP_MD5) &&	    inst->ignore_unknown_eap_types &&	    ((eap_msg->vp_octets[4] == 0) ||	     (eap_msg->vp_octets[4] > PW_EAP_MAX_TYPES) ||	     (inst->types[eap_msg->vp_octets[4]] == NULL))) {		RDEBUG2(" Ignoring Unknown EAP type");		return EAP_NOOP;	}	/*	 *	They're NAKing the EAP type we wanted to use, and	 *	asking for one which we don't support.	 *	 *	NAK is code + id + length1 + length + NAK	 *             + requested EAP type(s).	 *	 *	We know at this point that we can't handle the	 *	request.  We could either return an EAP-Fail here, but	 *	it's not too critical.	 *	 *	By returning "noop", we can ensure that authorize()	 *	returns NOOP, and another module may choose to proxy	 *	the request.	 */	if ((eap_msg->vp_octets[4] == PW_EAP_NAK) &&	    (eap_msg->length >= (EAP_HEADER_LEN + 2)) &&	    inst->ignore_unknown_eap_types &&	    ((eap_msg->vp_octets[5] == 0) ||	     (eap_msg->vp_octets[5] > PW_EAP_MAX_TYPES) ||	     (inst->types[eap_msg->vp_octets[5]] == NULL))) {		RDEBUG2("Ignoring NAK with request for unknown EAP type");		return EAP_NOOP;	}	if ((eap_msg->vp_octets[4] == PW_EAP_TTLS) ||	    (eap_msg->vp_octets[4] == PW_EAP_PEAP)) {		RDEBUG2("Continuing tunnel setup.");		return EAP_OK;	}	/*	 *	Later EAP messages are longer than the 'start'	 *	message, so if everything is OK, 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.	 */	RDEBUG2("No EAP Start, assuming it's an on-going EAP conversation");	return EAP_NOTFOUND;}/* *	compose EAP FAILURE packet in EAP-Message */void eap_fail(EAP_HANDLER *handler){	/*	 *	Delete any previous replies.	 */	pairdelete(&handler->request->reply->vps, PW_EAP_MESSAGE);	pairdelete(&handler->request->reply->vps, PW_STATE);	eap_packet_free(&handler->eap_ds->request);	handler->eap_ds->request = eap_packet_alloc();	handler->eap_ds->request->code = PW_EAP_FAILURE;	eap_compose(handler);}/* *	compose EAP SUCCESS packet in EAP-Message */void eap_success(EAP_HANDLER *handler){	handler->eap_ds->request->code = PW_EAP_SUCCESS;	eap_compose(handler);}/* * Basic EAP packet verfications & validations */static int eap_validation(REQUEST *request, 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_request(L_AUTH, 0, request, 			       "Badly formatted 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_request(L_AUTH, 0, request, "Got NOTIFICATION, "			       "Ignoring the packet");		return EAP_INVALID;	}	return EAP_VALID;}/* *  Get the user Identity only from EAP-Identity packets */static char *eap_identity(REQUEST *request, 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)) {		RDEBUG("UserIdentity Unknown ");		return NULL;	}	size = len - 5;	identity = rad_malloc(size + 1);	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 = *eap_packet_p;	int		typelen;	uint16_t	len;	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;	/*	 *	We've eaten the eap packet into the eap_ds.	 */	*eap_packet_p = NULL;	/*	 *	First 5 bytes in eap, are code + id + length(2) + type.	 *	 *	The rest is type-specific data.  We skip type while	 *	getting typedata from data.	 */	typelen = len - 5/*code + id + length + type */;	if (typelen > 0) {		/*		 *	Since the packet contains 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;	}	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(rlm_eap_t *inst, eap_packet_t **eap_packet_p,			 REQUEST *request){	EAP_HANDLER	*handler = NULL;	eap_packet_t	*eap_packet = *eap_packet_p;	VALUE_PAIR	*vp;	/*	 *	Ensure it's a valid EAP-Request, or EAP-Response.	 */	if (eap_validation(request, eap_packet) == EAP_INVALID) {		free(*eap_packet_p);		*eap_packet_p = NULL;		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) {		handler = eaplist_find(inst, request, eap_packet);		if (handler == NULL) {			/* Either send EAP_Identity or EAP-Fail */			RDEBUG("Either EAP-request timed out OR"			       " EAP-response to an unknown EAP-request");			free(*eap_packet_p);			*eap_packet_p = NULL;			return NULL;		}		/*		 *	Even more paranoia.  Without this, some weird		 *	clients could do crazy things.		 *		 *	It's ok to send EAP sub-type NAK in response		 *	to a request for a particular type, but it's NOT		 *	OK to blindly return data for another type.		 */		if ((eap_packet->data[0] != PW_EAP_NAK) &&		    (eap_packet->data[0] != handler->eap_type)) {			RDEBUG("Response appears to match, but EAP type is wrong.");			free(*eap_packet_p);			*eap_packet_p = NULL;			return NULL;		}               vp = pairfind(request->packet->vps, PW_USER_NAME);               if (!vp) {                       /*                        *	NAS did not set the User-Name                        *	attribute, so we set it here and                        *	prepend it to the beginning of the                        *	request vps so that autz's work                        *	correctly			*/		       RDEBUG2("Broken NAS did not set User-Name, setting from EAP Identity");                       vp = pairmake("User-Name", handler->identity, T_OP_EQ);                       if (vp == NULL) {			       RDEBUG("Out of memory");                               free(*eap_packet_p);                               *eap_packet_p = NULL;                               return NULL;                       }                       vp->next = request->packet->vps;                       request->packet->vps = vp;               } else {                       /*                        *      A little more paranoia.  If the NAS                        *      *did* set the User-Name, and it doesn't                        *      match the identity, (i.e. If they                        *      change their User-Name part way through                        *      the EAP transaction), then reject the                        *      request as the NAS is doing something                        *      funny.			*/                       if (strncmp(handler->identity, vp->vp_strvalue,				   MAX_STRING_LEN) != 0) {                               RDEBUG("Identity does not match User-Name.  Authentication failed.");                               free(*eap_packet_p);                               *eap_packet_p = NULL;                               return NULL;                       }	       }	} else {		/* packet was EAP identity */		handler = eap_handler_alloc();		if (handler == NULL) {			RDEBUG("Out of memory.");			free(*eap_packet_p);			*eap_packet_p = NULL;			return NULL;		}		/*		 *	All fields in the handler are set to zero.		 */		handler->identity = eap_identity(request, eap_packet);		if (handler->identity == NULL) {			RDEBUG("Identity Unknown, authentication failed");			free(*eap_packet_p);			*eap_packet_p = NULL;			eap_handler_free(handler);			return NULL;		}               vp = pairfind(request->packet->vps, PW_USER_NAME);               if (!vp) {                       /*                        *	NAS did not set the User-Name                        *	attribute, so we set it here and                        *	prepend it to the beginning of the                        *	request vps so that autz's work                        *	correctly			*/		       RDEBUG2("WARNING NAS did not set User-Name.  Setting it locally from EAP Identity");                       vp = pairmake("User-Name", handler->identity, T_OP_EQ);                       if (vp == NULL) {                               RDEBUG("Out of memory");                               free(*eap_packet_p);                               *eap_packet_p = NULL;			       eap_handler_free(handler);                               return NULL;                       }                       vp->next = request->packet->vps;                       request->packet->vps = vp;               } else {                       /*                        *      Paranoia.  If the NAS *did* set the                        *      User-Name, and it doesn't match the                        *      identity, the NAS is doing something                        *      funny, so reject the request.			*/                       if (strncmp(handler->identity, vp->vp_strvalue,				   MAX_STRING_LEN) != 0) {                               RDEBUG("Identity does not match User-Name, setting from EAP Identity.");                               free(*eap_packet_p);                               *eap_packet_p = NULL;                               eap_handler_free(handler);                               return NULL;                       }	       }	}	handler->eap_ds = eap_buildds(eap_packet_p);	if (handler->eap_ds == NULL) {		free(*eap_packet_p);		*eap_packet_p = NULL;		eap_handler_free(handler);		return NULL;	}	handler->timestamp = request->timestamp;	handler->request = request; /* LEAP needs this */	return handler;}

⌨️ 快捷键说明

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