2 * upap.c - User/Password Authentication Protocol.
4 * Copyright (c) 1989 Carnegie Mellon University.
7 * Redistribution and use in source and binary forms are permitted
8 * provided that the above copyright notice and this paragraph are
9 * duplicated in all such forms and that any documentation,
10 * advertising materials, and other materials related to such
11 * distribution and use acknowledge that the software was developed
12 * by Carnegie Mellon University. The name of the
13 * University may not be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 #define RCSID "$Id: upap.c,v 1.4 2004/10/06 10:22:21 honor Exp $"
33 static const char rcsid
[] = RCSID
;
35 static bool hide_password
= 1;
38 * Command-line options.
40 static option_t pap_option_list
[] = {
41 { "hide-password", o_bool
, &hide_password
,
42 "Don't output passwords to log", OPT_PRIO
| 1 },
43 { "show-password", o_bool
, &hide_password
,
44 "Show password string in debug log messages", OPT_PRIOSUB
| 0 },
46 { "pap-restart", o_int
, &upap
[0].us_timeouttime
,
47 "Set retransmit timeout for PAP", OPT_PRIO
},
48 { "pap-max-authreq", o_int
, &upap
[0].us_maxtransmits
,
49 "Set max number of transmissions for auth-reqs", OPT_PRIO
},
50 { "pap-timeout", o_int
, &upap
[0].us_reqtimeout
,
51 "Set time limit for peer PAP authentication", OPT_PRIO
},
57 * Protocol entry points.
59 static void upap_init
__P((int));
60 static void upap_lowerup
__P((int));
61 static void upap_lowerdown
__P((int));
62 static void upap_input
__P((int, u_char
*, int));
63 static void upap_protrej
__P((int));
64 static int upap_printpkt
__P((u_char
*, int,
65 void (*) __P((void *, char *, ...)), void *));
67 struct protent pap_protent
= {
87 upap_state upap
[NUM_PPP
]; /* UPAP state; one for each unit */
89 static void upap_timeout
__P((void *));
90 static void upap_reqtimeout
__P((void *));
91 static void upap_rauthreq
__P((upap_state
*, u_char
*, int, int));
92 static void upap_rauthack
__P((upap_state
*, u_char
*, int, int));
93 static void upap_rauthnak
__P((upap_state
*, u_char
*, int, int));
94 static void upap_sauthreq
__P((upap_state
*));
95 static void upap_sresp
__P((upap_state
*, int, int, char *, int));
99 * upap_init - Initialize a UPAP unit.
105 upap_state
*u
= &upap
[unit
];
112 u
->us_clientstate
= UPAPCS_INITIAL
;
113 u
->us_serverstate
= UPAPSS_INITIAL
;
115 u
->us_timeouttime
= UPAP_DEFTIMEOUT
;
116 u
->us_maxtransmits
= 10;
117 u
->us_reqtimeout
= UPAP_DEFREQTIME
;
122 * upap_authwithpeer - Authenticate us with our peer (start client).
124 * Set new state and send authenticate's.
127 upap_authwithpeer(unit
, user
, password
)
129 char *user
, *password
;
131 upap_state
*u
= &upap
[unit
];
133 /* Save the username and password we're given */
135 u
->us_userlen
= strlen(user
);
136 u
->us_passwd
= password
;
137 u
->us_passwdlen
= strlen(password
);
140 /* Lower layer up yet? */
141 if (u
->us_clientstate
== UPAPCS_INITIAL
||
142 u
->us_clientstate
== UPAPCS_PENDING
) {
143 u
->us_clientstate
= UPAPCS_PENDING
;
147 upap_sauthreq(u
); /* Start protocol */
152 * upap_authpeer - Authenticate our peer (start server).
160 upap_state
*u
= &upap
[unit
];
162 /* Lower layer up yet? */
163 if (u
->us_serverstate
== UPAPSS_INITIAL
||
164 u
->us_serverstate
== UPAPSS_PENDING
) {
165 u
->us_serverstate
= UPAPSS_PENDING
;
169 u
->us_serverstate
= UPAPSS_LISTEN
;
170 if (u
->us_reqtimeout
> 0)
171 TIMEOUT(upap_reqtimeout
, u
, u
->us_reqtimeout
);
176 * upap_timeout - Retransmission timer for sending auth-reqs expired.
182 upap_state
*u
= (upap_state
*) arg
;
184 if (u
->us_clientstate
!= UPAPCS_AUTHREQ
)
187 if (u
->us_transmits
>= u
->us_maxtransmits
) {
188 /* give up in disgust */
190 LOGX_ERROR("No response from remote peer to PAP authenticate-requests.");
191 error("No response to PAP authenticate-requests");
193 u
->us_clientstate
= UPAPCS_BADAUTH
;
194 auth_withpeer_fail(u
->us_unit
, PPP_PAP
);
198 upap_sauthreq(u
); /* Send Authenticate-Request */
203 * upap_reqtimeout - Give up waiting for the peer to send an auth-req.
209 upap_state
*u
= (upap_state
*) arg
;
211 if (u
->us_serverstate
!= UPAPSS_LISTEN
)
214 auth_peer_fail(u
->us_unit
, PPP_PAP
);
215 u
->us_serverstate
= UPAPSS_BADAUTH
;
220 * upap_lowerup - The lower layer is up.
222 * Start authenticating if pending.
228 upap_state
*u
= &upap
[unit
];
230 if (u
->us_clientstate
== UPAPCS_INITIAL
)
231 u
->us_clientstate
= UPAPCS_CLOSED
;
232 else if (u
->us_clientstate
== UPAPCS_PENDING
) {
233 upap_sauthreq(u
); /* send an auth-request */
236 if (u
->us_serverstate
== UPAPSS_INITIAL
)
237 u
->us_serverstate
= UPAPSS_CLOSED
;
238 else if (u
->us_serverstate
== UPAPSS_PENDING
) {
239 u
->us_serverstate
= UPAPSS_LISTEN
;
240 if (u
->us_reqtimeout
> 0)
241 TIMEOUT(upap_reqtimeout
, u
, u
->us_reqtimeout
);
247 * upap_lowerdown - The lower layer is down.
249 * Cancel all timeouts.
255 upap_state
*u
= &upap
[unit
];
257 if (u
->us_clientstate
== UPAPCS_AUTHREQ
) /* Timeout pending? */
258 UNTIMEOUT(upap_timeout
, u
); /* Cancel timeout */
259 if (u
->us_serverstate
== UPAPSS_LISTEN
&& u
->us_reqtimeout
> 0)
260 UNTIMEOUT(upap_reqtimeout
, u
);
262 u
->us_clientstate
= UPAPCS_INITIAL
;
263 u
->us_serverstate
= UPAPSS_INITIAL
;
268 * upap_protrej - Peer doesn't speak this protocol.
270 * This shouldn't happen. In any case, pretend lower layer went down.
276 upap_state
*u
= &upap
[unit
];
278 if (u
->us_clientstate
== UPAPCS_AUTHREQ
) {
280 LOGX_ERROR("PAP authentication failed due to local protocol-reject.");
281 error("PAP authentication failed due to protocol-reject");
282 auth_withpeer_fail(unit
, PPP_PAP
);
284 if (u
->us_serverstate
== UPAPSS_LISTEN
) {
285 LOGX_ERROR("PAP authentication of remote peer failed (protocol-reject).");
286 error("PAP authentication of peer failed (protocol-reject)");
287 auth_peer_fail(unit
, PPP_PAP
);
289 upap_lowerdown(unit
);
294 * upap_input - Input UPAP packet.
297 upap_input(unit
, inpacket
, l
)
302 upap_state
*u
= &upap
[unit
];
308 * Parse header (code, id and length).
309 * If packet too short, drop it.
312 if (l
< UPAP_HEADERLEN
) {
313 UPAPDEBUG(("pap_input: rcvd short header."));
319 if (len
< UPAP_HEADERLEN
) {
320 UPAPDEBUG(("pap_input: rcvd illegal length."));
324 UPAPDEBUG(("pap_input: rcvd short packet."));
327 len
-= UPAP_HEADERLEN
;
330 * Action depends on code.
334 upap_rauthreq(u
, inp
, id
, len
);
338 upap_rauthack(u
, inp
, id
, len
);
342 upap_rauthnak(u
, inp
, id
, len
);
352 * upap_rauth - Receive Authenticate.
355 upap_rauthreq(u
, inp
, id
, len
)
361 u_char ruserlen
, rpasswdlen
;
362 char *ruser
, *rpasswd
;
367 if (u
->us_serverstate
< UPAPSS_LISTEN
)
370 LOGX_INFO("Received PAP Authenticate.");
372 * If we receive a duplicate authenticate-request, we are
373 * supposed to return the same status as for the first request.
375 if (u
->us_serverstate
== UPAPSS_OPEN
) {
376 upap_sresp(u
, UPAP_AUTHACK
, id
, "", 0); /* return auth-ack */
379 if (u
->us_serverstate
== UPAPSS_BADAUTH
) {
380 upap_sresp(u
, UPAP_AUTHNAK
, id
, "", 0); /* return auth-nak */
388 UPAPDEBUG(("pap_rauth: rcvd short packet."));
391 GETCHAR(ruserlen
, inp
);
392 len
-= sizeof (u_char
) + ruserlen
+ sizeof (u_char
);
394 UPAPDEBUG(("pap_rauth: rcvd short packet."));
397 ruser
= (char *) inp
;
398 INCPTR(ruserlen
, inp
);
399 GETCHAR(rpasswdlen
, inp
);
400 if (len
< rpasswdlen
) {
401 UPAPDEBUG(("pap_rauth: rcvd short packet."));
404 rpasswd
= (char *) inp
;
407 * Check the username and password given.
409 retcode
= check_passwd(u
->us_unit
, ruser
, ruserlen
, rpasswd
,
411 BZERO(rpasswd
, rpasswdlen
);
412 msglen
= strlen(msg
);
416 upap_sresp(u
, retcode
, id
, msg
, msglen
);
418 if (retcode
== UPAP_AUTHACK
) {
419 u
->us_serverstate
= UPAPSS_OPEN
;
420 auth_peer_success(u
->us_unit
, PPP_PAP
, ruser
, ruserlen
);
422 u
->us_serverstate
= UPAPSS_BADAUTH
;
423 auth_peer_fail(u
->us_unit
, PPP_PAP
);
426 if (u
->us_reqtimeout
> 0)
427 UNTIMEOUT(upap_reqtimeout
, u
);
432 * upap_rauthack - Receive Authenticate-Ack.
435 upap_rauthack(u
, inp
, id
, len
)
444 if (u
->us_clientstate
!= UPAPCS_AUTHREQ
)
451 UPAPDEBUG(("pap_rauthack: ignoring missing msg-length."));
453 GETCHAR(msglen
, inp
);
455 len
-= sizeof (u_char
);
457 UPAPDEBUG(("pap_rauthack: rcvd short packet."));
461 PRINTMSG(msg
, msglen
);
465 LOGX_INFO("PAP authentication succeeded.");
467 u
->us_clientstate
= UPAPCS_OPEN
;
469 auth_withpeer_success(u
->us_unit
, PPP_PAP
);
474 * upap_rauthnak - Receive Authenticate-Nakk.
477 upap_rauthnak(u
, inp
, id
, len
)
486 if (u
->us_clientstate
!= UPAPCS_AUTHREQ
)
493 UPAPDEBUG(("pap_rauthnak: ignoring missing msg-length."));
495 GETCHAR(msglen
, inp
);
497 len
-= sizeof (u_char
);
499 UPAPDEBUG(("pap_rauthnak: rcvd short packet."));
503 PRINTMSG(msg
, msglen
);
507 u
->us_clientstate
= UPAPCS_BADAUTH
;
509 LOGX_ERROR("PAP authentication failed.");
510 error("PAP authentication failed");
512 //log_to_file("PAP_AUTH_FAIL"); // add by honor
513 system("ppp_event -t PAP_AUTH_FAIL &");
515 auth_withpeer_fail(u
->us_unit
, PPP_PAP
);
520 * upap_sauthreq - Send an Authenticate-Request.
529 LOGX_INFO("Sending PAP Authenticate-Request.");
531 outlen
= UPAP_HEADERLEN
+ 2 * sizeof (u_char
) +
532 u
->us_userlen
+ u
->us_passwdlen
;
533 outp
= outpacket_buf
;
535 MAKEHEADER(outp
, PPP_PAP
);
537 PUTCHAR(UPAP_AUTHREQ
, outp
);
538 PUTCHAR(++u
->us_id
, outp
);
539 PUTSHORT(outlen
, outp
);
540 PUTCHAR(u
->us_userlen
, outp
);
541 BCOPY(u
->us_user
, outp
, u
->us_userlen
);
542 INCPTR(u
->us_userlen
, outp
);
543 PUTCHAR(u
->us_passwdlen
, outp
);
544 BCOPY(u
->us_passwd
, outp
, u
->us_passwdlen
);
546 output(u
->us_unit
, outpacket_buf
, outlen
+ PPP_HDRLEN
);
548 TIMEOUT(upap_timeout
, u
, u
->us_timeouttime
);
550 u
->us_clientstate
= UPAPCS_AUTHREQ
;
555 * upap_sresp - Send a response (ack or nak).
558 upap_sresp(u
, code
, id
, msg
, msglen
)
567 outlen
= UPAP_HEADERLEN
+ sizeof (u_char
) + msglen
;
568 outp
= outpacket_buf
;
569 MAKEHEADER(outp
, PPP_PAP
);
573 PUTSHORT(outlen
, outp
);
574 PUTCHAR(msglen
, outp
);
575 BCOPY(msg
, outp
, msglen
);
576 output(u
->us_unit
, outpacket_buf
, outlen
+ PPP_HDRLEN
);
580 * upap_printpkt - print the contents of a PAP packet.
582 static char *upap_codenames
[] = {
583 "AuthReq", "AuthAck", "AuthNak"
587 upap_printpkt(p
, plen
, printer
, arg
)
590 void (*printer
) __P((void *, char *, ...));
594 int mlen
, ulen
, wlen
;
595 char *user
, *pwd
, *msg
;
598 if (plen
< UPAP_HEADERLEN
)
604 if (len
< UPAP_HEADERLEN
|| len
> plen
)
607 if (code
>= 1 && code
<= sizeof(upap_codenames
) / sizeof(char *))
608 printer(arg
, " %s", upap_codenames
[code
-1]);
610 printer(arg
, " code=0x%x", code
);
611 printer(arg
, " id=0x%x", id
);
612 len
-= UPAP_HEADERLEN
;
621 if (len
< ulen
+ wlen
+ 2)
623 user
= (char *) (p
+ 1);
624 pwd
= (char *) (p
+ ulen
+ 2);
625 p
+= ulen
+ wlen
+ 2;
626 len
-= ulen
+ wlen
+ 2;
627 printer(arg
, " user=");
628 print_string(user
, ulen
, printer
, arg
);
629 printer(arg
, " password=");
631 print_string(pwd
, wlen
, printer
, arg
);
633 printer(arg
, "<hidden>");
642 msg
= (char *) (p
+ 1);
646 print_string(msg
, mlen
, printer
, arg
);
650 /* print the rest of the bytes in the packet */
651 for (; len
> 0; --len
) {
653 printer(arg
, " %.2x", code
);