#include <freeradius-devel/ident.h>
RCSID("$Id$")
#define _FR_MD4_H
#define _FR_SHA1_H
#include <freeradius-devel/rad_assert.h>
#include "extern.h"
#include "otp.h"
#include "otp_mppe.h"
#include <openssl/des.h>
#include <openssl/md4.h>
#include <openssl/md5.h>
#include <openssl/sha.h>
#include <string.h>
void
otp_mppe(REQUEST *request, otp_pwe_t pwe, const otp_option_t *opt,
const char *passcode)
{
VALUE_PAIR **avp = &request->reply->vps;
VALUE_PAIR *cvp, *rvp, *vp;
cvp = pairfind(request->packet->vps, pwattr[pwe - 1]);
rvp = pairfind(request->packet->vps, pwattr[pwe]);
switch (pwe) {
case PWE_PAP:
case PWE_CHAP:
return;
case PWE_MSCHAP:
vp = pairmake("MS-MPPE-Encryption-Policy",
otp_mppe_policy[opt->mschap_mppe_policy], T_OP_EQ);
rad_assert(vp != NULL);
pairadd(avp, vp);
vp = pairmake("MS-MPPE-Encryption-Types",
otp_mppe_types[opt->mschap_mppe_types], T_OP_EQ);
rad_assert(vp != NULL);
pairadd(avp, vp);
if (!opt->mschap_mppe_policy)
return;
{
size_t i, passcode_len;
unsigned char password_unicode[2 * OTP_MAX_PASSCODE_LEN];
unsigned char password_md[MD4_DIGEST_LENGTH];
unsigned char mppe_keys[32];
char mppe_keys_string[2 + (2 * sizeof(mppe_keys)) + 1];
(void) memset(mppe_keys, 0, sizeof(mppe_keys));
passcode_len = strlen(passcode);
for (i = 0; i < passcode_len; ++i) {
password_unicode[i * 2] = *passcode++;
password_unicode[i * 2 + 1] = 0;
}
(void) MD4(password_unicode, 2 * passcode_len, password_md);
(void) MD4(password_md, MD4_DIGEST_LENGTH, &mppe_keys[8]);
#if 0
{
unsigned char md5_md[MD5_DIGEST_LENGTH];
unsigned char encode_buf[AUTH_VECTOR_LEN + MAX_STRING_LEN];
int secretlen;
secretlen = strlen(request->secret);
(void) memcpy(encode_buf, request->secret, secretlen);
(void) memcpy(encode_buf + secretlen, request->packet->vector,
AUTH_VECTOR_LEN);
(void) MD5(encode_buf, secretlen + AUTH_VECTOR_LEN, md5_md);
for (i = 0; i < 16; ++i)
mppe_keys[i] ^= md5_md[i];
(void) memcpy(encode_buf + secretlen, mppe_keys, MD5_DIGEST_LENGTH);
(void) MD5(encode_buf, secretlen + MD5_DIGEST_LENGTH, md5_md);
for (i = 0; i < 16; ++i)
mppe_keys[i + 16] ^= md5_md[i];
}
#endif
mppe_keys_string[0] = '0';
mppe_keys_string[1] = 'x';
for (i = 0; i < 32; ++i)
(void) sprintf(&mppe_keys_string[i*2+2], "%02X", mppe_keys[i]);
vp = pairmake("MS-CHAP-MPPE-Keys", mppe_keys_string, T_OP_EQ);
rad_assert(vp != NULL);
pairadd(avp, vp);
}
break;
case PWE_MSCHAP2:
{
size_t i;
unsigned char password_md_md[MD4_DIGEST_LENGTH];
{
size_t passcode_len;
unsigned char password_unicode[2 * OTP_MAX_PASSCODE_LEN];
unsigned char password_md[MD4_DIGEST_LENGTH];
SHA_CTX ctx;
unsigned char md1[SHA_DIGEST_LENGTH];
unsigned char md2[SHA_DIGEST_LENGTH];
unsigned char auth_md[SHA_DIGEST_LENGTH];
char auth_md_string[2 + (2 * sizeof(auth_md)) + 1];
char auth_octet_string[2 + 2 + (2 * sizeof(auth_md_string))];
char *username = request->username->vp_strvalue;
int username_len = request->username->length;
unsigned char magic1[39] =
{ 0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,
0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,
0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,
0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74 };
unsigned char magic2[41] =
{ 0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,
0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,
0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,
0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,
0x6E };
passcode_len = strlen(passcode);
for (i = 0; i < passcode_len; ++i) {
password_unicode[i * 2] = *passcode++;
password_unicode[i * 2 + 1] = 0;
}
(void) MD4(password_unicode, 2 * passcode_len, password_md);
(void) MD4(password_md, MD4_DIGEST_LENGTH, password_md_md);
SHA1_Init(&ctx);
SHA1_Update(&ctx, password_md_md, MD4_DIGEST_LENGTH);
SHA1_Update(&ctx, rvp->vp_strvalue + 26, 24);
SHA1_Update(&ctx, magic1, sizeof(magic1));
SHA1_Final(md1, &ctx);
SHA1_Init(&ctx);
SHA1_Update(&ctx, rvp->vp_strvalue + 2, 16);
SHA1_Update(&ctx, cvp->vp_strvalue, 16);
SHA1_Update(&ctx, username, username_len);
SHA1_Final(md2, &ctx);
SHA1_Init(&ctx);
SHA1_Update(&ctx, md1, SHA_DIGEST_LENGTH);
SHA1_Update(&ctx, md2, 8);
SHA1_Update(&ctx, magic2, sizeof(magic2));
SHA1_Final(auth_md, &ctx);
auth_md_string[0] = 'S';
auth_md_string[1] = '=';
for (i = 0; i < sizeof(auth_md); ++i)
(void) sprintf(&auth_md_string[i * 2 + 2], "%02X", auth_md[i]);
auth_octet_string[0] = '0';
auth_octet_string[1] = 'x';
(void) sprintf(&auth_octet_string[2], "%02X", rvp->vp_strvalue[0]);
for (i = 0; i < sizeof(auth_md_string) - 1; ++i)
(void) sprintf(&auth_octet_string[i * 2 +4], "%02X", auth_md_string[i]);
vp = pairmake("MS-CHAP2-Success", auth_octet_string, T_OP_EQ);
rad_assert(vp != NULL);
pairadd(avp, vp);
}
vp = pairmake("MS-MPPE-Encryption-Policy",
otp_mppe_policy[opt->mschapv2_mppe_policy], T_OP_EQ);
rad_assert(vp != NULL);
pairadd(avp, vp);
vp = pairmake("MS-MPPE-Encryption-Types",
otp_mppe_types[opt->mschapv2_mppe_types], T_OP_EQ);
rad_assert(vp != NULL);
pairadd(avp, vp);
if (!opt->mschapv2_mppe_policy)
return;
{
unsigned char Magic1[27] =
{ 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d,
0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79 };
unsigned char Magic2[84] =
{ 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65,
0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
0x6b, 0x65, 0x79, 0x2e };
unsigned char Magic3[84] =
{ 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73,
0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73,
0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20,
0x6b, 0x65, 0x79, 0x2e };
unsigned char SHSpad1[40] =
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
unsigned char SHSpad2[40] =
{ 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2 };
unsigned char MasterKey[16];
unsigned char MasterSendKey[16];
unsigned char MasterReceiveKey[16];
SHA_CTX ctx;
unsigned char sha_md[SHA_DIGEST_LENGTH];
#if 0
unsigned char md5_md[MD5_DIGEST_LENGTH];
unsigned char encode_buf[MAX_STRING_LEN + AUTH_VECTOR_LEN + 2];
int secretlen;
unsigned char salt[2];
unsigned char mppe_key[32];
unsigned char mppe_key_string[2 + (2 * sizeof(salt)) +
(2 * sizeof(mppe_key)) + 1];
#else
unsigned char mppe_key_string[2 + (2 * sizeof(MasterKey)) + 1];
#endif
SHA1_Init(&ctx);
SHA1_Update(&ctx, password_md_md, MD4_DIGEST_LENGTH);
SHA1_Update(&ctx, rvp->vp_strvalue + 26, 24);
SHA1_Update(&ctx, Magic1, sizeof(Magic1));
SHA1_Final(sha_md, &ctx);
(void) memcpy(MasterKey, sha_md, 16);
SHA1_Init(&ctx);
SHA1_Update(&ctx, MasterKey, 16);
SHA1_Update(&ctx, SHSpad1, 40);
SHA1_Update(&ctx, Magic3, sizeof(Magic3));
SHA1_Update(&ctx, SHSpad2, 40);
SHA1_Final(sha_md, &ctx);
(void) memcpy(MasterSendKey, sha_md, 16);
SHA1_Init(&ctx);
SHA1_Update(&ctx, MasterKey, 16);
SHA1_Update(&ctx, SHSpad1, 40);
SHA1_Update(&ctx, Magic2, sizeof(Magic3));
SHA1_Update(&ctx, SHSpad2, 40);
SHA1_Final(sha_md, &ctx);
(void) memcpy(MasterReceiveKey, sha_md, 16);
#if 0
salt[0] = 0x80;
salt[1] = 0x01;
(void) memset(mppe_key, 0, sizeof(mppe_key));
mppe_key[0] = 16;
(void) memcpy(&mppe_key[1], MasterSendKey, 16);
secretlen = strlen(request->secret);
(void) memcpy(encode_buf, request->secret, secretlen);
(void) memcpy(encode_buf + secretlen, request->packet->vector,
AUTH_VECTOR_LEN);
(void) memcpy(encode_buf + secretlen + 16, salt, 2);
(void) MD5(encode_buf, secretlen + AUTH_VECTOR_LEN + 2, md5_md);
for (i = 0; i < 16; ++i)
mppe_key[i] ^= md5_md[i];
(void) memcpy(encode_buf + secretlen, mppe_key, 16);
(void) MD5(encode_buf, secretlen + 16, md5_md);
for (i = 0; i < 16; ++i)
mppe_key[i + 16] ^= md5_md[i];
mppe_key_string[0] = '0';
mppe_key_string[1] = 'x';
(void) sprintf(&mppe_key_string[2], "%02X", salt[0]);
(void) sprintf(&mppe_key_string[4], "%02X", salt[1]);
for (i = 0; i < sizeof(mppe_key); ++i)
(void) sprintf(&mppe_key_string[i*2+6], "%02X", mppe_key[i]);
#else
mppe_key_string[0] = '0';
mppe_key_string[1] = 'x';
for (i = 0; i < sizeof(MasterSendKey); ++i)
(void) sprintf(&mppe_key_string[i*2+2], "%02X", MasterSendKey[i]);
#endif
vp = pairmake("MS-MPPE-Send-Key", mppe_key_string, T_OP_EQ);
rad_assert(vp != NULL);
pairadd(avp, vp);
#if 0
salt[0] = 0x80;
salt[1] = 0x02;
(void) memset(mppe_key, 0, sizeof(mppe_key));
mppe_key[0] = 16;
(void) memcpy(&mppe_key[1], MasterReceiveKey, 16);
secretlen = strlen(request->secret);
(void) memcpy(encode_buf, request->secret, secretlen);
(void) memcpy(encode_buf + secretlen, request->packet->vector,
AUTH_VECTOR_LEN);
(void) memcpy(encode_buf + secretlen + 16, salt, 2);
(void) MD5(encode_buf, secretlen + AUTH_VECTOR_LEN + 2, md5_md);
for (i = 0; i < 16; ++i)
mppe_key[i] ^= md5_md[i];
(void) memcpy(encode_buf + secretlen, mppe_key, 16);
(void) MD5(encode_buf, secretlen + 16, md5_md);
for (i = 0; i < 16; ++i)
mppe_key[i + 16] ^= md5_md[i];
mppe_key_string[0] = '0';
mppe_key_string[1] = 'x';
(void) sprintf(&mppe_key_string[2], "%02X", salt[0]);
(void) sprintf(&mppe_key_string[4], "%02X", salt[1]);
for (i = 0; i < sizeof(mppe_key); ++i)
(void) sprintf(&mppe_key_string[i*2+6], "%02X", mppe_key[i]);
#else
mppe_key_string[0] = '0';
mppe_key_string[1] = 'x';
for (i = 0; i < sizeof(MasterReceiveKey); ++i)
(void) sprintf(&mppe_key_string[i*2+2], "%02X", MasterReceiveKey[i]);
#endif
vp = pairmake("MS-MPPE-Recv-Key", mppe_key_string, T_OP_EQ);
rad_assert(vp != NULL);
pairadd(avp, vp);
}
}
break;
}
return;
}