xref: /freebsd/usr.sbin/ppp/pap.c (revision a8445737e740901f5f2c8d24c12ef7fc8b00134e)
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.26 1998/08/07 18:42:50 brian Exp $
22  *
23  *	TODO:
24  */
25 #include <sys/types.h>
26 #include <netinet/in.h>
27 #include <netinet/in_systm.h>
28 #include <netinet/ip.h>
29 #include <sys/un.h>
30 
31 #include <string.h>
32 #include <termios.h>
33 
34 #include "mbuf.h"
35 #include "log.h"
36 #include "defs.h"
37 #include "timer.h"
38 #include "fsm.h"
39 #include "lcp.h"
40 #include "auth.h"
41 #include "pap.h"
42 #include "lqr.h"
43 #include "hdlc.h"
44 #include "lcpproto.h"
45 #include "async.h"
46 #include "throughput.h"
47 #include "ccp.h"
48 #include "link.h"
49 #include "descriptor.h"
50 #include "physical.h"
51 #include "iplist.h"
52 #include "slcompress.h"
53 #include "ipcp.h"
54 #include "filter.h"
55 #include "mp.h"
56 #include "bundle.h"
57 #include "chat.h"
58 #include "chap.h"
59 #include "cbcp.h"
60 #include "datalink.h"
61 
62 static const char *papcodes[] = { "???", "REQUEST", "SUCCESS", "FAILURE" };
63 
64 void
65 pap_SendChallenge(struct authinfo *auth, int papid, struct physical *physical)
66 {
67   struct fsmheader lh;
68   struct mbuf *bp;
69   u_char *cp;
70   int namelen, keylen, plen;
71 
72   namelen = strlen(physical->dl->bundle->cfg.auth.name);
73   keylen = strlen(physical->dl->bundle->cfg.auth.key);
74   plen = namelen + keylen + 2;
75   log_Printf(LogDEBUG, "pap_SendChallenge: namelen = %d, keylen = %d\n",
76 	    namelen, keylen);
77   log_Printf(LogPHASE, "Pap Output: %s ********\n",
78              physical->dl->bundle->cfg.auth.name);
79   if (*physical->dl->bundle->cfg.auth.name == '\0')
80     log_Printf(LogWARN, "Sending empty PAP authname!\n");
81   lh.code = PAP_REQUEST;
82   lh.id = papid;
83   lh.length = htons(plen + sizeof(struct fsmheader));
84   bp = mbuf_Alloc(plen + sizeof(struct fsmheader), MB_FSM);
85   memcpy(MBUF_CTOP(bp), &lh, sizeof(struct fsmheader));
86   cp = MBUF_CTOP(bp) + sizeof(struct fsmheader);
87   *cp++ = namelen;
88   memcpy(cp, physical->dl->bundle->cfg.auth.name, namelen);
89   cp += namelen;
90   *cp++ = keylen;
91   memcpy(cp, physical->dl->bundle->cfg.auth.key, keylen);
92 
93   hdlc_Output(&physical->link, PRI_LINK, PROTO_PAP, bp);
94 }
95 
96 static void
97 SendPapCode(int id, int code, const char *message, struct physical *physical)
98 {
99   struct fsmheader lh;
100   struct mbuf *bp;
101   u_char *cp;
102   int plen, mlen;
103 
104   lh.code = code;
105   lh.id = id;
106   mlen = strlen(message);
107   plen = mlen + 1;
108   lh.length = htons(plen + sizeof(struct fsmheader));
109   bp = mbuf_Alloc(plen + sizeof(struct fsmheader), MB_FSM);
110   memcpy(MBUF_CTOP(bp), &lh, sizeof(struct fsmheader));
111   cp = MBUF_CTOP(bp) + sizeof(struct fsmheader);
112   *cp++ = mlen;
113   memcpy(cp, message, mlen);
114   log_Printf(LogPHASE, "Pap Output: %s\n", papcodes[code]);
115   hdlc_Output(&physical->link, PRI_LINK, PROTO_PAP, bp);
116 }
117 
118 /*
119  * Validate given username and passwrd against with secret table
120  */
121 static int
122 PapValidate(struct bundle *bundle, u_char *name, u_char *key,
123             struct physical *physical)
124 {
125   int nlen, klen;
126 
127   nlen = *name++;
128   klen = *key;
129   *key++ = 0;
130   key[klen] = 0;
131   log_Printf(LogDEBUG, "PapValidate: name %s (%d), key %s (%d)\n",
132 	    name, nlen, key, klen);
133 
134   return auth_Validate(bundle, name, key, physical);
135 }
136 
137 void
138 pap_Input(struct bundle *bundle, struct mbuf *bp, struct physical *physical)
139 {
140   int len = mbuf_Length(bp);
141   struct fsmheader *php;
142   u_char *cp;
143 
144   if (len >= sizeof(struct fsmheader)) {
145     php = (struct fsmheader *) MBUF_CTOP(bp);
146     if (len >= ntohs(php->length)) {
147       if (php->code < PAP_REQUEST || php->code > PAP_NAK)
148 	php->code = 0;
149       switch (php->code) {
150       case PAP_REQUEST:
151 	cp = (u_char *) (php + 1);
152         log_Printf(LogPHASE, "Pap Input: %s (%.*s)\n",
153                    papcodes[php->code], *cp, cp + 1);
154 	if (PapValidate(bundle, cp, cp + *cp + 1, physical)) {
155           datalink_GotAuthname(physical->dl, cp+1, *cp);
156 	  SendPapCode(php->id, PAP_ACK, "Greetings!!", physical);
157 	  physical->link.lcp.auth_ineed = 0;
158           if (Enabled(bundle, OPT_UTMP))
159             physical_Login(physical, cp + 1);
160 
161           if (physical->link.lcp.auth_iwait == 0)
162             /*
163              * Either I didn't need to authenticate, or I've already been
164              * told that I got the answer right.
165              */
166             datalink_AuthOk(physical->dl);
167 
168 	} else {
169 	  SendPapCode(php->id, PAP_NAK, "Login incorrect", physical);
170           datalink_AuthNotOk(physical->dl);
171 	}
172 	break;
173       case PAP_ACK:
174 	auth_StopTimer(&physical->dl->pap);
175 	cp = (u_char *) (php + 1);
176 	len = *cp++;
177 	cp[len] = 0;
178 	log_Printf(LogPHASE, "Pap Input: %s (%s)\n", papcodes[php->code], cp);
179 	if (physical->link.lcp.auth_iwait == PROTO_PAP) {
180 	  physical->link.lcp.auth_iwait = 0;
181 	  if (physical->link.lcp.auth_ineed == 0)
182             /*
183              * We've succeeded in our ``login''
184              * If we're not expecting  the peer to authenticate (or he already
185              * has), proceed to network phase.
186              */
187             datalink_AuthOk(physical->dl);
188 	}
189 	break;
190       case PAP_NAK:
191 	auth_StopTimer(&physical->dl->pap);
192 	cp = (u_char *) (php + 1);
193 	len = *cp++;
194 	cp[len] = 0;
195 	log_Printf(LogPHASE, "Pap Input: %s (%s)\n", papcodes[php->code], cp);
196         datalink_AuthNotOk(physical->dl);
197 	break;
198       }
199     }
200   }
201   mbuf_Free(bp);
202 }
203