CPU: Wrong CPU Load %.
[tomato.git] / release / src / router / ppp / pppd / upap.c
blob6e963c00505629c80c5ebbb4a400db8741d672e7
1 /*
2 * upap.c - User/Password Authentication Protocol.
4 * Copyright (c) 1989 Carnegie Mellon University.
5 * All rights reserved.
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 $"
23 * TODO:
26 #include <stdio.h>
27 #include <string.h>
28 #include <stdlib.h>
30 #include <pppd.h>
31 #include "upap.h"
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 },
53 { NULL }
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 = {
68 PPP_PAP,
69 upap_init,
70 upap_input,
71 upap_protrej,
72 upap_lowerup,
73 upap_lowerdown,
74 NULL,
75 NULL,
76 upap_printpkt,
77 NULL,
79 "PAP",
80 NULL,
81 pap_option_list,
82 NULL,
83 NULL,
84 NULL
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.
101 static void
102 upap_init(unit)
103 int unit;
105 upap_state *u = &upap[unit];
107 u->us_unit = unit;
108 u->us_user = NULL;
109 u->us_userlen = 0;
110 u->us_passwd = NULL;
111 u->us_passwdlen = 0;
112 u->us_clientstate = UPAPCS_INITIAL;
113 u->us_serverstate = UPAPSS_INITIAL;
114 u->us_id = 0;
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.
126 void
127 upap_authwithpeer(unit, user, password)
128 int unit;
129 char *user, *password;
131 upap_state *u = &upap[unit];
133 /* Save the username and password we're given */
134 u->us_user = user;
135 u->us_userlen = strlen(user);
136 u->us_passwd = password;
137 u->us_passwdlen = strlen(password);
138 u->us_transmits = 0;
140 /* Lower layer up yet? */
141 if (u->us_clientstate == UPAPCS_INITIAL ||
142 u->us_clientstate == UPAPCS_PENDING) {
143 u->us_clientstate = UPAPCS_PENDING;
144 return;
147 upap_sauthreq(u); /* Start protocol */
152 * upap_authpeer - Authenticate our peer (start server).
154 * Set new state.
156 void
157 upap_authpeer(unit)
158 int unit;
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;
166 return;
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.
178 static void
179 upap_timeout(arg)
180 void *arg;
182 upap_state *u = (upap_state *) arg;
184 if (u->us_clientstate != UPAPCS_AUTHREQ)
185 return;
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);
195 return;
198 upap_sauthreq(u); /* Send Authenticate-Request */
203 * upap_reqtimeout - Give up waiting for the peer to send an auth-req.
205 static void
206 upap_reqtimeout(arg)
207 void *arg;
209 upap_state *u = (upap_state *) arg;
211 if (u->us_serverstate != UPAPSS_LISTEN)
212 return; /* huh?? */
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.
224 static void
225 upap_lowerup(unit)
226 int unit;
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.
251 static void
252 upap_lowerdown(unit)
253 int unit;
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.
272 static void
273 upap_protrej(unit)
274 int unit;
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.
296 static void
297 upap_input(unit, inpacket, l)
298 int unit;
299 u_char *inpacket;
300 int l;
302 upap_state *u = &upap[unit];
303 u_char *inp;
304 u_char code, id;
305 int len;
308 * Parse header (code, id and length).
309 * If packet too short, drop it.
311 inp = inpacket;
312 if (l < UPAP_HEADERLEN) {
313 UPAPDEBUG(("pap_input: rcvd short header."));
314 return;
316 GETCHAR(code, inp);
317 GETCHAR(id, inp);
318 GETSHORT(len, inp);
319 if (len < UPAP_HEADERLEN) {
320 UPAPDEBUG(("pap_input: rcvd illegal length."));
321 return;
323 if (len > l) {
324 UPAPDEBUG(("pap_input: rcvd short packet."));
325 return;
327 len -= UPAP_HEADERLEN;
330 * Action depends on code.
332 switch (code) {
333 case UPAP_AUTHREQ:
334 upap_rauthreq(u, inp, id, len);
335 break;
337 case UPAP_AUTHACK:
338 upap_rauthack(u, inp, id, len);
339 break;
341 case UPAP_AUTHNAK:
342 upap_rauthnak(u, inp, id, len);
343 break;
345 default:
346 break;
352 * upap_rauth - Receive Authenticate.
354 static void
355 upap_rauthreq(u, inp, id, len)
356 upap_state *u;
357 u_char *inp;
358 int id;
359 int len;
361 u_char ruserlen, rpasswdlen;
362 char *ruser, *rpasswd;
363 int retcode;
364 char *msg = "";
365 int msglen;
367 if (u->us_serverstate < UPAPSS_LISTEN)
368 return;
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 */
377 return;
379 if (u->us_serverstate == UPAPSS_BADAUTH) {
380 upap_sresp(u, UPAP_AUTHNAK, id, "", 0); /* return auth-nak */
381 return;
385 * Parse user/passwd.
387 if (len < 1) {
388 UPAPDEBUG(("pap_rauth: rcvd short packet."));
389 return;
391 GETCHAR(ruserlen, inp);
392 len -= sizeof (u_char) + ruserlen + sizeof (u_char);
393 if (len < 0) {
394 UPAPDEBUG(("pap_rauth: rcvd short packet."));
395 return;
397 ruser = (char *) inp;
398 INCPTR(ruserlen, inp);
399 GETCHAR(rpasswdlen, inp);
400 if (len < rpasswdlen) {
401 UPAPDEBUG(("pap_rauth: rcvd short packet."));
402 return;
404 rpasswd = (char *) inp;
407 * Check the username and password given.
409 retcode = check_passwd(u->us_unit, ruser, ruserlen, rpasswd,
410 rpasswdlen, &msg);
411 BZERO(rpasswd, rpasswdlen);
412 msglen = strlen(msg);
413 if (msglen > 255)
414 msglen = 255;
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);
421 } else {
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.
434 static void
435 upap_rauthack(u, inp, id, len)
436 upap_state *u;
437 u_char *inp;
438 int id;
439 int len;
441 u_char msglen;
442 char *msg;
444 if (u->us_clientstate != UPAPCS_AUTHREQ)
445 return;
448 * Parse message.
450 if (len < 1) {
451 UPAPDEBUG(("pap_rauthack: ignoring missing msg-length."));
452 } else {
453 GETCHAR(msglen, inp);
454 if (msglen > 0) {
455 len -= sizeof (u_char);
456 if (len < msglen) {
457 UPAPDEBUG(("pap_rauthack: rcvd short packet."));
458 return;
460 msg = (char *) inp;
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.
476 static void
477 upap_rauthnak(u, inp, id, len)
478 upap_state *u;
479 u_char *inp;
480 int id;
481 int len;
483 u_char msglen;
484 char *msg;
486 if (u->us_clientstate != UPAPCS_AUTHREQ)
487 return;
490 * Parse message.
492 if (len < 1) {
493 UPAPDEBUG(("pap_rauthnak: ignoring missing msg-length."));
494 } else {
495 GETCHAR(msglen, inp);
496 if (msglen > 0) {
497 len -= sizeof (u_char);
498 if (len < msglen) {
499 UPAPDEBUG(("pap_rauthnak: rcvd short packet."));
500 return;
502 msg = (char *) inp;
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.
522 static void
523 upap_sauthreq(u)
524 upap_state *u;
526 u_char *outp;
527 int outlen;
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);
549 ++u->us_transmits;
550 u->us_clientstate = UPAPCS_AUTHREQ;
555 * upap_sresp - Send a response (ack or nak).
557 static void
558 upap_sresp(u, code, id, msg, msglen)
559 upap_state *u;
560 u_char code, id;
561 char *msg;
562 int msglen;
564 u_char *outp;
565 int outlen;
567 outlen = UPAP_HEADERLEN + sizeof (u_char) + msglen;
568 outp = outpacket_buf;
569 MAKEHEADER(outp, PPP_PAP);
571 PUTCHAR(code, outp);
572 PUTCHAR(id, outp);
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"
586 static int
587 upap_printpkt(p, plen, printer, arg)
588 u_char *p;
589 int plen;
590 void (*printer) __P((void *, char *, ...));
591 void *arg;
593 int code, id, len;
594 int mlen, ulen, wlen;
595 char *user, *pwd, *msg;
596 u_char *pstart;
598 if (plen < UPAP_HEADERLEN)
599 return 0;
600 pstart = p;
601 GETCHAR(code, p);
602 GETCHAR(id, p);
603 GETSHORT(len, p);
604 if (len < UPAP_HEADERLEN || len > plen)
605 return 0;
607 if (code >= 1 && code <= sizeof(upap_codenames) / sizeof(char *))
608 printer(arg, " %s", upap_codenames[code-1]);
609 else
610 printer(arg, " code=0x%x", code);
611 printer(arg, " id=0x%x", id);
612 len -= UPAP_HEADERLEN;
613 switch (code) {
614 case UPAP_AUTHREQ:
615 if (len < 1)
616 break;
617 ulen = p[0];
618 if (len < ulen + 2)
619 break;
620 wlen = p[ulen + 1];
621 if (len < ulen + wlen + 2)
622 break;
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=");
630 if (!hide_password)
631 print_string(pwd, wlen, printer, arg);
632 else
633 printer(arg, "<hidden>");
634 break;
635 case UPAP_AUTHACK:
636 case UPAP_AUTHNAK:
637 if (len < 1)
638 break;
639 mlen = p[0];
640 if (len < mlen + 1)
641 break;
642 msg = (char *) (p + 1);
643 p += mlen + 1;
644 len -= mlen + 1;
645 printer(arg, " ");
646 print_string(msg, mlen, printer, arg);
647 break;
650 /* print the rest of the bytes in the packet */
651 for (; len > 0; --len) {
652 GETCHAR(code, p);
653 printer(arg, " %.2x", code);
656 return p - pstart;