FreeRTOS
[armadillo_firmware.git] / FreeRTOS / Common / ethernet / lwIP_132 / src / netif / ppp / pap.c
blobe8c45dff9c92b96236d3528bf28d7d0000dbe8dd
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 ******************************************************************************
26 * REVISION HISTORY
28 * 03-01-01 Marc Boucher <marc@mbsi.ca>
29 * Ported to lwIP.
30 * 97-12-12 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
31 * Original.
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.
52 #include "lwip/opt.h"
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 */
58 #include "ppp.h"
59 #include "pppdebug.h"
61 #include "auth.h"
62 #include "pap.h"
64 #include <string.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 = {
91 PPP_PAP,
92 upap_init,
93 upap_input,
94 upap_protrej,
95 upap_lowerup,
96 upap_lowerdown,
97 NULL,
98 NULL,
99 #if 0
100 upap_printpkt,
101 NULL,
102 #endif
104 "PAP",
105 #if 0
106 NULL,
107 NULL,
108 NULL
109 #endif
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
122 void
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 */
128 u->us_user = luser;
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.
140 void
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);
150 u->us_transmits = 0;
152 /* Lower layer up yet? */
153 if (u->us_clientstate == UPAPCS_INITIAL ||
154 u->us_clientstate == UPAPCS_PENDING) {
155 u->us_clientstate = UPAPCS_PENDING;
156 return;
159 upap_sauthreq(u); /* Start protocol */
164 * upap_authpeer - Authenticate our peer (start server).
166 * Set new state.
168 void
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;
177 return;
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.
194 static void
195 upap_init(int unit)
197 upap_state *u = &upap[unit];
199 UPAPDEBUG((LOG_INFO, "upap_init: %d\n", unit));
200 u->us_unit = unit;
201 u->us_user = NULL;
202 u->us_userlen = 0;
203 u->us_passwd = NULL;
204 u->us_passwdlen = 0;
205 u->us_clientstate = UPAPCS_INITIAL;
206 u->us_serverstate = UPAPSS_INITIAL;
207 u->us_id = 0;
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.
216 static void
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) {
225 return;
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);
233 return;
236 upap_sauthreq(u); /* Send Authenticate-Request */
241 * upap_reqtimeout - Give up waiting for the peer to send an auth-req.
243 static void
244 upap_reqtimeout(void *arg)
246 upap_state *u = (upap_state *) arg;
248 if (u->us_serverstate != UPAPSS_LISTEN) {
249 return; /* huh?? */
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.
262 static void
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.
291 static void
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.
315 static void
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.
335 static void
336 upap_input(int unit, u_char *inpacket, int l)
338 upap_state *u = &upap[unit];
339 u_char *inp;
340 u_char code, id;
341 int len;
344 * Parse header (code, id and length).
345 * If packet too short, drop it.
347 inp = inpacket;
348 if (l < UPAP_HEADERLEN) {
349 UPAPDEBUG((LOG_INFO, "pap_input: rcvd short header.\n"));
350 return;
352 GETCHAR(code, inp);
353 GETCHAR(id, inp);
354 GETSHORT(len, inp);
355 if (len < UPAP_HEADERLEN) {
356 UPAPDEBUG((LOG_INFO, "pap_input: rcvd illegal length.\n"));
357 return;
359 if (len > l) {
360 UPAPDEBUG((LOG_INFO, "pap_input: rcvd short packet.\n"));
361 return;
363 len -= UPAP_HEADERLEN;
366 * Action depends on code.
368 switch (code) {
369 case UPAP_AUTHREQ:
370 upap_rauthreq(u, inp, id, len);
371 break;
373 case UPAP_AUTHACK:
374 upap_rauthack(u, inp, id, len);
375 break;
377 case UPAP_AUTHNAK:
378 upap_rauthnak(u, inp, id, len);
379 break;
381 default: /* XXX Need code reject */
382 break;
388 * upap_rauth - Receive Authenticate.
390 static void
391 upap_rauthreq(upap_state *u, u_char *inp, int id, int len)
393 u_char ruserlen, rpasswdlen;
394 char *ruser, *rpasswd;
395 int retcode;
396 char *msg;
397 int msglen;
399 UPAPDEBUG((LOG_INFO, "pap_rauth: Rcvd id %d.\n", id));
401 if (u->us_serverstate < UPAPSS_LISTEN) {
402 return;
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 */
411 return;
413 if (u->us_serverstate == UPAPSS_BADAUTH) {
414 upap_sresp(u, UPAP_AUTHNAK, id, "", 0); /* return auth-nak */
415 return;
419 * Parse user/passwd.
421 if (len < sizeof (u_char)) {
422 UPAPDEBUG((LOG_INFO, "pap_rauth: rcvd short packet.\n"));
423 return;
425 GETCHAR(ruserlen, inp);
426 len -= sizeof (u_char) + ruserlen + sizeof (u_char);
427 if (len < 0) {
428 UPAPDEBUG((LOG_INFO, "pap_rauth: rcvd short packet.\n"));
429 return;
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"));
436 return;
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);
451 } else {
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.
465 static void
466 upap_rauthack(upap_state *u, u_char *inp, int id, int len)
468 u_char msglen;
469 char *msg;
471 LWIP_UNUSED_ARG(id);
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 return;
480 * Parse message.
482 if (len < sizeof (u_char)) {
483 UPAPDEBUG((LOG_INFO, "pap_rauthack: rcvd short packet.\n"));
484 return;
486 GETCHAR(msglen, inp);
487 len -= sizeof (u_char);
488 if (len < msglen) {
489 UPAPDEBUG((LOG_INFO, "pap_rauthack: rcvd short packet.\n"));
490 return;
492 msg = (char *) inp;
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.
505 static void
506 upap_rauthnak(upap_state *u, u_char *inp, int id, int len)
508 u_char msglen;
509 char *msg;
511 LWIP_UNUSED_ARG(id);
513 UPAPDEBUG((LOG_INFO, "pap_rauthnak: Rcvd id %d s=%d\n", id, u->us_clientstate));
515 if (u->us_clientstate != UPAPCS_AUTHREQ) { /* XXX */
516 return;
520 * Parse message.
522 if (len < sizeof (u_char)) {
523 UPAPDEBUG((LOG_INFO, "pap_rauthnak: rcvd short packet.\n"));
524 } else {
525 GETCHAR(msglen, inp);
526 if(msglen > 0) {
527 len -= sizeof (u_char);
528 if (len < msglen) {
529 UPAPDEBUG((LOG_INFO, "pap_rauthnak: rcvd short packet.\n"));
530 return;
532 msg = (char *) inp;
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.
547 static void
548 upap_sauthreq(upap_state *u)
550 u_char *outp;
551 int outlen;
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);
573 ++u->us_transmits;
574 u->us_clientstate = UPAPCS_AUTHREQ;
579 * upap_sresp - Send a response (ack or nak).
581 static void
582 upap_sresp(upap_state *u, u_char code, u_char id, char *msg, int msglen)
584 u_char *outp;
585 int outlen;
587 outlen = UPAP_HEADERLEN + sizeof (u_char) + msglen;
588 outp = outpacket_buf[u->us_unit];
589 MAKEHEADER(outp, PPP_PAP);
591 PUTCHAR(code, outp);
592 PUTCHAR(id, outp);
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));
601 #if 0
603 * upap_printpkt - print the contents of a PAP packet.
605 static int upap_printpkt(
606 u_char *p,
607 int plen,
608 void (*printer) (void *, char *, ...),
609 void *arg
612 LWIP_UNUSED_ARG(p);
613 LWIP_UNUSED_ARG(plen);
614 LWIP_UNUSED_ARG(printer);
615 LWIP_UNUSED_ARG(arg);
616 return 0;
618 #endif /* 0 */
620 #endif /* PAP_SUPPORT */
622 #endif /* PPP_SUPPORT */