| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628 |
- /*****************************************************************************
- * 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 "lwip/opt.h"
- #if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */
- #if PAP_SUPPORT /* don't build if not configured for use in lwipopts.h */
- #include "ppp_impl.h"
- #include "pppdebug.h"
- #include "auth.h"
- #include "pap.h"
- #include <string.h>
- #if 0 /* UNUSED */
- static bool hide_password = 1;
- /*
- * Command-line options.
- */
- static option_t pap_option_list[] = {
- { "hide-password", o_bool, &hide_password,
- "Don't output passwords to log", 1 },
- { "show-password", o_bool, &hide_password,
- "Show password string in debug log messages", 0 },
- { "pap-restart", o_int, &upap[0].us_timeouttime,
- "Set retransmit timeout for PAP" },
- { "pap-max-authreq", o_int, &upap[0].us_maxtransmits,
- "Set max number of transmissions for auth-reqs" },
- { "pap-timeout", o_int, &upap[0].us_reqtimeout,
- "Set time limit for peer PAP authentication" },
- { NULL }
- };
- #endif
- /*
- * 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);
- #if PPP_ADDITIONAL_CALLBACKS
- static int upap_printpkt (u_char *, int, void (*)(void *, char *, ...), void *);
- #endif /* PPP_ADDITIONAL_CALLBACKS */
- struct protent pap_protent = {
- PPP_PAP,
- upap_init,
- upap_input,
- upap_protrej,
- upap_lowerup,
- upap_lowerdown,
- NULL,
- NULL,
- #if PPP_ADDITIONAL_CALLBACKS
- upap_printpkt,
- NULL,
- #endif /* PPP_ADDITIONAL_CALLBACKS */
- 1,
- "PAP",
- #if PPP_ADDITIONAL_CALLBACKS
- NULL,
- NULL,
- NULL
- #endif /* PPP_ADDITIONAL_CALLBACKS */
- };
- upap_state upap[NUM_PPP]; /* UPAP state; one for each unit */
- static void upap_timeout (void *);
- static void upap_reqtimeout(void *);
- static void upap_rauthreq (upap_state *, u_char *, u_char, 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);
- /*
- * upap_init - Initialize a UPAP unit.
- */
- static void
- upap_init(int unit)
- {
- upap_state *u = &upap[unit];
- UPAPDEBUG(LOG_INFO, ("upap_init: %d\n", 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_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=%d\n",
- unit, user, password, u->us_clientstate));
- /* Save the username and password we're given */
- u->us_user = user;
- u->us_userlen = (int)strlen(user);
- u->us_passwd = password;
- u->us_passwdlen = (int)strlen(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);
- }
- }
- /*
- * upap_timeout - Retransmission timer for sending auth-reqs expired.
- */
- static void
- upap_timeout(void *arg)
- {
- upap_state *u = (upap_state *) arg;
- UPAPDEBUG(LOG_INFO, ("upap_timeout: %d timeout %d expired s=%d\n",
- u->us_unit, u->us_timeouttime, u->us_clientstate));
- if (u->us_clientstate != UPAPCS_AUTHREQ) {
- UPAPDEBUG(LOG_INFO, ("upap_timeout: not in AUTHREQ state!\n"));
- return;
- }
- if (u->us_transmits >= u->us_maxtransmits) {
- /* give up in disgust */
- UPAPDEBUG(LOG_ERR, ("No response to PAP authenticate-requests\n"));
- u->us_clientstate = UPAPCS_BADAUTH;
- auth_withpeer_fail(u->us_unit, PPP_PAP);
- return;
- }
- upap_sauthreq(u); /* Send Authenticate-Request and set upap timeout*/
- }
- /*
- * 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: init %d clientstate s=%d\n", 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 */
- /* now client state is UPAPCS__AUTHREQ */
- }
- 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=%d\n", 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-reject\n"));
- 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 < (int)UPAP_HEADERLEN) {
- UPAPDEBUG(LOG_INFO, ("pap_input: rcvd short header.\n"));
- return;
- }
- GETCHAR(code, inp);
- GETCHAR(id, inp);
- GETSHORT(len, inp);
- if (len < (int)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 */
- UPAPDEBUG(LOG_INFO, ("pap_input: UNHANDLED default: code: %d, id: %d, len: %d.\n", code, id, len));
- break;
- }
- }
- /*
- * upap_rauth - Receive Authenticate.
- */
- static void
- upap_rauthreq(upap_state *u, u_char *inp, u_char id, int len)
- {
- u_char ruserlen, rpasswdlen;
- char *ruser, *rpasswd;
- u_char 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 < (int)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);
- /* lwip: currently retcode is always UPAP_AUTHACK */
- 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;
- LWIP_UNUSED_ARG(id);
- UPAPDEBUG(LOG_INFO, ("pap_rauthack: Rcvd id %d s=%d\n", id, u->us_clientstate));
- if (u->us_clientstate != UPAPCS_AUTHREQ) { /* XXX */
- UPAPDEBUG(LOG_INFO, ("pap_rauthack: us_clientstate != UPAPCS_AUTHREQ\n"));
- return;
- }
- /*
- * Parse message.
- */
- if (len < (int)sizeof (u_char)) {
- UPAPDEBUG(LOG_INFO, ("pap_rauthack: ignoring missing msg-length.\n"));
- } else {
- GETCHAR(msglen, inp);
- if (msglen > 0) {
- len -= sizeof (u_char);
- if (len < msglen) {
- UPAPDEBUG(LOG_INFO, ("pap_rauthack: rcvd short packet.\n"));
- return;
- }
- msg = (char *) inp;
- PRINTMSG(msg, msglen);
- }
- }
- UNTIMEOUT(upap_timeout, u); /* Cancel timeout */
- u->us_clientstate = UPAPCS_OPEN;
- auth_withpeer_success(u->us_unit, PPP_PAP);
- }
- /*
- * upap_rauthnak - Receive Authenticate-Nak.
- */
- static void
- upap_rauthnak(upap_state *u, u_char *inp, int id, int len)
- {
- u_char msglen;
- char *msg;
- LWIP_UNUSED_ARG(id);
- UPAPDEBUG(LOG_INFO, ("pap_rauthnak: Rcvd id %d s=%d\n", id, u->us_clientstate));
- if (u->us_clientstate != UPAPCS_AUTHREQ) { /* XXX */
- return;
- }
- /*
- * Parse message.
- */
- if (len < sizeof (u_char)) {
- UPAPDEBUG(LOG_INFO, ("pap_rauthnak: ignoring missing msg-length.\n"));
- } else {
- GETCHAR(msglen, inp);
- if(msglen > 0) {
- 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 failed\n"));
- 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 %d\n", 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=%d\n", code, id, u->us_clientstate));
- }
- #if PPP_ADDITIONAL_CALLBACKS
- static char *upap_codenames[] = {
- "AuthReq", "AuthAck", "AuthNak"
- };
- /*
- * upap_printpkt - print the contents of a PAP packet.
- */
- static int upap_printpkt(
- u_char *p,
- int plen,
- void (*printer) (void *, char *, ...),
- void *arg
- )
- {
- LWIP_UNUSED_ARG(p);
- LWIP_UNUSED_ARG(plen);
- LWIP_UNUSED_ARG(printer);
- LWIP_UNUSED_ARG(arg);
- return 0;
- }
- #endif /* PPP_ADDITIONAL_CALLBACKS */
- #endif /* PAP_SUPPORT */
- #endif /* PPP_SUPPORT */
|