ReactOS  0.4.15-dev-1207-g698a8e6
chap.c
Go to the documentation of this file.
1 /*** WARNING - THIS HAS NEVER BEEN FINISHED ***/
2 /*****************************************************************************
3 * chap.c - Network Challenge Handshake Authentication Protocol program file.
4 *
5 * Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
6 * portions Copyright (c) 1997 by Global Election Systems Inc.
7 *
8 * The authors hereby grant permission to use, copy, modify, distribute,
9 * and license this software and its documentation for any purpose, provided
10 * that existing copyright notices are retained in all copies and that this
11 * notice and the following disclaimer are included verbatim in any
12 * distributions. No written agreement, license, or royalty fee is required
13 * for any of the authorized uses.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 ******************************************************************************
27 * REVISION HISTORY
28 *
29 * 03-01-01 Marc Boucher <marc@mbsi.ca>
30 * Ported to lwIP.
31 * 97-12-04 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
32 * Original based on BSD chap.c.
33 *****************************************************************************/
34 /*
35  * chap.c - Challenge Handshake Authentication Protocol.
36  *
37  * Copyright (c) 1993 The Australian National University.
38  * All rights reserved.
39  *
40  * Redistribution and use in source and binary forms are permitted
41  * provided that the above copyright notice and this paragraph are
42  * duplicated in all such forms and that any documentation,
43  * advertising materials, and other materials related to such
44  * distribution and use acknowledge that the software was developed
45  * by the Australian National University. The name of the University
46  * may not be used to endorse or promote products derived from this
47  * software without specific prior written permission.
48  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
49  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
50  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
51  *
52  * Copyright (c) 1991 Gregory M. Christy.
53  * All rights reserved.
54  *
55  * Redistribution and use in source and binary forms are permitted
56  * provided that the above copyright notice and this paragraph are
57  * duplicated in all such forms and that any documentation,
58  * advertising materials, and other materials related to such
59  * distribution and use acknowledge that the software was developed
60  * by Gregory M. Christy. The name of the author may not be used to
61  * endorse or promote products derived from this software without
62  * specific prior written permission.
63  *
64  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
65  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
66  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
67  */
68 
69 #include "lwip/opt.h"
70 
71 #if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */
72 
73 #if CHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */
74 
75 #include "ppp_impl.h"
76 #include "pppdebug.h"
77 
78 #include "magic.h"
79 #include "randm.h"
80 #include "auth.h"
81 #include "md5.h"
82 #include "chap.h"
83 #include "chpms.h"
84 
85 #include <string.h>
86 
87 #if 0 /* UNUSED */
88 /*
89  * Command-line options.
90  */
91 static option_t chap_option_list[] = {
92  { "chap-restart", o_int, &chap[0].timeouttime,
93  "Set timeout for CHAP" },
94  { "chap-max-challenge", o_int, &chap[0].max_transmits,
95  "Set max #xmits for challenge" },
96  { "chap-interval", o_int, &chap[0].chal_interval,
97  "Set interval for rechallenge" },
98 #ifdef MSLANMAN
99  { "ms-lanman", o_bool, &ms_lanman,
100  "Use LanMan passwd when using MS-CHAP", 1 },
101 #endif
102  { NULL }
103 };
104 #endif /* UNUSED */
105 
106 /*
107  * Protocol entry points.
108  */
109 static void ChapInit (int);
110 static void ChapLowerUp (int);
111 static void ChapLowerDown (int);
112 static void ChapInput (int, u_char *, int);
113 static void ChapProtocolReject (int);
114 #if PPP_ADDITIONAL_CALLBACKS
115 static int ChapPrintPkt (u_char *, int, void (*) (void *, char *, ...), void *);
116 #endif
117 
118 struct protent chap_protent = {
119  PPP_CHAP,
120  ChapInit,
121  ChapInput,
122  ChapProtocolReject,
123  ChapLowerUp,
124  ChapLowerDown,
125  NULL,
126  NULL,
127 #if PPP_ADDITIONAL_CALLBACKS
128  ChapPrintPkt,
129  NULL,
130 #endif /* PPP_ADDITIONAL_CALLBACKS */
131  1,
132  "CHAP",
133 #if PPP_ADDITIONAL_CALLBACKS
134  NULL,
135  NULL,
136  NULL
137 #endif /* PPP_ADDITIONAL_CALLBACKS */
138 };
139 
140 chap_state chap[NUM_PPP]; /* CHAP state; one for each unit */
141 
142 static void ChapChallengeTimeout (void *);
143 static void ChapResponseTimeout (void *);
144 static void ChapReceiveChallenge (chap_state *, u_char *, u_char, int);
145 static void ChapRechallenge (void *);
146 static void ChapReceiveResponse (chap_state *, u_char *, int, int);
147 static void ChapReceiveSuccess(chap_state *cstate, u_char *inp, u_char id, int len);
148 static void ChapReceiveFailure(chap_state *cstate, u_char *inp, u_char id, int len);
149 static void ChapSendStatus (chap_state *, int);
150 static void ChapSendChallenge (chap_state *);
151 static void ChapSendResponse (chap_state *);
152 static void ChapGenChallenge (chap_state *);
153 
154 /*
155  * ChapInit - Initialize a CHAP unit.
156  */
157 static void
158 ChapInit(int unit)
159 {
160  chap_state *cstate = &chap[unit];
161 
162  BZERO(cstate, sizeof(*cstate));
163  cstate->unit = unit;
164  cstate->clientstate = CHAPCS_INITIAL;
165  cstate->serverstate = CHAPSS_INITIAL;
166  cstate->timeouttime = CHAP_DEFTIMEOUT;
167  cstate->max_transmits = CHAP_DEFTRANSMITS;
168  /* random number generator is initialized in magic_init */
169 }
170 
171 
172 /*
173  * ChapAuthWithPeer - Authenticate us with our peer (start client).
174  *
175  */
176 void
177 ChapAuthWithPeer(int unit, char *our_name, u_char digest)
178 {
179  chap_state *cstate = &chap[unit];
180 
181  cstate->resp_name = our_name;
182  cstate->resp_type = digest;
183 
184  if (cstate->clientstate == CHAPCS_INITIAL ||
185  cstate->clientstate == CHAPCS_PENDING) {
186  /* lower layer isn't up - wait until later */
187  cstate->clientstate = CHAPCS_PENDING;
188  return;
189  }
190 
191  /*
192  * We get here as a result of LCP coming up.
193  * So even if CHAP was open before, we will
194  * have to re-authenticate ourselves.
195  */
196  cstate->clientstate = CHAPCS_LISTEN;
197 }
198 
199 
200 /*
201  * ChapAuthPeer - Authenticate our peer (start server).
202  */
203 void
204 ChapAuthPeer(int unit, char *our_name, u_char digest)
205 {
206  chap_state *cstate = &chap[unit];
207 
208  cstate->chal_name = our_name;
209  cstate->chal_type = digest;
210 
211  if (cstate->serverstate == CHAPSS_INITIAL ||
212  cstate->serverstate == CHAPSS_PENDING) {
213  /* lower layer isn't up - wait until later */
214  cstate->serverstate = CHAPSS_PENDING;
215  return;
216  }
217 
218  ChapGenChallenge(cstate);
219  ChapSendChallenge(cstate); /* crank it up dude! */
220  cstate->serverstate = CHAPSS_INITIAL_CHAL;
221 }
222 
223 
224 /*
225  * ChapChallengeTimeout - Timeout expired on sending challenge.
226  */
227 static void
228 ChapChallengeTimeout(void *arg)
229 {
231 
232  /* if we aren't sending challenges, don't worry. then again we */
233  /* probably shouldn't be here either */
234  if (cstate->serverstate != CHAPSS_INITIAL_CHAL &&
235  cstate->serverstate != CHAPSS_RECHALLENGE) {
236  return;
237  }
238 
239  if (cstate->chal_transmits >= cstate->max_transmits) {
240  /* give up on peer */
241  CHAPDEBUG(LOG_ERR, ("Peer failed to respond to CHAP challenge\n"));
242  cstate->serverstate = CHAPSS_BADAUTH;
243  auth_peer_fail(cstate->unit, PPP_CHAP);
244  return;
245  }
246 
247  ChapSendChallenge(cstate); /* Re-send challenge */
248 }
249 
250 
251 /*
252  * ChapResponseTimeout - Timeout expired on sending response.
253  */
254 static void
255 ChapResponseTimeout(void *arg)
256 {
258 
259  /* if we aren't sending a response, don't worry. */
260  if (cstate->clientstate != CHAPCS_RESPONSE) {
261  return;
262  }
263 
264  ChapSendResponse(cstate); /* re-send response */
265 }
266 
267 
268 /*
269  * ChapRechallenge - Time to challenge the peer again.
270  */
271 static void
272 ChapRechallenge(void *arg)
273 {
275 
276  /* if we aren't sending a response, don't worry. */
277  if (cstate->serverstate != CHAPSS_OPEN) {
278  return;
279  }
280 
281  ChapGenChallenge(cstate);
282  ChapSendChallenge(cstate);
283  cstate->serverstate = CHAPSS_RECHALLENGE;
284 }
285 
286 
287 /*
288  * ChapLowerUp - The lower layer is up.
289  *
290  * Start up if we have pending requests.
291  */
292 static void
293 ChapLowerUp(int unit)
294 {
295  chap_state *cstate = &chap[unit];
296 
297  if (cstate->clientstate == CHAPCS_INITIAL) {
298  cstate->clientstate = CHAPCS_CLOSED;
299  } else if (cstate->clientstate == CHAPCS_PENDING) {
300  cstate->clientstate = CHAPCS_LISTEN;
301  }
302 
303  if (cstate->serverstate == CHAPSS_INITIAL) {
304  cstate->serverstate = CHAPSS_CLOSED;
305  } else if (cstate->serverstate == CHAPSS_PENDING) {
306  ChapGenChallenge(cstate);
307  ChapSendChallenge(cstate);
308  cstate->serverstate = CHAPSS_INITIAL_CHAL;
309  }
310 }
311 
312 
313 /*
314  * ChapLowerDown - The lower layer is down.
315  *
316  * Cancel all timeouts.
317  */
318 static void
319 ChapLowerDown(int unit)
320 {
321  chap_state *cstate = &chap[unit];
322 
323  /* Timeout(s) pending? Cancel if so. */
324  if (cstate->serverstate == CHAPSS_INITIAL_CHAL ||
325  cstate->serverstate == CHAPSS_RECHALLENGE) {
326  UNTIMEOUT(ChapChallengeTimeout, cstate);
327  } else if (cstate->serverstate == CHAPSS_OPEN
328  && cstate->chal_interval != 0) {
329  UNTIMEOUT(ChapRechallenge, cstate);
330  }
331  if (cstate->clientstate == CHAPCS_RESPONSE) {
332  UNTIMEOUT(ChapResponseTimeout, cstate);
333  }
334  cstate->clientstate = CHAPCS_INITIAL;
335  cstate->serverstate = CHAPSS_INITIAL;
336 }
337 
338 
339 /*
340  * ChapProtocolReject - Peer doesn't grok CHAP.
341  */
342 static void
343 ChapProtocolReject(int unit)
344 {
345  chap_state *cstate = &chap[unit];
346 
347  if (cstate->serverstate != CHAPSS_INITIAL &&
348  cstate->serverstate != CHAPSS_CLOSED) {
349  auth_peer_fail(unit, PPP_CHAP);
350  }
351  if (cstate->clientstate != CHAPCS_INITIAL &&
352  cstate->clientstate != CHAPCS_CLOSED) {
353  auth_withpeer_fail(unit, PPP_CHAP); /* lwip: just sets the PPP error code on this unit to PPPERR_AUTHFAIL */
354  }
355  ChapLowerDown(unit); /* shutdown chap */
356 }
357 
358 
359 /*
360  * ChapInput - Input CHAP packet.
361  */
362 static void
363 ChapInput(int unit, u_char *inpacket, int packet_len)
364 {
365  chap_state *cstate = &chap[unit];
366  u_char *inp;
367  u_char code, id;
368  int len;
369 
370  /*
371  * Parse header (code, id and length).
372  * If packet too short, drop it.
373  */
374  inp = inpacket;
375  if (packet_len < CHAP_HEADERLEN) {
376  CHAPDEBUG(LOG_INFO, ("ChapInput: rcvd short header.\n"));
377  return;
378  }
379  GETCHAR(code, inp);
380  GETCHAR(id, inp);
381  GETSHORT(len, inp);
382  if (len < CHAP_HEADERLEN) {
383  CHAPDEBUG(LOG_INFO, ("ChapInput: rcvd illegal length.\n"));
384  return;
385  }
386  if (len > packet_len) {
387  CHAPDEBUG(LOG_INFO, ("ChapInput: rcvd short packet.\n"));
388  return;
389  }
390  len -= CHAP_HEADERLEN;
391 
392  /*
393  * Action depends on code (as in fact it usually does :-).
394  */
395  switch (code) {
396  case CHAP_CHALLENGE:
397  ChapReceiveChallenge(cstate, inp, id, len);
398  break;
399 
400  case CHAP_RESPONSE:
401  ChapReceiveResponse(cstate, inp, id, len);
402  break;
403 
404  case CHAP_FAILURE:
405  ChapReceiveFailure(cstate, inp, id, len);
406  break;
407 
408  case CHAP_SUCCESS:
409  ChapReceiveSuccess(cstate, inp, id, len);
410  break;
411 
412  default: /* Need code reject? */
413  CHAPDEBUG(LOG_WARNING, ("Unknown CHAP code (%d) received.\n", code));
414  break;
415  }
416 }
417 
418 
419 /*
420  * ChapReceiveChallenge - Receive Challenge and send Response.
421  */
422 static void
423 ChapReceiveChallenge(chap_state *cstate, u_char *inp, u_char id, int len)
424 {
425  int rchallenge_len;
426  u_char *rchallenge;
427  int secret_len;
428  char secret[MAXSECRETLEN];
429  char rhostname[256];
430  MD5_CTX mdContext;
432 
433  CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: Rcvd id %d.\n", id));
434  if (cstate->clientstate == CHAPCS_CLOSED ||
435  cstate->clientstate == CHAPCS_PENDING) {
436  CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: in state %d\n",
437  cstate->clientstate));
438  return;
439  }
440 
441  if (len < 2) {
442  CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: rcvd short packet.\n"));
443  return;
444  }
445 
446  GETCHAR(rchallenge_len, inp);
447  len -= sizeof (u_char) + rchallenge_len; /* now name field length */
448  if (len < 0) {
449  CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: rcvd short packet.\n"));
450  return;
451  }
452  rchallenge = inp;
453  INCPTR(rchallenge_len, inp);
454 
455  if (len >= (int)sizeof(rhostname)) {
456  len = sizeof(rhostname) - 1;
457  }
458  BCOPY(inp, rhostname, len);
459  rhostname[len] = '\000';
460 
461  CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: received name field '%s'\n",
462  rhostname));
463 
464  /* Microsoft doesn't send their name back in the PPP packet */
465  if (ppp_settings.remote_name[0] != 0 && (ppp_settings.explicit_remote || rhostname[0] == 0)) {
466  strncpy(rhostname, ppp_settings.remote_name, sizeof(rhostname));
467  rhostname[sizeof(rhostname) - 1] = 0;
468  CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: using '%s' as remote name\n",
469  rhostname));
470  }
471 
472  /* get secret for authenticating ourselves with the specified host */
473  if (!get_secret(cstate->unit, cstate->resp_name, rhostname,
474  secret, &secret_len, 0)) {
475  secret_len = 0; /* assume null secret if can't find one */
476  CHAPDEBUG(LOG_WARNING, ("No CHAP secret found for authenticating us to %s\n",
477  rhostname));
478  }
479 
480  /* cancel response send timeout if necessary */
481  if (cstate->clientstate == CHAPCS_RESPONSE) {
482  UNTIMEOUT(ChapResponseTimeout, cstate);
483  }
484 
485  cstate->resp_id = id;
486  cstate->resp_transmits = 0;
487 
488  /* generate MD based on negotiated type */
489  switch (cstate->resp_type) {
490 
491  case CHAP_DIGEST_MD5:
492  MD5Init(&mdContext);
493  MD5Update(&mdContext, &cstate->resp_id, 1);
494  MD5Update(&mdContext, (u_char*)secret, secret_len);
495  MD5Update(&mdContext, rchallenge, rchallenge_len);
496  MD5Final(hash, &mdContext);
497  BCOPY(hash, cstate->response, MD5_SIGNATURE_SIZE);
498  cstate->resp_length = MD5_SIGNATURE_SIZE;
499  break;
500 
501 #if MSCHAP_SUPPORT
502  case CHAP_MICROSOFT:
503  ChapMS(cstate, rchallenge, rchallenge_len, secret, secret_len);
504  break;
505 #endif
506 
507  default:
508  CHAPDEBUG(LOG_INFO, ("unknown digest type %d\n", cstate->resp_type));
509  return;
510  }
511 
512  BZERO(secret, sizeof(secret));
513  ChapSendResponse(cstate);
514 }
515 
516 
517 /*
518  * ChapReceiveResponse - Receive and process response.
519  */
520 static void
521 ChapReceiveResponse(chap_state *cstate, u_char *inp, int id, int len)
522 {
523  u_char *remmd, remmd_len;
524  int secret_len, old_state;
525  int code;
526  char rhostname[256];
527  MD5_CTX mdContext;
528  char secret[MAXSECRETLEN];
530 
531  CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: Rcvd id %d.\n", id));
532 
533  if (cstate->serverstate == CHAPSS_CLOSED ||
534  cstate->serverstate == CHAPSS_PENDING) {
535  CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: in state %d\n",
536  cstate->serverstate));
537  return;
538  }
539 
540  if (id != cstate->chal_id) {
541  return; /* doesn't match ID of last challenge */
542  }
543 
544  /*
545  * If we have received a duplicate or bogus Response,
546  * we have to send the same answer (Success/Failure)
547  * as we did for the first Response we saw.
548  */
549  if (cstate->serverstate == CHAPSS_OPEN) {
550  ChapSendStatus(cstate, CHAP_SUCCESS);
551  return;
552  }
553  if (cstate->serverstate == CHAPSS_BADAUTH) {
554  ChapSendStatus(cstate, CHAP_FAILURE);
555  return;
556  }
557 
558  if (len < 2) {
559  CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: rcvd short packet.\n"));
560  return;
561  }
562  GETCHAR(remmd_len, inp); /* get length of MD */
563  remmd = inp; /* get pointer to MD */
564  INCPTR(remmd_len, inp);
565 
566  len -= sizeof (u_char) + remmd_len;
567  if (len < 0) {
568  CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: rcvd short packet.\n"));
569  return;
570  }
571 
572  UNTIMEOUT(ChapChallengeTimeout, cstate);
573 
574  if (len >= (int)sizeof(rhostname)) {
575  len = sizeof(rhostname) - 1;
576  }
577  BCOPY(inp, rhostname, len);
578  rhostname[len] = '\000';
579 
580  CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: received name field: %s\n",
581  rhostname));
582 
583  /*
584  * Get secret for authenticating them with us,
585  * do the hash ourselves, and compare the result.
586  */
587  code = CHAP_FAILURE;
588  if (!get_secret(cstate->unit, rhostname, cstate->chal_name,
589  secret, &secret_len, 1)) {
590  CHAPDEBUG(LOG_WARNING, ("No CHAP secret found for authenticating %s\n",
591  rhostname));
592  } else {
593  /* generate MD based on negotiated type */
594  switch (cstate->chal_type) {
595 
596  case CHAP_DIGEST_MD5: /* only MD5 is defined for now */
597  if (remmd_len != MD5_SIGNATURE_SIZE) {
598  break; /* it's not even the right length */
599  }
600  MD5Init(&mdContext);
601  MD5Update(&mdContext, &cstate->chal_id, 1);
602  MD5Update(&mdContext, (u_char*)secret, secret_len);
603  MD5Update(&mdContext, cstate->challenge, cstate->chal_len);
604  MD5Final(hash, &mdContext);
605 
606  /* compare local and remote MDs and send the appropriate status */
607  if (memcmp (hash, remmd, MD5_SIGNATURE_SIZE) == 0) {
608  code = CHAP_SUCCESS; /* they are the same! */
609  }
610  break;
611 
612  default:
613  CHAPDEBUG(LOG_INFO, ("unknown digest type %d\n", cstate->chal_type));
614  }
615  }
616 
617  BZERO(secret, sizeof(secret));
618  ChapSendStatus(cstate, code);
619 
620  if (code == CHAP_SUCCESS) {
621  old_state = cstate->serverstate;
622  cstate->serverstate = CHAPSS_OPEN;
623  if (old_state == CHAPSS_INITIAL_CHAL) {
624  auth_peer_success(cstate->unit, PPP_CHAP, rhostname, len);
625  }
626  if (cstate->chal_interval != 0) {
627  TIMEOUT(ChapRechallenge, cstate, cstate->chal_interval);
628  }
629  } else {
630  CHAPDEBUG(LOG_ERR, ("CHAP peer authentication failed\n"));
631  cstate->serverstate = CHAPSS_BADAUTH;
632  auth_peer_fail(cstate->unit, PPP_CHAP);
633  }
634 }
635 
636 /*
637  * ChapReceiveSuccess - Receive Success
638  */
639 static void
640 ChapReceiveSuccess(chap_state *cstate, u_char *inp, u_char id, int len)
641 {
642  LWIP_UNUSED_ARG(id);
643  LWIP_UNUSED_ARG(inp);
644 
645  CHAPDEBUG(LOG_INFO, ("ChapReceiveSuccess: Rcvd id %d.\n", id));
646 
647  if (cstate->clientstate == CHAPCS_OPEN) {
648  /* presumably an answer to a duplicate response */
649  return;
650  }
651 
652  if (cstate->clientstate != CHAPCS_RESPONSE) {
653  /* don't know what this is */
654  CHAPDEBUG(LOG_INFO, ("ChapReceiveSuccess: in state %d\n",
655  cstate->clientstate));
656  return;
657  }
658 
659  UNTIMEOUT(ChapResponseTimeout, cstate);
660 
661  /*
662  * Print message.
663  */
664  if (len > 0) {
665  PRINTMSG(inp, len);
666  }
667 
668  cstate->clientstate = CHAPCS_OPEN;
669 
670  auth_withpeer_success(cstate->unit, PPP_CHAP);
671 }
672 
673 
674 /*
675  * ChapReceiveFailure - Receive failure.
676  */
677 static void
678 ChapReceiveFailure(chap_state *cstate, u_char *inp, u_char id, int len)
679 {
680  LWIP_UNUSED_ARG(id);
681  LWIP_UNUSED_ARG(inp);
682 
683  CHAPDEBUG(LOG_INFO, ("ChapReceiveFailure: Rcvd id %d.\n", id));
684 
685  if (cstate->clientstate != CHAPCS_RESPONSE) {
686  /* don't know what this is */
687  CHAPDEBUG(LOG_INFO, ("ChapReceiveFailure: in state %d\n",
688  cstate->clientstate));
689  return;
690  }
691 
692  UNTIMEOUT(ChapResponseTimeout, cstate);
693 
694  /*
695  * Print message.
696  */
697  if (len > 0) {
698  PRINTMSG(inp, len);
699  }
700 
701  CHAPDEBUG(LOG_ERR, ("CHAP authentication failed\n"));
702  auth_withpeer_fail(cstate->unit, PPP_CHAP); /* lwip: just sets the PPP error code on this unit to PPPERR_AUTHFAIL */
703 }
704 
705 
706 /*
707  * ChapSendChallenge - Send an Authenticate challenge.
708  */
709 static void
710 ChapSendChallenge(chap_state *cstate)
711 {
712  u_char *outp;
713  int chal_len, name_len;
714  int outlen;
715 
716  chal_len = cstate->chal_len;
717  name_len = (int)strlen(cstate->chal_name);
718  outlen = CHAP_HEADERLEN + sizeof (u_char) + chal_len + name_len;
719  outp = outpacket_buf[cstate->unit];
720 
721  MAKEHEADER(outp, PPP_CHAP); /* paste in a CHAP header */
722 
723  PUTCHAR(CHAP_CHALLENGE, outp);
724  PUTCHAR(cstate->chal_id, outp);
725  PUTSHORT(outlen, outp);
726 
727  PUTCHAR(chal_len, outp); /* put length of challenge */
728  BCOPY(cstate->challenge, outp, chal_len);
729  INCPTR(chal_len, outp);
730 
731  BCOPY(cstate->chal_name, outp, name_len); /* append hostname */
732 
733  pppWrite(cstate->unit, outpacket_buf[cstate->unit], outlen + PPP_HDRLEN);
734 
735  CHAPDEBUG(LOG_INFO, ("ChapSendChallenge: Sent id %d.\n", cstate->chal_id));
736 
737  TIMEOUT(ChapChallengeTimeout, cstate, cstate->timeouttime);
738  ++cstate->chal_transmits;
739 }
740 
741 
742 /*
743  * ChapSendStatus - Send a status response (ack or nak).
744  */
745 static void
746 ChapSendStatus(chap_state *cstate, int code)
747 {
748  u_char *outp;
749  int outlen, msglen;
750  char msg[256]; /* @todo: this can be a char*, no strcpy needed */
751 
752  if (code == CHAP_SUCCESS) {
753  strcpy(msg, "Welcome!");
754  } else {
755  strcpy(msg, "I don't like you. Go 'way.");
756  }
757  msglen = (int)strlen(msg);
758 
759  outlen = CHAP_HEADERLEN + msglen;
760  outp = outpacket_buf[cstate->unit];
761 
762  MAKEHEADER(outp, PPP_CHAP); /* paste in a header */
763 
764  PUTCHAR(code, outp);
765  PUTCHAR(cstate->chal_id, outp);
766  PUTSHORT(outlen, outp);
767  BCOPY(msg, outp, msglen);
768  pppWrite(cstate->unit, outpacket_buf[cstate->unit], outlen + PPP_HDRLEN);
769 
770  CHAPDEBUG(LOG_INFO, ("ChapSendStatus: Sent code %d, id %d.\n", code,
771  cstate->chal_id));
772 }
773 
774 /*
775  * ChapGenChallenge is used to generate a pseudo-random challenge string of
776  * a pseudo-random length between min_len and max_len. The challenge
777  * string and its length are stored in *cstate, and various other fields of
778  * *cstate are initialized.
779  */
780 
781 static void
782 ChapGenChallenge(chap_state *cstate)
783 {
784  int chal_len;
785  u_char *ptr = cstate->challenge;
786  int i;
787 
788  /* pick a random challenge length between MIN_CHALLENGE_LENGTH and
789  MAX_CHALLENGE_LENGTH */
790  chal_len = (unsigned)
791  ((((magic() >> 16) *
794  LWIP_ASSERT("chal_len <= 0xff", chal_len <= 0xffff);
795  cstate->chal_len = (u_char)chal_len;
796  cstate->chal_id = ++cstate->id;
797  cstate->chal_transmits = 0;
798 
799  /* generate a random string */
800  for (i = 0; i < chal_len; i++ ) {
801  *ptr++ = (char) (magic() & 0xff);
802  }
803 }
804 
805 /*
806  * ChapSendResponse - send a response packet with values as specified
807  * in *cstate.
808  */
809 /* ARGSUSED */
810 static void
811 ChapSendResponse(chap_state *cstate)
812 {
813  u_char *outp;
814  int outlen, md_len, name_len;
815 
816  md_len = cstate->resp_length;
817  name_len = (int)strlen(cstate->resp_name);
818  outlen = CHAP_HEADERLEN + sizeof (u_char) + md_len + name_len;
819  outp = outpacket_buf[cstate->unit];
820 
821  MAKEHEADER(outp, PPP_CHAP);
822 
823  PUTCHAR(CHAP_RESPONSE, outp); /* we are a response */
824  PUTCHAR(cstate->resp_id, outp); /* copy id from challenge packet */
825  PUTSHORT(outlen, outp); /* packet length */
826 
827  PUTCHAR(md_len, outp); /* length of MD */
828  BCOPY(cstate->response, outp, md_len); /* copy MD to buffer */
829  INCPTR(md_len, outp);
830 
831  BCOPY(cstate->resp_name, outp, name_len); /* append our name */
832 
833  /* send the packet */
834  pppWrite(cstate->unit, outpacket_buf[cstate->unit], outlen + PPP_HDRLEN);
835 
836  cstate->clientstate = CHAPCS_RESPONSE;
837  TIMEOUT(ChapResponseTimeout, cstate, cstate->timeouttime);
838  ++cstate->resp_transmits;
839 }
840 
841 #if PPP_ADDITIONAL_CALLBACKS
842 static char *ChapCodenames[] = {
843  "Challenge", "Response", "Success", "Failure"
844 };
845 /*
846  * ChapPrintPkt - print the contents of a CHAP packet.
847  */
848 static int
849 ChapPrintPkt( u_char *p, int plen, void (*printer) (void *, char *, ...), void *arg)
850 {
851  int code, id, len;
852  int clen, nlen;
853  u_char x;
854 
855  if (plen < CHAP_HEADERLEN) {
856  return 0;
857  }
858  GETCHAR(code, p);
859  GETCHAR(id, p);
860  GETSHORT(len, p);
862  return 0;
863  }
864 
865  if (code >= 1 && code <= sizeof(ChapCodenames) / sizeof(char *)) {
866  printer(arg, " %s", ChapCodenames[code-1]);
867  } else {
868  printer(arg, " code=0x%x", code);
869  }
870  printer(arg, " id=0x%x", id);
871  len -= CHAP_HEADERLEN;
872  switch (code) {
873  case CHAP_CHALLENGE:
874  case CHAP_RESPONSE:
875  if (len < 1) {
876  break;
877  }
878  clen = p[0];
879  if (len < clen + 1) {
880  break;
881  }
882  ++p;
883  nlen = len - clen - 1;
884  printer(arg, " <");
885  for (; clen > 0; --clen) {
886  GETCHAR(x, p);
887  printer(arg, "%.2x", x);
888  }
889  printer(arg, ">, name = %.*Z", nlen, p);
890  break;
891  case CHAP_FAILURE:
892  case CHAP_SUCCESS:
893  printer(arg, " %.*Z", len, p);
894  break;
895  default:
896  for (clen = len; clen > 0; --clen) {
897  GETCHAR(x, p);
898  printer(arg, " %.2x", x);
899  }
900  }
901 
902  return len + CHAP_HEADERLEN;
903 }
904 #endif /* PPP_ADDITIONAL_CALLBACKS */
905 
906 #endif /* CHAP_SUPPORT */
907 
908 #endif /* PPP_SUPPORT */
Definition: vj.h:105
#define CHAPCS_CLOSED
Definition: chap.h:126
#define CHAPCS_PENDING
Definition: chap.h:127
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
#define CHAP_RESPONSE
Definition: chap.h:84
VOID WINAPI MD5Init(MD5_CTX *)
Definition: md5.c:45
#define LOG_WARNING
Definition: syslog.h:49
#define CHAPSS_OPEN
Definition: chap.h:139
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
char * strncpy(char *DstString, const char *SrcString, ACPI_SIZE Count)
Definition: utclib.c:427
#define CHAP_CHALLENGE
Definition: chap.h:83
chap_state chap[]
u32_t magic(void)
VOID WINAPI MD5Final(MD5_CTX *)
Definition: md5.c:113
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
#define MAX_CHALLENGE_LENGTH
Definition: chap.h:92
void ChapMS(chap_state *, char *, int, char *, int)
void auth_withpeer_fail(int, u16_t)
#define CHAPCS_RESPONSE
Definition: chap.h:129
#define CHAPCS_OPEN
Definition: chap.h:130
VOID WINAPI MD5Update(MD5_CTX *, const unsigned char *, unsigned int)
Definition: md5.c:59
void ChapAuthPeer(int, char *, u_char)
#define LWIP_ASSERT(message, assertion)
Definition: debug.h:66
#define MD5_SIGNATURE_SIZE
Definition: chap.h:79
void auth_withpeer_success(int, u16_t)
int chal_interval
Definition: chap.h:109
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
int max_transmits
Definition: chap.h:111
int get_secret(int, char *, char *, char *, int *, int)
#define CHAPDEBUG(a, b)
Definition: pppdebug.h:68
static PVOID ptr
Definition: dispmode.c:27
png_const_structrp png_const_inforp int * unit
Definition: png.h:2161
smooth NULL
Definition: ftsmooth.c:416
#define CHAP_DIGEST_MD5
Definition: chap.h:78
unsigned char
Definition: typeof.h:29
#define TIMEOUT
Definition: ntpclient.c:12
#define CHAPSS_PENDING
Definition: chap.h:137
int timeouttime
Definition: chap.h:110
#define CHAPSS_BADAUTH
Definition: chap.h:141
#define LOG_ERR
Definition: syslog.h:48
#define CHAP_FAILURE
Definition: chap.h:86
static UCHAR * secret
Definition: bcrypt.c:29
#define CHAP_HEADERLEN
Definition: chap.h:72
#define CHAPSS_RECHALLENGE
Definition: chap.h:140
GLenum GLsizei len
Definition: glext.h:6722
Definition: inflate.c:139
int code
Definition: i386-dis.c:3591
#define CHAPSS_INITIAL
Definition: chap.h:135
#define CHAPSS_CLOSED
Definition: chap.h:136
#define CHAP_MICROSOFT
Definition: chap.h:80
#define CHAP_SUCCESS
Definition: chap.h:85
#define CHAPSS_INITIAL_CHAL
Definition: chap.h:138
#define CHAPCS_LISTEN
Definition: chap.h:128
#define MIN_CHALLENGE_LENGTH
Definition: chap.h:91
void ChapAuthWithPeer(int, char *, u_char)
void auth_peer_success(int, u16_t, char *, int)
#define msg(x)
Definition: auth_time.c:54
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
GLenum GLuint id
Definition: glext.h:5579
Definition: msi.c:4078
struct protent chap_protent
GLfloat GLfloat p
Definition: glext.h:8902
void auth_peer_fail(int, u16_t)
UCHAR u_char
Definition: types.h:80
Definition: _hash_fun.h:40
#define CHAPCS_INITIAL
Definition: chap.h:125
#define LWIP_UNUSED_ARG(x)
Definition: arch.h:73
#define LOG_INFO
Definition: syslog.h:51
static unsigned(__cdecl *hash_bstr)(bstr_t s)
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31