SAMV71 Xplained Ultra Software Package 1.5

pap.c

00001 /*****************************************************************************
00002 * pap.c - Network Password Authentication Protocol program file.
00003 *
00004 * Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
00005 * portions Copyright (c) 1997 by Global Election Systems Inc.
00006 *
00007 * The authors hereby grant permission to use, copy, modify, distribute,
00008 * and license this software and its documentation for any purpose, provided
00009 * that existing copyright notices are retained in all copies and that this
00010 * notice and the following disclaimer are included verbatim in any 
00011 * distributions. No written agreement, license, or royalty fee is required
00012 * for any of the authorized uses.
00013 *
00014 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
00015 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00016 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
00017 * IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00018 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00019 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00020 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00021 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00022 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00023 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00024 *
00025 ******************************************************************************
00026 * REVISION HISTORY
00027 *
00028 * 03-01-01 Marc Boucher <marc@mbsi.ca>
00029 *   Ported to lwIP.
00030 * 97-12-12 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
00031 *   Original.
00032 *****************************************************************************/
00033 /*
00034  * upap.c - User/Password Authentication Protocol.
00035  *
00036  * Copyright (c) 1989 Carnegie Mellon University.
00037  * All rights reserved.
00038  *
00039  * Redistribution and use in source and binary forms are permitted
00040  * provided that the above copyright notice and this paragraph are
00041  * duplicated in all such forms and that any documentation,
00042  * advertising materials, and other materials related to such
00043  * distribution and use acknowledge that the software was developed
00044  * by Carnegie Mellon University.  The name of the
00045  * University may not be used to endorse or promote products derived
00046  * from this software without specific prior written permission.
00047  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
00048  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
00049  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00050  */
00051 
00052 #include "lwip/opt.h"
00053 
00054 #if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */
00055 
00056 #if PAP_SUPPORT /* don't build if not configured for use in lwipopts.h */
00057 
00058 #include "ppp.h"
00059 #include "pppdebug.h"
00060 
00061 #include "auth.h"
00062 #include "pap.h"
00063 
00064 #include <string.h>
00065 
00066 /***********************************/
00067 /*** LOCAL FUNCTION DECLARATIONS ***/
00068 /***********************************/
00069 /*
00070  * Protocol entry points.
00071  */
00072 static void upap_init      (int);
00073 static void upap_lowerup   (int);
00074 static void upap_lowerdown (int);
00075 static void upap_input     (int, u_char *, int);
00076 static void upap_protrej   (int);
00077 
00078 static void upap_timeout   (void *);
00079 static void upap_reqtimeout(void *);
00080 static void upap_rauthreq  (upap_state *, u_char *, int, int);
00081 static void upap_rauthack  (upap_state *, u_char *, int, int);
00082 static void upap_rauthnak  (upap_state *, u_char *, int, int);
00083 static void upap_sauthreq  (upap_state *);
00084 static void upap_sresp     (upap_state *, u_char, u_char, char *, int);
00085 
00086 
00087 /******************************/
00088 /*** PUBLIC DATA STRUCTURES ***/
00089 /******************************/
00090 struct protent pap_protent = {
00091   PPP_PAP,
00092   upap_init,
00093   upap_input,
00094   upap_protrej,
00095   upap_lowerup,
00096   upap_lowerdown,
00097   NULL,
00098   NULL,
00099 #if 0
00100   upap_printpkt,
00101   NULL,
00102 #endif
00103   1,
00104   "PAP",
00105 #if 0
00106   NULL,
00107   NULL,
00108   NULL
00109 #endif
00110 };
00111 
00112 upap_state upap[NUM_PPP]; /* UPAP state; one for each unit */
00113 
00114 
00115 
00116 /***********************************/
00117 /*** PUBLIC FUNCTION DEFINITIONS ***/
00118 /***********************************/
00119 /*
00120  *  Set the default login name and password for the pap sessions
00121  */
00122 void
00123 upap_setloginpasswd(int unit, const char *luser, const char *lpassword)
00124 {
00125   upap_state *u = &upap[unit];
00126   
00127   /* Save the username and password we're given */
00128   u->us_user = luser;
00129   u->us_userlen = strlen(luser);
00130   u->us_passwd = lpassword;
00131   u->us_passwdlen = strlen(lpassword);
00132 }
00133 
00134 
00135 /*
00136  * upap_authwithpeer - Authenticate us with our peer (start client).
00137  *
00138  * Set new state and send authenticate's.
00139  */
00140 void
00141 upap_authwithpeer(int unit, char *user, char *password)
00142 {
00143   upap_state *u = &upap[unit];
00144 
00145   UPAPDEBUG((LOG_INFO, "upap_authwithpeer: %d user=%s password=%s s=%d\n",
00146              unit, user, password, u->us_clientstate));
00147 
00148   upap_setloginpasswd(unit, user, password);
00149 
00150   u->us_transmits = 0;
00151 
00152   /* Lower layer up yet? */
00153   if (u->us_clientstate == UPAPCS_INITIAL ||
00154       u->us_clientstate == UPAPCS_PENDING) {
00155     u->us_clientstate = UPAPCS_PENDING;
00156     return;
00157   }
00158 
00159   upap_sauthreq(u);      /* Start protocol */
00160 }
00161 
00162 
00163 /*
00164  * upap_authpeer - Authenticate our peer (start server).
00165  *
00166  * Set new state.
00167  */
00168 void
00169 upap_authpeer(int unit)
00170 {
00171   upap_state *u = &upap[unit];
00172 
00173   /* Lower layer up yet? */
00174   if (u->us_serverstate == UPAPSS_INITIAL ||
00175       u->us_serverstate == UPAPSS_PENDING) {
00176     u->us_serverstate = UPAPSS_PENDING;
00177     return;
00178   }
00179 
00180   u->us_serverstate = UPAPSS_LISTEN;
00181   if (u->us_reqtimeout > 0) {
00182     TIMEOUT(upap_reqtimeout, u, u->us_reqtimeout);
00183   }
00184 }
00185 
00186 
00187 
00188 /**********************************/
00189 /*** LOCAL FUNCTION DEFINITIONS ***/
00190 /**********************************/
00191 /*
00192  * upap_init - Initialize a UPAP unit.
00193  */
00194 static void
00195 upap_init(int unit)
00196 {
00197   upap_state *u = &upap[unit];
00198 
00199   UPAPDEBUG((LOG_INFO, "upap_init: %d\n", unit));
00200   u->us_unit         = unit;
00201   u->us_user         = NULL;
00202   u->us_userlen      = 0;
00203   u->us_passwd       = NULL;
00204   u->us_passwdlen    = 0;
00205   u->us_clientstate  = UPAPCS_INITIAL;
00206   u->us_serverstate  = UPAPSS_INITIAL;
00207   u->us_id           = 0;
00208   u->us_timeouttime  = UPAP_DEFTIMEOUT;
00209   u->us_maxtransmits = 10;
00210   u->us_reqtimeout   = UPAP_DEFREQTIME;
00211 }
00212 
00213 /*
00214  * upap_timeout - Retransmission timer for sending auth-reqs expired.
00215  */
00216 static void
00217 upap_timeout(void *arg)
00218 {
00219   upap_state *u = (upap_state *) arg;
00220 
00221   UPAPDEBUG((LOG_INFO, "upap_timeout: %d timeout %d expired s=%d\n", 
00222         u->us_unit, u->us_timeouttime, u->us_clientstate));
00223 
00224   if (u->us_clientstate != UPAPCS_AUTHREQ) {
00225     return;
00226   }
00227 
00228   if (u->us_transmits >= u->us_maxtransmits) {
00229     /* give up in disgust */
00230     UPAPDEBUG((LOG_ERR, "No response to PAP authenticate-requests\n"));
00231     u->us_clientstate = UPAPCS_BADAUTH;
00232     auth_withpeer_fail(u->us_unit, PPP_PAP);
00233     return;
00234   }
00235 
00236   upap_sauthreq(u);    /* Send Authenticate-Request */
00237 }
00238 
00239 
00240 /*
00241  * upap_reqtimeout - Give up waiting for the peer to send an auth-req.
00242  */
00243 static void
00244 upap_reqtimeout(void *arg)
00245 {
00246   upap_state *u = (upap_state *) arg;
00247 
00248   if (u->us_serverstate != UPAPSS_LISTEN) {
00249     return; /* huh?? */
00250   }
00251 
00252   auth_peer_fail(u->us_unit, PPP_PAP);
00253   u->us_serverstate = UPAPSS_BADAUTH;
00254 }
00255 
00256 
00257 /*
00258  * upap_lowerup - The lower layer is up.
00259  *
00260  * Start authenticating if pending.
00261  */
00262 static void
00263 upap_lowerup(int unit)
00264 {
00265   upap_state *u = &upap[unit];
00266 
00267   UPAPDEBUG((LOG_INFO, "upap_lowerup: %d s=%d\n", unit, u->us_clientstate));
00268 
00269   if (u->us_clientstate == UPAPCS_INITIAL) {
00270     u->us_clientstate = UPAPCS_CLOSED;
00271   } else if (u->us_clientstate == UPAPCS_PENDING) {
00272     upap_sauthreq(u);  /* send an auth-request */
00273   }
00274 
00275   if (u->us_serverstate == UPAPSS_INITIAL) {
00276     u->us_serverstate = UPAPSS_CLOSED;
00277   } else if (u->us_serverstate == UPAPSS_PENDING) {
00278     u->us_serverstate = UPAPSS_LISTEN;
00279     if (u->us_reqtimeout > 0) {
00280       TIMEOUT(upap_reqtimeout, u, u->us_reqtimeout);
00281     }
00282   }
00283 }
00284 
00285 
00286 /*
00287  * upap_lowerdown - The lower layer is down.
00288  *
00289  * Cancel all timeouts.
00290  */
00291 static void
00292 upap_lowerdown(int unit)
00293 {
00294   upap_state *u = &upap[unit];
00295 
00296   UPAPDEBUG((LOG_INFO, "upap_lowerdown: %d s=%d\n", unit, u->us_clientstate));
00297 
00298   if (u->us_clientstate == UPAPCS_AUTHREQ) { /* Timeout pending? */
00299     UNTIMEOUT(upap_timeout, u);    /* Cancel timeout */
00300   }
00301   if (u->us_serverstate == UPAPSS_LISTEN && u->us_reqtimeout > 0) {
00302     UNTIMEOUT(upap_reqtimeout, u);
00303   }
00304 
00305   u->us_clientstate = UPAPCS_INITIAL;
00306   u->us_serverstate = UPAPSS_INITIAL;
00307 }
00308 
00309 
00310 /*
00311  * upap_protrej - Peer doesn't speak this protocol.
00312  *
00313  * This shouldn't happen.  In any case, pretend lower layer went down.
00314  */
00315 static void
00316 upap_protrej(int unit)
00317 {
00318   upap_state *u = &upap[unit];
00319 
00320   if (u->us_clientstate == UPAPCS_AUTHREQ) {
00321     UPAPDEBUG((LOG_ERR, "PAP authentication failed due to protocol-reject\n"));
00322     auth_withpeer_fail(unit, PPP_PAP);
00323   }
00324   if (u->us_serverstate == UPAPSS_LISTEN) {
00325     UPAPDEBUG((LOG_ERR, "PAP authentication of peer failed (protocol-reject)\n"));
00326     auth_peer_fail(unit, PPP_PAP);
00327   }
00328   upap_lowerdown(unit);
00329 }
00330 
00331 
00332 /*
00333  * upap_input - Input UPAP packet.
00334  */
00335 static void
00336 upap_input(int unit, u_char *inpacket, int l)
00337 {
00338   upap_state *u = &upap[unit];
00339   u_char *inp;
00340   u_char code, id;
00341   int len;
00342 
00343   /*
00344    * Parse header (code, id and length).
00345    * If packet too short, drop it.
00346    */
00347   inp = inpacket;
00348   if (l < UPAP_HEADERLEN) {
00349     UPAPDEBUG((LOG_INFO, "pap_input: rcvd short header.\n"));
00350     return;
00351   }
00352   GETCHAR(code, inp);
00353   GETCHAR(id, inp);
00354   GETSHORT(len, inp);
00355   if (len < UPAP_HEADERLEN) {
00356     UPAPDEBUG((LOG_INFO, "pap_input: rcvd illegal length.\n"));
00357     return;
00358   }
00359   if (len > l) {
00360     UPAPDEBUG((LOG_INFO, "pap_input: rcvd short packet.\n"));
00361     return;
00362   }
00363   len -= UPAP_HEADERLEN;
00364 
00365   /*
00366    * Action depends on code.
00367    */
00368   switch (code) {
00369     case UPAP_AUTHREQ:
00370       upap_rauthreq(u, inp, id, len);
00371       break;
00372 
00373     case UPAP_AUTHACK:
00374       upap_rauthack(u, inp, id, len);
00375       break;
00376 
00377     case UPAP_AUTHNAK:
00378       upap_rauthnak(u, inp, id, len);
00379       break;
00380 
00381     default:        /* XXX Need code reject */
00382       break;
00383   }
00384 }
00385 
00386 
00387 /*
00388  * upap_rauth - Receive Authenticate.
00389  */
00390 static void
00391 upap_rauthreq(upap_state *u, u_char *inp, int id, int len)
00392 {
00393   u_char ruserlen, rpasswdlen;
00394   char *ruser, *rpasswd;
00395   int retcode;
00396   char *msg;
00397   int msglen;
00398 
00399   UPAPDEBUG((LOG_INFO, "pap_rauth: Rcvd id %d.\n", id));
00400 
00401   if (u->us_serverstate < UPAPSS_LISTEN) {
00402     return;
00403   }
00404 
00405   /*
00406    * If we receive a duplicate authenticate-request, we are
00407    * supposed to return the same status as for the first request.
00408    */
00409   if (u->us_serverstate == UPAPSS_OPEN) {
00410     upap_sresp(u, UPAP_AUTHACK, id, "", 0);  /* return auth-ack */
00411     return;
00412   }
00413   if (u->us_serverstate == UPAPSS_BADAUTH) {
00414     upap_sresp(u, UPAP_AUTHNAK, id, "", 0);  /* return auth-nak */
00415     return;
00416   }
00417 
00418   /*
00419    * Parse user/passwd.
00420    */
00421   if (len < sizeof (u_char)) {
00422     UPAPDEBUG((LOG_INFO, "pap_rauth: rcvd short packet.\n"));
00423     return;
00424   }
00425   GETCHAR(ruserlen, inp);
00426   len -= sizeof (u_char) + ruserlen + sizeof (u_char);
00427   if (len < 0) {
00428     UPAPDEBUG((LOG_INFO, "pap_rauth: rcvd short packet.\n"));
00429     return;
00430   }
00431   ruser = (char *) inp;
00432   INCPTR(ruserlen, inp);
00433   GETCHAR(rpasswdlen, inp);
00434   if (len < rpasswdlen) {
00435     UPAPDEBUG((LOG_INFO, "pap_rauth: rcvd short packet.\n"));
00436     return;
00437   }
00438   rpasswd = (char *) inp;
00439 
00440   /*
00441    * Check the username and password given.
00442    */
00443   retcode = check_passwd(u->us_unit, ruser, ruserlen, rpasswd, rpasswdlen, &msg, &msglen);
00444   BZERO(rpasswd, rpasswdlen);
00445 
00446   upap_sresp(u, retcode, id, msg, msglen);
00447 
00448   if (retcode == UPAP_AUTHACK) {
00449     u->us_serverstate = UPAPSS_OPEN;
00450     auth_peer_success(u->us_unit, PPP_PAP, ruser, ruserlen);
00451   } else {
00452     u->us_serverstate = UPAPSS_BADAUTH;
00453     auth_peer_fail(u->us_unit, PPP_PAP);
00454   }
00455 
00456   if (u->us_reqtimeout > 0) {
00457     UNTIMEOUT(upap_reqtimeout, u);
00458   }
00459 }
00460 
00461 
00462 /*
00463  * upap_rauthack - Receive Authenticate-Ack.
00464  */
00465 static void
00466 upap_rauthack(upap_state *u, u_char *inp, int id, int len)
00467 {
00468   u_char msglen;
00469   char *msg;
00470 
00471   LWIP_UNUSED_ARG(id);
00472 
00473   UPAPDEBUG((LOG_INFO, "pap_rauthack: Rcvd id %d s=%d\n", id, u->us_clientstate));
00474 
00475   if (u->us_clientstate != UPAPCS_AUTHREQ) { /* XXX */
00476     return;
00477   }
00478 
00479   /*
00480    * Parse message.
00481    */
00482   if (len < sizeof (u_char)) {
00483     UPAPDEBUG((LOG_INFO, "pap_rauthack: rcvd short packet.\n"));
00484     return;
00485   }
00486   GETCHAR(msglen, inp);
00487   len -= sizeof (u_char);
00488   if (len < msglen) {
00489     UPAPDEBUG((LOG_INFO, "pap_rauthack: rcvd short packet.\n"));
00490     return;
00491   }
00492   msg = (char *) inp;
00493   PRINTMSG(msg, msglen);
00494 
00495   UNTIMEOUT(upap_timeout, u);    /* Cancel timeout */
00496   u->us_clientstate = UPAPCS_OPEN;
00497 
00498   auth_withpeer_success(u->us_unit, PPP_PAP);
00499 }
00500 
00501 
00502 /*
00503  * upap_rauthnak - Receive Authenticate-Nakk.
00504  */
00505 static void
00506 upap_rauthnak(upap_state *u, u_char *inp, int id, int len)
00507 {
00508   u_char msglen;
00509   char *msg;
00510 
00511   LWIP_UNUSED_ARG(id);
00512 
00513   UPAPDEBUG((LOG_INFO, "pap_rauthnak: Rcvd id %d s=%d\n", id, u->us_clientstate));
00514 
00515   if (u->us_clientstate != UPAPCS_AUTHREQ) { /* XXX */
00516     return;
00517   }
00518 
00519   /*
00520    * Parse message.
00521    */
00522   if (len < sizeof (u_char)) {
00523     UPAPDEBUG((LOG_INFO, "pap_rauthnak: rcvd short packet.\n"));
00524   } else {
00525     GETCHAR(msglen, inp);
00526     if(msglen > 0) {
00527       len -= sizeof (u_char);
00528       if (len < msglen) {
00529         UPAPDEBUG((LOG_INFO, "pap_rauthnak: rcvd short packet.\n"));
00530         return;
00531       }
00532       msg = (char *) inp;
00533       PRINTMSG(msg, msglen);
00534     }
00535   }
00536 
00537   u->us_clientstate = UPAPCS_BADAUTH;
00538 
00539   UPAPDEBUG((LOG_ERR, "PAP authentication failed\n"));
00540   auth_withpeer_fail(u->us_unit, PPP_PAP);
00541 }
00542 
00543 
00544 /*
00545  * upap_sauthreq - Send an Authenticate-Request.
00546  */
00547 static void
00548 upap_sauthreq(upap_state *u)
00549 {
00550   u_char *outp;
00551   int outlen;
00552 
00553   outlen = UPAP_HEADERLEN + 2 * sizeof (u_char) 
00554          + u->us_userlen + u->us_passwdlen;
00555   outp = outpacket_buf[u->us_unit];
00556 
00557   MAKEHEADER(outp, PPP_PAP);
00558 
00559   PUTCHAR(UPAP_AUTHREQ, outp);
00560   PUTCHAR(++u->us_id, outp);
00561   PUTSHORT(outlen, outp);
00562   PUTCHAR(u->us_userlen, outp);
00563   BCOPY(u->us_user, outp, u->us_userlen);
00564   INCPTR(u->us_userlen, outp);
00565   PUTCHAR(u->us_passwdlen, outp);
00566   BCOPY(u->us_passwd, outp, u->us_passwdlen);
00567 
00568   pppWrite(u->us_unit, outpacket_buf[u->us_unit], outlen + PPP_HDRLEN);
00569 
00570   UPAPDEBUG((LOG_INFO, "pap_sauth: Sent id %d\n", u->us_id));
00571 
00572   TIMEOUT(upap_timeout, u, u->us_timeouttime);
00573   ++u->us_transmits;
00574   u->us_clientstate = UPAPCS_AUTHREQ;
00575 }
00576 
00577 
00578 /*
00579  * upap_sresp - Send a response (ack or nak).
00580  */
00581 static void
00582 upap_sresp(upap_state *u, u_char code, u_char id, char *msg, int msglen)
00583 {
00584   u_char *outp;
00585   int outlen;
00586 
00587   outlen = UPAP_HEADERLEN + sizeof (u_char) + msglen;
00588   outp = outpacket_buf[u->us_unit];
00589   MAKEHEADER(outp, PPP_PAP);
00590 
00591   PUTCHAR(code, outp);
00592   PUTCHAR(id, outp);
00593   PUTSHORT(outlen, outp);
00594   PUTCHAR(msglen, outp);
00595   BCOPY(msg, outp, msglen);
00596   pppWrite(u->us_unit, outpacket_buf[u->us_unit], outlen + PPP_HDRLEN);
00597 
00598   UPAPDEBUG((LOG_INFO, "pap_sresp: Sent code %d, id %d s=%d\n", code, id, u->us_clientstate));
00599 }
00600 
00601 #if 0
00602 /*
00603  * upap_printpkt - print the contents of a PAP packet.
00604  */
00605 static int upap_printpkt(
00606   u_char *p,
00607   int plen,
00608   void (*printer) (void *, char *, ...),
00609   void *arg
00610 )
00611 {
00612   LWIP_UNUSED_ARG(p);
00613   LWIP_UNUSED_ARG(plen);
00614   LWIP_UNUSED_ARG(printer);
00615   LWIP_UNUSED_ARG(arg);
00616   return 0;
00617 }
00618 #endif /* 0 */
00619 
00620 #endif /* PAP_SUPPORT */
00621 
00622 #endif /* PPP_SUPPORT */
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines