Mercurial > illumos > onarm
comparison usr/src/cmd/cmd-inet/usr.bin/pppd/chap_ms.c @ 0:c9caec207d52 b86
Initial porting based on b86
author | Koji Uno <koji.uno@sun.com> |
---|---|
date | Tue, 02 Jun 2009 18:56:50 +0900 |
parents | |
children | 1a15d5aaf794 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:c9caec207d52 |
---|---|
1 /* | |
2 * chap_ms.c - Microsoft MS-CHAP compatible implementation. | |
3 * | |
4 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. | |
5 * Use is subject to license terms. | |
6 * | |
7 * Copyright (c) 1995 Eric Rosenquist, Strata Software Limited. | |
8 * http://www.strataware.com/ | |
9 * | |
10 * All rights reserved. | |
11 * | |
12 * Redistribution and use in source and binary forms are permitted | |
13 * provided that the above copyright notice and this paragraph are | |
14 * duplicated in all such forms and that any documentation, | |
15 * advertising materials, and other materials related to such | |
16 * distribution and use acknowledge that the software was developed | |
17 * by Eric Rosenquist. The name of the author may not be used to | |
18 * endorse or promote products derived from this software without | |
19 * specific prior written permission. | |
20 * | |
21 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR | |
22 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED | |
23 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. | |
24 */ | |
25 | |
26 /* | |
27 * This module implements MS-CHAPv1 (RFC 2433) and MS-CHAPv2 (RFC 2759). | |
28 * | |
29 * Modifications by Lauri Pesonen / lpesonen@clinet.fi, april 1997 | |
30 * | |
31 * Implemented LANManager type password response to MS-CHAP challenges. | |
32 * Now pppd provides both NT style and LANMan style blocks, and the | |
33 * prefered is set by option "ms-lanman". Default is to use NT. | |
34 * The hash text (StdText) was taken from Win95 RASAPI32.DLL. | |
35 * | |
36 * You should also use DOMAIN\\USERNAME as described in README.MSCHAP80 | |
37 * | |
38 * Modifications by James Carlson / james.d.carlson@sun.com, June 1st, 2000. | |
39 * | |
40 * Added MS-CHAPv2 support. | |
41 */ | |
42 | |
43 #pragma ident "@(#)chap_ms.c 1.2 07/12/05 SMI" | |
44 #define RCSID "$Id: chap_ms.c,v 1.15 1999/08/13 06:46:12 paulus Exp $" | |
45 | |
46 #if defined(CHAPMS) || defined(CHAPMSV2) | |
47 | |
48 #include <stdio.h> | |
49 #include <stdlib.h> | |
50 #include <string.h> | |
51 #include <ctype.h> | |
52 #include <sys/types.h> | |
53 #include <sys/time.h> | |
54 #include <unistd.h> | |
55 #ifdef HAVE_CRYPT_H | |
56 #include <crypt.h> | |
57 #endif | |
58 | |
59 #ifdef CHAPMSV2 | |
60 #include "sha1.h" | |
61 #endif | |
62 | |
63 #ifndef USE_CRYPT | |
64 #include <des.h> | |
65 #endif | |
66 | |
67 #include "pppd.h" | |
68 #include "chap.h" | |
69 #include "chap_ms.h" | |
70 #include "md4.h" | |
71 | |
72 #if !defined(lint) && !defined(_lint) | |
73 static const char rcsid[] = RCSID; | |
74 #endif | |
75 | |
76 typedef struct { | |
77 u_char LANManResp[24]; | |
78 u_char NTResp[24]; | |
79 u_char UseNT; /* If 1, ignore the LANMan response field */ | |
80 } MS_ChapResponse; | |
81 /* We use MS_CHAP_RESPONSE_LEN, rather than sizeof(MS_ChapResponse), | |
82 in case this struct gets padded. */ | |
83 | |
84 typedef struct { | |
85 u_char PeerChallenge[16]; | |
86 u_char MustBeZero[8]; | |
87 u_char NTResp[24]; | |
88 u_char Flags; /* Should be zero (Win98 sends 04) */ | |
89 } MS_Chapv2Response; | |
90 /* We use MS_CHAPV2_RESPONSE_LEN, rather than sizeof(MS_Chapv2Response), | |
91 in case this struct gets padded. */ | |
92 | |
93 static void ChallengeResponse __P((u_char *, u_char *, u_char *)); | |
94 static void DesEncrypt __P((u_char *, u_char *, u_char *)); | |
95 static void MakeKey __P((u_char *, u_char *)); | |
96 static u_char Get7Bits __P((u_char *, int)); | |
97 #ifdef CHAPMS | |
98 static void ChapMS_NT __P((u_char *, char *, int, MS_ChapResponse *)); | |
99 #ifdef MSLANMAN | |
100 static void ChapMS_LANMan __P((u_char *, char *, int, MS_ChapResponse *)); | |
101 #endif | |
102 #endif | |
103 #ifdef CHAPMSV2 | |
104 static void ChapMSv2_NT __P((char *, u_char *, char *, int, | |
105 MS_Chapv2Response *)); | |
106 #endif | |
107 | |
108 #ifdef USE_CRYPT | |
109 static void Expand __P((u_char *, char *)); | |
110 static void Collapse __P((char *, u_char *)); | |
111 #endif | |
112 | |
113 #if defined(MSLANMAN) && defined(CHAPMS) | |
114 bool ms_lanman = 0; /* Use LanMan password instead of NT */ | |
115 /* Has meaning only with MS-CHAP challenges */ | |
116 #endif | |
117 | |
118 #ifdef CHAPMSV2 | |
119 /* Specially-formatted Microsoft CHAP response message. */ | |
120 static char status_message[256]; | |
121 #endif | |
122 | |
123 static void | |
124 ChallengeResponse(challenge, pwHash, response) | |
125 u_char *challenge; /* IN 8 octets */ | |
126 u_char *pwHash; /* IN 16 octets */ | |
127 u_char *response; /* OUT 24 octets */ | |
128 { | |
129 u_char ZPasswordHash[21]; | |
130 | |
131 BZERO(ZPasswordHash, sizeof(ZPasswordHash)); | |
132 BCOPY(pwHash, ZPasswordHash, MD4_SIGNATURE_SIZE); | |
133 | |
134 #if 0 | |
135 dbglog("ChallengeResponse - ZPasswordHash %.*B", | |
136 sizeof(ZPasswordHash), ZPasswordHash); | |
137 #endif | |
138 | |
139 DesEncrypt(challenge, ZPasswordHash + 0, response + 0); | |
140 DesEncrypt(challenge, ZPasswordHash + 7, response + 8); | |
141 DesEncrypt(challenge, ZPasswordHash + 14, response + 16); | |
142 | |
143 #if 0 | |
144 dbglog("ChallengeResponse - response %.24B", response); | |
145 #endif | |
146 } | |
147 | |
148 | |
149 #ifdef USE_CRYPT | |
150 static void | |
151 DesEncrypt(clear, key, cipher) | |
152 u_char *clear; /* IN 8 octets */ | |
153 u_char *key; /* IN 7 octets */ | |
154 u_char *cipher; /* OUT 8 octets */ | |
155 { | |
156 u_char des_key[8]; | |
157 char crypt_key[66]; | |
158 char des_input[66]; | |
159 | |
160 MakeKey(key, des_key); | |
161 | |
162 Expand(des_key, crypt_key); | |
163 setkey(crypt_key); | |
164 | |
165 #if 0 | |
166 CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet input : %.8B", clear)); | |
167 #endif | |
168 | |
169 Expand(clear, des_input); | |
170 encrypt(des_input, 0); | |
171 Collapse(des_input, cipher); | |
172 | |
173 #if 0 | |
174 CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet output: %.8B", cipher)); | |
175 #endif | |
176 } | |
177 | |
178 #else /* USE_CRYPT */ | |
179 | |
180 static void | |
181 DesEncrypt(clear, key, cipher) | |
182 u_char *clear; /* IN 8 octets */ | |
183 u_char *key; /* IN 7 octets */ | |
184 u_char *cipher; /* OUT 8 octets */ | |
185 { | |
186 des_cblock des_key; | |
187 des_key_schedule key_schedule; | |
188 | |
189 MakeKey(key, des_key); | |
190 | |
191 des_set_key(&des_key, key_schedule); | |
192 | |
193 #if 0 | |
194 CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet input : %.8B", clear)); | |
195 #endif | |
196 | |
197 des_ecb_encrypt((des_cblock *)clear, (des_cblock *)cipher, key_schedule, 1); | |
198 | |
199 #if 0 | |
200 CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet output: %.8B", cipher)); | |
201 #endif | |
202 } | |
203 | |
204 #endif /* USE_CRYPT */ | |
205 | |
206 | |
207 static u_char Get7Bits(input, startBit) | |
208 u_char *input; | |
209 int startBit; | |
210 { | |
211 register unsigned int word; | |
212 | |
213 word = (unsigned)input[startBit / 8] << 8; | |
214 word |= (unsigned)input[startBit / 8 + 1]; | |
215 | |
216 word >>= 15 - (startBit % 8 + 7); | |
217 | |
218 return word & 0xFE; | |
219 } | |
220 | |
221 #ifdef USE_CRYPT | |
222 | |
223 /* in == 8-byte string (expanded version of the 56-bit key) | |
224 * out == 64-byte string where each byte is either 1 or 0 | |
225 * Note that the low-order "bit" is always ignored by by setkey() | |
226 */ | |
227 static void Expand(in, out) | |
228 u_char *in; | |
229 char *out; | |
230 { | |
231 int j, c; | |
232 int i; | |
233 | |
234 for(i = 0; i < 64; in++){ | |
235 c = *in; | |
236 for(j = 7; j >= 0; j--) | |
237 *out++ = (c >> j) & 01; | |
238 i += 8; | |
239 } | |
240 } | |
241 | |
242 /* The inverse of Expand | |
243 */ | |
244 static void Collapse(in, out) | |
245 char *in; | |
246 u_char *out; | |
247 { | |
248 int j; | |
249 int i; | |
250 unsigned int c; | |
251 | |
252 for (i = 0; i < 64; i += 8, out++) { | |
253 c = 0; | |
254 for (j = 7; j >= 0; j--, in++) | |
255 c |= *(u_char *)in << j; | |
256 *out = c & 0xff; | |
257 } | |
258 } | |
259 #endif | |
260 | |
261 static void MakeKey(key, des_key) | |
262 u_char *key; /* IN 56 bit DES key missing parity bits */ | |
263 u_char *des_key; /* OUT 64 bit DES key with parity bits added */ | |
264 { | |
265 des_key[0] = Get7Bits(key, 0); | |
266 des_key[1] = Get7Bits(key, 7); | |
267 des_key[2] = Get7Bits(key, 14); | |
268 des_key[3] = Get7Bits(key, 21); | |
269 des_key[4] = Get7Bits(key, 28); | |
270 des_key[5] = Get7Bits(key, 35); | |
271 des_key[6] = Get7Bits(key, 42); | |
272 des_key[7] = Get7Bits(key, 49); | |
273 | |
274 #ifndef USE_CRYPT | |
275 des_set_odd_parity((des_cblock *)des_key); | |
276 #endif | |
277 | |
278 #if 0 | |
279 CHAPDEBUG((LOG_INFO, "MakeKey: 56-bit input : %.7B", key)); | |
280 CHAPDEBUG((LOG_INFO, "MakeKey: 64-bit output: %.8B", des_key)); | |
281 #endif | |
282 } | |
283 | |
284 #ifdef CHAPMS | |
285 static void | |
286 ChapMS_NT(rchallenge, secret, secret_len, response) | |
287 u_char *rchallenge; | |
288 char *secret; | |
289 int secret_len; | |
290 MS_ChapResponse *response; | |
291 { | |
292 int i; | |
293 #if defined(__NetBSD__) || defined(HAVE_LIBMD) | |
294 /* NetBSD uses the libc md4 routines which take bytes instead of bits */ | |
295 int mdlen = secret_len * 2; | |
296 #else | |
297 int mdlen = secret_len * 2 * 8; | |
298 #endif | |
299 MD4_CTX md4Context; | |
300 u_char hash[MD4_SIGNATURE_SIZE]; | |
301 u_char unicodePassword[MAX_NT_PASSWORD * 2]; | |
302 | |
303 /* Initialize the Unicode version of the secret (== password). */ | |
304 /* This implicitly supports 8-bit ISO8859/1 characters. */ | |
305 BZERO(unicodePassword, sizeof(unicodePassword)); | |
306 for (i = 0; i < secret_len; i++) | |
307 unicodePassword[i * 2] = (u_char)secret[i]; | |
308 | |
309 MD4Init(&md4Context); | |
310 MD4Update(&md4Context, unicodePassword, mdlen); | |
311 | |
312 MD4Final(hash, &md4Context); /* Tell MD4 we're done */ | |
313 | |
314 ChallengeResponse(rchallenge, hash, response->NTResp); | |
315 } | |
316 | |
317 #ifdef MSLANMAN | |
318 static u_char *StdText = (u_char *)"KGS!@#$%"; /* key from rasapi32.dll */ | |
319 | |
320 static void | |
321 ChapMS_LANMan(rchallenge, secret, secret_len, response) | |
322 u_char *rchallenge; | |
323 char *secret; | |
324 int secret_len; | |
325 MS_ChapResponse *response; | |
326 { | |
327 int i; | |
328 u_char UcasePassword[MAX_NT_PASSWORD]; /* max is actually 14 */ | |
329 u_char PasswordHash[MD4_SIGNATURE_SIZE]; | |
330 | |
331 /* LANMan password is case insensitive */ | |
332 BZERO(UcasePassword, sizeof(UcasePassword)); | |
333 for (i = 0; i < secret_len; i++) | |
334 UcasePassword[i] = (u_char)( | |
335 islower(secret[i]) ? toupper(secret[i]) : secret[i]); | |
336 DesEncrypt( StdText, UcasePassword + 0, PasswordHash + 0 ); | |
337 DesEncrypt( StdText, UcasePassword + 7, PasswordHash + 8 ); | |
338 ChallengeResponse(rchallenge, PasswordHash, response->LANManResp); | |
339 } | |
340 #endif | |
341 | |
342 void | |
343 ChapMS(cstate, rchallenge, rchallenge_len, secret, secret_len) | |
344 chap_state *cstate; | |
345 u_char *rchallenge; | |
346 int rchallenge_len; | |
347 char *secret; | |
348 int secret_len; | |
349 { | |
350 MS_ChapResponse response; | |
351 | |
352 if (rchallenge_len < 8) { | |
353 cstate->resp_length = 0; | |
354 return; | |
355 } | |
356 | |
357 #if 0 | |
358 CHAPDEBUG((LOG_INFO, "ChapMS: secret is '%.*s'", secret_len, secret)); | |
359 #endif | |
360 BZERO(&response, sizeof(response)); | |
361 | |
362 /* Calculate both always */ | |
363 ChapMS_NT(rchallenge, secret, secret_len, &response); | |
364 | |
365 #ifdef MSLANMAN | |
366 ChapMS_LANMan(rchallenge, secret, secret_len, &response); | |
367 | |
368 /* prefered method is set by option */ | |
369 response.UseNT = !ms_lanman; | |
370 #else | |
371 response.UseNT = 1; | |
372 #endif | |
373 | |
374 BCOPY(&response, cstate->response, MS_CHAP_RESPONSE_LEN); | |
375 cstate->resp_length = MS_CHAP_RESPONSE_LEN; | |
376 } | |
377 | |
378 static int | |
379 ChapMSStatus(cstate, flag) | |
380 chap_state *cstate; | |
381 int flag; | |
382 { | |
383 if (flag != 0) { | |
384 cstate->stat_message = NULL; | |
385 cstate->stat_length = 0; | |
386 } else { | |
387 cstate->stat_message = "E=691 R=0 M=\"Authentication failed\""; | |
388 cstate->stat_length = strlen(cstate->stat_message); | |
389 } | |
390 return (flag); | |
391 } | |
392 | |
393 int | |
394 ChapMSValidate(cstate, response, response_len, secret, secret_len) | |
395 chap_state *cstate; | |
396 u_char *response; | |
397 int response_len; | |
398 char *secret; | |
399 int secret_len; | |
400 { | |
401 MS_ChapResponse ckresp; | |
402 | |
403 if (response_len < MS_CHAP_RESPONSE_LEN || cstate->chal_len < 8) | |
404 return (0); | |
405 | |
406 BZERO(&ckresp, sizeof(ckresp)); | |
407 | |
408 if (response[MS_CHAP_RESPONSE_LEN-1]) { | |
409 ChapMS_NT(cstate->challenge, secret, secret_len, &ckresp); | |
410 return (ChapMSStatus(cstate, memcmp(ckresp.NTResp, response+24, | |
411 24) == 0)); | |
412 } | |
413 | |
414 #ifdef MSLANMAN | |
415 ChapMS_LANMan(cstate->challenge, secret, secret_len, &ckresp); | |
416 return (ChapMSStatus(cstate, | |
417 memcmp(ckresp.LANManResp, response, 24) == 0)); | |
418 #else | |
419 return (ChapMSStatus(cstate, 0)); | |
420 #endif | |
421 } | |
422 #endif /* CHAPMS */ | |
423 | |
424 #ifdef CHAPMSV2 | |
425 static void | |
426 ChallengeHash(peerchallenge, authenticatorchallenge, username, challenge) | |
427 u_char *peerchallenge, *authenticatorchallenge, *challenge; | |
428 char *username; | |
429 { | |
430 uint8_t digest[20]; | |
431 SHA1_CTX sha1Context; | |
432 char *cp; | |
433 | |
434 SHA1Init(&sha1Context); | |
435 SHA1Update(&sha1Context, peerchallenge, 16); | |
436 SHA1Update(&sha1Context, authenticatorchallenge, 16); | |
437 | |
438 /* | |
439 * Only the user name (as presented by the peer and | |
440 * excluding any prepended domain name) | |
441 * is used as input to SHAUpdate(). | |
442 */ | |
443 if ((cp = strchr(username,'\\')) != NULL) | |
444 username = cp; | |
445 | |
446 SHA1Update(&sha1Context, (uint8_t *)username, strlen(username)); | |
447 SHA1Final(digest, &sha1Context); | |
448 BCOPY(digest, challenge, 8); | |
449 } | |
450 | |
451 static void | |
452 ChapMSv2_NT(username, rchallenge, secret, secret_len, response) | |
453 char *username; | |
454 u_char *rchallenge; | |
455 char *secret; | |
456 int secret_len; | |
457 MS_Chapv2Response *response; | |
458 { | |
459 int i; | |
460 #if defined(__NetBSD__) || defined(HAVE_LIBMD) | |
461 /* NetBSD uses the libc md4 routines that take bytes instead of bits */ | |
462 int mdlen = secret_len * 2; | |
463 #else | |
464 int mdlen = secret_len * 2 * 8; | |
465 #endif | |
466 MD4_CTX md4Context; | |
467 u_char hash[MD4_SIGNATURE_SIZE]; | |
468 u_char challenge[8]; | |
469 u_char unicodePassword[MAX_NT_PASSWORD * 2]; | |
470 | |
471 /* Initialize the Unicode version of the secret (== password). */ | |
472 /* This implicitly supports 8-bit ISO8859/1 characters. */ | |
473 BZERO(unicodePassword, sizeof(unicodePassword)); | |
474 for (i = 0; i < secret_len && i < MAX_NT_PASSWORD; i++) | |
475 if ((unicodePassword[i * 2] = (u_char)secret[i]) == '\0') | |
476 break; | |
477 | |
478 ChallengeHash(response->PeerChallenge, rchallenge, username, challenge); | |
479 | |
480 MD4Init(&md4Context); | |
481 MD4Update(&md4Context, unicodePassword, mdlen); | |
482 | |
483 MD4Final(hash, &md4Context); /* Tell MD4 we're done */ | |
484 | |
485 ChallengeResponse(challenge, hash, response->NTResp); | |
486 } | |
487 | |
488 void | |
489 ChapMSv2(cstate, rchallenge, rchallenge_len, secret, secret_len) | |
490 chap_state *cstate; | |
491 u_char *rchallenge; | |
492 int rchallenge_len; | |
493 char *secret; | |
494 int secret_len; | |
495 { | |
496 MS_Chapv2Response response; | |
497 u_char *ptr; | |
498 int i; | |
499 | |
500 if (rchallenge_len < 8) { | |
501 cstate->resp_length = 0; | |
502 return; | |
503 } | |
504 | |
505 BZERO(&response, sizeof(response)); | |
506 | |
507 ptr = response.PeerChallenge; | |
508 for (i = 0; i < 16; i++) | |
509 *ptr++ = (u_char) (drand48() * 0xff); | |
510 | |
511 ChapMSv2_NT(cstate->resp_name, rchallenge, secret, secret_len, &response); | |
512 | |
513 BCOPY(&response, cstate->response, MS_CHAPV2_RESPONSE_LEN); | |
514 cstate->resp_length = MS_CHAPV2_RESPONSE_LEN; | |
515 } | |
516 | |
517 static void | |
518 ChapMSv2Success(cstate, msresp, authchall, rhostname, secret, secret_len) | |
519 chap_state *cstate; | |
520 MS_Chapv2Response *msresp; | |
521 u_char *authchall; | |
522 char *rhostname, *secret; | |
523 int secret_len; | |
524 { | |
525 static const u_char Magic1[39] = "Magic server to client signing constant"; | |
526 static const u_char Magic2[41] = | |
527 "Pad to make it do more than one iteration"; | |
528 #if defined(__NetBSD__) || defined(HAVE_LIBMD) | |
529 /* NetBSD uses the libc md4 routines that take bytes instead of bits */ | |
530 int mdlen = 1; | |
531 #else | |
532 int mdlen = 8; | |
533 #endif | |
534 u_char unicodePassword[MAX_NT_PASSWORD * 2]; | |
535 MD4_CTX md4Context; | |
536 u_char hash[MD4_SIGNATURE_SIZE]; | |
537 u_char hashhash[MD4_SIGNATURE_SIZE]; | |
538 SHA1_CTX sha1Context; | |
539 uint8_t digest[20]; | |
540 u_char challenge[8]; | |
541 char *cp; | |
542 static const char hexdig[] = "0123456789ABCDEF"; | |
543 int i; | |
544 | |
545 /* Initialize the Unicode version of the secret (== password). */ | |
546 /* This implicitly supports 8-bit ISO8859/1 characters. */ | |
547 BZERO(unicodePassword, sizeof(unicodePassword)); | |
548 for (i = 0; i < secret_len && i < MAX_NT_PASSWORD; i++) | |
549 if ((unicodePassword[i * 2] = (u_char)secret[i]) == '\0') | |
550 break; | |
551 | |
552 /* Hash the password with MD4 */ | |
553 MD4Init(&md4Context); | |
554 MD4Update(&md4Context, unicodePassword, secret_len * 2 * mdlen); | |
555 MD4Final(hash, &md4Context); | |
556 | |
557 /* Now hash the hash */ | |
558 MD4Init(&md4Context); | |
559 MD4Update(&md4Context, hash, MD4_SIGNATURE_SIZE * mdlen); | |
560 MD4Final(hashhash, &md4Context); | |
561 | |
562 SHA1Init(&sha1Context); | |
563 SHA1Update(&sha1Context, hashhash, MD4_SIGNATURE_SIZE); | |
564 SHA1Update(&sha1Context, msresp->NTResp, sizeof (msresp->NTResp)); | |
565 SHA1Update(&sha1Context, Magic1, 39); | |
566 SHA1Final(digest, &sha1Context); | |
567 | |
568 ChallengeHash(msresp->PeerChallenge, authchall, rhostname, challenge); | |
569 | |
570 SHA1Init(&sha1Context); | |
571 SHA1Update(&sha1Context, digest, 20); | |
572 SHA1Update(&sha1Context, challenge, 8); | |
573 SHA1Update(&sha1Context, Magic2, 41); | |
574 SHA1Final(digest, &sha1Context); | |
575 | |
576 cp = status_message; | |
577 *cp++ = 'S'; | |
578 *cp++ = '='; | |
579 for (i = 0; i < 20; i++) { | |
580 *cp++ = hexdig[digest[i]>>4]; | |
581 *cp++ = hexdig[digest[i]&15]; | |
582 } | |
583 /* | |
584 * RFC 2759 says that a M=<string> greeting message is possible | |
585 * here. It lies. Any such greeting causes Windoze-98 to give | |
586 * error number 742, "Dial-Up Networking was unable to complete | |
587 * the connection. The computer you're dialing in to does not | |
588 * support the data encryption requirements specified. Please | |
589 * check your encryption settings in the properties of the | |
590 * connection. If this problem persists, contact your network | |
591 * administrator." | |
592 */ | |
593 *cp = '\0'; | |
594 #if 0 | |
595 slprintf(cp, sizeof (status_message) - (cp-status_message), | |
596 "M=\"Welcome to %s.\"", hostname); | |
597 #endif | |
598 cstate->stat_message = status_message; | |
599 cstate->stat_length = strlen(status_message); | |
600 } | |
601 | |
602 int | |
603 ChapMSv2Validate(cstate, rhostname, response, response_len, secret, secret_len) | |
604 chap_state *cstate; | |
605 char *rhostname; | |
606 u_char *response; | |
607 int response_len; | |
608 char *secret; | |
609 int secret_len; | |
610 { | |
611 MS_Chapv2Response ckresp; | |
612 | |
613 if (response_len < MS_CHAPV2_RESPONSE_LEN || | |
614 /* response[MS_CHAPV2_RESPONSE_LEN-1] != 0 || */cstate->chal_len < 8) { | |
615 cstate->stat_message = NULL; | |
616 cstate->stat_length = 0; | |
617 return 0; | |
618 } | |
619 | |
620 BZERO(&ckresp, sizeof(ckresp)); | |
621 | |
622 BCOPY(response, ckresp.PeerChallenge, 16); | |
623 | |
624 ChapMSv2_NT(rhostname, cstate->challenge, secret, secret_len, &ckresp); | |
625 if (memcmp(ckresp.NTResp, response+24, 24) != 0) { | |
626 cstate->stat_message = "E=691 R=0 C=11111111111111111111111111111111 V=3 M=\"Authentication failed\""; | |
627 cstate->stat_length = strlen(cstate->stat_message); | |
628 return (0); | |
629 } | |
630 ChapMSv2Success(cstate, (MS_Chapv2Response *)response, cstate->challenge, | |
631 rhostname, secret, secret_len); | |
632 return (1); | |
633 } | |
634 #endif /* CHAPMSV2 */ | |
635 | |
636 #endif /* CHAPMS or CHAPMSV2 */ |