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