OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [Common/] [ethernet/] [lwIP_132/] [src/] [netif/] [ppp/] [chap.c] - Blame information for rev 606

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 606 jeremybenn
/*** 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.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
/*************************/
88
/*** LOCAL DEFINITIONS ***/
89
/*************************/
90
 
91
 
92
/************************/
93
/*** LOCAL DATA TYPES ***/
94
/************************/
95
 
96
 
97
/***********************************/
98
/*** LOCAL FUNCTION DECLARATIONS ***/
99
/***********************************/
100
/*
101
 * Protocol entry points.
102
 */
103
static void ChapInit (int);
104
static void ChapLowerUp (int);
105
static void ChapLowerDown (int);
106
static void ChapInput (int, u_char *, int);
107
static void ChapProtocolReject (int);
108
#if 0
109
static int  ChapPrintPkt (u_char *, int, void (*) (void *, char *, ...), void *);
110
#endif
111
 
112
static void ChapChallengeTimeout (void *);
113
static void ChapResponseTimeout (void *);
114
static void ChapReceiveChallenge (chap_state *, u_char *, int, int);
115
static void ChapRechallenge (void *);
116
static void ChapReceiveResponse (chap_state *, u_char *, int, int);
117
static void ChapReceiveSuccess(chap_state *cstate, u_char *inp, u_char id, int len);
118
static void ChapReceiveFailure(chap_state *cstate, u_char *inp, u_char id, int len);
119
static void ChapSendStatus (chap_state *, int);
120
static void ChapSendChallenge (chap_state *);
121
static void ChapSendResponse (chap_state *);
122
static void ChapGenChallenge (chap_state *);
123
 
124
 
125
/******************************/
126
/*** PUBLIC DATA STRUCTURES ***/
127
/******************************/
128
chap_state chap[NUM_PPP]; /* CHAP state; one for each unit */
129
 
130
struct protent chap_protent = {
131
  PPP_CHAP,
132
  ChapInit,
133
  ChapInput,
134
  ChapProtocolReject,
135
  ChapLowerUp,
136
  ChapLowerDown,
137
  NULL,
138
  NULL,
139
#if 0
140
  ChapPrintPkt,
141
  NULL,
142
#endif
143
  1,
144
  "CHAP",
145
#if 0
146
  NULL,
147
  NULL,
148
  NULL
149
#endif
150
};
151
 
152
 
153
/***********************************/
154
/*** PUBLIC FUNCTION DEFINITIONS ***/
155
/***********************************/
156
/*
157
 * ChapAuthWithPeer - Authenticate us with our peer (start client).
158
 *
159
 */
160
void
161
ChapAuthWithPeer(int unit, char *our_name, int digest)
162
{
163
  chap_state *cstate = &chap[unit];
164
 
165
  cstate->resp_name = our_name;
166
  cstate->resp_type = digest;
167
 
168
  if (cstate->clientstate == CHAPCS_INITIAL ||
169
      cstate->clientstate == CHAPCS_PENDING) {
170
    /* lower layer isn't up - wait until later */
171
    cstate->clientstate = CHAPCS_PENDING;
172
    return;
173
  }
174
 
175
  /*
176
   * We get here as a result of LCP coming up.
177
   * So even if CHAP was open before, we will
178
   * have to re-authenticate ourselves.
179
   */
180
  cstate->clientstate = CHAPCS_LISTEN;
181
}
182
 
183
 
184
/*
185
 * ChapAuthPeer - Authenticate our peer (start server).
186
 */
187
void
188
ChapAuthPeer(int unit, char *our_name, int digest)
189
{
190
  chap_state *cstate = &chap[unit];
191
 
192
  cstate->chal_name = our_name;
193
  cstate->chal_type = digest;
194
 
195
  if (cstate->serverstate == CHAPSS_INITIAL ||
196
      cstate->serverstate == CHAPSS_PENDING) {
197
    /* lower layer isn't up - wait until later */
198
    cstate->serverstate = CHAPSS_PENDING;
199
    return;
200
  }
201
 
202
  ChapGenChallenge(cstate);
203
  ChapSendChallenge(cstate);    /* crank it up dude! */
204
  cstate->serverstate = CHAPSS_INITIAL_CHAL;
205
}
206
 
