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