1195972f6Sopenharmony_ci/*
2195972f6Sopenharmony_ci * upap.c - User/Password Authentication Protocol.
3195972f6Sopenharmony_ci *
4195972f6Sopenharmony_ci * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved.
5195972f6Sopenharmony_ci *
6195972f6Sopenharmony_ci * Redistribution and use in source and binary forms, with or without
7195972f6Sopenharmony_ci * modification, are permitted provided that the following conditions
8195972f6Sopenharmony_ci * are met:
9195972f6Sopenharmony_ci *
10195972f6Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright
11195972f6Sopenharmony_ci *    notice, this list of conditions and the following disclaimer.
12195972f6Sopenharmony_ci *
13195972f6Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright
14195972f6Sopenharmony_ci *    notice, this list of conditions and the following disclaimer in
15195972f6Sopenharmony_ci *    the documentation and/or other materials provided with the
16195972f6Sopenharmony_ci *    distribution.
17195972f6Sopenharmony_ci *
18195972f6Sopenharmony_ci * 3. The name "Carnegie Mellon University" must not be used to
19195972f6Sopenharmony_ci *    endorse or promote products derived from this software without
20195972f6Sopenharmony_ci *    prior written permission. For permission or any legal
21195972f6Sopenharmony_ci *    details, please contact
22195972f6Sopenharmony_ci *      Office of Technology Transfer
23195972f6Sopenharmony_ci *      Carnegie Mellon University
24195972f6Sopenharmony_ci *      5000 Forbes Avenue
25195972f6Sopenharmony_ci *      Pittsburgh, PA  15213-3890
26195972f6Sopenharmony_ci *      (412) 268-4387, fax: (412) 268-7395
27195972f6Sopenharmony_ci *      tech-transfer@andrew.cmu.edu
28195972f6Sopenharmony_ci *
29195972f6Sopenharmony_ci * 4. Redistributions of any form whatsoever must retain the following
30195972f6Sopenharmony_ci *    acknowledgment:
31195972f6Sopenharmony_ci *    "This product includes software developed by Computing Services
32195972f6Sopenharmony_ci *     at Carnegie Mellon University (http://www.cmu.edu/computing/)."
33195972f6Sopenharmony_ci *
34195972f6Sopenharmony_ci * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
35195972f6Sopenharmony_ci * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
36195972f6Sopenharmony_ci * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
37195972f6Sopenharmony_ci * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
38195972f6Sopenharmony_ci * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
39195972f6Sopenharmony_ci * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
40195972f6Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
41195972f6Sopenharmony_ci */
42195972f6Sopenharmony_ci
43195972f6Sopenharmony_ci#include "netif/ppp/ppp_opts.h"
44195972f6Sopenharmony_ci#if PPP_SUPPORT && PAP_SUPPORT  /* don't build if not configured for use in lwipopts.h */
45195972f6Sopenharmony_ci
46195972f6Sopenharmony_ci/*
47195972f6Sopenharmony_ci * @todo:
48195972f6Sopenharmony_ci */
49195972f6Sopenharmony_ci
50195972f6Sopenharmony_ci#if 0 /* UNUSED */
51195972f6Sopenharmony_ci#include <stdio.h>
52195972f6Sopenharmony_ci#include <string.h>
53195972f6Sopenharmony_ci#endif /* UNUSED */
54195972f6Sopenharmony_ci
55195972f6Sopenharmony_ci#include "netif/ppp/ppp_impl.h"
56195972f6Sopenharmony_ci
57195972f6Sopenharmony_ci#include "netif/ppp/upap.h"
58195972f6Sopenharmony_ci
59195972f6Sopenharmony_ci#if PPP_OPTIONS
60195972f6Sopenharmony_ci/*
61195972f6Sopenharmony_ci * Command-line options.
62195972f6Sopenharmony_ci */
63195972f6Sopenharmony_cistatic option_t pap_option_list[] = {
64195972f6Sopenharmony_ci    { "hide-password", o_bool, &hide_password,
65195972f6Sopenharmony_ci      "Don't output passwords to log", OPT_PRIO | 1 },
66195972f6Sopenharmony_ci    { "show-password", o_bool, &hide_password,
67195972f6Sopenharmony_ci      "Show password string in debug log messages", OPT_PRIOSUB | 0 },
68195972f6Sopenharmony_ci
69195972f6Sopenharmony_ci    { "pap-restart", o_int, &upap[0].us_timeouttime,
70195972f6Sopenharmony_ci      "Set retransmit timeout for PAP", OPT_PRIO },
71195972f6Sopenharmony_ci    { "pap-max-authreq", o_int, &upap[0].us_maxtransmits,
72195972f6Sopenharmony_ci      "Set max number of transmissions for auth-reqs", OPT_PRIO },
73195972f6Sopenharmony_ci    { "pap-timeout", o_int, &upap[0].us_reqtimeout,
74195972f6Sopenharmony_ci      "Set time limit for peer PAP authentication", OPT_PRIO },
75195972f6Sopenharmony_ci
76195972f6Sopenharmony_ci    { NULL }
77195972f6Sopenharmony_ci};
78195972f6Sopenharmony_ci#endif /* PPP_OPTIONS */
79195972f6Sopenharmony_ci
80195972f6Sopenharmony_ci/*
81195972f6Sopenharmony_ci * Protocol entry points.
82195972f6Sopenharmony_ci */
83195972f6Sopenharmony_cistatic void upap_init(ppp_pcb *pcb);
84195972f6Sopenharmony_cistatic void upap_lowerup(ppp_pcb *pcb);
85195972f6Sopenharmony_cistatic void upap_lowerdown(ppp_pcb *pcb);
86195972f6Sopenharmony_cistatic void upap_input(ppp_pcb *pcb, u_char *inpacket, int l);
87195972f6Sopenharmony_cistatic void upap_protrej(ppp_pcb *pcb);
88195972f6Sopenharmony_ci#if PRINTPKT_SUPPORT
89195972f6Sopenharmony_cistatic int upap_printpkt(const u_char *p, int plen, void (*printer) (void *, const char *, ...), void *arg);
90195972f6Sopenharmony_ci#endif /* PRINTPKT_SUPPORT */
91195972f6Sopenharmony_ci
92195972f6Sopenharmony_ciconst struct protent pap_protent = {
93195972f6Sopenharmony_ci    PPP_PAP,
94195972f6Sopenharmony_ci    upap_init,
95195972f6Sopenharmony_ci    upap_input,
96195972f6Sopenharmony_ci    upap_protrej,
97195972f6Sopenharmony_ci    upap_lowerup,
98195972f6Sopenharmony_ci    upap_lowerdown,
99195972f6Sopenharmony_ci    NULL,
100195972f6Sopenharmony_ci    NULL,
101195972f6Sopenharmony_ci#if PRINTPKT_SUPPORT
102195972f6Sopenharmony_ci    upap_printpkt,
103195972f6Sopenharmony_ci#endif /* PRINTPKT_SUPPORT */
104195972f6Sopenharmony_ci#if PPP_DATAINPUT
105195972f6Sopenharmony_ci    NULL,
106195972f6Sopenharmony_ci#endif /* PPP_DATAINPUT */
107195972f6Sopenharmony_ci#if PRINTPKT_SUPPORT
108195972f6Sopenharmony_ci    "PAP",
109195972f6Sopenharmony_ci    NULL,
110195972f6Sopenharmony_ci#endif /* PRINTPKT_SUPPORT */
111195972f6Sopenharmony_ci#if PPP_OPTIONS
112195972f6Sopenharmony_ci    pap_option_list,
113195972f6Sopenharmony_ci    NULL,
114195972f6Sopenharmony_ci#endif /* PPP_OPTIONS */
115195972f6Sopenharmony_ci#if DEMAND_SUPPORT
116195972f6Sopenharmony_ci    NULL,
117195972f6Sopenharmony_ci    NULL
118195972f6Sopenharmony_ci#endif /* DEMAND_SUPPORT */
119195972f6Sopenharmony_ci};
120195972f6Sopenharmony_ci
121195972f6Sopenharmony_cistatic void upap_timeout(void *arg);
122195972f6Sopenharmony_ci#if PPP_SERVER
123195972f6Sopenharmony_cistatic void upap_reqtimeout(void *arg);
124195972f6Sopenharmony_cistatic void upap_rauthreq(ppp_pcb *pcb, u_char *inp, int id, int len);
125195972f6Sopenharmony_ci#endif /* PPP_SERVER */
126195972f6Sopenharmony_cistatic void upap_rauthack(ppp_pcb *pcb, u_char *inp, int id, int len);
127195972f6Sopenharmony_cistatic void upap_rauthnak(ppp_pcb *pcb, u_char *inp, int id, int len);
128195972f6Sopenharmony_cistatic void upap_sauthreq(ppp_pcb *pcb);
129195972f6Sopenharmony_ci#if PPP_SERVER
130195972f6Sopenharmony_cistatic void upap_sresp(ppp_pcb *pcb, u_char code, u_char id, const char *msg, int msglen);
131195972f6Sopenharmony_ci#endif /* PPP_SERVER */
132195972f6Sopenharmony_ci
133195972f6Sopenharmony_ci
134195972f6Sopenharmony_ci/*
135195972f6Sopenharmony_ci * upap_init - Initialize a UPAP unit.
136195972f6Sopenharmony_ci */
137195972f6Sopenharmony_cistatic void upap_init(ppp_pcb *pcb) {
138195972f6Sopenharmony_ci    pcb->upap.us_user = NULL;
139195972f6Sopenharmony_ci    pcb->upap.us_userlen = 0;
140195972f6Sopenharmony_ci    pcb->upap.us_passwd = NULL;
141195972f6Sopenharmony_ci    pcb->upap.us_passwdlen = 0;
142195972f6Sopenharmony_ci    pcb->upap.us_clientstate = UPAPCS_INITIAL;
143195972f6Sopenharmony_ci#if PPP_SERVER
144195972f6Sopenharmony_ci    pcb->upap.us_serverstate = UPAPSS_INITIAL;
145195972f6Sopenharmony_ci#endif /* PPP_SERVER */
146195972f6Sopenharmony_ci    pcb->upap.us_id = 0;
147195972f6Sopenharmony_ci}
148195972f6Sopenharmony_ci
149195972f6Sopenharmony_ci
150195972f6Sopenharmony_ci/*
151195972f6Sopenharmony_ci * upap_authwithpeer - Authenticate us with our peer (start client).
152195972f6Sopenharmony_ci *
153195972f6Sopenharmony_ci * Set new state and send authenticate's.
154195972f6Sopenharmony_ci */
155195972f6Sopenharmony_civoid upap_authwithpeer(ppp_pcb *pcb, const char *user, const char *password) {
156195972f6Sopenharmony_ci
157195972f6Sopenharmony_ci    if(!user || !password)
158195972f6Sopenharmony_ci        return;
159195972f6Sopenharmony_ci
160195972f6Sopenharmony_ci    /* Save the username and password we're given */
161195972f6Sopenharmony_ci    pcb->upap.us_user = user;
162195972f6Sopenharmony_ci    pcb->upap.us_userlen = (u8_t)LWIP_MIN(strlen(user), 0xff);
163195972f6Sopenharmony_ci    pcb->upap.us_passwd = password;
164195972f6Sopenharmony_ci    pcb->upap.us_passwdlen = (u8_t)LWIP_MIN(strlen(password), 0xff);
165195972f6Sopenharmony_ci    pcb->upap.us_transmits = 0;
166195972f6Sopenharmony_ci
167195972f6Sopenharmony_ci    /* Lower layer up yet? */
168195972f6Sopenharmony_ci    if (pcb->upap.us_clientstate == UPAPCS_INITIAL ||
169195972f6Sopenharmony_ci	pcb->upap.us_clientstate == UPAPCS_PENDING) {
170195972f6Sopenharmony_ci	pcb->upap.us_clientstate = UPAPCS_PENDING;
171195972f6Sopenharmony_ci	return;
172195972f6Sopenharmony_ci    }
173195972f6Sopenharmony_ci
174195972f6Sopenharmony_ci    upap_sauthreq(pcb);		/* Start protocol */
175195972f6Sopenharmony_ci}
176195972f6Sopenharmony_ci
177195972f6Sopenharmony_ci#if PPP_SERVER
178195972f6Sopenharmony_ci/*
179195972f6Sopenharmony_ci * upap_authpeer - Authenticate our peer (start server).
180195972f6Sopenharmony_ci *
181195972f6Sopenharmony_ci * Set new state.
182195972f6Sopenharmony_ci */
183195972f6Sopenharmony_civoid upap_authpeer(ppp_pcb *pcb) {
184195972f6Sopenharmony_ci
185195972f6Sopenharmony_ci    /* Lower layer up yet? */
186195972f6Sopenharmony_ci    if (pcb->upap.us_serverstate == UPAPSS_INITIAL ||
187195972f6Sopenharmony_ci	pcb->upap.us_serverstate == UPAPSS_PENDING) {
188195972f6Sopenharmony_ci	pcb->upap.us_serverstate = UPAPSS_PENDING;
189195972f6Sopenharmony_ci	return;
190195972f6Sopenharmony_ci    }
191195972f6Sopenharmony_ci
192195972f6Sopenharmony_ci    pcb->upap.us_serverstate = UPAPSS_LISTEN;
193195972f6Sopenharmony_ci    if (pcb->settings.pap_req_timeout > 0)
194195972f6Sopenharmony_ci	TIMEOUT(upap_reqtimeout, pcb, pcb->settings.pap_req_timeout);
195195972f6Sopenharmony_ci}
196195972f6Sopenharmony_ci#endif /* PPP_SERVER */
197195972f6Sopenharmony_ci
198195972f6Sopenharmony_ci/*
199195972f6Sopenharmony_ci * upap_timeout - Retransmission timer for sending auth-reqs expired.
200195972f6Sopenharmony_ci */
201195972f6Sopenharmony_cistatic void upap_timeout(void *arg) {
202195972f6Sopenharmony_ci    ppp_pcb *pcb = (ppp_pcb*)arg;
203195972f6Sopenharmony_ci
204195972f6Sopenharmony_ci    if (pcb->upap.us_clientstate != UPAPCS_AUTHREQ)
205195972f6Sopenharmony_ci	return;
206195972f6Sopenharmony_ci
207195972f6Sopenharmony_ci    if (pcb->upap.us_transmits >= pcb->settings.pap_max_transmits) {
208195972f6Sopenharmony_ci	/* give up in disgust */
209195972f6Sopenharmony_ci	ppp_error("No response to PAP authenticate-requests");
210195972f6Sopenharmony_ci	pcb->upap.us_clientstate = UPAPCS_BADAUTH;
211195972f6Sopenharmony_ci	auth_withpeer_fail(pcb, PPP_PAP);
212195972f6Sopenharmony_ci	return;
213195972f6Sopenharmony_ci    }
214195972f6Sopenharmony_ci
215195972f6Sopenharmony_ci    upap_sauthreq(pcb);		/* Send Authenticate-Request */
216195972f6Sopenharmony_ci}
217195972f6Sopenharmony_ci
218195972f6Sopenharmony_ci
219195972f6Sopenharmony_ci#if PPP_SERVER
220195972f6Sopenharmony_ci/*
221195972f6Sopenharmony_ci * upap_reqtimeout - Give up waiting for the peer to send an auth-req.
222195972f6Sopenharmony_ci */
223195972f6Sopenharmony_cistatic void upap_reqtimeout(void *arg) {
224195972f6Sopenharmony_ci    ppp_pcb *pcb = (ppp_pcb*)arg;
225195972f6Sopenharmony_ci
226195972f6Sopenharmony_ci    if (pcb->upap.us_serverstate != UPAPSS_LISTEN)
227195972f6Sopenharmony_ci	return;			/* huh?? */
228195972f6Sopenharmony_ci
229195972f6Sopenharmony_ci    auth_peer_fail(pcb, PPP_PAP);
230195972f6Sopenharmony_ci    pcb->upap.us_serverstate = UPAPSS_BADAUTH;
231195972f6Sopenharmony_ci}
232195972f6Sopenharmony_ci#endif /* PPP_SERVER */
233195972f6Sopenharmony_ci
234195972f6Sopenharmony_ci
235195972f6Sopenharmony_ci/*
236195972f6Sopenharmony_ci * upap_lowerup - The lower layer is up.
237195972f6Sopenharmony_ci *
238195972f6Sopenharmony_ci * Start authenticating if pending.
239195972f6Sopenharmony_ci */
240195972f6Sopenharmony_cistatic void upap_lowerup(ppp_pcb *pcb) {
241195972f6Sopenharmony_ci
242195972f6Sopenharmony_ci    if (pcb->upap.us_clientstate == UPAPCS_INITIAL)
243195972f6Sopenharmony_ci	pcb->upap.us_clientstate = UPAPCS_CLOSED;
244195972f6Sopenharmony_ci    else if (pcb->upap.us_clientstate == UPAPCS_PENDING) {
245195972f6Sopenharmony_ci	upap_sauthreq(pcb);	/* send an auth-request */
246195972f6Sopenharmony_ci    }
247195972f6Sopenharmony_ci
248195972f6Sopenharmony_ci#if PPP_SERVER
249195972f6Sopenharmony_ci    if (pcb->upap.us_serverstate == UPAPSS_INITIAL)
250195972f6Sopenharmony_ci	pcb->upap.us_serverstate = UPAPSS_CLOSED;
251195972f6Sopenharmony_ci    else if (pcb->upap.us_serverstate == UPAPSS_PENDING) {
252195972f6Sopenharmony_ci	pcb->upap.us_serverstate = UPAPSS_LISTEN;
253195972f6Sopenharmony_ci	if (pcb->settings.pap_req_timeout > 0)
254195972f6Sopenharmony_ci	    TIMEOUT(upap_reqtimeout, pcb, pcb->settings.pap_req_timeout);
255195972f6Sopenharmony_ci    }
256195972f6Sopenharmony_ci#endif /* PPP_SERVER */
257195972f6Sopenharmony_ci}
258195972f6Sopenharmony_ci
259195972f6Sopenharmony_ci
260195972f6Sopenharmony_ci/*
261195972f6Sopenharmony_ci * upap_lowerdown - The lower layer is down.
262195972f6Sopenharmony_ci *
263195972f6Sopenharmony_ci * Cancel all timeouts.
264195972f6Sopenharmony_ci */
265195972f6Sopenharmony_cistatic void upap_lowerdown(ppp_pcb *pcb) {
266195972f6Sopenharmony_ci
267195972f6Sopenharmony_ci    if (pcb->upap.us_clientstate == UPAPCS_AUTHREQ)	/* Timeout pending? */
268195972f6Sopenharmony_ci	UNTIMEOUT(upap_timeout, pcb);		/* Cancel timeout */
269195972f6Sopenharmony_ci#if PPP_SERVER
270195972f6Sopenharmony_ci    if (pcb->upap.us_serverstate == UPAPSS_LISTEN && pcb->settings.pap_req_timeout > 0)
271195972f6Sopenharmony_ci	UNTIMEOUT(upap_reqtimeout, pcb);
272195972f6Sopenharmony_ci#endif /* PPP_SERVER */
273195972f6Sopenharmony_ci
274195972f6Sopenharmony_ci    pcb->upap.us_clientstate = UPAPCS_INITIAL;
275195972f6Sopenharmony_ci#if PPP_SERVER
276195972f6Sopenharmony_ci    pcb->upap.us_serverstate = UPAPSS_INITIAL;
277195972f6Sopenharmony_ci#endif /* PPP_SERVER */
278195972f6Sopenharmony_ci}
279195972f6Sopenharmony_ci
280195972f6Sopenharmony_ci
281195972f6Sopenharmony_ci/*
282195972f6Sopenharmony_ci * upap_protrej - Peer doesn't speak this protocol.
283195972f6Sopenharmony_ci *
284195972f6Sopenharmony_ci * This shouldn't happen.  In any case, pretend lower layer went down.
285195972f6Sopenharmony_ci */
286195972f6Sopenharmony_cistatic void upap_protrej(ppp_pcb *pcb) {
287195972f6Sopenharmony_ci
288195972f6Sopenharmony_ci    if (pcb->upap.us_clientstate == UPAPCS_AUTHREQ) {
289195972f6Sopenharmony_ci	ppp_error("PAP authentication failed due to protocol-reject");
290195972f6Sopenharmony_ci	auth_withpeer_fail(pcb, PPP_PAP);
291195972f6Sopenharmony_ci    }
292195972f6Sopenharmony_ci#if PPP_SERVER
293195972f6Sopenharmony_ci    if (pcb->upap.us_serverstate == UPAPSS_LISTEN) {
294195972f6Sopenharmony_ci	ppp_error("PAP authentication of peer failed (protocol-reject)");
295195972f6Sopenharmony_ci	auth_peer_fail(pcb, PPP_PAP);
296195972f6Sopenharmony_ci    }
297195972f6Sopenharmony_ci#endif /* PPP_SERVER */
298195972f6Sopenharmony_ci    upap_lowerdown(pcb);
299195972f6Sopenharmony_ci}
300195972f6Sopenharmony_ci
301195972f6Sopenharmony_ci
302195972f6Sopenharmony_ci/*
303195972f6Sopenharmony_ci * upap_input - Input UPAP packet.
304195972f6Sopenharmony_ci */
305195972f6Sopenharmony_cistatic void upap_input(ppp_pcb *pcb, u_char *inpacket, int l) {
306195972f6Sopenharmony_ci    u_char *inp;
307195972f6Sopenharmony_ci    u_char code, id;
308195972f6Sopenharmony_ci    int len;
309195972f6Sopenharmony_ci
310195972f6Sopenharmony_ci    /*
311195972f6Sopenharmony_ci     * Parse header (code, id and length).
312195972f6Sopenharmony_ci     * If packet too short, drop it.
313195972f6Sopenharmony_ci     */
314195972f6Sopenharmony_ci    inp = inpacket;
315195972f6Sopenharmony_ci    if (l < UPAP_HEADERLEN) {
316195972f6Sopenharmony_ci	UPAPDEBUG(("pap_input: rcvd short header."));
317195972f6Sopenharmony_ci	return;
318195972f6Sopenharmony_ci    }
319195972f6Sopenharmony_ci    GETCHAR(code, inp);
320195972f6Sopenharmony_ci    GETCHAR(id, inp);
321195972f6Sopenharmony_ci    GETSHORT(len, inp);
322195972f6Sopenharmony_ci    if (len < UPAP_HEADERLEN) {
323195972f6Sopenharmony_ci	UPAPDEBUG(("pap_input: rcvd illegal length."));
324195972f6Sopenharmony_ci	return;
325195972f6Sopenharmony_ci    }
326195972f6Sopenharmony_ci    if (len > l) {
327195972f6Sopenharmony_ci	UPAPDEBUG(("pap_input: rcvd short packet."));
328195972f6Sopenharmony_ci	return;
329195972f6Sopenharmony_ci    }
330195972f6Sopenharmony_ci    len -= UPAP_HEADERLEN;
331195972f6Sopenharmony_ci
332195972f6Sopenharmony_ci    /*
333195972f6Sopenharmony_ci     * Action depends on code.
334195972f6Sopenharmony_ci     */
335195972f6Sopenharmony_ci    switch (code) {
336195972f6Sopenharmony_ci    case UPAP_AUTHREQ:
337195972f6Sopenharmony_ci#if PPP_SERVER
338195972f6Sopenharmony_ci	upap_rauthreq(pcb, inp, id, len);
339195972f6Sopenharmony_ci#endif /* PPP_SERVER */
340195972f6Sopenharmony_ci	break;
341195972f6Sopenharmony_ci
342195972f6Sopenharmony_ci    case UPAP_AUTHACK:
343195972f6Sopenharmony_ci	upap_rauthack(pcb, inp, id, len);
344195972f6Sopenharmony_ci	break;
345195972f6Sopenharmony_ci
346195972f6Sopenharmony_ci    case UPAP_AUTHNAK:
347195972f6Sopenharmony_ci	upap_rauthnak(pcb, inp, id, len);
348195972f6Sopenharmony_ci	break;
349195972f6Sopenharmony_ci
350195972f6Sopenharmony_ci    default:				/* XXX Need code reject */
351195972f6Sopenharmony_ci	break;
352195972f6Sopenharmony_ci    }
353195972f6Sopenharmony_ci}
354195972f6Sopenharmony_ci
355195972f6Sopenharmony_ci#if PPP_SERVER
356195972f6Sopenharmony_ci/*
357195972f6Sopenharmony_ci * upap_rauth - Receive Authenticate.
358195972f6Sopenharmony_ci */
359195972f6Sopenharmony_cistatic void upap_rauthreq(ppp_pcb *pcb, u_char *inp, int id, int len) {
360195972f6Sopenharmony_ci    u_char ruserlen, rpasswdlen;
361195972f6Sopenharmony_ci    char *ruser;
362195972f6Sopenharmony_ci    char *rpasswd;
363195972f6Sopenharmony_ci    char rhostname[256];
364195972f6Sopenharmony_ci    int retcode;
365195972f6Sopenharmony_ci    const char *msg;
366195972f6Sopenharmony_ci    int msglen;
367195972f6Sopenharmony_ci
368195972f6Sopenharmony_ci    if (pcb->upap.us_serverstate < UPAPSS_LISTEN)
369195972f6Sopenharmony_ci	return;
370195972f6Sopenharmony_ci
371195972f6Sopenharmony_ci    /*
372195972f6Sopenharmony_ci     * If we receive a duplicate authenticate-request, we are
373195972f6Sopenharmony_ci     * supposed to return the same status as for the first request.
374195972f6Sopenharmony_ci     */
375195972f6Sopenharmony_ci    if (pcb->upap.us_serverstate == UPAPSS_OPEN) {
376195972f6Sopenharmony_ci	upap_sresp(pcb, UPAP_AUTHACK, id, "", 0);	/* return auth-ack */
377195972f6Sopenharmony_ci	return;
378195972f6Sopenharmony_ci    }
379195972f6Sopenharmony_ci    if (pcb->upap.us_serverstate == UPAPSS_BADAUTH) {
380195972f6Sopenharmony_ci	upap_sresp(pcb, UPAP_AUTHNAK, id, "", 0);	/* return auth-nak */
381195972f6Sopenharmony_ci	return;
382195972f6Sopenharmony_ci    }
383195972f6Sopenharmony_ci
384195972f6Sopenharmony_ci    /*
385195972f6Sopenharmony_ci     * Parse user/passwd.
386195972f6Sopenharmony_ci     */
387195972f6Sopenharmony_ci    if (len < 1) {
388195972f6Sopenharmony_ci	UPAPDEBUG(("pap_rauth: rcvd short packet."));
389195972f6Sopenharmony_ci	return;
390195972f6Sopenharmony_ci    }
391195972f6Sopenharmony_ci    GETCHAR(ruserlen, inp);
392195972f6Sopenharmony_ci    len -= sizeof (u_char) + ruserlen + sizeof (u_char);
393195972f6Sopenharmony_ci    if (len < 0) {
394195972f6Sopenharmony_ci	UPAPDEBUG(("pap_rauth: rcvd short packet."));
395195972f6Sopenharmony_ci	return;
396195972f6Sopenharmony_ci    }
397195972f6Sopenharmony_ci    ruser = (char *) inp;
398195972f6Sopenharmony_ci    INCPTR(ruserlen, inp);
399195972f6Sopenharmony_ci    GETCHAR(rpasswdlen, inp);
400195972f6Sopenharmony_ci    if (len < rpasswdlen) {
401195972f6Sopenharmony_ci	UPAPDEBUG(("pap_rauth: rcvd short packet."));
402195972f6Sopenharmony_ci	return;
403195972f6Sopenharmony_ci    }
404195972f6Sopenharmony_ci
405195972f6Sopenharmony_ci    rpasswd = (char *) inp;
406195972f6Sopenharmony_ci
407195972f6Sopenharmony_ci    /*
408195972f6Sopenharmony_ci     * Check the username and password given.
409195972f6Sopenharmony_ci     */
410195972f6Sopenharmony_ci    retcode = UPAP_AUTHNAK;
411195972f6Sopenharmony_ci    if (auth_check_passwd(pcb, ruser, ruserlen, rpasswd, rpasswdlen, &msg, &msglen)) {
412195972f6Sopenharmony_ci      retcode = UPAP_AUTHACK;
413195972f6Sopenharmony_ci    }
414195972f6Sopenharmony_ci    BZERO(rpasswd, rpasswdlen);
415195972f6Sopenharmony_ci
416195972f6Sopenharmony_ci#if 0 /* UNUSED */
417195972f6Sopenharmony_ci    /*
418195972f6Sopenharmony_ci     * Check remote number authorization.  A plugin may have filled in
419195972f6Sopenharmony_ci     * the remote number or added an allowed number, and rather than
420195972f6Sopenharmony_ci     * return an authenticate failure, is leaving it for us to verify.
421195972f6Sopenharmony_ci     */
422195972f6Sopenharmony_ci    if (retcode == UPAP_AUTHACK) {
423195972f6Sopenharmony_ci	if (!auth_number()) {
424195972f6Sopenharmony_ci	    /* We do not want to leak info about the pap result. */
425195972f6Sopenharmony_ci	    retcode = UPAP_AUTHNAK; /* XXX exit value will be "wrong" */
426195972f6Sopenharmony_ci	    warn("calling number %q is not authorized", remote_number);
427195972f6Sopenharmony_ci	}
428195972f6Sopenharmony_ci    }
429195972f6Sopenharmony_ci
430195972f6Sopenharmony_ci    msglen = strlen(msg);
431195972f6Sopenharmony_ci    if (msglen > 255)
432195972f6Sopenharmony_ci	msglen = 255;
433195972f6Sopenharmony_ci#endif /* UNUSED */
434195972f6Sopenharmony_ci
435195972f6Sopenharmony_ci    upap_sresp(pcb, retcode, id, msg, msglen);
436195972f6Sopenharmony_ci
437195972f6Sopenharmony_ci    /* Null terminate and clean remote name. */
438195972f6Sopenharmony_ci    ppp_slprintf(rhostname, sizeof(rhostname), "%.*v", ruserlen, ruser);
439195972f6Sopenharmony_ci
440195972f6Sopenharmony_ci    if (retcode == UPAP_AUTHACK) {
441195972f6Sopenharmony_ci	pcb->upap.us_serverstate = UPAPSS_OPEN;
442195972f6Sopenharmony_ci	ppp_notice("PAP peer authentication succeeded for %q", rhostname);
443195972f6Sopenharmony_ci	auth_peer_success(pcb, PPP_PAP, 0, ruser, ruserlen);
444195972f6Sopenharmony_ci    } else {
445195972f6Sopenharmony_ci	pcb->upap.us_serverstate = UPAPSS_BADAUTH;
446195972f6Sopenharmony_ci	ppp_warn("PAP peer authentication failed for %q", rhostname);
447195972f6Sopenharmony_ci	auth_peer_fail(pcb, PPP_PAP);
448195972f6Sopenharmony_ci    }
449195972f6Sopenharmony_ci
450195972f6Sopenharmony_ci    if (pcb->settings.pap_req_timeout > 0)
451195972f6Sopenharmony_ci	UNTIMEOUT(upap_reqtimeout, pcb);
452195972f6Sopenharmony_ci}
453195972f6Sopenharmony_ci#endif /* PPP_SERVER */
454195972f6Sopenharmony_ci
455195972f6Sopenharmony_ci/*
456195972f6Sopenharmony_ci * upap_rauthack - Receive Authenticate-Ack.
457195972f6Sopenharmony_ci */
458195972f6Sopenharmony_cistatic void upap_rauthack(ppp_pcb *pcb, u_char *inp, int id, int len) {
459195972f6Sopenharmony_ci    u_char msglen;
460195972f6Sopenharmony_ci    char *msg;
461195972f6Sopenharmony_ci    LWIP_UNUSED_ARG(id);
462195972f6Sopenharmony_ci
463195972f6Sopenharmony_ci    if (pcb->upap.us_clientstate != UPAPCS_AUTHREQ) /* XXX */
464195972f6Sopenharmony_ci	return;
465195972f6Sopenharmony_ci
466195972f6Sopenharmony_ci    /*
467195972f6Sopenharmony_ci     * Parse message.
468195972f6Sopenharmony_ci     */
469195972f6Sopenharmony_ci    if (len < 1) {
470195972f6Sopenharmony_ci	UPAPDEBUG(("pap_rauthack: ignoring missing msg-length."));
471195972f6Sopenharmony_ci    } else {
472195972f6Sopenharmony_ci	GETCHAR(msglen, inp);
473195972f6Sopenharmony_ci	if (msglen > 0) {
474195972f6Sopenharmony_ci	    len -= sizeof (u_char);
475195972f6Sopenharmony_ci	    if (len < msglen) {
476195972f6Sopenharmony_ci		UPAPDEBUG(("pap_rauthack: rcvd short packet."));
477195972f6Sopenharmony_ci		return;
478195972f6Sopenharmony_ci	    }
479195972f6Sopenharmony_ci	    msg = (char *) inp;
480195972f6Sopenharmony_ci	    PRINTMSG(msg, msglen);
481195972f6Sopenharmony_ci	}
482195972f6Sopenharmony_ci    }
483195972f6Sopenharmony_ci
484195972f6Sopenharmony_ci    pcb->upap.us_clientstate = UPAPCS_OPEN;
485195972f6Sopenharmony_ci
486195972f6Sopenharmony_ci    auth_withpeer_success(pcb, PPP_PAP, 0);
487195972f6Sopenharmony_ci}
488195972f6Sopenharmony_ci
489195972f6Sopenharmony_ci
490195972f6Sopenharmony_ci/*
491195972f6Sopenharmony_ci * upap_rauthnak - Receive Authenticate-Nak.
492195972f6Sopenharmony_ci */
493195972f6Sopenharmony_cistatic void upap_rauthnak(ppp_pcb *pcb, u_char *inp, int id, int len) {
494195972f6Sopenharmony_ci    u_char msglen;
495195972f6Sopenharmony_ci    char *msg;
496195972f6Sopenharmony_ci    LWIP_UNUSED_ARG(id);
497195972f6Sopenharmony_ci
498195972f6Sopenharmony_ci    if (pcb->upap.us_clientstate != UPAPCS_AUTHREQ) /* XXX */
499195972f6Sopenharmony_ci	return;
500195972f6Sopenharmony_ci
501195972f6Sopenharmony_ci    /*
502195972f6Sopenharmony_ci     * Parse message.
503195972f6Sopenharmony_ci     */
504195972f6Sopenharmony_ci    if (len < 1) {
505195972f6Sopenharmony_ci	UPAPDEBUG(("pap_rauthnak: ignoring missing msg-length."));
506195972f6Sopenharmony_ci    } else {
507195972f6Sopenharmony_ci	GETCHAR(msglen, inp);
508195972f6Sopenharmony_ci	if (msglen > 0) {
509195972f6Sopenharmony_ci	    len -= sizeof (u_char);
510195972f6Sopenharmony_ci	    if (len < msglen) {
511195972f6Sopenharmony_ci		UPAPDEBUG(("pap_rauthnak: rcvd short packet."));
512195972f6Sopenharmony_ci		return;
513195972f6Sopenharmony_ci	    }
514195972f6Sopenharmony_ci	    msg = (char *) inp;
515195972f6Sopenharmony_ci	    PRINTMSG(msg, msglen);
516195972f6Sopenharmony_ci	}
517195972f6Sopenharmony_ci    }
518195972f6Sopenharmony_ci
519195972f6Sopenharmony_ci    pcb->upap.us_clientstate = UPAPCS_BADAUTH;
520195972f6Sopenharmony_ci
521195972f6Sopenharmony_ci    ppp_error("PAP authentication failed");
522195972f6Sopenharmony_ci    auth_withpeer_fail(pcb, PPP_PAP);
523195972f6Sopenharmony_ci}
524195972f6Sopenharmony_ci
525195972f6Sopenharmony_ci
526195972f6Sopenharmony_ci/*
527195972f6Sopenharmony_ci * upap_sauthreq - Send an Authenticate-Request.
528195972f6Sopenharmony_ci */
529195972f6Sopenharmony_cistatic void upap_sauthreq(ppp_pcb *pcb) {
530195972f6Sopenharmony_ci    struct pbuf *p;
531195972f6Sopenharmony_ci    u_char *outp;
532195972f6Sopenharmony_ci    int outlen;
533195972f6Sopenharmony_ci
534195972f6Sopenharmony_ci    outlen = UPAP_HEADERLEN + 2 * sizeof (u_char) +
535195972f6Sopenharmony_ci	pcb->upap.us_userlen + pcb->upap.us_passwdlen;
536195972f6Sopenharmony_ci    p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN +outlen), PPP_CTRL_PBUF_TYPE);
537195972f6Sopenharmony_ci    if(NULL == p)
538195972f6Sopenharmony_ci        return;
539195972f6Sopenharmony_ci    if(p->tot_len != p->len) {
540195972f6Sopenharmony_ci        pbuf_free(p);
541195972f6Sopenharmony_ci        return;
542195972f6Sopenharmony_ci    }
543195972f6Sopenharmony_ci
544195972f6Sopenharmony_ci    outp = (u_char*)p->payload;
545195972f6Sopenharmony_ci    MAKEHEADER(outp, PPP_PAP);
546195972f6Sopenharmony_ci
547195972f6Sopenharmony_ci    PUTCHAR(UPAP_AUTHREQ, outp);
548195972f6Sopenharmony_ci    PUTCHAR(++pcb->upap.us_id, outp);
549195972f6Sopenharmony_ci    PUTSHORT(outlen, outp);
550195972f6Sopenharmony_ci    PUTCHAR(pcb->upap.us_userlen, outp);
551195972f6Sopenharmony_ci    MEMCPY(outp, pcb->upap.us_user, pcb->upap.us_userlen);
552195972f6Sopenharmony_ci    INCPTR(pcb->upap.us_userlen, outp);
553195972f6Sopenharmony_ci    PUTCHAR(pcb->upap.us_passwdlen, outp);
554195972f6Sopenharmony_ci    MEMCPY(outp, pcb->upap.us_passwd, pcb->upap.us_passwdlen);
555195972f6Sopenharmony_ci
556195972f6Sopenharmony_ci    ppp_write(pcb, p);
557195972f6Sopenharmony_ci
558195972f6Sopenharmony_ci    TIMEOUT(upap_timeout, pcb, pcb->settings.pap_timeout_time);
559195972f6Sopenharmony_ci    ++pcb->upap.us_transmits;
560195972f6Sopenharmony_ci    pcb->upap.us_clientstate = UPAPCS_AUTHREQ;
561195972f6Sopenharmony_ci}
562195972f6Sopenharmony_ci
563195972f6Sopenharmony_ci#if PPP_SERVER
564195972f6Sopenharmony_ci/*
565195972f6Sopenharmony_ci * upap_sresp - Send a response (ack or nak).
566195972f6Sopenharmony_ci */
567195972f6Sopenharmony_cistatic void upap_sresp(ppp_pcb *pcb, u_char code, u_char id, const char *msg, int msglen) {
568195972f6Sopenharmony_ci    struct pbuf *p;
569195972f6Sopenharmony_ci    u_char *outp;
570195972f6Sopenharmony_ci    int outlen;
571195972f6Sopenharmony_ci
572195972f6Sopenharmony_ci    outlen = UPAP_HEADERLEN + sizeof (u_char) + msglen;
573195972f6Sopenharmony_ci    p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN +outlen), PPP_CTRL_PBUF_TYPE);
574195972f6Sopenharmony_ci    if(NULL == p)
575195972f6Sopenharmony_ci        return;
576195972f6Sopenharmony_ci    if(p->tot_len != p->len) {
577195972f6Sopenharmony_ci        pbuf_free(p);
578195972f6Sopenharmony_ci        return;
579195972f6Sopenharmony_ci    }
580195972f6Sopenharmony_ci
581195972f6Sopenharmony_ci    outp = (u_char*)p->payload;
582195972f6Sopenharmony_ci    MAKEHEADER(outp, PPP_PAP);
583195972f6Sopenharmony_ci
584195972f6Sopenharmony_ci    PUTCHAR(code, outp);
585195972f6Sopenharmony_ci    PUTCHAR(id, outp);
586195972f6Sopenharmony_ci    PUTSHORT(outlen, outp);
587195972f6Sopenharmony_ci    PUTCHAR(msglen, outp);
588195972f6Sopenharmony_ci    MEMCPY(outp, msg, msglen);
589195972f6Sopenharmony_ci
590195972f6Sopenharmony_ci    ppp_write(pcb, p);
591195972f6Sopenharmony_ci}
592195972f6Sopenharmony_ci#endif /* PPP_SERVER */
593195972f6Sopenharmony_ci
594195972f6Sopenharmony_ci#if PRINTPKT_SUPPORT
595195972f6Sopenharmony_ci/*
596195972f6Sopenharmony_ci * upap_printpkt - print the contents of a PAP packet.
597195972f6Sopenharmony_ci */
598195972f6Sopenharmony_cistatic const char* const upap_codenames[] = {
599195972f6Sopenharmony_ci    "AuthReq", "AuthAck", "AuthNak"
600195972f6Sopenharmony_ci};
601195972f6Sopenharmony_ci
602195972f6Sopenharmony_cistatic int upap_printpkt(const u_char *p, int plen, void (*printer) (void *, const char *, ...), void *arg) {
603195972f6Sopenharmony_ci    int code, id, len;
604195972f6Sopenharmony_ci    int mlen, ulen, wlen;
605195972f6Sopenharmony_ci    const u_char *user, *pwd, *msg;
606195972f6Sopenharmony_ci    const u_char *pstart;
607195972f6Sopenharmony_ci
608195972f6Sopenharmony_ci    if (plen < UPAP_HEADERLEN)
609195972f6Sopenharmony_ci	return 0;
610195972f6Sopenharmony_ci    pstart = p;
611195972f6Sopenharmony_ci    GETCHAR(code, p);
612195972f6Sopenharmony_ci    GETCHAR(id, p);
613195972f6Sopenharmony_ci    GETSHORT(len, p);
614195972f6Sopenharmony_ci    if (len < UPAP_HEADERLEN || len > plen)
615195972f6Sopenharmony_ci	return 0;
616195972f6Sopenharmony_ci
617195972f6Sopenharmony_ci    if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(upap_codenames))
618195972f6Sopenharmony_ci	printer(arg, " %s", upap_codenames[code-1]);
619195972f6Sopenharmony_ci    else
620195972f6Sopenharmony_ci	printer(arg, " code=0x%x", code);
621195972f6Sopenharmony_ci    printer(arg, " id=0x%x", id);
622195972f6Sopenharmony_ci    len -= UPAP_HEADERLEN;
623195972f6Sopenharmony_ci    switch (code) {
624195972f6Sopenharmony_ci    case UPAP_AUTHREQ:
625195972f6Sopenharmony_ci	if (len < 1)
626195972f6Sopenharmony_ci	    break;
627195972f6Sopenharmony_ci	ulen = p[0];
628195972f6Sopenharmony_ci	if (len < ulen + 2)
629195972f6Sopenharmony_ci	    break;
630195972f6Sopenharmony_ci	wlen = p[ulen + 1];
631195972f6Sopenharmony_ci	if (len < ulen + wlen + 2)
632195972f6Sopenharmony_ci	    break;
633195972f6Sopenharmony_ci	user = (const u_char *) (p + 1);
634195972f6Sopenharmony_ci	pwd = (const u_char *) (p + ulen + 2);
635195972f6Sopenharmony_ci	p += ulen + wlen + 2;
636195972f6Sopenharmony_ci	len -= ulen + wlen + 2;
637195972f6Sopenharmony_ci	printer(arg, " user=");
638195972f6Sopenharmony_ci	ppp_print_string(user, ulen, printer, arg);
639195972f6Sopenharmony_ci	printer(arg, " password=");
640195972f6Sopenharmony_ci/* FIXME: require ppp_pcb struct as printpkt() argument */
641195972f6Sopenharmony_ci#if 0
642195972f6Sopenharmony_ci	if (!pcb->settings.hide_password)
643195972f6Sopenharmony_ci#endif
644195972f6Sopenharmony_ci	    ppp_print_string(pwd, wlen, printer, arg);
645195972f6Sopenharmony_ci#if 0
646195972f6Sopenharmony_ci	else
647195972f6Sopenharmony_ci	    printer(arg, "<hidden>");
648195972f6Sopenharmony_ci#endif
649195972f6Sopenharmony_ci	break;
650195972f6Sopenharmony_ci    case UPAP_AUTHACK:
651195972f6Sopenharmony_ci    case UPAP_AUTHNAK:
652195972f6Sopenharmony_ci	if (len < 1)
653195972f6Sopenharmony_ci	    break;
654195972f6Sopenharmony_ci	mlen = p[0];
655195972f6Sopenharmony_ci	if (len < mlen + 1)
656195972f6Sopenharmony_ci	    break;
657195972f6Sopenharmony_ci	msg = (const u_char *) (p + 1);
658195972f6Sopenharmony_ci	p += mlen + 1;
659195972f6Sopenharmony_ci	len -= mlen + 1;
660195972f6Sopenharmony_ci	printer(arg, " ");
661195972f6Sopenharmony_ci	ppp_print_string(msg, mlen, printer, arg);
662195972f6Sopenharmony_ci	break;
663195972f6Sopenharmony_ci    default:
664195972f6Sopenharmony_ci	break;
665195972f6Sopenharmony_ci    }
666195972f6Sopenharmony_ci
667195972f6Sopenharmony_ci    /* print the rest of the bytes in the packet */
668195972f6Sopenharmony_ci    for (; len > 0; --len) {
669195972f6Sopenharmony_ci	GETCHAR(code, p);
670195972f6Sopenharmony_ci	printer(arg, " %.2x", code);
671195972f6Sopenharmony_ci    }
672195972f6Sopenharmony_ci
673195972f6Sopenharmony_ci    return p - pstart;
674195972f6Sopenharmony_ci}
675195972f6Sopenharmony_ci#endif /* PRINTPKT_SUPPORT */
676195972f6Sopenharmony_ci
677195972f6Sopenharmony_ci#endif /* PPP_SUPPORT && PAP_SUPPORT */
678