X-Git-Url: https://git.ozlabs.org/?a=blobdiff_plain;f=pppd%2Fchap_ms.c;h=e6b84f203fc3fc2f62ca2a471b17e11d8422e975;hb=14c1a77816e837852138e87a4adccfd66030b2c3;hp=05c6225a720612fe01afc43c917c59dd58a37ea3;hpb=6bd2208f408588cab66a4da26ebee1159840db81;p=ppp.git diff --git a/pppd/chap_ms.c b/pppd/chap_ms.c index 05c6225..e6b84f2 100644 --- a/pppd/chap_ms.c +++ b/pppd/chap_ms.c @@ -74,7 +74,7 @@ * */ -#define RCSID "$Id: chap_ms.c,v 1.34 2004/11/15 22:13:26 paulus Exp $" +#define RCSID "$Id: chap_ms.c,v 1.38 2007/12/01 20:10:51 carlsonj Exp $" #ifdef CHAPMS @@ -94,25 +94,24 @@ #include "pppcrypt.h" #include "magic.h" -static const char rcsid[] = RCSID; -static void ascii2unicode __P((char[], int, u_char[])); -static void NTPasswordHash __P((char *, int, u_char[MD4_SIGNATURE_SIZE])); -static void ChallengeResponse __P((u_char *, u_char *, u_char[24])); -static void ChapMS_NT __P((u_char *, char *, int, u_char[24])); -static void ChapMS2_NT __P((u_char *, u_char[16], char *, char *, int, - u_char[24])); +static void ascii2unicode (char[], int, u_char[]); +static void NTPasswordHash (u_char *, int, u_char[MD4_SIGNATURE_SIZE]); +static void ChallengeResponse (u_char *, u_char *, u_char[24]); +static void ChapMS_NT (u_char *, char *, int, u_char[24]); +static void ChapMS2_NT (u_char *, u_char[16], char *, char *, int, + u_char[24]); static void GenerateAuthenticatorResponsePlain - __P((char*, int, u_char[24], u_char[16], u_char *, - char *, u_char[41])); + (char*, int, u_char[24], u_char[16], u_char *, + char *, u_char[41]); #ifdef MSLANMAN -static void ChapMS_LANMan __P((u_char *, char *, int, u_char *)); +static void ChapMS_LANMan (u_char *, char *, int, u_char *); #endif #ifdef MPPE -static void Set_Start_Key __P((u_char *, char *, int)); -static void SetMasterKeys __P((char *, int, u_char[24], int)); +static void Set_Start_Key (u_char *, char *, int); +static void SetMasterKeys (char *, int, u_char[24], int); #endif #ifdef MSLANMAN @@ -320,25 +319,90 @@ chapms_make_response(unsigned char *response, int id, char *our_name, ChapMS(challenge, secret, secret_len, response); } +struct chapms2_response_cache_entry { + int id; + unsigned char challenge[16]; + unsigned char response[MS_CHAP2_RESPONSE_LEN]; + unsigned char auth_response[MS_AUTH_RESPONSE_LENGTH]; +}; + +#define CHAPMS2_MAX_RESPONSE_CACHE_SIZE 10 +static struct chapms2_response_cache_entry + chapms2_response_cache[CHAPMS2_MAX_RESPONSE_CACHE_SIZE]; +static int chapms2_response_cache_next_index = 0; +static int chapms2_response_cache_size = 0; + +static void +chapms2_add_to_response_cache(int id, unsigned char *challenge, + unsigned char *response, + unsigned char *auth_response) +{ + int i = chapms2_response_cache_next_index; + + chapms2_response_cache[i].id = id; + memcpy(chapms2_response_cache[i].challenge, challenge, 16); + memcpy(chapms2_response_cache[i].response, response, + MS_CHAP2_RESPONSE_LEN); + memcpy(chapms2_response_cache[i].auth_response, + auth_response, MS_AUTH_RESPONSE_LENGTH); + chapms2_response_cache_next_index = + (i + 1) % CHAPMS2_MAX_RESPONSE_CACHE_SIZE; + if (chapms2_response_cache_next_index > chapms2_response_cache_size) + chapms2_response_cache_size = chapms2_response_cache_next_index; + dbglog("added response cache entry %d", i); +} + +static struct chapms2_response_cache_entry* +chapms2_find_in_response_cache(int id, unsigned char *challenge, + unsigned char *auth_response) +{ + int i; + + for (i = 0; i < chapms2_response_cache_size; i++) { + if (id == chapms2_response_cache[i].id + && (!challenge + || memcmp(challenge, + chapms2_response_cache[i].challenge, + 16) == 0) + && (!auth_response + || memcmp(auth_response, + chapms2_response_cache[i].auth_response, + MS_AUTH_RESPONSE_LENGTH) == 0)) { + dbglog("response found in cache (entry %d)", i); + return &chapms2_response_cache[i]; + } + } + return NULL; /* not found */ +} + static void chapms2_make_response(unsigned char *response, int id, char *our_name, unsigned char *challenge, char *secret, int secret_len, unsigned char *private) { + const struct chapms2_response_cache_entry *cache_entry; + unsigned char auth_response[MS_AUTH_RESPONSE_LENGTH+1]; + challenge++; /* skip length, should be 16 */ *response++ = MS_CHAP2_RESPONSE_LEN; + cache_entry = chapms2_find_in_response_cache(id, challenge, NULL); + if (cache_entry) { + memcpy(response, cache_entry->response, MS_CHAP2_RESPONSE_LEN); + return; + } ChapMS2(challenge, #ifdef DEBUGMPPEKEY mschap2_peer_challenge, #else NULL, #endif - our_name, secret, secret_len, response, private, + our_name, secret, secret_len, response, auth_response, MS_CHAP2_AUTHENTICATEE); + chapms2_add_to_response_cache(id, challenge, response, auth_response); } static int -chapms2_check_success(unsigned char *msg, int len, unsigned char *private) +chapms2_check_success(int id, unsigned char *msg, int len) { if ((len < MS_AUTH_RESPONSE_LENGTH + 2) || strncmp((char *)msg, "S=", 2) != 0) { @@ -349,7 +413,7 @@ chapms2_check_success(unsigned char *msg, int len, unsigned char *private) msg += 2; len -= 2; if (len < MS_AUTH_RESPONSE_LENGTH - || memcmp(msg, private, MS_AUTH_RESPONSE_LENGTH)) { + || !chapms2_find_in_response_cache(id, NULL /* challenge */, msg)) { /* Authenticator Response did not match expected. */ error("MS-CHAPv2 mutual authentication failed."); return 0; @@ -359,6 +423,8 @@ chapms2_check_success(unsigned char *msg, int len, unsigned char *private) len -= MS_AUTH_RESPONSE_LENGTH; if ((len >= 3) && !strncmp((char *)msg, " M=", 3)) { msg += 3; /* Eat the delimiter */ + } else if ((len >= 2) && !strncmp((char *)msg, "M=", 2)) { + msg += 2; /* Eat the delimiter */ } else if (len) { /* Packet has extra text which does not begin " M=" */ error("MS-CHAPv2 Success packet is badly formed."); @@ -390,7 +456,7 @@ chapms_handle_failure(unsigned char *inp, int len) * chapms[2]_verify_response. */ if (!strncmp(p, "E=", 2)) - err = strtol(p, NULL, 10); /* Remember the error code. */ + err = strtol(p+2, NULL, 10); /* Remember the error code. */ else goto print_msg; /* Message is badly formatted. */ @@ -507,7 +573,7 @@ ascii2unicode(char ascii[], int ascii_len, u_char unicode[]) } static void -NTPasswordHash(char *secret, int secret_len, u_char hash[MD4_SIGNATURE_SIZE]) +NTPasswordHash(u_char *secret, int secret_len, u_char hash[MD4_SIGNATURE_SIZE]) { #ifdef __NetBSD__ /* NetBSD uses the libc md4 routines which take bytes instead of bits */ @@ -518,7 +584,13 @@ NTPasswordHash(char *secret, int secret_len, u_char hash[MD4_SIGNATURE_SIZE]) MD4_CTX md4Context; MD4Init(&md4Context); - MD4Update(&md4Context, (unsigned char *)secret, mdlen); + /* MD4Update can take at most 64 bytes at a time */ + while (mdlen > 512) { + MD4Update(&md4Context, secret, 512); + secret += 64; + mdlen -= 512; + } + MD4Update(&md4Context, secret, mdlen); MD4Final(hash, &md4Context); } @@ -532,7 +604,7 @@ ChapMS_NT(u_char *rchallenge, char *secret, int secret_len, /* Hash the Unicode version of the secret (== password). */ ascii2unicode(secret, secret_len, unicodePassword); - NTPasswordHash((char *)unicodePassword, secret_len * 2, PasswordHash); + NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash); ChallengeResponse(rchallenge, PasswordHash, NTResponse); } @@ -549,7 +621,7 @@ ChapMS2_NT(u_char *rchallenge, u_char PeerChallenge[16], char *username, /* Hash the Unicode version of the secret (== password). */ ascii2unicode(secret, secret_len, unicodePassword); - NTPasswordHash((char *)unicodePassword, secret_len * 2, PasswordHash); + NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash); ChallengeResponse(Challenge, PasswordHash, NTResponse); } @@ -637,8 +709,8 @@ GenerateAuthenticatorResponsePlain /* Hash (x2) the Unicode version of the secret (== password). */ ascii2unicode(secret, secret_len, unicodePassword); - NTPasswordHash((char *)unicodePassword, secret_len * 2, PasswordHash); - NTPasswordHash((char *)PasswordHash, sizeof(PasswordHash), + NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash); + NTPasswordHash(PasswordHash, sizeof(PasswordHash), PasswordHashHash); GenerateAuthenticatorResponse(PasswordHashHash, NTResponse, PeerChallenge, @@ -813,7 +885,8 @@ ChapMS(u_char *rchallenge, char *secret, int secret_len, ChapMS_NT(rchallenge, secret, secret_len, &response[MS_CHAP_NTRESP]); #ifdef MSLANMAN - ChapMS_LANMan(rchallenge, secret, secret_len, &response); + ChapMS_LANMan(rchallenge, secret, secret_len, + &response[MS_CHAP_LANMANRESP]); /* preferred method is set by option */ response[MS_CHAP_USENT] = !ms_lanman; @@ -846,7 +919,7 @@ ChapMS2(u_char *rchallenge, u_char *PeerChallenge, u_char *p = &response[MS_CHAP2_PEER_CHALLENGE]; int i; - BZERO(response, sizeof(*response)); + BZERO(response, MS_CHAP2_RESPONSE_LEN); /* Generate the Peer-Challenge if requested, or copy it if supplied. */ if (!PeerChallenge)