xref: /freebsd/usr.sbin/ppp/pap.c (revision 42d4d396689ff18f91456f636cf531b2f116e79b)
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  *
2142d4d396SBrian Somers  * $Id: pap.c,v 1.20.2.7 1998/02/07 20:50:01 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"
5742d4d396SBrian Somers #include "descriptor.h"
5863b73463SBrian Somers #include "physical.h"
59455aabc3SBrian Somers #include "bundle.h"
601ae349f5Scvs2svn 
611ae349f5Scvs2svn static const char *papcodes[] = { "???", "REQUEST", "ACK", "NAK" };
621ae349f5Scvs2svn 
631ae349f5Scvs2svn static void
6463b73463SBrian Somers SendPapChallenge(int papid, struct physical *physical)
651ae349f5Scvs2svn {
661ae349f5Scvs2svn   struct fsmheader lh;
671ae349f5Scvs2svn   struct mbuf *bp;
681ae349f5Scvs2svn   u_char *cp;
691ae349f5Scvs2svn   int namelen, keylen, plen;
701ae349f5Scvs2svn 
711ae349f5Scvs2svn   namelen = strlen(VarAuthName);
721ae349f5Scvs2svn   keylen = strlen(VarAuthKey);
731ae349f5Scvs2svn   plen = namelen + keylen + 2;
741ae349f5Scvs2svn   LogPrintf(LogDEBUG, "SendPapChallenge: namelen = %d, keylen = %d\n",
751ae349f5Scvs2svn 	    namelen, keylen);
761ae349f5Scvs2svn   if (LogIsKept(LogDEBUG))
771ae349f5Scvs2svn     LogPrintf(LogPHASE, "PAP: %s (%s)\n", VarAuthName, VarAuthKey);
781ae349f5Scvs2svn   else
791ae349f5Scvs2svn     LogPrintf(LogPHASE, "PAP: %s\n", VarAuthName);
801ae349f5Scvs2svn   lh.code = PAP_REQUEST;
811ae349f5Scvs2svn   lh.id = papid;
821ae349f5Scvs2svn   lh.length = htons(plen + sizeof(struct fsmheader));
831ae349f5Scvs2svn   bp = mballoc(plen + sizeof(struct fsmheader), MB_FSM);
841ae349f5Scvs2svn   memcpy(MBUF_CTOP(bp), &lh, sizeof(struct fsmheader));
851ae349f5Scvs2svn   cp = MBUF_CTOP(bp) + sizeof(struct fsmheader);
861ae349f5Scvs2svn   *cp++ = namelen;
871ae349f5Scvs2svn   memcpy(cp, VarAuthName, namelen);
881ae349f5Scvs2svn   cp += namelen;
891ae349f5Scvs2svn   *cp++ = keylen;
901ae349f5Scvs2svn   memcpy(cp, VarAuthKey, keylen);
911ae349f5Scvs2svn 
928c07a7b2SBrian Somers   HdlcOutput(physical2link(physical), PRI_LINK, PROTO_PAP, bp);
931ae349f5Scvs2svn }
941ae349f5Scvs2svn 
951ae349f5Scvs2svn struct authinfo AuthPapInfo = {
961ae349f5Scvs2svn   SendPapChallenge,
971ae349f5Scvs2svn };
981ae349f5Scvs2svn 
991ae349f5Scvs2svn static void
10063b73463SBrian Somers SendPapCode(int id, int code, const char *message, struct physical *physical)
1011ae349f5Scvs2svn {
1021ae349f5Scvs2svn   struct fsmheader lh;
1031ae349f5Scvs2svn   struct mbuf *bp;
1041ae349f5Scvs2svn   u_char *cp;
1051ae349f5Scvs2svn   int plen, mlen;
1061ae349f5Scvs2svn 
1071ae349f5Scvs2svn   lh.code = code;
1081ae349f5Scvs2svn   lh.id = id;
1091ae349f5Scvs2svn   mlen = strlen(message);
1101ae349f5Scvs2svn   plen = mlen + 1;
1111ae349f5Scvs2svn   lh.length = htons(plen + sizeof(struct fsmheader));
1121ae349f5Scvs2svn   bp = mballoc(plen + sizeof(struct fsmheader), MB_FSM);
1131ae349f5Scvs2svn   memcpy(MBUF_CTOP(bp), &lh, sizeof(struct fsmheader));
1141ae349f5Scvs2svn   cp = MBUF_CTOP(bp) + sizeof(struct fsmheader);
1151ae349f5Scvs2svn   *cp++ = mlen;
1161ae349f5Scvs2svn   memcpy(cp, message, mlen);
1171ae349f5Scvs2svn   LogPrintf(LogPHASE, "PapOutput: %s\n", papcodes[code]);
1188c07a7b2SBrian Somers   HdlcOutput(physical2link(physical), PRI_LINK, PROTO_PAP, bp);
1191ae349f5Scvs2svn }
1201ae349f5Scvs2svn 
1211ae349f5Scvs2svn /*
1221ae349f5Scvs2svn  * Validate given username and passwrd against with secret table
1231ae349f5Scvs2svn  */
1241ae349f5Scvs2svn static int
1257a6f8720SBrian Somers PapValidate(struct bundle *bundle, u_char *name, u_char *key,
1267a6f8720SBrian Somers             struct physical *physical)
1271ae349f5Scvs2svn {
1281ae349f5Scvs2svn   int nlen, klen;
1291ae349f5Scvs2svn 
1301ae349f5Scvs2svn   nlen = *name++;
1311ae349f5Scvs2svn   klen = *key;
1321ae349f5Scvs2svn   *key++ = 0;
1331ae349f5Scvs2svn   key[klen] = 0;
1341ae349f5Scvs2svn   LogPrintf(LogDEBUG, "PapValidate: name %s (%d), key %s (%d)\n",
1351ae349f5Scvs2svn 	    name, nlen, key, klen);
1361ae349f5Scvs2svn 
1371ae349f5Scvs2svn #ifndef NOPASSWDAUTH
1381ae349f5Scvs2svn   if (Enabled(ConfPasswdAuth)) {
1391ae349f5Scvs2svn     struct passwd *pwd;
1401ae349f5Scvs2svn     int result;
1411ae349f5Scvs2svn 
1421ae349f5Scvs2svn     LogPrintf(LogLCP, "Using PasswdAuth\n");
1431ae349f5Scvs2svn     result = (pwd = getpwnam(name)) &&
1441ae349f5Scvs2svn              !strcmp(crypt(key, pwd->pw_passwd), pwd->pw_passwd);
1451ae349f5Scvs2svn     endpwent();
1461ae349f5Scvs2svn     return result;
1471ae349f5Scvs2svn   }
1481ae349f5Scvs2svn #endif
1491ae349f5Scvs2svn 
1507a6f8720SBrian Somers   return AuthValidate(bundle, SECRETFILE, name, key, physical);
1511ae349f5Scvs2svn }
1521ae349f5Scvs2svn 
1531ae349f5Scvs2svn void
1547a6f8720SBrian Somers PapInput(struct bundle *bundle, struct mbuf *bp, struct physical *physical)
1551ae349f5Scvs2svn {
1561ae349f5Scvs2svn   int len = plength(bp);
1571ae349f5Scvs2svn   struct fsmheader *php;
1581ae349f5Scvs2svn   u_char *cp;
1591ae349f5Scvs2svn 
1601ae349f5Scvs2svn   if (len >= sizeof(struct fsmheader)) {
1611ae349f5Scvs2svn     php = (struct fsmheader *) MBUF_CTOP(bp);
1621ae349f5Scvs2svn     if (len >= ntohs(php->length)) {
1631ae349f5Scvs2svn       if (php->code < PAP_REQUEST || php->code > PAP_NAK)
1641ae349f5Scvs2svn 	php->code = 0;
1651ae349f5Scvs2svn       LogPrintf(LogPHASE, "PapInput: %s\n", papcodes[php->code]);
1661ae349f5Scvs2svn 
1671ae349f5Scvs2svn       switch (php->code) {
1681ae349f5Scvs2svn       case PAP_REQUEST:
1691ae349f5Scvs2svn 	cp = (u_char *) (php + 1);
1707a6f8720SBrian Somers 	if (PapValidate(bundle, cp, cp + *cp + 1, physical)) {
17163b73463SBrian Somers 	  SendPapCode(php->id, PAP_ACK, "Greetings!!", physical);
172c8ee0d78SBrian Somers 	  LcpInfo.auth_ineed = 0;
17363b73463SBrian Somers           if ((mode & MODE_DIRECT) && Physical_IsATTY(physical) &&
17463b73463SBrian Somers               Enabled(ConfUtmp))
1751ae349f5Scvs2svn             if (Utmp)
1761ae349f5Scvs2svn               LogPrintf(LogERROR, "Oops, already logged in on %s\n",
1771ae349f5Scvs2svn                         VarBaseDevice);
1781ae349f5Scvs2svn             else {
1791ae349f5Scvs2svn               struct utmp ut;
1801ae349f5Scvs2svn               memset(&ut, 0, sizeof ut);
1811ae349f5Scvs2svn               time(&ut.ut_time);
1821ae349f5Scvs2svn               strncpy(ut.ut_name, cp+1, sizeof ut.ut_name - 1);
1831ae349f5Scvs2svn               strncpy(ut.ut_line, VarBaseDevice, sizeof ut.ut_line - 1);
1841ae349f5Scvs2svn               if (logout(ut.ut_line))
1851ae349f5Scvs2svn                 logwtmp(ut.ut_line, "", "");
1861ae349f5Scvs2svn               login(&ut);
1871ae349f5Scvs2svn               Utmp = 1;
1881ae349f5Scvs2svn             }
189455aabc3SBrian Somers 
190455aabc3SBrian Somers           if (LcpInfo.auth_iwait == 0)
191455aabc3SBrian Somers             /*
192455aabc3SBrian Somers              * Either I didn't need to authenticate, or I've already been
193455aabc3SBrian Somers              * told that I got the answer right.
194455aabc3SBrian Somers              */
195455aabc3SBrian Somers             bundle_NewPhase(bundle, physical, PHASE_NETWORK);
196455aabc3SBrian Somers 
1971ae349f5Scvs2svn 	} else {
19863b73463SBrian Somers 	  SendPapCode(php->id, PAP_NAK, "Login incorrect", physical);
1991ae349f5Scvs2svn           reconnect(RECON_FALSE);
200455aabc3SBrian Somers           bundle_Close(bundle, &LcpInfo.fsm);
2011ae349f5Scvs2svn 	}
2021ae349f5Scvs2svn 	break;
2031ae349f5Scvs2svn       case PAP_ACK:
2041ae349f5Scvs2svn 	StopAuthTimer(&AuthPapInfo);
2051ae349f5Scvs2svn 	cp = (u_char *) (php + 1);
2061ae349f5Scvs2svn 	len = *cp++;
2071ae349f5Scvs2svn 	cp[len] = 0;
2081ae349f5Scvs2svn 	LogPrintf(LogPHASE, "Received PAP_ACK (%s)\n", cp);
209c8ee0d78SBrian Somers 	if (LcpInfo.auth_iwait == PROTO_PAP) {
210c8ee0d78SBrian Somers 	  LcpInfo.auth_iwait = 0;
211c8ee0d78SBrian Somers 	  if (LcpInfo.auth_ineed == 0)
212455aabc3SBrian Somers             /*
213455aabc3SBrian Somers              * We've succeeded in our ``login''
214455aabc3SBrian Somers              * If we're not expecting  the peer to authenticate (or he already
215455aabc3SBrian Somers              * has), proceed to network phase.
216455aabc3SBrian Somers              */
217455aabc3SBrian Somers 	    bundle_NewPhase(bundle, physical, PHASE_NETWORK);
2181ae349f5Scvs2svn 	}
2191ae349f5Scvs2svn 	break;
2201ae349f5Scvs2svn       case PAP_NAK:
2211ae349f5Scvs2svn 	StopAuthTimer(&AuthPapInfo);
2221ae349f5Scvs2svn 	cp = (u_char *) (php + 1);
2231ae349f5Scvs2svn 	len = *cp++;
2241ae349f5Scvs2svn 	cp[len] = 0;
2251ae349f5Scvs2svn 	LogPrintf(LogPHASE, "Received PAP_NAK (%s)\n", cp);
2261ae349f5Scvs2svn 	reconnect(RECON_FALSE);
227455aabc3SBrian Somers         bundle_Close(bundle, &LcpInfo.fsm);
2281ae349f5Scvs2svn 	break;
2291ae349f5Scvs2svn       }
2301ae349f5Scvs2svn     }
2311ae349f5Scvs2svn   }
2321ae349f5Scvs2svn   pfree(bp);
2331ae349f5Scvs2svn }
234