xref: /freebsd/usr.sbin/ppp/pap.c (revision 455aabc3f8ec34f01e0c38a52775d8fad9b7b55c)
11ae349f5Scvs2svn /*
21ae349f5Scvs2svn  *			PPP PAP Module
31ae349f5Scvs2svn  *
41ae349f5Scvs2svn  *	    Written by Toshiharu OHNO (tony-o@iij.ad.jp)
51ae349f5Scvs2svn  *
61ae349f5Scvs2svn  *   Copyright (C) 1993-94, Internet Initiative Japan, Inc.
71ae349f5Scvs2svn  *		     All rights reserverd.
81ae349f5Scvs2svn  *
91ae349f5Scvs2svn  * Redistribution and use in source and binary forms are permitted
101ae349f5Scvs2svn  * provided that the above copyright notice and this paragraph are
111ae349f5Scvs2svn  * duplicated in all such forms and that any documentation,
121ae349f5Scvs2svn  * advertising materials, and other materials related to such
131ae349f5Scvs2svn  * distribution and use acknowledge that the software was developed
141ae349f5Scvs2svn  * by the Internet Initiative Japan, Inc.  The name of the
151ae349f5Scvs2svn  * IIJ may not be used to endorse or promote products derived
161ae349f5Scvs2svn  * from this software without specific prior written permission.
171ae349f5Scvs2svn  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
181ae349f5Scvs2svn  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
191ae349f5Scvs2svn  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
201ae349f5Scvs2svn  *
21455aabc3SBrian Somers  * $Id: pap.c,v 1.20.2.6 1998/02/02 19:33:39 brian Exp $
221ae349f5Scvs2svn  *
231ae349f5Scvs2svn  *	TODO:
241ae349f5Scvs2svn  */
251ae349f5Scvs2svn #include <sys/param.h>
261ae349f5Scvs2svn #include <netinet/in.h>
271ae349f5Scvs2svn 
281ae349f5Scvs2svn #include <pwd.h>
291ae349f5Scvs2svn #include <stdio.h>
301ae349f5Scvs2svn #include <string.h>
311ae349f5Scvs2svn #include <time.h>
326140ba11SBrian Somers #include <termios.h>
331ae349f5Scvs2svn #include <unistd.h>
341ae349f5Scvs2svn #ifdef __OpenBSD__
351ae349f5Scvs2svn #include <util.h>
361ae349f5Scvs2svn #else
371ae349f5Scvs2svn #include <libutil.h>
381ae349f5Scvs2svn #endif
391ae349f5Scvs2svn #include <utmp.h>
401ae349f5Scvs2svn 
411ae349f5Scvs2svn #include "command.h"
421ae349f5Scvs2svn #include "mbuf.h"
431ae349f5Scvs2svn #include "log.h"
441ae349f5Scvs2svn #include "defs.h"
451ae349f5Scvs2svn #include "timer.h"
461ae349f5Scvs2svn #include "fsm.h"
471ae349f5Scvs2svn #include "lcp.h"
481ae349f5Scvs2svn #include "pap.h"
491ae349f5Scvs2svn #include "loadalias.h"
501ae349f5Scvs2svn #include "vars.h"
511ae349f5Scvs2svn #include "hdlc.h"
521ae349f5Scvs2svn #include "lcpproto.h"
531ae349f5Scvs2svn #include "auth.h"
546140ba11SBrian Somers #include "async.h"
556140ba11SBrian Somers #include "throughput.h"
566140ba11SBrian Somers #include "link.h"
5763b73463SBrian Somers #include "physical.h"
58455aabc3SBrian Somers #include "bundle.h"
591ae349f5Scvs2svn 
601ae349f5Scvs2svn static const char *papcodes[] = { "???", "REQUEST", "ACK", "NAK" };
611ae349f5Scvs2svn 
621ae349f5Scvs2svn static void
6363b73463SBrian Somers SendPapChallenge(int papid, struct physical *physical)
641ae349f5Scvs2svn {
651ae349f5Scvs2svn   struct fsmheader lh;
661ae349f5Scvs2svn   struct mbuf *bp;
671ae349f5Scvs2svn   u_char *cp;
681ae349f5Scvs2svn   int namelen, keylen, plen;
691ae349f5Scvs2svn 
701ae349f5Scvs2svn   namelen = strlen(VarAuthName);
711ae349f5Scvs2svn   keylen = strlen(VarAuthKey);
721ae349f5Scvs2svn   plen = namelen + keylen + 2;
731ae349f5Scvs2svn   LogPrintf(LogDEBUG, "SendPapChallenge: namelen = %d, keylen = %d\n",
741ae349f5Scvs2svn 	    namelen, keylen);
751ae349f5Scvs2svn   if (LogIsKept(LogDEBUG))
761ae349f5Scvs2svn     LogPrintf(LogPHASE, "PAP: %s (%s)\n", VarAuthName, VarAuthKey);
771ae349f5Scvs2svn   else
781ae349f5Scvs2svn     LogPrintf(LogPHASE, "PAP: %s\n", VarAuthName);
791ae349f5Scvs2svn   lh.code = PAP_REQUEST;
801ae349f5Scvs2svn   lh.id = papid;
811ae349f5Scvs2svn   lh.length = htons(plen + sizeof(struct fsmheader));
821ae349f5Scvs2svn   bp = mballoc(plen + sizeof(struct fsmheader), MB_FSM);
831ae349f5Scvs2svn   memcpy(MBUF_CTOP(bp), &lh, sizeof(struct fsmheader));
841ae349f5Scvs2svn   cp = MBUF_CTOP(bp) + sizeof(struct fsmheader);
851ae349f5Scvs2svn   *cp++ = namelen;
861ae349f5Scvs2svn   memcpy(cp, VarAuthName, namelen);
871ae349f5Scvs2svn   cp += namelen;
881ae349f5Scvs2svn   *cp++ = keylen;
891ae349f5Scvs2svn   memcpy(cp, VarAuthKey, keylen);
901ae349f5Scvs2svn 
918c07a7b2SBrian Somers   HdlcOutput(physical2link(physical), PRI_LINK, PROTO_PAP, bp);
921ae349f5Scvs2svn }
931ae349f5Scvs2svn 
941ae349f5Scvs2svn struct authinfo AuthPapInfo = {
951ae349f5Scvs2svn   SendPapChallenge,
961ae349f5Scvs2svn };
971ae349f5Scvs2svn 
981ae349f5Scvs2svn static void
9963b73463SBrian Somers SendPapCode(int id, int code, const char *message, struct physical *physical)
1001ae349f5Scvs2svn {
1011ae349f5Scvs2svn   struct fsmheader lh;
1021ae349f5Scvs2svn   struct mbuf *bp;
1031ae349f5Scvs2svn   u_char *cp;
1041ae349f5Scvs2svn   int plen, mlen;
1051ae349f5Scvs2svn 
1061ae349f5Scvs2svn   lh.code = code;
1071ae349f5Scvs2svn   lh.id = id;
1081ae349f5Scvs2svn   mlen = strlen(message);
1091ae349f5Scvs2svn   plen = mlen + 1;
1101ae349f5Scvs2svn   lh.length = htons(plen + sizeof(struct fsmheader));
1111ae349f5Scvs2svn   bp = mballoc(plen + sizeof(struct fsmheader), MB_FSM);
1121ae349f5Scvs2svn   memcpy(MBUF_CTOP(bp), &lh, sizeof(struct fsmheader));
1131ae349f5Scvs2svn   cp = MBUF_CTOP(bp) + sizeof(struct fsmheader);
1141ae349f5Scvs2svn   *cp++ = mlen;
1151ae349f5Scvs2svn   memcpy(cp, message, mlen);
1161ae349f5Scvs2svn   LogPrintf(LogPHASE, "PapOutput: %s\n", papcodes[code]);
1178c07a7b2SBrian Somers   HdlcOutput(physical2link(physical), PRI_LINK, PROTO_PAP, bp);
1181ae349f5Scvs2svn }
1191ae349f5Scvs2svn 
1201ae349f5Scvs2svn /*
1211ae349f5Scvs2svn  * Validate given username and passwrd against with secret table
1221ae349f5Scvs2svn  */
1231ae349f5Scvs2svn static int
1247a6f8720SBrian Somers PapValidate(struct bundle *bundle, u_char *name, u_char *key,
1257a6f8720SBrian Somers             struct physical *physical)
1261ae349f5Scvs2svn {
1271ae349f5Scvs2svn   int nlen, klen;
1281ae349f5Scvs2svn 
1291ae349f5Scvs2svn   nlen = *name++;
1301ae349f5Scvs2svn   klen = *key;
1311ae349f5Scvs2svn   *key++ = 0;
1321ae349f5Scvs2svn   key[klen] = 0;
1331ae349f5Scvs2svn   LogPrintf(LogDEBUG, "PapValidate: name %s (%d), key %s (%d)\n",
1341ae349f5Scvs2svn 	    name, nlen, key, klen);
1351ae349f5Scvs2svn 
1361ae349f5Scvs2svn #ifndef NOPASSWDAUTH
1371ae349f5Scvs2svn   if (Enabled(ConfPasswdAuth)) {
1381ae349f5Scvs2svn     struct passwd *pwd;
1391ae349f5Scvs2svn     int result;
1401ae349f5Scvs2svn 
1411ae349f5Scvs2svn     LogPrintf(LogLCP, "Using PasswdAuth\n");
1421ae349f5Scvs2svn     result = (pwd = getpwnam(name)) &&
1431ae349f5Scvs2svn              !strcmp(crypt(key, pwd->pw_passwd), pwd->pw_passwd);
1441ae349f5Scvs2svn     endpwent();
1451ae349f5Scvs2svn     return result;
1461ae349f5Scvs2svn   }
1471ae349f5Scvs2svn #endif
1481ae349f5Scvs2svn 
1497a6f8720SBrian Somers   return AuthValidate(bundle, SECRETFILE, name, key, physical);
1501ae349f5Scvs2svn }
1511ae349f5Scvs2svn 
1521ae349f5Scvs2svn void
1537a6f8720SBrian Somers PapInput(struct bundle *bundle, struct mbuf *bp, struct physical *physical)
1541ae349f5Scvs2svn {
1551ae349f5Scvs2svn   int len = plength(bp);
1561ae349f5Scvs2svn   struct fsmheader *php;
1571ae349f5Scvs2svn   u_char *cp;
1581ae349f5Scvs2svn 
1591ae349f5Scvs2svn   if (len >= sizeof(struct fsmheader)) {
1601ae349f5Scvs2svn     php = (struct fsmheader *) MBUF_CTOP(bp);
1611ae349f5Scvs2svn     if (len >= ntohs(php->length)) {
1621ae349f5Scvs2svn       if (php->code < PAP_REQUEST || php->code > PAP_NAK)
1631ae349f5Scvs2svn 	php->code = 0;
1641ae349f5Scvs2svn       LogPrintf(LogPHASE, "PapInput: %s\n", papcodes[php->code]);
1651ae349f5Scvs2svn 
1661ae349f5Scvs2svn       switch (php->code) {
1671ae349f5Scvs2svn       case PAP_REQUEST:
1681ae349f5Scvs2svn 	cp = (u_char *) (php + 1);
1697a6f8720SBrian Somers 	if (PapValidate(bundle, cp, cp + *cp + 1, physical)) {
17063b73463SBrian Somers 	  SendPapCode(php->id, PAP_ACK, "Greetings!!", physical);
171c8ee0d78SBrian Somers 	  LcpInfo.auth_ineed = 0;
17263b73463SBrian Somers           if ((mode & MODE_DIRECT) && Physical_IsATTY(physical) &&
17363b73463SBrian Somers               Enabled(ConfUtmp))
1741ae349f5Scvs2svn             if (Utmp)
1751ae349f5Scvs2svn               LogPrintf(LogERROR, "Oops, already logged in on %s\n",
1761ae349f5Scvs2svn                         VarBaseDevice);
1771ae349f5Scvs2svn             else {
1781ae349f5Scvs2svn               struct utmp ut;
1791ae349f5Scvs2svn               memset(&ut, 0, sizeof ut);
1801ae349f5Scvs2svn               time(&ut.ut_time);
1811ae349f5Scvs2svn               strncpy(ut.ut_name, cp+1, sizeof ut.ut_name - 1);
1821ae349f5Scvs2svn               strncpy(ut.ut_line, VarBaseDevice, sizeof ut.ut_line - 1);
1831ae349f5Scvs2svn               if (logout(ut.ut_line))
1841ae349f5Scvs2svn                 logwtmp(ut.ut_line, "", "");
1851ae349f5Scvs2svn               login(&ut);
1861ae349f5Scvs2svn               Utmp = 1;
1871ae349f5Scvs2svn             }
188455aabc3SBrian Somers 
189455aabc3SBrian Somers           if (LcpInfo.auth_iwait == 0)
190455aabc3SBrian Somers             /*
191455aabc3SBrian Somers              * Either I didn't need to authenticate, or I've already been
192455aabc3SBrian Somers              * told that I got the answer right.
193455aabc3SBrian Somers              */
194455aabc3SBrian Somers             bundle_NewPhase(bundle, physical, PHASE_NETWORK);
195455aabc3SBrian Somers 
1961ae349f5Scvs2svn 	} else {
19763b73463SBrian Somers 	  SendPapCode(php->id, PAP_NAK, "Login incorrect", physical);
1981ae349f5Scvs2svn           reconnect(RECON_FALSE);
199455aabc3SBrian Somers           bundle_Close(bundle, &LcpInfo.fsm);
2001ae349f5Scvs2svn 	}
2011ae349f5Scvs2svn 	break;
2021ae349f5Scvs2svn       case PAP_ACK:
2031ae349f5Scvs2svn 	StopAuthTimer(&AuthPapInfo);
2041ae349f5Scvs2svn 	cp = (u_char *) (php + 1);
2051ae349f5Scvs2svn 	len = *cp++;
2061ae349f5Scvs2svn 	cp[len] = 0;
2071ae349f5Scvs2svn 	LogPrintf(LogPHASE, "Received PAP_ACK (%s)\n", cp);
208c8ee0d78SBrian Somers 	if (LcpInfo.auth_iwait == PROTO_PAP) {
209c8ee0d78SBrian Somers 	  LcpInfo.auth_iwait = 0;
210c8ee0d78SBrian Somers 	  if (LcpInfo.auth_ineed == 0)
211455aabc3SBrian Somers             /*
212455aabc3SBrian Somers              * We've succeeded in our ``login''
213455aabc3SBrian Somers              * If we're not expecting  the peer to authenticate (or he already
214455aabc3SBrian Somers              * has), proceed to network phase.
215455aabc3SBrian Somers              */
216455aabc3SBrian Somers 	    bundle_NewPhase(bundle, physical, PHASE_NETWORK);
2171ae349f5Scvs2svn 	}
2181ae349f5Scvs2svn 	break;
2191ae349f5Scvs2svn       case PAP_NAK:
2201ae349f5Scvs2svn 	StopAuthTimer(&AuthPapInfo);
2211ae349f5Scvs2svn 	cp = (u_char *) (php + 1);
2221ae349f5Scvs2svn 	len = *cp++;
2231ae349f5Scvs2svn 	cp[len] = 0;
2241ae349f5Scvs2svn 	LogPrintf(LogPHASE, "Received PAP_NAK (%s)\n", cp);
2251ae349f5Scvs2svn 	reconnect(RECON_FALSE);
226455aabc3SBrian Somers         bundle_Close(bundle, &LcpInfo.fsm);
2271ae349f5Scvs2svn 	break;
2281ae349f5Scvs2svn       }
2291ae349f5Scvs2svn     }
2301ae349f5Scvs2svn   }
2311ae349f5Scvs2svn   pfree(bp);
2321ae349f5Scvs2svn }
233