2 * upap.c - User/Password Authentication Protocol.
4 * Copyright (c) 1989 Carnegie Mellon University.
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.
20 #define RCSID "$Id: upap.c,v 1.3 2004/10/06 10:23:18 honor Exp $"
32 static const char rcsid
[] = RCSID
;
34 static bool hide_password
= 1;
37 * Command-line options.
39 static option_t pap_option_list
[] = {
40 { "hide-password", o_bool
, &hide_password
,
41 "Don't output passwords to log", OPT_PRIO
| 1 },
42 { "show-password", o_bool
, &hide_password
,
43 "Show password string in debug log messages", OPT_PRIOSUB
| 0 },
45 { "pap-restart", o_int
, &upap
[0].us_timeouttime
,
46 "Set retransmit timeout for PAP", OPT_PRIO
},
47 { "pap-max-authreq", o_int
, &upap
[0].us_maxtransmits
,
48 "Set max number of transmissions for auth-reqs", OPT_PRIO
},
49 { "pap-timeout", o_int
, &upap
[0].us_reqtimeout
,
50 "Set time limit for peer PAP authentication", OPT_PRIO
},
56 * Protocol entry points.
58 static void upap_init
__P((int));
59 static void upap_lowerup
__P((int));
60 static void upap_lowerdown
__P((int));
61 static void upap_input
__P((int, u_char
*, int));
62 static void upap_protrej
__P((int));
63 static int upap_printpkt
__P((u_char
*, int,
64 void (*) __P((void *, char *, ...)), void *));
66 struct protent pap_protent
= {
86 upap_state upap
[NUM_PPP
]; /* UPAP state; one for each unit */
88 static void upap_timeout
__P((void *));
89 static void upap_reqtimeout
__P((void *));
90 static void upap_rauthreq
__P((upap_state
*, u_char
*, int, int));
91 static void upap_rauthack
__P((upap_state
*, u_char
*, int, int));
92 static void upap_rauthnak
__P((upap_state
*, u_char
*, int, int));
93 static void upap_sauthreq
__P((upap_state
*));
94 static void upap_sresp
__P((upap_state
*, int, int, char *, int));
98 * upap_init - Initialize a UPAP unit.
104 upap_state
*u
= &upap
[unit
];
111 u
->us_clientstate
= UPAPCS_INITIAL
;
112 u
->us_serverstate
= UPAPSS_INITIAL
;
114 u
->us_timeouttime
= UPAP_DEFTIMEOUT
;
115 u
->us_maxtransmits
= 10;
116 u
->us_reqtimeout
= UPAP_DEFREQTIME
;
121 * upap_authwithpeer - Authenticate us with our peer (start client).
123 * Set new state and send authenticate's.
126 upap_authwithpeer(unit
, user
, password
)
128 char *user
, *password
;
130 upap_state
*u
= &upap
[unit
];
132 /* Save the username and password we're given */
134 u
->us_userlen
= strlen(user
);
135 u
->us_passwd
= password
;
136 u
->us_passwdlen
= strlen(password
);
139 /* Lower layer up yet? */
140 if (u
->us_clientstate
== UPAPCS_INITIAL
||
141 u
->us_clientstate
== UPAPCS_PENDING
) {
142 u
->us_clientstate
= UPAPCS_PENDING
;
146 upap_sauthreq(u
); /* Start protocol */
151 * upap_authpeer - Authenticate our peer (start server).
159 upap_state
*u
= &upap
[unit
];
161 /* Lower layer up yet? */
162 if (u
->us_serverstate
== UPAPSS_INITIAL
||
163 u
->us_serverstate
== UPAPSS_PENDING
) {
164 u
->us_serverstate
= UPAPSS_PENDING
;
168 u
->us_serverstate
= UPAPSS_LISTEN
;
169 if (u
->us_reqtimeout
> 0)
170 TIMEOUT(upap_reqtimeout
, u
, u
->us_reqtimeout
);
175 * upap_timeout - Retransmission timer for sending auth-reqs expired.
181 upap_state
*u
= (upap_state
*) arg
;
183 if (u
->us_clientstate
!= UPAPCS_AUTHREQ
)
186 if (u
->us_transmits
>= u
->us_maxtransmits
) {
187 /* give up in disgust */
188 error("No response to PAP authenticate-requests");
189 u
->us_clientstate
= UPAPCS_BADAUTH
;
190 auth_withpeer_fail(u
->us_unit
, PPP_PAP
);
194 upap_sauthreq(u
); /* Send Authenticate-Request */
199 * upap_reqtimeout - Give up waiting for the peer to send an auth-req.
205 upap_state
*u
= (upap_state
*) arg
;
207 if (u
->us_serverstate
!= UPAPSS_LISTEN
)
210 auth_peer_fail(u
->us_unit
, PPP_PAP
);
211 u
->us_serverstate
= UPAPSS_BADAUTH
;
216 * upap_lowerup - The lower layer is up.
218 * Start authenticating if pending.
224 upap_state
*u
= &upap
[unit
];
226 if (u
->us_clientstate
== UPAPCS_INITIAL
)
227 u
->us_clientstate
= UPAPCS_CLOSED
;
228 else if (u
->us_clientstate
== UPAPCS_PENDING
) {
229 upap_sauthreq(u
); /* send an auth-request */
232 if (u
->us_serverstate
== UPAPSS_INITIAL
)
233 u
->us_serverstate
= UPAPSS_CLOSED
;
234 else if (u
->us_serverstate
== UPAPSS_PENDING
) {
235 u
->us_serverstate
= UPAPSS_LISTEN
;
236 if (u
->us_reqtimeout
> 0)
237 TIMEOUT(upap_reqtimeout
, u
, u
->us_reqtimeout
);
243 * upap_lowerdown - The lower layer is down.
245 * Cancel all timeouts.
251 upap_state
*u
= &upap
[unit
];
253 if (u
->us_clientstate
== UPAPCS_AUTHREQ
) /* Timeout pending? */
254 UNTIMEOUT(upap_timeout
, u
); /* Cancel timeout */
255 if (u
->us_serverstate
== UPAPSS_LISTEN
&& u
->us_reqtimeout
> 0)
256 UNTIMEOUT(upap_reqtimeout
, u
);
258 u
->us_clientstate
= UPAPCS_INITIAL
;
259 u
->us_serverstate
= UPAPSS_INITIAL
;
264 * upap_protrej - Peer doesn't speak this protocol.
266 * This shouldn't happen. In any case, pretend lower layer went down.
272 upap_state
*u
= &upap
[unit
];
274 if (u
->us_clientstate
== UPAPCS_AUTHREQ
) {
275 error("PAP authentication failed due to protocol-reject");
276 auth_withpeer_fail(unit
, PPP_PAP
);
278 if (u
->us_serverstate
== UPAPSS_LISTEN
) {
279 error("PAP authentication of peer failed (protocol-reject)");
280 auth_peer_fail(unit
, PPP_PAP
);
282 upap_lowerdown(unit
);
287 * upap_input - Input UPAP packet.
290 upap_input(unit
, inpacket
, l
)
295 upap_state
*u
= &upap
[unit
];
301 * Parse header (code, id and length).
302 * If packet too short, drop it.
305 if (l
< UPAP_HEADERLEN
) {
306 UPAPDEBUG(("pap_input: rcvd short header."));
312 if (len
< UPAP_HEADERLEN
) {
313 UPAPDEBUG(("pap_input: rcvd illegal length."));
317 UPAPDEBUG(("pap_input: rcvd short packet."));
320 len
-= UPAP_HEADERLEN
;
323 * Action depends on code.
327 upap_rauthreq(u
, inp
, id
, len
);
331 upap_rauthack(u
, inp
, id
, len
);
335 upap_rauthnak(u
, inp
, id
, len
);
338 default: /* XXX Need code reject */
345 * upap_rauth - Receive Authenticate.
348 upap_rauthreq(u
, inp
, id
, len
)
354 u_char ruserlen
, rpasswdlen
;
355 char *ruser
, *rpasswd
;
360 if (u
->us_serverstate
< UPAPSS_LISTEN
)
364 * If we receive a duplicate authenticate-request, we are
365 * supposed to return the same status as for the first request.
367 if (u
->us_serverstate
== UPAPSS_OPEN
) {
368 upap_sresp(u
, UPAP_AUTHACK
, id
, "", 0); /* return auth-ack */
371 if (u
->us_serverstate
== UPAPSS_BADAUTH
) {
372 upap_sresp(u
, UPAP_AUTHNAK
, id
, "", 0); /* return auth-nak */
380 UPAPDEBUG(("pap_rauth: rcvd short packet."));
383 GETCHAR(ruserlen
, inp
);
384 len
-= sizeof (u_char
) + ruserlen
+ sizeof (u_char
);
386 UPAPDEBUG(("pap_rauth: rcvd short packet."));
389 ruser
= (char *) inp
;
390 INCPTR(ruserlen
, inp
);
391 GETCHAR(rpasswdlen
, inp
);
392 if (len
< rpasswdlen
) {
393 UPAPDEBUG(("pap_rauth: rcvd short packet."));
396 rpasswd
= (char *) inp
;
399 * Check the username and password given.
401 retcode
= check_passwd(u
->us_unit
, ruser
, ruserlen
, rpasswd
,
403 BZERO(rpasswd
, rpasswdlen
);
404 msglen
= strlen(msg
);
408 upap_sresp(u
, retcode
, id
, msg
, msglen
);
410 if (retcode
== UPAP_AUTHACK
) {
411 u
->us_serverstate
= UPAPSS_OPEN
;
412 auth_peer_success(u
->us_unit
, PPP_PAP
, ruser
, ruserlen
);
414 u
->us_serverstate
= UPAPSS_BADAUTH
;
415 auth_peer_fail(u
->us_unit
, PPP_PAP
);
418 if (u
->us_reqtimeout
> 0)
419 UNTIMEOUT(upap_reqtimeout
, u
);
424 * upap_rauthack - Receive Authenticate-Ack.
427 upap_rauthack(u
, inp
, id
, len
)
436 if (u
->us_clientstate
!= UPAPCS_AUTHREQ
) /* XXX */
443 UPAPDEBUG(("pap_rauthack: ignoring missing msg-length."));
445 GETCHAR(msglen
, inp
);
447 len
-= sizeof (u_char
);
449 UPAPDEBUG(("pap_rauthack: rcvd short packet."));
453 PRINTMSG(msg
, msglen
);
457 u
->us_clientstate
= UPAPCS_OPEN
;
459 auth_withpeer_success(u
->us_unit
, PPP_PAP
);
464 * upap_rauthnak - Receive Authenticate-Nakk.
467 upap_rauthnak(u
, inp
, id
, len
)
476 if (u
->us_clientstate
!= UPAPCS_AUTHREQ
) /* XXX */
483 UPAPDEBUG(("pap_rauthnak: ignoring missing msg-length."));
485 GETCHAR(msglen
, inp
);
487 len
-= sizeof (u_char
);
489 UPAPDEBUG(("pap_rauthnak: rcvd short packet."));
493 PRINTMSG(msg
, msglen
);
497 u
->us_clientstate
= UPAPCS_BADAUTH
;
499 error("PAP authentication failed");
501 //log_to_file("PAP_AUTH_FAIL");
502 system("ppp_event -t PAP_AUTH_FAIL &");
504 auth_withpeer_fail(u
->us_unit
, PPP_PAP
);
509 * upap_sauthreq - Send an Authenticate-Request.
518 outlen
= UPAP_HEADERLEN
+ 2 * sizeof (u_char
) +
519 u
->us_userlen
+ u
->us_passwdlen
;
520 outp
= outpacket_buf
;
522 MAKEHEADER(outp
, PPP_PAP
);
524 PUTCHAR(UPAP_AUTHREQ
, outp
);
525 PUTCHAR(++u
->us_id
, outp
);
526 PUTSHORT(outlen
, outp
);
527 PUTCHAR(u
->us_userlen
, outp
);
528 BCOPY(u
->us_user
, outp
, u
->us_userlen
);
529 INCPTR(u
->us_userlen
, outp
);
530 PUTCHAR(u
->us_passwdlen
, outp
);
531 BCOPY(u
->us_passwd
, outp
, u
->us_passwdlen
);
533 output(u
->us_unit
, outpacket_buf
, outlen
+ PPP_HDRLEN
);
535 TIMEOUT(upap_timeout
, u
, u
->us_timeouttime
);
537 u
->us_clientstate
= UPAPCS_AUTHREQ
;
542 * upap_sresp - Send a response (ack or nak).
545 upap_sresp(u
, code
, id
, msg
, msglen
)
554 outlen
= UPAP_HEADERLEN
+ sizeof (u_char
) + msglen
;
555 outp
= outpacket_buf
;
556 MAKEHEADER(outp
, PPP_PAP
);
560 PUTSHORT(outlen
, outp
);
561 PUTCHAR(msglen
, outp
);
562 BCOPY(msg
, outp
, msglen
);
563 output(u
->us_unit
, outpacket_buf
, outlen
+ PPP_HDRLEN
);
567 * upap_printpkt - print the contents of a PAP packet.
569 static char *upap_codenames
[] = {
570 "AuthReq", "AuthAck", "AuthNak"
574 upap_printpkt(p
, plen
, printer
, arg
)
577 void (*printer
) __P((void *, char *, ...));
581 int mlen
, ulen
, wlen
;
582 char *user
, *pwd
, *msg
;
585 if (plen
< UPAP_HEADERLEN
)
591 if (len
< UPAP_HEADERLEN
|| len
> plen
)
594 if (code
>= 1 && code
<= sizeof(upap_codenames
) / sizeof(char *))
595 printer(arg
, " %s", upap_codenames
[code
-1]);
597 printer(arg
, " code=0x%x", code
);
598 printer(arg
, " id=0x%x", id
);
599 len
-= UPAP_HEADERLEN
;
608 if (len
< ulen
+ wlen
+ 2)
610 user
= (char *) (p
+ 1);
611 pwd
= (char *) (p
+ ulen
+ 2);
612 p
+= ulen
+ wlen
+ 2;
613 len
-= ulen
+ wlen
+ 2;
614 printer(arg
, " user=");
615 print_string(user
, ulen
, printer
, arg
);
616 printer(arg
, " password=");
618 print_string(pwd
, wlen
, printer
, arg
);
620 printer(arg
, "<hidden>");
629 msg
= (char *) (p
+ 1);
633 print_string(msg
, mlen
, printer
, arg
);
637 /* print the rest of the bytes in the packet */
638 for (; len
> 0; --len
) {
640 printer(arg
, " %.2x", code
);