3 --- pppd/chap_ms.c.orig Fri Aug 13 08:46:12 1999
4 +++ pppd/chap_ms.c Wed Dec 8 14:52:48 1999
6 * You should also use DOMAIN\\USERNAME as described in README.MSCHAP80
10 + * Mods by Tim Hockin, Cobalt Networks Inc. <thockin@cobaltnet.com> June 1999
12 + * Cleanup, fixes and major reorganization.
13 + * Migrated all MPPE code to mppe.c, shared crypto code to extra_crypto.c
17 #define RCSID "$Id: chap_ms.c,v 1.15 1999/08/13 06:46:12 paulus Exp $"
34 +#include "extra_crypto.h"
36 static const char rcsid[] = RCSID;
39 /* We use MS_CHAP_RESPONSE_LEN, rather than sizeof(MS_ChapResponse),
40 in case this struct gets padded. */
43 + u_char PeerChallenge[16];
47 +} MS_ChapResponse_v2;
49 static void ChallengeResponse __P((u_char *, u_char *, u_char *));
50 -static void DesEncrypt __P((u_char *, u_char *, u_char *));
51 -static void MakeKey __P((u_char *, u_char *));
52 -static u_char Get7Bits __P((u_char *, int));
53 static void ChapMS_NT __P((char *, int, char *, int, MS_ChapResponse *));
55 static void ChapMS_LANMan __P((char *, int, char *, int, MS_ChapResponse *));
59 -static void Expand __P((u_char *, u_char *));
60 -static void Collapse __P((u_char *, u_char *));
64 bool ms_lanman = 0; /* Use LanMan password instead of NT */
65 /* Has meaning only with MS-CHAP challenges */
73 -DesEncrypt(clear, key, cipher)
74 - u_char *clear; /* IN 8 octets */
75 - u_char *key; /* IN 7 octets */
76 - u_char *cipher; /* OUT 8 octets */
79 - u_char crypt_key[66];
80 - u_char des_input[66];
82 - MakeKey(key, des_key);
84 - Expand(des_key, crypt_key);
88 - CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet input : %.8B", clear));
91 - Expand(clear, des_input);
92 - encrypt(des_input, 0);
93 - Collapse(des_input, cipher);
96 - CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet output: %.8B", cipher));
100 -#else /* USE_CRYPT */
103 -DesEncrypt(clear, key, cipher)
104 - u_char *clear; /* IN 8 octets */
105 - u_char *key; /* IN 7 octets */
106 - u_char *cipher; /* OUT 8 octets */
108 - des_cblock des_key;
109 - des_key_schedule key_schedule;
111 - MakeKey(key, des_key);
113 - des_set_key(&des_key, key_schedule);
116 - CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet input : %.8B", clear));
119 - des_ecb_encrypt((des_cblock *)clear, (des_cblock *)cipher, key_schedule, 1);
122 - CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet output: %.8B", cipher));
126 -#endif /* USE_CRYPT */
129 -static u_char Get7Bits(input, startBit)
133 - register unsigned int word;
135 - word = (unsigned)input[startBit / 8] << 8;
136 - word |= (unsigned)input[startBit / 8 + 1];
138 - word >>= 15 - (startBit % 8 + 7);
140 - return word & 0xFE;
145 -/* in == 8-byte string (expanded version of the 56-bit key)
146 - * out == 64-byte string where each byte is either 1 or 0
147 - * Note that the low-order "bit" is always ignored by by setkey()
149 -static void Expand(in, out)
156 - for(i = 0; i < 64; in++){
158 - for(j = 7; j >= 0; j--)
159 - *out++ = (c >> j) & 01;
164 -/* The inverse of Expand
166 -static void Collapse(in, out)
174 - for (i = 0; i < 64; i += 8, out++) {
176 - for (j = 7; j >= 0; j--, in++)
183 -static void MakeKey(key, des_key)
184 - u_char *key; /* IN 56 bit DES key missing parity bits */
185 - u_char *des_key; /* OUT 64 bit DES key with parity bits added */
187 - des_key[0] = Get7Bits(key, 0);
188 - des_key[1] = Get7Bits(key, 7);
189 - des_key[2] = Get7Bits(key, 14);
190 - des_key[3] = Get7Bits(key, 21);
191 - des_key[4] = Get7Bits(key, 28);
192 - des_key[5] = Get7Bits(key, 35);
193 - des_key[6] = Get7Bits(key, 42);
194 - des_key[7] = Get7Bits(key, 49);
197 - des_set_odd_parity((des_cblock *)des_key);
201 - CHAPDEBUG((LOG_INFO, "MakeKey: 56-bit input : %.7B", key));
202 - CHAPDEBUG((LOG_INFO, "MakeKey: 64-bit output: %.8B", des_key));
207 ChapMS_NT(rchallenge, rchallenge_len, secret, secret_len, response)
209 @@ -254,34 +126,13 @@
211 MS_ChapResponse *response;
215 - /* NetBSD uses the libc md4 routines which take bytes instead of bits */
216 - int mdlen = secret_len * 2;
218 - int mdlen = secret_len * 2 * 8;
220 - MD4_CTX md4Context;
221 u_char hash[MD4_SIGNATURE_SIZE];
222 - u_char unicodePassword[MAX_NT_PASSWORD * 2];
224 - /* Initialize the Unicode version of the secret (== password). */
225 - /* This implicitly supports 8-bit ISO8859/1 characters. */
226 - BZERO(unicodePassword, sizeof(unicodePassword));
227 - for (i = 0; i < secret_len; i++)
228 - unicodePassword[i * 2] = (u_char)secret[i];
230 - MD4Init(&md4Context);
231 - MD4Update(&md4Context, unicodePassword, mdlen);
233 - MD4Final(hash, &md4Context); /* Tell MD4 we're done */
235 + NtPasswordHash(secret, secret_len, hash);
236 ChallengeResponse(rchallenge, hash, response->NTResp);
240 -static u_char *StdText = (u_char *)"KGS!@#$%"; /* key from rasapi32.dll */
243 ChapMS_LANMan(rchallenge, rchallenge_len, secret, secret_len, response)
247 MS_ChapResponse *response;
250 - u_char UcasePassword[MAX_NT_PASSWORD]; /* max is actually 14 */
251 u_char PasswordHash[MD4_SIGNATURE_SIZE];
253 - /* LANMan password is case insensitive */
254 - BZERO(UcasePassword, sizeof(UcasePassword));
255 - for (i = 0; i < secret_len; i++)
256 - UcasePassword[i] = (u_char)toupper(secret[i]);
257 - DesEncrypt( StdText, UcasePassword + 0, PasswordHash + 0 );
258 - DesEncrypt( StdText, UcasePassword + 7, PasswordHash + 8 );
259 + LmPasswordHash(secret, secret_len, PasswordHash);
260 ChallengeResponse(rchallenge, PasswordHash, response->LANManResp);
263 @@ -331,8 +175,209 @@
268 + mppe_gen_master_key(secret, secret_len, rchallenge);
270 + BCOPY(&response, cstate->response, MS_CHAP_RESPONSE_LEN);
271 + cstate->resp_length = MS_CHAP_RESPONSE_LEN;
275 +ChapMS_Resp(cstate, secret, secret_len, remmd)
276 + chap_state *cstate;
281 + MS_ChapResponse local;
282 + MS_ChapResponse *response = (MS_ChapResponse *)remmd;
285 + BZERO(&local, sizeof(response));
287 + if(response->UseNT)
289 + ChapMS_NT(cstate->challenge,cstate->chal_len, secret, secret_len, &local);
290 + i = memcmp(local.NTResp, response->NTResp, sizeof(local.NTResp));
294 + mppe_gen_master_key(secret, secret_len, cstate->challenge);
300 + ChapMS_LANMan(cstate->challenge, cstate->chal_len, secret, secret_len,
302 + if(memcmp(local.LANManResp, response->LANManResp,
303 + sizeof(local.LANManResp)) == 0) {
305 + mppe_gen_master_key(secret, secret_len, cstate->challenge);
309 +#endif /* MSLANMAN */
314 +ChallengeHash(PeerChallenge, AuthenticatorChallenge, UserName, Challenge)
315 + char *PeerChallenge;
316 + char *AuthenticatorChallenge;
321 + u_char Digest[SHA_DIGEST_LENGTH];
324 + if((username = strrchr(UserName, '\\')) != (char *)NULL)
327 + username = UserName;
328 + SHA1_Init(&Context);
329 + SHA1_Update(&Context, PeerChallenge, 16);
330 + SHA1_Update(&Context, AuthenticatorChallenge, 16);
331 + SHA1_Update(&Context, username, strlen(username));
332 + SHA1_Final(Digest, &Context);
333 + BCOPY(Digest, Challenge, 8);
337 +ChapMS_v2(cstate, AuthenticatorChallenge, AuthenticatorChallengeLen, Password, PasswordLen)
338 + chap_state *cstate;
339 + char *AuthenticatorChallenge;
340 + int AuthenticatorChallengeLen;
344 + u_char Challenge[8];
345 + u_char PasswordHash[MD4_SIGNATURE_SIZE];
346 + MS_ChapResponse_v2 response;
348 + BZERO(&response, sizeof(response));
349 + ChapGenChallenge(cstate);
350 + BCOPY(cstate->challenge, response.PeerChallenge,
351 + sizeof(response.PeerChallenge));
352 + ChallengeHash(response.PeerChallenge, AuthenticatorChallenge,
353 + cstate->resp_name, Challenge);
354 + NtPasswordHash(Password, PasswordLen, PasswordHash);
355 + ChallengeResponse(Challenge, PasswordHash, response.NTResp);
356 BCOPY(&response, cstate->response, MS_CHAP_RESPONSE_LEN);
357 cstate->resp_length = MS_CHAP_RESPONSE_LEN;
359 + mppe_gen_master_key_v2(Password, PasswordLen, response.NTResp, 0);
364 +ChapMS_v2_Resp(cstate, Password, PasswordLen, remmd, UserName)
365 + chap_state *cstate;
371 + u_char Challenge[8];
372 + u_char PasswordHash[MD4_SIGNATURE_SIZE];
373 + MS_ChapResponse_v2 response, response1;
376 + BCOPY(remmd, &response, MS_CHAP_RESPONSE_LEN);
377 + ChallengeHash(response.PeerChallenge,cstate->challenge,UserName,Challenge);
378 + NtPasswordHash(Password, PasswordLen, PasswordHash);
379 + ChallengeResponse(Challenge, PasswordHash, response1.NTResp);
380 + i = memcmp(response.NTResp, response1.NTResp, sizeof(response.NTResp));
383 + mppe_gen_master_key_v2(Password, PasswordLen, response1.NTResp, 1);
389 +ChapMS_v2_Auth(cstate, Password, PasswordLen, remmd, UserName)
390 + chap_state *cstate;
396 + u_char PasswordHash[MD4_SIGNATURE_SIZE];
397 + u_char PasswordHashHash[MD4_SIGNATURE_SIZE];
398 + u_char Challenge[8];
399 + static char Magic1[] = "Magic server to client signing constant";
400 + static char Magic2[] = "Pad to make it do more than one iteration";
403 + u_char Digest[SHA_DIGEST_LENGTH];
404 + MS_ChapResponse_v2 *response = (MS_ChapResponse_v2 *)remmd;
405 + char StrResponse[SHA_DIGEST_LENGTH * 2 + 3], *s;
407 + static char HexDigs[] = "0123456789ABCDEF";
409 + NtPasswordHash(Password, PasswordLen, PasswordHash);
410 + md4(PasswordHash, sizeof(PasswordHash), PasswordHashHash);
412 + SHA1_Init(&Context);
413 + SHA1_Update(&Context, PasswordHashHash, 16);
414 + SHA1_Update(&Context, response->NTResp, 24);
415 + SHA1_Update(&Context, Magic1, sizeof(Magic1) - 1);
416 + SHA1_Final(Digest, &Context);
418 + ChallengeHash(response->PeerChallenge,cstate->challenge,UserName,Challenge);
420 + SHA1_Init(&Context);
421 + SHA1_Update(&Context, Digest, SHA_DIGEST_LENGTH);
422 + SHA1_Update(&Context, Challenge, 8);
423 + SHA1_Update(&Context, Magic2, sizeof(Magic2) - 1);
424 + SHA1_Final(Digest, &Context);
425 + s = strcpy(StrResponse, "S=")+2;
426 + for(i = 0; i < SHA_DIGEST_LENGTH; ++i) {
427 + *s++ = HexDigs[Digest[i] >> 4];
428 + *s++ = HexDigs[Digest[i] & 0x0F];
431 + BCOPY(StrResponse, cstate->response, sizeof(StrResponse));
432 + cstate->resp_length = sizeof(StrResponse) - 1;
436 + * functions called from config options
439 +reqchapms(char **argv)
441 + lcp_wantoptions[0].neg_chap = 1;
442 + lcp_wantoptions[0].use_chapms = 1;
449 +nochapms(char **argv)
451 + lcp_wantoptions[0].use_chapms = 0;
456 +reqchapms_v2(char **argv)
458 + lcp_wantoptions[0].neg_chap = 1;
459 + lcp_wantoptions[0].use_chapms_v2 = 1;
466 +nochapms_v2(char **argv)
468 + lcp_wantoptions[0].use_chapms_v2 = 0;