]> Joshua Wise's Git repositories - netwatch.git/blame - lwip/src/netif/ppp/pap.c
Don't necessarily wait for data.
[netwatch.git] / lwip / src / netif / ppp / pap.c
CommitLineData
6e6d4a8b
JP
1/*****************************************************************************
2* pap.c - Network Password Authentication Protocol program file.
3*
4* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
5* portions Copyright (c) 1997 by Global Election Systems Inc.
6*
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.
13*
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.
24*
25******************************************************************************
26* REVISION HISTORY
27*
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*****************************************************************************/
33/*
34 * upap.c - User/Password Authentication Protocol.
35 *
36 * Copyright (c) 1989 Carnegie Mellon University.
37 * All rights reserved.
38 *
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.
50 */
51
52#include "lwip/opt.h"
53
54#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */
55
56#if PAP_SUPPORT /* don't build if not configured for use in lwipopts.h */
57
58#include "ppp.h"
59#include "pppdebug.h"
60
61#include "auth.h"
62#include "pap.h"
63
64/***********************************/
65/*** LOCAL FUNCTION DECLARATIONS ***/
66/***********************************/
67/*
68 * Protocol entry points.
69 */
70static void upap_init (int);
71static void upap_lowerup (int);
72static void upap_lowerdown (int);
73static void upap_input (int, u_char *, int);
74static void upap_protrej (int);
75
76static void upap_timeout (void *);
77static void upap_reqtimeout(void *);
78static void upap_rauthreq (upap_state *, u_char *, int, int);
79static void upap_rauthack (upap_state *, u_char *, int, int);
80static void upap_rauthnak (upap_state *, u_char *, int, int);
81static void upap_sauthreq (upap_state *);
82static void upap_sresp (upap_state *, u_char, u_char, char *, int);
83
84
85/******************************/
86/*** PUBLIC DATA STRUCTURES ***/
87/******************************/
88struct protent pap_protent = {
89 PPP_PAP,
90 upap_init,
91 upap_input,
92 upap_protrej,
93 upap_lowerup,
94 upap_lowerdown,
95 NULL,
96 NULL,
97#if 0
98 upap_printpkt,
99 NULL,
100#endif
101 1,
102 "PAP",
103#if 0
104 NULL,
105 NULL,
106 NULL
107#endif
108};
109
110upap_state upap[NUM_PPP]; /* UPAP state; one for each unit */
111
112
113
114/***********************************/
115/*** PUBLIC FUNCTION DEFINITIONS ***/
116/***********************************/
117/*
118 * Set the default login name and password for the pap sessions
119 */
120void
121upap_setloginpasswd(int unit, const char *luser, const char *lpassword)
122{
123 upap_state *u = &upap[unit];
124
125 /* Save the username and password we're given */
126 u->us_user = luser;
127 u->us_userlen = strlen(luser);
128 u->us_passwd = lpassword;
129 u->us_passwdlen = strlen(lpassword);
130}
131
132
133/*
134 * upap_authwithpeer - Authenticate us with our peer (start client).
135 *
136 * Set new state and send authenticate's.
137 */
138void
139upap_authwithpeer(int unit, char *user, char *password)
140{
141 upap_state *u = &upap[unit];
142
143 UPAPDEBUG((LOG_INFO, "upap_authwithpeer: %d user=%s password=%s s=%d\n",
144 unit, user, password, u->us_clientstate));
145
146 upap_setloginpasswd(unit, user, password);
147
148 u->us_transmits = 0;
149
150 /* Lower layer up yet? */
151 if (u->us_clientstate == UPAPCS_INITIAL ||
152 u->us_clientstate == UPAPCS_PENDING) {
153 u->us_clientstate = UPAPCS_PENDING;
154 return;
155 }
156
157 upap_sauthreq(u); /* Start protocol */
158}
159
160
161/*
162 * upap_authpeer - Authenticate our peer (start server).
163 *
164 * Set new state.
165 */
166void
167upap_authpeer(int unit)
168{
169 upap_state *u = &upap[unit];
170
171 /* Lower layer up yet? */
172 if (u->us_serverstate == UPAPSS_INITIAL ||
173 u->us_serverstate == UPAPSS_PENDING) {
174 u->us_serverstate = UPAPSS_PENDING;
175 return;
176 }
177
178 u->us_serverstate = UPAPSS_LISTEN;
179 if (u->us_reqtimeout > 0) {
180 TIMEOUT(upap_reqtimeout, u, u->us_reqtimeout);
181 }
182}
183
184
185
186/**********************************/
187/*** LOCAL FUNCTION DEFINITIONS ***/
188/**********************************/
189/*
190 * upap_init - Initialize a UPAP unit.
191 */
192static void
193upap_init(int unit)
194{
195 upap_state *u = &upap[unit];
196
197 UPAPDEBUG((LOG_INFO, "upap_init: %d\n", unit));
198 u->us_unit = unit;
199 u->us_user = NULL;
200 u->us_userlen = 0;
201 u->us_passwd = NULL;
202 u->us_passwdlen = 0;
203 u->us_clientstate = UPAPCS_INITIAL;
204 u->us_serverstate = UPAPSS_INITIAL;
205 u->us_id = 0;
206 u->us_timeouttime = UPAP_DEFTIMEOUT;
207 u->us_maxtransmits = 10;
208 u->us_reqtimeout = UPAP_DEFREQTIME;
209}
210
211/*
212 * upap_timeout - Retransmission timer for sending auth-reqs expired.
213 */
214static void
215upap_timeout(void *arg)
216{
217 upap_state *u = (upap_state *) arg;
218
219 UPAPDEBUG((LOG_INFO, "upap_timeout: %d timeout %d expired s=%d\n",
220 u->us_unit, u->us_timeouttime, u->us_clientstate));
221
222 if (u->us_clientstate != UPAPCS_AUTHREQ) {
223 return;
224 }
225
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);
231 return;
232 }
233
234 upap_sauthreq(u); /* Send Authenticate-Request */
235}
236
237
238/*
239 * upap_reqtimeout - Give up waiting for the peer to send an auth-req.
240 */
241static void
242upap_reqtimeout(void *arg)
243{
244 upap_state *u = (upap_state *) arg;
245
246 if (u->us_serverstate != UPAPSS_LISTEN) {
247 return; /* huh?? */
248 }
249
250 auth_peer_fail(u->us_unit, PPP_PAP);
251 u->us_serverstate = UPAPSS_BADAUTH;
252}
253
254
255/*
256 * upap_lowerup - The lower layer is up.
257 *
258 * Start authenticating if pending.
259 */
260static void
261upap_lowerup(int unit)
262{
263 upap_state *u = &upap[unit];
264
265 UPAPDEBUG((LOG_INFO, "upap_lowerup: %d s=%d\n", unit, u->us_clientstate));
266
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 */
271 }
272
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);
279 }
280 }
281}
282
283
284/*
285 * upap_lowerdown - The lower layer is down.
286 *
287 * Cancel all timeouts.
288 */
289static void
290upap_lowerdown(int unit)
291{
292 upap_state *u = &upap[unit];
293
294 UPAPDEBUG((LOG_INFO, "upap_lowerdown: %d s=%d\n", unit, u->us_clientstate));
295
296 if (u->us_clientstate == UPAPCS_AUTHREQ) { /* Timeout pending? */
297 UNTIMEOUT(upap_timeout, u); /* Cancel timeout */
298 }
299 if (u->us_serverstate == UPAPSS_LISTEN && u->us_reqtimeout > 0) {
300 UNTIMEOUT(upap_reqtimeout, u);
301 }
302
303 u->us_clientstate = UPAPCS_INITIAL;
304 u->us_serverstate = UPAPSS_INITIAL;
305}
306
307
308/*
309 * upap_protrej - Peer doesn't speak this protocol.
310 *
311 * This shouldn't happen. In any case, pretend lower layer went down.
312 */
313static void
314upap_protrej(int unit)
315{
316 upap_state *u = &upap[unit];
317
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);
321 }
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);
325 }
326 upap_lowerdown(unit);
327}
328
329
330/*
331 * upap_input - Input UPAP packet.
332 */
333static void
334upap_input(int unit, u_char *inpacket, int l)
335{
336 upap_state *u = &upap[unit];
337 u_char *inp;
338 u_char code, id;
339 int len;
340
341 /*
342 * Parse header (code, id and length).
343 * If packet too short, drop it.
344 */
345 inp = inpacket;
346 if (l < UPAP_HEADERLEN) {
347 UPAPDEBUG((LOG_INFO, "pap_input: rcvd short header.\n"));
348 return;
349 }
350 GETCHAR(code, inp);
351 GETCHAR(id, inp);
352 GETSHORT(len, inp);
353 if (len < UPAP_HEADERLEN) {
354 UPAPDEBUG((LOG_INFO, "pap_input: rcvd illegal length.\n"));
355 return;
356 }
357 if (len > l) {
358 UPAPDEBUG((LOG_INFO, "pap_input: rcvd short packet.\n"));
359 return;
360 }
361 len -= UPAP_HEADERLEN;
362
363 /*
364 * Action depends on code.
365 */
366 switch (code) {
367 case UPAP_AUTHREQ:
368 upap_rauthreq(u, inp, id, len);
369 break;
370
371 case UPAP_AUTHACK:
372 upap_rauthack(u, inp, id, len);
373 break;
374
375 case UPAP_AUTHNAK:
376 upap_rauthnak(u, inp, id, len);
377 break;
378
379 default: /* XXX Need code reject */
380 break;
381 }
382}
383
384
385/*
386 * upap_rauth - Receive Authenticate.
387 */
388static void
389upap_rauthreq(upap_state *u, u_char *inp, int id, int len)
390{
391 u_char ruserlen, rpasswdlen;
392 char *ruser, *rpasswd;
393 int retcode;
394 char *msg;
395 int msglen;
396
397 UPAPDEBUG((LOG_INFO, "pap_rauth: Rcvd id %d.\n", id));
398
399 if (u->us_serverstate < UPAPSS_LISTEN) {
400 return;
401 }
402
403 /*
404 * If we receive a duplicate authenticate-request, we are
405 * supposed to return the same status as for the first request.
406 */
407 if (u->us_serverstate == UPAPSS_OPEN) {
408 upap_sresp(u, UPAP_AUTHACK, id, "", 0); /* return auth-ack */
409 return;
410 }
411 if (u->us_serverstate == UPAPSS_BADAUTH) {
412 upap_sresp(u, UPAP_AUTHNAK, id, "", 0); /* return auth-nak */
413 return;
414 }
415
416 /*
417 * Parse user/passwd.
418 */
419 if (len < sizeof (u_char)) {
420 UPAPDEBUG((LOG_INFO, "pap_rauth: rcvd short packet.\n"));
421 return;
422 }
423 GETCHAR(ruserlen, inp);
424 len -= sizeof (u_char) + ruserlen + sizeof (u_char);
425 if (len < 0) {
426 UPAPDEBUG((LOG_INFO, "pap_rauth: rcvd short packet.\n"));
427 return;
428 }
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"));
434 return;
435 }
436 rpasswd = (char *) inp;
437
438 /*
439 * Check the username and password given.
440 */
441 retcode = check_passwd(u->us_unit, ruser, ruserlen, rpasswd, rpasswdlen, &msg, &msglen);
442 BZERO(rpasswd, rpasswdlen);
443
444 upap_sresp(u, retcode, id, msg, msglen);
445
446 if (retcode == UPAP_AUTHACK) {
447 u->us_serverstate = UPAPSS_OPEN;
448 auth_peer_success(u->us_unit, PPP_PAP, ruser, ruserlen);
449 } else {
450 u->us_serverstate = UPAPSS_BADAUTH;
451 auth_peer_fail(u->us_unit, PPP_PAP);
452 }
453
454 if (u->us_reqtimeout > 0) {
455 UNTIMEOUT(upap_reqtimeout, u);
456 }
457}
458
459
460/*
461 * upap_rauthack - Receive Authenticate-Ack.
462 */
463static void
464upap_rauthack(upap_state *u, u_char *inp, int id, int len)
465{
466 u_char msglen;
467 char *msg;
468
469 LWIP_UNUSED_ARG(id);
470
471 UPAPDEBUG((LOG_INFO, "pap_rauthack: Rcvd id %d s=%d\n", id, u->us_clientstate));
472
473 if (u->us_clientstate != UPAPCS_AUTHREQ) { /* XXX */
474 return;
475 }
476
477 /*
478 * Parse message.
479 */
480 if (len < sizeof (u_char)) {
481 UPAPDEBUG((LOG_INFO, "pap_rauthack: rcvd short packet.\n"));
482 return;
483 }
484 GETCHAR(msglen, inp);
485 len -= sizeof (u_char);
486 if (len < msglen) {
487 UPAPDEBUG((LOG_INFO, "pap_rauthack: rcvd short packet.\n"));
488 return;
489 }
490 msg = (char *) inp;
491 PRINTMSG(msg, msglen);
492
493 u->us_clientstate = UPAPCS_OPEN;
494
495 auth_withpeer_success(u->us_unit, PPP_PAP);
496}
497
498
499/*
500 * upap_rauthnak - Receive Authenticate-Nakk.
501 */
502static void
503upap_rauthnak(upap_state *u, u_char *inp, int id, int len)
504{
505 u_char msglen;
506 char *msg;
507
508 LWIP_UNUSED_ARG(id);
509
510 UPAPDEBUG((LOG_INFO, "pap_rauthnak: Rcvd id %d s=%d\n", id, u->us_clientstate));
511
512 if (u->us_clientstate != UPAPCS_AUTHREQ) { /* XXX */
513 return;
514 }
515
516 /*
517 * Parse message.
518 */
519 if (len < sizeof (u_char)) {
520 UPAPDEBUG((LOG_INFO, "pap_rauthnak: rcvd short packet.\n"));
521 return;
522 }
523 GETCHAR(msglen, inp);
524 len -= sizeof (u_char);
525 if (len < msglen) {
526 UPAPDEBUG((LOG_INFO, "pap_rauthnak: rcvd short packet.\n"));
527 return;
528 }
529 msg = (char *) inp;
530 PRINTMSG(msg, msglen);
531
532 u->us_clientstate = UPAPCS_BADAUTH;
533
534 UPAPDEBUG((LOG_ERR, "PAP authentication failed\n"));
535 auth_withpeer_fail(u->us_unit, PPP_PAP);
536}
537
538
539/*
540 * upap_sauthreq - Send an Authenticate-Request.
541 */
542static void
543upap_sauthreq(upap_state *u)
544{
545 u_char *outp;
546 int outlen;
547
548 outlen = UPAP_HEADERLEN + 2 * sizeof (u_char)
549 + u->us_userlen + u->us_passwdlen;
550 outp = outpacket_buf[u->us_unit];
551
552 MAKEHEADER(outp, PPP_PAP);
553
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);
562
563 pppWrite(u->us_unit, outpacket_buf[u->us_unit], outlen + PPP_HDRLEN);
564
565 UPAPDEBUG((LOG_INFO, "pap_sauth: Sent id %d\n", u->us_id));
566
567 TIMEOUT(upap_timeout, u, u->us_timeouttime);
568 ++u->us_transmits;
569 u->us_clientstate = UPAPCS_AUTHREQ;
570}
571
572
573/*
574 * upap_sresp - Send a response (ack or nak).
575 */
576static void
577upap_sresp(upap_state *u, u_char code, u_char id, char *msg, int msglen)
578{
579 u_char *outp;
580 int outlen;
581
582 outlen = UPAP_HEADERLEN + sizeof (u_char) + msglen;
583 outp = outpacket_buf[u->us_unit];
584 MAKEHEADER(outp, PPP_PAP);
585
586 PUTCHAR(code, outp);
587 PUTCHAR(id, outp);
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);
592
593 UPAPDEBUG((LOG_INFO, "pap_sresp: Sent code %d, id %d s=%d\n", code, id, u->us_clientstate));
594}
595
596#if 0
597/*
598 * upap_printpkt - print the contents of a PAP packet.
599 */
600static int upap_printpkt(
601 u_char *p,
602 int plen,
603 void (*printer) (void *, char *, ...),
604 void *arg
605)
606{
607 LWIP_UNUSED_ARG(p);
608 LWIP_UNUSED_ARG(plen);
609 LWIP_UNUSED_ARG(printer);
610 LWIP_UNUSED_ARG(arg);
611 return 0;
612}
613#endif /* 0 */
614
615#endif /* PAP_SUPPORT */
616
617#endif /* PPP_SUPPORT */
This page took 0.073284 seconds and 4 git commands to generate.