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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [net/] [ppp/] [current/] [src/] [chap.c] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//      src/chap.c
4
//
5
//==========================================================================
6
// ####ECOSGPLCOPYRIGHTBEGIN####                                            
7
// -------------------------------------------                              
8
// This file is part of eCos, the Embedded Configurable Operating System.   
9
// Copyright (C) 2003 Free Software Foundation, Inc.                        
10
//
11
// eCos is free software; you can redistribute it and/or modify it under    
12
// the terms of the GNU General Public License as published by the Free     
13
// Software Foundation; either version 2 or (at your option) any later      
14
// version.                                                                 
15
//
16
// eCos is distributed in the hope that it will be useful, but WITHOUT      
17
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or    
18
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License    
19
// for more details.                                                        
20
//
21
// You should have received a copy of the GNU General Public License        
22
// along with eCos; if not, write to the Free Software Foundation, Inc.,    
23
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
24
//
25
// As a special exception, if other files instantiate templates or use      
26
// macros or inline functions from this file, or you compile this file      
27
// and link it with other works to produce a work based on this file,       
28
// this file does not by itself cause the resulting work to be covered by   
29
// the GNU General Public License. However the source code for this file    
30
// must still be made available in accordance with section (3) of the GNU   
31
// General Public License v2.                                               
32
//
33
// This exception does not invalidate any other reasons why a work based    
34
// on this file might be covered by the GNU General Public License.         
35
// -------------------------------------------                              
36
// ####ECOSGPLCOPYRIGHTEND####                                              
37
// ####BSDALTCOPYRIGHTBEGIN####                                             
38
// -------------------------------------------                              
39
// Portions of this software may have been derived from FreeBSD, OpenBSD,   
40
// or other sources, and if so are covered by the appropriate copyright     
41
// and license included herein.                                             
42
// -------------------------------------------                              
43
// ####BSDALTCOPYRIGHTEND####                                               
44
//==========================================================================
45
 
46
/*
47
 * chap.c - Challenge Handshake Authentication Protocol.
48
 *
49
 * Copyright (c) 1993 The Australian National University.
50
 * All rights reserved.
51
 *
52
 * Redistribution and use in source and binary forms are permitted
53
 * provided that the above copyright notice and this paragraph are
54
 * duplicated in all such forms and that any documentation,
55
 * advertising materials, and other materials related to such
56
 * distribution and use acknowledge that the software was developed
57
 * by the Australian National University.  The name of the University
58
 * may not be used to endorse or promote products derived from this
59
 * software without specific prior written permission.
60
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
61
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
62
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
63
 *
64
 * Copyright (c) 1991 Gregory M. Christy.
65
 * All rights reserved.
66
 *
67
 * Redistribution and use in source and binary forms are permitted
68
 * provided that the above copyright notice and this paragraph are
69
 * duplicated in all such forms and that any documentation,
70
 * advertising materials, and other materials related to such
71
 * distribution and use acknowledge that the software was developed
72
 * by Gregory M. Christy.  The name of the author may not be used to
73
 * endorse or promote products derived from this software without
74
 * specific prior written permission.
75
 *
76
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
77
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
78
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
79
 */
80
 
81
#ifndef lint
82
//static char rcsid[] = "$FreeBSD: src/usr.sbin/pppd/chap.c,v 1.10 1999/08/28 01:19:01 peter Exp $";
83
#endif
84
 
85
/*
86
 * TODO:
87
 */
88
 
89
#include <stdio.h>
90
#include <string.h>
91
#include <sys/types.h>
92
#include <sys/time.h>
93
#include <cyg/ppp/syslog.h>
94
#include <sys/md5.h>
95
 
96
#include "cyg/ppp/pppd.h"
97
#include "cyg/ppp/chap.h"
98
//#include "md5.h"
99
#ifdef CHAPMS
100
#include "cyg/ppp/chap_ms.h"
101
#endif
102
 
103
/*
104
 * Protocol entry points.
105
 */
