Esempio n. 1
0
/*
 * verify = MD5(id+password+challenge_sent)
 */
int eapmd5_verify(MD5_PACKET *packet, VALUE_PAIR* password,
		  uint8_t *challenge)
{
	char	*ptr;
	char	string[1 + MAX_STRING_LEN*2];
	unsigned char output[MAX_STRING_LEN];
	unsigned short len;

	/*
	 *	Sanity check it.
	 */
	if (packet->value_size != 16) {
		radlog(L_ERR, "rlm_eap_md5: Expected 16 bytes of response to challenge, got %d", packet->value_size);
		return 0;
	}

	len = 0;
	ptr = string;

	/*
	 *	This is really rad_chap_pwencode()...
	 */
	*ptr++ = packet->id;
	len++;
	memcpy(ptr, password->vp_strvalue, password->length);
	ptr += password->length;
	len += password->length;

	/*
	 *	The challenge size is hard-coded.
	 */
	memcpy(ptr, challenge, MD5_CHALLENGE_LEN);
	len += MD5_CHALLENGE_LEN;

	fr_md5_calc((u_char *)output, (u_char *)string, len);

	/*
	 *	The length of the response is always 16 for MD5.
	 */
	if (memcmp(output, packet->value, 16) != 0) {
		return 0;
	}
	return 1;
}
Esempio n. 2
0
static int sendrecv_eap(RADIUS_PACKET *rep)
{
	RADIUS_PACKET *req = NULL;
	VALUE_PAIR *vp, *vpnext;
	int tried_eap_md5 = 0;

	if (!rep) return -1;

	/*
	 *	Keep a copy of the the User-Password attribute.
	 */
	if ((vp = pairfind(rep->vps, PW_CLEARTEXT_PASSWORD, 0, TAG_ANY)) != NULL) {
		strlcpy(password, vp->vp_strvalue, sizeof(password));

	} else 	if ((vp = pairfind(rep->vps, PW_USER_PASSWORD, 0, TAG_ANY)) != NULL) {
		strlcpy(password, vp->vp_strvalue, sizeof(password));
		/*
		 *	Otherwise keep a copy of the CHAP-Password attribute.
		 */
	} else if ((vp = pairfind(rep->vps, PW_CHAP_PASSWORD, 0, TAG_ANY)) != NULL) {
		strlcpy(password, vp->vp_strvalue, sizeof(password));
	} else {
		*password = '******';
	}

 again:
	rep->id++;

	/*
	 * if there are EAP types, encode them into an EAP-Message
	 *
	 */
	map_eap_methods(rep);

	/*
	 *  Fix up Digest-Attributes issues
	 */
	for (vp = rep->vps; vp != NULL; vp = vp->next) {
		switch (vp->da->attr) {
		default:
			break;

		case PW_DIGEST_REALM:
		case PW_DIGEST_NONCE:
		case PW_DIGEST_METHOD:
		case PW_DIGEST_URI:
		case PW_DIGEST_QOP:
		case PW_DIGEST_ALGORITHM:
		case PW_DIGEST_BODY_DIGEST:
		case PW_DIGEST_CNONCE:
		case PW_DIGEST_NONCE_COUNT:
		case PW_DIGEST_USER_NAME:
			/* overlapping! */
			{
				DICT_ATTR const *da;
				uint8_t *p, *q;

				p = talloc_array(vp, uint8_t, vp->length + 2);

				memcpy(p + 2, vp->vp_octets, vp->length);
				p[0] = vp->da->attr - PW_DIGEST_REALM + 1;
				vp->length += 2;
				p[1] = vp->length;

				da = dict_attrbyvalue(PW_DIGEST_ATTRIBUTES, 0);
				vp->da = da;

				/*
				 *	Re-do pairmemsteal ourselves,
				 *	because we play games with
				 *	vp->da, and pairmemsteal goes
				 *	to GREAT lengths to sanitize
				 *	and fix and change and
				 *	double-check the various
				 *	fields.
				 */
				memcpy(&q, &vp->vp_octets, sizeof(q));
				talloc_free(q);

				vp->vp_octets = talloc_steal(vp, p);
				vp->type = VT_DATA;

				VERIFY_VP(vp);
			}
			break;
		}
	}

	/*
	 *	If we've already sent a packet, free up the old
	 *	one, and ensure that the next packet has a unique
	 *	ID and authentication vector.
	 */
	if (rep->data) {
		talloc_free(rep->data);
		rep->data = NULL;
	}

	fr_md5_calc(rep->vector, rep->vector,
			sizeof(rep->vector));

	if (*password != '\0') {
		if ((vp = pairfind(rep->vps, PW_CLEARTEXT_PASSWORD, 0, TAG_ANY)) != NULL) {
			pairstrcpy(vp, password);

		} else if ((vp = pairfind(rep->vps, PW_USER_PASSWORD, 0, TAG_ANY)) != NULL) {
			pairstrcpy(vp, password);

		} else if ((vp = pairfind(rep->vps, PW_CHAP_PASSWORD, 0, TAG_ANY)) != NULL) {
			pairstrcpy(vp, password);

			uint8_t *p;
			p = talloc_zero_array(vp, uint8_t, 17);
			rad_chap_encode(rep, p, rep->id, vp);
			pairmemsteal(vp, p);
		}
	} /* there WAS a password */

	/* send the response, wait for the next request */
	send_packet(rep, &req);

	if (!req) return -1;

	/* okay got back the packet, go and decode the EAP-Message. */
	unmap_eap_methods(req);

	debug_packet(req, R_RECV);

	/* now look for the code type. */
	for (vp = req->vps; vp != NULL; vp = vpnext) {
		vpnext = vp->next;

		switch (vp->da->attr) {
		default:
			break;

		case ATTRIBUTE_EAP_BASE+PW_EAP_MD5:
			if(respond_eap_md5(req, rep) && tried_eap_md5 < 3)
			{
				tried_eap_md5++;
				goto again;
			}
			break;

		case ATTRIBUTE_EAP_BASE+PW_EAP_SIM:
			if(respond_eap_sim(req, rep))
			{
				goto again;
			}
			break;
		}
	}

	return 1;
}
Esempio n. 3
0
static int sendrecv_eap(RADIUS_PACKET *rep)
{
	RADIUS_PACKET *req = NULL;
	VALUE_PAIR *vp, *vpnext;
	int tried_eap_md5 = 0;

	/*
	 *	Keep a copy of the the User-Password attribute.
	 */
	if ((vp = pairfind(rep->vps, PW_CLEARTEXT_PASSWORD, 0, TAG_ANY)) != NULL) {
		strlcpy(password, (char *)vp->vp_strvalue, sizeof(vp->vp_strvalue));

	} else 	if ((vp = pairfind(rep->vps, PW_USER_PASSWORD, 0, TAG_ANY)) != NULL) {
		strlcpy(password, (char *)vp->vp_strvalue, sizeof(vp->vp_strvalue));
		/*
		 *	Otherwise keep a copy of the CHAP-Password attribute.
		 */
	} else if ((vp = pairfind(rep->vps, PW_CHAP_PASSWORD, 0, TAG_ANY)) != NULL) {
		strlcpy(password, (char *)vp->vp_strvalue, sizeof(vp->vp_strvalue));
	} else {
		*password = '******';
	}

 again:
	rep->id++;

	/*
	 * if there are EAP types, encode them into an EAP-Message
	 *
	 */
	map_eap_methods(rep);

	/*
	 *  Fix up Digest-Attributes issues
	 */
	for (vp = rep->vps; vp != NULL; vp = vp->next) {
		switch (vp->da->attribute) {
		default:
			break;

		case PW_DIGEST_REALM:
		case PW_DIGEST_NONCE:
		case PW_DIGEST_METHOD:
		case PW_DIGEST_URI:
		case PW_DIGEST_QOP:
		case PW_DIGEST_ALGORITHM:
		case PW_DIGEST_BODY_DIGEST:
		case PW_DIGEST_CNONCE:
		case PW_DIGEST_NONCE_COUNT:
		case PW_DIGEST_USER_NAME:
			/* overlapping! */
			memmove(&vp->vp_strvalue[2], &vp->vp_octets[0], vp->length);
			vp->vp_octets[0] = vp->da->attribute - PW_DIGEST_REALM + 1;
			vp->length += 2;
			vp->vp_octets[1] = vp->length;
			vp->da->attribute = PW_DIGEST_ATTRIBUTES;
			break;
		}
	}

	/*
	 *	If we've already sent a packet, free up the old
	 *	one, and ensure that the next packet has a unique
	 *	ID and authentication vector.
	 */
	if (rep->data) {
		talloc_free(rep->data);
		rep->data = NULL;
	}

	fr_md5_calc(rep->vector, rep->vector,
			sizeof(rep->vector));

	if (*password != '\0') {
		if ((vp = pairfind(rep->vps, PW_CLEARTEXT_PASSWORD, 0, TAG_ANY)) != NULL) {
			pairstrcpy(vp, password);

		} else if ((vp = pairfind(rep->vps, PW_USER_PASSWORD, 0, TAG_ANY)) != NULL) {
			pairstrcpy(vp, password);

		} else if ((vp = pairfind(rep->vps, PW_CHAP_PASSWORD, 0, TAG_ANY)) != NULL) {
			pairstrcpy(vp, password);

			rad_chap_encode(rep, vp->vp_octets, rep->id, vp);
			vp->length = 17;
		}
	} /* there WAS a password */

	/* send the response, wait for the next request */
	send_packet(rep, &req);

	/* okay got back the packet, go and decode the EAP-Message. */
	unmap_eap_methods(req);

	debug_packet(req, R_RECV);

	/* now look for the code type. */
	for (vp = req->vps; vp != NULL; vp = vpnext) {
		vpnext = vp->next;

		switch (vp->da->attribute) {
		default:
			break;

		case ATTRIBUTE_EAP_BASE+PW_EAP_MD5:
			if(respond_eap_md5(req, rep) && tried_eap_md5 < 3)
			{
				tried_eap_md5++;
				goto again;
			}
			break;

		case ATTRIBUTE_EAP_BASE+PW_EAP_SIM:
			if(respond_eap_sim(req, rep))
			{
				goto again;
			}
			break;
		}
	}

	return 1;
}
Esempio n. 4
0
/*Note:
 * We just support EAP proxy.
 * rad_send_eap_response
 * send a EAP response to radius server
 */
