Пример #1
0
/**
 * @brief Calculate the MD5 hash of a string.
 *
 * Example: "%{md5:foo}" == "acbd18db4cc2f85cedef654fccc4a4d8"
 */
static size_t xlat_md5(UNUSED void *instance, REQUEST *request,
		       char *fmt, char *out, size_t outlen,
		       UNUSED RADIUS_ESCAPE_STRING func)
{
	int i;
	uint8_t digest[16];
	FR_MD5_CTX ctx;
	char buffer[1024];

	if (!radius_xlat(buffer, sizeof(buffer), fmt, request, func)) {
		*out = '\0';
		return 0;
	}

	fr_MD5Init(&ctx);
	fr_MD5Update(&ctx, (void *) buffer, strlen(buffer));
	fr_MD5Final(digest, &ctx);

	if (outlen < 33) {
		snprintf(out, outlen, "md5_overflow");
		return strlen(out);
	}

	for (i = 0; i < 16; i++) {
		snprintf(out + i * 2, 3, "%02x", digest[i]);
	}

	return strlen(out);
}
Пример #2
0
/**
 * @brief Calculate the MD5 hash of a string.
 *
 * Example: "%{md5:foo}" == "acbd18db4cc2f85cedef654fccc4a4d8"
 */
static size_t md5_xlat(UNUSED void *instance, UNUSED REQUEST *request,
		       char const *fmt, char *out, size_t outlen)
{
	uint8_t digest[16];
	int i, len;
	FR_MD5_CTX ctx;
	
	/*
	 *	We need room for at least one octet of output.
	 */
	if (outlen < 3) {
		*out = '\0';
		return 0;
	}

	fr_MD5Init(&ctx);
	fr_MD5Update(&ctx, (const void *) fmt, strlen(fmt));
	fr_MD5Final(digest, &ctx);

	/*
	 *	Each digest octet takes two hex digits, plus one for
	 *	the terminating NUL.
	 */
	len = (outlen / 2) - 1;
	if (len > 16) len = 16;

	for (i = 0; i < len; i++) {
		snprintf(out + i * 2, 3, "%02x", digest[i]);
	}

	return strlen(out);
}
Пример #3
0
static void calc_md5_digest(uint8_t *buffer, uint8_t const *challenge, size_t challen, char const *password)
{
	uint8_t buf[1024];
	int i;
	FR_MD5_CTX context;

	memset(buf, 0, 1024);
	memset(buf, 0x36, 64);
	for(i=0; i<64 && password[i]; i++) buf[i]^=password[i];
	memcpy(buf+64, challenge, challen);
	fr_MD5Init(&context);
	fr_MD5Update(&context, buf, 64+challen);
	memset(buf, 0x5c, 64);
	for(i=0; i<64 && password[i]; i++) buf[i]^=password[i];
	fr_MD5Final(buf+64,&context);
	fr_MD5Init(&context);
	fr_MD5Update(&context,buf,64+16);
	fr_MD5Final(buffer,&context);
}
Пример #4
0
static void calc_apop_digest(uint8_t *buffer, uint8_t const *challenge,
			     size_t challen, char const *password)
{
	FR_MD5_CTX context;

	fr_MD5Init(&context);
	fr_MD5Update(&context, challenge, challen);
	fr_MD5Update(&context, (uint8_t const *) password, strlen(password));
	fr_MD5Final(buffer, &context);
}
Пример #5
0
static int respond_eap_md5(RADIUS_PACKET *req,
			   RADIUS_PACKET *rep)
{
	VALUE_PAIR *vp, *id, *state;
	size_t valuesize;
	uint8_t identifier;
	uint8_t const *value;
	FR_MD5_CTX	context;
	uint8_t    response[16];

	cleanresp(rep);

	if ((state = paircopy2(NULL, req->vps, PW_STATE, 0, TAG_ANY)) == NULL)
	{
		fprintf(stderr, "radeapclient: no state attribute found\n");
		return 0;
	}

	if ((id = paircopy2(NULL, req->vps, ATTRIBUTE_EAP_ID, 0, TAG_ANY)) == NULL)
	{
		fprintf(stderr, "radeapclient: no EAP-ID attribute found\n");
		return 0;
	}
	identifier = id->vp_integer;

	if ((vp = pairfind(req->vps, ATTRIBUTE_EAP_BASE+PW_EAP_MD5, 0, TAG_ANY)) == NULL)
	{
		fprintf(stderr, "radeapclient: no EAP-MD5 attribute found\n");
		return 0;
	}

	/* got the details of the MD5 challenge */
	valuesize = vp->vp_octets[0];
	value = &vp->vp_octets[1];

	/* sanitize items */
	if(valuesize > vp->length)
	{
		fprintf(stderr, "radeapclient: md5 valuesize if too big (%u > %u)\n",
			(unsigned int) valuesize, (unsigned int) vp->length);
		return 0;
	}

	/* now do the CHAP operation ourself, rather than build the
	 * buffer. We could also call rad_chap_encode, but it wants
	 * a CHAP-Challenge, which we don't want to bother with.
	 */
	fr_MD5Init(&context);
	fr_MD5Update(&context, &identifier, 1);
	fr_MD5Update(&context, (uint8_t *) password, strlen(password));
	fr_MD5Update(&context, value, valuesize);
	fr_MD5Final(response, &context);

	{
		uint8_t *p;
		uint8_t lg_response;

		vp = paircreate(rep, ATTRIBUTE_EAP_BASE+PW_EAP_MD5, 0);
		vp->length = 17;

		p = talloc_zero_array(vp, uint8_t, 17);
		lg_response = 16;
		memcpy(p, &lg_response, 1);
		memcpy(p + 1, response, 16);
		pairmemsteal(vp, p);
	}
	pairreplace(&(rep->vps), vp);

	pairreplace(&(rep->vps), id);

	/* copy the state object in */
	pairreplace(&(rep->vps), state);

	return 1;
}
Пример #6
0
void
fr_hmac_md5(const uint8_t *text, int text_len,
	      const uint8_t *key, int key_len,
	      uint8_t *digest)
{
	FR_MD5_CTX context;
	uint8_t k_ipad[65];    /* inner padding -
				      * key XORd with ipad
				      */
	uint8_t k_opad[65];    /* outer padding -
				      * key XORd with opad
				      */
	uint8_t tk[16];
	int i;
	/* if key is longer than 64 bytes reset it to key=MD5(key) */
	if (key_len > 64) {

		FR_MD5_CTX      tctx;

		fr_MD5Init(&tctx);
		fr_MD5Update(&tctx, key, key_len);
		fr_MD5Final(tk, &tctx);

		key = tk;
		key_len = 16;
	}

	/*
	 * the HMAC_MD5 transform looks like:
	 *
	 * MD5(K XOR opad, MD5(K XOR ipad, text))
	 *
	 * where K is an n byte key
	 * ipad is the byte 0x36 repeated 64 times

	 * opad is the byte 0x5c repeated 64 times
	 * and text is the data being protected
	 */

	/* start out by storing key in pads */
	memset( k_ipad, 0, sizeof(k_ipad));
	memset( k_opad, 0, sizeof(k_opad));
	memcpy( k_ipad, key, key_len);
	memcpy( k_opad, key, key_len);

	/* XOR key with ipad and opad values */
	for (i = 0; i < 64; i++) {
		k_ipad[i] ^= 0x36;
		k_opad[i] ^= 0x5c;
	}
	/*
	 * perform inner MD5
	 */
	fr_MD5Init(&context);		   /* init context for 1st
					      * pass */
	fr_MD5Update(&context, k_ipad, 64);      /* start with inner pad */
	fr_MD5Update(&context, text, text_len); /* then text of datagram */
	fr_MD5Final(digest, &context);	  /* finish up 1st pass */
	/*
	 * perform outer MD5
	 */
	fr_MD5Init(&context);		   /* init context for 2nd
					      * pass */
	fr_MD5Update(&context, k_opad, 64);     /* start with outer pad */
	fr_MD5Update(&context, digest, 16);     /* then results of 1st
					      * hash */
	fr_MD5Final(digest, &context);	  /* finish up 2nd pass */
}
Пример #7
0
static int 
respond_eap_md5(RADIUS_PACKET *req,
			   RADIUS_PACKET *rep,const char* pwd)
{
	VALUE_PAIR *vp, *id, *state;
	size_t valuesize;
	uint8_t identifier;
	uint8_t *value;
	FR_MD5_CTX	context;
	uint8_t    response[16];

	cleanresp(rep);

	if ((state = paircopy2(req->vps, PW_STATE)) == NULL)
	{
		fr_strerror_printf("radeapclient: no state attribute found");
		return 0;
	}

	if ((id = paircopy2(req->vps, ATTRIBUTE_EAP_ID)) == NULL)
	{
		fr_strerror_printf("radeapclient: no EAP-ID attribute found");
		return 0;
	}
	identifier = id->vp_integer;

	if ((vp = pairfind(req->vps, ATTRIBUTE_EAP_BASE+PW_EAP_MD5)) == NULL)
	{
		fr_strerror_printf("radeapclient: no EAP-MD5 attribute found");
		return 0;
	}

	/* got the details of the MD5 challenge */
	valuesize = vp->vp_octets[0];
	value = &vp->vp_octets[1];

	/* sanitize items */
	if(valuesize > vp->length)
	{
		fr_strerror_printf("radeapclient: md5 valuesize if too big (%u > %u)\n",
			(unsigned int) valuesize, (unsigned int) vp->length);
		return 0;
	}

	/* now do the CHAP operation ourself, rather than build the
	 * buffer. We could also call rad_chap_encode, but it wants
	 * a CHAP-Challenge, which we don't want to bother with.
	 */
	fr_MD5Init(&context);
	fr_MD5Update(&context, &identifier, 1);
	fr_MD5Update(&context, (uint8_t *) pwd, strlen(pwd));
	fr_MD5Update(&context, value, valuesize);
	fr_MD5Final(response, &context);

	vp = paircreate(ATTRIBUTE_EAP_BASE+PW_EAP_MD5, PW_TYPE_OCTETS);
	vp->vp_octets[0]=16;
	memcpy(&vp->vp_strvalue[1], response, 16);
	vp->length = 17;

	pairreplace(&(rep->vps), vp);

	pairreplace(&(rep->vps), id);

	/* copy the state object in */
	pairreplace(&(rep->vps), state);

	return 1;
}