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.
19 * $FreeBSD: src/usr.sbin/pppd/upap.c,v 1.8 1999/08/28 01:19:08 peter Exp $
20 * $DragonFly: src/usr.sbin/pppd/upap.c,v 1.4 2005/11/24 23:42:54 swildner Exp $
29 #include <sys/types.h>
37 * Protocol entry points.
39 static void upap_init(int);
40 static void upap_lowerup(int);
41 static void upap_lowerdown(int);
42 static void upap_input(int, u_char
*, int);
43 static void upap_protrej(int);
44 static int upap_printpkt(u_char
*, int,
45 void (*)(void *, char *, ...), void *);
47 struct protent pap_protent
= {
65 upap_state upap
[NUM_PPP
]; /* UPAP state; one for each unit */
67 static void upap_timeout(void *);
68 static void upap_reqtimeout(void *);
69 static void upap_rauthreq(upap_state
*, u_char
*, int, int);
70 static void upap_rauthack(upap_state
*, u_char
*, int, int);
71 static void upap_rauthnak(upap_state
*, u_char
*, int, int);
72 static void upap_sauthreq(upap_state
*);
73 static void upap_sresp(upap_state
*, int, int, char *, int);
77 * upap_init - Initialize a UPAP unit.
82 upap_state
*u
= &upap
[unit
];
89 u
->us_clientstate
= UPAPCS_INITIAL
;
90 u
->us_serverstate
= UPAPSS_INITIAL
;
92 u
->us_timeouttime
= UPAP_DEFTIMEOUT
;
93 u
->us_maxtransmits
= 10;
94 u
->us_reqtimeout
= UPAP_DEFREQTIME
;
99 * upap_authwithpeer - Authenticate us with our peer (start client).
101 * Set new state and send authenticate's.
104 upap_authwithpeer(int unit
, char *user
, char *password
)
106 upap_state
*u
= &upap
[unit
];
108 /* Save the username and password we're given */
110 u
->us_userlen
= strlen(user
);
111 u
->us_passwd
= password
;
112 u
->us_passwdlen
= strlen(password
);
115 /* Lower layer up yet? */
116 if (u
->us_clientstate
== UPAPCS_INITIAL
||
117 u
->us_clientstate
== UPAPCS_PENDING
) {
118 u
->us_clientstate
= UPAPCS_PENDING
;
122 upap_sauthreq(u
); /* Start protocol */
127 * upap_authpeer - Authenticate our peer (start server).
132 upap_authpeer(int unit
)
134 upap_state
*u
= &upap
[unit
];
136 /* Lower layer up yet? */
137 if (u
->us_serverstate
== UPAPSS_INITIAL
||
138 u
->us_serverstate
== UPAPSS_PENDING
) {
139 u
->us_serverstate
= UPAPSS_PENDING
;
143 u
->us_serverstate
= UPAPSS_LISTEN
;
144 if (u
->us_reqtimeout
> 0)
145 TIMEOUT(upap_reqtimeout
, u
, u
->us_reqtimeout
);
150 * upap_timeout - Retransmission timer for sending auth-reqs expired.
153 upap_timeout(void *arg
)
155 upap_state
*u
= (upap_state
*) arg
;
157 if (u
->us_clientstate
!= UPAPCS_AUTHREQ
)
160 if (u
->us_transmits
>= u
->us_maxtransmits
) {
161 /* give up in disgust */
162 syslog(LOG_ERR
, "No response to PAP authenticate-requests");
163 u
->us_clientstate
= UPAPCS_BADAUTH
;
164 auth_withpeer_fail(u
->us_unit
, PPP_PAP
);
168 upap_sauthreq(u
); /* Send Authenticate-Request */
173 * upap_reqtimeout - Give up waiting for the peer to send an auth-req.
176 upap_reqtimeout(void *arg
)
178 upap_state
*u
= (upap_state
*) arg
;
180 if (u
->us_serverstate
!= UPAPSS_LISTEN
)
183 auth_peer_fail(u
->us_unit
, PPP_PAP
);
184 u
->us_serverstate
= UPAPSS_BADAUTH
;
189 * upap_lowerup - The lower layer is up.
191 * Start authenticating if pending.
194 upap_lowerup(int unit
)
196 upap_state
*u
= &upap
[unit
];
198 if (u
->us_clientstate
== UPAPCS_INITIAL
)
199 u
->us_clientstate
= UPAPCS_CLOSED
;
200 else if (u
->us_clientstate
== UPAPCS_PENDING
) {
201 upap_sauthreq(u
); /* send an auth-request */
204 if (u
->us_serverstate
== UPAPSS_INITIAL
)
205 u
->us_serverstate
= UPAPSS_CLOSED
;
206 else if (u
->us_serverstate
== UPAPSS_PENDING
) {
207 u
->us_serverstate
= UPAPSS_LISTEN
;
208 if (u
->us_reqtimeout
> 0)
209 TIMEOUT(upap_reqtimeout
, u
, u
->us_reqtimeout
);
215 * upap_lowerdown - The lower layer is down.
217 * Cancel all timeouts.
220 upap_lowerdown(int unit
)
222 upap_state
*u
= &upap
[unit
];
224 if (u
->us_clientstate
== UPAPCS_AUTHREQ
) /* Timeout pending? */
225 UNTIMEOUT(upap_timeout
, u
); /* Cancel timeout */
226 if (u
->us_serverstate
== UPAPSS_LISTEN
&& u
->us_reqtimeout
> 0)
227 UNTIMEOUT(upap_reqtimeout
, u
);
229 u
->us_clientstate
= UPAPCS_INITIAL
;
230 u
->us_serverstate
= UPAPSS_INITIAL
;
235 * upap_protrej - Peer doesn't speak this protocol.
237 * This shouldn't happen. In any case, pretend lower layer went down.
240 upap_protrej(int unit
)
242 upap_state
*u
= &upap
[unit
];
244 if (u
->us_clientstate
== UPAPCS_AUTHREQ
) {
245 syslog(LOG_ERR
, "PAP authentication failed due to protocol-reject");
246 auth_withpeer_fail(unit
, PPP_PAP
);
248 if (u
->us_serverstate
== UPAPSS_LISTEN
) {
249 syslog(LOG_ERR
, "PAP authentication of peer failed (protocol-reject)");
250 auth_peer_fail(unit
, PPP_PAP
);
252 upap_lowerdown(unit
);
257 * upap_input - Input UPAP packet.
260 upap_input(int unit
, u_char
*inpacket
, int l
)
262 upap_state
*u
= &upap
[unit
];
268 * Parse header (code, id and length).
269 * If packet too short, drop it.
272 if (l
< UPAP_HEADERLEN
) {
273 UPAPDEBUG((LOG_INFO
, "pap_input: rcvd short header."));
279 if (len
< UPAP_HEADERLEN
) {
280 UPAPDEBUG((LOG_INFO
, "pap_input: rcvd illegal length."));
284 UPAPDEBUG((LOG_INFO
, "pap_input: rcvd short packet."));
287 len
-= UPAP_HEADERLEN
;
290 * Action depends on code.
294 upap_rauthreq(u
, inp
, id
, len
);
298 upap_rauthack(u
, inp
, id
, len
);
302 upap_rauthnak(u
, inp
, id
, len
);
305 default: /* XXX Need code reject */
312 * upap_rauth - Receive Authenticate.
315 upap_rauthreq(upap_state
*u
, u_char
*inp
, int id
, int len
)
317 u_char ruserlen
, rpasswdlen
;
318 char *ruser
, *rpasswd
;
323 UPAPDEBUG((LOG_INFO
, "pap_rauth: Rcvd id %d.", id
));
325 if (u
->us_serverstate
< UPAPSS_LISTEN
)
329 * If we receive a duplicate authenticate-request, we are
330 * supposed to return the same status as for the first request.
332 if (u
->us_serverstate
== UPAPSS_OPEN
) {
333 upap_sresp(u
, UPAP_AUTHACK
, id
, "", 0); /* return auth-ack */
336 if (u
->us_serverstate
== UPAPSS_BADAUTH
) {
337 upap_sresp(u
, UPAP_AUTHNAK
, id
, "", 0); /* return auth-nak */
344 if (len
< sizeof (u_char
)) {
345 UPAPDEBUG((LOG_INFO
, "pap_rauth: rcvd short packet."));
348 GETCHAR(ruserlen
, inp
);
349 len
-= sizeof (u_char
) + ruserlen
+ sizeof (u_char
);
351 UPAPDEBUG((LOG_INFO
, "pap_rauth: rcvd short packet."));
354 ruser
= (char *) inp
;
355 INCPTR(ruserlen
, inp
);
356 GETCHAR(rpasswdlen
, inp
);
357 if (len
< rpasswdlen
) {
358 UPAPDEBUG((LOG_INFO
, "pap_rauth: rcvd short packet."));
361 rpasswd
= (char *) inp
;
364 * Check the username and password given.
366 retcode
= check_passwd(u
->us_unit
, ruser
, ruserlen
, rpasswd
,
367 rpasswdlen
, &msg
, &msglen
);
368 BZERO(rpasswd
, rpasswdlen
);
370 upap_sresp(u
, retcode
, id
, msg
, msglen
);
372 if (retcode
== UPAP_AUTHACK
) {
373 u
->us_serverstate
= UPAPSS_OPEN
;
374 auth_peer_success(u
->us_unit
, PPP_PAP
, ruser
, ruserlen
);
376 u
->us_serverstate
= UPAPSS_BADAUTH
;
377 auth_peer_fail(u
->us_unit
, PPP_PAP
);
380 if (u
->us_reqtimeout
> 0)
381 UNTIMEOUT(upap_reqtimeout
, u
);
386 * upap_rauthack - Receive Authenticate-Ack.
389 upap_rauthack(upap_state
*u
, u_char
*inp
, int id
, int len
)
394 UPAPDEBUG((LOG_INFO
, "pap_rauthack: Rcvd id %d.", id
));
395 if (u
->us_clientstate
!= UPAPCS_AUTHREQ
) /* XXX */
401 if (len
< sizeof (u_char
)) {
402 UPAPDEBUG((LOG_INFO
, "pap_rauthack: rcvd short packet."));
405 GETCHAR(msglen
, inp
);
406 len
-= sizeof (u_char
);
408 UPAPDEBUG((LOG_INFO
, "pap_rauthack: rcvd short packet."));
412 PRINTMSG(msg
, msglen
);
414 u
->us_clientstate
= UPAPCS_OPEN
;
416 auth_withpeer_success(u
->us_unit
, PPP_PAP
);
421 * upap_rauthnak - Receive Authenticate-Nakk.
424 upap_rauthnak(upap_state
*u
, u_char
*inp
, int id
, int len
)
429 UPAPDEBUG((LOG_INFO
, "pap_rauthnak: Rcvd id %d.", id
));
430 if (u
->us_clientstate
!= UPAPCS_AUTHREQ
) /* XXX */
436 if (len
< sizeof (u_char
)) {
437 UPAPDEBUG((LOG_INFO
, "pap_rauthnak: rcvd short packet."));
440 GETCHAR(msglen
, inp
);
441 len
-= sizeof (u_char
);
443 UPAPDEBUG((LOG_INFO
, "pap_rauthnak: rcvd short packet."));
447 PRINTMSG(msg
, msglen
);
449 u
->us_clientstate
= UPAPCS_BADAUTH
;
451 syslog(LOG_ERR
, "PAP authentication failed");
452 auth_withpeer_fail(u
->us_unit
, PPP_PAP
);
457 * upap_sauthreq - Send an Authenticate-Request.
460 upap_sauthreq(upap_state
*u
)
465 outlen
= UPAP_HEADERLEN
+ 2 * sizeof (u_char
) +
466 u
->us_userlen
+ u
->us_passwdlen
;
467 outp
= outpacket_buf
;
469 MAKEHEADER(outp
, PPP_PAP
);
471 PUTCHAR(UPAP_AUTHREQ
, outp
);
472 PUTCHAR(++u
->us_id
, outp
);
473 PUTSHORT(outlen
, outp
);
474 PUTCHAR(u
->us_userlen
, outp
);
475 BCOPY(u
->us_user
, outp
, u
->us_userlen
);
476 INCPTR(u
->us_userlen
, outp
);
477 PUTCHAR(u
->us_passwdlen
, outp
);
478 BCOPY(u
->us_passwd
, outp
, u
->us_passwdlen
);
480 output(u
->us_unit
, outpacket_buf
, outlen
+ PPP_HDRLEN
);
482 UPAPDEBUG((LOG_INFO
, "pap_sauth: Sent id %d.", u
->us_id
));
484 TIMEOUT(upap_timeout
, u
, u
->us_timeouttime
);
486 u
->us_clientstate
= UPAPCS_AUTHREQ
;
491 * upap_sresp - Send a response (ack or nak).
494 upap_sresp(upap_state
*u
, int code
, int id
, char *msg
, int msglen
)
499 outlen
= UPAP_HEADERLEN
+ sizeof (u_char
) + msglen
;
500 outp
= outpacket_buf
;
501 MAKEHEADER(outp
, PPP_PAP
);
505 PUTSHORT(outlen
, outp
);
506 PUTCHAR(msglen
, outp
);
507 BCOPY(msg
, outp
, msglen
);
508 output(u
->us_unit
, outpacket_buf
, outlen
+ PPP_HDRLEN
);
510 UPAPDEBUG((LOG_INFO
, "pap_sresp: Sent code %d, id %d.", code
, id
));
514 * upap_printpkt - print the contents of a PAP packet.
516 static char *upap_codenames
[] = {
517 "AuthReq", "AuthAck", "AuthNak"
521 upap_printpkt(u_char
*p
, int plen
, void (*printer
)(void *, char *, ...),
525 int mlen
, ulen
, wlen
;
526 char *user
, *pwd
, *msg
;
529 if (plen
< UPAP_HEADERLEN
)
535 if (len
< UPAP_HEADERLEN
|| len
> plen
)
538 if (code
>= 1 && code
<= sizeof(upap_codenames
) / sizeof(char *))
539 printer(arg
, " %s", upap_codenames
[code
-1]);
541 printer(arg
, " code=0x%x", code
);
542 printer(arg
, " id=0x%x", id
);
543 len
-= UPAP_HEADERLEN
;
552 if (len
< ulen
+ wlen
+ 2)
554 user
= (char *) (p
+ 1);
555 pwd
= (char *) (p
+ ulen
+ 2);
556 p
+= ulen
+ wlen
+ 2;
557 len
-= ulen
+ wlen
+ 2;
558 printer(arg
, " user=");
559 print_string(user
, ulen
, printer
, arg
);
560 printer(arg
, " password=");
561 print_string(pwd
, wlen
, printer
, arg
);
570 msg
= (char *) (p
+ 1);
574 print_string(msg
, mlen
, printer
, arg
);
578 /* print the rest of the bytes in the packet */
579 for (; len
> 0; --len
) {
581 printer(arg
, " %.2x", code
);