207
 
208
/**********************************/
209
/*** LOCAL FUNCTION DEFINITIONS ***/
210
/**********************************/
211
/*
212
 * ChapInit - Initialize a CHAP unit.
213
 */
214
static void
215
ChapInit(int unit)
216
{
217
  chap_state *cstate = &chap[unit];
218
 
219
  BZERO(cstate, sizeof(*cstate));
220
  cstate->unit = unit;
221
  cstate->clientstate = CHAPCS_INITIAL;
222
  cstate->serverstate = CHAPSS_INITIAL;
223
  cstate->timeouttime = CHAP_DEFTIMEOUT;
224
  cstate->max_transmits = CHAP_DEFTRANSMITS;
225
  /* random number generator is initialized in magic_init */
226
}
227
 
228
 
229
/*
230
 * ChapChallengeTimeout - Timeout expired on sending challenge.
231
 */
232
static void
233
ChapChallengeTimeout(void *arg)
234
{
235
  chap_state *cstate = (chap_state *) arg;
236
 
237
  /* if we aren't sending challenges, don't worry.  then again we */
238
  /* probably shouldn't be here either */
239
  if (cstate->serverstate != CHAPSS_INITIAL_CHAL &&
240
      cstate->serverstate != CHAPSS_RECHALLENGE) {
241
    return;
242
  }
243
 
244
  if (cstate->chal_transmits >= cstate->max_transmits) {
245
    /* give up on peer */
246
    CHAPDEBUG((LOG_ERR, "Peer failed to respond to CHAP challenge\n"));
247
    cstate->serverstate = CHAPSS_BADAUTH;
248
    auth_peer_fail(cstate->unit, PPP_CHAP);
249
    return;
250
  }
251
 
252
  ChapSendChallenge(cstate); /* Re-send challenge */
253
}
254
 
255
 
256
/*
257
 * ChapResponseTimeout - Timeout expired on sending response.
258
 */
259
static void
260
ChapResponseTimeout(void *arg)
261
{
262
  chap_state *cstate = (chap_state *) arg;
263
 
264
  /* if we aren't sending a response, don't worry. */
265
  if (cstate->clientstate != CHAPCS_RESPONSE) {
266
    return;
267
  }
268
 
269
  ChapSendResponse(cstate);    /* re-send response */
270
}
271
 
272
 
273
/*
274
 * ChapRechallenge - Time to challenge the peer again.
275
 */
276
static void
277
ChapRechallenge(void *arg)
278
{
279
  chap_state *cstate = (chap_state *) arg;
280
 
281
  /* if we aren't sending a response, don't worry. */
282
  if (cstate->serverstate != CHAPSS_OPEN) {
283
    return;
284
  }
285
 
286
  ChapGenChallenge(cstate);
287
  ChapSendChallenge(cstate);
288
  cstate->serverstate = CHAPSS_RECHALLENGE;
289
}
290
 
291
 
292
/*
293
 * ChapLowerUp - The lower layer is up.
294
 *
295
 * Start up if we have pending requests.
296
 */
297
static void
298
ChapLowerUp(int unit)
299
{
300
  chap_state *cstate = &chap[unit];
301
 
302
  if (cstate->clientstate == CHAPCS_INITIAL) {
303
    cstate->clientstate = CHAPCS_CLOSED;
304
  } else if (cstate->clientstate == CHAPCS_PENDING) {
305
    cstate->clientstate = CHAPCS_LISTEN;
306
  }
307
 
308
  if (cstate->serverstate == CHAPSS_INITIAL) {
309
    cstate->serverstate = CHAPSS_CLOSED;
310
  } else if (cstate->serverstate == CHAPSS_PENDING) {
311
    ChapGenChallenge(cstate);
312
    ChapSendChallenge(cstate);
313
    cstate->serverstate = CHAPSS_INITIAL_CHAL;
314
  }
315
}
316
 
