2 * chap_ms.c - Microsoft MS-CHAP compatible implementation.
4 * Copyright (c) 1995 Eric Rosenquist. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
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
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.
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.
32 * Modifications by Lauri Pesonen / lpesonen@clinet.fi, april 1997
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.
39 * You should also use DOMAIN\\USERNAME as described in README.MSCHAP80
43 * Modifications by Frank Cusack, frank@google.com, March 2002.
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.
49 * Copyright (c) 2002 The Android Open Source Project
51 * Redistribution and use in source and binary forms, with or without
52 * modification, are permitted provided that the following conditions
55 * 1. Redistributions of source code must retain the above copyright
56 * notice, this list of conditions and the following disclaimer.
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
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.
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.
77 #define RCSID "$Id: chap_ms.c,v 1.33 2004/11/12 09:57:43 paulus Exp $"
85 #include <sys/types.h>
92 #ifdef ANDROID_CHANGES
93 #include "openssl-hash.h"
101 static const char rcsid[] = RCSID;
104 static void ascii2unicode __P((char[], int, u_char[]));
105 static void NTPasswordHash __P((char *, int, u_char[MD4_SIGNATURE_SIZE]));
106 static void ChallengeResponse __P((u_char *, u_char *, u_char[24]));
107 static void ChapMS_NT __P((u_char *, char *, int, u_char[24]));
108 static void ChapMS2_NT __P((char *, u_char[16], char *, char *, int,
110 static void GenerateAuthenticatorResponsePlain
111 __P((char*, int, u_char[24], u_char[16], u_char *,
112 char *, u_char[41]));
114 static void ChapMS_LANMan __P((u_char *, char *, int, MS_ChapResponse *));
118 static void Set_Start_Key __P((u_char *, char *, int));
119 static void SetMasterKeys __P((char *, int, u_char[24], int));
123 bool ms_lanman = 0; /* Use LanMan password instead of NT */
124 /* Has meaning only with MS-CHAP challenges */
128 u_char mppe_send_key[MPPE_MAX_KEY_LEN];
129 u_char mppe_recv_key[MPPE_MAX_KEY_LEN];
130 int mppe_keys_set = 0; /* Have the MPPE keys been set? */
134 /* Use "[]|}{?/><,`!2&&(" (sans quotes) for RFC 3079 MS-CHAPv2 test value */
135 static char *mschap_challenge = NULL;
136 /* Use "!@\#$%^&*()_+:3|~" (sans quotes, backslash is to escape #) for ... */
137 static char *mschap2_peer_challenge = NULL;
140 #include "fsm.h" /* Need to poke MPPE options */
142 #include <net/ppp-comp.h>
146 * Command-line options.
148 static option_t chapms_option_list[] = {
150 { "ms-lanman", o_bool, &ms_lanman,
151 "Use LanMan passwd when using MS-CHAP", 1 },
154 { "mschap-challenge", o_string, &mschap_challenge,
155 "specify CHAP challenge" },
156 { "mschap2-peer-challenge", o_string, &mschap2_peer_challenge,
157 "specify CHAP peer challenge" },
163 * chapms_generate_challenge - generate a challenge for MS-CHAP.
164 * For MS-CHAP the challenge length is fixed at 8 bytes.
165 * The length goes in challenge[0] and the actual challenge starts
169 chapms_generate_challenge(unsigned char *challenge)
173 if (mschap_challenge && strlen(mschap_challenge) == 8)
174 memcpy(challenge, mschap_challenge, 8);
177 random_bytes(challenge, 8);
181 chapms2_generate_challenge(unsigned char *challenge)
185 if (mschap_challenge && strlen(mschap_challenge) == 16)
186 memcpy(challenge, mschap_challenge, 16);
189 random_bytes(challenge, 16);
193 chapms_verify_response(int id, char *name,
194 unsigned char *secret, int secret_len,
195 unsigned char *challenge, unsigned char *response,
196 char *message, int message_space)
198 MS_ChapResponse *rmd;
201 int challenge_len, response_len;
203 challenge_len = *challenge++; /* skip length, is 8 */
204 response_len = *response++;
205 if (response_len != MS_CHAP_RESPONSE_LEN)
208 rmd = (MS_ChapResponse *) response;
211 if (!rmd->UseNT[0]) {
212 /* Should really propagate this into the error packet. */
213 notice("Peer request for LANMAN auth not supported");
218 /* Generate the expected response. */
219 ChapMS(challenge, (char *)secret, secret_len, &md);
222 /* Determine which part of response to verify against */
224 diff = memcmp(&rmd->LANManResp, &md.LANManResp,
225 sizeof(md.LANManResp));
228 diff = memcmp(&rmd->NTResp, &md.NTResp, sizeof(md.NTResp));
231 slprintf(message, message_space, "Access granted");
236 /* See comments below for MS-CHAP V2 */
237 slprintf(message, message_space, "E=691 R=1 C=%0.*B V=0",
238 challenge_len, challenge);
243 chapms2_verify_response(int id, char *name,
244 unsigned char *secret, int secret_len,
245 unsigned char *challenge, unsigned char *response,
246 char *message, int message_space)
248 MS_Chap2Response *rmd;
250 char saresponse[MS_AUTH_RESPONSE_LENGTH+1];
251 int challenge_len, response_len;
253 challenge_len = *challenge++; /* skip length, is 16 */
254 response_len = *response++;
255 if (response_len != MS_CHAP2_RESPONSE_LEN)
256 goto bad; /* not even the right length */
258 rmd = (MS_Chap2Response *) response;
260 /* Generate the expected response and our mutual auth. */
261 ChapMS2(challenge, rmd->PeerChallenge, name,
262 (char *)secret, secret_len, &md,
263 (unsigned char *)saresponse, MS_CHAP2_AUTHENTICATOR);
265 /* compare MDs and send the appropriate status */
267 * Per RFC 2759, success message must be formatted as
268 * "S=<auth_string> M=<message>"
270 * <auth_string> is the Authenticator Response (mutual auth)
271 * <message> is a text message
273 * However, some versions of Windows (win98 tested) do not know
274 * about the M=<message> part (required per RFC 2759) and flag
275 * it as an error (reported incorrectly as an encryption error
276 * to the user). Since the RFC requires it, and it can be
277 * useful information, we supply it if the peer is a conforming
278 * system. Luckily (?), win98 sets the Flags field to 0x04
279 * (contrary to RFC requirements) so we can use that to
280 * distinguish between conforming and non-conforming systems.
282 * Special thanks to Alex Swiridov <say@real.kharkov.ua> for
283 * help debugging this.
285 if (memcmp(md.NTResp, rmd->NTResp, sizeof(md.NTResp)) == 0) {
287 slprintf(message, message_space, "S=%s", saresponse);
289 slprintf(message, message_space, "S=%s M=%s",
290 saresponse, "Access granted");
296 * Failure message must be formatted as
297 * "E=e R=r C=c V=v M=m"
299 * e = error code (we use 691, ERROR_AUTHENTICATION_FAILURE)
300 * r = retry (we use 1, ok to retry)
301 * c = challenge to use for next response, we reuse previous
302 * v = Change Password version supported, we use 0
305 * The M=m part is only for MS-CHAPv2. Neither win2k nor
306 * win98 (others untested) display the message to the user anyway.
307 * They also both ignore the E=e code.
309 * Note that it's safe to reuse the same challenge as we don't
310 * actually accept another response based on the error message
311 * (and no clients try to resend a response anyway).
313 * Basically, this whole bit is useless code, even the small
314 * implementation here is only because of overspecification.
316 slprintf(message, message_space, "E=691 R=1 C=%0.*B V=0 M=%s",
317 challenge_len, challenge, "Access denied");
322 chapms_make_response(unsigned char *response, int id, char *our_name,
323 unsigned char *challenge, char *secret, int secret_len,
324 unsigned char *private)
326 challenge++; /* skip length, should be 8 */
327 *response++ = MS_CHAP_RESPONSE_LEN;
328 ChapMS(challenge, secret, secret_len, (MS_ChapResponse *) response);
332 chapms2_make_response(unsigned char *response, int id, char *our_name,
333 unsigned char *challenge, char *secret, int secret_len,
334 unsigned char *private)
336 challenge++; /* skip length, should be 16 */
337 *response++ = MS_CHAP2_RESPONSE_LEN;
340 mschap2_peer_challenge,
344 our_name, secret, secret_len,
345 (MS_Chap2Response *) response, private,
346 MS_CHAP2_AUTHENTICATEE);
350 chapms2_check_success(unsigned char *msg, int len, unsigned char *private)
352 if ((len < MS_AUTH_RESPONSE_LENGTH + 2) ||
353 strncmp((char *)msg, "S=", 2) != 0) {
354 /* Packet does not start with "S=" */
355 error("MS-CHAPv2 Success packet is badly formed.");
360 if (len < MS_AUTH_RESPONSE_LENGTH
361 || memcmp(msg, private, MS_AUTH_RESPONSE_LENGTH)) {
362 /* Authenticator Response did not match expected. */
363 error("MS-CHAPv2 mutual authentication failed.");
366 /* Authenticator Response matches. */
367 msg += MS_AUTH_RESPONSE_LENGTH; /* Eat it */
368 len -= MS_AUTH_RESPONSE_LENGTH;
369 if ((len >= 3) && !strncmp((char *)msg, " M=", 3)) {
370 msg += 3; /* Eat the delimiter */
372 /* Packet has extra text which does not begin " M=" */
373 error("MS-CHAPv2 Success packet is badly formed.");
380 chapms_handle_failure(unsigned char *inp, int len)
385 /* We want a null-terminated string for strxxx(). */
386 msg = malloc(len + 1);
388 notice("Out of memory in chapms_handle_failure");
391 BCOPY(inp, msg, len);
396 * Deal with MS-CHAP formatted failure messages; just print the
397 * M=<message> part (if any). For MS-CHAP we're not really supposed
398 * to use M=<message>, but it shouldn't hurt. See
399 * chapms[2]_verify_response.
401 if (!strncmp(p, "E=", 2))
402 err = strtol(p, NULL, 10); /* Remember the error code. */
404 goto print_msg; /* Message is badly formatted. */
406 if (len && ((p = strstr(p, " M=")) != NULL)) {
407 /* M=<message> field found. */
410 /* No M=<message>; use the error code. */
412 case MS_CHAP_ERROR_RESTRICTED_LOGON_HOURS:
413 p = "E=646 Restricted logon hours";
416 case MS_CHAP_ERROR_ACCT_DISABLED:
417 p = "E=647 Account disabled";
420 case MS_CHAP_ERROR_PASSWD_EXPIRED:
421 p = "E=648 Password expired";
424 case MS_CHAP_ERROR_NO_DIALIN_PERMISSION:
425 p = "E=649 No dialin permission";
428 case MS_CHAP_ERROR_AUTHENTICATION_FAILURE:
429 p = "E=691 Authentication failure";
432 case MS_CHAP_ERROR_CHANGING_PASSWORD:
433 /* Should never see this, we don't support Change Password. */
434 p = "E=709 Error changing password";
439 error("Unknown MS-CHAP authentication failure: %.*v",
446 error("MS-CHAP authentication failed: %v", p);
451 ChallengeResponse(u_char *challenge,
452 u_char PasswordHash[MD4_SIGNATURE_SIZE],
455 u_char ZPasswordHash[21];
457 BZERO(ZPasswordHash, sizeof(ZPasswordHash));
458 BCOPY(PasswordHash, ZPasswordHash, MD4_SIGNATURE_SIZE);
461 dbglog("ChallengeResponse - ZPasswordHash %.*B",
462 sizeof(ZPasswordHash), ZPasswordHash);
465 (void) DesSetkey(ZPasswordHash + 0);
466 DesEncrypt(challenge, response + 0);
467 (void) DesSetkey(ZPasswordHash + 7);
468 DesEncrypt(challenge, response + 8);
469 (void) DesSetkey(ZPasswordHash + 14);
470 DesEncrypt(challenge, response + 16);
473 dbglog("ChallengeResponse - response %.24B", response);
478 ChallengeHash(u_char PeerChallenge[16], u_char *rchallenge,
479 char *username, u_char Challenge[8])
482 SHA1_CTX sha1Context;
483 u_char sha1Hash[SHA1_SIGNATURE_SIZE];
486 /* remove domain from "domain\username" */
487 if ((user = strrchr(username, '\\')) != NULL)
492 SHA1_Init(&sha1Context);
493 SHA1_Update(&sha1Context, PeerChallenge, 16);
494 SHA1_Update(&sha1Context, rchallenge, 16);
495 SHA1_Update(&sha1Context, (unsigned char *)user, strlen(user));
496 SHA1_Final(sha1Hash, &sha1Context);
498 BCOPY(sha1Hash, Challenge, 8);
502 * Convert the ASCII version of the password to Unicode.
503 * This implicitly supports 8-bit ISO8859/1 characters.
504 * This gives us the little-endian representation, which
505 * is assumed by all M$ CHAP RFCs. (Unicode byte ordering
506 * is machine-dependent.)
509 ascii2unicode(char ascii[], int ascii_len, u_char unicode[])
513 BZERO(unicode, ascii_len * 2);
514 for (i = 0; i < ascii_len; i++)
515 unicode[i * 2] = (u_char) ascii[i];
519 NTPasswordHash(char *secret, int secret_len, u_char hash[MD4_SIGNATURE_SIZE])
521 #ifdef ANDROID_CHANGES
522 /* We link with MD4 routines in openssl, we have to take bytes instead */
523 int mdlen = secret_len;
526 /* NetBSD uses the libc md4 routines which take bytes instead of bits */
527 int mdlen = secret_len;
529 int mdlen = secret_len * 8;
534 MD4Init(&md4Context);
535 MD4Update(&md4Context, (unsigned char *)secret, mdlen);
536 MD4Final(hash, &md4Context);
541 ChapMS_NT(u_char *rchallenge, char *secret, int secret_len,
542 u_char NTResponse[24])
544 u_char unicodePassword[MAX_NT_PASSWORD * 2];
545 u_char PasswordHash[MD4_SIGNATURE_SIZE];
547 /* Hash the Unicode version of the secret (== password). */
548 ascii2unicode(secret, secret_len, unicodePassword);
549 NTPasswordHash((char *)unicodePassword, secret_len * 2, PasswordHash);
551 ChallengeResponse(rchallenge, PasswordHash, NTResponse);
555 ChapMS2_NT(char *rchallenge, u_char PeerChallenge[16], char *username,
556 char *secret, int secret_len, u_char NTResponse[24])
558 u_char unicodePassword[MAX_NT_PASSWORD * 2];
559 u_char PasswordHash[MD4_SIGNATURE_SIZE];
562 ChallengeHash(PeerChallenge, (unsigned char *)rchallenge, username,
565 /* Hash the Unicode version of the secret (== password). */
566 ascii2unicode(secret, secret_len, unicodePassword);
567 NTPasswordHash((char *)unicodePassword, secret_len * 2, PasswordHash);
569 ChallengeResponse(Challenge, PasswordHash, NTResponse);
573 static u_char *StdText = (u_char *)"KGS!@#$%"; /* key from rasapi32.dll */
576 ChapMS_LANMan(u_char *rchallenge, char *secret, int secret_len,
577 MS_ChapResponse *response)
580 u_char UcasePassword[MAX_NT_PASSWORD]; /* max is actually 14 */
581 u_char PasswordHash[MD4_SIGNATURE_SIZE];
583 /* LANMan password is case insensitive */
584 BZERO(UcasePassword, sizeof(UcasePassword));
585 for (i = 0; i < secret_len; i++)
586 UcasePassword[i] = (u_char)toupper(secret[i]);
587 (void) DesSetkey(UcasePassword + 0);
588 DesEncrypt( StdText, PasswordHash + 0 );
589 (void) DesSetkey(UcasePassword + 7);
590 DesEncrypt( StdText, PasswordHash + 8 );
591 ChallengeResponse(rchallenge, PasswordHash, response->LANManResp);
597 GenerateAuthenticatorResponse(u_char PasswordHashHash[MD4_SIGNATURE_SIZE],
598 u_char NTResponse[24], u_char PeerChallenge[16],
599 u_char *rchallenge, char *username,
600 u_char authResponse[MS_AUTH_RESPONSE_LENGTH+1])
603 * "Magic" constants used in response generation, from RFC 2759.
605 u_char Magic1[39] = /* "Magic server to client signing constant" */
606 { 0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,
607 0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,
608 0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,
609 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74 };
610 u_char Magic2[41] = /* "Pad to make it do more than one iteration" */
611 { 0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,
612 0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,
613 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,
614 0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,
618 SHA1_CTX sha1Context;
619 u_char Digest[SHA1_SIGNATURE_SIZE];
622 SHA1_Init(&sha1Context);
623 SHA1_Update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE);
624 SHA1_Update(&sha1Context, NTResponse, 24);
625 SHA1_Update(&sha1Context, Magic1, sizeof(Magic1));
626 SHA1_Final(Digest, &sha1Context);
628 ChallengeHash(PeerChallenge, rchallenge, username, Challenge);
630 SHA1_Init(&sha1Context);
631 SHA1_Update(&sha1Context, Digest, sizeof(Digest));
632 SHA1_Update(&sha1Context, Challenge, sizeof(Challenge));
633 SHA1_Update(&sha1Context, Magic2, sizeof(Magic2));
634 SHA1_Final(Digest, &sha1Context);
636 /* Convert to ASCII hex string. */
637 for (i = 0; i < MAX((MS_AUTH_RESPONSE_LENGTH / 2), sizeof(Digest)); i++)
638 sprintf((char *)&authResponse[i * 2], "%02X", Digest[i]);
643 GenerateAuthenticatorResponsePlain
644 (char *secret, int secret_len,
645 u_char NTResponse[24], u_char PeerChallenge[16],
646 u_char *rchallenge, char *username,
647 u_char authResponse[MS_AUTH_RESPONSE_LENGTH+1])
649 u_char unicodePassword[MAX_NT_PASSWORD * 2];
650 u_char PasswordHash[MD4_SIGNATURE_SIZE];
651 u_char PasswordHashHash[MD4_SIGNATURE_SIZE];
653 /* Hash (x2) the Unicode version of the secret (== password). */
654 ascii2unicode(secret, secret_len, unicodePassword);
655 NTPasswordHash((char *)unicodePassword, secret_len * 2, PasswordHash);
656 NTPasswordHash((char *)PasswordHash, sizeof(PasswordHash),
659 GenerateAuthenticatorResponse(PasswordHashHash, NTResponse, PeerChallenge,
660 rchallenge, username, authResponse);
666 * Set mppe_xxxx_key from the NTPasswordHashHash.
667 * RFC 2548 (RADIUS support) requires us to export this function (ugh).
670 mppe_set_keys(u_char *rchallenge, u_char PasswordHashHash[MD4_SIGNATURE_SIZE])
672 SHA1_CTX sha1Context;
673 u_char Digest[SHA1_SIGNATURE_SIZE]; /* >= MPPE_MAX_KEY_LEN */
675 SHA1_Init(&sha1Context);
676 SHA1_Update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE);
677 SHA1_Update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE);
678 SHA1_Update(&sha1Context, rchallenge, 8);
679 SHA1_Final(Digest, &sha1Context);
681 /* Same key in both directions. */
682 BCOPY(Digest, mppe_send_key, sizeof(mppe_send_key));
683 BCOPY(Digest, mppe_recv_key, sizeof(mppe_recv_key));
689 * Set mppe_xxxx_key from MS-CHAP credentials. (see RFC 3079)
692 Set_Start_Key(u_char *rchallenge, char *secret, int secret_len)
694 u_char unicodePassword[MAX_NT_PASSWORD * 2];
695 u_char PasswordHash[MD4_SIGNATURE_SIZE];
696 u_char PasswordHashHash[MD4_SIGNATURE_SIZE];
698 /* Hash (x2) the Unicode version of the secret (== password). */
699 ascii2unicode(secret, secret_len, unicodePassword);
700 NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash);
701 NTPasswordHash(PasswordHash, sizeof(PasswordHash), PasswordHashHash);
703 mppe_set_keys(rchallenge, PasswordHashHash);
707 * Set mppe_xxxx_key from MS-CHAPv2 credentials. (see RFC 3079)
709 * This helper function used in the Winbind module, which gets the
710 * NTHashHash from the server.
713 mppe_set_keys2(u_char PasswordHashHash[MD4_SIGNATURE_SIZE],
714 u_char NTResponse[24], int IsServer)
716 SHA1_CTX sha1Context;
717 u_char MasterKey[SHA1_SIGNATURE_SIZE]; /* >= MPPE_MAX_KEY_LEN */
718 u_char Digest[SHA1_SIGNATURE_SIZE]; /* >= MPPE_MAX_KEY_LEN */
721 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
722 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
723 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
724 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
726 { 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
727 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
728 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
729 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2 };
731 /* "This is the MPPE Master Key" */
733 { 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
734 0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d,
735 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79 };
736 /* "On the client side, this is the send key; "
737 "on the server side, it is the receive key." */
739 { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
740 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
741 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
742 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
743 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
744 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65,
745 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
746 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
747 0x6b, 0x65, 0x79, 0x2e };
748 /* "On the client side, this is the receive key; "
749 "on the server side, it is the send key." */
751 { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
752 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
753 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
754 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
755 0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
756 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73,
757 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73,
758 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20,
759 0x6b, 0x65, 0x79, 0x2e };
762 SHA1_Init(&sha1Context);
763 SHA1_Update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE);
764 SHA1_Update(&sha1Context, NTResponse, 24);
765 SHA1_Update(&sha1Context, Magic1, sizeof(Magic1));
766 SHA1_Final(MasterKey, &sha1Context);
775 SHA1_Init(&sha1Context);
776 SHA1_Update(&sha1Context, MasterKey, 16);
777 SHA1_Update(&sha1Context, SHApad1, sizeof(SHApad1));
778 SHA1_Update(&sha1Context, s, 84);
779 SHA1_Update(&sha1Context, SHApad2, sizeof(SHApad2));
780 SHA1_Final(Digest, &sha1Context);
782 BCOPY(Digest, mppe_send_key, sizeof(mppe_send_key));
791 SHA1_Init(&sha1Context);
792 SHA1_Update(&sha1Context, MasterKey, 16);
793 SHA1_Update(&sha1Context, SHApad1, sizeof(SHApad1));
794 SHA1_Update(&sha1Context, s, 84);
795 SHA1_Update(&sha1Context, SHApad2, sizeof(SHApad2));
796 SHA1_Final(Digest, &sha1Context);
798 BCOPY(Digest, mppe_recv_key, sizeof(mppe_recv_key));
804 * Set mppe_xxxx_key from MS-CHAPv2 credentials. (see RFC 3079)
807 SetMasterKeys(char *secret, int secret_len, u_char NTResponse[24], int IsServer)
809 u_char unicodePassword[MAX_NT_PASSWORD * 2];
810 u_char PasswordHash[MD4_SIGNATURE_SIZE];
811 u_char PasswordHashHash[MD4_SIGNATURE_SIZE];
812 /* Hash (x2) the Unicode version of the secret (== password). */
813 ascii2unicode(secret, secret_len, unicodePassword);
814 NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash);
815 NTPasswordHash(PasswordHash, sizeof(PasswordHash), PasswordHashHash);
816 mppe_set_keys2(PasswordHashHash, NTResponse, IsServer);
823 ChapMS(u_char *rchallenge, char *secret, int secret_len,
824 MS_ChapResponse *response)
826 BZERO(response, sizeof(*response));
828 ChapMS_NT(rchallenge, secret, secret_len, response->NTResp);
831 ChapMS_LANMan(rchallenge, secret, secret_len, response);
833 /* preferred method is set by option */
834 response->UseNT[0] = !ms_lanman;
836 response->UseNT[0] = 1;
840 Set_Start_Key(rchallenge, secret, secret_len);
846 * If PeerChallenge is NULL, one is generated and response->PeerChallenge
847 * is filled in. Call this way when generating a response.
848 * If PeerChallenge is supplied, it is copied into response->PeerChallenge.
849 * Call this way when verifying a response (or debugging).
850 * Do not call with PeerChallenge = response->PeerChallenge.
852 * response->PeerChallenge is then used for calculation of the
853 * Authenticator Response.
856 ChapMS2(u_char *rchallenge, u_char *PeerChallenge,
857 char *user, char *secret, int secret_len, MS_Chap2Response *response,
858 u_char authResponse[], int authenticator)
861 u_char *p = response->PeerChallenge;
864 BZERO(response, sizeof(*response));
866 /* Generate the Peer-Challenge if requested, or copy it if supplied. */
868 for (i = 0; i < sizeof(response->PeerChallenge); i++)
869 *p++ = (u_char) (drand48() * 0xff);
871 BCOPY(PeerChallenge, response->PeerChallenge,
872 sizeof(response->PeerChallenge));
874 /* Generate the NT-Response */
875 ChapMS2_NT((char *)rchallenge, response->PeerChallenge, user,
876 secret, secret_len, response->NTResp);
878 /* Generate the Authenticator Response. */
879 GenerateAuthenticatorResponsePlain(secret, secret_len, response->NTResp,
880 response->PeerChallenge, rchallenge,
884 SetMasterKeys(secret, secret_len, response->NTResp, authenticator);
890 * Set MPPE options from plugins.
893 set_mppe_enc_types(int policy, int types)
895 /* Early exit for unknown policies. */
896 if (policy != MPPE_ENC_POL_ENC_ALLOWED ||
897 policy != MPPE_ENC_POL_ENC_REQUIRED)
900 /* Don't modify MPPE if it's optional and wasn't already configured. */
901 if (policy == MPPE_ENC_POL_ENC_ALLOWED && !ccp_wantoptions[0].mppe)
905 * Disable undesirable encryption types. Note that we don't ENABLE
906 * any encryption types, to avoid overriding manual configuration.
909 case MPPE_ENC_TYPES_RC4_40:
910 ccp_wantoptions[0].mppe &= ~MPPE_OPT_128; /* disable 128-bit */
912 case MPPE_ENC_TYPES_RC4_128:
913 ccp_wantoptions[0].mppe &= ~MPPE_OPT_40; /* disable 40-bit */
921 static struct chap_digest_type chapms_digest = {
922 CHAP_MICROSOFT, /* code */
923 chapms_generate_challenge,
924 chapms_verify_response,
925 chapms_make_response,
926 NULL, /* check_success */
927 chapms_handle_failure,
930 static struct chap_digest_type chapms2_digest = {
931 CHAP_MICROSOFT_V2, /* code */
932 chapms2_generate_challenge,
933 chapms2_verify_response,
934 chapms2_make_response,
935 chapms2_check_success,
936 chapms_handle_failure,
942 chap_register_digest(&chapms_digest);
943 chap_register_digest(&chapms2_digest);
944 add_options(chapms_option_list);