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