Пример #1
0
/*
 *	Authenticate a previously sent challenge.
 */
static int md5_authenticate(UNUSED void *arg, EAP_HANDLER *handler)
{
    MD5_PACKET	*packet;
    MD5_PACKET	*reply;
    VALUE_PAIR	*password;

    /*
     *	Get the Cleartext-Password for this user.
     */
    rad_assert(handler->request != NULL);
    rad_assert(handler->stage == AUTHENTICATE);

    password = pairfind(handler->request->config_items, PW_CLEARTEXT_PASSWORD);
    if (password == NULL) {
        DEBUG2("rlm_eap_md5: Cleartext-Password is required for EAP-MD5 authentication");
        return 0;
    }

    /*
     *	Extract the EAP-MD5 packet.
     */
    if (!(packet = eapmd5_extract(handler->eap_ds)))
        return 0;

    /*
     *	Create a reply, and initialize it.
     */
    reply = eapmd5_alloc();
    if (!reply) {
        eapmd5_free(&packet);
        return 0;
    }
    reply->id = handler->eap_ds->request->id;
    reply->length = 0;

    /*
     *	Verify the received packet against the previous packet
     *	(i.e. challenge) which we sent out.
     */
    if (eapmd5_verify(packet, password, handler->opaque)) {
        reply->code = PW_MD5_SUCCESS;
    } else {
        reply->code = PW_MD5_FAILURE;
    }

    /*
     *	Compose the EAP-MD5 packet out of the data structure,
     *	and free it.
     */
    eapmd5_compose(handler->eap_ds, reply);

    eapmd5_free(&packet);
    return 1;
}
Пример #2
0
/*
 *	Compose the portions of the reply packet specific to the
 *	EAP-MD5 protocol, in the EAP reply typedata
 */
int eapmd5_compose(EAP_DS *eap_ds, MD5_PACKET *reply)
{
	uint8_t *ptr;
	unsigned short name_len;

	/*
	 *	We really only send Challenge (EAP-Identity),
	 *	and EAP-Success, and EAP-Failure.
	 */
	if (reply->code < 3) {
		eap_ds->request->type.type = PW_EAP_MD5;

		rad_assert(reply->length > 0);

		eap_ds->request->type.data = malloc(reply->length);
		if (eap_ds->request->type.data == NULL) {
			eapmd5_free(&reply);
			radlog(L_ERR, "rlm_eap_md5: out of memory");
			return 0;
		}
		ptr = eap_ds->request->type.data;
		*ptr++ = (uint8_t)(reply->value_size & 0xFF);
		memcpy(ptr, reply->value, reply->value_size);

		/* Just the Challenge length */
		eap_ds->request->type.length = reply->value_size + 1;

		/*
		 *	Return the name, if necessary.
		 *
		 *	Don't see why this is *ever* necessary...
		 */
		name_len = reply->length - (reply->value_size + 1);
		if (name_len && reply->name) {
			ptr += reply->value_size;
			memcpy(ptr, reply->name, name_len);
			/* Challenge length + Name length */
			eap_ds->request->type.length += name_len;
		}
	} else {
		eap_ds->request->type.length = 0;
		/* TODO: In future we might add message here wrt rfc1994 */
	}
	eap_ds->request->code = reply->code;

	eapmd5_free(&reply);

	return 1;
}
Пример #3
0
/*
 * If an EAP MD5 request needs to be initiated then
 * create such a packet.
 */
MD5_PACKET *eapmd5_initiate(EAP_DS *eap_ds)
{
	MD5_PACKET 	*reply;

	reply = eapmd5_alloc();
	if (reply == NULL)  {
		radlog(L_ERR, "rlm_eap_md5: out of memory");
		return NULL;
	}

	reply->code = PW_MD5_CHALLENGE;
	reply->length = MD5_HEADER_LEN + 1/*value_size*/ + MD5_LEN;
	reply->value_size = MD5_LEN;

	reply->value = malloc(reply->value_size);
	if (reply->value == NULL) {
		radlog(L_ERR, "rlm_eap_md5: out of memory");
		eapmd5_free(&reply);
		return NULL;
	}

	eapmd5_challenge(reply->value, reply->value_size);

	return reply;
}
Пример #4
0
/* 
 * We expect only RESPONSE for which CHALLENGE, SUCCESS or FAILURE is sent back
 */ 