317
 
318
/*
319
 * ChapLowerDown - The lower layer is down.
320
 *
321
 * Cancel all timeouts.
322
 */
323
static void
324
ChapLowerDown(int unit)
325
{
326
  chap_state *cstate = &chap[unit];
327
 
328
  /* Timeout(s) pending?  Cancel if so. */
329
  if (cstate->serverstate == CHAPSS_INITIAL_CHAL ||
330
      cstate->serverstate == CHAPSS_RECHALLENGE) {
331
    UNTIMEOUT(ChapChallengeTimeout, cstate);
332
  } else if (cstate->serverstate == CHAPSS_OPEN
333
      && cstate->chal_interval != 0) {
334
    UNTIMEOUT(ChapRechallenge, cstate);
335
  }
336
  if (cstate->clientstate == CHAPCS_RESPONSE) {
337
    UNTIMEOUT(ChapResponseTimeout, cstate);
338
  }
339
  cstate->clientstate = CHAPCS_INITIAL;
340
  cstate->serverstate = CHAPSS_INITIAL;
341
}
342
 
343
 
344
/*
345
 * ChapProtocolReject - Peer doesn't grok CHAP.
346
 */
347
static void
348
ChapProtocolReject(int unit)
349
{
350
  chap_state *cstate = &chap[unit];
351
 
352
  if (cstate->serverstate != CHAPSS_INITIAL &&
353
      cstate->serverstate != CHAPSS_CLOSED) {
354
    auth_peer_fail(unit, PPP_CHAP);
355
  }
356
  if (cstate->clientstate != CHAPCS_INITIAL &&
357
      cstate->clientstate != CHAPCS_CLOSED) {
358
    auth_withpeer_fail(unit, PPP_CHAP);
359
  }
360
  ChapLowerDown(unit); /* shutdown chap */
361
}
362
 
363
 
364
/*
365
 * ChapInput - Input CHAP packet.
366
 */
367
static void
368
ChapInput(int unit, u_char *inpacket, int packet_len)
369
{
370
  chap_state *cstate = &chap[unit];
371
  u_char *inp;
372
  u_char code, id;
373
  int len;
374
 
375
  /*
376
   * Parse header (code, id and length).
377
   * If packet too short, drop it.
378
   */
379
  inp = inpacket;
380
  if (packet_len < CHAP_HEADERLEN) {
381
    CHAPDEBUG((LOG_INFO, "ChapInput: rcvd short header.\n"));
382
    return;
383
  }
384
  GETCHAR(code, inp);
385
  GETCHAR(id, inp);
386
  GETSHORT(len, inp);
387
  if (len < CHAP_HEADERLEN) {
388
    CHAPDEBUG((LOG_INFO, "ChapInput: rcvd illegal length.\n"));
389
    return;
390
  }
391
  if (len > packet_len) {
392
    CHAPDEBUG((LOG_INFO, "ChapInput: rcvd short packet.\n"));
393
    return;
394
  }
395
  len -= CHAP_HEADERLEN;
396
 
397
  /*
398
   * Action depends on code (as in fact it usually does :-).
399
   */
400
  switch (code) {
401
    case CHAP_CHALLENGE:
402
      ChapReceiveChallenge(cstate, inp, id, len);
403
      break;
404
 
405
    case CHAP_RESPONSE:
406
      ChapReceiveResponse(cstate, inp, id, len);
407
      break;
408
 
409
    case CHAP_FAILURE:
410
      ChapReceiveFailure(cstate, inp, id, len);
411
      break;
412
 
413
    case CHAP_SUCCESS:
414
      ChapReceiveSuccess(cstate, inp, id, len);
415
      break;
416
 
417
    default:        /* Need code reject? */
418
      CHAPDEBUG((LOG_WARNING, "Unknown CHAP code (%d) received.\n", code));
419
      break;
420
  }
421
}
422
 
