8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / cmd-inet / usr.bin / pppd / upap.c
blobb9263af55b0e146a499fb921624d46942aedd083
1 /*
2 * upap.c - User/Password Authentication Protocol.
4 * Copyright (c) 2000 by Sun Microsystems, Inc.
5 * All rights reserved.
7 * Permission to use, copy, modify, and distribute this software and its
8 * documentation is hereby granted, provided that the above copyright
9 * notice appears in all copies.
11 * SUN MAKES NO REPRESENTATION OR WARRANTIES ABOUT THE SUITABILITY OF
12 * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
13 * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
14 * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
15 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
16 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES
18 * Copyright (c) 1989 Carnegie Mellon University.
19 * All rights reserved.
21 * Redistribution and use in source and binary forms are permitted
22 * provided that the above copyright notice and this paragraph are
23 * duplicated in all such forms and that any documentation,
24 * advertising materials, and other materials related to such
25 * distribution and use acknowledge that the software was developed
26 * by Carnegie Mellon University. The name of the
27 * University may not be used to endorse or promote products derived
28 * from this software without specific prior written permission.
29 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
30 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
31 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
34 #pragma ident "%Z%%M% %I% %E% SMI"
35 #define RCSID "$Id: upap.c,v 1.23 1999/11/20 05:11:47 paulus Exp $"
37 #include <stdio.h>
38 #include <string.h>
40 #include "pppd.h"
41 #include "upap.h"
43 #if !defined(lint) && !defined(_lint)
44 static const char rcsid[] = RCSID;
45 #endif
47 static bool hide_password = 1;
50 * Command-line options.
52 static option_t pap_option_list[] = {
53 { "hide-password", o_bool, &hide_password,
54 "Don't output passwords to log", 1 },
55 { "show-password", o_bool, &hide_password,
56 "Show password string in debug log messages", 0 },
57 { "pap-restart", o_int, &upap[0].us_timeouttime,
58 "Set retransmit timeout for PAP" },
59 { "pap-max-authreq", o_int, &upap[0].us_maxtransmits,
60 "Max number of PAP Authenticate-Request sent" },
61 { "pap-max-receive", o_int, &upap[0].us_maxreceives,
62 "Max allowable PAP Authenticate-Request received" },
63 { "pap-timeout", o_int, &upap[0].us_reqtimeout,
64 "Set time limit for peer PAP authentication" },
65 { NULL }
69 * Protocol entry points.
71 static void upap_init __P((int));
72 static void upap_lowerup __P((int));
73 static void upap_lowerdown __P((int));
74 static void upap_input __P((int, u_char *, int));
75 static void upap_protrej __P((int));
76 static int upap_printpkt __P((u_char *, int,
77 void (*) __P((void *, const char *, ...)), void *));
79 struct protent pap_protent = {
80 PPP_PAP,
81 upap_init,
82 upap_input,
83 upap_protrej,
84 upap_lowerup,
85 upap_lowerdown,
86 NULL,
87 NULL,
88 upap_printpkt,
89 NULL,
91 "PAP",
92 NULL,
93 pap_option_list,
94 NULL,
95 NULL,
96 NULL
99 upap_state upap[NUM_PPP]; /* UPAP state; one for each unit */
101 static void upap_timeout __P((void *));
102 static void upap_reqtimeout __P((void *));
103 static void upap_rauthreq __P((upap_state *, u_char *, int, int));
104 static void upap_rauthack __P((upap_state *, u_char *, int, int));
105 static void upap_rauthnak __P((upap_state *, u_char *, int, int));
106 static void upap_sauthreq __P((upap_state *));
107 static void upap_sresp __P((upap_state *, int, int, char *, int));
109 static const char *
110 pap_cstate(clientstate)
111 int clientstate;
113 static const char *cstate[] = { UPAPCS__NAMES };
114 static char buf[32];
116 if (clientstate < 0 || clientstate >= Dim(cstate)) {
117 (void) slprintf(buf, sizeof (buf), "Cli#%d", clientstate);
118 return ((const char *)buf);
120 return (cstate[clientstate]);
123 static const char *
124 pap_sstate(serverstate)
125 int serverstate;
127 static const char *sstate[] = { UPAPSS__NAMES };
128 static char buf[32];
130 if (serverstate < 0 || serverstate >= Dim(sstate)) {
131 (void) slprintf(buf, sizeof (buf), "Srv#%d", serverstate);
132 return ((const char *)buf);
134 return (sstate[serverstate]);
138 * upap_init - Initialize a UPAP unit.
140 static void
141 upap_init(unit)
142 int unit;
144 upap_state *u = &upap[unit];
146 u->us_unit = unit;
147 u->us_user = NULL;
148 u->us_userlen = 0;
149 u->us_passwd = NULL;
150 u->us_clientstate = UPAPCS_INITIAL;
151 u->us_serverstate = UPAPSS_INITIAL;
152 u->us_id = 0;
153 u->us_timeouttime = UPAP_DEFTIMEOUT;
154 u->us_maxtransmits = 10;
155 u->us_reqtimeout = UPAP_DEFREQTIME;
156 u->us_maxreceives = 3;
157 u->us_msg = "";
158 u->us_msglen = 0;
163 * upap_authwithpeer - Authenticate us with our peer (start client).
165 * Set new state and send authenticate's.
167 void
168 upap_authwithpeer(unit, user, password)
169 int unit;
170 char *user, *password;
172 upap_state *u = &upap[unit];
174 /* Save the username and password we're given */
175 u->us_user = user;
176 u->us_userlen = strlen(user);
177 u->us_passwd = password;
178 u->us_transmits = 0;
180 /* Lower layer up yet? */
181 if (u->us_clientstate == UPAPCS_INITIAL ||
182 u->us_clientstate == UPAPCS_PENDING) {
183 u->us_clientstate = UPAPCS_PENDING;
184 return;
187 upap_sauthreq(u); /* Start protocol */
192 * upap_authpeer - Authenticate our peer (start server).
194 * Set new state.
196 void
197 upap_authpeer(unit)
198 int unit;
200 upap_state *u = &upap[unit];
202 /* Lower layer up yet? */
203 if (u->us_serverstate == UPAPSS_INITIAL ||
204 u->us_serverstate == UPAPSS_PENDING) {
205 u->us_serverstate = UPAPSS_PENDING;
206 return;
209 u->us_serverstate = UPAPSS_LISTEN;
210 u->us_receives = 0;
211 if (u->us_reqtimeout > 0)
212 TIMEOUT(upap_reqtimeout, u, u->us_reqtimeout);
217 * upap_timeout - Retransmission timer for sending auth-reqs expired.
219 static void
220 upap_timeout(arg)
221 void *arg;
223 upap_state *u = (upap_state *) arg;
225 if (u->us_clientstate != UPAPCS_AUTHREQ)
226 return;
228 if (u->us_transmits >= u->us_maxtransmits) {
229 /* give up in disgust */
230 error("No response to %d PAP Authenticate-Requests", u->us_transmits);
231 u->us_clientstate = UPAPCS_BADAUTH;
232 auth_withpeer_fail(u->us_unit, PPP_PAP);
233 return;
236 upap_sauthreq(u); /* Send Authenticate-Request */
241 * upap_reqtimeout - Give up waiting for the peer to send a valid auth-req.
243 static void
244 upap_reqtimeout(arg)
245 void *arg;
247 upap_state *u = (upap_state *) arg;
249 if (u->us_serverstate != UPAPSS_LISTEN)
250 return; /* huh?? */
252 auth_peer_fail(u->us_unit, PPP_PAP);
253 u->us_serverstate = UPAPSS_BADAUTH;
258 * upap_lowerup - The lower layer is up.
260 * Start authenticating if pending.
262 static void
263 upap_lowerup(unit)
264 int unit;
266 upap_state *u = &upap[unit];
268 if (u->us_clientstate == UPAPCS_INITIAL)
269 u->us_clientstate = UPAPCS_CLOSED;
270 else if (u->us_clientstate == UPAPCS_PENDING) {
271 upap_sauthreq(u); /* send an auth-request */
274 if (u->us_serverstate == UPAPSS_INITIAL)
275 u->us_serverstate = UPAPSS_CLOSED;
276 else if (u->us_serverstate == UPAPSS_PENDING) {
277 u->us_serverstate = UPAPSS_LISTEN;
278 if (u->us_reqtimeout > 0)
279 TIMEOUT(upap_reqtimeout, u, u->us_reqtimeout);
285 * upap_lowerdown - The lower layer is down.
287 * Cancel all timeouts.
289 static void
290 upap_lowerdown(unit)
291 int unit;
293 upap_state *u = &upap[unit];
295 /* Cancel timeouts */
296 if (u->us_clientstate == UPAPCS_AUTHREQ && u->us_timeouttime > 0)
297 UNTIMEOUT(upap_timeout, u);
298 if (u->us_serverstate == UPAPSS_LISTEN && u->us_reqtimeout > 0)
299 UNTIMEOUT(upap_reqtimeout, u);
301 u->us_clientstate = UPAPCS_INITIAL;
302 u->us_serverstate = UPAPSS_INITIAL;
307 * upap_protrej - Peer doesn't speak this protocol.
309 * This shouldn't happen. In any case, pretend lower layer went down.
311 static void
312 upap_protrej(unit)
313 int unit;
315 upap_state *u = &upap[unit];
317 if (u->us_clientstate == UPAPCS_AUTHREQ) {
318 error("PAP authentication failed due to protocol-reject");
319 auth_withpeer_fail(unit, PPP_PAP);
321 if (u->us_serverstate == UPAPSS_LISTEN) {
322 error("PAP authentication of peer failed (protocol-reject)");
323 auth_peer_fail(unit, PPP_PAP);
325 upap_lowerdown(unit);
330 * upap_input - Input UPAP packet.
332 static void
333 upap_input(unit, inpacket, l)
334 int unit;
335 u_char *inpacket;
336 int l;
338 upap_state *u = &upap[unit];
339 u_char *inp;
340 u_char code, id;
341 int len;
344 * Parse header (code, id and length).
345 * If packet too short, drop it.
347 inp = inpacket;
348 if (l < UPAP_HEADERLEN) {
349 error("PAP: packet is too small (%d < %d)", l, UPAP_HEADERLEN);
350 return;
352 GETCHAR(code, inp);
353 GETCHAR(id, inp);
354 GETSHORT(len, inp);
355 if ((len < UPAP_HEADERLEN) || (len > l)) {
356 error("PAP: packet has illegal length %d (%d..%d)", len,
357 UPAP_HEADERLEN, l);
358 return;
360 len -= UPAP_HEADERLEN;
363 * Action depends on code.
365 switch (code) {
366 case UPAP_AUTHREQ:
367 upap_rauthreq(u, inp, id, len);
368 break;
370 case UPAP_AUTHACK:
371 upap_rauthack(u, inp, id, len);
372 break;
374 case UPAP_AUTHNAK:
375 upap_rauthnak(u, inp, id, len);
376 break;
378 default:
379 warn("Unknown PAP code (%d) received.", code);
380 break;
386 * upap_rauth - Receive Authenticate.
388 static void
389 upap_rauthreq(u, inp, id, len)
390 upap_state *u;
391 u_char *inp;
392 int id;
393 int len;
395 u_char ruserlen, rpasswdlen;
396 char *ruser, *rpasswd;
397 int retcode;
398 char *msg;
399 int msglen;
401 if (u->us_serverstate < UPAPSS_LISTEN) {
402 info("PAP: discarded Authenticate-Request in state %s",
403 pap_sstate(u->us_serverstate));
404 return;
408 * If we receive a duplicate authenticate-request, we are
409 * supposed to return the same status as for the first request.
411 if (u->us_serverstate == UPAPSS_OPEN) {
412 /* return auth-ack */
413 upap_sresp(u, UPAP_AUTHACK, id, u->us_msg, u->us_msglen);
414 return;
416 if (u->us_serverstate == UPAPSS_BADAUTH) {
417 /* return auth-nak */
418 upap_sresp(u, UPAP_AUTHNAK, id, u->us_msg, u->us_msglen);
419 return;
423 * Parse user/passwd.
425 if (len < 1) {
426 error("PAP: rcvd short packet; no data");
427 return;
429 GETCHAR(ruserlen, inp);
430 len -= sizeof (u_char) + ruserlen + sizeof (u_char);
431 if (len < 0) {
432 error("PAP: rcvd short packet; peer name missing");
433 return;
435 ruser = (char *) inp;
436 INCPTR(ruserlen, inp);
437 GETCHAR(rpasswdlen, inp);
438 if (len < rpasswdlen) {
439 error("PAP: rcvd short packet; pass len %d < %d", len, rpasswdlen);
440 return;
442 rpasswd = (char *) inp;
445 * Check the username and password given.
447 retcode = check_passwd(u->us_unit, ruser, ruserlen, rpasswd,
448 rpasswdlen, &msg);
449 BZERO(rpasswd, rpasswdlen);
450 msglen = strlen(msg);
451 if (msglen > 255)
452 msglen = 255;
454 u->us_msg = msg;
455 u->us_msglen = msglen;
456 upap_sresp(u, retcode, id, u->us_msg, u->us_msglen);
458 if (retcode == UPAP_AUTHACK) {
459 u->us_serverstate = UPAPSS_OPEN;
460 auth_peer_success(u->us_unit, PPP_PAP, ruser, ruserlen);
461 } else if (++u->us_receives >= u->us_maxreceives) {
462 u->us_serverstate = UPAPSS_BADAUTH;
463 auth_peer_fail(u->us_unit, PPP_PAP);
464 } else {
465 /* Just wait for a good one to arrive, or for time-out. */
466 return;
469 if (u->us_reqtimeout > 0)
470 UNTIMEOUT(upap_reqtimeout, u);
475 * upap_rauthack - Receive Authenticate-Ack.
477 /*ARGSUSED*/
478 static void
479 upap_rauthack(u, inp, id, len)
480 upap_state *u;
481 u_char *inp;
482 int id;
483 int len;
485 u_char msglen;
486 char *msg;
488 if (u->us_clientstate != UPAPCS_AUTHREQ) {
489 info("PAP: discarded Authenticate-Ack in state %s",
490 pap_cstate(u->us_clientstate));
491 return;
494 if (id != u->us_id) {
495 dbglog("PAP: discard Authenticate-Ack; ID %d != %d",
496 id, u->us_id);
497 return;
500 if (u->us_timeouttime > 0)
501 UNTIMEOUT(upap_timeout, u);
504 * Parse message.
506 if (len < 1) {
507 info("PAP: Ignoring missing ack msg-length octet");
508 } else {
509 GETCHAR(msglen, inp);
510 if (msglen > 0) {
511 len -= sizeof (u_char);
512 if (len < msglen) {
513 error("PAP: Discarding short packet (%d < %d)", len, msglen);
514 return;
516 msg = (char *) inp;
517 PRINTMSG(msg, msglen);
521 u->us_clientstate = UPAPCS_OPEN;
523 auth_withpeer_success(u->us_unit, PPP_PAP);
528 * upap_rauthnak - Receive Authenticate-Nakk.
530 /*ARGSUSED*/
531 static void
532 upap_rauthnak(u, inp, id, len)
533 upap_state *u;
534 u_char *inp;
535 int id;
536 int len;
538 u_char msglen;
539 char *msg;
541 if (u->us_clientstate != UPAPCS_AUTHREQ) {
542 info("PAP: discarded Authenticate-Nak in state %s",
543 pap_cstate(u->us_clientstate));
544 return;
547 if (id != u->us_id) {
548 dbglog("PAP: discard Authenticate-Ack; ID %d != %d",
549 id, u->us_id);
550 return;
553 if (u->us_timeouttime > 0)
554 UNTIMEOUT(upap_timeout, u);
557 * Parse message.
559 if (len < 1) {
560 error("PAP: ignoring missing nak msg-length octet");
561 } else {
562 GETCHAR(msglen, inp);
563 if (msglen > 0) {
564 len -= sizeof (u_char);
565 if (len < msglen) {
566 error("PAP: Discarding short packet (%d < %d)", len, msglen);
567 return;
569 msg = (char *) inp;
570 PRINTMSG(msg, msglen);
574 /* Try to get a new password from the plugin. */
575 if (pap_passwd_hook != NULL) {
576 if (u->us_transmits < u->us_maxtransmits) {
577 if ((*pap_passwd_hook)(user, passwd) >= 0) {
578 upap_sauthreq(u);
579 return;
581 } else {
582 /* Tell plug-in that we're giving up. */
583 (void) (*pap_passwd_hook)(NULL, NULL);
587 u->us_clientstate = UPAPCS_BADAUTH;
589 error("PAP authentication failed");
590 auth_withpeer_fail(u->us_unit, PPP_PAP);
595 * upap_sauthreq - Send an Authenticate-Request.
597 static void
598 upap_sauthreq(u)
599 upap_state *u;
601 u_char *outp;
602 int pwlen;
603 int outlen;
605 pwlen = strllen(passwd, MAXSECRETLEN);
606 if (pwlen > 0xFF)
607 pwlen = 0xFF;
608 outlen = UPAP_HEADERLEN + 2 * sizeof (u_char) + u->us_userlen + pwlen;
609 outp = outpacket_buf;
611 MAKEHEADER(outp, PPP_PAP);
613 PUTCHAR(UPAP_AUTHREQ, outp);
614 PUTCHAR(++u->us_id, outp);
615 PUTSHORT(outlen, outp);
616 PUTCHAR(u->us_userlen, outp);
617 BCOPY(u->us_user, outp, u->us_userlen);
618 INCPTR(u->us_userlen, outp);
619 PUTCHAR(pwlen, outp);
620 BCOPY(u->us_passwd, outp, pwlen);
622 output(u->us_unit, outpacket_buf, outlen + PPP_HDRLEN);
624 if (u->us_timeouttime > 0)
625 TIMEOUT(upap_timeout, u, u->us_timeouttime);
626 ++u->us_transmits;
627 u->us_clientstate = UPAPCS_AUTHREQ;
632 * upap_sresp - Send a response (ack or nak).
634 static void
635 upap_sresp(u, code, id, msg, msglen)
636 upap_state *u;
637 u_char code, id;
638 char *msg;
639 int msglen;
641 u_char *outp;
642 int outlen;
644 outlen = UPAP_HEADERLEN + sizeof (u_char) + msglen;
645 outp = outpacket_buf;
646 MAKEHEADER(outp, PPP_PAP);
648 PUTCHAR(code, outp);
649 PUTCHAR(id, outp);
650 PUTSHORT(outlen, outp);
651 PUTCHAR(msglen, outp);
652 BCOPY(msg, outp, msglen);
653 output(u->us_unit, outpacket_buf, outlen + PPP_HDRLEN);
657 * upap_printpkt - print the contents of a PAP packet.
659 static char *upap_codenames[] = {
660 "AuthReq", "AuthAck", "AuthNak"
663 static int
664 upap_printpkt(p, plen, printer, arg)
665 u_char *p;
666 int plen;
667 void (*printer) __P((void *, const char *, ...));
668 void *arg;
670 int code, id, len;
671 int mlen, ulen, wlen;
672 char *user, *pwd, *msg;
673 u_char *pstart;
675 if (plen < UPAP_HEADERLEN)
676 return (0);
677 pstart = p;
678 GETCHAR(code, p);
679 GETCHAR(id, p);
680 GETSHORT(len, p);
681 if (len < UPAP_HEADERLEN || len > plen)
682 return (0);
684 if (code >= 1 && code <= Dim(upap_codenames))
685 printer(arg, " %s", upap_codenames[code-1]);
686 else
687 printer(arg, " code=0x%x", code);
688 printer(arg, " id=0x%x", id);
689 len -= UPAP_HEADERLEN;
690 switch (code) {
691 case UPAP_AUTHREQ:
692 if (len < 1)
693 break;
694 ulen = p[0];
695 if (len < ulen + 2)
696 break;
697 wlen = p[ulen + 1];
698 if (len < ulen + wlen + 2)
699 break;
700 user = (char *) (p + 1);
701 pwd = (char *) (p + ulen + 2);
702 p += ulen + wlen + 2;
703 len -= ulen + wlen + 2;
704 printer(arg, " user=");
705 print_string(user, ulen, printer, arg);
706 printer(arg, " password=");
707 if (!hide_password)
708 print_string(pwd, wlen, printer, arg);
709 else
710 printer(arg, "<hidden>");
711 break;
712 case UPAP_AUTHACK:
713 case UPAP_AUTHNAK:
714 if (len < 1)
715 break;
716 mlen = p[0];
717 if (len < mlen + 1)
718 break;
719 msg = (char *) (p + 1);
720 p += mlen + 1;
721 len -= mlen + 1;
722 printer(arg, " ");
723 print_string(msg, mlen, printer, arg);
724 break;
727 /* print the rest of the bytes in the packet */
728 for (; len > 0; --len) {
729 GETCHAR(code, p);
730 printer(arg, " %.2x", code);
733 return (p - pstart);