X-Git-Url: http://git.ozlabs.org/?p=ppp.git;a=blobdiff_plain;f=pppd%2Fchap_ms.c;h=ae8ab1d461660fdaca14281d9b4a27d43ba924f6;hp=c69f4b6a4b38a42ab590983d3a1b029e38dfc225;hb=2dc6b270ecf72688083f03d80df67d0682e1e02c;hpb=e79f90482eb6f90c3f1fe7732258756d2ea0277f diff --git a/pppd/chap_ms.c b/pppd/chap_ms.c index c69f4b6..ae8ab1d 100644 --- a/pppd/chap_ms.c +++ b/pppd/chap_ms.c @@ -20,23 +20,42 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ +/* + * Modifications by Lauri Pesonen / lpesonen@clinet.fi, april 1997 + * + * Implemented LANManager type password response to MS-CHAP challenges. + * Now pppd provides both NT style and LANMan style blocks, and the + * prefered is set by option "ms-lanman". Default is to use NT. + * The hash text (StdText) was taken from Win95 RASAPI32.DLL. + * + * You should also use DOMAIN\\USERNAME as described in README.MSCHAP80 + */ + #ifndef lint -static char rcsid[] = "$Id: chap_ms.c,v 1.1 1996/05/28 00:42:30 paulus Exp $"; +static char rcsid[] = "$Id: chap_ms.c,v 1.7 1998/03/25 03:08:14 paulus Exp $"; #endif +#ifdef CHAPMS + #include +#include +#include #include #include #include +#include +#ifdef USE_CRYPT +#include +#endif #include "pppd.h" #include "chap.h" #include "chap_ms.h" #include "md4.h" - -#ifdef CHAPMS +#ifndef USE_CRYPT #include +#endif typedef struct { u_char LANManResp[24]; @@ -47,9 +66,19 @@ typedef struct { in case this struct gets padded. */ +static void ChallengeResponse __P((u_char *, u_char *, u_char *)); static void DesEncrypt __P((u_char *, u_char *, u_char *)); static void MakeKey __P((u_char *, u_char *)); +static u_char Get7Bits __P((u_char *, int)); +static void ChapMS_NT __P((char *, int, char *, int, MS_ChapResponse *)); +#ifdef MSLANMAN +static void ChapMS_LANMan __P((char *, int, char *, int, MS_ChapResponse *)); +#endif +#ifdef USE_CRYPT +static void Expand __P((u_char *, u_char *)); +static void Collapse __P((u_char *, u_char *)); +#endif static void ChallengeResponse(challenge, pwHash, response) @@ -60,10 +89,10 @@ ChallengeResponse(challenge, pwHash, response) char ZPasswordHash[21]; BZERO(ZPasswordHash, sizeof(ZPasswordHash)); - BCOPY(pwHash, ZPasswordHash, 16); + BCOPY(pwHash, ZPasswordHash, MD4_SIGNATURE_SIZE); #if 0 - log_packet(ZPasswordHash, sizeof(ZPasswordHash), "ChallengeResponse - ZPasswordHash"); + log_packet(ZPasswordHash, sizeof(ZPasswordHash), "ChallengeResponse - ZPasswordHash", LOG_DEBUG); #endif DesEncrypt(challenge, ZPasswordHash + 0, response + 0); @@ -71,11 +100,44 @@ ChallengeResponse(challenge, pwHash, response) DesEncrypt(challenge, ZPasswordHash + 14, response + 16); #if 0 - log_packet(response, 24, "ChallengeResponse - response"); + log_packet(response, 24, "ChallengeResponse - response", LOG_DEBUG); #endif } +#ifdef USE_CRYPT +static void +DesEncrypt(clear, key, cipher) + u_char *clear; /* IN 8 octets */ + u_char *key; /* IN 7 octets */ + u_char *cipher; /* OUT 8 octets */ +{ + u_char des_key[8]; + u_char crypt_key[66]; + u_char des_input[66]; + + MakeKey(key, des_key); + + Expand(des_key, crypt_key); + setkey(crypt_key); + +#if 0 + CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet input : %02X%02X%02X%02X%02X%02X%02X%02X", + clear[0], clear[1], clear[2], clear[3], clear[4], clear[5], clear[6], clear[7])); +#endif + + Expand(clear, des_input); + encrypt(des_input, 0); + Collapse(des_input, cipher); + +#if 0 + CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet output: %02X%02X%02X%02X%02X%02X%02X%02X", + cipher[0], cipher[1], cipher[2], cipher[3], cipher[4], cipher[5], cipher[6], cipher[7])); +#endif +} + +#else /* USE_CRYPT */ + static void DesEncrypt(clear, key, cipher) u_char *clear; /* IN 8 octets */ @@ -102,6 +164,8 @@ DesEncrypt(clear, key, cipher) #endif } +#endif /* USE_CRYPT */ + static u_char Get7Bits(input, startBit) u_char *input; @@ -117,6 +181,45 @@ static u_char Get7Bits(input, startBit) return word & 0xFE; } +#ifdef USE_CRYPT + +/* in == 8-byte string (expanded version of the 56-bit key) + * out == 64-byte string where each byte is either 1 or 0 + * Note that the low-order "bit" is always ignored by by setkey() + */ +static void Expand(in, out) + u_char *in; + u_char *out; +{ + int j, c; + int i; + + for(i = 0; i < 64; in++){ + c = *in; + for(j = 7; j >= 0; j--) + *out++ = (c >> j) & 01; + i += 8; + } +} + +/* The inverse of Expand + */ +static void Collapse(in, out) + u_char *in; + u_char *out; +{ + int j; + int i; + unsigned int c; + + for (i = 0; i < 64; i += 8, out++) { + c = 0; + for (j = 7; j >= 0; j--, in++) + c |= *in << j; + *out = c & 0xff; + } +} +#endif static void MakeKey(key, des_key) u_char *key; /* IN 56 bit DES key missing parity bits */ @@ -131,7 +234,9 @@ static void MakeKey(key, des_key) des_key[6] = Get7Bits(key, 42); des_key[7] = Get7Bits(key, 49); +#ifndef USE_CRYPT des_set_odd_parity((des_cblock *)des_key); +#endif #if 0 CHAPDEBUG((LOG_INFO, "MakeKey: 56-bit input : %02X%02X%02X%02X%02X%02X%02X", @@ -141,8 +246,57 @@ static void MakeKey(key, des_key) #endif } -#endif /* CHAPMS */ +static void +ChapMS_NT(rchallenge, rchallenge_len, secret, secret_len, response) + char *rchallenge; + int rchallenge_len; + char *secret; + int secret_len; + MS_ChapResponse *response; +{ + int i; + MD4_CTX md4Context; + u_char hash[MD4_SIGNATURE_SIZE]; + u_char unicodePassword[MAX_NT_PASSWORD * 2]; + + /* Initialize the Unicode version of the secret (== password). */ + /* This implicitly supports 8-bit ISO8859/1 characters. */ + BZERO(unicodePassword, sizeof(unicodePassword)); + for (i = 0; i < secret_len; i++) + unicodePassword[i * 2] = (u_char)secret[i]; + + MD4Init(&md4Context); + MD4Update(&md4Context, unicodePassword, secret_len * 2 * 8); /* Unicode is 2 bytes/char, *8 for bit count */ + + MD4Final(hash, &md4Context); /* Tell MD4 we're done */ + + ChallengeResponse(rchallenge, hash, response->NTResp); +} + +#ifdef MSLANMAN +static u_char *StdText = (u_char *)"KGS!@#$%"; /* key from rasapi32.dll */ + +static void +ChapMS_LANMan(rchallenge, rchallenge_len, secret, secret_len, response) + char *rchallenge; + int rchallenge_len; + char *secret; + int secret_len; + MS_ChapResponse *response; +{ + int i; + u_char UcasePassword[MAX_NT_PASSWORD]; /* max is actually 14 */ + u_char PasswordHash[MD4_SIGNATURE_SIZE]; + /* LANMan password is case insensitive */ + BZERO(UcasePassword, sizeof(UcasePassword)); + for (i = 0; i < secret_len; i++) + UcasePassword[i] = (u_char)toupper(secret[i]); + DesEncrypt( StdText, UcasePassword + 0, PasswordHash + 0 ); + DesEncrypt( StdText, UcasePassword + 7, PasswordHash + 8 ); + ChallengeResponse(rchallenge, PasswordHash, response->LANManResp); +} +#endif void ChapMS(cstate, rchallenge, rchallenge_len, secret, secret_len) @@ -152,33 +306,30 @@ ChapMS(cstate, rchallenge, rchallenge_len, secret, secret_len) char *secret; int secret_len; { -#ifdef CHAPMS - int i; - MDstruct md4Context; MS_ChapResponse response; - u_char unicodePassword[MAX_NT_PASSWORD * 2]; +#ifdef MSLANMAN + extern int ms_lanman; +#endif #if 0 CHAPDEBUG((LOG_INFO, "ChapMS: secret is '%.*s'", secret_len, secret)); #endif - BZERO(&response, sizeof(response)); - /* Initialize the Unicode version of the secret (== password). */ - /* This implicitly supports 8-bit ISO8859/1 characters. */ - BZERO(unicodePassword, sizeof(unicodePassword)); - for (i = 0; i < secret_len; i++) - unicodePassword[i * 2] = (u_char)secret[i]; + /* Calculate both always */ + ChapMS_NT(rchallenge, rchallenge_len, secret, secret_len, &response); - MDbegin(&md4Context); - MDupdate(&md4Context, unicodePassword, secret_len * 2 * 8); /* Unicode is 2 bytes/char, *8 for bit count */ - MDupdate(&md4Context, NULL, 0); /* Tell MD4 we're done */ - - ChallengeResponse(rchallenge, (char *)md4Context.buffer, response.NTResp); +#ifdef MSLANMAN + ChapMS_LANMan(rchallenge, rchallenge_len, secret, secret_len, &response); + /* prefered method is set by option */ + response.UseNT = !ms_lanman; +#else response.UseNT = 1; +#endif BCOPY(&response, cstate->response, MS_CHAP_RESPONSE_LEN); cstate->resp_length = MS_CHAP_RESPONSE_LEN; -#endif /* CHAPMS */ } + +#endif /* CHAPMS */