423
 
424
/*
425
 * ChapReceiveChallenge - Receive Challenge and send Response.
426
 */
427
static void
428
ChapReceiveChallenge(chap_state *cstate, u_char *inp, int id, int len)
429
{
430
  int rchallenge_len;
431
  u_char *rchallenge;
432
  int secret_len;
433
  char secret[MAXSECRETLEN];
434
  char rhostname[256];
435
  MD5_CTX mdContext;
436
  u_char hash[MD5_SIGNATURE_SIZE];
437
 
438
  CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: Rcvd id %d.\n", id));
439
  if (cstate->clientstate == CHAPCS_CLOSED ||
440
    cstate->clientstate == CHAPCS_PENDING) {
441
    CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: in state %d\n",
442
         cstate->clientstate));
443
    return;
444
  }
445
 
446
  if (len < 2) {
447
    CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: rcvd short packet.\n"));
448
    return;
449
  }
450
 
451
  GETCHAR(rchallenge_len, inp);
452
  len -= sizeof (u_char) + rchallenge_len;  /* now name field length */
453
  if (len < 0) {
454
    CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: rcvd short packet.\n"));
455
    return;
456
  }
457
  rchallenge = inp;
458
  INCPTR(rchallenge_len, inp);
459
 
460
  if (len >= sizeof(rhostname)) {
461
    len = sizeof(rhostname) - 1;
462
  }
463
  BCOPY(inp, rhostname, len);
464
  rhostname[len] = '\000';
465
 
466
  CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: received name field '%s'\n", rhostname));
467
 
468
  /* Microsoft doesn't send their name back in the PPP packet */
469
  if (ppp_settings.remote_name[0] != 0 && (ppp_settings.explicit_remote || rhostname[0] == 0)) {
470
    strncpy(rhostname, ppp_settings.remote_name, sizeof(rhostname));
471
    rhostname[sizeof(rhostname) - 1] = 0;
472
    CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: using '%s' as remote name\n", rhostname));
473
  }
474
 
475
  /* get secret for authenticating ourselves with the specified host */
476
  if (!get_secret(cstate->unit, cstate->resp_name, rhostname, secret, &secret_len, 0)) {
477
    secret_len = 0;    /* assume null secret if can't find one */
478
    CHAPDEBUG((LOG_WARNING, "No CHAP secret found for authenticating us to %s\n", rhostname));
479
  }
480
 
481
  /* cancel response send timeout if necessary */
482
  if (cstate->clientstate == CHAPCS_RESPONSE) {
483
    UNTIMEOUT(ChapResponseTimeout, cstate);
484
  }
485
 
486
  cstate->resp_id = id;
487
  cstate->resp_transmits = 0;
488
 
489
  /*  generate MD based on negotiated type */
490
  switch (cstate->resp_type) {
491
 
492
  case CHAP_DIGEST_MD5:
493
    MD5Init(&mdContext);
494
    MD5Update(&mdContext, &cstate->resp_id, 1);
495
    MD5Update(&mdContext, (u_char*)secret, secret_len);
496
    MD5Update(&mdContext, rchallenge, rchallenge_len);
497
    MD5Final(hash, &mdContext);
498
    BCOPY(hash, cstate->response, MD5_SIGNATURE_SIZE);
499
    cstate->resp_length = MD5_SIGNATURE_SIZE;
500
    break;
501
 
502
#ifdef CHAPMS
503
  case CHAP_MICROSOFT:
504
    ChapMS(cstate, rchallenge, rchallenge_len, secret, secret_len);
505
    break;
506
#endif
507
 
508
  default:
509
    CHAPDEBUG((LOG_INFO, "unknown digest type %d\n", cstate->resp_type));
510
    return;
511
  }
512
 
513
  BZERO(secret, sizeof(secret));
514
  ChapSendResponse(cstate);
515
}
516
 
