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

5
Last change on this file since a2a71b5 was 33a1a4db, checked in by Peng Fan <van.freenix@…>, on 04/05/16 at 12:45:55

cpukit: pppd: fix compile warning

rcsid is defined, but not used. So discard it.

Signed-off-by: Peng Fan <van.freenix@…>

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