106
static void ChapInit __P((int));
107
static void ChapLowerUp __P((int));
108
static void ChapLowerDown __P((int));
109
static void ChapInput __P((int, u_char *, int));
110
static void ChapProtocolReject __P((int));
111
static int  ChapPrintPkt __P((u_char *, int,
112
                              void (*) __P((void *, char *, ...)), void *));
113
 
114
struct protent chap_protent = {
115
    PPP_CHAP,
116
    ChapInit,
117
    ChapInput,
118
    ChapProtocolReject,
119
    ChapLowerUp,
120
    ChapLowerDown,
121
    NULL,
122
    NULL,
123
    ChapPrintPkt,
124
    NULL,
125
    1,
126
    "CHAP",
127
    NULL,
128
    NULL,
129
    NULL
130
};
131
 
132
chap_state chap[NUM_PPP];               /* CHAP state; one for each unit */
133
 
134
static void ChapChallengeTimeout __P((void *));
135
static void ChapResponseTimeout __P((void *));
136
static void ChapReceiveChallenge __P((chap_state *, u_char *, int, int));
137
static void ChapRechallenge __P((void *));
138
static void ChapReceiveResponse __P((chap_state *, u_char *, int, int));
139
static void ChapReceiveSuccess __P((chap_state *, u_char *, int, int));
140
static void ChapReceiveFailure __P((chap_state *, u_char *, int, int));
141
static void ChapSendStatus __P((chap_state *, int));
142
static void ChapSendChallenge __P((chap_state *));
143
static void ChapSendResponse __P((chap_state *));
144
static void ChapGenChallenge __P((chap_state *));
145
 
146
extern double drand48 __P((void));
147
extern void srand48 __P((long));
148
 
149
/*
150
 * ChapInit - Initialize a CHAP unit.
151
 */
152
static void
153
ChapInit(unit)
154
    int unit;
155
{
156
    chap_state *cstate = &chap[unit];
157
 
158
    BZERO(cstate, sizeof(*cstate));
159
    cstate->unit = unit;
160
    cstate->clientstate = CHAPCS_INITIAL;
161
    cstate->serverstate = CHAPSS_INITIAL;
162
    cstate->timeouttime = CHAP_DEFTIMEOUT;
163
    cstate->max_transmits = CHAP_DEFTRANSMITS;
164
    /* random number generator is initialized in magic_init */
165
}
166
 
167
 
168
/*
169
 * ChapAuthWithPeer - Authenticate us with our peer (start client).
170
 *
171
 */
172
void
173
ChapAuthWithPeer(unit, our_name, digest)
174
    int unit;
175
    char *our_name;
176
    int digest;
177
{
178
    chap_state *cstate = &chap[unit];
179
 
180
    cstate->resp_name = our_name;
181
    cstate->resp_type = digest;
182
 
183
    if (cstate->clientstate == CHAPCS_INITIAL ||
184
        cstate->clientstate == CHAPCS_PENDING) {
185
        /* lower layer isn't up - wait until later */
186
        cstate->clientstate = CHAPCS_PENDING;
187
        return;
188
    }
189
 
190
    /*
191
     * We get here as a result of LCP coming up.
192
     * So even if CHAP was open before, we will
193
     * have to re-authenticate ourselves.
194
     */
195
    cstate->clientstate = CHAPCS_LISTEN;
196
}
197
 
198
 
199
/*
200
 * ChapAuthPeer - Authenticate our peer (start server).
201
 */
202
void
203
ChapAuthPeer(unit, our_name, digest)
204
    int unit;
205
    char *our_name;
206
    int digest;
207
{
208
    chap_state *cstate = &chap[unit];
209
 
210
    cstate->chal_name = our_name;
211
    cstate->chal_type = digest;
212
 
213
    if (cstate->serverstate == CHAPSS_INITIAL ||
214
        cstate->serverstate == CHAPSS_PENDING) {
215
        /* lower layer isn't up - wait until later */
216
        cstate->serverstate = CHAPSS_PENDING;
217
        return;
218
    }
219
 
220
    ChapGenChallenge(cstate);
221
    ChapSendChallenge(cstate);          /* crank it up dude! */
222
    cstate->serverstate = CHAPSS_INITIAL_CHAL;
223
}
224
 
