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

📄 eap_tls.c

📁 使用最广泛的radius的linux的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * eap_tls.c * * Version:     $Id: eap_tls.c,v 1.10 2007/12/15 14:56:10 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA * * Copyright 2001  hereUare Communications, Inc. <raghud@hereuare.com> * Copyright 2003  Alan DeKok <aland@freeradius.org> * Copyright 2006  The FreeRADIUS server project *//* * *  TLS Packet Format in EAP *  --- ------ ------ -- --- * 0                   1                   2                   3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |     Code      |   Identifier  |            Length             | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |     Type      |     Flags     |      TLS Message Length * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |     TLS Message Length        |       TLS Data... * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * */#include <freeradius-devel/ident.h>RCSID("$Id: eap_tls.c,v 1.10 2007/12/15 14:56:10 aland Exp $")#include <freeradius-devel/autoconf.h>#include <assert.h>#include "eap_tls.h"/* *      Allocate a new TLS_PACKET */EAPTLS_PACKET *eaptls_alloc(void){	EAPTLS_PACKET   *rp;	if ((rp = malloc(sizeof(EAPTLS_PACKET))) == NULL) {		radlog(L_ERR, "rlm_eap_tls: out of memory");		return NULL;	}	memset(rp, 0, sizeof(EAPTLS_PACKET));	return rp;}/* *      Free EAPTLS_PACKET */void eaptls_free(EAPTLS_PACKET **eaptls_packet_ptr){	EAPTLS_PACKET *eaptls_packet;	if (!eaptls_packet_ptr) return;	eaptls_packet = *eaptls_packet_ptr;	if (eaptls_packet == NULL) return;	if (eaptls_packet->data) {		free(eaptls_packet->data);		eaptls_packet->data = NULL;	}	free(eaptls_packet);	*eaptls_packet_ptr = NULL;}/*   The S flag is set only within the EAP-TLS start message   sent from the EAP server to the peer.*/int eaptls_start(EAP_DS *eap_ds, int peap_flag){	EAPTLS_PACKET 	reply;	reply.code = EAPTLS_START;	reply.length = TLS_HEADER_LEN + 1/*flags*/;	reply.flags = peap_flag;	reply.flags = SET_START(reply.flags);	reply.data = NULL;	reply.dlen = 0;	eaptls_compose(eap_ds, &reply);	return 1;}int eaptls_success(EAP_DS *eap_ds, int peap_flag){	EAPTLS_PACKET	reply;	reply.code = EAPTLS_SUCCESS;	reply.length = TLS_HEADER_LEN;	reply.flags = peap_flag;	reply.data = NULL;	reply.dlen = 0;	eaptls_compose(eap_ds, &reply);	return 1;}int eaptls_fail(EAP_DS *eap_ds, int peap_flag){	EAPTLS_PACKET	reply;	reply.code = EAPTLS_FAIL;	reply.length = TLS_HEADER_LEN;	reply.flags = peap_flag;	reply.data = NULL;	reply.dlen = 0;	eaptls_compose(eap_ds, &reply);	return 1;}/*   A single TLS record may be up to 16384 octets in length, but a TLS   message may span multiple TLS records, and a TLS certificate message   may in principle be as long as 16MB.*//* *	Frame the Dirty data that needs to be send to the client in an *	EAP-Request.  We always embed the TLS-length in all EAP-TLS *	packets that we send, for easy reference purpose.  Handle *	fragmentation and sending the next fragment etc. */int eaptls_request(EAP_DS *eap_ds, tls_session_t *ssn){	EAPTLS_PACKET	reply;	unsigned int	size;	unsigned int 	nlen;	unsigned int 	lbit = 0;	/* This value determines whether we set (L)ength flag for		EVERY packet we send and add corresponding		"TLS Message Length" field.	length_flag = TRUE;		This means we include L flag and "TLS Msg Len" in EVERY		packet we send out.	length_flag = FALSE;		This means we include L flag and "TLS Msg Len" **ONLY**		in First packet of a fragment series. We do not use		it anywhere else.		Having L flag in every packet is prefered.	*/	if (ssn->length_flag) {		lbit = 4;	}	if (ssn->fragment == 0) {		ssn->tls_msg_len = ssn->dirty_out.used;	}	reply.code = EAPTLS_REQUEST;	reply.flags = ssn->peap_flag;	/* Send data, NOT more than the FRAGMENT size */	if (ssn->dirty_out.used > ssn->offset) {		size = ssn->offset;		reply.flags = SET_MORE_FRAGMENTS(reply.flags);		/* Length MUST be included if it is the First Fragment */		if (ssn->fragment == 0) {			lbit = 4;		}		ssn->fragment = 1;	} else {		size = ssn->dirty_out.used;		ssn->fragment = 0;	}	reply.dlen = lbit + size;	reply.length = TLS_HEADER_LEN + 1/*flags*/ + reply.dlen;	reply.data = malloc(reply.dlen);	if (lbit) {		nlen = htonl(ssn->tls_msg_len);		memcpy(reply.data, &nlen, lbit);		reply.flags = SET_LENGTH_INCLUDED(reply.flags);	}	(ssn->record_minus)(&ssn->dirty_out, reply.data + lbit, size);	eaptls_compose(eap_ds, &reply);	free(reply.data);	reply.data = NULL;	return 1;}/* * Acknowledge received is for one of the following messages sent earlier * 1. Handshake completed Message, so now send, EAP-Success * 2. Alert Message, now send, EAP-Failure * 3. Fragment Message, now send, next Fragment */static eaptls_status_t eaptls_ack_handler(EAP_HANDLER *handler){	tls_session_t *tls_session;	tls_session = (tls_session_t *)handler->opaque;	if (tls_session == NULL){		radlog(L_ERR, "rlm_eap_tls: Unexpected ACK received");		return EAPTLS_FAIL;	}	if (tls_session->info.initialized == 0) {		DEBUG("  rlm_eap_tls: No SSL info available. Waiting for more SSL data.");		return EAPTLS_REQUEST;	}	if (tls_session->info.origin == 0) {		radlog(L_ERR, "rlm_eap_tls: Unexpected ACK received");		return EAPTLS_FAIL;	}	switch (tls_session->info.content_type) {	case alert:		DEBUG2("  rlm_eap_tls: ack alert");		eaptls_fail(handler->eap_ds, tls_session->peap_flag);		return EAPTLS_FAIL;	case handshake:		if ((tls_session->info.handshake_type == finished) &&		    (tls_session->dirty_out.used == 0)) {			DEBUG2("  rlm_eap_tls: ack handshake is finished");			return EAPTLS_SUCCESS;		} /* else more data to send */		DEBUG2("  rlm_eap_tls: ack handshake fragment handler");		/* Fragmentation handler, send next fragment */		return EAPTLS_REQUEST;		/*		 *	For the rest of the conditions, switch over		 *	to the default section below.		 */	default:		DEBUG2("  rlm_eap_tls: ack default");		radlog(L_ERR, "rlm_eap_tls: Invalid ACK received: %d",		       tls_session->info.content_type);		return EAPTLS_FAIL;	}}/* *	Similarly, when the EAP server receives an EAP-Response with *	the M bit set, it MUST respond with an EAP-Request with *	EAP-Type=EAP-TLS and no data. This serves as a fragment ACK. * *	In order to prevent errors in the processing of fragments, the *	EAP server MUST use increment the Identifier value for each *	fragment ACK contained within an EAP-Request, and the peer *	MUST include this Identifier value in the subsequent fragment *	contained within an EAP- Reponse. * *	EAP server sends an ACK when it determines there are More *	fragments to receive to make the complete *	TLS-record/TLS-Message */static int eaptls_send_ack(EAP_DS *eap_ds, int peap_flag){	EAPTLS_PACKET 	reply;	reply.code = EAPTLS_ACK;	reply.length = TLS_HEADER_LEN + 1/*flags*/;	reply.flags = peap_flag;	reply.data = NULL;	reply.dlen = 0;	eaptls_compose(eap_ds, &reply);	return 1;}/* *	The S flag is set only within the EAP-TLS start message sent *	from the EAP server to the peer. * *	Similarly, when the EAP server receives an EAP-Response with *	the M bit set, it MUST respond with an EAP-Request with *	EAP-Type=EAP-TLS and no data. This serves as a fragment *	ACK. The EAP peer MUST wait. */static eaptls_status_t eaptls_verify(EAP_HANDLER *handler){	EAP_DS *eap_ds = handler->eap_ds;	EAP_DS *prev_eap_ds = handler->prev_eapds;	eaptls_packet_t	*eaptls_packet, *eaptls_prev = NULL;	/*	 *	We don't check ANY of the input parameters.  It's all	 *	code which works together, so if something is wrong,	 *	we SHOULD core dump.	 *	 *	e.g. if eap_ds is NULL, of if eap_ds->response is	 *	NULL, of if it's NOT an EAP-Response, or if the packet	 *	is too short.  See eap_validation()., in ../../eap.c	 *	 *	Also, eaptype_select() takes care of selecting the	 *	appropriate type, so we don't need to check	 *	eap_ds->response->type.type == PW_EAP_TLS, or anything	 *	else.	 */	eaptls_packet = (eaptls_packet_t *)eap_ds->response->type.data;	if (prev_eap_ds && prev_eap_ds->response)		eaptls_prev = (eaptls_packet_t *)prev_eap_ds->response->type.data;	/*	 *	check for ACK	 *	 *	If there's no TLS data, or there's 1 byte of TLS data,	 *	with the flags set to zero, then it's an ACK.	 *	 *	Find if this is a reply to the previous request sent	 */	if ((eaptls_packet == NULL) ||	    ((eap_ds->response->length == EAP_HEADER_LEN + 2) &&	     ((eaptls_packet->flags & 0xc0) == 0x00))) {#if 0		/*		 *	Un-comment this for TLS inside of TTLS/PEAP		 */		DEBUG2("rlm_eap_tls: Received EAP-TLS ACK message");		return eaptls_ack_handler(handler);#else		if (prev_eap_ds->request->id == eap_ds->response->id) {			/*			 *	Run the ACK handler directly from here.			 */			DEBUG2("rlm_eap_tls: Received EAP-TLS ACK message");			return eaptls_ack_handler(handler);		} else {			radlog(L_ERR, "rlm_eap_tls: Received Invalid EAP-TLS ACK message");			return EAPTLS_INVALID;		}#endif	}	/*	 *	We send TLS_START, but do not receive it.	 */	if (TLS_START(eaptls_packet->flags)) {		radlog(L_ERR, "rlm_eap_tls:  Received unexpected EAP-TLS Start message");		return EAPTLS_INVALID;	}	/*	 *	The L bit (length included) is set to indicate the	 *	presence of the four octet TLS Message Length field,	 *	and MUST be set for the first fragment of a fragmented	 *	TLS message or set of messages.	 *	 *	The M bit (more fragments) is set on all but the last	 *	fragment.	 *	 *	The S bit (EAP-TLS start) is set in an EAP-TLS Start	 *	message. This differentiates the EAP-TLS Start message	 *	from a fragment acknowledgement.	 */	if (TLS_LENGTH_INCLUDED(eaptls_packet->flags)) {		DEBUG2("  TLS Length %d",		       eaptls_packet->data[2] * 256 | eaptls_packet->data[3]);		if (TLS_MORE_FRAGMENTS(eaptls_packet->flags)) {			/*			 * FIRST_FRAGMENT is identified			 * 1. If there is no previous EAP-response received.			 * 2. If EAP-response received, then its M bit not set.			 * 	(It is because Last fragment will not have M bit set)			 */			if (!prev_eap_ds ||			    (prev_eap_ds->response == NULL) ||			    (eaptls_prev == NULL) ||			    !TLS_MORE_FRAGMENTS(eaptls_prev->flags)) {				DEBUG2("rlm_eap_tls:  Received EAP-TLS First Fragment of the message");				return EAPTLS_FIRST_FRAGMENT;			} else {				DEBUG2("rlm_eap_tls:  More Fragments with length included");				return EAPTLS_MORE_FRAGMENTS_WITH_LENGTH;			}		} else {			DEBUG2("rlm_eap_tls:  Length Included");			return EAPTLS_LENGTH_INCLUDED;		}	}	if (TLS_MORE_FRAGMENTS(eaptls_packet->flags)) {		DEBUG2("rlm_eap_tls:  More fragments to follow");		return EAPTLS_MORE_FRAGMENTS;	}	/*	 *	None of the flags are set, but it's still a valid	 *	EAPTLS packet.	 */	return EAPTLS_OK;}/* * EAPTLS_PACKET * code   =  EAP-code * id     =  EAP-id * length = code + id + length + flags + tlsdata *        =  1   +  1 +   2    +  1    +  X * length = EAP-length - 1(EAP-Type = 1 octet) * flags  = EAP-typedata[0] (1 octet) * dlen   = EAP-typedata[1-4] (4 octets), if L flag set *        = length - 5(code+id+length+flags), otherwise * data   = EAP-typedata[5-n], if L flag set *        = EAP-typedata[1-n], otherwise * packet = EAP-typedata (complete typedata) * * Points to consider during EAP-TLS data extraction * 1. In the received packet, No data will be present incase of ACK-NAK * 2. Incase if more fragments need to be received then ACK after retreiving this fragment. *

⌨️ 快捷键说明

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