517
 
518
/*
519
 * ChapReceiveResponse - Receive and process response.
520
 */
521
static void
522
ChapReceiveResponse(chap_state *cstate, u_char *inp, int id, int len)
523
{
524
  u_char *remmd, remmd_len;
525
  int secret_len, old_state;
526
  int code;
527
  char rhostname[256];
528
  MD5_CTX mdContext;
529
  char secret[MAXSECRETLEN];
530
  u_char hash[MD5_SIGNATURE_SIZE];
531
 
532
  CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: Rcvd id %d.\n", id));
533
 
534
  if (cstate->serverstate == CHAPSS_CLOSED ||
535
      cstate->serverstate == CHAPSS_PENDING) {
536
    CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: in state %d\n",
537
    cstate->serverstate));
538
    return;
539
  }
540
 
541
  if (id != cstate->chal_id) {
542
    return;      /* doesn't match ID of last challenge */
543
  }
544
 
545
  /*
546
  * If we have received a duplicate or bogus Response,
547
  * we have to send the same answer (Success/Failure)
548
  * as we did for the first Response we saw.
549
  */
550
  if (cstate->serverstate == CHAPSS_OPEN) {
551
    ChapSendStatus(cstate, CHAP_SUCCESS);
552
    return;
553
  }
554
  if (cstate->serverstate == CHAPSS_BADAUTH) {
555
    ChapSendStatus(cstate, CHAP_FAILURE);
556
    return;
557
  }
558
 
559
  if (len < 2) {
560
    CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: rcvd short packet.\n"));
561
    return;
562
  }
563
  GETCHAR(remmd_len, inp); /* get length of MD */
564
  remmd = inp;             /* get pointer to MD */
565
  INCPTR(remmd_len, inp);
566
 
567
  len -= sizeof (u_char) + remmd_len;
568
  if (len < 0) {
569
    CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: rcvd short packet.\n"));
570
    return;
571
  }
572
 
573
  UNTIMEOUT(ChapChallengeTimeout, cstate);
574
 
575
  if (len >= sizeof(rhostname)) {
576
    len = sizeof(rhostname) - 1;
577
  }
578
  BCOPY(inp, rhostname, len);
579
  rhostname[len] = '\000';
580
 
581
  CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: received name field: %s\n", 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, secret, &secret_len, 1)) {
589
    /* CHAPDEBUG((LOG_WARNING, TL_CHAP, "No CHAP secret found for authenticating %s\n", rhostname)); */
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", cstate->clientstate));
655
    return;
656
  }
657
 
658
  UNTIMEOUT(ChapResponseTimeout, cstate);
659
 
660
  /*
661
   * Print message.
662
   */
663
  if (len > 0) {
664
    PRINTMSG(inp, len);
665
  }
666
 
667
  cstate->clientstate = CHAPCS_OPEN;
668
 
669
  auth_withpeer_success(cstate->unit, PPP_CHAP);
670
}
671
 
672
 
673
/*
674
 * ChapReceiveFailure - Receive failure.
675
 */
676
static void
677
ChapReceiveFailure(chap_state *cstate, u_char *inp, u_char id, int len)
678
{
679
  LWIP_UNUSED_ARG(id);
680
  LWIP_UNUSED_ARG(inp);
681
 
682
  CHAPDEBUG((LOG_INFO, "ChapReceiveFailure: Rcvd id %d.\n", id));
683
 
684
  if (cstate->clientstate != CHAPCS_RESPONSE) {
685
    /* don't know what this is */
686
    CHAPDEBUG((LOG_INFO, "ChapReceiveFailure: in state %d\n", cstate->clientstate));
687
    return;
688
  }
689
 
690
  UNTIMEOUT(ChapResponseTimeout, cstate);
691
 
692
  /*
693
   * Print message.
694
   */
695
  if (len > 0) {
696
    PRINTMSG(inp, len);
697
  }
698
 
699
  CHAPDEBUG((LOG_ERR, "CHAP authentication failed\n"));
700
  auth_withpeer_fail(cstate->unit, PPP_CHAP);
701
}
702
 