225
 
226
/*
227
 * ChapChallengeTimeout - Timeout expired on sending challenge.
228
 */
229
static void
230
ChapChallengeTimeout(arg)
231
    void *arg;
232
{
233
    chap_state *cstate = (chap_state *) arg;
234
 
235
    /* if we aren't sending challenges, don't worry.  then again we */
236
    /* probably shouldn't be here either */
237
    if (cstate->serverstate != CHAPSS_INITIAL_CHAL &&
238
        cstate->serverstate != CHAPSS_RECHALLENGE)
239
        return;
240
 
241
    if (cstate->chal_transmits >= cstate->max_transmits) {
242
        /* give up on peer */
243
        syslog(LOG_ERR, "Peer failed to respond to CHAP challenge");
244
        cstate->serverstate = CHAPSS_BADAUTH;
245
        auth_peer_fail(cstate->unit, PPP_CHAP);
246
        return;
247
    }
248
 
249
    ChapSendChallenge(cstate);          /* Re-send challenge */
250
}
251
 
252
 
253
/*
254
 * ChapResponseTimeout - Timeout expired on sending response.
255
 */
256
static void
257
ChapResponseTimeout(arg)
258
    void *arg;
259
{
260
    chap_state *cstate = (chap_state *) arg;
261
 
262
    /* if we aren't sending a response, don't worry. */
263
    if (cstate->clientstate != CHAPCS_RESPONSE)
264
        return;
265
 
266
    ChapSendResponse(cstate);           /* re-send response */
267
}
268
 
269
 
270
/*
271
 * ChapRechallenge - Time to challenge the peer again.
272
 */
273
static void
274
ChapRechallenge(arg)
275
    void *arg;
276
{
277
    chap_state *cstate = (chap_state *) arg;
278
 
279
    /* if we aren't sending a response, don't worry. */
280
    if (cstate->serverstate != CHAPSS_OPEN)
281
        return;
282
 
283
    ChapGenChallenge(cstate);
284
    ChapSendChallenge(cstate);
285
    cstate->serverstate = CHAPSS_RECHALLENGE;
286
}
287
 
288
 
289
/*
290
 * ChapLowerUp - The lower layer is up.
291
 *
292
 * Start up if we have pending requests.
293
 */
294
static void
295
ChapLowerUp(unit)
296
    int unit;
297
{
298
    chap_state *cstate = &chap[unit];
299
 
300
    if (cstate->clientstate == CHAPCS_INITIAL)
301
        cstate->clientstate = CHAPCS_CLOSED;
302
    else if (cstate->clientstate == CHAPCS_PENDING)
303
        cstate->clientstate = CHAPCS_LISTEN;
304
 
305
    if (cstate->serverstate == CHAPSS_INITIAL)
306
        cstate->serverstate = CHAPSS_CLOSED;
307
    else if (cstate->serverstate == CHAPSS_PENDING) {
308
        ChapGenChallenge(cstate);
309
        ChapSendChallenge(cstate);
310
        cstate->serverstate = CHAPSS_INITIAL_CHAL;
311
    }
312
}
313
 
314
 
315
/*
316
 * ChapLowerDown - The lower layer is down.
317
 *
318
 * Cancel all timeouts.
319
 */
320
static void
321
ChapLowerDown(unit)
322
    int unit;
323
{
324
    chap_state *cstate = &chap[unit];
325
 
326
    /* Timeout(s) pending?  Cancel if so. */
327
    if (cstate->serverstate == CHAPSS_INITIAL_CHAL ||
328
        cstate->serverstate == CHAPSS_RECHALLENGE)
329
        UNTIMEOUT(ChapChallengeTimeout, cstate);
330
    else if (cstate->serverstate == CHAPSS_OPEN
331
             && cstate->chal_interval != 0)
332
        UNTIMEOUT(ChapRechallenge, cstate);
333
    if (cstate->clientstate == CHAPCS_RESPONSE)
334
        UNTIMEOUT(ChapResponseTimeout, cstate);
335
 
336
    cstate->clientstate = CHAPCS_INITIAL;
337
    cstate->serverstate = CHAPSS_INITIAL;
338
}
339
 
