예제 #1
0
/*
 *	Process an EAP request
 */
fr_tls_status_t eaptls_process(eap_handler_t *handler)
{
	tls_session_t *tls_session = (tls_session_t *) handler->opaque;
	EAPTLS_PACKET	*tlspacket;
	fr_tls_status_t	status;
	REQUEST *request = handler->request;

	if (!request) return FR_TLS_FAIL;

	RDEBUG2("Continuing EAP-TLS");

	SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_REQUEST, request);

	if (handler->certs) fr_pair_add(&request->packet->vps,
				    fr_pair_list_copy(request->packet, handler->certs));

	/*
	 *	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);
	if ((status == FR_TLS_INVALID) || (status == FR_TLS_FAIL)) {
		REDEBUG("[eaptls verify] = %s", fr_int2str(fr_tls_status_table, status, "<INVALID>"));
	} else {
		RDEBUG2("[eaptls verify] = %s", fr_int2str(fr_tls_status_table, status, "<INVALID>"));
	}

	switch (status) {
	default:
	case FR_TLS_INVALID:
	case FR_TLS_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 FR_TLS_SUCCESS:
		goto done;

	/*
	 *	Normal TLS request, continue with the "get rest
	 *	of fragments" phase.
	 */
	case FR_TLS_REQUEST:
		eaptls_request(handler->eap_ds, tls_session);
		status = FR_TLS_HANDLED;
		goto done;

	/*
	 *	The handshake is done, and we're in the "tunnel
	 *	data" phase.
	 */
	case FR_TLS_OK:
		RDEBUG2("Done initial handshake");

	/*
	 *	Get the rest of the fragments.
	 */
	case FR_TLS_FIRST_FRAGMENT:
	case FR_TLS_MORE_FRAGMENTS:
	case FR_TLS_LENGTH_INCLUDED:
		break;
	}

	/*
	 *	Extract the TLS packet from the buffer.
	 */
	if ((tlspacket = eaptls_extract(request, handler->eap_ds, status)) == NULL) {
		status = FR_TLS_FAIL;
		goto done;
	}

	/*
	 *	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)) {
		talloc_free(tlspacket);
		REDEBUG("Exceeded maximum record size");
		status = FR_TLS_FAIL;
		goto done;
	}

	/*
	 *	No longer needed.
	 */
	talloc_free(tlspacket);

	/*
	 *	SSL initalization is done.  Return.
	 *
	 *	The TLS data will be in the tls_session structure.
	 */
	if (SSL_is_init_finished(tls_session->ssl)) {
		/*
		 *	The initialization may be finished, but if
		 *	there more fragments coming, then send ACK,
		 *	and get the caller to continue the
		 *	conversation.
		 */
		if ((status == FR_TLS_MORE_FRAGMENTS) ||
		    (status == FR_TLS_FIRST_FRAGMENT)) {
			/*
			 *	Send the ACK.
			 */
			eaptls_send_ack(handler, tls_session->peap_flag);
			RDEBUG2("Init is done, but tunneled data is fragmented");
			status = FR_TLS_HANDLED;
			goto done;
		}

		status = tls_application_data(tls_session, request);
		goto done;
	}

	/*
	 *	Continue the handshake.
	 */
	status = eaptls_operation(status, handler);
	if (status == FR_TLS_SUCCESS) {
#define MAX_SESSION_SIZE (256)
		size_t size;
		VALUE_PAIR *vps;
		char buffer[2 * MAX_SESSION_SIZE + 1];
		/*
		 *	Restore the cached VPs before processing the
		 *	application data.
		 */
		size = tls_session->ssl->session->session_id_length;
		if (size > MAX_SESSION_SIZE) size = MAX_SESSION_SIZE;

		fr_bin2hex(buffer, tls_session->ssl->session->session_id, size);

		vps = SSL_SESSION_get_ex_data(tls_session->ssl->session, fr_tls_ex_index_vps);
		if (!vps) {
			RWDEBUG("No information in cached session %s", buffer);
		} else {
			vp_cursor_t cursor;
			VALUE_PAIR *vp;

			RDEBUG("Adding cached attributes from session %s", buffer);

			/*
			 *	The cbtls_get_session() function doesn't have
			 *	access to sock->certs or handler->certs, which
			 *	is where the certificates normally live.  So
			 *	the certs are all in the VPS list here, and
			 *	have to be manually extracted.
			 */
			RINDENT();
			for (vp = fr_cursor_init(&cursor, &vps);
			     vp;
			     vp = fr_cursor_next(&cursor)) {
				/*
				 *	TLS-* attrs get added back to
				 *	the request list.
				 */
				if ((vp->da->vendor == 0) &&
				    (vp->da->attr >= PW_TLS_CERT_SERIAL) &&
				    (vp->da->attr <= PW_TLS_CLIENT_CERT_SUBJECT_ALT_NAME_UPN)) {
					/*
					 *	Certs already exist.  Don't re-add them.
					 */
					if (!handler->certs) {
						rdebug_pair(L_DBG_LVL_2, request, vp, "request:");
						fr_pair_add(&request->packet->vps, fr_pair_copy(request->packet, vp));
					}
				} else {
					rdebug_pair(L_DBG_LVL_2, request, vp, "reply:");
					fr_pair_add(&request->reply->vps, fr_pair_copy(request->reply, vp));
				}
			}
			REXDENT();
		}
	}

 done:
	SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_REQUEST, NULL);

	return status;
}
/*
 *	Do authentication, by letting EAP-TLS do most of the work.
 */
