The Pedigree Project  0.1
chap_ms.c
1 /*
2  * chap_ms.c - Microsoft MS-CHAP compatible implementation.
3  *
4  * Copyright (c) 1995 Eric Rosenquist. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in
15  * the documentation and/or other materials provided with the
16  * distribution.
17  *
18  * 3. The name(s) of the authors of this software must not be used to
19  * endorse or promote products derived from this software without
20  * prior written permission.
21  *
22  * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
23  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
24  * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
25  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
26  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
27  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
28  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
29  */
30 
31 /*
32  * Modifications by Lauri Pesonen / lpesonen@clinet.fi, april 1997
33  *
34  * Implemented LANManager type password response to MS-CHAP challenges.
35  * Now pppd provides both NT style and LANMan style blocks, and the
36  * prefered is set by option "ms-lanman". Default is to use NT.
37  * The hash text (StdText) was taken from Win95 RASAPI32.DLL.
38  *
39  * You should also use DOMAIN\\USERNAME as described in README.MSCHAP80
40  */
41 
42 /*
43  * Modifications by Frank Cusack, frank@google.com, March 2002.
44  *
45  * Implemented MS-CHAPv2 functionality, heavily based on sample
46  * implementation in RFC 2759. Implemented MPPE functionality,
47  * heavily based on sample implementation in RFC 3079.
48  *
49  * Copyright (c) 2002 Google, Inc. All rights reserved.
50  *
51  * Redistribution and use in source and binary forms, with or without
52  * modification, are permitted provided that the following conditions
53  * are met:
54  *
55  * 1. Redistributions of source code must retain the above copyright
56  * notice, this list of conditions and the following disclaimer.
57  *
58  * 2. Redistributions in binary form must reproduce the above copyright
59  * notice, this list of conditions and the following disclaimer in
60  * the documentation and/or other materials provided with the
61  * distribution.
62  *
63  * 3. The name(s) of the authors of this software must not be used to
64  * endorse or promote products derived from this software without
65  * prior written permission.
66  *
67  * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
68  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
69  * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
70  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
71  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
72  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
73  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
74  *
75  */
76 
77 #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 */
#define LWIP_UNUSED_ARG(x)
Definition: arch.h:327