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 */
64 /***********************************/
65 /*** LOCAL FUNCTION DECLARATIONS ***/
66 /***********************************/
68 * Protocol entry points.
70 static void upap_init (int);
71 static void upap_lowerup (int);
72 static void upap_lowerdown (int);
73 static void upap_input (int, u_char
*, int);
74 static void upap_protrej (int);
76 static void upap_timeout (void *);
77 static void upap_reqtimeout(void *);
78 static void upap_rauthreq (upap_state
*, u_char
*, int, int);
79 static void upap_rauthack (upap_state
*, u_char
*, int, int);
80 static void upap_rauthnak (upap_state
*, u_char
*, int, int);
81 static void upap_sauthreq (upap_state
*);
82 static void upap_sresp (upap_state
*, u_char
, u_char
, char *, int);
85 /******************************/
86 /*** PUBLIC DATA STRUCTURES ***/
87 /******************************/
88 struct protent pap_protent
= {
110 upap_state upap
[NUM_PPP
]; /* UPAP state; one for each unit */
114 /***********************************/
115 /*** PUBLIC FUNCTION DEFINITIONS ***/
116 /***********************************/
118 * Set the default login name and password for the pap sessions
121 upap_setloginpasswd(int unit
, const char *luser
, const char *lpassword
)
123 upap_state
*u
= &upap
[unit
];
125 /* Save the username and password we're given */
127 u
->us_userlen
= strlen(luser
);
128 u
->us_passwd
= lpassword
;
129 u
->us_passwdlen
= strlen(lpassword
);
134 * upap_authwithpeer - Authenticate us with our peer (start client).
136 * Set new state and send authenticate's.
139 upap_authwithpeer(int unit
, char *user
, char *password
)
141 upap_state
*u
= &upap
[unit
];
143 UPAPDEBUG((LOG_INFO
, "upap_authwithpeer: %d user=%s password=%s s=%d\n",
144 unit
, user
, password
, u
->us_clientstate
));
146 upap_setloginpasswd(unit
, user
, password
);
150 /* Lower layer up yet? */
151 if (u
->us_clientstate
== UPAPCS_INITIAL
||
152 u
->us_clientstate
== UPAPCS_PENDING
) {
153 u
->us_clientstate
= UPAPCS_PENDING
;
157 upap_sauthreq(u
); /* Start protocol */
162 * upap_authpeer - Authenticate our peer (start server).
167 upap_authpeer(int unit
)
169 upap_state
*u
= &upap
[unit
];
171 /* Lower layer up yet? */
172 if (u
->us_serverstate
== UPAPSS_INITIAL
||
173 u
->us_serverstate
== UPAPSS_PENDING
) {
174 u
->us_serverstate
= UPAPSS_PENDING
;
178 u
->us_serverstate
= UPAPSS_LISTEN
;
179 if (u
->us_reqtimeout
> 0) {
180 TIMEOUT(upap_reqtimeout
, u
, u
->us_reqtimeout
);
186 /**********************************/
187 /*** LOCAL FUNCTION DEFINITIONS ***/
188 /**********************************/
190 * upap_init - Initialize a UPAP unit.
195 upap_state
*u
= &upap
[unit
];
197 UPAPDEBUG((LOG_INFO
, "upap_init: %d\n", unit
));
203 u
->us_clientstate
= UPAPCS_INITIAL
;
204 u
->us_serverstate
= UPAPSS_INITIAL
;
206 u
->us_timeouttime
= UPAP_DEFTIMEOUT
;
207 u
->us_maxtransmits
= 10;
208 u
->us_reqtimeout
= UPAP_DEFREQTIME
;
212 * upap_timeout - Retransmission timer for sending auth-reqs expired.
215 upap_timeout(void *arg
)
217 upap_state
*u
= (upap_state
*) arg
;
219 UPAPDEBUG((LOG_INFO
, "upap_timeout: %d timeout %d expired s=%d\n",
220 u
->us_unit
, u
->us_timeouttime
, u
->us_clientstate
));
222 if (u
->us_clientstate
!= UPAPCS_AUTHREQ
) {
226 if (u
->us_transmits
>= u
->us_maxtransmits
) {
227 /* give up in disgust */
228 UPAPDEBUG((LOG_ERR
, "No response to PAP authenticate-requests\n"));
229 u
->us_clientstate
= UPAPCS_BADAUTH
;
230 auth_withpeer_fail(u
->us_unit
, PPP_PAP
);
234 upap_sauthreq(u
); /* Send Authenticate-Request */
239 * upap_reqtimeout - Give up waiting for the peer to send an auth-req.
242 upap_reqtimeout(void *arg
)
244 upap_state
*u
= (upap_state
*) arg
;
246 if (u
->us_serverstate
!= UPAPSS_LISTEN
) {
250 auth_peer_fail(u
->us_unit
, PPP_PAP
);
251 u
->us_serverstate
= UPAPSS_BADAUTH
;
256 * upap_lowerup - The lower layer is up.
258 * Start authenticating if pending.
261 upap_lowerup(int unit
)
263 upap_state
*u
= &upap
[unit
];
265 UPAPDEBUG((LOG_INFO
, "upap_lowerup: %d s=%d\n", unit
, u
->us_clientstate
));
267 if (u
->us_clientstate
== UPAPCS_INITIAL
) {
268 u
->us_clientstate
= UPAPCS_CLOSED
;
269 } else if (u
->us_clientstate
== UPAPCS_PENDING
) {
270 upap_sauthreq(u
); /* send an auth-request */
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
< UPAP_HEADERLEN
) {
347 UPAPDEBUG((LOG_INFO
, "pap_input: rcvd short header.\n"));
353 if (len
< 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 */
386 * upap_rauth - Receive Authenticate.
389 upap_rauthreq(upap_state
*u
, u_char
*inp
, int id
, int len
)
391 u_char ruserlen
, rpasswdlen
;
392 char *ruser
, *rpasswd
;
397 UPAPDEBUG((LOG_INFO
, "pap_rauth: Rcvd id %d.\n", id
));
399 if (u
->us_serverstate
< UPAPSS_LISTEN
) {
404 * If we receive a duplicate authenticate-request, we are
405 * supposed to return the same status as for the first request.
407 if (u
->us_serverstate
== UPAPSS_OPEN
) {
408 upap_sresp(u
, UPAP_AUTHACK
, id
, "", 0); /* return auth-ack */
411 if (u
->us_serverstate
== UPAPSS_BADAUTH
) {
412 upap_sresp(u
, UPAP_AUTHNAK
, id
, "", 0); /* return auth-nak */
419 if (len
< sizeof (u_char
)) {
420 UPAPDEBUG((LOG_INFO
, "pap_rauth: rcvd short packet.\n"));
423 GETCHAR(ruserlen
, inp
);
424 len
-= sizeof (u_char
) + ruserlen
+ sizeof (u_char
);
426 UPAPDEBUG((LOG_INFO
, "pap_rauth: rcvd short packet.\n"));
429 ruser
= (char *) inp
;
430 INCPTR(ruserlen
, inp
);
431 GETCHAR(rpasswdlen
, inp
);
432 if (len
< rpasswdlen
) {
433 UPAPDEBUG((LOG_INFO
, "pap_rauth: rcvd short packet.\n"));
436 rpasswd
= (char *) inp
;
439 * Check the username and password given.
441 retcode
= check_passwd(u
->us_unit
, ruser
, ruserlen
, rpasswd
, rpasswdlen
, &msg
, &msglen
);
442 BZERO(rpasswd
, rpasswdlen
);
444 upap_sresp(u
, retcode
, id
, msg
, msglen
);
446 if (retcode
== UPAP_AUTHACK
) {
447 u
->us_serverstate
= UPAPSS_OPEN
;
448 auth_peer_success(u
->us_unit
, PPP_PAP
, ruser
, ruserlen
);
450 u
->us_serverstate
= UPAPSS_BADAUTH
;
451 auth_peer_fail(u
->us_unit
, PPP_PAP
);
454 if (u
->us_reqtimeout
> 0) {
455 UNTIMEOUT(upap_reqtimeout
, u
);
461 * upap_rauthack - Receive Authenticate-Ack.
464 upap_rauthack(upap_state
*u
, u_char
*inp
, int id
, int len
)
471 UPAPDEBUG((LOG_INFO
, "pap_rauthack: Rcvd id %d s=%d\n", id
, u
->us_clientstate
));
473 if (u
->us_clientstate
!= UPAPCS_AUTHREQ
) { /* XXX */
480 if (len
< sizeof (u_char
)) {
481 UPAPDEBUG((LOG_INFO
, "pap_rauthack: rcvd short packet.\n"));
484 GETCHAR(msglen
, inp
);
485 len
-= sizeof (u_char
);
487 UPAPDEBUG((LOG_INFO
, "pap_rauthack: rcvd short packet.\n"));
491 PRINTMSG(msg
, msglen
);
493 u
->us_clientstate
= UPAPCS_OPEN
;
495 auth_withpeer_success(u
->us_unit
, PPP_PAP
);
500 * upap_rauthnak - Receive Authenticate-Nakk.
503 upap_rauthnak(upap_state
*u
, u_char
*inp
, int id
, int len
)
510 UPAPDEBUG((LOG_INFO
, "pap_rauthnak: Rcvd id %d s=%d\n", id
, u
->us_clientstate
));
512 if (u
->us_clientstate
!= UPAPCS_AUTHREQ
) { /* XXX */
519 if (len
< sizeof (u_char
)) {
520 UPAPDEBUG((LOG_INFO
, "pap_rauthnak: rcvd short packet.\n"));
523 GETCHAR(msglen
, inp
);
524 len
-= sizeof (u_char
);
526 UPAPDEBUG((LOG_INFO
, "pap_rauthnak: rcvd short packet.\n"));
530 PRINTMSG(msg
, msglen
);
532 u
->us_clientstate
= UPAPCS_BADAUTH
;
534 UPAPDEBUG((LOG_ERR
, "PAP authentication failed\n"));
535 auth_withpeer_fail(u
->us_unit
, PPP_PAP
);
540 * upap_sauthreq - Send an Authenticate-Request.
543 upap_sauthreq(upap_state
*u
)
548 outlen
= UPAP_HEADERLEN
+ 2 * sizeof (u_char
)
549 + u
->us_userlen
+ u
->us_passwdlen
;
550 outp
= outpacket_buf
[u
->us_unit
];
552 MAKEHEADER(outp
, PPP_PAP
);
554 PUTCHAR(UPAP_AUTHREQ
, outp
);
555 PUTCHAR(++u
->us_id
, outp
);
556 PUTSHORT(outlen
, outp
);
557 PUTCHAR(u
->us_userlen
, outp
);
558 BCOPY(u
->us_user
, outp
, u
->us_userlen
);
559 INCPTR(u
->us_userlen
, outp
);
560 PUTCHAR(u
->us_passwdlen
, outp
);
561 BCOPY(u
->us_passwd
, outp
, u
->us_passwdlen
);
563 pppWrite(u
->us_unit
, outpacket_buf
[u
->us_unit
], outlen
+ PPP_HDRLEN
);
565 UPAPDEBUG((LOG_INFO
, "pap_sauth: Sent id %d\n", u
->us_id
));
567 TIMEOUT(upap_timeout
, u
, u
->us_timeouttime
);
569 u
->us_clientstate
= UPAPCS_AUTHREQ
;
574 * upap_sresp - Send a response (ack or nak).
577 upap_sresp(upap_state
*u
, u_char code
, u_char id
, char *msg
, int msglen
)
582 outlen
= UPAP_HEADERLEN
+ sizeof (u_char
) + msglen
;
583 outp
= outpacket_buf
[u
->us_unit
];
584 MAKEHEADER(outp
, PPP_PAP
);
588 PUTSHORT(outlen
, outp
);
589 PUTCHAR(msglen
, outp
);
590 BCOPY(msg
, outp
, msglen
);
591 pppWrite(u
->us_unit
, outpacket_buf
[u
->us_unit
], outlen
+ PPP_HDRLEN
);
593 UPAPDEBUG((LOG_INFO
, "pap_sresp: Sent code %d, id %d s=%d\n", code
, id
, u
->us_clientstate
));
598 * upap_printpkt - print the contents of a PAP packet.
600 static int upap_printpkt(
603 void (*printer
) (void *, char *, ...),
608 LWIP_UNUSED_ARG(plen
);
609 LWIP_UNUSED_ARG(printer
);
610 LWIP_UNUSED_ARG(arg
);
615 #endif /* PAP_SUPPORT */
617 #endif /* PPP_SUPPORT */