Merge from vendor branch TNF:
[pkgsrcv2.git] / net / ppp-mppe / patches / patch-bh
1 $NetBSD$
2
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
5 @@ -31,6 +31,14 @@
6   *   You should also use DOMAIN\\USERNAME as described in README.MSCHAP80
7   */
8  
9 +/*
10 + * Mods by Tim Hockin, Cobalt Networks Inc. <thockin@cobaltnet.com> June 1999
11 + *
12 + * Cleanup, fixes and major reorganization.
13 + * Migrated all MPPE code to mppe.c, shared crypto code to extra_crypto.c
14 + *
15 + */
16 +
17  #define RCSID  "$Id: chap_ms.c,v 1.15 1999/08/13 06:46:12 paulus Exp $"
18  
19  #ifdef CHAPMS
20 @@ -49,11 +57,13 @@
21  #include "pppd.h"
22  #include "chap.h"
23  #include "chap_ms.h"
24 -#include "md4.h"
25 -
26 -#ifndef USE_CRYPT
27 -#include <des.h>
28 +#include "sha.h"
29 +#include "fsm.h"
30 +#include "lcp.h"
31 +#ifdef MPPE
32 +#include "mppe.h"
33  #endif
34 +#include "extra_crypto.h"
35  
36  static const char rcsid[] = RCSID;
37  
38 @@ -65,21 +75,19 @@
39  /* We use MS_CHAP_RESPONSE_LEN, rather than sizeof(MS_ChapResponse),
40     in case this struct gets padded. */
41  
42 +typedef struct {
43 +    u_char PeerChallenge[16];
44 +    u_char Reserved[8];
45 +    u_char NTResp[24];
46 +    u_char Flags;
47 +} MS_ChapResponse_v2;
48  
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 *));
54  #ifdef MSLANMAN
55  static void    ChapMS_LANMan __P((char *, int, char *, int, MS_ChapResponse *));
56  #endif
57  
58 -#ifdef USE_CRYPT
59 -static void    Expand __P((u_char *, u_char *));
60 -static void    Collapse __P((u_char *, u_char *));
61 -#endif
62 -
63  #ifdef MSLANMAN
64  bool   ms_lanman = 0;          /* Use LanMan password instead of NT */
65                                 /* Has meaning only with MS-CHAP challenges */
66 @@ -110,142 +118,6 @@
67  #endif
68  }
69  
70 -
71 -#ifdef USE_CRYPT
72 -static void
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 */
77 -{
78 -    u_char des_key[8];
79 -    u_char crypt_key[66];
80 -    u_char des_input[66];
81 -
82 -    MakeKey(key, des_key);
83 -
84 -    Expand(des_key, crypt_key);
85 -    setkey(crypt_key);
86 -
87 -#if 0
88 -    CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet input : %.8B", clear));
89 -#endif
90 -
91 -    Expand(clear, des_input);
92 -    encrypt(des_input, 0);
93 -    Collapse(des_input, cipher);
94 -
95 -#if 0
96 -    CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet output: %.8B", cipher));
97 -#endif
98 -}
99 -
100 -#else /* USE_CRYPT */
101 -
102 -static void
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 */
107 -{
108 -    des_cblock         des_key;
109 -    des_key_schedule   key_schedule;
110 -
111 -    MakeKey(key, des_key);
112 -
113 -    des_set_key(&des_key, key_schedule);
114 -
115 -#if 0
116 -    CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet input : %.8B", clear));
117 -#endif
118 -
119 -    des_ecb_encrypt((des_cblock *)clear, (des_cblock *)cipher, key_schedule, 1);
120 -
121 -#if 0
122 -    CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet output: %.8B", cipher));
123 -#endif
124 -}
125 -
126 -#endif /* USE_CRYPT */
127 -
128 -
129 -static u_char Get7Bits(input, startBit)
130 -    u_char *input;
131 -    int startBit;
132 -{
133 -    register unsigned int      word;
134 -
135 -    word  = (unsigned)input[startBit / 8] << 8;
136 -    word |= (unsigned)input[startBit / 8 + 1];
137 -
138 -    word >>= 15 - (startBit % 8 + 7);
139 -
140 -    return word & 0xFE;
141 -}
142 -
143 -#ifdef USE_CRYPT
144 -
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()
148 - */
149 -static void Expand(in, out)
150 -    u_char *in;
151 -    u_char *out;
152 -{
153 -        int j, c;
154 -        int i;
155 -
156 -        for(i = 0; i < 64; in++){
157 -               c = *in;
158 -                for(j = 7; j >= 0; j--)
159 -                        *out++ = (c >> j) & 01;
160 -                i += 8;
161 -        }
162 -}
163 -
164 -/* The inverse of Expand
165 - */
166 -static void Collapse(in, out)
167 -    u_char *in;
168 -    u_char *out;
169 -{
170 -        int j;
171 -        int i;
172 -       unsigned int c;
173 -
174 -       for (i = 0; i < 64; i += 8, out++) {
175 -           c = 0;
176 -           for (j = 7; j >= 0; j--, in++)
177 -               c |= *in << j;
178 -           *out = c & 0xff;
179 -       }
180 -}
181 -#endif
182 -
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 */
186 -{
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);
195 -
196 -#ifndef USE_CRYPT
197 -    des_set_odd_parity((des_cblock *)des_key);
198 -#endif
199 -
200 -#if 0
201 -    CHAPDEBUG((LOG_INFO, "MakeKey: 56-bit input : %.7B", key));
202 -    CHAPDEBUG((LOG_INFO, "MakeKey: 64-bit output: %.8B", des_key));
203 -#endif
204 -}
205 -
206  static void
207  ChapMS_NT(rchallenge, rchallenge_len, secret, secret_len, response)
208      char *rchallenge;
209 @@ -254,34 +126,13 @@
210      int secret_len;
211      MS_ChapResponse    *response;
212  {
213 -    int                        i;
214 -#ifdef __NetBSD__
215 -    /* NetBSD uses the libc md4 routines which take bytes instead of bits */
216 -    int                        mdlen = secret_len * 2;
217 -#else
218 -    int                        mdlen = secret_len * 2 * 8;
219 -#endif
220 -    MD4_CTX            md4Context;
221      u_char             hash[MD4_SIGNATURE_SIZE];
222 -    u_char             unicodePassword[MAX_NT_PASSWORD * 2];
223 -
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];
229 -
230 -    MD4Init(&md4Context);
231 -    MD4Update(&md4Context, unicodePassword, mdlen);
232 -
233 -    MD4Final(hash, &md4Context);       /* Tell MD4 we're done */
234  
235 +    NtPasswordHash(secret, secret_len, hash);
236      ChallengeResponse(rchallenge, hash, response->NTResp);
237  }
238  
239  #ifdef MSLANMAN
240 -static u_char *StdText = (u_char *)"KGS!@#$%"; /* key from rasapi32.dll */
241 -
242  static void
243  ChapMS_LANMan(rchallenge, rchallenge_len, secret, secret_len, response)
244      char *rchallenge;
245 @@ -290,16 +141,9 @@
246      int secret_len;
247      MS_ChapResponse    *response;
248  {
249 -    int                        i;
250 -    u_char             UcasePassword[MAX_NT_PASSWORD]; /* max is actually 14 */
251      u_char             PasswordHash[MD4_SIGNATURE_SIZE];
252  
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);
261  }
262  #endif
263 @@ -331,8 +175,209 @@
264      response.UseNT = 1;
265  #endif
266  
267 +#ifdef MPPE
268 +    mppe_gen_master_key(secret, secret_len, rchallenge);
269 +#endif
270 +    BCOPY(&response, cstate->response, MS_CHAP_RESPONSE_LEN);
271 +    cstate->resp_length = MS_CHAP_RESPONSE_LEN;
272 +}
273 +
274 +int
275 +ChapMS_Resp(cstate, secret, secret_len, remmd)
276 +    chap_state *cstate;
277 +    char *secret;
278 +    int secret_len;
279 +    u_char *remmd;
280 +{
281 +    MS_ChapResponse local;
282 +    MS_ChapResponse *response = (MS_ChapResponse *)remmd;
283 +    int i;
284 +
285 +    BZERO(&local, sizeof(response));
286 +
287 +    if(response->UseNT)
288 +    {
289 +      ChapMS_NT(cstate->challenge,cstate->chal_len, secret, secret_len, &local);
290 +      i = memcmp(local.NTResp, response->NTResp, sizeof(local.NTResp));
291 +
292 +#ifdef MPPE
293 +      if(i == 0)
294 +        mppe_gen_master_key(secret, secret_len, cstate->challenge);
295 +#endif
296 +      return(i);
297 +    }
298 +
299 +#ifdef MSLANMAN
300 +    ChapMS_LANMan(cstate->challenge, cstate->chal_len, secret, secret_len, 
301 +               &local);
302 +    if(memcmp(local.LANManResp, response->LANManResp, 
303 +       sizeof(local.LANManResp)) == 0) {
304 +#ifdef MPPE
305 +      mppe_gen_master_key(secret, secret_len, cstate->challenge);
306 +#endif
307 +      return(0);
308 +    }
309 +#endif /* MSLANMAN */
310 +    return(1);
311 +}
312 +
313 +void
314 +ChallengeHash(PeerChallenge, AuthenticatorChallenge, UserName, Challenge)
315 +    char *PeerChallenge;
316 +    char *AuthenticatorChallenge;
317 +    char *UserName;
318 +    char *Challenge;
319 +{
320 +    SHA_CTX Context;
321 +    u_char Digest[SHA_DIGEST_LENGTH];
322 +    char *username;
323 +    
324 +    if((username = strrchr(UserName, '\\')) != (char *)NULL)
325 +      ++username;
326 +    else
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);
334 +}
335 +
336 +void
337 +ChapMS_v2(cstate, AuthenticatorChallenge, AuthenticatorChallengeLen, Password, PasswordLen)
338 +    chap_state *cstate;
339 +    char *AuthenticatorChallenge;
340 +    int AuthenticatorChallengeLen;
341 +    char *Password;
342 +    int PasswordLen;
343 +{
344 +    u_char Challenge[8];
345 +    u_char PasswordHash[MD4_SIGNATURE_SIZE];
346 +    MS_ChapResponse_v2 response;
347 +  
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;
358 +#ifdef MPPE
359 +    mppe_gen_master_key_v2(Password, PasswordLen, response.NTResp, 0);
360 +#endif
361 +}
362 +
363 +int
364 +ChapMS_v2_Resp(cstate, Password, PasswordLen, remmd, UserName)
365 +    chap_state *cstate;
366 +    char *Password;
367 +    int PasswordLen;
368 +    u_char *remmd;
369 +    char *UserName;
370 +{
371 +    u_char Challenge[8];
372 +    u_char PasswordHash[MD4_SIGNATURE_SIZE];
373 +    MS_ChapResponse_v2 response, response1;
374 +    int i;
375 +  
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));
381 +#ifdef MPPE
382 +    if(i == 0)
383 +      mppe_gen_master_key_v2(Password, PasswordLen, response1.NTResp, 1);
384 +#endif
385 +    return(i);
386 +}
387 +
388 +void
389 +ChapMS_v2_Auth(cstate, Password, PasswordLen, remmd, UserName)
390 +    chap_state *cstate;
391 +    char *Password;
392 +    int  PasswordLen;
393 +    u_char *remmd;
394 +    char *UserName;
395 +{
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";
401 +
402 +    SHA_CTX Context;
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;
406 +    int i;
407 +    static char HexDigs[] = "0123456789ABCDEF";
408 +    
409 +    NtPasswordHash(Password, PasswordLen, PasswordHash);
410 +    md4(PasswordHash, sizeof(PasswordHash), PasswordHashHash);
411 +
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);
417 +
418 +    ChallengeHash(response->PeerChallenge,cstate->challenge,UserName,Challenge);
419 +    
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];
429 +    }
430 +    *s = '\0';
431 +    BCOPY(StrResponse, cstate->response, sizeof(StrResponse));
432 +    cstate->resp_length = sizeof(StrResponse) - 1;
433 +}
434 +
435 +/*
436 + * functions called from config options
437 + */
438 +int 
439 +reqchapms(char **argv)
440 +{
441 +    lcp_wantoptions[0].neg_chap = 1;
442 +    lcp_wantoptions[0].use_chapms = 1;
443 +    auth_required = 1;
444 +
445 +    return 1;
446 +}
447 +
448 +int 
449 +nochapms(char **argv)
450 +{
451 +    lcp_wantoptions[0].use_chapms = 0;
452 +    return 1;
453 +}
454 +
455 +int 
456 +reqchapms_v2(char **argv)
457 +{
458 +    lcp_wantoptions[0].neg_chap = 1;
459 +    lcp_wantoptions[0].use_chapms_v2 = 1;
460 +    auth_required = 1;
461 +
462 +    return 1;
463 +}
464 +
465 +int 
466 +nochapms_v2(char **argv)
467 +{
468 +    lcp_wantoptions[0].use_chapms_v2 = 0;
469 +    return 1;
470  }
471  
472  #endif /* CHAPMS */