OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

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

powered by: WebSVN 2.1.0

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