MD5_PACKET *eapmd5_extract(EAP_DS *eap_ds)
{
	md5_packet_t	*data;
	MD5_PACKET	*packet;
	unsigned short	name_len;

	if (!eap_ds 					|| 
	    !eap_ds->response 				|| 
	    (eap_ds->response->code != PW_MD5_RESPONSE)	||
	    eap_ds->response->type.type != PW_EAP_MD5	||
	    !eap_ds->response->type.data 		||
	    (eap_ds->response->length < MD5_HEADER_LEN)	||
	    (eap_ds->response->type.data[0] <= 0)	) {
	  
		radlog(L_ERR, "rlm_eap_md5: corrupted data");
		return NULL;
	}

	packet = eapmd5_alloc();
	if (!packet) return NULL;

	/*
	 * Code, id & length for MD5 & EAP are same
	 * but md5_length = eap_length - 1(Type = 1 octet)
	 */
	packet->code = eap_ds->response->code;
	packet->id = eap_ds->response->id;
	packet->length = eap_ds->response->length - 1;
	packet->value_size = 0;
	packet->value = NULL;
	packet->name = NULL;

	data = (md5_packet_t *)eap_ds->response->type.data;

	packet->value_size = data->value_size;
	if (packet->value_size < 1) {
		radlog(L_ERR, "rlm_eap_md5: Value size is too small");
		eapmd5_free(&packet);
		return NULL;
	}

	packet->value = malloc(packet->value_size);
	if (packet->value == NULL) {
		radlog(L_ERR, "rlm_eap_md5: out of memory");
		eapmd5_free(&packet);
		return NULL;
	}
	memcpy(packet->value, data->value_name, packet->value_size);

	/*
	 * Name is optional and is present after Value, but we need to check for it
	 */
	name_len =  packet->length - (packet->value_size + 5);
	if (name_len) {
		packet->name = malloc(name_len+1);
		if (!packet->name) {
			radlog(L_ERR, "rlm_eap_md5: out of memory");
			eapmd5_free(&packet);
			return NULL;
		}
		memset(packet->name, 0, name_len+1);
		memcpy(packet->name, data->value_name+packet->value_size, name_len);
	}

	return packet;
}
Пример #5
0
/*
 * Identify whether the response that you got is either the
 * response to the challenge that we sent or a new one.
 * If it is a response to the request then issue success/failure
 * else issue a challenge
 */
MD5_PACKET *eapmd5_process(MD5_PACKET *packet, int id,
		VALUE_PAIR *username, VALUE_PAIR* password, md5_packet_t *request)
{
	unsigned char output[MAX_STRING_LEN];
	MD5_PACKET *reply;

	if (!username || !password || !packet)
		return NULL;

	reply = eapmd5_alloc();
	if (!reply) return NULL;
	memset(output, 0, MAX_STRING_LEN);
	reply->id = id;
	
	if (request) {
		/* verify and issue Success/failure */
		if (eapmd5_verify(packet, password, request) == 0) {
			radlog(L_INFO, "rlm_eap_md5: Challenge failed");
			reply->code = PW_MD5_FAILURE;
		}
		else {
			reply->code = PW_MD5_SUCCESS;
		}

	} else {
		/*
		 * Previous request not found.
		 * Probably it is timed out.
		 * So send another challenge.
		 * TODO: Later Send these challenges for the configurable
		 * 		number of times for each user & stop.
		 */

		/*
		 *	Ensure that the challenge is always of the correct
		 *	length.  i.e. Don't take value size from data
		 *	supplied by the client.
		 */
		if (reply->value_size != MD5_LEN) {
			free(reply->value);
			reply->value_size = MD5_LEN;
			reply->value = malloc(reply->value_size);
		}

		eapmd5_challenge(reply->value, reply->value_size);
		reply->code = PW_MD5_CHALLENGE;
		radlog(L_INFO, "rlm_eap_md5: Previous request not found");
		radlog(L_INFO, "rlm_eap_md5: Issuing Challenge to the user - %s",
			(char *)username->strvalue);
	}

	/* fill reply packet */
	if (reply->code == PW_MD5_CHALLENGE) {
		reply->value_size = packet->value_size;
		reply->value = malloc(reply->value_size);
		if (reply->value == NULL) {
			radlog(L_ERR, "rlm_eap_md5: out of memory");
			eapmd5_free(&reply);
			return NULL;
		}
		memcpy(reply->value, output, reply->value_size);
		reply->length = packet->length;
	} else {
		reply->length = MD5_HEADER_LEN;
	}
	
	return reply;
}
Пример #6
0
/*
 *	Initiate the EAP-MD5 session by sending a challenge to the peer.
 */
