Пример #1
0
/** Send a failure message
 *
 */
static int eap_sim_send_eap_failure_notification(eap_session_t *eap_session)
{
	REQUEST			*request = eap_session->request;
	RADIUS_PACKET		*packet = eap_session->request->reply;
	fr_cursor_t		cursor;
	VALUE_PAIR		*vp;
	eap_sim_session_t	*eap_sim_session = talloc_get_type_abort(eap_session->opaque, eap_sim_session_t);

	fr_cursor_init(&cursor, &packet->vps);

	vp = fr_pair_find_by_da(packet->vps, attr_eap_sim_notification, TAG_ANY);
	if (!vp) {
		vp = fr_pair_afrom_da(packet, attr_eap_sim_notification);
		vp->vp_uint16 = FR_EAP_SIM_NOTIFICATION_VALUE_GENERAL_FAILURE;
		fr_cursor_append(&cursor, vp);
	}

	/*
	 *	Change the failure notification depending where
	 *	we are in the state machine.
	 */
	if (eap_sim_session->challenge_success) {
		vp->vp_uint16 &= ~0x4000;	/* Unset phase bit */
	} else {
		vp->vp_uint16 |= 0x4000;	/* Set phase bit */
	}
	vp->vp_uint16 &= ~0x8000;               /* In both cases success bit should be low */

	RDEBUG2("Sending SIM-Notification (%pV)", &vp->data);
	eap_session->this_round->request->code = FR_EAP_CODE_REQUEST;

	/*
	 *	Set the subtype to notification
	 */
	vp = fr_pair_afrom_da(packet, attr_eap_sim_subtype);
	vp->vp_uint16 = FR_EAP_SIM_SUBTYPE_VALUE_SIM_NOTIFICATION;
	fr_cursor_append(&cursor, vp);

	/*
	 *	If we're after the challenge phase
	 *	then we need to include a MAC to
	 *	protect notifications.
	 */
	if (eap_sim_session->challenge_success) {
		vp = fr_pair_afrom_da(packet, attr_eap_sim_mac);
		fr_pair_replace(&packet->vps, vp);
	}

	/*
	 *	Encode the packet
	 */
	if (eap_sim_compose(eap_session, NULL, 0) < 0) {
		fr_pair_list_free(&packet->vps);
		return -1;
	}

	return 0;
}
Пример #2
0
/** Send a success notification
 *
 */
static int eap_sim_send_eap_success_notification(eap_session_t *eap_session)
{
	REQUEST			*request = eap_session->request;
	RADIUS_PACKET		*packet = eap_session->request->reply;
	eap_sim_session_t	*eap_sim_session = talloc_get_type_abort(eap_session->opaque, eap_sim_session_t);
	fr_cursor_t		cursor;
	VALUE_PAIR		*vp;

	RDEBUG2("Sending SIM-Notification (Success)");
	eap_session->this_round->request->code = FR_EAP_CODE_REQUEST;

	if (!fr_cond_assert(eap_sim_session->challenge_success)) return -1;

	fr_cursor_init(&cursor, &packet->vps);

	/*
	 *	Set the subtype to notification
	 */
	vp = fr_pair_afrom_da(packet, attr_eap_sim_subtype);
	vp->vp_uint16 = FR_EAP_SIM_SUBTYPE_VALUE_SIM_NOTIFICATION;
	fr_cursor_append(&cursor, vp);

	vp = fr_pair_afrom_da(packet, attr_eap_sim_notification);
	vp->vp_uint16 = FR_EAP_SIM_NOTIFICATION_VALUE_SUCCESS;
	fr_cursor_append(&cursor, vp);

	/*
	 *	Need to include an AT_MAC attribute so that it will get
	 *	calculated.
	 */
	vp = fr_pair_afrom_da(packet, attr_eap_sim_mac);
	fr_pair_replace(&packet->vps, vp);

	/*
	 *	Encode the packet
	 */
	if (eap_sim_compose(eap_session, NULL, 0) < 0) {
		fr_pair_list_free(&packet->vps);
		return -1;
	}

	return 0;
}
Пример #3
0
/*
 * run the server state machine.
 */
static void eap_sim_stateenter(EAP_HANDLER *handler,
			       struct eap_sim_server_state *ess,
			       enum eapsim_serverstates newstate)
{
	switch(newstate) {
	case eapsim_server_start:
		/*
		 * send the EAP-SIM Start message, listing the
		 * versions that we support.
		 */
		eap_sim_sendstart(handler);
		break;

	case eapsim_server_challenge:
		/*
		 * send the EAP-SIM Challenge message.
		 */
		eap_sim_sendchallenge(handler);
		break;

	case eapsim_server_success:
		/*
		 * send the EAP Success message
		 */
  	        eap_sim_sendsuccess(handler);
		handler->eap_ds->request->code = PW_EAP_SUCCESS;
		break;

	default:
		/*
		 * nothing to do for this transition.
		 */
		break;
	}

