source: rtems/cpukit/pppd/upap.c @ b5d91ad

4.104.114.84.95
Last change on this file since b5d91ad was a5d65440, checked in by Joel Sherrill <joel.sherrill@…>, on 07/25/02 at 13:54:40

2002-07-25 Ralf Corsepius <corsepiu@…>

  • pppd/chap.c, pppd/fsm.c, pppd/fsm.h, pppd/upap.c: Per PR255 fix prototype mismatches.
  • Property mode set to 100644
File size: 13.6 KB
Line 
1/*
2 * upap.c - User/Password Authentication Protocol.
3 *
4 * Copyright (c) 1989 Carnegie Mellon University.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms are permitted
8 * provided that the above copyright notice and this paragraph are
9 * duplicated in all such forms and that any documentation,
10 * advertising materials, and other materials related to such
11 * distribution and use acknowledge that the software was developed
12 * by Carnegie Mellon University.  The name of the
13 * University may not be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18 */
19
20#define RCSID   "$Id$"
21
22/*
23 * TODO:
24 */
25
26#include <stdio.h>
27#include <string.h>
28
29#include "pppd.h"
30#include "upap.h"
31
32static const char rcsid[] = RCSID;
33
34static bool hide_password = 1;
35
36/*
37 * Command-line options.
38 */
39static option_t pap_option_list[] = {
40    { "hide-password", o_bool, &hide_password,
41      "Don't output passwords to log", 1 },
42    { "show-password", o_bool, &hide_password,
43      "Show password string in debug log messages", 0 },
44    { "pap-restart", o_int, &upap[0].us_timeouttime,
45      "Set retransmit timeout for PAP" },
46    { "pap-max-authreq", o_int, &upap[0].us_maxtransmits,
47      "Set max number of transmissions for auth-reqs" },
48    { "pap-timeout", o_int, &upap[0].us_reqtimeout,
49      "Set time limit for peer PAP authentication" },
50    { NULL }
51};
52
53/*
54 * Protocol entry points.
55 */
56static void upap_init __P((int));
57static void upap_lowerup __P((int));
58static void upap_lowerdown __P((int));
59static void upap_input __P((int, u_char *, int));
60static void upap_protrej __P((int));
61static int  upap_printpkt __P((u_char *, int,
62                               void (*) __P((void *, char *, ...)), void *));
63
64struct protent pap_protent = {
65    PPP_PAP,
66    upap_init,
67    upap_input,
68    upap_protrej,
69    upap_lowerup,
70    upap_lowerdown,
71    NULL,
72    NULL,
73    upap_printpkt,
74    NULL,
75    1,
76    "PAP",
77    NULL,
78    pap_option_list,
79    NULL,
80    NULL,
81    NULL
82};
83
84upap_state upap[NUM_PPP];               /* UPAP state; one for each unit */
85
86static void upap_timeout __P((void *));
87static void upap_reqtimeout __P((void *));
88static void upap_rauthreq __P((upap_state *, u_char *, int, int));
89static void upap_rauthack __P((upap_state *, u_char *, int, int));
90static void upap_rauthnak __P((upap_state *, u_char *, int, int));
91static void upap_sauthreq __P((upap_state *));
92static void upap_sresp __P((upap_state *, u_char, u_char, char *, int));
93
94
95/*
96 * upap_init - Initialize a UPAP unit.
97 */
98static void
99upap_init(unit)
100    int unit;
101{
102    upap_state *u = &upap[unit];
103
104    u->us_unit = unit;
105    u->us_user = NULL;
106    u->us_userlen = 0;
107    u->us_passwd = NULL;
108    u->us_passwdlen = 0;
109    u->us_clientstate = UPAPCS_INITIAL;
110    u->us_serverstate = UPAPSS_INITIAL;
111    u->us_id = 0;
112    u->us_timeouttime = UPAP_DEFTIMEOUT;
113    u->us_maxtransmits = 10;
114    u->us_reqtimeout = UPAP_DEFREQTIME;
115}
116
117
118/*
119 * upap_authwithpeer - Authenticate us with our peer (start client).
120 *
121 * Set new state and send authenticate's.
122 */
123void
124upap_authwithpeer(unit, user, password)
125    int unit;
126    char *user, *password;
127{
128    upap_state *u = &upap[unit];
129
130    /* Save the username and password we're given */
131    u->us_user = user;
132    u->us_userlen = strlen(user);
133    u->us_passwd = password;
134    u->us_passwdlen = strlen(password);
135    u->us_transmits = 0;
136
137    /* Lower layer up yet? */
138    if (u->us_clientstate == UPAPCS_INITIAL ||
139        u->us_clientstate == UPAPCS_PENDING) {
140        u->us_clientstate = UPAPCS_PENDING;
141        return;
142    }
143
144    upap_sauthreq(u);                   /* Start protocol */
145}
146
147
148/*
149 * upap_authpeer - Authenticate our peer (start server).
150 *
151 * Set new state.
152 */
153void
154upap_authpeer(unit)
155    int unit;
156{
157    upap_state *u = &upap[unit];
158
159    /* Lower layer up yet? */
160    if (u->us_serverstate == UPAPSS_INITIAL ||
161        u->us_serverstate == UPAPSS_PENDING) {
162        u->us_serverstate = UPAPSS_PENDING;
163        return;
164    }
165
166    u->us_serverstate = UPAPSS_LISTEN;
167    if (u->us_reqtimeout > 0)
168        TIMEOUT(upap_reqtimeout, u, u->us_reqtimeout);
169}
170
171
172/*
173 * upap_timeout - Retransmission timer for sending auth-reqs expired.
174 */
175static void
176upap_timeout(arg)
177    void *arg;
178{
179    upap_state *u = (upap_state *) arg;
180
181    if (u->us_clientstate != UPAPCS_AUTHREQ)
182        return;
183
184    if (u->us_transmits >= u->us_maxtransmits) {
185        /* give up in disgust */
186        error("No response to PAP authenticate-requests");
187        u->us_clientstate = UPAPCS_BADAUTH;
188        auth_withpeer_fail(u->us_unit, PPP_PAP);
189        return;
190    }
191
192    upap_sauthreq(u);           /* Send Authenticate-Request */
193}
194
195
196/*
197 * upap_reqtimeout - Give up waiting for the peer to send an auth-req.
198 */
199static void
200upap_reqtimeout(arg)
201    void *arg;
202{
203    upap_state *u = (upap_state *) arg;
204
205    if (u->us_serverstate != UPAPSS_LISTEN)
206        return;                 /* huh?? */
207
208    auth_peer_fail(u->us_unit, PPP_PAP);
209    u->us_serverstate = UPAPSS_BADAUTH;
210}
211
212
213/*
214 * upap_lowerup - The lower layer is up.
215 *
216 * Start authenticating if pending.
217 */
218static void
219upap_lowerup(unit)
220    int unit;
221{
222    upap_state *u = &upap[unit];
223
224    if (u->us_clientstate == UPAPCS_INITIAL)
225        u->us_clientstate = UPAPCS_CLOSED;
226    else if (u->us_clientstate == UPAPCS_PENDING) {
227        upap_sauthreq(u);       /* send an auth-request */
228    }
229
230    if (u->us_serverstate == UPAPSS_INITIAL)
231        u->us_serverstate = UPAPSS_CLOSED;
232    else if (u->us_serverstate == UPAPSS_PENDING) {
233        u->us_serverstate = UPAPSS_LISTEN;
234        if (u->us_reqtimeout > 0)
235            TIMEOUT(upap_reqtimeout, u, u->us_reqtimeout);
236    }
237}
238
239
240/*
241 * upap_lowerdown - The lower layer is down.
242 *
243 * Cancel all timeouts.
244 */
245static void
246upap_lowerdown(unit)
247    int unit;
248{
249    upap_state *u = &upap[unit];
250
251    if (u->us_clientstate == UPAPCS_AUTHREQ)    /* Timeout pending? */
252        UNTIMEOUT(upap_timeout, u);             /* Cancel timeout */
253    if (u->us_serverstate == UPAPSS_LISTEN && u->us_reqtimeout > 0)
254        UNTIMEOUT(upap_reqtimeout, u);
255
256    u->us_clientstate = UPAPCS_INITIAL;
257    u->us_serverstate = UPAPSS_INITIAL;
258}
259
260
261/*
262 * upap_protrej - Peer doesn't speak this protocol.
263 *
264 * This shouldn't happen.  In any case, pretend lower layer went down.
265 */
266static void
267upap_protrej(unit)
268    int unit;
269{
270    upap_state *u = &upap[unit];
271
272    if (u->us_clientstate == UPAPCS_AUTHREQ) {
273        error("PAP authentication failed due to protocol-reject");
274        auth_withpeer_fail(unit, PPP_PAP);
275    }
276    if (u->us_serverstate == UPAPSS_LISTEN) {
277        error("PAP authentication of peer failed (protocol-reject)");
278        auth_peer_fail(unit, PPP_PAP);
279    }
280    upap_lowerdown(unit);
281}
282
283
284/*
285 * upap_input - Input UPAP packet.
286 */
287static void
288upap_input(unit, inpacket, l)
289    int unit;
290    u_char *inpacket;
291    int l;
292{
293    upap_state *u = &upap[unit];
294    u_char *inp;
295    u_char code, id;
296    int len;
297
298    /*
299     * Parse header (code, id and length).
300     * If packet too short, drop it.
301     */
302    inp = inpacket;
303    if (l < UPAP_HEADERLEN) {
304        UPAPDEBUG(("pap_input: rcvd short header."));
305        return;
306    }
307    GETCHAR(code, inp);
308    GETCHAR(id, inp);
309    GETSHORT(len, inp);
310    if (len < UPAP_HEADERLEN) {
311        UPAPDEBUG(("pap_input: rcvd illegal length."));
312        return;
313    }
314    if (len > l) {
315        UPAPDEBUG(("pap_input: rcvd short packet."));
316        return;
317    }
318    len -= UPAP_HEADERLEN;
319
320    /*
321     * Action depends on code.
322     */
323    switch (code) {
324    case UPAP_AUTHREQ:
325        upap_rauthreq(u, inp, id, len);
326        break;
327
328    case UPAP_AUTHACK:
329        upap_rauthack(u, inp, id, len);
330        break;
331
332    case UPAP_AUTHNAK:
333        upap_rauthnak(u, inp, id, len);
334        break;
335
336    default:                            /* XXX Need code reject */
337        break;
338    }
339}
340
341
342/*
343 * upap_rauth - Receive Authenticate.
344 */
345static void
346upap_rauthreq(u, inp, id, len)
347    upap_state *u;
348    u_char *inp;
349    int id;
350    int len;
351{
352    u_char ruserlen, rpasswdlen;
353    char *ruser, *rpasswd;
354    int retcode;
355    char *msg;
356    int msglen;
357
358    if (u->us_serverstate < UPAPSS_LISTEN)
359        return;
360
361    /*
362     * If we receive a duplicate authenticate-request, we are
363     * supposed to return the same status as for the first request.
364     */
365    if (u->us_serverstate == UPAPSS_OPEN) {
366        upap_sresp(u, UPAP_AUTHACK, id, "", 0); /* return auth-ack */
367        return;
368    }
369    if (u->us_serverstate == UPAPSS_BADAUTH) {
370        upap_sresp(u, UPAP_AUTHNAK, id, "", 0); /* return auth-nak */
371        return;
372    }
373
374    /*
375     * Parse user/passwd.
376     */
377    if (len < 1) {
378        UPAPDEBUG(("pap_rauth: rcvd short packet."));
379        return;
380    }
381    GETCHAR(ruserlen, inp);
382    len -= sizeof (u_char) + ruserlen + sizeof (u_char);
383    if (len < 0) {
384        UPAPDEBUG(("pap_rauth: rcvd short packet."));
385        return;
386    }
387    ruser = (char *) inp;
388    INCPTR(ruserlen, inp);
389    GETCHAR(rpasswdlen, inp);
390    if (len < rpasswdlen) {
391        UPAPDEBUG(("pap_rauth: rcvd short packet."));
392        return;
393    }
394    rpasswd = (char *) inp;
395
396    /*
397     * Check the username and password given.
398     */
399    retcode = check_passwd(u->us_unit, ruser, ruserlen, rpasswd,
400                           rpasswdlen, &msg);
401    BZERO(rpasswd, rpasswdlen);
402    msglen = strlen(msg);
403    if (msglen > 255)
404        msglen = 255;
405
406    upap_sresp(u, retcode, id, msg, msglen);
407
408    if (retcode == UPAP_AUTHACK) {
409        u->us_serverstate = UPAPSS_OPEN;
410        auth_peer_success(u->us_unit, PPP_PAP, ruser, ruserlen);
411    } else {
412        u->us_serverstate = UPAPSS_BADAUTH;
413        auth_peer_fail(u->us_unit, PPP_PAP);
414    }
415
416    if (u->us_reqtimeout > 0)
417        UNTIMEOUT(upap_reqtimeout, u);
418}
419
420
421/*
422 * upap_rauthack - Receive Authenticate-Ack.
423 */
424static void
425upap_rauthack(u, inp, id, len)
426    upap_state *u;
427    u_char *inp;
428    int id;
429    int len;
430{
431    u_char msglen;
432    char *msg;
433
434    if (u->us_clientstate != UPAPCS_AUTHREQ) /* XXX */
435        return;
436
437    /*
438     * Parse message.
439     */
440    if (len < 1) {
441        UPAPDEBUG(("pap_rauthack: ignoring missing msg-length."));
442    } else {
443        GETCHAR(msglen, inp);
444        if (msglen > 0) {
445            len -= sizeof (u_char);
446            if (len < msglen) {
447                UPAPDEBUG(("pap_rauthack: rcvd short packet."));
448                return;
449            }
450            msg = (char *) inp;
451            PRINTMSG(msg, msglen);
452        }
453    }
454
455    u->us_clientstate = UPAPCS_OPEN;
456
457    auth_withpeer_success(u->us_unit, PPP_PAP);
458}
459
460
461/*
462 * upap_rauthnak - Receive Authenticate-Nakk.
463 */
464static void
465upap_rauthnak(u, inp, id, len)
466    upap_state *u;
467    u_char *inp;
468    int id;
469    int len;
470{
471    u_char msglen;
472    char *msg;
473
474    if (u->us_clientstate != UPAPCS_AUTHREQ) /* XXX */
475        return;
476
477    /*
478     * Parse message.
479     */
480    if (len < 1) {
481        UPAPDEBUG(("pap_rauthnak: ignoring missing msg-length."));
482    } else {
483        GETCHAR(msglen, inp);
484        if (msglen > 0) {
485            len -= sizeof (u_char);
486            if (len < msglen) {
487                UPAPDEBUG(("pap_rauthnak: rcvd short packet."));
488                return;
489            }
490            msg = (char *) inp;
491            PRINTMSG(msg, msglen);
492        }
493    }
494
495    u->us_clientstate = UPAPCS_BADAUTH;
496
497    error("PAP authentication failed");
498    auth_withpeer_fail(u->us_unit, PPP_PAP);
499}
500
501
502/*
503 * upap_sauthreq - Send an Authenticate-Request.
504 */
505static void
506upap_sauthreq(u)
507    upap_state *u;
508{
509    u_char *outp;
510    int outlen;
511
512    outlen = UPAP_HEADERLEN + 2 * sizeof (u_char) +
513        u->us_userlen + u->us_passwdlen;
514    outp = outpacket_buf;
515   
516    MAKEHEADER(outp, PPP_PAP);
517
518    PUTCHAR(UPAP_AUTHREQ, outp);
519    PUTCHAR(++u->us_id, outp);
520    PUTSHORT(outlen, outp);
521    PUTCHAR(u->us_userlen, outp);
522    BCOPY(u->us_user, outp, u->us_userlen);
523    INCPTR(u->us_userlen, outp);
524    PUTCHAR(u->us_passwdlen, outp);
525    BCOPY(u->us_passwd, outp, u->us_passwdlen);
526
527    output(u->us_unit, outpacket_buf, outlen + PPP_HDRLEN);
528
529    TIMEOUT(upap_timeout, u, u->us_timeouttime);
530    ++u->us_transmits;
531    u->us_clientstate = UPAPCS_AUTHREQ;
532}
533
534
535/*
536 * upap_sresp - Send a response (ack or nak).
537 */
538static void
539upap_sresp(u, code, id, msg, msglen)
540    upap_state *u;
541    u_char code, id;
542    char *msg;
543    int msglen;
544{
545    u_char *outp;
546    int outlen;
547
548    outlen = UPAP_HEADERLEN + sizeof (u_char) + msglen;
549    outp = outpacket_buf;
550    MAKEHEADER(outp, PPP_PAP);
551
552    PUTCHAR(code, outp);
553    PUTCHAR(id, outp);
554    PUTSHORT(outlen, outp);
555    PUTCHAR(msglen, outp);
556    BCOPY(msg, outp, msglen);
557    output(u->us_unit, outpacket_buf, outlen + PPP_HDRLEN);
558}
559
560/*
561 * upap_printpkt - print the contents of a PAP packet.
562 */
563static char *upap_codenames[] = {
564    "AuthReq", "AuthAck", "AuthNak"
565};
566
567static int
568upap_printpkt(p, plen, printer, arg)
569    u_char *p;
570    int plen;
571    void (*printer) __P((void *, char *, ...));
572    void *arg;
573{
574    int code, id, len;
575    int mlen, ulen, wlen;
576    char *user, *pwd, *msg;
577    u_char *pstart;
578
579    if (plen < UPAP_HEADERLEN)
580        return 0;
581    pstart = p;
582    GETCHAR(code, p);
583    GETCHAR(id, p);
584    GETSHORT(len, p);
585    if (len < UPAP_HEADERLEN || len > plen)
586        return 0;
587
588    if (code >= 1 && code <= sizeof(upap_codenames) / sizeof(char *))
589        printer(arg, " %s", upap_codenames[code-1]);
590    else
591        printer(arg, " code=0x%x", code);
592    printer(arg, " id=0x%x", id);
593    len -= UPAP_HEADERLEN;
594    switch (code) {
595    case UPAP_AUTHREQ:
596        if (len < 1)
597            break;
598        ulen = p[0];
599        if (len < ulen + 2)
600            break;
601        wlen = p[ulen + 1];
602        if (len < ulen + wlen + 2)
603            break;
604        user = (char *) (p + 1);
605        pwd = (char *) (p + ulen + 2);
606        p += ulen + wlen + 2;
607        len -= ulen + wlen + 2;
608        printer(arg, " user=");
609        print_string(user, ulen, printer, arg);
610        printer(arg, " password=");
611        if (!hide_password)
612            print_string(pwd, wlen, printer, arg);
613        else
614            printer(arg, "<hidden>");
615        break;
616    case UPAP_AUTHACK:
617    case UPAP_AUTHNAK:
618        if (len < 1)
619            break;
620        mlen = p[0];
621        if (len < mlen + 1)
622            break;
623        msg = (char *) (p + 1);
624        p += mlen + 1;
625        len -= mlen + 1;
626        printer(arg, " ");
627        print_string(msg, mlen, printer, arg);
628        break;
629    }
630
631    /* print the rest of the bytes in the packet */
632    for (; len > 0; --len) {
633        GETCHAR(code, p);
634        printer(arg, " %.2x", code);
635    }
636
637    return p - pstart;
638}
Note: See TracBrowser for help on using the repository browser.