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.
60 /***********************************/
61 /*** LOCAL FUNCTION DECLARATIONS ***/
62 /***********************************/
64 * Protocol entry points.
66 static void upap_init (int);
67 static void upap_lowerup (int);
68 static void upap_lowerdown (int);
69 static void upap_input (int, u_char
*, int);
70 static void upap_protrej (int);
72 static void upap_timeout (void *);
73 static void upap_reqtimeout (void *);
74 static void upap_rauthreq (upap_state
*, u_char
*, int, int);
75 static void upap_rauthack (upap_state
*, u_char
*, int, int);
76 static void upap_rauthnak (upap_state
*, u_char
*, int, int);
77 static void upap_sauthreq (upap_state
*);
78 static void upap_sresp (upap_state
*, u_char
, u_char
, char *, int);
83 /******************************/
84 /*** PUBLIC DATA STRUCTURES ***/
85 /******************************/
86 struct protent pap_protent
= {
108 upap_state upap
[NUM_PPP
]; /* UPAP state; one for each unit */
112 /***********************************/
113 /*** PUBLIC FUNCTION DEFINITIONS ***/
114 /***********************************/
116 * Set the default login name and password for the pap sessions
118 void upap_setloginpasswd(int unit
, const char *luser
, const char *lpassword
)
120 upap_state
*u
= &upap
[unit
];
122 /* Save the username and password we're given */
124 u
->us_userlen
= strlen(luser
);
125 u
->us_passwd
= lpassword
;
126 u
->us_passwdlen
= strlen(lpassword
);
131 * upap_authwithpeer - Authenticate us with our peer (start client).
133 * Set new state and send authenticate's.
135 void upap_authwithpeer(int unit
, char *user
, char *password
)
137 upap_state
*u
= &upap
[unit
];
139 UPAPDEBUG((LOG_INFO
, "upap_authwithpeer: %d user=%s password=%s s=%d\n",
140 unit
, user
, password
, u
->us_clientstate
));
142 upap_setloginpasswd(unit
, user
, password
);
146 /* Lower layer up yet? */
147 if (u
->us_clientstate
== UPAPCS_INITIAL
||
148 u
->us_clientstate
== UPAPCS_PENDING
) {
149 u
->us_clientstate
= UPAPCS_PENDING
;
153 upap_sauthreq(u
); /* Start protocol */
158 * upap_authpeer - Authenticate our peer (start server).
162 void upap_authpeer(int unit
)
164 upap_state
*u
= &upap
[unit
];
166 /* Lower layer up yet? */
167 if (u
->us_serverstate
== UPAPSS_INITIAL
||
168 u
->us_serverstate
== UPAPSS_PENDING
) {
169 u
->us_serverstate
= UPAPSS_PENDING
;
173 u
->us_serverstate
= UPAPSS_LISTEN
;
174 if (u
->us_reqtimeout
> 0)
175 TIMEOUT(upap_reqtimeout
, u
, u
->us_reqtimeout
);
180 /**********************************/
181 /*** LOCAL FUNCTION DEFINITIONS ***/
182 /**********************************/
184 * upap_init - Initialize a UPAP unit.
186 static void upap_init(int unit
)
188 upap_state
*u
= &upap
[unit
];
190 UPAPDEBUG((LOG_INFO
, "upap_init: %d\n", unit
));
196 u
->us_clientstate
= UPAPCS_INITIAL
;
197 u
->us_serverstate
= UPAPSS_INITIAL
;
199 u
->us_timeouttime
= UPAP_DEFTIMEOUT
;
200 u
->us_maxtransmits
= 10;
201 u
->us_reqtimeout
= UPAP_DEFREQTIME
;
205 * upap_timeout - Retransmission timer for sending auth-reqs expired.
207 static void upap_timeout(void *arg
)
209 upap_state
*u
= (upap_state
*) arg
;
211 UPAPDEBUG((LOG_INFO
, "upap_timeout: %d timeout %d expired s=%d\n",
212 u
->us_unit
, u
->us_timeouttime
, u
->us_clientstate
));
214 if (u
->us_clientstate
!= UPAPCS_AUTHREQ
)
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
);
225 upap_sauthreq(u
); /* Send Authenticate-Request */
230 * upap_reqtimeout - Give up waiting for the peer to send an auth-req.
232 static void upap_reqtimeout(void *arg
)
234 upap_state
*u
= (upap_state
*) arg
;
236 if (u
->us_serverstate
!= UPAPSS_LISTEN
)
239 auth_peer_fail(u
->us_unit
, PPP_PAP
);
240 u
->us_serverstate
= UPAPSS_BADAUTH
;
245 * upap_lowerup - The lower layer is up.
247 * Start authenticating if pending.
249 static void upap_lowerup(int unit
)
251 upap_state
*u
= &upap
[unit
];
253 UPAPDEBUG((LOG_INFO
, "upap_lowerup: %d s=%d\n", unit
, u
->us_clientstate
));
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 */
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
);
272 * upap_lowerdown - The lower layer is down.
274 * Cancel all timeouts.
276 static void upap_lowerdown(int unit
)
278 upap_state
*u
= &upap
[unit
];
280 UPAPDEBUG((LOG_INFO
, "upap_lowerdown: %d s=%d\n", unit
, u
->us_clientstate
));
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
);
287 u
->us_clientstate
= UPAPCS_INITIAL
;
288 u
->us_serverstate
= UPAPSS_INITIAL
;
293 * upap_protrej - Peer doesn't speak this protocol.
295 * This shouldn't happen. In any case, pretend lower layer went down.
297 static void upap_protrej(int unit
)
299 upap_state
*u
= &upap
[unit
];
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
);
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
);
309 upap_lowerdown(unit
);
314 * upap_input - Input UPAP packet.
316 static void upap_input(int unit
, u_char
*inpacket
, int l
)
318 upap_state
*u
= &upap
[unit
];
324 * Parse header (code, id and length).
325 * If packet too short, drop it.
328 if (l
< UPAP_HEADERLEN
) {
329 UPAPDEBUG((LOG_INFO
, "pap_input: rcvd short header.\n"));
335 if (len
< UPAP_HEADERLEN
) {
336 UPAPDEBUG((LOG_INFO
, "pap_input: rcvd illegal length.\n"));
340 UPAPDEBUG((LOG_INFO
, "pap_input: rcvd short packet.\n"));
343 len
-= UPAP_HEADERLEN
;
346 * Action depends on code.
350 upap_rauthreq(u
, inp
, id
, len
);
354 upap_rauthack(u
, inp
, id
, len
);
358 upap_rauthnak(u
, inp
, id
, len
);
361 default: /* XXX Need code reject */
368 * upap_rauth - Receive Authenticate.
370 static void upap_rauthreq(
377 u_char ruserlen
, rpasswdlen
;
378 char *ruser
, *rpasswd
;
383 UPAPDEBUG((LOG_INFO
, "pap_rauth: Rcvd id %d.\n", id
));
385 if (u
->us_serverstate
< UPAPSS_LISTEN
)
389 * If we receive a duplicate authenticate-request, we are
390 * supposed to return the same status as for the first request.
392 if (u
->us_serverstate
== UPAPSS_OPEN
) {
393 upap_sresp(u
, UPAP_AUTHACK
, id
, "", 0); /* return auth-ack */
396 if (u
->us_serverstate
== UPAPSS_BADAUTH
) {
397 upap_sresp(u
, UPAP_AUTHNAK
, id
, "", 0); /* return auth-nak */
404 if (len
< sizeof (u_char
)) {
405 UPAPDEBUG((LOG_INFO
, "pap_rauth: rcvd short packet.\n"));
408 GETCHAR(ruserlen
, inp
);
409 len
-= sizeof (u_char
) + ruserlen
+ sizeof (u_char
);
411 UPAPDEBUG((LOG_INFO
, "pap_rauth: rcvd short packet.\n"));
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"));
421 rpasswd
= (char *) inp
;
424 * Check the username and password given.
426 retcode
= check_passwd(u
->us_unit
, ruser
, ruserlen
, rpasswd
,
427 rpasswdlen
, &msg
, &msglen
);
428 BZERO(rpasswd
, rpasswdlen
);
430 upap_sresp(u
, retcode
, id
, msg
, msglen
);
432 if (retcode
== UPAP_AUTHACK
) {
433 u
->us_serverstate
= UPAPSS_OPEN
;
434 auth_peer_success(u
->us_unit
, PPP_PAP
, ruser
, ruserlen
);
436 u
->us_serverstate
= UPAPSS_BADAUTH
;
437 auth_peer_fail(u
->us_unit
, PPP_PAP
);
440 if (u
->us_reqtimeout
> 0)
441 UNTIMEOUT(upap_reqtimeout
, u
);
446 * upap_rauthack - Receive Authenticate-Ack.
448 static void upap_rauthack(
458 UPAPDEBUG((LOG_INFO
, "pap_rauthack: Rcvd id %d s=%d\n", id
, u
->us_clientstate
));
460 if (u
->us_clientstate
!= UPAPCS_AUTHREQ
) /* XXX */
466 if (len
< sizeof (u_char
)) {
467 UPAPDEBUG((LOG_INFO
, "pap_rauthack: rcvd short packet.\n"));
470 GETCHAR(msglen
, inp
);
471 len
-= sizeof (u_char
);
473 UPAPDEBUG((LOG_INFO
, "pap_rauthack: rcvd short packet.\n"));
477 PRINTMSG(msg
, msglen
);
479 u
->us_clientstate
= UPAPCS_OPEN
;
481 auth_withpeer_success(u
->us_unit
, PPP_PAP
);
486 * upap_rauthnak - Receive Authenticate-Nakk.
488 static void upap_rauthnak(
498 UPAPDEBUG((LOG_INFO
, "pap_rauthnak: Rcvd id %d s=%d\n", id
, u
->us_clientstate
));
500 if (u
->us_clientstate
!= UPAPCS_AUTHREQ
) /* XXX */
506 if (len
< sizeof (u_char
)) {
507 UPAPDEBUG((LOG_INFO
, "pap_rauthnak: rcvd short packet.\n"));
510 GETCHAR(msglen
, inp
);
511 len
-= sizeof (u_char
);
513 UPAPDEBUG((LOG_INFO
, "pap_rauthnak: rcvd short packet.\n"));
517 PRINTMSG(msg
, msglen
);
519 u
->us_clientstate
= UPAPCS_BADAUTH
;
521 UPAPDEBUG((LOG_ERR
, "PAP authentication failed\n"));
522 auth_withpeer_fail(u
->us_unit
, PPP_PAP
);
527 * upap_sauthreq - Send an Authenticate-Request.
529 static void upap_sauthreq(upap_state
*u
)
534 outlen
= UPAP_HEADERLEN
+ 2 * sizeof (u_char
)
535 + u
->us_userlen
+ u
->us_passwdlen
;
536 outp
= outpacket_buf
[u
->us_unit
];
538 MAKEHEADER(outp
, PPP_PAP
);
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
);
549 pppWrite(u
->us_unit
, outpacket_buf
[u
->us_unit
], outlen
+ PPP_HDRLEN
);
551 UPAPDEBUG((LOG_INFO
, "pap_sauth: Sent id %d\n", u
->us_id
));
553 TIMEOUT(upap_timeout
, u
, u
->us_timeouttime
);
555 u
->us_clientstate
= UPAPCS_AUTHREQ
;
560 * upap_sresp - Send a response (ack or nak).
562 static void upap_sresp(
573 outlen
= UPAP_HEADERLEN
+ sizeof (u_char
) + msglen
;
574 outp
= outpacket_buf
[u
->us_unit
];
575 MAKEHEADER(outp
, PPP_PAP
);
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
);
584 UPAPDEBUG((LOG_INFO
, "pap_sresp: Sent code %d, id %d s=%d\n",
585 code
, id
, u
->us_clientstate
));
590 * upap_printpkt - print the contents of a PAP packet.
592 static int upap_printpkt(
595 void (*printer
) (void *, char *, ...),
607 #endif /* PAP_SUPPORT */