	ess->state = newstate;

	/* build the target packet */
	eap_sim_compose(handler);
}
/** Run the server state machine
 *
 */
static void eap_sim_stateenter(eap_handler_t *handler,
			       eap_sim_state_t *ess,
			       enum eapsim_serverstates newstate)
{
	switch(newstate) {
	/*
	 * 	Send the EAP-SIM Start message, listing the versions that we support.
	 */
	case EAPSIM_SERVER_START:
		eap_sim_sendstart(handler);
		break;
	/*
	 *	Send the EAP-SIM Challenge message.
	 */
	case EAPSIM_SERVER_CHALLENGE:
		eap_sim_sendchallenge(handler);
		break;

	/*
	 * 	Send the EAP Success message
	 */
	case EAPSIM_SERVER_SUCCESS:
		eap_sim_sendsuccess(handler);
		handler->eap_ds->request->code = PW_EAP_SUCCESS;
		break;
	/*
	 *	Nothing to do for this transition.
	 */
	default:

		break;
	}

	ess->state = newstate;

	/* build the target packet */
	eap_sim_compose(handler);
}
Пример #5
0
/** Send NONCE_S and re-key
 *
 */
static int eap_sim_send_reauthentication(eap_session_t *eap_session)
{
	REQUEST			*request = eap_session->request;
	eap_sim_session_t	*eap_sim_session = talloc_get_type_abort(eap_session->opaque, eap_sim_session_t);
	VALUE_PAIR		**to_peer, *vp, *mk, *counter;
	RADIUS_PACKET		*packet;

	rad_assert(eap_session->request != NULL);
	rad_assert(eap_session->request->reply);

	/*
	 *	to_peer is the data to the client
	 */
	packet = eap_session->request->reply;
	to_peer = &packet->vps;

	/*
	 *	If any of the session resumption inputs (on our side)
	 *	are missing or malformed, return an error code
	 *	and the state machine will jump to the start state.
	 */
	mk = fr_pair_find_by_da(request->control, attr_eap_sim_mk, TAG_ANY);
	if (!mk) {
		RWDEBUG2("Missing &control:EAP-SIM-MK, skipping session resumption");
		return -1;
	}
	if (mk->vp_length != SIM_MK_SIZE) {
		RWDEBUG("&control:EAP-SIM-MK has incorrect length, expected %u bytes got %zu bytes",
			SIM_MK_SIZE, mk->vp_length);
		return -1;
	}
	counter = fr_pair_find_by_da(request->control, attr_eap_sim_counter, TAG_ANY);
	if (!counter) {
		RWDEBUG2("Missing &control:EAP-SIM-Counter, skipping session resumption");
		return -1;
	}

	/*
	 *	All set, calculate keys!
	 */
	fr_sim_crypto_keys_init_kdf_0_reauth(&eap_sim_session->keys, mk->vp_octets, counter->vp_uint16);
	fr_sim_crypto_kdf_0_reauth(&eap_sim_session->keys);
	if (RDEBUG_ENABLED3) fr_sim_crypto_keys_log(request, &eap_sim_session->keys);

	RDEBUG2("Sending SIM-Reauthentication");
	eap_session->this_round->request->code = FR_EAP_CODE_REQUEST;

	/*
	 *	Set subtype to challenge.
	 */
	vp = fr_pair_afrom_da(packet, attr_eap_sim_subtype);
	vp->vp_uint16 = EAP_SIM_REAUTH;
	fr_pair_replace(to_peer, vp);

	/*
	 *	Add nonce_s
	 */
	MEM(vp = fr_pair_afrom_da(packet, attr_eap_sim_nonce_s));
	fr_pair_value_memcpy(vp, eap_sim_session->keys.reauth.nonce_s, sizeof(eap_sim_session->keys.reauth.nonce_s));
	fr_pair_replace(to_peer, vp);

	/*
	 *	Indicate we'd like to use protected success messages
	 */
	if (eap_sim_session->send_result_ind) {
		MEM(vp = fr_pair_afrom_da(packet, attr_eap_sim_result_ind));
		vp->vp_bool = true;
		fr_pair_replace(to_peer, vp);
	}

	/*
	 *	Need to include an AT_MAC attribute so that it will get
	 *	calculated.
	 */
	vp = fr_pair_afrom_da(packet, attr_eap_sim_mac);
	fr_pair_replace(to_peer, vp);

	/*
	 *	We've sent the challenge so the peer should now be able
	 *	to accept encrypted attributes.
	 */
	eap_sim_session->allow_encrypted = true;

	/*
	 *	Encode the packet
	 */
	if (eap_sim_compose(eap_session, NULL, 0) < 0) {
		fr_pair_list_free(&packet->vps);
		return -1;
	}

	return 0;
}
Пример #6
0
/** Send the challenge itself
 *
 * Challenges will come from one of three places eventually:
 *
 * 1  from attributes like FR_EAP_SIM_RANDx
 *	    (these might be retrieved from a database)
 *
 * 2  from internally implemented SIM authenticators
 *	    (a simple one based upon XOR will be provided)
 *
 * 3  from some kind of SS7 interface.
 *
 * For now, they only come from attributes.
 * It might be that the best way to do 2/3 will be with a different
 * module to generate/calculate things.
 */
