pap.c
上传用户:yyhongfa
上传日期:2013-01-18
资源大小:267k
文件大小:14k
- /*****************************************************************************
- * pap.c - Network Password Authentication Protocol program file.
- *
- * Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
- * portions Copyright (c) 1997 by Global Election Systems Inc.
- *
- * The authors hereby grant permission to use, copy, modify, distribute,
- * and license this software and its documentation for any purpose, provided
- * that existing copyright notices are retained in all copies and that this
- * notice and the following disclaimer are included verbatim in any
- * distributions. No written agreement, license, or royalty fee is required
- * for any of the authorized uses.
- *
- * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- ******************************************************************************
- * REVISION HISTORY
- *
- * 03-01-01 Marc Boucher <marc@mbsi.ca>
- * Ported to lwIP.
- * 97-12-12 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
- * Original.
- *****************************************************************************/
- /*
- * upap.c - User/Password Authentication Protocol.
- *
- * Copyright (c) 1989 Carnegie Mellon University.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by Carnegie Mellon University. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
- #include "ppp.h"
- #include "auth.h"
- #include "pap.h"
- #include "pppdebug.h"
- #include "timer.h"
- #if PAP_SUPPORT > 0
- /***********************************/
- /*** LOCAL FUNCTION DECLARATIONS ***/
- /***********************************/
- /*
- * Protocol entry points.
- */
- static void upap_init (int);
- static void upap_lowerup (int);
- static void upap_lowerdown (int);
- static void upap_input (int, u_char *, int);
- static void upap_protrej (int);
- static void upap_timeout (void *);
- static void upap_reqtimeout (void *);
- static void upap_rauthreq (upap_state *, u_char *, int, int);
- static void upap_rauthack (upap_state *, u_char *, int, int);
- static void upap_rauthnak (upap_state *, u_char *, int, int);
- static void upap_sauthreq (upap_state *);
- static void upap_sresp (upap_state *, u_char, u_char, char *, int);
- /******************************/
- /*** PUBLIC DATA STRUCTURES ***/
- /******************************/
- struct protent pap_protent = {
- PPP_PAP,
- upap_init,
- upap_input,
- upap_protrej,
- upap_lowerup,
- upap_lowerdown,
- NULL,
- NULL,
- #if 0
- upap_printpkt,
- NULL,
- #endif
- 1,
- "PAP",
- #if 0
- NULL,
- NULL,
- NULL
- #endif
- };
- upap_state upap[NUM_PPP]; /* UPAP state; one for each unit */
- /***********************************/
- /*** PUBLIC FUNCTION DEFINITIONS ***/
- /***********************************/
- /*
- * Set the default login name and password for the pap sessions
- */
- void upap_setloginpasswd(int unit, const char *luser, const char *lpassword)
- {
- upap_state *u = &upap[unit];
-
- /* Save the username and password we're given */
- u->us_user = luser;
- u->us_userlen = strlen(luser);
- u->us_passwd = lpassword;
- u->us_passwdlen = strlen(lpassword);
- }
- /*
- * upap_authwithpeer - Authenticate us with our peer (start client).
- *
- * Set new state and send authenticate's.
- */
- void upap_authwithpeer(int unit, char *user, char *password)
- {
- upap_state *u = &upap[unit];
-
- UPAPDEBUG((LOG_INFO, "upap_authwithpeer: %d user=%s password=%s s=%dn",
- unit, user, password, u->us_clientstate));
-
- upap_setloginpasswd(unit, user, password);
- u->us_transmits = 0;
-
- /* Lower layer up yet? */
- if (u->us_clientstate == UPAPCS_INITIAL ||
- u->us_clientstate == UPAPCS_PENDING) {
- u->us_clientstate = UPAPCS_PENDING;
- return;
- }
-
- upap_sauthreq(u); /* Start protocol */
- }
- /*
- * upap_authpeer - Authenticate our peer (start server).
- *
- * Set new state.
- */
- void upap_authpeer(int unit)
- {
- upap_state *u = &upap[unit];
-
- /* Lower layer up yet? */
- if (u->us_serverstate == UPAPSS_INITIAL ||
- u->us_serverstate == UPAPSS_PENDING) {
- u->us_serverstate = UPAPSS_PENDING;
- return;
- }
-
- u->us_serverstate = UPAPSS_LISTEN;
- if (u->us_reqtimeout > 0)
- TIMEOUT(upap_reqtimeout, u, u->us_reqtimeout);
- }
- /**********************************/
- /*** LOCAL FUNCTION DEFINITIONS ***/
- /**********************************/
- /*
- * upap_init - Initialize a UPAP unit.
- */
- static void upap_init(int unit)
- {
- upap_state *u = &upap[unit];
- UPAPDEBUG((LOG_INFO, "upap_init: %dn", unit));
- u->us_unit = unit;
- u->us_user = NULL;
- u->us_userlen = 0;
- u->us_passwd = NULL;
- u->us_passwdlen = 0;
- u->us_clientstate = UPAPCS_INITIAL;
- u->us_serverstate = UPAPSS_INITIAL;
- u->us_id = 0;
- u->us_timeouttime = UPAP_DEFTIMEOUT;
- u->us_maxtransmits = 10;
- u->us_reqtimeout = UPAP_DEFREQTIME;
- }
- /*
- * upap_timeout - Retransmission timer for sending auth-reqs expired.
- */
- static void upap_timeout(void *arg)
- {
- upap_state *u = (upap_state *) arg;
- DEBUG_FUNCTION("upap_timeout()");
-
- UPAPDEBUG((LOG_INFO, "upap_timeout: %d timeout %d expired s=%dn",
- u->us_unit, u->us_timeouttime, u->us_clientstate));
-
- if (u->us_clientstate != UPAPCS_AUTHREQ)
- return;
-
- if (u->us_transmits >= u->us_maxtransmits) {
- /* give up in disgust */
- UPAPDEBUG((LOG_ERR, "No response to PAP authenticate-requestsn"));
- u->us_clientstate = UPAPCS_BADAUTH;
- auth_withpeer_fail(u->us_unit, PPP_PAP);
- return;
- }
-
- upap_sauthreq(u); /* Send Authenticate-Request */
- }
- /*
- * upap_reqtimeout - Give up waiting for the peer to send an auth-req.
- */
- static void upap_reqtimeout(void *arg)
- {
- upap_state *u = (upap_state *) arg;
-
- if (u->us_serverstate != UPAPSS_LISTEN)
- return; /* huh?? */
-
- auth_peer_fail(u->us_unit, PPP_PAP);
- u->us_serverstate = UPAPSS_BADAUTH;
- }
- /*
- * upap_lowerup - The lower layer is up.
- *
- * Start authenticating if pending.
- */
- static void upap_lowerup(int unit)
- {
- upap_state *u = &upap[unit];
-
- UPAPDEBUG((LOG_INFO, "upap_lowerup: %d s=%dn", unit, u->us_clientstate));
-
- if (u->us_clientstate == UPAPCS_INITIAL)
- u->us_clientstate = UPAPCS_CLOSED;
- else if (u->us_clientstate == UPAPCS_PENDING) {
- upap_sauthreq(u); /* send an auth-request */
- }
-
- if (u->us_serverstate == UPAPSS_INITIAL)
- u->us_serverstate = UPAPSS_CLOSED;
- else if (u->us_serverstate == UPAPSS_PENDING) {
- u->us_serverstate = UPAPSS_LISTEN;
- if (u->us_reqtimeout > 0)
- TIMEOUT(upap_reqtimeout, u, u->us_reqtimeout);
- }
- }
- /*
- * upap_lowerdown - The lower layer is down.
- *
- * Cancel all timeouts.
- */
- static void upap_lowerdown(int unit)
- {
- upap_state *u = &upap[unit];
-
- UPAPDEBUG((LOG_INFO, "upap_lowerdown: %d s=%dn", unit, u->us_clientstate));
-
- if (u->us_clientstate == UPAPCS_AUTHREQ) /* Timeout pending? */
- UNTIMEOUT(upap_timeout, u); /* Cancel timeout */
- if (u->us_serverstate == UPAPSS_LISTEN && u->us_reqtimeout > 0)
- UNTIMEOUT(upap_reqtimeout, u);
-
- u->us_clientstate = UPAPCS_INITIAL;
- u->us_serverstate = UPAPSS_INITIAL;
- }
- /*
- * upap_protrej - Peer doesn't speak this protocol.
- *
- * This shouldn't happen. In any case, pretend lower layer went down.
- */
- static void upap_protrej(int unit)
- {
- upap_state *u = &upap[unit];
-
- if (u->us_clientstate == UPAPCS_AUTHREQ) {
- UPAPDEBUG((LOG_ERR, "PAP authentication failed due to protocol-rejectn"));
- auth_withpeer_fail(unit, PPP_PAP);
- }
- if (u->us_serverstate == UPAPSS_LISTEN) {
- UPAPDEBUG((LOG_ERR, "PAP authentication of peer failed (protocol-reject)n"));
- auth_peer_fail(unit, PPP_PAP);
- }
- upap_lowerdown(unit);
- }
- /*
- * upap_input - Input UPAP packet.
- */
- static void upap_input(int unit, u_char *inpacket, int l)
- {
- upap_state *u = &upap[unit];
- u_char *inp;
- u_char code, id;
- int len;
-
- /*
- * Parse header (code, id and length).
- * If packet too short, drop it.
- */
- inp = inpacket;
- if (l < UPAP_HEADERLEN) {
- UPAPDEBUG((LOG_INFO, "pap_input: rcvd short header.n"));
- return;
- }
- GETCHAR(code, inp);
- GETCHAR(id, inp);
- GETSHORT(len, inp);
- if (len < UPAP_HEADERLEN) {
- UPAPDEBUG((LOG_INFO, "pap_input: rcvd illegal length.n"));
- return;
- }
- if (len > l) {
- UPAPDEBUG((LOG_INFO, "pap_input: rcvd short packet.n"));
- return;
- }
- len -= UPAP_HEADERLEN;
-
- /*
- * Action depends on code.
- */
- switch (code) {
- case UPAP_AUTHREQ:
- upap_rauthreq(u, inp, id, len);
- break;
-
- case UPAP_AUTHACK:
- upap_rauthack(u, inp, id, len);
- break;
-
- case UPAP_AUTHNAK:
- upap_rauthnak(u, inp, id, len);
- break;
-
- default: /* XXX Need code reject */
- break;
- }
- }
- /*
- * upap_rauth - Receive Authenticate.
- */
- static void upap_rauthreq(
- upap_state *u,
- u_char *inp,
- int id,
- int len
- )
- {
- u_char ruserlen, rpasswdlen;
- char *ruser, *rpasswd;
- int retcode;
- char *msg;
- int msglen;
-
- UPAPDEBUG((LOG_INFO, "pap_rauth: Rcvd id %d.n", id));
-
- if (u->us_serverstate < UPAPSS_LISTEN)
- return;
-
- /*
- * If we receive a duplicate authenticate-request, we are
- * supposed to return the same status as for the first request.
- */
- if (u->us_serverstate == UPAPSS_OPEN) {
- upap_sresp(u, UPAP_AUTHACK, id, "", 0); /* return auth-ack */
- return;
- }
- if (u->us_serverstate == UPAPSS_BADAUTH) {
- upap_sresp(u, UPAP_AUTHNAK, id, "", 0); /* return auth-nak */
- return;
- }
-
- /*
- * Parse user/passwd.
- */
- if (len < sizeof (u_char)) {
- UPAPDEBUG((LOG_INFO, "pap_rauth: rcvd short packet.n"));
- return;
- }
- GETCHAR(ruserlen, inp);
- len -= sizeof (u_char) + ruserlen + sizeof (u_char);
- if (len < 0) {
- UPAPDEBUG((LOG_INFO, "pap_rauth: rcvd short packet.n"));
- return;
- }
- ruser = (char *) inp;
- INCPTR(ruserlen, inp);
- GETCHAR(rpasswdlen, inp);
- if (len < rpasswdlen) {
- UPAPDEBUG((LOG_INFO, "pap_rauth: rcvd short packet.n"));
- return;
- }
- rpasswd = (char *) inp;
-
- /*
- * Check the username and password given.
- */
- retcode = check_passwd(u->us_unit, ruser, ruserlen, rpasswd,
- rpasswdlen, &msg, &msglen);
- BZERO(rpasswd, rpasswdlen);
-
- upap_sresp(u, retcode, id, msg, msglen);
-
- if (retcode == UPAP_AUTHACK) {
- u->us_serverstate = UPAPSS_OPEN;
- auth_peer_success(u->us_unit, PPP_PAP, ruser, ruserlen);
- } else {
- u->us_serverstate = UPAPSS_BADAUTH;
- auth_peer_fail(u->us_unit, PPP_PAP);
- }
-
- if (u->us_reqtimeout > 0)
- UNTIMEOUT(upap_reqtimeout, u);
- }
- /*
- * upap_rauthack - Receive Authenticate-Ack.
- */
- static void upap_rauthack(
- upap_state *u,
- u_char *inp,
- int id,
- int len
- )
- {
- u_char msglen;
- char *msg;
-
- UPAPDEBUG((LOG_INFO, "pap_rauthack: Rcvd id %d s=%dn", id, u->us_clientstate));
-
- if (u->us_clientstate != UPAPCS_AUTHREQ) /* XXX */
- return;
-
- /*
- * Parse message.
- */
- if (len < sizeof (u_char)) {
- UPAPDEBUG((LOG_INFO, "pap_rauthack: rcvd short packet.n"));
- return;
- }
- GETCHAR(msglen, inp);
- len -= sizeof (u_char);
- if (len < msglen) {
- UPAPDEBUG((LOG_INFO, "pap_rauthack: rcvd short packet.n"));
- return;
- }
- msg = (char *) inp;
- PRINTMSG(msg, msglen);
-
- u->us_clientstate = UPAPCS_OPEN;
- /*
- *New added by zhouzhigang 2006.01.22
- */
- UNTIMEOUT(upap_timeout, u);
-
- auth_withpeer_success(u->us_unit, PPP_PAP);
- }
- /*
- * upap_rauthnak - Receive Authenticate-Nakk.
- */
- static void upap_rauthnak(
- upap_state *u,
- u_char *inp,
- int id,
- int len
- )
- {
- u_char msglen;
- char *msg;
-
- UPAPDEBUG((LOG_INFO, "pap_rauthnak: Rcvd id %d s=%dn", id, u->us_clientstate));
-
- if (u->us_clientstate != UPAPCS_AUTHREQ) /* XXX */
- return;
-
- /*
- * Parse message.
- */
- if (len < sizeof (u_char)) {
- UPAPDEBUG((LOG_INFO, "pap_rauthnak: rcvd short packet.n"));
- return;
- }
- GETCHAR(msglen, inp);
- len -= sizeof (u_char);
- if (len < msglen) {
- UPAPDEBUG((LOG_INFO, "pap_rauthnak: rcvd short packet.n"));
- return;
- }
- msg = (char *) inp;
- PRINTMSG(msg, msglen);
-
- u->us_clientstate = UPAPCS_BADAUTH;
-
- UPAPDEBUG((LOG_ERR, "PAP authentication failedn"));
- auth_withpeer_fail(u->us_unit, PPP_PAP);
- }
- /*
- * upap_sauthreq - Send an Authenticate-Request.
- */
- static void upap_sauthreq(upap_state *u)
- {
- u_char *outp;
- int outlen;
-
- outlen = UPAP_HEADERLEN + 2 * sizeof (u_char)
- + u->us_userlen + u->us_passwdlen;
- outp = outpacket_buf[u->us_unit];
-
- MAKEHEADER(outp, PPP_PAP);
-
- PUTCHAR(UPAP_AUTHREQ, outp);
- PUTCHAR(++u->us_id, outp);
- PUTSHORT(outlen, outp);
- PUTCHAR(u->us_userlen, outp);
- BCOPY(u->us_user, outp, u->us_userlen);
- INCPTR(u->us_userlen, outp);
- PUTCHAR(u->us_passwdlen, outp);
- BCOPY(u->us_passwd, outp, u->us_passwdlen);
-
- pppWrite(u->us_unit, outpacket_buf[u->us_unit], outlen + PPP_HDRLEN);
-
- UPAPDEBUG((LOG_INFO, "pap_sauth: Sent id %dn", u->us_id));
-
- TIMEOUT(upap_timeout, u, u->us_timeouttime);
- ++u->us_transmits;
- u->us_clientstate = UPAPCS_AUTHREQ;
- }
- /*
- * upap_sresp - Send a response (ack or nak).
- */
- static void upap_sresp(
- upap_state *u,
- u_char code,
- u_char id,
- char *msg,
- int msglen
- )
- {
- u_char *outp;
- int outlen;
-
- outlen = UPAP_HEADERLEN + sizeof (u_char) + msglen;
- outp = outpacket_buf[u->us_unit];
- MAKEHEADER(outp, PPP_PAP);
-
- PUTCHAR(code, outp);
- PUTCHAR(id, outp);
- PUTSHORT(outlen, outp);
- PUTCHAR(msglen, outp);
- BCOPY(msg, outp, msglen);
- pppWrite(u->us_unit, outpacket_buf[u->us_unit], outlen + PPP_HDRLEN);
-
- UPAPDEBUG((LOG_INFO, "pap_sresp: Sent code %d, id %d s=%dn",
- code, id, u->us_clientstate));
- }
- #if 0
- /*
- * upap_printpkt - print the contents of a PAP packet.
- */
- static int upap_printpkt(
- u_char *p,
- int plen,
- void (*printer) (void *, char *, ...),
- void *arg
- )
- {
- (void)p;
- (void)plen;
- (void)printer;
- (void)arg;
- return 0;
- }
- #endif
- #endif /* PAP_SUPPORT */