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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [lwIP_MCF5235_GCC/] [lwip/] [src/] [netif/] [ppp/] [chap.c] - Blame information for rev 586

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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