static int eap_sim_send_challenge(eap_session_t *eap_session)
{
	REQUEST			*request = eap_session->request;
	eap_sim_session_t	*eap_sim_session = talloc_get_type_abort(eap_session->opaque, eap_sim_session_t);
	VALUE_PAIR		**to_peer, *vp;
	RADIUS_PACKET		*packet;
	fr_sim_vector_src_t	src = SIM_VECTOR_SRC_AUTO;

	rad_assert(eap_session->request != NULL);
	rad_assert(eap_session->request->reply);

	RDEBUG2("Acquiring GSM vector(s)");
	if ((fr_sim_vector_gsm_from_attrs(eap_session, request->control, 0, &eap_sim_session->keys, &src) != 0) ||
	    (fr_sim_vector_gsm_from_attrs(eap_session, request->control, 1, &eap_sim_session->keys, &src) != 0) ||
	    (fr_sim_vector_gsm_from_attrs(eap_session, request->control, 2, &eap_sim_session->keys, &src) != 0)) {
	    	REDEBUG("Failed retrieving SIM vectors");
		return RLM_MODULE_FAIL;
	}

	/*
	 *	All set, calculate keys!
	 */
	fr_sim_crypto_kdf_0_gsm(&eap_sim_session->keys);
	if (RDEBUG_ENABLED3) fr_sim_crypto_keys_log(request, &eap_sim_session->keys);

	RDEBUG2("Sending SIM-Challenge");
	eap_session->this_round->request->code = FR_EAP_CODE_REQUEST;

	/*
	 *	to_peer is the data to the client
	 */
	packet = eap_session->request->reply;
	to_peer = &packet->vps;

	/*
	 *	Okay, we got the challenges! Put them into attributes.
	 */
	MEM(vp = fr_pair_afrom_da(packet, attr_eap_sim_rand));
	fr_pair_value_memcpy(vp, eap_sim_session->keys.gsm.vector[0].rand, SIM_VECTOR_GSM_RAND_SIZE);
	fr_pair_add(to_peer, vp);

	MEM(vp = fr_pair_afrom_da(packet, attr_eap_sim_rand));
	fr_pair_value_memcpy(vp, eap_sim_session->keys.gsm.vector[1].rand, SIM_VECTOR_GSM_RAND_SIZE);
	fr_pair_add(to_peer, vp);

	MEM(vp = fr_pair_afrom_da(packet, attr_eap_sim_rand));
	fr_pair_value_memcpy(vp, eap_sim_session->keys.gsm.vector[2].rand, SIM_VECTOR_GSM_RAND_SIZE);
	fr_pair_add(to_peer, vp);

	/*
	 *	Set subtype to challenge.
	 */
	vp = fr_pair_afrom_da(packet, attr_eap_sim_subtype);
	vp->vp_uint16 = EAP_SIM_CHALLENGE;
	fr_pair_replace(to_peer, vp);

	/*
	 *	Indicate we'd like to use protected success messages
	 */
	if (eap_sim_session->send_result_ind) {
		MEM(vp = fr_pair_afrom_da(packet, attr_eap_sim_result_ind));
		vp->vp_bool = true;
		fr_pair_replace(to_peer, vp);
	}

	/*
	 *	Need to include an AT_MAC attribute so that it will get
	 *	calculated.
	 */
	vp = fr_pair_afrom_da(packet, attr_eap_sim_mac);
	fr_pair_replace(to_peer, vp);

	/*
	 *	We've sent the challenge so the peer should now be able
	 *	to accept encrypted attributes.
	 */
	eap_sim_session->allow_encrypted = true;

	/*
	 *	Encode the packet
	 */
	if (eap_sim_compose(eap_session,
			    eap_sim_session->keys.gsm.nonce_mt, sizeof(eap_sim_session->keys.gsm.nonce_mt)) < 0) {
		fr_pair_list_free(&packet->vps);
		return -1;
	}

	return 0;
}
Пример #7
0
/*
 *	build a reply to be sent.
 */