int 
rad_send_eap_response(RADIUS_PACKET* rep,const char* secret,const char* pwd)
{
    VALUE_PAIR* vp;
	int rc;
	int old_debug_flag;

	vp = NULL;
	rc = 0;
	old_debug_flag = 0;

	/*
	 * if there are EAP types, encode them into an EAP-Message
	 *
	 */
	map_eap_types(rep);

	/*
	 *  Fix up Digest-Attributes issues
	 */
	for (vp = rep->vps; vp != NULL; vp = vp->next) {
		switch (vp->attribute) {
		default:
			break;

		case PW_DIGEST_REALM:
		case PW_DIGEST_NONCE:
		case PW_DIGEST_METHOD:
		case PW_DIGEST_URI:
		case PW_DIGEST_QOP:
		case PW_DIGEST_ALGORITHM:
		case PW_DIGEST_BODY_DIGEST:
		case PW_DIGEST_CNONCE:
		case PW_DIGEST_NONCE_COUNT:
		case PW_DIGEST_USER_NAME:
			/* overlapping! */
			memmove(&vp->vp_strvalue[2], &vp->vp_octets[0], vp->length);
			vp->vp_octets[0] = vp->attribute - PW_DIGEST_REALM + 1;
			vp->length += 2;
			vp->vp_octets[1] = vp->length;
			vp->attribute = PW_DIGEST_ATTRIBUTES;
			break;
		}
	}
	fr_md5_calc(rep->vector, rep->vector,
			sizeof(rep->vector));

	if ((pwd != NULL) && (*pwd != '\0')) {
		if ((vp = pairfind(rep->vps, PW_CLEARTEXT_PASSWORD)) != NULL) {
			strncpy((char *)vp->vp_strvalue, pwd, sizeof(vp->vp_strvalue) - 1);
			vp->length = strlen(pwd);

		} else if ((vp = pairfind(rep->vps, PW_USER_PASSWORD)) != NULL) {
			strncpy((char *)vp->vp_strvalue, pwd, sizeof(vp->vp_strvalue) - 1);
			vp->length = strlen(pwd);

		} else if ((vp = pairfind(rep->vps, PW_CHAP_PASSWORD)) != NULL) {
			strncpy((char *)vp->vp_strvalue, pwd, sizeof(vp->vp_strvalue) - 1);
			vp->length = strlen(pwd);

			rad_chap_encode(rep, vp->vp_octets, rep->id, vp);
			vp->length = 17;
		}
	} /* there WAS a password */

	/* send the response*/
    if(fr_debug_flag) {
        debug_packet(rep,R_SENT);
		old_debug_flag = fr_debug_flag;
		fr_debug_flag = 0; /*just turn off the debug-flag to avoid rad_send debug out agin*/
	}
	if(rad_send(rep,NULL,secret) < 0)
		rc = -1;
	else
		rc = 0;
	if(old_debug_flag)
		fr_debug_flag = old_debug_flag;

	return rc;
}