340
 
341
/*
342
 * ChapProtocolReject - Peer doesn't grok CHAP.
343
 */
344
static void
345
ChapProtocolReject(unit)
346
    int unit;
347
{
348
    chap_state *cstate = &chap[unit];
349
 
350
    if (cstate->serverstate != CHAPSS_INITIAL &&
351
        cstate->serverstate != CHAPSS_CLOSED)
352
        auth_peer_fail(unit, PPP_CHAP);
353
    if (cstate->clientstate != CHAPCS_INITIAL &&
354
        cstate->clientstate != CHAPCS_CLOSED)
355
        auth_withpeer_fail(unit, PPP_CHAP);
356
    ChapLowerDown(unit);                /* shutdown chap */
357
}
358
 
359
 
360
/*
361
 * ChapInput - Input CHAP packet.
362
 */
363
static void
364
ChapInput(unit, inpacket, packet_len)
365
    int unit;
366
    u_char *inpacket;
367
    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."));
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."));
388
        return;
389
    }
390
    if (len > packet_len) {
391
        CHAPDEBUG((LOG_INFO, "ChapInput: rcvd short packet."));
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
        syslog(LOG_WARNING, "Unknown CHAP code (%d) received.", code);
418
        break;
419
    }
420
}
421
 
422
 
423
/*
424
 * ChapReceiveChallenge - Receive Challenge and send Response.
425
 */
426
static void
427
ChapReceiveChallenge(cstate, inp, id, len)
428
    chap_state *cstate;
429
    u_char *inp;
430
    int id;
431
    int len;
432
{
433
    int rchallenge_len;
434
    u_char *rchallenge;
435
    int secret_len;
436
    char secret[MAXSECRETLEN];
437
    char rhostname[256];
438
    MD5_CTX mdContext;
439
    u_char hash[MD5_SIGNATURE_SIZE];
440
 
441
    CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: Rcvd id %d.", id));
442
    if (cstate->clientstate == CHAPCS_CLOSED ||
443
        cstate->clientstate == CHAPCS_PENDING) {
444
        CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: in state %d",
445
                   cstate->clientstate));
446
        return;
447
    }
448
 
449
    if (len < 2) {
450
        CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: rcvd short packet."));
451
        return;
452
    }
453
 
454
    GETCHAR(rchallenge_len, inp);
455
    len -= sizeof (u_char) + rchallenge_len;    /* now name field length */
456
    if (len < 0) {
457
        CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: rcvd short packet."));
458
        return;
459
    }
460
    rchallenge = inp;
461
    INCPTR(rchallenge_len, inp);
462
 
463
    if (len >= sizeof(rhostname))
464
        len = sizeof(rhostname) - 1;
465
    BCOPY(inp, rhostname, len);
466
    rhostname[len] = '\000';
467
 
468
    CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: received name field '%s'",
469
               rhostname));
470
 
471
    /* Microsoft doesn't send their name back in the PPP packet */
472
    if (remote_name[0] != 0 && (explicit_remote || rhostname[0] == 0)) {
473
        strncpy(rhostname, remote_name, sizeof(rhostname));
474
        rhostname[sizeof(rhostname) - 1] = 0;
475
        CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: using '%s' as remote name",
476
                   rhostname));
477
    }
478
 
479
    /* get secret for authenticating ourselves with the specified host */
480
    if (!get_secret(cstate->unit, cstate->resp_name, rhostname,
481
                    secret, &secret_len, 0)) {
482
        secret_len = 0;          /* assume null secret if can't find one */
483
        syslog(LOG_WARNING, "No CHAP secret found for authenticating us to %s",
484
               rhostname);
485
    }