static int mod_authenticate(void *arg, eap_handler_t *handler)
{
    int rcode;
    fr_tls_status_t status;
    rlm_eap_peap_t *inst = (rlm_eap_peap_t *) arg;
    tls_session_t *tls_session = (tls_session_t *) handler->opaque;
    peap_tunnel_t *peap = tls_session->opaque;
    REQUEST *request = handler->request;

    /*
     *	Session resumption requires the storage of data, so
     *	allocate it if it doesn't already exist.
     */
    if (!tls_session->opaque) {
        peap = tls_session->opaque = peap_alloc(tls_session, inst);
    }

    status = eaptls_process(handler);
    RDEBUG2("eaptls_process returned %d\n", status);
    switch (status) {
    /*
     *	EAP-TLS handshake was successful, tell the
     *	client to keep talking.
     *
     *	If this was EAP-TLS, we would just return
     *	an EAP-TLS-Success packet here.
     */
    case FR_TLS_SUCCESS:
        RDEBUG2("FR_TLS_SUCCESS");
        peap->status = PEAP_STATUS_TUNNEL_ESTABLISHED;
        break;

    /*
     *	The TLS code is still working on the TLS
     *	exchange, and it's a valid TLS request.
     *	do nothing.
     */
    case FR_TLS_HANDLED:
        /*
         *	FIXME: If the SSL session is established, grab the state
         *	and EAP id from the inner tunnel, and update it with
         *	the expected EAP id!
         */
        RDEBUG2("FR_TLS_HANDLED");
        return 1;

    /*
     *	Handshake is done, proceed with decoding tunneled
     *	data.
     */
    case FR_TLS_OK:
        RDEBUG2("FR_TLS_OK");
        break;

    /*
     *	Anything else: fail.
     */
    default:
        RDEBUG2("FR_TLS_OTHERS");
        return 0;
    }

    /*
     *	Session is established, proceed with decoding
     *	tunneled data.
     */
    RDEBUG2("Session established.  Decoding tunneled attributes");

    /*
     *	We may need PEAP data associated with the session, so
     *	allocate it here, if it wasn't already alloacted.
     */
    if (!tls_session->opaque) {
        tls_session->opaque = peap_alloc(tls_session, inst);
    }

    /*
     *	Process the PEAP portion of the request.
     */
    rcode = eappeap_process(handler, tls_session);
    switch (rcode) {
    case RLM_MODULE_REJECT:
        eaptls_fail(handler, 0);
        return 0;

    case RLM_MODULE_HANDLED:
        eaptls_request(handler->eap_ds, tls_session);
        return 1;

    case RLM_MODULE_OK:
        /*
         *	Move the saved VP's from the Access-Accept to
         *	our Access-Accept.
         */
        peap = tls_session->opaque;
        if (peap->soh_reply_vps) {
            RDEBUG2("Using saved attributes from the SoH reply");
            debug_pair_list(peap->soh_reply_vps);
            pairfilter(handler->request->reply,
                       &handler->request->reply->vps,
                       &peap->soh_reply_vps, 0, 0, TAG_ANY);
        }
        if (peap->accept_vps) {
            RDEBUG2("Using saved attributes from the original Access-Accept");
            debug_pair_list(peap->accept_vps);
            pairfilter(handler->request->reply,
                       &handler->request->reply->vps,
                       &peap->accept_vps, 0, 0, TAG_ANY);
        }

        /*
         *	Success: Automatically return MPPE keys.
         */
        return eaptls_success(handler, 0);

    /*
     *	No response packet, MUST be proxying it.
     *	The main EAP module will take care of discovering
     *	that the request now has a "proxy" packet, and
     *	will proxy it, rather than returning an EAP packet.
     */
    case RLM_MODULE_UPDATED:
#ifdef WITH_PROXY
        rad_assert(handler->request->proxy != NULL);
#endif
        return 1;
        break;

    default:
        break;
    }

    eaptls_fail(handler, 0);
    return 0;
}
예제 #3
0
/*
 * 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 fr_tls_status_t eaptls_operation(fr_tls_status_t status, eap_handler_t *handler)
{
	REQUEST		*request = handler->request;
	tls_session_t	*tls_session = handler->opaque;

	if ((status == FR_TLS_MORE_FRAGMENTS) ||
	    (status == FR_TLS_FIRST_FRAGMENT)) {
		/*
		 *	Send the ACK.
		 */
		eaptls_send_ack(handler, tls_session->peap_flag);
		return FR_TLS_HANDLED;

	}

	/*
	 *	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.
	 */
	if (!tls_handshake_recv(handler->request, tls_session)) {
		REDEBUG("TLS receive handshake failed during operation");
		tls_fail(tls_session);
		return FR_TLS_FAIL;
	}

	/*
	 *	FIXME: return success/fail.
	 *
	 *	TLS proper can decide what to do, then.
	 */
	if (tls_session->dirty_out.used > 0) {
		eaptls_request(handler->eap_ds, tls_session);
		return FR_TLS_HANDLED;
	}

	/*
	 *	If there is no data to send i.e
	 *	dirty_out.used <=0 and if the SSL
	 *	handshake is finished, then return a
	 *	EPTLS_SUCCESS
	 */

	if (SSL_is_init_finished(tls_session->ssl)) {
		/*
		 *	Init is finished.  The rest is
		 *	application data.
		 */
		tls_session->info.content_type = application_data;
		return FR_TLS_SUCCESS;
	}

	/*
	 *	Who knows what happened...
	 */
	REDEBUG("TLS failed during operation");
	return FR_TLS_FAIL;
}
예제 #4
0
/*
 *	Do authentication, by letting EAP-TLS do most of the work.
 */
