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 */