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

📄 eap_tls.c

📁 使用最广泛的radius的linux的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
 *  RFC 2716 Section 4.2.  PPP EAP TLS Request Packet * *  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... *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * *  The Length field is two octets and indicates the length of the EAP *  packet including the Code, Identifir, Length, Type, and TLS data *  fields. */static EAPTLS_PACKET *eaptls_extract(EAP_DS *eap_ds, eaptls_status_t status){	EAPTLS_PACKET	*tlspacket;	uint32_t	data_len = 0;	uint32_t	len = 0;	uint8_t		*data = NULL;	if (status  == EAPTLS_INVALID)		return NULL;	/*	 *	The main EAP code & eaptls_verify() take care of	 *	ensuring that the packet is OK, and that we can	 *	extract the various fields we want.	 *	 *	e.g. a TLS packet with zero data is allowed as an ACK,	 *	but we will never see it here, as we will simply	 *	send another fragment, instead of trying to extract	 *	the data.	 *	 *	MUST have TLS type octet, followed by flags, followed	 *	by data.	 */	assert(eap_ds->response->length > 2);	tlspacket = eaptls_alloc();	if (tlspacket == NULL) return NULL;	/*	 *	Code & id for EAPTLS & EAP are same	 *	but eaptls_length = eap_length - 1(EAP-Type = 1 octet)	 *	 *	length = code + id + length + type + tlsdata	 *	       =  1   +  1 +   2    +  1    +  X	 */	tlspacket->code = eap_ds->response->code;	tlspacket->id = eap_ds->response->id;	tlspacket->length = eap_ds->response->length - 1; /* EAP type */	tlspacket->flags = eap_ds->response->type.data[0];	/*	 *	A quick sanity check of the flags.  If we've been told	 *	that there's a length, and there isn't one, then stop.	 */	if (TLS_LENGTH_INCLUDED(tlspacket->flags) &&	    (tlspacket->length < 5)) { /* flags + TLS message length */		radlog(L_ERR, "rlm_eap_tls: Invalid EAP-TLS packet received.  (Length bit is set, but no length was found.)");		eaptls_free(&tlspacket);		return NULL;	}	/*	 *	If the final TLS packet is larger than we can handle, die	 *	now.	 *	 *	Likewise, if the EAP packet says N bytes, and the TLS	 *	packet says there's fewer bytes, it's a problem.	 *	 *	FIXME: Try to ensure that the claimed length is	 *	consistent across multiple TLS fragments.	 */	if (TLS_LENGTH_INCLUDED(tlspacket->flags)) {		memcpy(&data_len, &eap_ds->response->type.data[1], 4);		data_len = ntohl(data_len);		if (data_len > MAX_RECORD_SIZE) {			radlog(L_ERR, "rlm_eap_tls: The EAP-TLS packet will contain more data than we can process.");			eaptls_free(&tlspacket);			return NULL;		}#if 0		DEBUG2(" TLS: %d %d\n", data_len, tlspacket->length);		if (data_len < tlspacket->length) {			radlog(L_ERR, "rlm_eap_tls: EAP-TLS packet claims to be smaller than the encapsulating EAP packet.");			eaptls_free(&tlspacket);			return NULL;		}#endif	}	switch (status) {	/*	 *	The TLS Message Length field is four octets, and	 *	provides the total length of the TLS message or set of	 *	messages that is being fragmented; this simplifies	 *	buffer allocation.	 *	 *	Dynamic allocation of buffers as & when we know the	 *	length should solve the problem.	 */	case EAPTLS_FIRST_FRAGMENT:	case EAPTLS_LENGTH_INCLUDED:	case EAPTLS_MORE_FRAGMENTS_WITH_LENGTH:		if (tlspacket->length < 5) { /* flags + TLS message length */			radlog(L_ERR, "rlm_eap_tls: Invalid EAP-TLS packet received.  (Expected length, got none.)");			eaptls_free(&tlspacket);			return NULL;		}		/*		 *	Extract all the TLS fragments from the		 *	previous eap_ds Start appending this		 *	fragment to the above ds		 */		memcpy(&data_len, &eap_ds->response->type.data[1], sizeof(uint32_t));		data_len = ntohl(data_len);		data = (eap_ds->response->type.data + 5/*flags+TLS-Length*/);		len = eap_ds->response->type.length - 5/*flags+TLS-Length*/;		/*		 *	Hmm... this should be an error, too.		 */		if (data_len > len) {			data_len = len;		}		break;		/*		 *	Data length is implicit, from the EAP header.		 */	case EAPTLS_MORE_FRAGMENTS:	case EAPTLS_OK:		data_len = eap_ds->response->type.length - 1/*flags*/;		data = eap_ds->response->type.data + 1/*flags*/;		break;	default:		radlog(L_ERR, "rlm_eap_tls: Invalid EAP-TLS packet received");		eaptls_free(&tlspacket);		return NULL;	}	tlspacket->dlen = data_len;	if (data_len) {		tlspacket->data = (unsigned char *)malloc(data_len);		if (tlspacket->data == NULL) {			radlog(L_ERR, "rlm_eap_tls: out of memory");			eaptls_free(&tlspacket);			return NULL;		}		memcpy(tlspacket->data, data, data_len);	}	return tlspacket;}/* * To process the TLS, *  INCOMING DATA: * 	1. EAP-TLS should get the compelete TLS data from the peer. * 	2. Store that data in a data structure with any other required info *	3. Handle that data structure to the TLS module. *	4. TLS module will perform its operations on the data and *	handle back to EAP-TLS * *  OUTGOING DATA: * 	1. EAP-TLS if necessary will fragment it and send it to the * 	destination. * *	During EAP-TLS initialization, TLS Context object will be *	initialized and stored.  For every new authentication *	requests, TLS will open a new session object and that session *	object should be maintained even after the session is *	completed for session resumption. (Probably later as a feature *	as we donot know who maintains these session objects ie, *	SSL_CTX (internally) or TLS module(explicitly). If TLS module, *	then how to let SSL API know about these sessions.) */static void eaptls_operation(EAPTLS_PACKET *eaptls_packet UNUSED,			     eaptls_status_t status, EAP_HANDLER *handler){	tls_session_t *tls_session;	tls_session = (tls_session_t *)handler->opaque;	if ((status == EAPTLS_MORE_FRAGMENTS) ||	    (status == EAPTLS_MORE_FRAGMENTS_WITH_LENGTH) ||	    (status == EAPTLS_FIRST_FRAGMENT)) {		/*		 * Send the ACK.		 */		eaptls_send_ack(handler->eap_ds, tls_session->peap_flag);	} else {		int rcode;		/*		 *	We have the complete TLS-data or TLS-message.		 *		 *	Clean the dirty message.		 *		 *	Authenticate the user and send		 *	Success/Failure.		 *		 *	If more info		 *	is required then send another request.		 */		rcode = tls_handshake_recv(tls_session);		if (rcode == 1) {			/*			 *	FIXME: return success/fail.			 *			 *	TLS proper can decide what to do, then.			 */			eaptls_request(handler->eap_ds, tls_session);			/*			 *	TLS returns 0 or 1.			 *	anything else is application-specific.			 *			 *	In our code, this means "session			 *	resumption was OK".			 */		} else if (rcode == 0xea) {			/*			 *	FIXME: hard-code key based on EAP type.			 *	Also, this code is duplicated all over			 *	the place...			 */			eaptls_success(handler->eap_ds, 0);			eaptls_gen_mppe_keys(&handler->request->reply->vps,					     tls_session->ssl,					     "client EAP encryption");		} else {			eaptls_fail(handler->eap_ds, tls_session->peap_flag);		}	}	return;}/* * In the actual authentication first verify the packet and then create the data structure *//* * To process the TLS, *  INCOMING DATA: * 	1. EAP-TLS should get the compelete TLS data from the peer. * 	2. Store that data in a data structure with any other required info *	3. Hand this data structure to the TLS module. *	4. TLS module will perform its operations on the data and hands back to EAP-TLS *  OUTGOING DATA: * 	1. EAP-TLS if necessary will fragment it and send it to the destination. * *	During EAP-TLS initialization, TLS Context object will be *	initialized and stored.  For every new authentication *	requests, TLS will open a new session object and that *	session object SHOULD be maintained even after the session *	is completed, for session resumption. (Probably later as a *	feature, as we do not know who maintains these session *	objects ie, SSL_CTX (internally) or TLS module (explicitly). If *	TLS module, then how to let SSL API know about these *	sessions.) *//* *	Process an EAP request */eaptls_status_t eaptls_process(EAP_HANDLER *handler){	tls_session_t *tls_session = (tls_session_t *) handler->opaque;	EAPTLS_PACKET	*tlspacket;	eaptls_status_t	status;	DEBUG2("  rlm_eap_tls: processing TLS");	/* This case is when SSL generates Alert then we	 * send that alert to the client and then send the EAP-Failure	 */	status = eaptls_verify(handler);	DEBUG2("  eaptls_verify returned %d\n", status);	switch (status) {	default:	case EAPTLS_INVALID:	case EAPTLS_FAIL:		/*		 *	Success means that we're done the initial		 *	handshake.  For TTLS, this means send stuff		 *	back to the client, and the client sends us		 *	more tunneled data.		 */	case EAPTLS_SUCCESS:		return status;		break;		/*		 *	Normal TLS request, continue with the "get rest		 *	of fragments" phase.		 */	case EAPTLS_REQUEST:		eaptls_request(handler->eap_ds, tls_session);		return EAPTLS_HANDLED;		break;		/*		 *	The handshake is done, and we're in the "tunnel		 *	data" phase.		 */	case EAPTLS_OK:		DEBUG2("  rlm_eap_tls: Done initial handshake");		/*		 *	Get the rest of the fragments.		 */	case EAPTLS_FIRST_FRAGMENT:	case EAPTLS_MORE_FRAGMENTS:	case EAPTLS_LENGTH_INCLUDED:	case EAPTLS_MORE_FRAGMENTS_WITH_LENGTH:		break;	}	/*	 *	Extract the TLS packet from the buffer.	 */	if ((tlspacket = eaptls_extract(handler->eap_ds, status)) == NULL)		return EAPTLS_FAIL;	/*	 *	Get the session struct from the handler	 *	 *	update the dirty_in buffer	 *	 *	NOTE: This buffer will contain partial data when M bit is set.	 *	 * 	CAUTION while reinitializing this buffer, it should be	 * 	reinitialized only when this M bit is NOT set.	 */	if (tlspacket->dlen !=	    (tls_session->record_plus)(&tls_session->dirty_in, tlspacket->data, tlspacket->dlen)) {		eaptls_free(&tlspacket);		radlog(L_ERR, "rlm_eap_tls: Exceeded maximum record size");		return EAPTLS_FAIL;	}	/*	 *	SSL initalization is done.  Return.	 *	 *	The TLS data will be in the tls_session structure.	 */	if (SSL_is_init_finished(tls_session->ssl)) {		eaptls_free(&tlspacket);		return EAPTLS_OK;	}	/*	 *	Continue the handshake.	 */	eaptls_operation(tlspacket, status, handler);	eaptls_free(&tlspacket);	return EAPTLS_HANDLED;}/* *	compose the TLS reply packet in the EAP reply typedata */int eaptls_compose(EAP_DS *eap_ds, EAPTLS_PACKET *reply){	uint8_t *ptr;	/*	 *	Don't set eap_ds->request->type.type, as the main EAP	 *	handler will do that for us.  This allows the TLS	 *	module to be called from TTLS & PEAP.	 */	/*	 * 	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 until it receives	 * 	the EAP-Request before sending another fragment.	 *	 *	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_ds->request->type.data = malloc(reply->length - TLS_HEADER_LEN + 1);	if (eap_ds->request->type.data == NULL) {		radlog(L_ERR, "rlm_eap_tls: out of memory");		return 0;	}	/* EAPTLS Header length is excluded while computing EAP typelen */	eap_ds->request->type.length = reply->length - TLS_HEADER_LEN;	ptr = eap_ds->request->type.data;	*ptr++ = (uint8_t)(reply->flags & 0xFF);	if (reply->dlen) memcpy(ptr, reply->data, reply->dlen);	switch (reply->code) {	case EAPTLS_ACK:	case EAPTLS_START:	case EAPTLS_REQUEST:		eap_ds->request->code = PW_EAP_REQUEST;		break;	case EAPTLS_SUCCESS:		eap_ds->request->code = PW_EAP_SUCCESS;		break;	case EAPTLS_FAIL:		eap_ds->request->code = PW_EAP_FAILURE;		break;	default:		/* Should never enter here */		eap_ds->request->code = PW_EAP_FAILURE;		break;	}	return 1;}

⌨️ 快捷键说明

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