xref: /freebsd/usr.sbin/ppp/pap.c (revision 0de89efe5c443f213c7ea28773ef2dc6cf3af2ed)
1 /*
2  *			PPP PAP Module
3  *
4  *	    Written by Toshiharu OHNO (tony-o@iij.ad.jp)
5  *
6  *   Copyright (C) 1993-94, Internet Initiative Japan, Inc.
7  *		     All rights reserverd.
8  *
9  * Redistribution and use in source and binary forms are permitted
10  * provided that the above copyright notice and this paragraph are
11  * duplicated in all such forms and that any documentation,
12  * advertising materials, and other materials related to such
13  * distribution and use acknowledge that the software was developed
14  * by the Internet Initiative Japan, Inc.  The name of the
15  * IIJ may not be used to endorse or promote products derived
16  * from this software without specific prior written permission.
17  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
19  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20  *
21  * $Id: pap.c,v 1.15 1997/09/22 23:59:15 brian Exp $
22  *
23  *	TODO:
24  */
25 #include <time.h>
26 #include <utmp.h>
27 #include <pwd.h>
28 #include "fsm.h"
29 #include "lcp.h"
30 #include "pap.h"
31 #include "loadalias.h"
32 #include "vars.h"
33 #include "hdlc.h"
34 #include "lcpproto.h"
35 #include "phase.h"
36 #include "auth.h"
37 #ifdef __OpenBSD__
38 #include "util.h"
39 #else
40 #include "libutil.h"
41 #endif
42 
43 static char *papcodes[] = {
44   "???", "REQUEST", "ACK", "NAK"
45 };
46 
47 struct authinfo AuthPapInfo = {
48   SendPapChallenge,
49 };
50 
51 void
52 SendPapChallenge(int papid)
53 {
54   struct fsmheader lh;
55   struct mbuf *bp;
56   u_char *cp;
57   int namelen, keylen, plen;
58 
59   namelen = strlen(VarAuthName);
60   keylen = strlen(VarAuthKey);
61   plen = namelen + keylen + 2;
62   LogPrintf(LogDEBUG, "SendPapChallenge: namelen = %d, keylen = %d\n",
63 	    namelen, keylen);
64   LogPrintf(LogPHASE, "PAP: %s (%s)\n", VarAuthName, VarAuthKey);
65   lh.code = PAP_REQUEST;
66   lh.id = papid;
67   lh.length = htons(plen + sizeof(struct fsmheader));
68   bp = mballoc(plen + sizeof(struct fsmheader), MB_FSM);
69   bcopy(&lh, MBUF_CTOP(bp), sizeof(struct fsmheader));
70   cp = MBUF_CTOP(bp) + sizeof(struct fsmheader);
71   *cp++ = namelen;
72   bcopy(VarAuthName, cp, namelen);
73   cp += namelen;
74   *cp++ = keylen;
75   bcopy(VarAuthKey, cp, keylen);
76 
77   HdlcOutput(PRI_LINK, PROTO_PAP, bp);
78 }
79 
80 static void
81 SendPapCode(int id, int code, char *message)
82 {
83   struct fsmheader lh;
84   struct mbuf *bp;
85   u_char *cp;
86   int plen, mlen;
87 
88   lh.code = code;
89   lh.id = id;
90   mlen = strlen(message);
91   plen = mlen + 1;
92   lh.length = htons(plen + sizeof(struct fsmheader));
93   bp = mballoc(plen + sizeof(struct fsmheader), MB_FSM);
94   bcopy(&lh, MBUF_CTOP(bp), sizeof(struct fsmheader));
95   cp = MBUF_CTOP(bp) + sizeof(struct fsmheader);
96   *cp++ = mlen;
97   bcopy(message, cp, mlen);
98   LogPrintf(LogPHASE, "PapOutput: %s\n", papcodes[code]);
99   HdlcOutput(PRI_LINK, PROTO_PAP, bp);
100 }
101 
102 /*
103  * Validate given username and passwrd against with secret table
104  */
105 static int
106 PapValidate(u_char * name, u_char * key)
107 {
108   int nlen, klen;
109 
110   nlen = *name++;
111   klen = *key;
112   *key++ = 0;
113   key[klen] = 0;
114   LogPrintf(LogDEBUG, "PapValidate: name %s (%d), key %s (%d)\n",
115 	    name, nlen, key, klen);
116 
117 #ifndef NOPASSWDAUTH
118   if (Enabled(ConfPasswdAuth)) {
119     struct passwd *pwd;
120     int result;
121 
122     LogPrintf(LogLCP, "Using PasswdAuth\n");
123     result = (pwd = getpwnam(name)) &&
124              !strcmp(crypt(key, pwd->pw_passwd), pwd->pw_passwd);
125     endpwent();
126     return result;
127   }
128 #endif
129 
130   return (AuthValidate(SECRETFILE, name, key));
131 }
132 
133 void
134 PapInput(struct mbuf * bp)
135 {
136   int len = plength(bp);
137   struct fsmheader *php;
138   struct lcpstate *lcp = &LcpInfo;
139   u_char *cp;
140 
141   if (len >= sizeof(struct fsmheader)) {
142     php = (struct fsmheader *) MBUF_CTOP(bp);
143     if (len >= ntohs(php->length)) {
144       if (php->code < PAP_REQUEST || php->code > PAP_NAK)
145 	php->code = 0;
146       LogPrintf(LogPHASE, "PapInput: %s\n", papcodes[php->code]);
147 
148       switch (php->code) {
149       case PAP_REQUEST:
150 	cp = (u_char *) (php + 1);
151 	if (PapValidate(cp, cp + *cp + 1)) {
152 	  SendPapCode(php->id, PAP_ACK, "Greetings!!");
153 	  lcp->auth_ineed = 0;
154 	  if (lcp->auth_iwait == 0) {
155 	    if ((mode & MODE_DIRECT) && isatty(modem) && Enabled(ConfUtmp))
156 	      if (Utmp)
157 		LogPrintf(LogERROR, "Oops, already logged in on %s\n",
158 			  VarBaseDevice);
159 	      else {
160 	        struct utmp ut;
161 	        memset(&ut, 0, sizeof(ut));
162 	        time(&ut.ut_time);
163 	        strncpy(ut.ut_name, cp+1, sizeof(ut.ut_name)-1);
164 	        strncpy(ut.ut_line, VarBaseDevice, sizeof(ut.ut_line)-1);
165 	        if (logout(ut.ut_line))
166 		  logwtmp(ut.ut_line, "", "");
167 	        login(&ut);
168 	        Utmp = 1;
169 	      }
170 	    NewPhase(PHASE_NETWORK);
171 	  }
172 	} else {
173 	  SendPapCode(php->id, PAP_NAK, "Login incorrect");
174 	  reconnect(RECON_FALSE);
175 	  LcpClose();
176 	}
177 	break;
178       case PAP_ACK:
179 	StopAuthTimer(&AuthPapInfo);
180 	cp = (u_char *) (php + 1);
181 	len = *cp++;
182 	cp[len] = 0;
183 	LogPrintf(LogPHASE, "Received PAP_ACK (%s)\n", cp);
184 	if (lcp->auth_iwait == PROTO_PAP) {
185 	  lcp->auth_iwait = 0;
186 	  if (lcp->auth_ineed == 0)
187 	    NewPhase(PHASE_NETWORK);
188 	}
189 	break;
190       case PAP_NAK:
191 	StopAuthTimer(&AuthPapInfo);
192 	cp = (u_char *) (php + 1);
193 	len = *cp++;
194 	cp[len] = 0;
195 	LogPrintf(LogPHASE, "Received PAP_NAK (%s)\n", cp);
196 	reconnect(RECON_FALSE);
197 	LcpClose();
198 	break;
199       }
200     }
201   }
202   pfree(bp);
203 }
204