1*10465441SEvalZero /*
2*10465441SEvalZero * upap.c - User/Password Authentication Protocol.
3*10465441SEvalZero *
4*10465441SEvalZero * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved.
5*10465441SEvalZero *
6*10465441SEvalZero * Redistribution and use in source and binary forms, with or without
7*10465441SEvalZero * modification, are permitted provided that the following conditions
8*10465441SEvalZero * are met:
9*10465441SEvalZero *
10*10465441SEvalZero * 1. Redistributions of source code must retain the above copyright
11*10465441SEvalZero * notice, this list of conditions and the following disclaimer.
12*10465441SEvalZero *
13*10465441SEvalZero * 2. Redistributions in binary form must reproduce the above copyright
14*10465441SEvalZero * notice, this list of conditions and the following disclaimer in
15*10465441SEvalZero * the documentation and/or other materials provided with the
16*10465441SEvalZero * distribution.
17*10465441SEvalZero *
18*10465441SEvalZero * 3. The name "Carnegie Mellon University" must not be used to
19*10465441SEvalZero * endorse or promote products derived from this software without
20*10465441SEvalZero * prior written permission. For permission or any legal
21*10465441SEvalZero * details, please contact
22*10465441SEvalZero * Office of Technology Transfer
23*10465441SEvalZero * Carnegie Mellon University
24*10465441SEvalZero * 5000 Forbes Avenue
25*10465441SEvalZero * Pittsburgh, PA 15213-3890
26*10465441SEvalZero * (412) 268-4387, fax: (412) 268-7395
27*10465441SEvalZero * [email protected]
28*10465441SEvalZero *
29*10465441SEvalZero * 4. Redistributions of any form whatsoever must retain the following
30*10465441SEvalZero * acknowledgment:
31*10465441SEvalZero * "This product includes software developed by Computing Services
32*10465441SEvalZero * at Carnegie Mellon University (http://www.cmu.edu/computing/)."
33*10465441SEvalZero *
34*10465441SEvalZero * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
35*10465441SEvalZero * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
36*10465441SEvalZero * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
37*10465441SEvalZero * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
38*10465441SEvalZero * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
39*10465441SEvalZero * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
40*10465441SEvalZero * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
41*10465441SEvalZero */
42*10465441SEvalZero
43*10465441SEvalZero #include "netif/ppp/ppp_opts.h"
44*10465441SEvalZero #if PPP_SUPPORT && PAP_SUPPORT /* don't build if not configured for use in lwipopts.h */
45*10465441SEvalZero
46*10465441SEvalZero /*
47*10465441SEvalZero * @todo:
48*10465441SEvalZero */
49*10465441SEvalZero
50*10465441SEvalZero #if 0 /* UNUSED */
51*10465441SEvalZero #include <stdio.h>
52*10465441SEvalZero #include <string.h>
53*10465441SEvalZero #endif /* UNUSED */
54*10465441SEvalZero
55*10465441SEvalZero #include "netif/ppp/ppp_impl.h"
56*10465441SEvalZero
57*10465441SEvalZero #include "netif/ppp/upap.h"
58*10465441SEvalZero
59*10465441SEvalZero #if PPP_OPTIONS
60*10465441SEvalZero /*
61*10465441SEvalZero * Command-line options.
62*10465441SEvalZero */
63*10465441SEvalZero static option_t pap_option_list[] = {
64*10465441SEvalZero { "hide-password", o_bool, &hide_password,
65*10465441SEvalZero "Don't output passwords to log", OPT_PRIO | 1 },
66*10465441SEvalZero { "show-password", o_bool, &hide_password,
67*10465441SEvalZero "Show password string in debug log messages", OPT_PRIOSUB | 0 },
68*10465441SEvalZero
69*10465441SEvalZero { "pap-restart", o_int, &upap[0].us_timeouttime,
70*10465441SEvalZero "Set retransmit timeout for PAP", OPT_PRIO },
71*10465441SEvalZero { "pap-max-authreq", o_int, &upap[0].us_maxtransmits,
72*10465441SEvalZero "Set max number of transmissions for auth-reqs", OPT_PRIO },
73*10465441SEvalZero { "pap-timeout", o_int, &upap[0].us_reqtimeout,
74*10465441SEvalZero "Set time limit for peer PAP authentication", OPT_PRIO },
75*10465441SEvalZero
76*10465441SEvalZero { NULL }
77*10465441SEvalZero };
78*10465441SEvalZero #endif /* PPP_OPTIONS */
79*10465441SEvalZero
80*10465441SEvalZero /*
81*10465441SEvalZero * Protocol entry points.
82*10465441SEvalZero */
83*10465441SEvalZero static void upap_init(ppp_pcb *pcb);
84*10465441SEvalZero static void upap_lowerup(ppp_pcb *pcb);
85*10465441SEvalZero static void upap_lowerdown(ppp_pcb *pcb);
86*10465441SEvalZero static void upap_input(ppp_pcb *pcb, u_char *inpacket, int l);
87*10465441SEvalZero static void upap_protrej(ppp_pcb *pcb);
88*10465441SEvalZero #if PRINTPKT_SUPPORT
89*10465441SEvalZero static int upap_printpkt(const u_char *p, int plen, void (*printer) (void *, const char *, ...), void *arg);
90*10465441SEvalZero #endif /* PRINTPKT_SUPPORT */
91*10465441SEvalZero
92*10465441SEvalZero const struct protent pap_protent = {
93*10465441SEvalZero PPP_PAP,
94*10465441SEvalZero upap_init,
95*10465441SEvalZero upap_input,
96*10465441SEvalZero upap_protrej,
97*10465441SEvalZero upap_lowerup,
98*10465441SEvalZero upap_lowerdown,
99*10465441SEvalZero NULL,
100*10465441SEvalZero NULL,
101*10465441SEvalZero #if PRINTPKT_SUPPORT
102*10465441SEvalZero upap_printpkt,
103*10465441SEvalZero #endif /* PRINTPKT_SUPPORT */
104*10465441SEvalZero #if PPP_DATAINPUT
105*10465441SEvalZero NULL,
106*10465441SEvalZero #endif /* PPP_DATAINPUT */
107*10465441SEvalZero #if PRINTPKT_SUPPORT
108*10465441SEvalZero "PAP",
109*10465441SEvalZero NULL,
110*10465441SEvalZero #endif /* PRINTPKT_SUPPORT */
111*10465441SEvalZero #if PPP_OPTIONS
112*10465441SEvalZero pap_option_list,
113*10465441SEvalZero NULL,
114*10465441SEvalZero #endif /* PPP_OPTIONS */
115*10465441SEvalZero #if DEMAND_SUPPORT
116*10465441SEvalZero NULL,
117*10465441SEvalZero NULL
118*10465441SEvalZero #endif /* DEMAND_SUPPORT */
119*10465441SEvalZero };
120*10465441SEvalZero
121*10465441SEvalZero static void upap_timeout(void *arg);
122*10465441SEvalZero #if PPP_SERVER
123*10465441SEvalZero static void upap_reqtimeout(void *arg);
124*10465441SEvalZero static void upap_rauthreq(ppp_pcb *pcb, u_char *inp, int id, int len);
125*10465441SEvalZero #endif /* PPP_SERVER */
126*10465441SEvalZero static void upap_rauthack(ppp_pcb *pcb, u_char *inp, int id, int len);
127*10465441SEvalZero static void upap_rauthnak(ppp_pcb *pcb, u_char *inp, int id, int len);
128*10465441SEvalZero static void upap_sauthreq(ppp_pcb *pcb);
129*10465441SEvalZero #if PPP_SERVER
130*10465441SEvalZero static void upap_sresp(ppp_pcb *pcb, u_char code, u_char id, const char *msg, int msglen);
131*10465441SEvalZero #endif /* PPP_SERVER */
132*10465441SEvalZero
133*10465441SEvalZero
134*10465441SEvalZero /*
135*10465441SEvalZero * upap_init - Initialize a UPAP unit.
136*10465441SEvalZero */
upap_init(ppp_pcb * pcb)137*10465441SEvalZero static void upap_init(ppp_pcb *pcb) {
138*10465441SEvalZero pcb->upap.us_user = NULL;
139*10465441SEvalZero pcb->upap.us_userlen = 0;
140*10465441SEvalZero pcb->upap.us_passwd = NULL;
141*10465441SEvalZero pcb->upap.us_passwdlen = 0;
142*10465441SEvalZero pcb->upap.us_clientstate = UPAPCS_INITIAL;
143*10465441SEvalZero #if PPP_SERVER
144*10465441SEvalZero pcb->upap.us_serverstate = UPAPSS_INITIAL;
145*10465441SEvalZero #endif /* PPP_SERVER */
146*10465441SEvalZero pcb->upap.us_id = 0;
147*10465441SEvalZero }
148*10465441SEvalZero
149*10465441SEvalZero
150*10465441SEvalZero /*
151*10465441SEvalZero * upap_authwithpeer - Authenticate us with our peer (start client).
152*10465441SEvalZero *
153*10465441SEvalZero * Set new state and send authenticate's.
154*10465441SEvalZero */
upap_authwithpeer(ppp_pcb * pcb,const char * user,const char * password)155*10465441SEvalZero void upap_authwithpeer(ppp_pcb *pcb, const char *user, const char *password) {
156*10465441SEvalZero
157*10465441SEvalZero if(!user || !password)
158*10465441SEvalZero return;
159*10465441SEvalZero
160*10465441SEvalZero /* Save the username and password we're given */
161*10465441SEvalZero pcb->upap.us_user = user;
162*10465441SEvalZero pcb->upap.us_userlen = LWIP_MIN(strlen(user), 0xff);
163*10465441SEvalZero pcb->upap.us_passwd = password;
164*10465441SEvalZero pcb->upap.us_passwdlen = LWIP_MIN(strlen(password), 0xff);
165*10465441SEvalZero pcb->upap.us_transmits = 0;
166*10465441SEvalZero
167*10465441SEvalZero /* Lower layer up yet? */
168*10465441SEvalZero if (pcb->upap.us_clientstate == UPAPCS_INITIAL ||
169*10465441SEvalZero pcb->upap.us_clientstate == UPAPCS_PENDING) {
170*10465441SEvalZero pcb->upap.us_clientstate = UPAPCS_PENDING;
171*10465441SEvalZero return;
172*10465441SEvalZero }
173*10465441SEvalZero
174*10465441SEvalZero upap_sauthreq(pcb); /* Start protocol */
175*10465441SEvalZero }
176*10465441SEvalZero
177*10465441SEvalZero #if PPP_SERVER
178*10465441SEvalZero /*
179*10465441SEvalZero * upap_authpeer - Authenticate our peer (start server).
180*10465441SEvalZero *
181*10465441SEvalZero * Set new state.
182*10465441SEvalZero */
upap_authpeer(ppp_pcb * pcb)183*10465441SEvalZero void upap_authpeer(ppp_pcb *pcb) {
184*10465441SEvalZero
185*10465441SEvalZero /* Lower layer up yet? */
186*10465441SEvalZero if (pcb->upap.us_serverstate == UPAPSS_INITIAL ||
187*10465441SEvalZero pcb->upap.us_serverstate == UPAPSS_PENDING) {
188*10465441SEvalZero pcb->upap.us_serverstate = UPAPSS_PENDING;
189*10465441SEvalZero return;
190*10465441SEvalZero }
191*10465441SEvalZero
192*10465441SEvalZero pcb->upap.us_serverstate = UPAPSS_LISTEN;
193*10465441SEvalZero if (pcb->settings.pap_req_timeout > 0)
194*10465441SEvalZero TIMEOUT(upap_reqtimeout, pcb, pcb->settings.pap_req_timeout);
195*10465441SEvalZero }
196*10465441SEvalZero #endif /* PPP_SERVER */
197*10465441SEvalZero
198*10465441SEvalZero /*
199*10465441SEvalZero * upap_timeout - Retransmission timer for sending auth-reqs expired.
200*10465441SEvalZero */
upap_timeout(void * arg)201*10465441SEvalZero static void upap_timeout(void *arg) {
202*10465441SEvalZero ppp_pcb *pcb = (ppp_pcb*)arg;
203*10465441SEvalZero
204*10465441SEvalZero if (pcb->upap.us_clientstate != UPAPCS_AUTHREQ)
205*10465441SEvalZero return;
206*10465441SEvalZero
207*10465441SEvalZero if (pcb->upap.us_transmits >= pcb->settings.pap_max_transmits) {
208*10465441SEvalZero /* give up in disgust */
209*10465441SEvalZero ppp_error("No response to PAP authenticate-requests");
210*10465441SEvalZero pcb->upap.us_clientstate = UPAPCS_BADAUTH;
211*10465441SEvalZero auth_withpeer_fail(pcb, PPP_PAP);
212*10465441SEvalZero return;
213*10465441SEvalZero }
214*10465441SEvalZero
215*10465441SEvalZero upap_sauthreq(pcb); /* Send Authenticate-Request */
216*10465441SEvalZero }
217*10465441SEvalZero
218*10465441SEvalZero
219*10465441SEvalZero #if PPP_SERVER
220*10465441SEvalZero /*
221*10465441SEvalZero * upap_reqtimeout - Give up waiting for the peer to send an auth-req.
222*10465441SEvalZero */
upap_reqtimeout(void * arg)223*10465441SEvalZero static void upap_reqtimeout(void *arg) {
224*10465441SEvalZero ppp_pcb *pcb = (ppp_pcb*)arg;
225*10465441SEvalZero
226*10465441SEvalZero if (pcb->upap.us_serverstate != UPAPSS_LISTEN)
227*10465441SEvalZero return; /* huh?? */
228*10465441SEvalZero
229*10465441SEvalZero auth_peer_fail(pcb, PPP_PAP);
230*10465441SEvalZero pcb->upap.us_serverstate = UPAPSS_BADAUTH;
231*10465441SEvalZero }
232*10465441SEvalZero #endif /* PPP_SERVER */
233*10465441SEvalZero
234*10465441SEvalZero
235*10465441SEvalZero /*
236*10465441SEvalZero * upap_lowerup - The lower layer is up.
237*10465441SEvalZero *
238*10465441SEvalZero * Start authenticating if pending.
239*10465441SEvalZero */
upap_lowerup(ppp_pcb * pcb)240*10465441SEvalZero static void upap_lowerup(ppp_pcb *pcb) {
241*10465441SEvalZero
242*10465441SEvalZero if (pcb->upap.us_clientstate == UPAPCS_INITIAL)
243*10465441SEvalZero pcb->upap.us_clientstate = UPAPCS_CLOSED;
244*10465441SEvalZero else if (pcb->upap.us_clientstate == UPAPCS_PENDING) {
245*10465441SEvalZero upap_sauthreq(pcb); /* send an auth-request */
246*10465441SEvalZero }
247*10465441SEvalZero
248*10465441SEvalZero #if PPP_SERVER
249*10465441SEvalZero if (pcb->upap.us_serverstate == UPAPSS_INITIAL)
250*10465441SEvalZero pcb->upap.us_serverstate = UPAPSS_CLOSED;
251*10465441SEvalZero else if (pcb->upap.us_serverstate == UPAPSS_PENDING) {
252*10465441SEvalZero pcb->upap.us_serverstate = UPAPSS_LISTEN;
253*10465441SEvalZero if (pcb->settings.pap_req_timeout > 0)
254*10465441SEvalZero TIMEOUT(upap_reqtimeout, pcb, pcb->settings.pap_req_timeout);
255*10465441SEvalZero }
256*10465441SEvalZero #endif /* PPP_SERVER */
257*10465441SEvalZero }
258*10465441SEvalZero
259*10465441SEvalZero
260*10465441SEvalZero /*
261*10465441SEvalZero * upap_lowerdown - The lower layer is down.
262*10465441SEvalZero *
263*10465441SEvalZero * Cancel all timeouts.
264*10465441SEvalZero */
upap_lowerdown(ppp_pcb * pcb)265*10465441SEvalZero static void upap_lowerdown(ppp_pcb *pcb) {
266*10465441SEvalZero
267*10465441SEvalZero if (pcb->upap.us_clientstate == UPAPCS_AUTHREQ) /* Timeout pending? */
268*10465441SEvalZero UNTIMEOUT(upap_timeout, pcb); /* Cancel timeout */
269*10465441SEvalZero #if PPP_SERVER
270*10465441SEvalZero if (pcb->upap.us_serverstate == UPAPSS_LISTEN && pcb->settings.pap_req_timeout > 0)
271*10465441SEvalZero UNTIMEOUT(upap_reqtimeout, pcb);
272*10465441SEvalZero #endif /* PPP_SERVER */
273*10465441SEvalZero
274*10465441SEvalZero pcb->upap.us_clientstate = UPAPCS_INITIAL;
275*10465441SEvalZero #if PPP_SERVER
276*10465441SEvalZero pcb->upap.us_serverstate = UPAPSS_INITIAL;
277*10465441SEvalZero #endif /* PPP_SERVER */
278*10465441SEvalZero }
279*10465441SEvalZero
280*10465441SEvalZero
281*10465441SEvalZero /*
282*10465441SEvalZero * upap_protrej - Peer doesn't speak this protocol.
283*10465441SEvalZero *
284*10465441SEvalZero * This shouldn't happen. In any case, pretend lower layer went down.
285*10465441SEvalZero */
upap_protrej(ppp_pcb * pcb)286*10465441SEvalZero static void upap_protrej(ppp_pcb *pcb) {
287*10465441SEvalZero
288*10465441SEvalZero if (pcb->upap.us_clientstate == UPAPCS_AUTHREQ) {
289*10465441SEvalZero ppp_error("PAP authentication failed due to protocol-reject");
290*10465441SEvalZero auth_withpeer_fail(pcb, PPP_PAP);
291*10465441SEvalZero }
292*10465441SEvalZero #if PPP_SERVER
293*10465441SEvalZero if (pcb->upap.us_serverstate == UPAPSS_LISTEN) {
294*10465441SEvalZero ppp_error("PAP authentication of peer failed (protocol-reject)");
295*10465441SEvalZero auth_peer_fail(pcb, PPP_PAP);
296*10465441SEvalZero }
297*10465441SEvalZero #endif /* PPP_SERVER */
298*10465441SEvalZero upap_lowerdown(pcb);
299*10465441SEvalZero }
300*10465441SEvalZero
301*10465441SEvalZero
302*10465441SEvalZero /*
303*10465441SEvalZero * upap_input - Input UPAP packet.
304*10465441SEvalZero */
upap_input(ppp_pcb * pcb,u_char * inpacket,int l)305*10465441SEvalZero static void upap_input(ppp_pcb *pcb, u_char *inpacket, int l) {
306*10465441SEvalZero u_char *inp;
307*10465441SEvalZero u_char code, id;
308*10465441SEvalZero int len;
309*10465441SEvalZero
310*10465441SEvalZero /*
311*10465441SEvalZero * Parse header (code, id and length).
312*10465441SEvalZero * If packet too short, drop it.
313*10465441SEvalZero */
314*10465441SEvalZero inp = inpacket;
315*10465441SEvalZero if (l < UPAP_HEADERLEN) {
316*10465441SEvalZero UPAPDEBUG(("pap_input: rcvd short header."));
317*10465441SEvalZero return;
318*10465441SEvalZero }
319*10465441SEvalZero GETCHAR(code, inp);
320*10465441SEvalZero GETCHAR(id, inp);
321*10465441SEvalZero GETSHORT(len, inp);
322*10465441SEvalZero if (len < UPAP_HEADERLEN) {
323*10465441SEvalZero UPAPDEBUG(("pap_input: rcvd illegal length."));
324*10465441SEvalZero return;
325*10465441SEvalZero }
326*10465441SEvalZero if (len > l) {
327*10465441SEvalZero UPAPDEBUG(("pap_input: rcvd short packet."));
328*10465441SEvalZero return;
329*10465441SEvalZero }
330*10465441SEvalZero len -= UPAP_HEADERLEN;
331*10465441SEvalZero
332*10465441SEvalZero /*
333*10465441SEvalZero * Action depends on code.
334*10465441SEvalZero */
335*10465441SEvalZero switch (code) {
336*10465441SEvalZero case UPAP_AUTHREQ:
337*10465441SEvalZero #if PPP_SERVER
338*10465441SEvalZero upap_rauthreq(pcb, inp, id, len);
339*10465441SEvalZero #endif /* PPP_SERVER */
340*10465441SEvalZero break;
341*10465441SEvalZero
342*10465441SEvalZero case UPAP_AUTHACK:
343*10465441SEvalZero upap_rauthack(pcb, inp, id, len);
344*10465441SEvalZero break;
345*10465441SEvalZero
346*10465441SEvalZero case UPAP_AUTHNAK:
347*10465441SEvalZero upap_rauthnak(pcb, inp, id, len);
348*10465441SEvalZero break;
349*10465441SEvalZero
350*10465441SEvalZero default: /* XXX Need code reject */
351*10465441SEvalZero break;
352*10465441SEvalZero }
353*10465441SEvalZero }
354*10465441SEvalZero
355*10465441SEvalZero #if PPP_SERVER
356*10465441SEvalZero /*
357*10465441SEvalZero * upap_rauth - Receive Authenticate.
358*10465441SEvalZero */
upap_rauthreq(ppp_pcb * pcb,u_char * inp,int id,int len)359*10465441SEvalZero static void upap_rauthreq(ppp_pcb *pcb, u_char *inp, int id, int len) {
360*10465441SEvalZero u_char ruserlen, rpasswdlen;
361*10465441SEvalZero char *ruser;
362*10465441SEvalZero char *rpasswd;
363*10465441SEvalZero char rhostname[256];
364*10465441SEvalZero int retcode;
365*10465441SEvalZero const char *msg;
366*10465441SEvalZero int msglen;
367*10465441SEvalZero
368*10465441SEvalZero if (pcb->upap.us_serverstate < UPAPSS_LISTEN)
369*10465441SEvalZero return;
370*10465441SEvalZero
371*10465441SEvalZero /*
372*10465441SEvalZero * If we receive a duplicate authenticate-request, we are
373*10465441SEvalZero * supposed to return the same status as for the first request.
374*10465441SEvalZero */
375*10465441SEvalZero if (pcb->upap.us_serverstate == UPAPSS_OPEN) {
376*10465441SEvalZero upap_sresp(pcb, UPAP_AUTHACK, id, "", 0); /* return auth-ack */
377*10465441SEvalZero return;
378*10465441SEvalZero }
379*10465441SEvalZero if (pcb->upap.us_serverstate == UPAPSS_BADAUTH) {
380*10465441SEvalZero upap_sresp(pcb, UPAP_AUTHNAK, id, "", 0); /* return auth-nak */
381*10465441SEvalZero return;
382*10465441SEvalZero }
383*10465441SEvalZero
384*10465441SEvalZero /*
385*10465441SEvalZero * Parse user/passwd.
386*10465441SEvalZero */
387*10465441SEvalZero if (len < 1) {
388*10465441SEvalZero UPAPDEBUG(("pap_rauth: rcvd short packet."));
389*10465441SEvalZero return;
390*10465441SEvalZero }
391*10465441SEvalZero GETCHAR(ruserlen, inp);
392*10465441SEvalZero len -= sizeof (u_char) + ruserlen + sizeof (u_char);
393*10465441SEvalZero if (len < 0) {
394*10465441SEvalZero UPAPDEBUG(("pap_rauth: rcvd short packet."));
395*10465441SEvalZero return;
396*10465441SEvalZero }
397*10465441SEvalZero ruser = (char *) inp;
398*10465441SEvalZero INCPTR(ruserlen, inp);
399*10465441SEvalZero GETCHAR(rpasswdlen, inp);
400*10465441SEvalZero if (len < rpasswdlen) {
401*10465441SEvalZero UPAPDEBUG(("pap_rauth: rcvd short packet."));
402*10465441SEvalZero return;
403*10465441SEvalZero }
404*10465441SEvalZero
405*10465441SEvalZero rpasswd = (char *) inp;
406*10465441SEvalZero
407*10465441SEvalZero /*
408*10465441SEvalZero * Check the username and password given.
409*10465441SEvalZero */
410*10465441SEvalZero retcode = UPAP_AUTHNAK;
411*10465441SEvalZero if (auth_check_passwd(pcb, ruser, ruserlen, rpasswd, rpasswdlen, &msg, &msglen)) {
412*10465441SEvalZero retcode = UPAP_AUTHACK;
413*10465441SEvalZero }
414*10465441SEvalZero BZERO(rpasswd, rpasswdlen);
415*10465441SEvalZero
416*10465441SEvalZero #if 0 /* UNUSED */
417*10465441SEvalZero /*
418*10465441SEvalZero * Check remote number authorization. A plugin may have filled in
419*10465441SEvalZero * the remote number or added an allowed number, and rather than
420*10465441SEvalZero * return an authenticate failure, is leaving it for us to verify.
421*10465441SEvalZero */
422*10465441SEvalZero if (retcode == UPAP_AUTHACK) {
423*10465441SEvalZero if (!auth_number()) {
424*10465441SEvalZero /* We do not want to leak info about the pap result. */
425*10465441SEvalZero retcode = UPAP_AUTHNAK; /* XXX exit value will be "wrong" */
426*10465441SEvalZero warn("calling number %q is not authorized", remote_number);
427*10465441SEvalZero }
428*10465441SEvalZero }
429*10465441SEvalZero
430*10465441SEvalZero msglen = strlen(msg);
431*10465441SEvalZero if (msglen > 255)
432*10465441SEvalZero msglen = 255;
433*10465441SEvalZero #endif /* UNUSED */
434*10465441SEvalZero
435*10465441SEvalZero upap_sresp(pcb, retcode, id, msg, msglen);
436*10465441SEvalZero
437*10465441SEvalZero /* Null terminate and clean remote name. */
438*10465441SEvalZero ppp_slprintf(rhostname, sizeof(rhostname), "%.*v", ruserlen, ruser);
439*10465441SEvalZero
440*10465441SEvalZero if (retcode == UPAP_AUTHACK) {
441*10465441SEvalZero pcb->upap.us_serverstate = UPAPSS_OPEN;
442*10465441SEvalZero ppp_notice("PAP peer authentication succeeded for %q", rhostname);
443*10465441SEvalZero auth_peer_success(pcb, PPP_PAP, 0, ruser, ruserlen);
444*10465441SEvalZero } else {
445*10465441SEvalZero pcb->upap.us_serverstate = UPAPSS_BADAUTH;
446*10465441SEvalZero ppp_warn("PAP peer authentication failed for %q", rhostname);
447*10465441SEvalZero auth_peer_fail(pcb, PPP_PAP);
448*10465441SEvalZero }
449*10465441SEvalZero
450*10465441SEvalZero if (pcb->settings.pap_req_timeout > 0)
451*10465441SEvalZero UNTIMEOUT(upap_reqtimeout, pcb);
452*10465441SEvalZero }
453*10465441SEvalZero #endif /* PPP_SERVER */
454*10465441SEvalZero
455*10465441SEvalZero /*
456*10465441SEvalZero * upap_rauthack - Receive Authenticate-Ack.
457*10465441SEvalZero */
upap_rauthack(ppp_pcb * pcb,u_char * inp,int id,int len)458*10465441SEvalZero static void upap_rauthack(ppp_pcb *pcb, u_char *inp, int id, int len) {
459*10465441SEvalZero u_char msglen;
460*10465441SEvalZero char *msg;
461*10465441SEvalZero LWIP_UNUSED_ARG(id);
462*10465441SEvalZero
463*10465441SEvalZero if (pcb->upap.us_clientstate != UPAPCS_AUTHREQ) /* XXX */
464*10465441SEvalZero return;
465*10465441SEvalZero
466*10465441SEvalZero /*
467*10465441SEvalZero * Parse message.
468*10465441SEvalZero */
469*10465441SEvalZero if (len < 1) {
470*10465441SEvalZero UPAPDEBUG(("pap_rauthack: ignoring missing msg-length."));
471*10465441SEvalZero } else {
472*10465441SEvalZero GETCHAR(msglen, inp);
473*10465441SEvalZero if (msglen > 0) {
474*10465441SEvalZero len -= sizeof (u_char);
475*10465441SEvalZero if (len < msglen) {
476*10465441SEvalZero UPAPDEBUG(("pap_rauthack: rcvd short packet."));
477*10465441SEvalZero return;
478*10465441SEvalZero }
479*10465441SEvalZero msg = (char *) inp;
480*10465441SEvalZero PRINTMSG(msg, msglen);
481*10465441SEvalZero }
482*10465441SEvalZero }
483*10465441SEvalZero
484*10465441SEvalZero pcb->upap.us_clientstate = UPAPCS_OPEN;
485*10465441SEvalZero
486*10465441SEvalZero auth_withpeer_success(pcb, PPP_PAP, 0);
487*10465441SEvalZero }
488*10465441SEvalZero
489*10465441SEvalZero
490*10465441SEvalZero /*
491*10465441SEvalZero * upap_rauthnak - Receive Authenticate-Nak.
492*10465441SEvalZero */
upap_rauthnak(ppp_pcb * pcb,u_char * inp,int id,int len)493*10465441SEvalZero static void upap_rauthnak(ppp_pcb *pcb, u_char *inp, int id, int len) {
494*10465441SEvalZero u_char msglen;
495*10465441SEvalZero char *msg;
496*10465441SEvalZero LWIP_UNUSED_ARG(id);
497*10465441SEvalZero
498*10465441SEvalZero if (pcb->upap.us_clientstate != UPAPCS_AUTHREQ) /* XXX */
499*10465441SEvalZero return;
500*10465441SEvalZero
501*10465441SEvalZero /*
502*10465441SEvalZero * Parse message.
503*10465441SEvalZero */
504*10465441SEvalZero if (len < 1) {
505*10465441SEvalZero UPAPDEBUG(("pap_rauthnak: ignoring missing msg-length."));
506*10465441SEvalZero } else {
507*10465441SEvalZero GETCHAR(msglen, inp);
508*10465441SEvalZero if (msglen > 0) {
509*10465441SEvalZero len -= sizeof (u_char);
510*10465441SEvalZero if (len < msglen) {
511*10465441SEvalZero UPAPDEBUG(("pap_rauthnak: rcvd short packet."));
512*10465441SEvalZero return;
513*10465441SEvalZero }
514*10465441SEvalZero msg = (char *) inp;
515*10465441SEvalZero PRINTMSG(msg, msglen);
516*10465441SEvalZero }
517*10465441SEvalZero }
518*10465441SEvalZero
519*10465441SEvalZero pcb->upap.us_clientstate = UPAPCS_BADAUTH;
520*10465441SEvalZero
521*10465441SEvalZero ppp_error("PAP authentication failed");
522*10465441SEvalZero auth_withpeer_fail(pcb, PPP_PAP);
523*10465441SEvalZero }
524*10465441SEvalZero
525*10465441SEvalZero
526*10465441SEvalZero /*
527*10465441SEvalZero * upap_sauthreq - Send an Authenticate-Request.
528*10465441SEvalZero */
upap_sauthreq(ppp_pcb * pcb)529*10465441SEvalZero static void upap_sauthreq(ppp_pcb *pcb) {
530*10465441SEvalZero struct pbuf *p;
531*10465441SEvalZero u_char *outp;
532*10465441SEvalZero int outlen;
533*10465441SEvalZero
534*10465441SEvalZero outlen = UPAP_HEADERLEN + 2 * sizeof (u_char) +
535*10465441SEvalZero pcb->upap.us_userlen + pcb->upap.us_passwdlen;
536*10465441SEvalZero p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN +outlen), PPP_CTRL_PBUF_TYPE);
537*10465441SEvalZero if(NULL == p)
538*10465441SEvalZero return;
539*10465441SEvalZero if(p->tot_len != p->len) {
540*10465441SEvalZero pbuf_free(p);
541*10465441SEvalZero return;
542*10465441SEvalZero }
543*10465441SEvalZero
544*10465441SEvalZero outp = (u_char*)p->payload;
545*10465441SEvalZero MAKEHEADER(outp, PPP_PAP);
546*10465441SEvalZero
547*10465441SEvalZero PUTCHAR(UPAP_AUTHREQ, outp);
548*10465441SEvalZero PUTCHAR(++pcb->upap.us_id, outp);
549*10465441SEvalZero PUTSHORT(outlen, outp);
550*10465441SEvalZero PUTCHAR(pcb->upap.us_userlen, outp);
551*10465441SEvalZero MEMCPY(outp, pcb->upap.us_user, pcb->upap.us_userlen);
552*10465441SEvalZero INCPTR(pcb->upap.us_userlen, outp);
553*10465441SEvalZero PUTCHAR(pcb->upap.us_passwdlen, outp);
554*10465441SEvalZero MEMCPY(outp, pcb->upap.us_passwd, pcb->upap.us_passwdlen);
555*10465441SEvalZero
556*10465441SEvalZero ppp_write(pcb, p);
557*10465441SEvalZero
558*10465441SEvalZero TIMEOUT(upap_timeout, pcb, pcb->settings.pap_timeout_time);
559*10465441SEvalZero ++pcb->upap.us_transmits;
560*10465441SEvalZero pcb->upap.us_clientstate = UPAPCS_AUTHREQ;
561*10465441SEvalZero }
562*10465441SEvalZero
563*10465441SEvalZero #if PPP_SERVER
564*10465441SEvalZero /*
565*10465441SEvalZero * upap_sresp - Send a response (ack or nak).
566*10465441SEvalZero */
upap_sresp(ppp_pcb * pcb,u_char code,u_char id,const char * msg,int msglen)567*10465441SEvalZero static void upap_sresp(ppp_pcb *pcb, u_char code, u_char id, const char *msg, int msglen) {
568*10465441SEvalZero struct pbuf *p;
569*10465441SEvalZero u_char *outp;
570*10465441SEvalZero int outlen;
571*10465441SEvalZero
572*10465441SEvalZero outlen = UPAP_HEADERLEN + sizeof (u_char) + msglen;
573*10465441SEvalZero p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN +outlen), PPP_CTRL_PBUF_TYPE);
574*10465441SEvalZero if(NULL == p)
575*10465441SEvalZero return;
576*10465441SEvalZero if(p->tot_len != p->len) {
577*10465441SEvalZero pbuf_free(p);
578*10465441SEvalZero return;
579*10465441SEvalZero }
580*10465441SEvalZero
581*10465441SEvalZero outp = (u_char*)p->payload;
582*10465441SEvalZero MAKEHEADER(outp, PPP_PAP);
583*10465441SEvalZero
584*10465441SEvalZero PUTCHAR(code, outp);
585*10465441SEvalZero PUTCHAR(id, outp);
586*10465441SEvalZero PUTSHORT(outlen, outp);
587*10465441SEvalZero PUTCHAR(msglen, outp);
588*10465441SEvalZero MEMCPY(outp, msg, msglen);
589*10465441SEvalZero
590*10465441SEvalZero ppp_write(pcb, p);
591*10465441SEvalZero }
592*10465441SEvalZero #endif /* PPP_SERVER */
593*10465441SEvalZero
594*10465441SEvalZero #if PRINTPKT_SUPPORT
595*10465441SEvalZero /*
596*10465441SEvalZero * upap_printpkt - print the contents of a PAP packet.
597*10465441SEvalZero */
598*10465441SEvalZero static const char* const upap_codenames[] = {
599*10465441SEvalZero "AuthReq", "AuthAck", "AuthNak"
600*10465441SEvalZero };
601*10465441SEvalZero
upap_printpkt(const u_char * p,int plen,void (* printer)(void *,const char *,...),void * arg)602*10465441SEvalZero static int upap_printpkt(const u_char *p, int plen, void (*printer) (void *, const char *, ...), void *arg) {
603*10465441SEvalZero int code, id, len;
604*10465441SEvalZero int mlen, ulen, wlen;
605*10465441SEvalZero const u_char *user, *pwd, *msg;
606*10465441SEvalZero const u_char *pstart;
607*10465441SEvalZero
608*10465441SEvalZero if (plen < UPAP_HEADERLEN)
609*10465441SEvalZero return 0;
610*10465441SEvalZero pstart = p;
611*10465441SEvalZero GETCHAR(code, p);
612*10465441SEvalZero GETCHAR(id, p);
613*10465441SEvalZero GETSHORT(len, p);
614*10465441SEvalZero if (len < UPAP_HEADERLEN || len > plen)
615*10465441SEvalZero return 0;
616*10465441SEvalZero
617*10465441SEvalZero if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(upap_codenames))
618*10465441SEvalZero printer(arg, " %s", upap_codenames[code-1]);
619*10465441SEvalZero else
620*10465441SEvalZero printer(arg, " code=0x%x", code);
621*10465441SEvalZero printer(arg, " id=0x%x", id);
622*10465441SEvalZero len -= UPAP_HEADERLEN;
623*10465441SEvalZero switch (code) {
624*10465441SEvalZero case UPAP_AUTHREQ:
625*10465441SEvalZero if (len < 1)
626*10465441SEvalZero break;
627*10465441SEvalZero ulen = p[0];
628*10465441SEvalZero if (len < ulen + 2)
629*10465441SEvalZero break;
630*10465441SEvalZero wlen = p[ulen + 1];
631*10465441SEvalZero if (len < ulen + wlen + 2)
632*10465441SEvalZero break;
633*10465441SEvalZero user = (const u_char *) (p + 1);
634*10465441SEvalZero pwd = (const u_char *) (p + ulen + 2);
635*10465441SEvalZero p += ulen + wlen + 2;
636*10465441SEvalZero len -= ulen + wlen + 2;
637*10465441SEvalZero printer(arg, " user=");
638*10465441SEvalZero ppp_print_string(user, ulen, printer, arg);
639*10465441SEvalZero printer(arg, " password=");
640*10465441SEvalZero /* FIXME: require ppp_pcb struct as printpkt() argument */
641*10465441SEvalZero #if 0
642*10465441SEvalZero if (!pcb->settings.hide_password)
643*10465441SEvalZero #endif
644*10465441SEvalZero ppp_print_string(pwd, wlen, printer, arg);
645*10465441SEvalZero #if 0
646*10465441SEvalZero else
647*10465441SEvalZero printer(arg, "<hidden>");
648*10465441SEvalZero #endif
649*10465441SEvalZero break;
650*10465441SEvalZero case UPAP_AUTHACK:
651*10465441SEvalZero case UPAP_AUTHNAK:
652*10465441SEvalZero if (len < 1)
653*10465441SEvalZero break;
654*10465441SEvalZero mlen = p[0];
655*10465441SEvalZero if (len < mlen + 1)
656*10465441SEvalZero break;
657*10465441SEvalZero msg = (const u_char *) (p + 1);
658*10465441SEvalZero p += mlen + 1;
659*10465441SEvalZero len -= mlen + 1;
660*10465441SEvalZero printer(arg, " ");
661*10465441SEvalZero ppp_print_string(msg, mlen, printer, arg);
662*10465441SEvalZero break;
663*10465441SEvalZero default:
664*10465441SEvalZero break;
665*10465441SEvalZero }
666*10465441SEvalZero
667*10465441SEvalZero /* print the rest of the bytes in the packet */
668*10465441SEvalZero for (; len > 0; --len) {
669*10465441SEvalZero GETCHAR(code, p);
670*10465441SEvalZero printer(arg, " %.2x", code);
671*10465441SEvalZero }
672*10465441SEvalZero
673*10465441SEvalZero return p - pstart;
674*10465441SEvalZero }
675*10465441SEvalZero #endif /* PRINTPKT_SUPPORT */
676*10465441SEvalZero
677*10465441SEvalZero #endif /* PPP_SUPPORT && PAP_SUPPORT */
678