BadVPN – Blame information for rev 1

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