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