source: rtems-libbsd/rtemsbsd/pppd/upap.c @ f0aaa04

55-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since f0aaa04 was 70fa95a, checked in by Sebastian Huber <sebastian.huber@…>, on 09/30/14 at 12:46:12

ppp: Import from RTEMS sources

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