486
 
487
    /* cancel response send timeout if necessary */
488
    if (cstate->clientstate == CHAPCS_RESPONSE)
489
        UNTIMEOUT(ChapResponseTimeout, cstate);
490
 
491
    cstate->resp_id = id;
492
    cstate->resp_transmits = 0;
493
 
494
    /*  generate MD based on negotiated type */
495
    switch (cstate->resp_type) {
496
 
497
    case CHAP_DIGEST_MD5:
498
        MD5Init(&mdContext);
499
        MD5Update(&mdContext, &cstate->resp_id, 1);
500
        MD5Update(&mdContext, (u_char *)secret, secret_len);
501
        MD5Update(&mdContext, rchallenge, rchallenge_len);
502
        MD5Final(hash, &mdContext);
503
        BCOPY(hash, cstate->response, MD5_SIGNATURE_SIZE);
504
        cstate->resp_length = MD5_SIGNATURE_SIZE;
505
        break;
506
 
507
#ifdef CHAPMS
508
    case CHAP_MICROSOFT:
509
        ChapMS(cstate, rchallenge, rchallenge_len, secret, secret_len);
510
        break;
511
#endif
512
 
513
    default:
514
        CHAPDEBUG((LOG_INFO, "unknown digest type %d", cstate->resp_type));
515
        return;
516
    }
517
 
518
    BZERO(secret, sizeof(secret));
519
    ChapSendResponse(cstate);
520
}
521
 
522
 
523
/*
524
 * ChapReceiveResponse - Receive and process response.
525
 */
526
static void
527
ChapReceiveResponse(cstate, inp, id, len)
528
    chap_state *cstate;
529
    u_char *inp;
530
    int id;
531
    int len;
532
{
533
    u_char *remmd, remmd_len;
534
    int secret_len, old_state;
535
    int code;
536
    char rhostname[256];
537
    MD5_CTX mdContext;
538
    char secret[MAXSECRETLEN];
539
    u_char hash[MD5_SIGNATURE_SIZE];
540
 
541
    CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: Rcvd id %d.", id));
542
 
543
    if (cstate->serverstate == CHAPSS_CLOSED ||
544
        cstate->serverstate == CHAPSS_PENDING) {
545
        CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: in state %d",
546
                   cstate->serverstate));
547
        return;
548
    }
549
 
550
    if (id != cstate->chal_id)
551
        return;                 /* doesn't match ID of last challenge */
552
 
553
    /*
554
     * If we have received a duplicate or bogus Response,
555
     * we have to send the same answer (Success/Failure)
556
     * as we did for the first Response we saw.
557
     */
558
    if (cstate->serverstate == CHAPSS_OPEN) {
559
        ChapSendStatus(cstate, CHAP_SUCCESS);
560
        return;
561
    }
562
    if (cstate->serverstate == CHAPSS_BADAUTH) {
563
        ChapSendStatus(cstate, CHAP_FAILURE);
564
        return;
565
    }
566
 
567
    if (len < 2) {
568
        CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: rcvd short packet."));
569
        return;
570
    }
571
    GETCHAR(remmd_len, inp);            /* get length of MD */
572
    remmd = inp;                        /* get pointer to MD */
573
    INCPTR(remmd_len, inp);
574
 
575
    len -= sizeof (u_char) + remmd_len;
576
    if (len < 0) {
577
        CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: rcvd short packet."));
578
        return;
579
    }
580
 
581
    UNTIMEOUT(ChapChallengeTimeout, cstate);
582
 
583
    if (len >= sizeof(rhostname))
584
        len = sizeof(rhostname) - 1;
585
    BCOPY(inp, rhostname, len);
586
    rhostname[len] = '\000';
587
 
588
    CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: received name field: %s",
589
               rhostname));
590
 
591
    /*
592
     * Get secret for authenticating them with us,
593
     * do the hash ourselves, and compare the result.
594
     */
595
    code = CHAP_FAILURE;
