]> git.ozlabs.org Git - ppp.git/blob - pppd/chap_ms.c
Makefile.am: Add explicit openssl directory to pppd include path
[ppp.git] / pppd / chap_ms.c
1 /*
2  * chap_ms.c - Microsoft MS-CHAP compatible implementation.
3  *
4  * Copyright (c) 1995 Eric Rosenquist.  All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  *
18  * 3. The name(s) of the authors of this software must not be used to
19  *    endorse or promote products derived from this software without
20  *    prior written permission.
21  *
22  * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
23  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
24  * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
25  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
26  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
27  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
28  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
29  */
30
31 /*
32  * Modifications by Lauri Pesonen / lpesonen@clinet.fi, april 1997
33  *
34  *   Implemented LANManager type password response to MS-CHAP challenges.
35  *   Now pppd provides both NT style and LANMan style blocks, and the
36  *   prefered is set by option "ms-lanman". Default is to use NT.
37  *   The hash text (StdText) was taken from Win95 RASAPI32.DLL.
38  *
39  *   You should also use DOMAIN\\USERNAME as described in README.MSCHAP80
40  */
41
42 /*
43  * Modifications by Frank Cusack, frank@google.com, March 2002.
44  *
45  *   Implemented MS-CHAPv2 functionality, heavily based on sample
46  *   implementation in RFC 2759.  Implemented MPPE functionality,
47  *   heavily based on sample implementation in RFC 3079.
48  *
49  * Copyright (c) 2002 Google, Inc.  All rights reserved.
50  *
51  * Redistribution and use in source and binary forms, with or without
52  * modification, are permitted provided that the following conditions
53  * are met:
54  *
55  * 1. Redistributions of source code must retain the above copyright
56  *    notice, this list of conditions and the following disclaimer.
57  *
58  * 2. Redistributions in binary form must reproduce the above copyright
59  *    notice, this list of conditions and the following disclaimer in
60  *    the documentation and/or other materials provided with the
61  *    distribution.
62  *
63  * 3. The name(s) of the authors of this software must not be used to
64  *    endorse or promote products derived from this software without
65  *    prior written permission.
66  *
67  * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
68  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
69  * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
70  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
71  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
72  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
73  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
74  *
75  */
76
77 #define RCSID   "$Id: chap_ms.c,v 1.38 2007/12/01 20:10:51 carlsonj Exp $"
78
79 #ifdef CHAPMS
80
81 #include <stdio.h>
82 #include <stdlib.h>
83 #include <string.h>
84 #include <ctype.h>
85 #include <sys/types.h>
86 #include <sys/time.h>
87 #include <unistd.h>
88
89 #include "pppd.h"
90 #include "chap-new.h"
91 #include "chap_ms.h"
92 #include "md4.h"
93 #include "sha1.h"
94 #include "pppcrypt.h"
95 #include "magic.h"
96
97
98
99 static void     ascii2unicode __P((char[], int, u_char[]));
100 static void     NTPasswordHash __P((u_char *, int, u_char[MD4_SIGNATURE_SIZE]));
101 static void     ChallengeResponse __P((u_char *, u_char *, u_char[24]));
102 static void     ChapMS_NT __P((u_char *, char *, int, u_char[24]));
103 static void     ChapMS2_NT __P((u_char *, u_char[16], char *, char *, int,
104                                 u_char[24]));
105 static void     GenerateAuthenticatorResponsePlain
106                         __P((char*, int, u_char[24], u_char[16], u_char *,
107                              char *, u_char[41]));
108 #ifdef MSLANMAN
109 static void     ChapMS_LANMan __P((u_char *, char *, int, u_char *));
110 #endif
111
112 #ifdef MPPE
113 static void     Set_Start_Key __P((u_char *, char *, int));
114 static void     SetMasterKeys __P((char *, int, u_char[24], int));
115 #endif
116
117 #ifdef MSLANMAN
118 bool    ms_lanman = 0;          /* Use LanMan password instead of NT */
119                                 /* Has meaning only with MS-CHAP challenges */
120 #endif
121
122 #ifdef MPPE
123 u_char mppe_send_key[MPPE_MAX_KEY_LEN];
124 u_char mppe_recv_key[MPPE_MAX_KEY_LEN];
125 int mppe_keys_set = 0;          /* Have the MPPE keys been set? */
126
127 #ifdef DEBUGMPPEKEY
128 /* For MPPE debug */
129 /* Use "[]|}{?/><,`!2&&(" (sans quotes) for RFC 3079 MS-CHAPv2 test value */
130 static char *mschap_challenge = NULL;
131 /* Use "!@\#$%^&*()_+:3|~" (sans quotes, backslash is to escape #) for ... */
132 static char *mschap2_peer_challenge = NULL;
133 #endif
134
135 #include "fsm.h"                /* Need to poke MPPE options */
136 #include "ccp.h"
137 #include <net/ppp-comp.h>
138 #endif
139
140 /*
141  * Command-line options.
142  */
143 static option_t chapms_option_list[] = {
144 #ifdef MSLANMAN
145         { "ms-lanman", o_bool, &ms_lanman,
146           "Use LanMan passwd when using MS-CHAP", 1 },
147 #endif
148 #ifdef DEBUGMPPEKEY
149         { "mschap-challenge", o_string, &mschap_challenge,
150           "specify CHAP challenge" },
151         { "mschap2-peer-challenge", o_string, &mschap2_peer_challenge,
152           "specify CHAP peer challenge" },
153 #endif
154         { NULL }
155 };
156
157 /*
158  * chapms_generate_challenge - generate a challenge for MS-CHAP.
159  * For MS-CHAP the challenge length is fixed at 8 bytes.
160  * The length goes in challenge[0] and the actual challenge starts
161  * at challenge[1].
162  */
163 static void
164 chapms_generate_challenge(unsigned char *challenge)
165 {
166         *challenge++ = 8;
167 #ifdef DEBUGMPPEKEY
168         if (mschap_challenge && strlen(mschap_challenge) == 8)
169                 memcpy(challenge, mschap_challenge, 8);
170         else
171 #endif
172                 random_bytes(challenge, 8);
173 }
174
175 static void
176 chapms2_generate_challenge(unsigned char *challenge)
177 {
178         *challenge++ = 16;
179 #ifdef DEBUGMPPEKEY
180         if (mschap_challenge && strlen(mschap_challenge) == 16)
181                 memcpy(challenge, mschap_challenge, 16);
182         else
183 #endif
184                 random_bytes(challenge, 16);
185 }
186
187 static int
188 chapms_verify_response(int id, char *name,
189                        unsigned char *secret, int secret_len,
190                        unsigned char *challenge, unsigned char *response,
191                        char *message, int message_space)
192 {
193         unsigned char md[MS_CHAP_RESPONSE_LEN];
194         int diff;
195         int challenge_len, response_len;
196
197         challenge_len = *challenge++;   /* skip length, is 8 */
198         response_len = *response++;
199         if (response_len != MS_CHAP_RESPONSE_LEN)
200                 goto bad;
201
202 #ifndef MSLANMAN
203         if (!response[MS_CHAP_USENT]) {
204                 /* Should really propagate this into the error packet. */
205                 notice("Peer request for LANMAN auth not supported");
206                 goto bad;
207         }
208 #endif
209
210         /* Generate the expected response. */
211         ChapMS(challenge, (char *)secret, secret_len, md);
212
213 #ifdef MSLANMAN
214         /* Determine which part of response to verify against */
215         if (!response[MS_CHAP_USENT])
216                 diff = memcmp(&response[MS_CHAP_LANMANRESP],
217                               &md[MS_CHAP_LANMANRESP], MS_CHAP_LANMANRESP_LEN);
218         else
219 #endif
220                 diff = memcmp(&response[MS_CHAP_NTRESP], &md[MS_CHAP_NTRESP],
221                               MS_CHAP_NTRESP_LEN);
222
223         if (diff == 0) {
224                 slprintf(message, message_space, "Access granted");
225                 return 1;
226         }
227
228  bad:
229         /* See comments below for MS-CHAP V2 */
230         slprintf(message, message_space, "E=691 R=1 C=%0.*B V=0",
231                  challenge_len, challenge);
232         return 0;
233 }
234
235 static int
236 chapms2_verify_response(int id, char *name,
237                         unsigned char *secret, int secret_len,
238                         unsigned char *challenge, unsigned char *response,
239                         char *message, int message_space)
240 {
241         unsigned char md[MS_CHAP2_RESPONSE_LEN];
242         char saresponse[MS_AUTH_RESPONSE_LENGTH+1];
243         int challenge_len, response_len;
244
245         challenge_len = *challenge++;   /* skip length, is 16 */
246         response_len = *response++;
247         if (response_len != MS_CHAP2_RESPONSE_LEN)
248                 goto bad;       /* not even the right length */
249
250         /* Generate the expected response and our mutual auth. */
251         ChapMS2(challenge, &response[MS_CHAP2_PEER_CHALLENGE], name,
252                 (char *)secret, secret_len, md,
253                 (unsigned char *)saresponse, MS_CHAP2_AUTHENTICATOR);
254
255         /* compare MDs and send the appropriate status */
256         /*
257          * Per RFC 2759, success message must be formatted as
258          *     "S=<auth_string> M=<message>"
259          * where
260          *     <auth_string> is the Authenticator Response (mutual auth)
261          *     <message> is a text message
262          *
263          * However, some versions of Windows (win98 tested) do not know
264          * about the M=<message> part (required per RFC 2759) and flag
265          * it as an error (reported incorrectly as an encryption error
266          * to the user).  Since the RFC requires it, and it can be
267          * useful information, we supply it if the peer is a conforming
268          * system.  Luckily (?), win98 sets the Flags field to 0x04
269          * (contrary to RFC requirements) so we can use that to
270          * distinguish between conforming and non-conforming systems.
271          *
272          * Special thanks to Alex Swiridov <say@real.kharkov.ua> for
273          * help debugging this.
274          */
275         if (memcmp(&md[MS_CHAP2_NTRESP], &response[MS_CHAP2_NTRESP],
276                    MS_CHAP2_NTRESP_LEN) == 0) {
277                 if (response[MS_CHAP2_FLAGS])
278                         slprintf(message, message_space, "S=%s", saresponse);
279                 else
280                         slprintf(message, message_space, "S=%s M=%s",
281                                  saresponse, "Access granted");
282                 return 1;
283         }
284
285  bad:
286         /*
287          * Failure message must be formatted as
288          *     "E=e R=r C=c V=v M=m"
289          * where
290          *     e = error code (we use 691, ERROR_AUTHENTICATION_FAILURE)
291          *     r = retry (we use 1, ok to retry)
292          *     c = challenge to use for next response, we reuse previous
293          *     v = Change Password version supported, we use 0
294          *     m = text message
295          *
296          * The M=m part is only for MS-CHAPv2.  Neither win2k nor
297          * win98 (others untested) display the message to the user anyway.
298          * They also both ignore the E=e code.
299          *
300          * Note that it's safe to reuse the same challenge as we don't
301          * actually accept another response based on the error message
302          * (and no clients try to resend a response anyway).
303          *
304          * Basically, this whole bit is useless code, even the small
305          * implementation here is only because of overspecification.
306          */
307         slprintf(message, message_space, "E=691 R=1 C=%0.*B V=0 M=%s",
308                  challenge_len, challenge, "Access denied");
309         return 0;
310 }
311
312 static void
313 chapms_make_response(unsigned char *response, int id, char *our_name,
314                      unsigned char *challenge, char *secret, int secret_len,
315                      unsigned char *private)
316 {
317         challenge++;    /* skip length, should be 8 */
318         *response++ = MS_CHAP_RESPONSE_LEN;
319         ChapMS(challenge, secret, secret_len, response);
320 }
321
322 struct chapms2_response_cache_entry {
323         int id;
324         unsigned char challenge[16];
325         unsigned char response[MS_CHAP2_RESPONSE_LEN];
326         unsigned char auth_response[MS_AUTH_RESPONSE_LENGTH];
327 };
328
329 #define CHAPMS2_MAX_RESPONSE_CACHE_SIZE 10
330 static struct chapms2_response_cache_entry
331     chapms2_response_cache[CHAPMS2_MAX_RESPONSE_CACHE_SIZE];
332 static int chapms2_response_cache_next_index = 0;
333 static int chapms2_response_cache_size = 0;
334
335 static void
336 chapms2_add_to_response_cache(int id, unsigned char *challenge,
337                               unsigned char *response,
338                               unsigned char *auth_response)
339 {
340         int i = chapms2_response_cache_next_index;
341
342         chapms2_response_cache[i].id = id;
343         memcpy(chapms2_response_cache[i].challenge, challenge, 16);
344         memcpy(chapms2_response_cache[i].response, response,
345                MS_CHAP2_RESPONSE_LEN);
346         memcpy(chapms2_response_cache[i].auth_response,
347                auth_response, MS_AUTH_RESPONSE_LENGTH);
348         chapms2_response_cache_next_index =
349                 (i + 1) % CHAPMS2_MAX_RESPONSE_CACHE_SIZE;
350         if (chapms2_response_cache_next_index > chapms2_response_cache_size)
351                 chapms2_response_cache_size = chapms2_response_cache_next_index;
352         dbglog("added response cache entry %d", i);
353 }
354
355 static struct chapms2_response_cache_entry*
356 chapms2_find_in_response_cache(int id, unsigned char *challenge,
357                       unsigned char *auth_response)
358 {
359         int i;
360
361         for (i = 0; i < chapms2_response_cache_size; i++) {
362                 if (id == chapms2_response_cache[i].id
363                     && (!challenge
364                         || memcmp(challenge,
365                                   chapms2_response_cache[i].challenge,
366                                   16) == 0)
367                     && (!auth_response
368                         || memcmp(auth_response,
369                                   chapms2_response_cache[i].auth_response,
370                                   MS_AUTH_RESPONSE_LENGTH) == 0)) {
371                         dbglog("response found in cache (entry %d)", i);
372                         return &chapms2_response_cache[i];
373                 }
374         }
375         return NULL;  /* not found */
376 }
377
378 static void
379 chapms2_make_response(unsigned char *response, int id, char *our_name,
380                       unsigned char *challenge, char *secret, int secret_len,
381                       unsigned char *private)
382 {
383         const struct chapms2_response_cache_entry *cache_entry;
384         unsigned char auth_response[MS_AUTH_RESPONSE_LENGTH+1];
385
386         challenge++;    /* skip length, should be 16 */
387         *response++ = MS_CHAP2_RESPONSE_LEN;
388         cache_entry = chapms2_find_in_response_cache(id, challenge, NULL);
389         if (cache_entry) {
390                 memcpy(response, cache_entry->response, MS_CHAP2_RESPONSE_LEN);
391                 return;
392         }
393         ChapMS2(challenge,
394 #ifdef DEBUGMPPEKEY
395                 mschap2_peer_challenge,
396 #else
397                 NULL,
398 #endif
399                 our_name, secret, secret_len, response, auth_response,
400                 MS_CHAP2_AUTHENTICATEE);
401         chapms2_add_to_response_cache(id, challenge, response, auth_response);
402 }
403
404 static int
405 chapms2_check_success(int id, unsigned char *msg, int len)
406 {
407         if ((len < MS_AUTH_RESPONSE_LENGTH + 2) ||
408             strncmp((char *)msg, "S=", 2) != 0) {
409                 /* Packet does not start with "S=" */
410                 error("MS-CHAPv2 Success packet is badly formed.");
411                 return 0;
412         }
413         msg += 2;
414         len -= 2;
415         if (len < MS_AUTH_RESPONSE_LENGTH
416             || !chapms2_find_in_response_cache(id, NULL /* challenge */, msg)) {
417                 /* Authenticator Response did not match expected. */
418                 error("MS-CHAPv2 mutual authentication failed.");
419                 return 0;
420         }
421         /* Authenticator Response matches. */
422         msg += MS_AUTH_RESPONSE_LENGTH; /* Eat it */
423         len -= MS_AUTH_RESPONSE_LENGTH;
424         if ((len >= 3) && !strncmp((char *)msg, " M=", 3)) {
425                 msg += 3; /* Eat the delimiter */
426         } else if (len) {
427                 /* Packet has extra text which does not begin " M=" */
428                 error("MS-CHAPv2 Success packet is badly formed.");
429                 return 0;
430         }
431         return 1;
432 }
433
434 static void
435 chapms_handle_failure(unsigned char *inp, int len)
436 {
437         int err;
438         char *p, *msg;
439
440         /* We want a null-terminated string for strxxx(). */
441         msg = malloc(len + 1);
442         if (!msg) {
443                 notice("Out of memory in chapms_handle_failure");
444                 return;
445         }
446         BCOPY(inp, msg, len);
447         msg[len] = 0;
448         p = msg;
449
450         /*
451          * Deal with MS-CHAP formatted failure messages; just print the
452          * M=<message> part (if any).  For MS-CHAP we're not really supposed
453          * to use M=<message>, but it shouldn't hurt.  See
454          * chapms[2]_verify_response.
455          */
456         if (!strncmp(p, "E=", 2))
457                 err = strtol(p+2, NULL, 10); /* Remember the error code. */
458         else
459                 goto print_msg; /* Message is badly formatted. */
460
461         if (len && ((p = strstr(p, " M=")) != NULL)) {
462                 /* M=<message> field found. */
463                 p += 3;
464         } else {
465                 /* No M=<message>; use the error code. */
466                 switch (err) {
467                 case MS_CHAP_ERROR_RESTRICTED_LOGON_HOURS:
468                         p = "E=646 Restricted logon hours";
469                         break;
470
471                 case MS_CHAP_ERROR_ACCT_DISABLED:
472                         p = "E=647 Account disabled";
473                         break;
474
475                 case MS_CHAP_ERROR_PASSWD_EXPIRED:
476                         p = "E=648 Password expired";
477                         break;
478
479                 case MS_CHAP_ERROR_NO_DIALIN_PERMISSION:
480                         p = "E=649 No dialin permission";
481                         break;
482
483                 case MS_CHAP_ERROR_AUTHENTICATION_FAILURE:
484                         p = "E=691 Authentication failure";
485                         break;
486
487                 case MS_CHAP_ERROR_CHANGING_PASSWORD:
488                         /* Should never see this, we don't support Change Password. */
489                         p = "E=709 Error changing password";
490                         break;
491
492                 default:
493                         free(msg);
494                         error("Unknown MS-CHAP authentication failure: %.*v",
495                               len, inp);
496                         return;
497                 }
498         }
499 print_msg:
500         if (p != NULL)
501                 error("MS-CHAP authentication failed: %v", p);
502         free(msg);
503 }
504
505 static void
506 ChallengeResponse(u_char *challenge,
507                   u_char PasswordHash[MD4_SIGNATURE_SIZE],
508                   u_char response[24])
509 {
510     u_char    ZPasswordHash[21];
511
512     BZERO(ZPasswordHash, sizeof(ZPasswordHash));
513     BCOPY(PasswordHash, ZPasswordHash, MD4_SIGNATURE_SIZE);
514
515 #if 0
516     dbglog("ChallengeResponse - ZPasswordHash %.*B",
517            sizeof(ZPasswordHash), ZPasswordHash);
518 #endif
519
520     (void) DesSetkey(ZPasswordHash + 0);
521     DesEncrypt(challenge, response + 0);
522     (void) DesSetkey(ZPasswordHash + 7);
523     DesEncrypt(challenge, response + 8);
524     (void) DesSetkey(ZPasswordHash + 14);
525     DesEncrypt(challenge, response + 16);
526
527 #if 0
528     dbglog("ChallengeResponse - response %.24B", response);
529 #endif
530 }
531
532 void
533 ChallengeHash(u_char PeerChallenge[16], u_char *rchallenge,
534               char *username, u_char Challenge[8])
535     
536 {
537     SHA1_CTX    sha1Context;
538     u_char      sha1Hash[SHA1_SIGNATURE_SIZE];
539     char        *user;
540
541     /* remove domain from "domain\username" */
542     if ((user = strrchr(username, '\\')) != NULL)
543         ++user;
544     else
545         user = username;
546
547     SHA1_Init(&sha1Context);
548     SHA1_Update(&sha1Context, PeerChallenge, 16);
549     SHA1_Update(&sha1Context, rchallenge, 16);
550     SHA1_Update(&sha1Context, (unsigned char *)user, strlen(user));
551     SHA1_Final(sha1Hash, &sha1Context);
552
553     BCOPY(sha1Hash, Challenge, 8);
554 }
555
556 /*
557  * Convert the ASCII version of the password to Unicode.
558  * This implicitly supports 8-bit ISO8859/1 characters.
559  * This gives us the little-endian representation, which
560  * is assumed by all M$ CHAP RFCs.  (Unicode byte ordering
561  * is machine-dependent.)
562  */
563 static void
564 ascii2unicode(char ascii[], int ascii_len, u_char unicode[])
565 {
566     int i;
567
568     BZERO(unicode, ascii_len * 2);
569     for (i = 0; i < ascii_len; i++)
570         unicode[i * 2] = (u_char) ascii[i];
571 }
572
573 static void
574 NTPasswordHash(u_char *secret, int secret_len, u_char hash[MD4_SIGNATURE_SIZE])
575 {
576 #ifdef __NetBSD__
577     /* NetBSD uses the libc md4 routines which take bytes instead of bits */
578     int                 mdlen = secret_len;
579 #else
580     int                 mdlen = secret_len * 8;
581 #endif
582     MD4_CTX             md4Context;
583
584     MD4Init(&md4Context);
585     /* MD4Update can take at most 64 bytes at a time */
586     while (mdlen > 512) {
587         MD4Update(&md4Context, secret, 512);
588         secret += 64;
589         mdlen -= 512;
590     }
591     MD4Update(&md4Context, secret, mdlen);
592     MD4Final(hash, &md4Context);
593
594 }
595
596 static void
597 ChapMS_NT(u_char *rchallenge, char *secret, int secret_len,
598           u_char NTResponse[24])
599 {
600     u_char      unicodePassword[MAX_NT_PASSWORD * 2];
601     u_char      PasswordHash[MD4_SIGNATURE_SIZE];
602
603     /* Hash the Unicode version of the secret (== password). */
604     ascii2unicode(secret, secret_len, unicodePassword);
605     NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash);
606
607     ChallengeResponse(rchallenge, PasswordHash, NTResponse);
608 }
609
610 static void
611 ChapMS2_NT(u_char *rchallenge, u_char PeerChallenge[16], char *username,
612            char *secret, int secret_len, u_char NTResponse[24])
613 {
614     u_char      unicodePassword[MAX_NT_PASSWORD * 2];
615     u_char      PasswordHash[MD4_SIGNATURE_SIZE];
616     u_char      Challenge[8];
617
618     ChallengeHash(PeerChallenge, rchallenge, username, Challenge);
619
620     /* Hash the Unicode version of the secret (== password). */
621     ascii2unicode(secret, secret_len, unicodePassword);
622     NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash);
623
624     ChallengeResponse(Challenge, PasswordHash, NTResponse);
625 }
626
627 #ifdef MSLANMAN
628 static u_char *StdText = (u_char *)"KGS!@#$%"; /* key from rasapi32.dll */
629
630 static void
631 ChapMS_LANMan(u_char *rchallenge, char *secret, int secret_len,
632               unsigned char *response)
633 {
634     int                 i;
635     u_char              UcasePassword[MAX_NT_PASSWORD]; /* max is actually 14 */
636     u_char              PasswordHash[MD4_SIGNATURE_SIZE];
637
638     /* LANMan password is case insensitive */
639     BZERO(UcasePassword, sizeof(UcasePassword));
640     for (i = 0; i < secret_len; i++)
641        UcasePassword[i] = (u_char)toupper(secret[i]);
642     (void) DesSetkey(UcasePassword + 0);
643     DesEncrypt( StdText, PasswordHash + 0 );
644     (void) DesSetkey(UcasePassword + 7);
645     DesEncrypt( StdText, PasswordHash + 8 );
646     ChallengeResponse(rchallenge, PasswordHash, &response[MS_CHAP_LANMANRESP]);
647 }
648 #endif
649
650
651 void
652 GenerateAuthenticatorResponse(u_char PasswordHashHash[MD4_SIGNATURE_SIZE],
653                               u_char NTResponse[24], u_char PeerChallenge[16],
654                               u_char *rchallenge, char *username,
655                               u_char authResponse[MS_AUTH_RESPONSE_LENGTH+1])
656 {
657     /*
658      * "Magic" constants used in response generation, from RFC 2759.
659      */
660     u_char Magic1[39] = /* "Magic server to client signing constant" */
661         { 0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,
662           0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,
663           0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,
664           0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74 };
665     u_char Magic2[41] = /* "Pad to make it do more than one iteration" */
666         { 0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,
667           0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,
668           0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,
669           0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,
670           0x6E };
671
672     int         i;
673     SHA1_CTX    sha1Context;
674     u_char      Digest[SHA1_SIGNATURE_SIZE];
675     u_char      Challenge[8];
676
677     SHA1_Init(&sha1Context);
678     SHA1_Update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE);
679     SHA1_Update(&sha1Context, NTResponse, 24);
680     SHA1_Update(&sha1Context, Magic1, sizeof(Magic1));
681     SHA1_Final(Digest, &sha1Context);
682
683     ChallengeHash(PeerChallenge, rchallenge, username, Challenge);
684
685     SHA1_Init(&sha1Context);
686     SHA1_Update(&sha1Context, Digest, sizeof(Digest));
687     SHA1_Update(&sha1Context, Challenge, sizeof(Challenge));
688     SHA1_Update(&sha1Context, Magic2, sizeof(Magic2));
689     SHA1_Final(Digest, &sha1Context);
690
691     /* Convert to ASCII hex string. */
692     for (i = 0; i < MAX((MS_AUTH_RESPONSE_LENGTH / 2), sizeof(Digest)); i++)
693         sprintf((char *)&authResponse[i * 2], "%02X", Digest[i]);
694 }
695
696
697 static void
698 GenerateAuthenticatorResponsePlain
699                 (char *secret, int secret_len,
700                  u_char NTResponse[24], u_char PeerChallenge[16],
701                  u_char *rchallenge, char *username,
702                  u_char authResponse[MS_AUTH_RESPONSE_LENGTH+1])
703 {
704     u_char      unicodePassword[MAX_NT_PASSWORD * 2];
705     u_char      PasswordHash[MD4_SIGNATURE_SIZE];
706     u_char      PasswordHashHash[MD4_SIGNATURE_SIZE];
707
708     /* Hash (x2) the Unicode version of the secret (== password). */
709     ascii2unicode(secret, secret_len, unicodePassword);
710     NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash);
711     NTPasswordHash(PasswordHash, sizeof(PasswordHash),
712                    PasswordHashHash);
713
714     GenerateAuthenticatorResponse(PasswordHashHash, NTResponse, PeerChallenge,
715                                   rchallenge, username, authResponse);
716 }
717
718
719 #ifdef MPPE
720 /*
721  * Set mppe_xxxx_key from the NTPasswordHashHash.
722  * RFC 2548 (RADIUS support) requires us to export this function (ugh).
723  */
724 void
725 mppe_set_keys(u_char *rchallenge, u_char PasswordHashHash[MD4_SIGNATURE_SIZE])
726 {
727     SHA1_CTX    sha1Context;
728     u_char      Digest[SHA1_SIGNATURE_SIZE];    /* >= MPPE_MAX_KEY_LEN */
729
730     SHA1_Init(&sha1Context);
731     SHA1_Update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE);
732     SHA1_Update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE);
733     SHA1_Update(&sha1Context, rchallenge, 8);
734     SHA1_Final(Digest, &sha1Context);
735
736     /* Same key in both directions. */
737     BCOPY(Digest, mppe_send_key, sizeof(mppe_send_key));
738     BCOPY(Digest, mppe_recv_key, sizeof(mppe_recv_key));
739
740     mppe_keys_set = 1;
741 }
742
743 /*
744  * Set mppe_xxxx_key from MS-CHAP credentials. (see RFC 3079)
745  */
746 static void
747 Set_Start_Key(u_char *rchallenge, char *secret, int secret_len)
748 {
749     u_char      unicodePassword[MAX_NT_PASSWORD * 2];
750     u_char      PasswordHash[MD4_SIGNATURE_SIZE];
751     u_char      PasswordHashHash[MD4_SIGNATURE_SIZE];
752
753     /* Hash (x2) the Unicode version of the secret (== password). */
754     ascii2unicode(secret, secret_len, unicodePassword);
755     NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash);
756     NTPasswordHash(PasswordHash, sizeof(PasswordHash), PasswordHashHash);
757
758     mppe_set_keys(rchallenge, PasswordHashHash);
759 }
760
761 /*
762  * Set mppe_xxxx_key from MS-CHAPv2 credentials. (see RFC 3079)
763  *
764  * This helper function used in the Winbind module, which gets the
765  * NTHashHash from the server.
766  */
767 void
768 mppe_set_keys2(u_char PasswordHashHash[MD4_SIGNATURE_SIZE],
769                u_char NTResponse[24], int IsServer)
770 {
771     SHA1_CTX    sha1Context;
772     u_char      MasterKey[SHA1_SIGNATURE_SIZE]; /* >= MPPE_MAX_KEY_LEN */
773     u_char      Digest[SHA1_SIGNATURE_SIZE];    /* >= MPPE_MAX_KEY_LEN */
774
775     u_char SHApad1[40] =
776         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
777           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
778           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
779           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
780     u_char SHApad2[40] =
781         { 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
782           0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
783           0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
784           0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2 };
785
786     /* "This is the MPPE Master Key" */
787     u_char Magic1[27] =
788         { 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
789           0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d,
790           0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79 };
791     /* "On the client side, this is the send key; "
792        "on the server side, it is the receive key." */
793     u_char Magic2[84] =
794         { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
795           0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
796           0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
797           0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
798           0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
799           0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65,
800           0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
801           0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
802           0x6b, 0x65, 0x79, 0x2e };
803     /* "On the client side, this is the receive key; "
804        "on the server side, it is the send key." */
805     u_char Magic3[84] =
806         { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
807           0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
808           0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
809           0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
810           0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
811           0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73,
812           0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73,
813           0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20,
814           0x6b, 0x65, 0x79, 0x2e };
815     u_char *s;
816
817     SHA1_Init(&sha1Context);
818     SHA1_Update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE);
819     SHA1_Update(&sha1Context, NTResponse, 24);
820     SHA1_Update(&sha1Context, Magic1, sizeof(Magic1));
821     SHA1_Final(MasterKey, &sha1Context);
822
823     /*
824      * generate send key
825      */
826     if (IsServer)
827         s = Magic3;
828     else
829         s = Magic2;
830     SHA1_Init(&sha1Context);
831     SHA1_Update(&sha1Context, MasterKey, 16);
832     SHA1_Update(&sha1Context, SHApad1, sizeof(SHApad1));
833     SHA1_Update(&sha1Context, s, 84);
834     SHA1_Update(&sha1Context, SHApad2, sizeof(SHApad2));
835     SHA1_Final(Digest, &sha1Context);
836
837     BCOPY(Digest, mppe_send_key, sizeof(mppe_send_key));
838
839     /*
840      * generate recv key
841      */
842     if (IsServer)
843         s = Magic2;
844     else
845         s = Magic3;
846     SHA1_Init(&sha1Context);
847     SHA1_Update(&sha1Context, MasterKey, 16);
848     SHA1_Update(&sha1Context, SHApad1, sizeof(SHApad1));
849     SHA1_Update(&sha1Context, s, 84);
850     SHA1_Update(&sha1Context, SHApad2, sizeof(SHApad2));
851     SHA1_Final(Digest, &sha1Context);
852
853     BCOPY(Digest, mppe_recv_key, sizeof(mppe_recv_key));
854
855     mppe_keys_set = 1;
856 }
857
858 /*
859  * Set mppe_xxxx_key from MS-CHAPv2 credentials. (see RFC 3079)
860  */
861 static void
862 SetMasterKeys(char *secret, int secret_len, u_char NTResponse[24], int IsServer)
863 {
864     u_char      unicodePassword[MAX_NT_PASSWORD * 2];
865     u_char      PasswordHash[MD4_SIGNATURE_SIZE];
866     u_char      PasswordHashHash[MD4_SIGNATURE_SIZE];
867     /* Hash (x2) the Unicode version of the secret (== password). */
868     ascii2unicode(secret, secret_len, unicodePassword);
869     NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash);
870     NTPasswordHash(PasswordHash, sizeof(PasswordHash), PasswordHashHash);
871     mppe_set_keys2(PasswordHashHash, NTResponse, IsServer);
872 }
873
874 #endif /* MPPE */
875
876
877 void
878 ChapMS(u_char *rchallenge, char *secret, int secret_len,
879        unsigned char *response)
880 {
881     BZERO(response, MS_CHAP_RESPONSE_LEN);
882
883     ChapMS_NT(rchallenge, secret, secret_len, &response[MS_CHAP_NTRESP]);
884
885 #ifdef MSLANMAN
886     ChapMS_LANMan(rchallenge, secret, secret_len,
887                   &response[MS_CHAP_LANMANRESP]);
888
889     /* preferred method is set by option  */
890     response[MS_CHAP_USENT] = !ms_lanman;
891 #else
892     response[MS_CHAP_USENT] = 1;
893 #endif
894
895 #ifdef MPPE
896     Set_Start_Key(rchallenge, secret, secret_len);
897 #endif
898 }
899
900
901 /*
902  * If PeerChallenge is NULL, one is generated and the PeerChallenge
903  * field of response is filled in.  Call this way when generating a response.
904  * If PeerChallenge is supplied, it is copied into the PeerChallenge field.
905  * Call this way when verifying a response (or debugging).
906  * Do not call with PeerChallenge = response.
907  *
908  * The PeerChallenge field of response is then used for calculation of the
909  * Authenticator Response.
910  */
911 void
912 ChapMS2(u_char *rchallenge, u_char *PeerChallenge,
913         char *user, char *secret, int secret_len, unsigned char *response,
914         u_char authResponse[], int authenticator)
915 {
916     /* ARGSUSED */
917     u_char *p = &response[MS_CHAP2_PEER_CHALLENGE];
918     int i;
919
920     BZERO(response, MS_CHAP2_RESPONSE_LEN);
921
922     /* Generate the Peer-Challenge if requested, or copy it if supplied. */
923     if (!PeerChallenge)
924         for (i = 0; i < MS_CHAP2_PEER_CHAL_LEN; i++)
925             *p++ = (u_char) (drand48() * 0xff);
926     else
927         BCOPY(PeerChallenge, &response[MS_CHAP2_PEER_CHALLENGE],
928               MS_CHAP2_PEER_CHAL_LEN);
929
930     /* Generate the NT-Response */
931     ChapMS2_NT(rchallenge, &response[MS_CHAP2_PEER_CHALLENGE], user,
932                secret, secret_len, &response[MS_CHAP2_NTRESP]);
933
934     /* Generate the Authenticator Response. */
935     GenerateAuthenticatorResponsePlain(secret, secret_len,
936                                        &response[MS_CHAP2_NTRESP],
937                                        &response[MS_CHAP2_PEER_CHALLENGE],
938                                        rchallenge, user, authResponse);
939
940 #ifdef MPPE
941     SetMasterKeys(secret, secret_len,
942                   &response[MS_CHAP2_NTRESP], authenticator);
943 #endif
944 }
945
946 #ifdef MPPE
947 /*
948  * Set MPPE options from plugins.
949  */
950 void
951 set_mppe_enc_types(int policy, int types)
952 {
953     /* Early exit for unknown policies. */
954     if (policy != MPPE_ENC_POL_ENC_ALLOWED ||
955         policy != MPPE_ENC_POL_ENC_REQUIRED)
956         return;
957
958     /* Don't modify MPPE if it's optional and wasn't already configured. */
959     if (policy == MPPE_ENC_POL_ENC_ALLOWED && !ccp_wantoptions[0].mppe)
960         return;
961
962     /*
963      * Disable undesirable encryption types.  Note that we don't ENABLE
964      * any encryption types, to avoid overriding manual configuration.
965      */
966     switch(types) {
967         case MPPE_ENC_TYPES_RC4_40:
968             ccp_wantoptions[0].mppe &= ~MPPE_OPT_128;   /* disable 128-bit */
969             break;
970         case MPPE_ENC_TYPES_RC4_128:
971             ccp_wantoptions[0].mppe &= ~MPPE_OPT_40;    /* disable 40-bit */
972             break;
973         default:
974             break;
975     }
976 }
977 #endif /* MPPE */
978
979 static struct chap_digest_type chapms_digest = {
980         CHAP_MICROSOFT,         /* code */
981         chapms_generate_challenge,
982         chapms_verify_response,
983         chapms_make_response,
984         NULL,                   /* check_success */
985         chapms_handle_failure,
986 };
987
988 static struct chap_digest_type chapms2_digest = {
989         CHAP_MICROSOFT_V2,      /* code */
990         chapms2_generate_challenge,
991         chapms2_verify_response,
992         chapms2_make_response,
993         chapms2_check_success,
994         chapms_handle_failure,
995 };
996
997 void
998 chapms_init(void)
999 {
1000         chap_register_digest(&chapms_digest);
1001         chap_register_digest(&chapms2_digest);
1002         add_options(chapms_option_list);
1003 }
1004
1005 #endif /* CHAPMS */