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