596
    if (!get_secret(cstate->unit, rhostname, cstate->chal_name,
597
                   secret, &secret_len, 1)) {
598
        syslog(LOG_WARNING, "No CHAP secret found for authenticating %s",
599
               rhostname);
600
    } else {
601
 
602
        /*  generate MD based on negotiated type */
603
        switch (cstate->chal_type) {
604
 
605
        case CHAP_DIGEST_MD5:           /* only MD5 is defined for now */
606
            if (remmd_len != MD5_SIGNATURE_SIZE)
607
                break;                  /* it's not even the right length */
608
            MD5Init(&mdContext);
609
            MD5Update(&mdContext, &cstate->chal_id, 1);
610
            MD5Update(&mdContext, (u_char *)secret, secret_len);
611
            MD5Update(&mdContext, cstate->challenge, cstate->chal_len);
612
            MD5Final(hash, &mdContext);
613
 
614
            /* compare local and remote MDs and send the appropriate status */
615
            if (memcmp (hash, remmd, MD5_SIGNATURE_SIZE) == 0)
616
                code = CHAP_SUCCESS;    /* they are the same! */
617
            break;
618
 
619
        default:
620
            CHAPDEBUG((LOG_INFO, "unknown digest type %d", cstate->chal_type));
621
        }
622
    }
623
 
624
    BZERO(secret, sizeof(secret));
625
    ChapSendStatus(cstate, code);
626
 
627
    if (code == CHAP_SUCCESS) {
628
        old_state = cstate->serverstate;
629
        cstate->serverstate = CHAPSS_OPEN;
630
        if (old_state == CHAPSS_INITIAL_CHAL) {
631
            auth_peer_success(cstate->unit, PPP_CHAP, rhostname, len);
632
        }
633
        if (cstate->chal_interval != 0)
634
            TIMEOUT(ChapRechallenge, cstate, cstate->chal_interval);
635
        syslog(LOG_NOTICE, "CHAP peer authentication succeeded for %s",
636
               rhostname);
637
 
638
    } else {
639
        syslog(LOG_ERR, "CHAP peer authentication failed for remote host %s",
640
               rhostname);
641
        cstate->serverstate = CHAPSS_BADAUTH;
642
        auth_peer_fail(cstate->unit, PPP_CHAP);
643
    }
644
}
645
 
646
/*
647
 * ChapReceiveSuccess - Receive Success
648
 */
649
static void
650
ChapReceiveSuccess(cstate, inp, id, len)
651
    chap_state *cstate;
652
    u_char *inp;
653
    u_char id;
654
    int len;