703
 
704
/*
705
 * ChapSendChallenge - Send an Authenticate challenge.
706
 */
707
static void
708
ChapSendChallenge(chap_state *cstate)
709
{
710
  u_char *outp;
711
  int chal_len, name_len;
712
  int outlen;
713
 
714
  chal_len = cstate->chal_len;
715
  name_len = strlen(cstate->chal_name);
716
  outlen = CHAP_HEADERLEN + sizeof (u_char) + chal_len + name_len;
717
  outp = outpacket_buf[cstate->unit];
718
 
719
  MAKEHEADER(outp, PPP_CHAP);    /* paste in a CHAP header */
720
 
721
  PUTCHAR(CHAP_CHALLENGE, outp);
722
  PUTCHAR(cstate->chal_id, outp);
723
  PUTSHORT(outlen, outp);
724
 
725
  PUTCHAR(chal_len, outp);    /* put length of challenge */
726
  BCOPY(cstate->challenge, outp, chal_len);
727
  INCPTR(chal_len, outp);
728
 
729
  BCOPY(cstate->chal_name, outp, name_len);  /* append hostname */
730
 
731
  pppWrite(cstate->unit, outpacket_buf[cstate->unit], outlen + PPP_HDRLEN);
732
 
733
  CHAPDEBUG((LOG_INFO, "ChapSendChallenge: Sent id %d.\n", cstate->chal_id));
734
 
735
  TIMEOUT(ChapChallengeTimeout, cstate, cstate->timeouttime);
736
  ++cstate->chal_transmits;
737
}
738
 
739
 
740
/*
741
 * ChapSendStatus - Send a status response (ack or nak).
742
 */
743
static void
744
ChapSendStatus(chap_state *cstate, int code)
745
{
746
  u_char *outp;
747
  int outlen, msglen;
748
  char msg[256];
749
 
750
  if (code == CHAP_SUCCESS) {
751
    strcpy(msg, "Welcome!");
752
  } else {
753
    strcpy(msg, "I don't like you.  Go 'way.");
754
  }
755
  msglen = strlen(msg);
756
 
757
  outlen = CHAP_HEADERLEN + msglen;
758
  outp = outpacket_buf[cstate->unit];
759
 
760
  MAKEHEADER(outp, PPP_CHAP);    /* paste in a header */
761
 
762
  PUTCHAR(code, outp);
763
  PUTCHAR(cstate->chal_id, outp);
764
  PUTSHORT(outlen, outp);
765
  BCOPY(msg, outp, msglen);
766
  pppWrite(cstate->unit, outpacket_buf[cstate->unit], outlen + PPP_HDRLEN);
767
 
768
  CHAPDEBUG((LOG_INFO, "ChapSendStatus: Sent code %d, id %d.\n", code, cstate->chal_id));
769
}
770
 
771
/*
772
 * ChapGenChallenge is used to generate a pseudo-random challenge string of
773
 * a pseudo-random length between min_len and max_len.  The challenge
774
 * string and its length are stored in *cstate, and various other fields of
775
 * *cstate are initialized.
776
 */
777
 
778
static void
779
ChapGenChallenge(chap_state *cstate)
780
{
781
  int chal_len;
782
  u_char *ptr = cstate->challenge;
783
  int i;
784
 
785
  /* pick a random challenge length between MIN_CHALLENGE_LENGTH and
786
     MAX_CHALLENGE_LENGTH */
787
  chal_len = (unsigned)
788
        ((((magic() >> 16) *
789
              (MAX_CHALLENGE_LENGTH - MIN_CHALLENGE_LENGTH)) >> 16)
790
           + MIN_CHALLENGE_LENGTH);
791
  cstate->chal_len = chal_len;
792
  cstate->chal_id = ++cstate->id;
793
  cstate->chal_transmits = 0;
794
 
795
  /* generate a random string */
796
  for (i = 0; i < chal_len; i++ ) {
797
    *ptr++ = (char) (magic() & 0xff);
798
  }
799
}
800
 
