1 /*****************************************************************************
2 * pap.c - Network Password Authentication Protocol program file.
4 * Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
5 * portions Copyright (c) 1997 by Global Election Systems Inc.
7 * The authors hereby grant permission to use, copy, modify, distribute,
8 * and license this software and its documentation for any purpose, provided
9 * that existing copyright notices are retained in all copies and that this
10 * notice and the following disclaimer are included verbatim in any
11 * distributions. No written agreement, license, or royalty fee is required
12 * for any of the authorized uses.
14 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 ******************************************************************************
28 * 03-01-01 Marc Boucher <marc@mbsi.ca>
30 * 97-12-12 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
32 *****************************************************************************/
34 * upap.c - User/Password Authentication Protocol.
36 * Copyright (c) 1989 Carnegie Mellon University.
37 * All rights reserved.
39 * Redistribution and use in source and binary forms are permitted
40 * provided that the above copyright notice and this paragraph are
41 * duplicated in all such forms and that any documentation,
42 * advertising materials, and other materials related to such
43 * distribution and use acknowledge that the software was developed
44 * by Carnegie Mellon University. The name of the
45 * University may not be used to endorse or promote products derived
46 * from this software without specific prior written permission.
47 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
48 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
49 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
54 #if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */
56 #if PAP_SUPPORT /* don't build if not configured for use in lwipopts.h */
67 static bool hide_password
= 1;
70 * Command-line options.
72 static option_t pap_option_list
[] = {
73 { "hide-password", o_bool
, &hide_password
,
74 "Don't output passwords to log", 1 },
75 { "show-password", o_bool
, &hide_password
,
76 "Show password string in debug log messages", 0 },
77 { "pap-restart", o_int
, &upap
[0].us_timeouttime
,
78 "Set retransmit timeout for PAP" },
79 { "pap-max-authreq", o_int
, &upap
[0].us_maxtransmits
,
80 "Set max number of transmissions for auth-reqs" },
81 { "pap-timeout", o_int
, &upap
[0].us_reqtimeout
,
82 "Set time limit for peer PAP authentication" },
88 * Protocol entry points.
90 static void upap_init (int);
91 static void upap_lowerup (int);
92 static void upap_lowerdown (int);
93 static void upap_input (int, u_char
*, int);
94 static void upap_protrej (int);
95 #if PPP_ADDITIONAL_CALLBACKS
96 static int upap_printpkt (u_char
*, int, void (*)(void *, char *, ...), void *);
97 #endif /* PPP_ADDITIONAL_CALLBACKS */
99 struct protent pap_protent
= {
108 #if PPP_ADDITIONAL_CALLBACKS
111 #endif /* PPP_ADDITIONAL_CALLBACKS */
114 #if PPP_ADDITIONAL_CALLBACKS
118 #endif /* PPP_ADDITIONAL_CALLBACKS */
121 upap_state upap
[NUM_PPP
]; /* UPAP state; one for each unit */
123 static void upap_timeout (void *);
124 static void upap_reqtimeout(void *);
125 static void upap_rauthreq (upap_state
*, u_char
*, u_char
, int);
126 static void upap_rauthack (upap_state
*, u_char
*, int, int);
127 static void upap_rauthnak (upap_state
*, u_char
*, int, int);
128 static void upap_sauthreq (upap_state
*);
129 static void upap_sresp (upap_state
*, u_char
, u_char
, char *, int);
133 * upap_init - Initialize a UPAP unit.
138 upap_state
*u
= &upap
[unit
];
140 UPAPDEBUG(LOG_INFO
, ("upap_init: %d\n", unit
));
146 u
->us_clientstate
= UPAPCS_INITIAL
;
147 u
->us_serverstate
= UPAPSS_INITIAL
;
149 u
->us_timeouttime
= UPAP_DEFTIMEOUT
;
150 u
->us_maxtransmits
= 10;
151 u
->us_reqtimeout
= UPAP_DEFREQTIME
;
155 * upap_authwithpeer - Authenticate us with our peer (start client).
157 * Set new state and send authenticate's.
160 upap_authwithpeer(int unit
, char *user
, char *password
)
162 upap_state
*u
= &upap
[unit
];
164 UPAPDEBUG(LOG_INFO
, ("upap_authwithpeer: %d user=%s password=%s s=%d\n",
165 unit
, user
, password
, u
->us_clientstate
));
167 /* Save the username and password we're given */
169 u
->us_userlen
= (int)strlen(user
);
170 u
->us_passwd
= password
;
171 u
->us_passwdlen
= (int)strlen(password
);
175 /* Lower layer up yet? */
176 if (u
->us_clientstate
== UPAPCS_INITIAL
||
177 u
->us_clientstate
== UPAPCS_PENDING
) {
178 u
->us_clientstate
= UPAPCS_PENDING
;
182 upap_sauthreq(u
); /* Start protocol */
187 * upap_authpeer - Authenticate our peer (start server).
192 upap_authpeer(int unit
)
194 upap_state
*u
= &upap
[unit
];
196 /* Lower layer up yet? */
197 if (u
->us_serverstate
== UPAPSS_INITIAL
||
198 u
->us_serverstate
== UPAPSS_PENDING
) {
199 u
->us_serverstate
= UPAPSS_PENDING
;
203 u
->us_serverstate
= UPAPSS_LISTEN
;
204 if (u
->us_reqtimeout
> 0) {
205 TIMEOUT(upap_reqtimeout
, u
, u
->us_reqtimeout
);
210 * upap_timeout - Retransmission timer for sending auth-reqs expired.
213 upap_timeout(void *arg
)
215 upap_state
*u
= (upap_state
*) arg
;
217 UPAPDEBUG(LOG_INFO
, ("upap_timeout: %d timeout %d expired s=%d\n",
218 u
->us_unit
, u
->us_timeouttime
, u
->us_clientstate
));
220 if (u
->us_clientstate
!= UPAPCS_AUTHREQ
) {
221 UPAPDEBUG(LOG_INFO
, ("upap_timeout: not in AUTHREQ state!\n"));
225 if (u
->us_transmits
>= u
->us_maxtransmits
) {
226 /* give up in disgust */
227 UPAPDEBUG(LOG_ERR
, ("No response to PAP authenticate-requests\n"));
228 u
->us_clientstate
= UPAPCS_BADAUTH
;
229 auth_withpeer_fail(u
->us_unit
, PPP_PAP
);
233 upap_sauthreq(u
); /* Send Authenticate-Request and set upap timeout*/
238 * upap_reqtimeout - Give up waiting for the peer to send an auth-req.
241 upap_reqtimeout(void *arg
)
243 upap_state
*u
= (upap_state
*) arg
;
245 if (u
->us_serverstate
!= UPAPSS_LISTEN
) {
249 auth_peer_fail(u
->us_unit
, PPP_PAP
);
250 u
->us_serverstate
= UPAPSS_BADAUTH
;
255 * upap_lowerup - The lower layer is up.
257 * Start authenticating if pending.
260 upap_lowerup(int unit
)
262 upap_state
*u
= &upap
[unit
];
264 UPAPDEBUG(LOG_INFO
, ("upap_lowerup: init %d clientstate s=%d\n", unit
, u
->us_clientstate
));
266 if (u
->us_clientstate
== UPAPCS_INITIAL
) {
267 u
->us_clientstate
= UPAPCS_CLOSED
;
268 } else if (u
->us_clientstate
== UPAPCS_PENDING
) {
269 upap_sauthreq(u
); /* send an auth-request */
270 /* now client state is UPAPCS__AUTHREQ */
273 if (u
->us_serverstate
== UPAPSS_INITIAL
) {
274 u
->us_serverstate
= UPAPSS_CLOSED
;
275 } else if (u
->us_serverstate
== UPAPSS_PENDING
) {
276 u
->us_serverstate
= UPAPSS_LISTEN
;
277 if (u
->us_reqtimeout
> 0) {
278 TIMEOUT(upap_reqtimeout
, u
, u
->us_reqtimeout
);
285 * upap_lowerdown - The lower layer is down.
287 * Cancel all timeouts.
290 upap_lowerdown(int unit
)
292 upap_state
*u
= &upap
[unit
];
294 UPAPDEBUG(LOG_INFO
, ("upap_lowerdown: %d s=%d\n", unit
, u
->us_clientstate
));
296 if (u
->us_clientstate
== UPAPCS_AUTHREQ
) { /* Timeout pending? */
297 UNTIMEOUT(upap_timeout
, u
); /* Cancel timeout */
299 if (u
->us_serverstate
== UPAPSS_LISTEN
&& u
->us_reqtimeout
> 0) {
300 UNTIMEOUT(upap_reqtimeout
, u
);
303 u
->us_clientstate
= UPAPCS_INITIAL
;
304 u
->us_serverstate
= UPAPSS_INITIAL
;
309 * upap_protrej - Peer doesn't speak this protocol.
311 * This shouldn't happen. In any case, pretend lower layer went down.
314 upap_protrej(int unit
)
316 upap_state
*u
= &upap
[unit
];
318 if (u
->us_clientstate
== UPAPCS_AUTHREQ
) {
319 UPAPDEBUG(LOG_ERR
, ("PAP authentication failed due to protocol-reject\n"));
320 auth_withpeer_fail(unit
, PPP_PAP
);
322 if (u
->us_serverstate
== UPAPSS_LISTEN
) {
323 UPAPDEBUG(LOG_ERR
, ("PAP authentication of peer failed (protocol-reject)\n"));
324 auth_peer_fail(unit
, PPP_PAP
);
326 upap_lowerdown(unit
);
331 * upap_input - Input UPAP packet.
334 upap_input(int unit
, u_char
*inpacket
, int l
)
336 upap_state
*u
= &upap
[unit
];
342 * Parse header (code, id and length).
343 * If packet too short, drop it.
346 if (l
< (int)UPAP_HEADERLEN
) {
347 UPAPDEBUG(LOG_INFO
, ("pap_input: rcvd short header.\n"));
353 if (len
< (int)UPAP_HEADERLEN
) {
354 UPAPDEBUG(LOG_INFO
, ("pap_input: rcvd illegal length.\n"));
358 UPAPDEBUG(LOG_INFO
, ("pap_input: rcvd short packet.\n"));
361 len
-= UPAP_HEADERLEN
;
364 * Action depends on code.
368 upap_rauthreq(u
, inp
, id
, len
);
372 upap_rauthack(u
, inp
, id
, len
);
376 upap_rauthnak(u
, inp
, id
, len
);
379 default: /* XXX Need code reject */
380 UPAPDEBUG(LOG_INFO
, ("pap_input: UNHANDLED default: code: %d, id: %d, len: %d.\n", code
, id
, len
));
387 * upap_rauth - Receive Authenticate.
390 upap_rauthreq(upap_state
*u
, u_char
*inp
, u_char id
, int len
)
392 u_char ruserlen
, rpasswdlen
;
393 char *ruser
, *rpasswd
;
398 UPAPDEBUG(LOG_INFO
, ("pap_rauth: Rcvd id %d.\n", id
));
400 if (u
->us_serverstate
< UPAPSS_LISTEN
) {
405 * If we receive a duplicate authenticate-request, we are
406 * supposed to return the same status as for the first request.
408 if (u
->us_serverstate
== UPAPSS_OPEN
) {
409 upap_sresp(u
, UPAP_AUTHACK
, id
, "", 0); /* return auth-ack */
412 if (u
->us_serverstate
== UPAPSS_BADAUTH
) {
413 upap_sresp(u
, UPAP_AUTHNAK
, id
, "", 0); /* return auth-nak */
420 if (len
< (int)sizeof (u_char
)) {
421 UPAPDEBUG(LOG_INFO
, ("pap_rauth: rcvd short packet.\n"));
424 GETCHAR(ruserlen
, inp
);
425 len
-= sizeof (u_char
) + ruserlen
+ sizeof (u_char
);
427 UPAPDEBUG(LOG_INFO
, ("pap_rauth: rcvd short packet.\n"));
430 ruser
= (char *) inp
;
431 INCPTR(ruserlen
, inp
);
432 GETCHAR(rpasswdlen
, inp
);
433 if (len
< rpasswdlen
) {
434 UPAPDEBUG(LOG_INFO
, ("pap_rauth: rcvd short packet.\n"));
437 rpasswd
= (char *) inp
;
440 * Check the username and password given.
442 retcode
= check_passwd(u
->us_unit
, ruser
, ruserlen
, rpasswd
, rpasswdlen
, &msg
, &msglen
);
443 /* lwip: currently retcode is always UPAP_AUTHACK */
444 BZERO(rpasswd
, rpasswdlen
);
446 upap_sresp(u
, retcode
, id
, msg
, msglen
);
448 if (retcode
== UPAP_AUTHACK
) {
449 u
->us_serverstate
= UPAPSS_OPEN
;
450 auth_peer_success(u
->us_unit
, PPP_PAP
, ruser
, ruserlen
);
452 u
->us_serverstate
= UPAPSS_BADAUTH
;
453 auth_peer_fail(u
->us_unit
, PPP_PAP
);
456 if (u
->us_reqtimeout
> 0) {
457 UNTIMEOUT(upap_reqtimeout
, u
);
463 * upap_rauthack - Receive Authenticate-Ack.
466 upap_rauthack(upap_state
*u
, u_char
*inp
, int id
, int len
)
473 UPAPDEBUG(LOG_INFO
, ("pap_rauthack: Rcvd id %d s=%d\n", id
, u
->us_clientstate
));
475 if (u
->us_clientstate
!= UPAPCS_AUTHREQ
) { /* XXX */
476 UPAPDEBUG(LOG_INFO
, ("pap_rauthack: us_clientstate != UPAPCS_AUTHREQ\n"));
483 if (len
< (int)sizeof (u_char
)) {
484 UPAPDEBUG(LOG_INFO
, ("pap_rauthack: ignoring missing msg-length.\n"));
486 GETCHAR(msglen
, inp
);
488 len
-= sizeof (u_char
);
490 UPAPDEBUG(LOG_INFO
, ("pap_rauthack: rcvd short packet.\n"));
494 PRINTMSG(msg
, msglen
);
497 UNTIMEOUT(upap_timeout
, u
); /* Cancel timeout */
498 u
->us_clientstate
= UPAPCS_OPEN
;
500 auth_withpeer_success(u
->us_unit
, PPP_PAP
);
505 * upap_rauthnak - Receive Authenticate-Nak.
508 upap_rauthnak(upap_state
*u
, u_char
*inp
, int id
, int len
)
515 UPAPDEBUG(LOG_INFO
, ("pap_rauthnak: Rcvd id %d s=%d\n", id
, u
->us_clientstate
));
517 if (u
->us_clientstate
!= UPAPCS_AUTHREQ
) { /* XXX */
524 if (len
< sizeof (u_char
)) {
525 UPAPDEBUG(LOG_INFO
, ("pap_rauthnak: ignoring missing msg-length.\n"));
527 GETCHAR(msglen
, inp
);
529 len
-= sizeof (u_char
);
531 UPAPDEBUG(LOG_INFO
, ("pap_rauthnak: rcvd short packet.\n"));
535 PRINTMSG(msg
, msglen
);
539 u
->us_clientstate
= UPAPCS_BADAUTH
;
541 UPAPDEBUG(LOG_ERR
, ("PAP authentication failed\n"));
542 auth_withpeer_fail(u
->us_unit
, PPP_PAP
);
547 * upap_sauthreq - Send an Authenticate-Request.
550 upap_sauthreq(upap_state
*u
)
555 outlen
= UPAP_HEADERLEN
+ 2 * sizeof (u_char
)
556 + u
->us_userlen
+ u
->us_passwdlen
;
557 outp
= outpacket_buf
[u
->us_unit
];
559 MAKEHEADER(outp
, PPP_PAP
);
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
);
570 pppWrite(u
->us_unit
, outpacket_buf
[u
->us_unit
], outlen
+ PPP_HDRLEN
);
572 UPAPDEBUG(LOG_INFO
, ("pap_sauth: Sent id %d\n", u
->us_id
));
574 TIMEOUT(upap_timeout
, u
, u
->us_timeouttime
);
576 u
->us_clientstate
= UPAPCS_AUTHREQ
;
581 * upap_sresp - Send a response (ack or nak).
584 upap_sresp(upap_state
*u
, u_char code
, u_char id
, char *msg
, int msglen
)
589 outlen
= UPAP_HEADERLEN
+ sizeof (u_char
) + msglen
;
590 outp
= outpacket_buf
[u
->us_unit
];
591 MAKEHEADER(outp
, PPP_PAP
);
595 PUTSHORT(outlen
, outp
);
596 PUTCHAR(msglen
, outp
);
597 BCOPY(msg
, outp
, msglen
);
598 pppWrite(u
->us_unit
, outpacket_buf
[u
->us_unit
], outlen
+ PPP_HDRLEN
);
600 UPAPDEBUG(LOG_INFO
, ("pap_sresp: Sent code %d, id %d s=%d\n", code
, id
, u
->us_clientstate
));
603 #if PPP_ADDITIONAL_CALLBACKS
604 static char *upap_codenames
[] = {
605 "AuthReq", "AuthAck", "AuthNak"
609 * upap_printpkt - print the contents of a PAP packet.
611 static int upap_printpkt(
614 void (*printer
) (void *, char *, ...),
619 LWIP_UNUSED_ARG(plen
);
620 LWIP_UNUSED_ARG(printer
);
621 LWIP_UNUSED_ARG(arg
);
624 #endif /* PPP_ADDITIONAL_CALLBACKS */
626 #endif /* PAP_SUPPORT */
628 #endif /* PPP_SUPPORT */