static int eap_sim_compose(eap_session_t *eap_session, uint8_t const *hmac_extra, size_t hmac_extra_len)
{
	eap_sim_session_t	*eap_sim_session = talloc_get_type_abort(eap_session->opaque, eap_sim_session_t);
	fr_cursor_t		cursor;
	fr_cursor_t		to_encode;
	VALUE_PAIR		*head = NULL, *vp;
	REQUEST			*request = eap_session->request;
	fr_sim_encode_ctx_t	encoder_ctx = {
					.root = fr_dict_root(dict_eap_sim),
					.keys = &eap_sim_session->keys,

					.iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
						0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
					.iv_included = false,

					.hmac_md = EVP_sha1(),
					.eap_packet = eap_session->this_round->request,
					.hmac_extra = hmac_extra,
					.hmac_extra_len = hmac_extra_len
				};

	ssize_t			ret;

	/* we will set the ID on requests, since we have to HMAC it */
	eap_session->this_round->set_request_id = true;

	fr_cursor_init(&cursor, &eap_session->request->reply->vps);
	fr_cursor_init(&to_encode, &head);

	while ((vp = fr_cursor_current(&cursor))) {
		if (!fr_dict_parent_common(fr_dict_root(dict_eap_sim), vp->da, true)) {
			fr_cursor_next(&cursor);
			continue;
		}
		vp = fr_cursor_remove(&cursor);

		/*
		 *	Silently discard encrypted attributes until
		 *	the peer should have k_encr.  These can be
		 *	added by policy, and seem to cause
		 *	wpa_supplicant to fail if sent before the challenge.
		 */
		if (!eap_sim_session->allow_encrypted && fr_dict_parent_common(attr_eap_sim_encr_data, vp->da, true)) {
			RWDEBUG("Silently discarding &reply:%s: Encrypted attributes not allowed in this round",
				vp->da->name);
			talloc_free(vp);
			continue;
		}

		fr_cursor_append(&to_encode, vp);
	}

	RDEBUG2("Encoding EAP-SIM attributes");
	log_request_pair_list(L_DBG_LVL_2, request, head, NULL);

	eap_session->this_round->request->type.num = FR_EAP_SIM;
	eap_session->this_round->request->id = eap_sim_session->sim_id++ & 0xff;
	eap_session->this_round->set_request_id = true;

	ret = fr_sim_encode(eap_session->request, head, &encoder_ctx);
	fr_cursor_head(&to_encode);
	fr_cursor_free_list(&to_encode);

	if (ret < 0) {
		RPEDEBUG("Failed encoding EAP-SIM data");
		return -1;
	}
	return 0;
}

static int eap_sim_send_start(eap_session_t *eap_session)
{
	REQUEST			*request = eap_session->request;
	VALUE_PAIR		**vps, *vp;
	uint16_t		version;
	eap_sim_session_t	*eap_sim_session = talloc_get_type_abort(eap_session->opaque, eap_sim_session_t);
	RADIUS_PACKET		*packet;

	rad_assert(eap_session->request != NULL);
	rad_assert(eap_session->request->reply);

	RDEBUG2("Sending SIM-State");
	eap_session->this_round->request->code = FR_EAP_CODE_REQUEST;
	eap_sim_session->allow_encrypted = false;	/* In case this is after failed fast-resumption */

	/* these are the outgoing attributes */
	packet = eap_session->request->reply;
	vps = &packet->vps;
	rad_assert(vps != NULL);

	/*
	 *	Add appropriate TLVs for the EAP things we wish to send.
	 */
	vp = fr_pair_afrom_da(packet, attr_eap_sim_version_list);
	vp->vp_uint16 = EAP_SIM_VERSION;
	fr_pair_add(vps, vp);

	/* record it in the ess */
	version = htons(EAP_SIM_VERSION);
	memcpy(eap_sim_session->keys.gsm.version_list, &version, sizeof(version));
	eap_sim_session->keys.gsm.version_list_len = 2;

	/*
	 *	Select the right type of identity request attribute
	 */
	switch (eap_sim_session->id_req) {
	case SIM_ANY_ID_REQ:
		vp = fr_pair_afrom_da(packet, attr_eap_sim_any_id_req);
		break;

	case SIM_PERMANENT_ID_REQ:
		vp = fr_pair_afrom_da(packet, attr_eap_sim_permanent_id_req);
		break;

	case SIM_FULLAUTH_ID_REQ:
		vp = fr_pair_afrom_da(packet, attr_eap_sim_fullauth_id_req);
		break;

	default:
		rad_assert(0);
	}
	vp->vp_bool = true;
	fr_pair_replace(vps, vp);

	/* the SUBTYPE, set to start. */
	vp = fr_pair_afrom_da(packet, attr_eap_sim_subtype);
	vp->vp_uint16 = EAP_SIM_START;
	fr_pair_replace(vps, vp);

	/*
	 *	Encode the packet
	 */
	if (eap_sim_compose(eap_session, NULL, 0) < 0) {
		fr_pair_list_free(&packet->vps);
		return -1;
	}

	return 0;
}