static int eapttls_authenticate(void *arg, EAP_HANDLER *handler)
{
	int rcode;
	fr_tls_status_t	status;
	rlm_eap_ttls_t *inst = (rlm_eap_ttls_t *) arg;
	tls_session_t *tls_session = (tls_session_t *) handler->opaque;
	ttls_tunnel_t *t = (ttls_tunnel_t *) tls_session->opaque;
	REQUEST *request = handler->request;

	RDEBUG2("Authenticate");

	tls_session->length_flag = inst->include_length;

	/*
	 *	Process TLS layer until done.
	 */
	status = eaptls_process(handler);
	RDEBUG2("eaptls_process returned %d\n", status);
	switch (status) {
		/*
		 *	EAP-TLS handshake was successful, tell the
		 *	client to keep talking.
		 *
		 *	If this was EAP-TLS, we would just return
		 *	an EAP-TLS-Success packet here.
		 */
	case FR_TLS_SUCCESS:
		if (SSL_session_reused(tls_session->ssl)) {
			RDEBUG("Skipping Phase2 due to session resumption");
			goto do_keys;
		}

		if (t && t->authenticated) {
			RDEBUG2("Using saved attributes from the original Access-Accept");
			debug_pair_list(t->accept_vps);
			pairadd(&handler->request->reply->vps,
				t->accept_vps);
			t->accept_vps = NULL;
		do_keys:
			/*
			 *	Success: Automatically return MPPE keys.
			 */
			return eaptls_success(handler, 0);
		} else {
			eaptls_request(handler->eap_ds, tls_session);
		}
		return 1;

		/*
		 *	The TLS code is still working on the TLS
		 *	exchange, and it's a valid TLS request.
		 *	do nothing.
		 */
	case FR_TLS_HANDLED:
		return 1;

		/*
		 *	Handshake is done, proceed with decoding tunneled
		 *	data.
		 */
	case FR_TLS_OK:
		break;

		/*
		 *	Anything else: fail.
		 */
	default:
		return 0;
	}

	/*
	 *	Session is established, proceed with decoding
	 *	tunneled data.
	 */
	RDEBUG2("Session established.  Proceeding to decode tunneled attributes.");

	/*
	 *	We may need TTLS data associated with the session, so
	 *	allocate it here, if it wasn't already alloacted.
	 */
	if (!tls_session->opaque) {
		tls_session->opaque = ttls_alloc(inst);
		tls_session->free_opaque = ttls_free;
	}

	/*
	 *	Process the TTLS portion of the request.
	 */
	rcode = eapttls_process(handler, tls_session);
	switch (rcode) {
	case PW_AUTHENTICATION_REJECT:
		eaptls_fail(handler, 0);
		return 0;

		/*
		 *	Access-Challenge, continue tunneled conversation.
		 */
	case PW_ACCESS_CHALLENGE:
		eaptls_request(handler->eap_ds, tls_session);
		return 1;

		/*
		 *	Success: Automatically return MPPE keys.
		 */
	case PW_AUTHENTICATION_ACK:
		return eaptls_success(handler, 0);

		/*
		 *	No response packet, MUST be proxying it.
		 *	The main EAP module will take care of discovering
		 *	that the request now has a "proxy" packet, and
		 *	will proxy it, rather than returning an EAP packet.
		 */
	case PW_STATUS_CLIENT:
#ifdef WITH_PROXY
		rad_assert(handler->request->proxy != NULL);
#endif
		return 1;
		break;

	default:
		break;
	}

	/*
	 *	Something we don't understand: Reject it.
	 */
	eaptls_fail(handler, 0);
	return 0;
}
예제 #5
0
/*
 *	Process an EAP request
 */
