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 */
66 /***********************************/
67 /*** LOCAL FUNCTION DECLARATIONS ***/
68 /***********************************/
70 * Protocol entry points.
72 static void upap_init (int);
73 static void upap_lowerup (int);
74 static void upap_lowerdown (int);
75 static void upap_input (int, u_char
*, int);
76 static void upap_protrej (int);
78 static void upap_timeout (void *);
79 static void upap_reqtimeout(void *);
80 static void upap_rauthreq (upap_state
*, u_char
*, int, int);
81 static void upap_rauthack (upap_state
*, u_char
*, int, int);
82 static void upap_rauthnak (upap_state
*, u_char
*, int, int);
83 static void upap_sauthreq (upap_state
*);
84 static void upap_sresp (upap_state
*, u_char
, u_char
, char *, int);
87 /******************************/
88 /*** PUBLIC DATA STRUCTURES ***/
89 /******************************/
90 struct protent pap_protent
= {
112 upap_state upap
[NUM_PPP
]; /* UPAP state; one for each unit */
116 /***********************************/
117 /*** PUBLIC FUNCTION DEFINITIONS ***/
118 /***********************************/
120 * Set the default login name and password for the pap sessions
123 upap_setloginpasswd(int unit
, const char *luser
, const char *lpassword
)
125 upap_state
*u
= &upap
[unit
];
127 /* Save the username and password we're given */
129 u
->us_userlen
= strlen(luser
);
130 u
->us_passwd
= lpassword
;
131 u
->us_passwdlen
= strlen(lpassword
);
136 * upap_authwithpeer - Authenticate us with our peer (start client).
138 * Set new state and send authenticate's.
141 upap_authwithpeer(int unit
, char *user
, char *password
)
143 upap_state
*u
= &upap
[unit
];
145 UPAPDEBUG((LOG_INFO
, "upap_authwithpeer: %d user=%s password=%s s=%d\n",
146 unit
, user
, password
, u
->us_clientstate
));
148 upap_setloginpasswd(unit
, user
, password
);
152 /* Lower layer up yet? */
153 if (u
->us_clientstate
== UPAPCS_INITIAL
||
154 u
->us_clientstate
== UPAPCS_PENDING
) {
155 u
->us_clientstate
= UPAPCS_PENDING
;
159 upap_sauthreq(u
); /* Start protocol */
164 * upap_authpeer - Authenticate our peer (start server).
169 upap_authpeer(int unit
)
171 upap_state
*u
= &upap
[unit
];
173 /* Lower layer up yet? */
174 if (u
->us_serverstate
== UPAPSS_INITIAL
||
175 u
->us_serverstate
== UPAPSS_PENDING
) {
176 u
->us_serverstate
= UPAPSS_PENDING
;
180 u
->us_serverstate
= UPAPSS_LISTEN
;
181 if (u
->us_reqtimeout
> 0) {
182 TIMEOUT(upap_reqtimeout
, u
, u
->us_reqtimeout
);
188 /**********************************/
189 /*** LOCAL FUNCTION DEFINITIONS ***/
190 /**********************************/
192 * upap_init - Initialize a UPAP unit.
197 upap_state
*u
= &upap
[unit
];
199 UPAPDEBUG((LOG_INFO
, "upap_init: %d\n", unit
));
205 u
->us_clientstate
= UPAPCS_INITIAL
;
206 u
->us_serverstate
= UPAPSS_INITIAL
;
208 u
->us_timeouttime
= UPAP_DEFTIMEOUT
;
209 u
->us_maxtransmits
= 10;
210 u
->us_reqtimeout
= UPAP_DEFREQTIME
;
214 * upap_timeout - Retransmission timer for sending auth-reqs expired.
217 upap_timeout(void *arg
)
219 upap_state
*u
= (upap_state
*) arg
;
221 UPAPDEBUG((LOG_INFO
, "upap_timeout: %d timeout %d expired s=%d\n",
222 u
->us_unit
, u
->us_timeouttime
, u
->us_clientstate
));
224 if (u
->us_clientstate
!= UPAPCS_AUTHREQ
) {
228 if (u
->us_transmits
>= u
->us_maxtransmits
) {
229 /* give up in disgust */
230 UPAPDEBUG((LOG_ERR
, "No response to PAP authenticate-requests\n"));
231 u
->us_clientstate
= UPAPCS_BADAUTH
;
232 auth_withpeer_fail(u
->us_unit
, PPP_PAP
);
236 upap_sauthreq(u
); /* Send Authenticate-Request */
241 * upap_reqtimeout - Give up waiting for the peer to send an auth-req.
244 upap_reqtimeout(void *arg
)
246 upap_state
*u
= (upap_state
*) arg
;
248 if (u
->us_serverstate
!= UPAPSS_LISTEN
) {
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.
263 upap_lowerup(int unit
)
265 upap_state
*u
= &upap
[unit
];
267 UPAPDEBUG((LOG_INFO
, "upap_lowerup: %d s=%d\n", unit
, u
->us_clientstate
));
269 if (u
->us_clientstate
== UPAPCS_INITIAL
) {
270 u
->us_clientstate
= UPAPCS_CLOSED
;
271 } else if (u
->us_clientstate
== UPAPCS_PENDING
) {
272 upap_sauthreq(u
); /* send an auth-request */
275 if (u
->us_serverstate
== UPAPSS_INITIAL
) {
276 u
->us_serverstate
= UPAPSS_CLOSED
;
277 } else if (u
->us_serverstate
== UPAPSS_PENDING
) {
278 u
->us_serverstate
= UPAPSS_LISTEN
;
279 if (u
->us_reqtimeout
> 0) {
280 TIMEOUT(upap_reqtimeout
, u
, u
->us_reqtimeout
);
287 * upap_lowerdown - The lower layer is down.
289 * Cancel all timeouts.
292 upap_lowerdown(int unit
)
294 upap_state
*u
= &upap
[unit
];
296 UPAPDEBUG((LOG_INFO
, "upap_lowerdown: %d s=%d\n", unit
, u
->us_clientstate
));
298 if (u
->us_clientstate
== UPAPCS_AUTHREQ
) { /* Timeout pending? */
299 UNTIMEOUT(upap_timeout
, u
); /* Cancel timeout */
301 if (u
->us_serverstate
== UPAPSS_LISTEN
&& u
->us_reqtimeout
> 0) {
302 UNTIMEOUT(upap_reqtimeout
, u
);
305 u
->us_clientstate
= UPAPCS_INITIAL
;
306 u
->us_serverstate
= UPAPSS_INITIAL
;
311 * upap_protrej - Peer doesn't speak this protocol.
313 * This shouldn't happen. In any case, pretend lower layer went down.
316 upap_protrej(int unit
)
318 upap_state
*u
= &upap
[unit
];
320 if (u
->us_clientstate
== UPAPCS_AUTHREQ
) {
321 UPAPDEBUG((LOG_ERR
, "PAP authentication failed due to protocol-reject\n"));
322 auth_withpeer_fail(unit
, PPP_PAP
);
324 if (u
->us_serverstate
== UPAPSS_LISTEN
) {
325 UPAPDEBUG((LOG_ERR
, "PAP authentication of peer failed (protocol-reject)\n"));
326 auth_peer_fail(unit
, PPP_PAP
);
328 upap_lowerdown(unit
);
333 * upap_input - Input UPAP packet.
336 upap_input(int unit
, u_char
*inpacket
, int l
)
338 upap_state
*u
= &upap
[unit
];
344 * Parse header (code, id and length).
345 * If packet too short, drop it.
348 if (l
< UPAP_HEADERLEN
) {
349 UPAPDEBUG((LOG_INFO
, "pap_input: rcvd short header.\n"));
355 if (len
< UPAP_HEADERLEN
) {
356 UPAPDEBUG((LOG_INFO
, "pap_input: rcvd illegal length.\n"));
360 UPAPDEBUG((LOG_INFO
, "pap_input: rcvd short packet.\n"));
363 len
-= UPAP_HEADERLEN
;
366 * Action depends on code.
370 upap_rauthreq(u
, inp
, id
, len
);
374 upap_rauthack(u
, inp
, id
, len
);
378 upap_rauthnak(u
, inp
, id
, len
);
381 default: /* XXX Need code reject */
388 * upap_rauth - Receive Authenticate.
391 upap_rauthreq(upap_state
*u
, u_char
*inp
, int id
, int len
)
393 u_char ruserlen
, rpasswdlen
;
394 char *ruser
, *rpasswd
;
399 UPAPDEBUG((LOG_INFO
, "pap_rauth: Rcvd id %d.\n", id
));
401 if (u
->us_serverstate
< UPAPSS_LISTEN
) {
406 * If we receive a duplicate authenticate-request, we are
407 * supposed to return the same status as for the first request.
409 if (u
->us_serverstate
== UPAPSS_OPEN
) {
410 upap_sresp(u
, UPAP_AUTHACK
, id
, "", 0); /* return auth-ack */
413 if (u
->us_serverstate
== UPAPSS_BADAUTH
) {
414 upap_sresp(u
, UPAP_AUTHNAK
, id
, "", 0); /* return auth-nak */
421 if (len
< sizeof (u_char
)) {
422 UPAPDEBUG((LOG_INFO
, "pap_rauth: rcvd short packet.\n"));
425 GETCHAR(ruserlen
, inp
);
426 len
-= sizeof (u_char
) + ruserlen
+ sizeof (u_char
);
428 UPAPDEBUG((LOG_INFO
, "pap_rauth: rcvd short packet.\n"));
431 ruser
= (char *) inp
;
432 INCPTR(ruserlen
, inp
);
433 GETCHAR(rpasswdlen
, inp
);
434 if (len
< rpasswdlen
) {
435 UPAPDEBUG((LOG_INFO
, "pap_rauth: rcvd short packet.\n"));
438 rpasswd
= (char *) inp
;
441 * Check the username and password given.
443 retcode
= check_passwd(u
->us_unit
, ruser
, ruserlen
, rpasswd
, rpasswdlen
, &msg
, &msglen
);
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 */
482 if (len
< sizeof (u_char
)) {
483 UPAPDEBUG((LOG_INFO
, "pap_rauthack: rcvd short packet.\n"));
486 GETCHAR(msglen
, inp
);
487 len
-= sizeof (u_char
);
489 UPAPDEBUG((LOG_INFO
, "pap_rauthack: rcvd short packet.\n"));
493 PRINTMSG(msg
, msglen
);
495 UNTIMEOUT(upap_timeout
, u
); /* Cancel timeout */
496 u
->us_clientstate
= UPAPCS_OPEN
;
498 auth_withpeer_success(u
->us_unit
, PPP_PAP
);
503 * upap_rauthnak - Receive Authenticate-Nakk.
506 upap_rauthnak(upap_state
*u
, u_char
*inp
, int id
, int len
)
513 UPAPDEBUG((LOG_INFO
, "pap_rauthnak: Rcvd id %d s=%d\n", id
, u
->us_clientstate
));
515 if (u
->us_clientstate
!= UPAPCS_AUTHREQ
) { /* XXX */
522 if (len
< sizeof (u_char
)) {
523 UPAPDEBUG((LOG_INFO
, "pap_rauthnak: rcvd short packet.\n"));
525 GETCHAR(msglen
, inp
);
527 len
-= sizeof (u_char
);
529 UPAPDEBUG((LOG_INFO
, "pap_rauthnak: rcvd short packet.\n"));
533 PRINTMSG(msg
, msglen
);
537 u
->us_clientstate
= UPAPCS_BADAUTH
;
539 UPAPDEBUG((LOG_ERR
, "PAP authentication failed\n"));
540 auth_withpeer_fail(u
->us_unit
, PPP_PAP
);
545 * upap_sauthreq - Send an Authenticate-Request.
548 upap_sauthreq(upap_state
*u
)
553 outlen
= UPAP_HEADERLEN
+ 2 * sizeof (u_char
)
554 + u
->us_userlen
+ u
->us_passwdlen
;
555 outp
= outpacket_buf
[u
->us_unit
];
557 MAKEHEADER(outp
, PPP_PAP
);
559 PUTCHAR(UPAP_AUTHREQ
, outp
);
560 PUTCHAR(++u
->us_id
, outp
);
561 PUTSHORT(outlen
, outp
);
562 PUTCHAR(u
->us_userlen
, outp
);
563 BCOPY(u
->us_user
, outp
, u
->us_userlen
);
564 INCPTR(u
->us_userlen
, outp
);
565 PUTCHAR(u
->us_passwdlen
, outp
);
566 BCOPY(u
->us_passwd
, outp
, u
->us_passwdlen
);
568 pppWrite(u
->us_unit
, outpacket_buf
[u
->us_unit
], outlen
+ PPP_HDRLEN
);
570 UPAPDEBUG((LOG_INFO
, "pap_sauth: Sent id %d\n", u
->us_id
));
572 TIMEOUT(upap_timeout
, u
, u
->us_timeouttime
);
574 u
->us_clientstate
= UPAPCS_AUTHREQ
;
579 * upap_sresp - Send a response (ack or nak).
582 upap_sresp(upap_state
*u
, u_char code
, u_char id
, char *msg
, int msglen
)
587 outlen
= UPAP_HEADERLEN
+ sizeof (u_char
) + msglen
;
588 outp
= outpacket_buf
[u
->us_unit
];
589 MAKEHEADER(outp
, PPP_PAP
);
593 PUTSHORT(outlen
, outp
);
594 PUTCHAR(msglen
, outp
);
595 BCOPY(msg
, outp
, msglen
);
596 pppWrite(u
->us_unit
, outpacket_buf
[u
->us_unit
], outlen
+ PPP_HDRLEN
);
598 UPAPDEBUG((LOG_INFO
, "pap_sresp: Sent code %d, id %d s=%d\n", code
, id
, u
->us_clientstate
));
603 * upap_printpkt - print the contents of a PAP packet.
605 static int upap_printpkt(
608 void (*printer
) (void *, char *, ...),
613 LWIP_UNUSED_ARG(plen
);
614 LWIP_UNUSED_ARG(printer
);
615 LWIP_UNUSED_ARG(arg
);
620 #endif /* PAP_SUPPORT */
622 #endif /* PPP_SUPPORT */