801
/*
802
 * ChapSendResponse - send a response packet with values as specified
803
 * in *cstate.
804
 */
805
/* ARGSUSED */
806
static void
807
ChapSendResponse(chap_state *cstate)
808
{
809
  u_char *outp;
810
  int outlen, md_len, name_len;
811
 
812
  md_len = cstate->resp_length;
813
  name_len = strlen(cstate->resp_name);
814
  outlen = CHAP_HEADERLEN + sizeof (u_char) + md_len + name_len;
815
  outp = outpacket_buf[cstate->unit];
816
 
817
  MAKEHEADER(outp, PPP_CHAP);
818
 
819
  PUTCHAR(CHAP_RESPONSE, outp);  /* we are a response */
820
  PUTCHAR(cstate->resp_id, outp);  /* copy id from challenge packet */
821
  PUTSHORT(outlen, outp);      /* packet length */
822
 
823
  PUTCHAR(md_len, outp);      /* length of MD */
824
  BCOPY(cstate->response, outp, md_len);    /* copy MD to buffer */
825
  INCPTR(md_len, outp);
826
 
827
  BCOPY(cstate->resp_name, outp, name_len);  /* append our name */
828
 
829
  /* send the packet */
830
  pppWrite(cstate->unit, outpacket_buf[cstate->unit], outlen + PPP_HDRLEN);
831
 
832
  cstate->clientstate = CHAPCS_RESPONSE;
833
  TIMEOUT(ChapResponseTimeout, cstate, cstate->timeouttime);
834
  ++cstate->resp_transmits;
835
}
836
 
837
#if 0
838
static char *ChapCodenames[] = {
839
  "Challenge", "Response", "Success", "Failure"
840
};
841
/*
842
 * ChapPrintPkt - print the contents of a CHAP packet.
843
 */
844
static int
845
ChapPrintPkt( u_char *p, int plen, void (*printer) (void *, char *, ...), void *arg)
846
{
847
  int code, id, len;
848
  int clen, nlen;
849
  u_char x;
850
 
851
  if (plen < CHAP_HEADERLEN) {
852
    return 0;
853
  }
854
  GETCHAR(code, p);
855
  GETCHAR(id, p);
856
  GETSHORT(len, p);
857
  if (len < CHAP_HEADERLEN || len > plen) {
858
    return 0;
859
  }
860
  if (code >= 1 && code <= sizeof(ChapCodenames) / sizeof(char *)) {
861
    printer(arg, " %s", ChapCodenames[code-1]);
862
  } else {
863
    printer(arg, " code=0x%x", code);
864
  }
865
  printer(arg, " id=0x%x", id);
866
  len -= CHAP_HEADERLEN;
867
  switch (code) {
868
    case CHAP_CHALLENGE:
869
    case CHAP_RESPONSE:
870
      if (len < 1) {
871
        break;
872
      }
873
      clen = p[0];
874
      if (len < clen + 1) {
875
        break;
876
      }
877
      ++p;
878
      nlen = len - clen - 1;
879
      printer(arg, " <");
880
      for (; clen > 0; --clen) {
881
        GETCHAR(x, p);
882
        printer(arg, "%.2x", x);
883
      }
884
      printer(arg, ">, name = %.*Z", nlen, p);
885
      break;
886
    case CHAP_FAILURE:
887
    case CHAP_SUCCESS:
888
      printer(arg, " %.*Z", len, p);
889
      break;
890
    default:
891
      for (clen = len; clen > 0; --clen) {
892
        GETCHAR(x, p);
893
        printer(arg, " %.2x", x);
894
      }
895
  }
896
 
897
  return len + CHAP_HEADERLEN;
898
}
899
#endif
900
 
901
#endif /* CHAP_SUPPORT */
902
 
903
#endif /* PPP_SUPPORT */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.