fr_tls_status_t eaptls_process(eap_handler_t *handler)
{
	tls_session_t *tls_session = (tls_session_t *) handler->opaque;
	EAPTLS_PACKET	*tlspacket;
	fr_tls_status_t	status;
	REQUEST *request = handler->request;

	if (!request) return FR_TLS_FAIL;

	RDEBUG2("processing EAP-TLS");
	SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_REQUEST, request);

	if (handler->certs) pairadd(&request->packet->vps,
				    paircopy(request->packet, handler->certs));

	/* 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);
	RDEBUG2("eaptls_verify returned %d\n", status);

	switch (status) {
	default:
	case FR_TLS_INVALID:
	case FR_TLS_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 FR_TLS_SUCCESS:
		goto done;

		/*
		 *	Normal TLS request, continue with the "get rest
		 *	of fragments" phase.
		 */
	case FR_TLS_REQUEST:
		eaptls_request(handler->eap_ds, tls_session);
		status = FR_TLS_HANDLED;
		goto done;

		/*
		 *	The handshake is done, and we're in the "tunnel
		 *	data" phase.
		 */
	case FR_TLS_OK:
		RDEBUG2("Done initial handshake");

		/*
		 *	Get the rest of the fragments.
		 */
	case FR_TLS_FIRST_FRAGMENT:
	case FR_TLS_MORE_FRAGMENTS:
	case FR_TLS_LENGTH_INCLUDED:
	case FR_TLS_MORE_FRAGMENTS_WITH_LENGTH:
		break;
	}

	/*
	 *	Extract the TLS packet from the buffer.
	 */
	if ((tlspacket = eaptls_extract(request, handler->eap_ds, status)) == NULL) {
		status = FR_TLS_FAIL;
		goto done;
	}

	/*
	 *	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)) {
		talloc_free(tlspacket);
		RDEBUG("Exceeded maximum record size");
		status =FR_TLS_FAIL;
		goto done;
	}

	/*
	 *	No longer needed.
	 */
	talloc_free(tlspacket);

	/*
	 *	SSL initalization is done.  Return.
	 *
	 *	The TLS data will be in the tls_session structure.
	 */
	if (SSL_is_init_finished(tls_session->ssl)) {
		/*
		 *	The initialization may be finished, but if
		 *	there more fragments coming, then send ACK,
		 *	and get the caller to continue the
		 *	conversation.
		 */
		if ((status == FR_TLS_MORE_FRAGMENTS) ||
		    (status == FR_TLS_MORE_FRAGMENTS_WITH_LENGTH) ||
		    (status == FR_TLS_FIRST_FRAGMENT)) {
			/*
			 *	Send the ACK.
			 */
			eaptls_send_ack(handler->eap_ds,
					tls_session->peap_flag);
			RDEBUG2("Init is done, but tunneled data is fragmented");
			status = FR_TLS_HANDLED;
			goto done;
		}

		status = tls_application_data(tls_session, request);
		goto done;
	}

	/*
	 *	Continue the handshake.
	 */
	status = eaptls_operation(status, handler);

 done:
	SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_REQUEST, NULL);

	return status;
}
예제 #6
0
/*
 *	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;
	REQUEST *request = handler->request;

	RDEBUG2("processing EAP-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);
	RDEBUG2("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:
		RDEBUG2("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(request, 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);
		RDEBUG("Exceeded maximum record size");
		return EAPTLS_FAIL;
	}

	/*
	 *	No longer needed.
	 */
	eaptls_free(&tlspacket);

	/*
	 *	SSL initalization is done.  Return.
	 *
	 *	The TLS data will be in the tls_session structure.
	 */
	if (SSL_is_init_finished(tls_session->ssl)) {
		int err;

		/*
		 *	The initialization may be finished, but if
		 *	there more fragments coming, then send ACK,
		 *	and get the caller to continue the
		 *	conversation.
		 */	
	        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);
			RDEBUG2("Init is done, but tunneled data is fragmented");
			return EAPTLS_HANDLED;
		}

		/*	
		 *	Decrypt the complete record.
		 */
		BIO_write(tls_session->into_ssl, tls_session->dirty_in.data,
			  tls_session->dirty_in.used);

		/*
		 *      Clear the dirty buffer now that we are done with it
		 *      and init the clean_out buffer to store decrypted data
		 */
		(tls_session->record_init)(&tls_session->dirty_in);
		(tls_session->record_init)(&tls_session->clean_out);

		/*
		 *      Read (and decrypt) the tunneled data from the
		 *      SSL session, and put it into the decrypted
		 *      data buffer.
		 */
		err = SSL_read(tls_session->ssl, tls_session->clean_out.data,
			       sizeof(tls_session->clean_out.data));

		if (err < 0) {
			RDEBUG("SSL_read Error");

			switch (SSL_get_error(tls_session->ssl, err)) {
			case SSL_ERROR_WANT_READ:
			case SSL_ERROR_WANT_WRITE:
				RDEBUG("Error in fragmentation logic");
				break;
			default:
				/*
				 *	FIXME: Call int_ssl_check?
				 */
				break;
			}
			return EAPTLS_FAIL;
		}

		if (err == 0) {
			RDEBUG("WARNING: No data inside of the tunnel.");
		}
	
		/*
		 *	Passed all checks, successfully decrypted data
		 */
		tls_session->clean_out.used = err;
		
		return EAPTLS_OK;
	}

	/*
	 *	Continue the handshake.
	 */
	return eaptls_operation(status, handler);
}
예제 #7
0
/*
 *	Do post-proxy processing,
 */