static int md5_initiate(void *type_data, EAP_HANDLER *handler)
{
    int		i;
    MD5_PACKET	*reply;

    type_data = type_data;	/* -Wunused */

    /*
     *	Allocate an EAP-MD5 packet.
     */
    reply = eapmd5_alloc();
    if (reply == NULL)  {
        radlog(L_ERR, "rlm_eap_md5: out of memory");
        return 0;
    }

    /*
     *	Fill it with data.
     */
    reply->code = PW_MD5_CHALLENGE;
    reply->length = 1 + MD5_CHALLENGE_LEN; /* one byte of value size */
    reply->value_size = MD5_CHALLENGE_LEN;

    /*
     *	Allocate user data.
     */
    reply->value = malloc(reply->value_size);
    if (reply->value == NULL) {
        radlog(L_ERR, "rlm_eap_md5: out of memory");
        eapmd5_free(&reply);
        return 0;
    }

    /*
     *	Get a random challenge.
     */
    for (i = 0; i < reply->value_size; i++) {
        reply->value[i] = fr_rand();
    }
    DEBUG2("rlm_eap_md5: Issuing Challenge");

    /*
     *	Keep track of the challenge.
     */
    handler->opaque = malloc(reply->value_size);
    rad_assert(handler->opaque != NULL);
    memcpy(handler->opaque, reply->value, reply->value_size);
    handler->free_opaque = free;

    /*
     *	Compose the EAP-MD5 packet out of the data structure,
     *	and free it.
     */
    eapmd5_compose(handler->eap_ds, reply);

    /*
     *	We don't need to authorize the user at this point.
     *
     *	We also don't need to keep the challenge, as it's
     *	stored in 'handler->eap_ds', which will be given back
     *	to us...
     */
    handler->stage = AUTHENTICATE;

    return 1;
}
Пример #7
0
/*
 *	We expect only RESPONSE for which SUCCESS or FAILURE is sent back
 */
MD5_PACKET *eapmd5_extract(EAP_DS *eap_ds)
{
	md5_packet_t	*data;
	MD5_PACKET	*packet;
	unsigned short	name_len;

	/*
	 *	We need a response, of type EAP-MD5, with at least
	 *	one byte of type data (EAP-MD5) following the 4-byte
	 *	EAP-Packet header.
	 */
	if (!eap_ds 					 ||
	    !eap_ds->response 				 ||
	    (eap_ds->response->code != PW_MD5_RESPONSE)	 ||
	    eap_ds->response->type.type != PW_EAP_MD5	 ||
	    !eap_ds->response->type.data 		 ||
	    (eap_ds->response->length <= MD5_HEADER_LEN) ||
	    (eap_ds->response->type.data[0] <= 0)) {
		radlog(L_ERR, "rlm_eap_md5: corrupted data");
		return NULL;
	}

	packet = eapmd5_alloc();
	if (!packet) return NULL;

	/*
	 *	Code & id for MD5 & EAP are same
	 *
	 *	but md5_length = length of the EAP-MD5 data, which
	 *	doesn't include the EAP header, or the octet saying
	 *	EAP-MD5.
	 */
	packet->code = eap_ds->response->code;
	packet->id = eap_ds->response->id;
	packet->length = eap_ds->response->length - (MD5_HEADER_LEN + 1);

	/*
	 *	Sanity check the EAP-MD5 packet sent to us
	 *	by the client.
	 */
	data = (md5_packet_t *)eap_ds->response->type.data;

	/*
	 *	Already checked the size above.
	 */
	packet->value_size = data->value_size;

	/*
	 *	Allocate room for the data, and copy over the data.
	 */
	packet->value = malloc(packet->value_size);
	if (packet->value == NULL) {
		radlog(L_ERR, "rlm_eap_md5: out of memory");
		eapmd5_free(&packet);
		return NULL;
	}
	memcpy(packet->value, data->value_name, packet->value_size);

	/*
	 *	Name is optional and is present after Value, but we
	 *	need to check for it, as eapmd5_compose()
	 */
	name_len =  packet->length - (packet->value_size + 1);
	if (name_len) {
		packet->name = malloc(name_len + 1);
		if (!packet->name) {
			radlog(L_ERR, "rlm_eap_md5: out of memory");
			eapmd5_free(&packet);
			return NULL;
		}
		memcpy(packet->name, data->value_name + packet->value_size,
		       name_len);
		packet->name[name_len] = 0;
	}

	return packet;
}