655
{
656
 
657
    CHAPDEBUG((LOG_INFO, "ChapReceiveSuccess: Rcvd id %d.", id));
658
 
659
    if (cstate->clientstate == CHAPCS_OPEN)
660
        /* presumably an answer to a duplicate response */
661
        return;
662
 
663
    if (cstate->clientstate != CHAPCS_RESPONSE) {
664
        /* don't know what this is */
665
        CHAPDEBUG((LOG_INFO, "ChapReceiveSuccess: 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
    cstate->clientstate = CHAPCS_OPEN;
679
 
680
    auth_withpeer_success(cstate->unit, PPP_CHAP);
681
}
682
 
683
 
684
/*
685
 * ChapReceiveFailure - Receive failure.
686
 */
687
static void
688
ChapReceiveFailure(cstate, inp, id, len)
689
    chap_state *cstate;
690
    u_char *inp;
691
    u_char id;
692
    int len;
693
{
694
    CHAPDEBUG((LOG_INFO, "ChapReceiveFailure: Rcvd id %d.", id));
695
 
696
    if (cstate->clientstate != CHAPCS_RESPONSE) {
697
        /* don't know what this is */
698
        CHAPDEBUG((LOG_INFO, "ChapReceiveFailure: in state %d\n",
699
                   cstate->clientstate));
700
        return;
701
    }
702
 
703
    UNTIMEOUT(ChapResponseTimeout, cstate);
704
 
705
    /*
706
     * Print message.
707
     */
708
    if (len > 0)
709
        PRINTMSG(inp, len);
710
 
711
    syslog(LOG_ERR, "CHAP authentication failed");
712
    auth_withpeer_fail(cstate->unit, PPP_CHAP);
713
}
714
 
715
 
716
/*
717
 * ChapSendChallenge - Send an Authenticate challenge.
718
 */
719
static void
720
ChapSendChallenge(cstate)
721
    chap_state *cstate;
722
{
723
    u_char *outp;
724
    int chal_len, name_len;
725
    int outlen;
726
 
727
    chal_len = cstate->chal_len;
728
    name_len = strlen(cstate->chal_name);
729
    outlen = CHAP_HEADERLEN + sizeof (u_char) + chal_len + name_len;
730
    outp = outpacket_buf;
731
 
732
    MAKEHEADER(outp, PPP_CHAP);         /* paste in a CHAP header */
733
 
734
    PUTCHAR(CHAP_CHALLENGE, outp);
735
    PUTCHAR(cstate->chal_id, outp);
736
    PUTSHORT(outlen, outp);
737
 
738
    PUTCHAR(chal_len, outp);            /* put length of challenge */
739
    BCOPY(cstate->challenge, outp, chal_len);
740
    INCPTR(chal_len, outp);
741
 
742
    BCOPY(cstate->chal_name, outp, name_len);   /* append hostname */
743
 
744
    output(cstate->unit, outpacket_buf, outlen + PPP_HDRLEN);
745
 
746
    CHAPDEBUG((LOG_INFO, "ChapSendChallenge: Sent id %d.", cstate->chal_id));
747
 
748
    TIMEOUT(ChapChallengeTimeout, cstate, cstate->timeouttime);
749
    ++cstate->chal_transmits;
750
}
751
 
752
 
753
/*
754
 * ChapSendStatus - Send a status response (ack or nak).
755
 */
756
static void
757
ChapSendStatus(cstate, code)
758
    chap_state *cstate;
759
    int code;
760
{
761
    u_char *outp;
762
    int outlen, msglen;
763
    char msg[256];
764
 
765
    if (code == CHAP_SUCCESS)
766
        sprintf(msg, "Welcome to %s.", cyg_ppp_hostname);
767
    else
768
        sprintf(msg, "I don't like you.  Go 'way.");
769
    msglen = strlen(msg);
770
 
771
    outlen = CHAP_HEADERLEN + msglen;
772
    outp = outpacket_buf;
773
 
774
    MAKEHEADER(outp, PPP_CHAP); /* paste in a header */
775
 
776
    PUTCHAR(code, outp);
777
    PUTCHAR(cstate->chal_id, outp);
778
    PUTSHORT(outlen, outp);
779
    BCOPY(msg, outp, msglen);
780
    output(cstate->unit, outpacket_buf, outlen + PPP_HDRLEN);
781
 
782
    CHAPDEBUG((LOG_INFO, "ChapSendStatus: Sent code %d, id %d.", code,
783
               cstate->chal_id));
784
}
785
 
786
/*
787
 * ChapGenChallenge is used to generate a pseudo-random challenge string of
788
 * a pseudo-random length between min_len and max_len.  The challenge
789
 * string and its length are stored in *cstate, and various other fields of
790
 * *cstate are initialized.
791
 */
792
 
793
static void
794
ChapGenChallenge(cstate)
795
    chap_state *cstate;
796
{
797
    int chal_len;
798
    u_char *ptr = cstate->challenge;
799
    unsigned int i;
800
 
801
    /* pick a random challenge length between MIN_CHALLENGE_LENGTH and
802
       MAX_CHALLENGE_LENGTH */
803
    chal_len =  (unsigned) ((drand48() *
804
                             (MAX_CHALLENGE_LENGTH - MIN_CHALLENGE_LENGTH)) +
805
                            MIN_CHALLENGE_LENGTH);
806
    cstate->chal_len = chal_len;
807
    cstate->chal_id = ++cstate->id;
808
    cstate->chal_transmits = 0;
809
 
810
    /* generate a random string */
811
    for (i = 0; i < chal_len; i++ )
812
        *ptr++ = (char) (drand48() * 0xff);
813
}
814
 
815
/*
816
 * ChapSendResponse - send a response packet with values as specified
817
 * in *cstate.
818
 */
819
/* ARGSUSED */
820
static void
821
ChapSendResponse(cstate)
822
    chap_state *cstate;
823
{
824
    u_char *outp;
825
    int outlen, md_len, name_len;
826
 
827
    md_len = cstate->resp_length;
828
    name_len = strlen(cstate->resp_name);
829
    outlen = CHAP_HEADERLEN + sizeof (u_char) + md_len + name_len;
830
    outp = outpacket_buf;
831
 
832
    MAKEHEADER(outp, PPP_CHAP);
833
 
834
    PUTCHAR(CHAP_RESPONSE, outp);       /* we are a response */
835
    PUTCHAR(cstate->resp_id, outp);     /* copy id from challenge packet */
836
    PUTSHORT(outlen, outp);             /* packet length */
837
 
838
    PUTCHAR(md_len, outp);              /* length of MD */
839
    BCOPY(cstate->response, outp, md_len);      /* copy MD to buffer */
840
    INCPTR(md_len, outp);
841
 
842
    BCOPY(cstate->resp_name, outp, name_len); /* append our name */
843
 
844
    /* send the packet */
845
    output(cstate->unit, outpacket_buf, outlen + PPP_HDRLEN);
846
 
847
    cstate->clientstate = CHAPCS_RESPONSE;
848
    TIMEOUT(ChapResponseTimeout, cstate, cstate->timeouttime);
849
    ++cstate->resp_transmits;
850
}
851
 
852
/*
853
 * ChapPrintPkt - print the contents of a CHAP packet.
854
 */
855
static char *ChapCodenames[] = {
856
    "Challenge", "Response", "Success", "Failure"
857
};
858
 
859
static int
860
ChapPrintPkt(p, plen, printer, arg)
861
    u_char *p;
862
    int plen;
863
    void (*printer) __P((void *, char *, ...));
864
    void *arg;
865
{
866
    int code, id, len;
867
    int clen, nlen;
868
    u_char x;
869
 
870
    if (plen < CHAP_HEADERLEN)
871
        return 0;
872
    GETCHAR(code, p);
873
    GETCHAR(id, p);
874
    GETSHORT(len, p);
875
    if (len < CHAP_HEADERLEN || len > plen)
876
        return 0;
877
 
878
    if (code >= 1 && code <= sizeof(ChapCodenames) / sizeof(char *))
879
        printer(arg, " %s", ChapCodenames[code-1]);
880
    else
881
        printer(arg, " code=0x%x", code);
882
    printer(arg, " id=0x%x", id);
883
    len -= CHAP_HEADERLEN;
884
    switch (code) {
885
    case CHAP_CHALLENGE:
886
    case CHAP_RESPONSE:
887
        if (len < 1)
888
            break;
889
        clen = p[0];
890
        if (len < clen + 1)
891
            break;
892
        ++p;
893
        nlen = len - clen - 1;
894
        printer(arg, " <");
895
        for (; clen > 0; --clen) {
896
            GETCHAR(x, p);
897
            printer(arg, "%.2x", x);
898
        }
899
        printer(arg, ">, name = ");
900
        print_string(p, nlen, printer, arg);
901
        break;
902
    case CHAP_FAILURE:
903
    case CHAP_SUCCESS:
904
        printer(arg, " ");
905
        print_string(p, len, printer, arg);
906
        break;
907
    default:
908
        for (clen = len; clen > 0; --clen) {
909
            GETCHAR(x, p);
910
            printer(arg, " %.2x", x);
911
        }
912
    }
913
 
914
    return len + CHAP_HEADERLEN;
915
}

powered by: WebSVN 2.1.0

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