static int CC_HINT(nonnull) eapttls_postproxy(eap_handler_t *handler, void *data)
{
	int rcode;
	tls_session_t *tls_session = (tls_session_t *) data;
	REQUEST *fake, *request = handler->request;

	RDEBUG("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_CODE_ACCESS_ACCEPT)) {
		/*
		 *	Terrible hacks.
		 */
		rad_assert(!fake->packet);
		fake->packet = talloc_steal(fake, request->proxy);
		fake->packet->src_ipaddr = request->packet->src_ipaddr;
		request->proxy = NULL;

		rad_assert(!fake->reply);
		fake->reply = talloc_steal(fake, request->proxy_reply);
		request->proxy_reply = NULL;

		if ((rad_debug_lvl > 0) && fr_log_fp) {
			fprintf(fr_log_fp, "server %s {\n",
				(!fake->server) ? "" : fake->server);
		}

		/*
		 *	Perform a post-auth stage for the tunneled
		 *	session.
		 */
		fake->options &= ~RAD_REQUEST_OPTION_PROXY_EAP;
		rcode = rad_postauth(fake);
		RDEBUG2("post-auth returns %d", rcode);

		if ((rad_debug_lvl > 0) && fr_log_fp) {
			fprintf(fr_log_fp, "} # server %s\n",
				(!fake->server) ? "" : fake->server);

			RDEBUG("Final reply from tunneled session code %d", fake->reply->code);
			rdebug_pair_list(L_DBG_LVL_1, request, fake->reply->vps, NULL);
		}

		/*
		 *	Terrible hacks.
		 */
		request->proxy = talloc_steal(request, fake->packet);
		fake->packet = NULL;
		request->proxy_reply = talloc_steal(request, fake->reply);
		fake->reply = NULL;

		/*
		 *	And we're done with this request.
		 */

		switch (rcode) {
		case RLM_MODULE_FAIL:
			talloc_free(fake);
			eaptls_fail(handler, 0);
			return 0;

		default:  /* Don't Do Anything */
			RDEBUG2("Got reply %d",
			       request->proxy_reply->code);
			break;
		}
	}
	talloc_free(fake);	/* robust if !fake */

	/*
	 *	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.
	 */
	fr_pair_list_free(&handler->request->proxy_reply->vps);

	switch (rcode) {
	case RLM_MODULE_REJECT:
		RDEBUG("Reply was rejected");
		break;

	case RLM_MODULE_HANDLED:
		RDEBUG("Reply was handled");
		eaptls_request(handler->eap_ds, tls_session);
		request->proxy_reply->code = PW_CODE_ACCESS_CHALLENGE;
		return 1;

	case RLM_MODULE_OK:
		RDEBUG("Reply was OK");

		/*
		 *	Success: Automatically return MPPE keys.
		 */
		return eaptls_success(handler, 0);

	default:
		RDEBUG("Reply was unknown");
		break;
	}

	eaptls_fail(handler, 0);
	return 0;
}