1/*	$OpenBSD: lcp.c,v 1.18 2019/02/27 04:52:19 denis Exp $ */
2
3/*-
4 * Copyright (c) 2009 Internet Initiative Japan Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28/* $Id: lcp.c,v 1.18 2019/02/27 04:52:19 denis Exp $ */
29/**@file
30 * This file provides LCP related functions.
31 *<pre>
32 * RFC1661: The Point-to-Point Protocol (PPP)
33 * RFC1570:  PPP LCP Extensions
34 *</pre>
35 */
36#include <sys/types.h>
37#include <sys/socket.h>
38#include <sys/time.h>
39#include <netinet/in.h>
40#include <net/if_dl.h>
41#include <stdlib.h>
42#include <stdio.h>
43#include <syslog.h>
44#include <string.h>
45#include <event.h>
46#include <ctype.h>
47
48#include "npppd.h"
49#include "ppp.h"
50#include "psm-opt.h"
51
52#define	SPACE	" \t\r\n"
53
54#include "debugutil.h"
55
56#ifdef	LCP_DEBUG
57#define	LCP_DBG(x)	fsm_log x
58#define	LCP_ASSERT(x)	ASSERT(x)
59#else
60#define	LCP_DBG(x)
61#define	LCP_ASSERT(x)
62#endif
63
64#define	PROTREJ			0x08
65#define	ECHOREQ			0x09
66#define	ECHOREP			0x0a
67#define	IDENTIFICATION		0x0c
68
69static void  lcp_resetci(fsm *);
70static void  lcp_addci(fsm *, u_char *, int *);
71static int   lcp_reqci(fsm *, u_char *, int *, int);
72static int   lcp_ackci(fsm *, u_char *, int);
73static int   lcp_nakci(fsm *, u_char *, int);
74static int   lcp_rejci(fsm *, u_char *, int);
75static int   lcp_cilen(fsm *);
76static void  lcp_open(fsm *);
77static void  lcp_down(fsm *);
78static void  lcp_finished(fsm *);
79static int   lcp_ext(fsm *, int, int, u_char *, int);
80static void  lcp_timeout(void *);
81static void  lcp_reset_timeout(void *);
82static int   lcp_proxy_recv_ci(fsm *, u_char *, int);
83static int   lcp_proxy_sent_ci(fsm *, u_char *, int);
84static void  lcp_load_authconfig(fsm *f);
85
86static struct fsm_callbacks lcp_callbacks = {
87	lcp_resetci,	/* Reset our Configuration Information */
88	lcp_cilen,	/* Length of our Configuration Information */
89	lcp_addci,	/* Add our Configuration Information */
90	lcp_ackci,	/* ACK our Configuration Information */
91	lcp_nakci,	/* NAK our Configuration Information */
92	lcp_rejci,	/* Reject our Configuration Information */
93	lcp_reqci,	/* Request peer's Configuration Information */
94	lcp_open,	/* Called when fsm reaches OPENED state */
95	lcp_down,	/* Called when fsm leaves OPENED state */
96	NULL,		/* Called when we want the lower layer up */
97	lcp_finished,	/* Called when we want the lower layer down */
98	NULL,		/* Called when Protocol-Reject received */
99	NULL,		/* Retransmission is necessary */
100	lcp_ext,	/* Called to handle LCP-specific codes */
101	"lcp"		/* String name of protocol */
102};
103#define	NO_AUTH_AGREEABLE(lcp)	\
104    (!psm_opt_is_enabled(lcp, pap) || psm_opt_is_rejected(lcp, pap)) &&	    \
105    (!psm_opt_is_enabled(lcp, chap) || psm_opt_is_rejected(lcp, chap)) &&   \
106    (!psm_opt_is_enabled(lcp, chapms) || psm_opt_is_rejected(lcp, chapms)) &&\
107    (!psm_opt_is_enabled(lcp, chapms_v2) || psm_opt_is_rejected(lcp, chapms_v2)) && \
108    (!psm_opt_is_enabled(lcp, eap) || psm_opt_is_rejected(lcp, eap))
109
110
111/** initializing context for LCP. */
112void
113lcp_init(lcp *_this, npppd_ppp *ppp)
114{
115	struct tunnconf *conf;
116
117	fsm_init(&_this->fsm);
118
119	_this->fsm.ppp = ppp;
120	_this->fsm.callbacks = &lcp_callbacks;
121	_this->fsm.protocol = PPP_PROTO_LCP;
122	_this->fsm.flags |= OPT_SILENT;
123	_this->timerctx.ctx = _this;
124
125	_this->recv_ress = 0;
126	_this->recv_reqs = 0;
127	_this->magic_number = arc4random();
128
129	conf = ppp_get_tunnconf(ppp);
130	PPP_FSM_CONFIG(&_this->fsm, timeouttime, conf->lcp_timeout);
131	PPP_FSM_CONFIG(&_this->fsm, maxconfreqtransmits,
132	    conf->lcp_max_configure);
133	PPP_FSM_CONFIG(&_this->fsm, maxtermtransmits,
134	    conf->lcp_max_terminate);
135	PPP_FSM_CONFIG(&_this->fsm, maxnakloops,
136	    conf->lcp_max_nak_loop);
137
138	_this->echo_failures = 0;
139	if (!conf->lcp_keepalive)
140		_this->echo_interval = 0;
141	else {
142		_this->echo_interval = conf->lcp_keepalive_interval;
143		_this->echo_retry_interval = conf->lcp_keepalive_retry_interval;
144		_this->echo_max_retries = conf->lcp_keepalive_max_retries;
145	}
146	_this->auth_order[0] = -1;
147}
148
149
150/**
151 * This function is called when HDLC as LCP's lower layer is up.
152 */
153void
154lcp_lowerup(lcp *_this)
155{
156	fsm_lowerup(&_this->fsm);
157	fsm_open(&_this->fsm);
158
159	if (_this->dialin_proxy != 0 &&
160	    _this->dialin_proxy_lcp_renegotiation == 0) {
161		_this->fsm.state = OPENED;
162		lcp_open(&_this->fsm);
163	}
164}
165
166/**
167 * sending Protocol-Reject.
168 */
169void
170lcp_send_protrej(lcp *_this, u_char *pktp, int lpktp)
171{
172	LCP_ASSERT(_this != NULL);
173	LCP_ASSERT(pktp != NULL);
174
175	fsm_sdata(&_this->fsm, PROTREJ, _this->fsm.id++, pktp, lpktp);
176}
177
178static const char *
179lcp_auth_string(int auth)
180{
181	switch (auth) {
182	case PPP_AUTH_PAP:		return "PAP";
183	case PPP_AUTH_CHAP_MD5:		return "MD5-CHAP";
184	case PPP_AUTH_CHAP_MS:		return "MS-CHAP";
185	case PPP_AUTH_CHAP_MS_V2:	return "MS-CHAP-V2";
186	case PPP_AUTH_EAP:		return "EAP";
187	case 0:				return "none";
188	default:			return "ERROR";
189	}
190}
191
192static void
193lcp_open(fsm *f)
194{
195	lcp *_this;
196	int peer_auth = 0;
197
198	LCP_ASSERT(f != NULL);
199	_this = &f->ppp->lcp;
200
201	if (psm_opt_is_accepted(_this, pap))
202		peer_auth = PPP_AUTH_PAP;
203	else if (psm_opt_is_accepted(_this, chap))
204		peer_auth = PPP_AUTH_CHAP_MD5;
205	else if (psm_opt_is_accepted(_this, chapms))
206		peer_auth = PPP_AUTH_CHAP_MS;
207	else if (psm_opt_is_accepted(_this, chapms_v2))
208		peer_auth = PPP_AUTH_CHAP_MS_V2;
209	else if (psm_opt_is_accepted(_this, eap))
210		peer_auth = PPP_AUTH_EAP;
211	else {
212		if (_this->auth_order[0] > 0) {
213			fsm_log(f, LOG_INFO,
214			    "failed to negotiate a auth protocol.");
215			fsm_close(f, "Authentication is required");
216			ppp_set_disconnect_cause(f->ppp,
217			    PPP_DISCON_AUTH_PROTOCOL_UNACCEPTABLE,
218			    _this->auth_order[0] /* first one */,
219			    1 /* peer refused */, NULL);
220			ppp_stop(f->ppp, "Authentication is required");
221			return;
222		}
223	}
224	f->ppp->peer_auth = peer_auth;
225
226	if (_this->xxxmru > 0 && f->ppp->peer_mru <= 0)
227		f->ppp->peer_mru = _this->xxxmru;
228	if (f->ppp->peer_mru <= 0)
229		f->ppp->peer_mru = f->ppp->mru;
230
231	/* checking the size of ppp->peer_mru. */
232	LCP_ASSERT(f->ppp->peer_mru > 500);
233
234	fsm_log(f, LOG_INFO, "logtype=Opened mru=%d/%d auth=%s magic=%08x/%08x"
235	    , f->ppp->mru, f->ppp->peer_mru
236	    , lcp_auth_string(peer_auth)
237	    , f->ppp->lcp.magic_number, f->ppp->lcp.peer_magic_number
238	);
239	lcp_reset_timeout(_this);
240
241	ppp_lcp_up(f->ppp);
242}
243
244static void
245lcp_down(fsm *f)
246{
247	lcp *_this;
248
249	if (f->ppp->disconnect_code == PPP_DISCON_NO_INFORMATION) {
250		/*
251		 * disconnect code is set when we are closing the lcp, so
252		 * 'no info' means the lcp is going down by peer's termreq.
253		 */
254		ppp_set_disconnect_cause(f->ppp, PPP_DISCON_NORMAL, 0,
255		    1 /* peer */, NULL);
256#ifdef USE_NPPPD_RADIUS
257		ppp_set_radius_terminate_cause(f->ppp,
258		    RADIUS_TERMNATE_CAUSE_USER_REQUEST);
259#endif
260	}
261
262	_this = &f->ppp->lcp;
263	UNTIMEOUT(lcp_timeout, _this);
264}
265
266static void
267lcp_finished(fsm *f)
268{
269	ppp_lcp_finished(f->ppp);
270}
271
272/**
273 * resetting ConfReq.
274 */
275static void
276lcp_resetci(fsm *f)
277{
278	LCP_ASSERT(f != NULL);
279
280	/* Unless doing dialin-proxy without re-negotiation */
281	if (!(f->ppp->lcp.dialin_proxy != 0 &&
282	    f->ppp->lcp.dialin_proxy_lcp_renegotiation == 0)) {
283
284		/* Reset the LCP options' state */
285		memset(&f->ppp->lcp.opt, 0, sizeof(f->ppp->lcp.opt));
286		f->ppp->lcp.auth_order[0] = -1;
287	}
288}
289
290/**
291 * The length of ConfReq.
292 */
293static int
294lcp_cilen(fsm *f)
295{
296	LCP_ASSERT(f != NULL);
297	return f->ppp->mru;
298}
299
300/**
301 * selecting authentication protocols which is not rejected yet in order
302 * of auth_order, and adding Authentication-Protocol options in ConfReq
303 * packet area.
304 */
305static int
306lcp_add_auth(fsm *f, u_char **ucpp)
307{
308	int i;
309	u_char *ucp;
310	lcp *_this;
311
312	ucp = *ucpp;
313	_this = &f->ppp->lcp;
314
315	for (i = 0; _this->auth_order[i] > 0 &&
316	    i < countof(_this->auth_order); i++) {
317		switch (_this->auth_order[i]) {
318		case PPP_AUTH_PAP:
319			if (psm_opt_is_rejected(_this, pap))
320				break;
321			PUTCHAR(PPP_LCP_AUTH_PROTOCOL, ucp);
322			PUTCHAR(4, ucp);
323			PUTSHORT(PPP_AUTH_PAP, ucp);
324			psm_opt_set_requested(_this, pap, 1);
325			_this->lastauth = PPP_AUTH_PAP;
326			goto end_loop;
327		case PPP_AUTH_CHAP_MD5:
328			if (psm_opt_is_rejected(_this, chap))
329				break;
330			PUTCHAR(PPP_LCP_AUTH_PROTOCOL, ucp);
331			PUTCHAR(5, ucp);
332			PUTSHORT(PPP_AUTH_CHAP, ucp);
333			PUTCHAR(PPP_AUTH_CHAP_MD5, ucp);
334			psm_opt_set_requested(_this, chap, 1);
335			_this->lastauth = PPP_AUTH_CHAP_MD5;
336			goto end_loop;
337		case PPP_AUTH_CHAP_MS:
338			if (psm_opt_is_rejected(_this, chapms))
339				break;
340			PUTCHAR(PPP_LCP_AUTH_PROTOCOL, ucp);
341			PUTCHAR(5, ucp);
342			PUTSHORT(PPP_AUTH_CHAP, ucp);
343			PUTCHAR(PPP_AUTH_CHAP_MS, ucp);
344			psm_opt_set_requested(_this, chapms, 1);
345			_this->lastauth = PPP_AUTH_CHAP_MS;
346			goto end_loop;
347		case PPP_AUTH_CHAP_MS_V2:
348			if (psm_opt_is_rejected(_this, chapms_v2))
349				break;
350			PUTCHAR(PPP_LCP_AUTH_PROTOCOL, ucp);
351			PUTCHAR(5, ucp);
352			PUTSHORT(PPP_AUTH_CHAP, ucp);
353			PUTCHAR(PPP_AUTH_CHAP_MS_V2, ucp);
354			psm_opt_set_requested(_this, chapms_v2,1);
355			_this->lastauth = PPP_AUTH_CHAP_MS_V2;
356			goto end_loop;
357                case PPP_AUTH_EAP:
358                        if (psm_opt_is_rejected(_this, eap))
359                                break;
360                        PUTCHAR(PPP_LCP_AUTH_PROTOCOL, ucp);
361                        PUTCHAR(4, ucp);
362                        PUTSHORT(PPP_AUTH_EAP, ucp);
363                        psm_opt_set_requested(_this, eap, 1);
364                        _this->lastauth = PPP_AUTH_EAP;
365                        goto end_loop;
366		}
367	}
368	_this->lastauth = -1;
369	return -1;
370end_loop:
371	*ucpp = ucp;
372
373	return 0;
374}
375
376/**
377 * making ConfReq.
378 */
379static void
380lcp_addci(fsm *f, u_char *ucp, int *lenp)
381{
382	lcp *_this;
383	u_char *start_ucp = ucp;
384
385	LCP_ASSERT(f != NULL);
386
387	_this = &f->ppp->lcp;
388	if (!psm_opt_is_rejected(_this, mru)) {
389		PUTCHAR(PPP_LCP_MRU, ucp);
390		PUTCHAR(4, ucp);
391
392		if (_this->xxxmru > 0) {	/* this value is got by Nak. */
393			PUTSHORT(_this->xxxmru, ucp);
394		} else {
395			PUTSHORT(f->ppp->mru, ucp);
396		}
397		psm_opt_set_requested(_this, mru, 1);
398	}
399	if (f->ppp->has_acf == 1) {
400		if (!psm_opt_is_rejected(_this, pfc)) {
401			PUTCHAR(PPP_LCP_PFC, ucp);
402			PUTCHAR(2, ucp);
403			psm_opt_set_requested(_this, pfc, 1);
404		}
405		if (!psm_opt_is_rejected(_this, acfc)) {
406			PUTCHAR(PPP_LCP_ACFC, ucp);
407			PUTCHAR(2, ucp);
408			psm_opt_set_requested(_this, acfc, 1);
409		}
410	}
411	PUTCHAR(PPP_LCP_MAGICNUMBER, ucp);
412	PUTCHAR(6, ucp);
413	PUTLONG(_this->magic_number, ucp);
414
415	if (f->ppp->peer_auth != 0) {
416		_this->auth_order[0] = f->ppp->peer_auth;
417		_this->auth_order[1] = -1;
418	} else if (_this->auth_order[0] < 0) {
419		lcp_load_authconfig(f);
420	}
421
422	lcp_add_auth(f, &ucp);
423	*lenp = ucp - start_ucp;
424}
425
426static int
427lcp_reqci(fsm *f, u_char *inp, int *lenp, int reject_if_disagree)
428{
429	uint32_t magic;
430	int type, len, rcode, mru, lrej;
431	u_char *inp0, *rejbuf, *nakbuf, *nakbuf0;
432	lcp *_this;
433
434	_this = &f->ppp->lcp;
435	rejbuf = NULL;
436	rcode = -1;
437	inp0 = inp;
438	lrej = 0;
439
440	if ((rejbuf = malloc(*lenp)) == NULL)
441		return -1;
442	if ((nakbuf0 = malloc(*lenp)) == NULL) {
443		free(rejbuf);
444		return -1;
445	}
446	nakbuf = nakbuf0;
447
448#define	remlen()	(*lenp - (inp - inp0))
449#define	LCP_OPT_PEER_ACCEPTED(opt)				\
450	psm_peer_opt_set_accepted(&f->ppp->lcp, opt, 1);
451
452	f->ppp->lcp.recv_reqs++;
453
454	while (remlen() >= 2) {
455		GETCHAR(type, inp);
456		GETCHAR(len, inp);
457		if (len <= 0 || remlen() + 2 < len)
458			goto fail;
459
460		switch (type) {
461		case PPP_LCP_MRU:
462			if (len != 4)
463				goto fail;
464			GETSHORT(mru, inp);
465			f->ppp->peer_mru = mru;
466			if (mru < NPPPD_MIN_MRU) {
467				if (reject_if_disagree) {
468					inp -= 2;
469					goto reject;
470				}
471				if (lrej > 0) {
472				/* if there is a reject, will send Rej, not send Nak. */
473				} else {
474					inp -= 2;
475					memcpy(nakbuf, inp, len);
476					nakbuf += len;
477					inp += 2;
478					PUTSHORT(f->ppp->mru, nakbuf);
479
480					rcode = CONFNAK;
481				}
482			} else
483				LCP_OPT_PEER_ACCEPTED(mru);
484			break;
485		case PPP_LCP_MAGICNUMBER:
486			if (len != 6)
487				goto fail;
488			GETLONG(magic, inp);
489			if (magic == _this->magic_number) {
490				inp -= 4;
491				goto reject;
492			}
493			_this->peer_magic_number = magic;
494			break;
495		case PPP_LCP_PFC:
496			if (len != 2)
497				goto fail;
498			LCP_OPT_PEER_ACCEPTED(pfc);
499			break;
500		case PPP_LCP_ACFC:
501			if (len != 2)
502				goto fail;
503			LCP_OPT_PEER_ACCEPTED(acfc);
504			break;
505		case PPP_LCP_AUTH_PROTOCOL:
506			/* currently never authenticate. */
507		case PPP_LCP_QUALITY_PROTOCOL:	/* not used */
508		default:
509reject:
510			inp -= 2;
511			memcpy(rejbuf + lrej, inp, len);
512			lrej += len;
513			inp += len;
514			rcode = CONFREJ;
515		}
516		continue;
517	}
518	if (rcode == -1)
519		rcode = CONFACK;
520fail:
521	switch (rcode) {
522	case CONFREJ:
523		memcpy(inp0, rejbuf, lrej);
524		*lenp = lrej;
525		break;
526	case CONFNAK:
527		memcpy(inp0, nakbuf0, nakbuf - nakbuf0);
528		*lenp = nakbuf - nakbuf0;
529		break;
530	}
531	if (rcode != CONFACK) {
532		psm_peer_opt_set_accepted(&f->ppp->lcp, mru, 0);
533		psm_peer_opt_set_accepted(&f->ppp->lcp, pfc, 0);
534		psm_peer_opt_set_accepted(&f->ppp->lcp, acfc, 0);
535	}
536	free(rejbuf);
537	free(nakbuf0);
538
539	return rcode;
540#undef	remlen
541#undef LCP_OPT_PEER_ACCEPTED
542}
543
544/** receiving ConfAck. */
545static int
546lcp_ackci(fsm *f, u_char *inp, int inlen)
547{
548	int chapalg, authproto, type, len, mru, magic;
549	u_char *inp0;
550
551#define	remlen()	(inlen - (inp - inp0))
552#define	LCP_OPT_ACCEPTED(opt)				\
553	if (!psm_opt_is_requested(&f->ppp->lcp, opt))	\
554		goto fail;				\
555	psm_opt_set_accepted(&f->ppp->lcp, opt, 1);
556
557	f->ppp->lcp.recv_ress++;
558	inp0 = inp;
559	while (remlen() >= 2) {
560		GETCHAR(type, inp);
561		GETCHAR(len, inp);
562
563		if (len <= 0 || remlen() + 2 < len)
564			goto fail;
565
566		switch (type) {
567		case PPP_LCP_MAGICNUMBER:
568			if (len != 6)
569				goto fail;
570			GETLONG(magic, inp);
571			if (f->ppp->lcp.magic_number != magic)
572				goto fail;
573			break;
574		case PPP_LCP_MRU:
575			if (len != 4)
576				goto fail;
577			LCP_OPT_ACCEPTED(mru);
578			GETSHORT(mru, inp);
579			break;
580		case PPP_LCP_AUTH_PROTOCOL:
581			if (len < 4)
582				goto fail;
583			GETSHORT(authproto, inp);
584			switch (authproto) {
585			case PPP_AUTH_PAP:
586				if (len != 4)
587					goto fail;
588				LCP_OPT_ACCEPTED(pap);
589				break;
590			case PPP_AUTH_CHAP:
591				if (len != 5)
592					goto fail;
593				GETCHAR(chapalg, inp);
594				switch (chapalg) {
595				case PPP_AUTH_CHAP_MD5:
596					LCP_OPT_ACCEPTED(chap);
597					break;
598				case PPP_AUTH_CHAP_MS:
599					LCP_OPT_ACCEPTED(chapms);
600					break;
601				case PPP_AUTH_CHAP_MS_V2:
602					LCP_OPT_ACCEPTED(chapms_v2);
603					break;
604				}
605				break;
606                        case PPP_AUTH_EAP:
607                                if (len != 4)
608                                     goto fail;
609                                LCP_OPT_ACCEPTED(eap);
610                                break;
611			}
612			break;
613
614		/*
615		 * As RFC1661, ConfRej must be used for boolean options, but
616		 * at least RouterTester uses ConfNak for them.
617		 */
618		case PPP_LCP_PFC:
619			if (len != 2)
620				goto fail;
621			LCP_OPT_ACCEPTED(pfc);
622			break;
623		case PPP_LCP_ACFC:
624			if (len != 2)
625				goto fail;
626			LCP_OPT_ACCEPTED(acfc);
627			break;
628
629		default:
630			goto fail;
631		}
632	}
633	return 1;
634fail:
635	fsm_log(f, LOG_ERR, "Received unexpected ConfAck.");
636	if (debug_get_debugfp() != NULL)
637		show_hd(debug_get_debugfp(), inp, remlen());
638	return 0;
639#undef	LCP_OPT_ACCEPTED
640}
641
642/** receiving ConfNak. */
643static int
644lcp_nakci(fsm *f, u_char *inp, int inlen)
645{
646	int chapalg, authproto, type, len, mru;
647	u_char *inp0;
648	lcp *_this;
649	const char *peer_auth = "unknown";
650
651#define	remlen()	(inlen - (inp - inp0))
652#define	LCP_OPT_REJECTED(opt)				\
653	if (!psm_opt_is_requested(&f->ppp->lcp, opt))	\
654		goto fail;				\
655	psm_opt_set_rejected(&f->ppp->lcp, opt, 1);
656
657	f->ppp->lcp.recv_ress++;
658	inp0 = inp;
659	_this = &f->ppp->lcp;
660	while (remlen() >= 2) {
661		GETCHAR(type, inp);
662		GETCHAR(len, inp);
663
664		if (len <= 0 || remlen() + 2 < len)
665			goto fail;
666
667		switch (type) {
668		case PPP_LCP_MRU:
669			if (len < 4)
670				goto fail;
671			GETSHORT(mru, inp);
672			fsm_log(f, LOG_NOTICE,
673			    "ignored ConfNak from the peer: mru=%d", mru);
674			_this->xxxmru = mru;
675			break;
676		case PPP_LCP_AUTH_PROTOCOL:
677			if (len < 4)
678				goto fail;
679			switch (_this->lastauth) {
680			case PPP_AUTH_PAP:
681				psm_opt_set_rejected(_this, pap, 1);
682				break;
683			case PPP_AUTH_CHAP_MD5:
684				psm_opt_set_rejected(_this, chap, 1);
685				break;
686			case PPP_AUTH_CHAP_MS:
687				psm_opt_set_rejected(_this, chapms, 1);
688				break;
689			case PPP_AUTH_CHAP_MS_V2:
690				psm_opt_set_rejected(_this, chapms_v2, 1);
691				break;
692                        case PPP_AUTH_EAP:
693                                psm_opt_set_rejected(_this, eap, 1);
694                                break;
695			}
696			GETSHORT(authproto, inp);
697			switch (authproto) {
698			case PPP_AUTH_PAP:
699				if (psm_opt_is_requested(_this, pap))
700					psm_opt_set_accepted(_this, pap, 1);
701				peer_auth = "pap";
702				break;
703			case PPP_AUTH_CHAP:
704				chapalg = 0;
705				if (len == 5)
706					GETCHAR(chapalg, inp);
707				switch (chapalg) {
708				case PPP_AUTH_CHAP_MD5:
709					if (psm_opt_is_requested(_this, chap))
710						psm_opt_set_accepted(_this,
711						    chap, 1);
712					peer_auth = "chap";
713					break;
714				case PPP_AUTH_CHAP_MS:
715					if (psm_opt_is_requested(_this, chapms))
716						psm_opt_set_accepted(_this,
717						    chapms, 1);
718					peer_auth = "mschap";
719					break;
720				case PPP_AUTH_CHAP_MS_V2:
721					if (psm_opt_is_requested(_this,
722					    chapms_v2))
723						psm_opt_set_accepted(_this,
724						    chapms_v2, 1);
725					peer_auth = "mschap_v2";
726					break;
727				default:
728					fsm_log(f, LOG_INFO,
729					    "Nacked chap algorithm is "
730					    "unknown(%d).", chapalg);
731					peer_auth = "unknown";
732					break;
733				}
734				break;
735                        case PPP_AUTH_EAP:
736                                if (len != 4)
737                                        goto fail;
738                                peer_auth = "eap";
739				if (psm_opt_is_requested(_this, eap))
740					psm_opt_set_accepted(_this, eap, 1);
741                                break;
742			}
743			if (NO_AUTH_AGREEABLE(_this)) {
744				fsm_log(f, LOG_INFO, "No authentication "
745				    "protocols are agreeable.  peer's "
746				    "auth proto=%s",
747				    peer_auth);
748				ppp_set_disconnect_cause(f->ppp,
749				    PPP_DISCON_AUTH_PROTOCOL_UNACCEPTABLE,
750				    authproto, 2 /* couldn't accept peer's */,
751				    NULL);
752				ppp_stop(f->ppp, "Authentication is required");
753				return 1;
754			}
755			break;
756		case PPP_LCP_PFC:
757			if (len != 2)
758				goto fail;
759			LCP_OPT_REJECTED(pfc);
760			break;
761		case PPP_LCP_ACFC:
762			if (len != 2)
763				goto fail;
764			LCP_OPT_REJECTED(acfc);
765			break;
766		default:
767			goto fail;
768		}
769	}
770	return 1;
771fail:
772	log_printf(LOG_ERR, "Received unexpected ConfNak.");
773	if (debug_get_debugfp() != NULL)
774		show_hd(debug_get_debugfp(), inp, inlen);
775	return 0;
776#undef remlen
777#undef LCP_OPT_REJECTED
778}
779
780/**
781 * receiving ConfRej.
782 */
783static int
784lcp_rejci(fsm *f, u_char *inp, int inlen)
785{
786	int chapalg, authproto, type, len, mru;
787	u_char *inp0;
788	lcp *_this;
789
790#define	remlen()	(inlen - (inp - inp0))
791#define	LCP_OPT_REJECTED(opt)				\
792	if (!psm_opt_is_requested(&f->ppp->lcp, opt))	\
793		goto fail;				\
794	psm_opt_set_rejected(&f->ppp->lcp, opt, 1);
795
796	f->ppp->lcp.recv_ress++;
797	inp0 = inp;
798	_this = &f->ppp->lcp;
799	while (remlen() >= 2) {
800		GETCHAR(type, inp);
801		GETCHAR(len, inp);
802
803		if (len <= 0 || remlen() + 2 < len)
804			goto fail;
805
806		switch (type) {
807		case PPP_LCP_MAGICNUMBER:
808			if (f->ppp->lcp.echo_interval > 0)
809				goto fail;
810			inp += 4;
811			break;
812		case PPP_LCP_MRU:
813			LCP_OPT_REJECTED(mru);
814			GETSHORT(mru, inp);
815			break;
816		case PPP_LCP_AUTH_PROTOCOL:
817			if (len < 4)
818				goto fail;
819			GETSHORT(authproto, inp);
820			switch (authproto) {
821			case PPP_AUTH_PAP:
822                                if (len != 4)
823                                        goto fail;
824				LCP_OPT_REJECTED(pap);
825				break;
826			case PPP_AUTH_CHAP:
827				chapalg = 0;
828				if (len == 5)
829					GETCHAR(chapalg, inp);
830				switch (chapalg) {
831				case PPP_AUTH_CHAP_MD5:
832					LCP_OPT_REJECTED(chap);
833					break;
834				case PPP_AUTH_CHAP_MS:
835					LCP_OPT_REJECTED(chapms);
836					break;
837				case PPP_AUTH_CHAP_MS_V2:
838					LCP_OPT_REJECTED(chapms_v2);
839					break;
840				default:
841					fsm_log(f, LOG_INFO,
842					    "Rejected chap algorithm is "
843					    "unknown(%d).", chapalg);
844					break;
845				}
846				break;
847                         case PPP_AUTH_EAP:
848                                if (len != 4)
849                                        goto fail;
850                                LCP_OPT_REJECTED(eap);
851                                break;
852			}
853			if (NO_AUTH_AGREEABLE(_this)) {
854				fsm_log(f, LOG_INFO, "No authentication "
855				    "protocols are agreeable.");
856				ppp_set_disconnect_cause(f->ppp,
857				    PPP_DISCON_AUTH_PROTOCOL_UNACCEPTABLE,
858				    authproto, 1 /* rejected by peer */, NULL);
859				ppp_stop(f->ppp, "Authentication is required");
860				return 1;
861			}
862			break;
863		case PPP_LCP_PFC:
864			if (len != 2)
865				goto fail;
866			LCP_OPT_REJECTED(pfc);
867			break;
868		case PPP_LCP_ACFC:
869			if (len != 2)
870				goto fail;
871			LCP_OPT_REJECTED(acfc);
872			break;
873		default:
874			goto fail;
875		}
876	}
877	return 1;
878fail:
879	log_printf(LOG_ERR, "Received unexpected ConfRej.");
880	if (debug_get_debugfp() != NULL)
881		show_hd(debug_get_debugfp(), inp, inlen);
882	return 0;
883#undef remlen
884}
885
886static void
887lcp_rcoderej(fsm *f, u_char *inp, int inlen)
888{
889	uint16_t proto;
890	fsm *rejfsm;
891
892	if (inlen < 2) {
893		fsm_log(f, LOG_WARNING, "Received short ProtRej packet.");
894		return;
895	}
896	GETSHORT(proto, inp);
897
898	rejfsm = NULL;
899
900	switch (proto) {
901	case PPP_PROTO_LCP:
902		rejfsm = &f->ppp->lcp.fsm;
903		break;
904	case PPP_PROTO_PAP:
905		fsm_log(f, LOG_WARNING, "our PAP packet is rejected");
906		return;
907	case PPP_PROTO_CHAP:
908		fsm_log(f, LOG_WARNING, "our CHAP packet is rejected");
909		return;
910        case PPP_PROTO_EAP:
911                fsm_log(f, LOG_ERR, "our EAP packet is rejected");
912                ppp_stop(f->ppp, "Authentication Required");
913                break;
914	case PPP_PROTO_NCP | NCP_IPCP:
915		rejfsm = &f->ppp->ipcp.fsm;
916		break;
917	case PPP_PROTO_NCP | NCP_CCP:
918		rejfsm = &f->ppp->ccp.fsm;
919		break;
920	}
921	if (rejfsm == NULL) {
922		fsm_log(f, LOG_WARNING,
923		    "Received ProtRej packet for unknown protocol=(%d/%04x)",
924		    proto, proto);
925		return;
926	}
927	fsm_protreject(rejfsm);
928
929	return;
930}
931
932static void
933lcp_reset_timeout(void *ctx)
934{
935	lcp *_this;
936
937	_this = ctx;
938
939	if (_this->echo_interval > 0) {
940		if (_this->echo_failures == 0) {
941			TIMEOUT(lcp_timeout, _this, _this->echo_interval);
942		} else {
943			TIMEOUT(lcp_timeout, _this, _this->echo_retry_interval);
944		}
945	} else {
946		UNTIMEOUT(lcp_timeout, _this);
947	}
948}
949
950static void
951lcp_timeout(void *ctx)
952{
953	lcp *_this;
954	u_char *cp, buf[32];
955
956	_this = ctx;
957	if (_this->echo_failures >= _this->echo_max_retries) {
958		fsm_log(&_this->fsm, LOG_NOTICE, "keepalive failure.");
959		if (_this->fsm.ppp != NULL) {
960#ifdef USE_NPPPD_RADIUS
961			ppp_set_radius_terminate_cause(_this->fsm.ppp,
962			    RADIUS_TERMNATE_CAUSE_IDLE_TIMEOUT);
963#endif
964			ppp_stop(_this->fsm.ppp, NULL);
965		}
966		return;
967	}
968	cp = buf;
969	PUTLONG(_this->magic_number, cp);
970	fsm_sdata(&_this->fsm, ECHOREQ, _this->fsm.id++, buf, 4);
971	_this->echo_failures++;
972
973	lcp_reset_timeout(_this);
974}
975
976static int
977lcp_rechoreq(fsm *f, int id, u_char *inp, int inlen)
978{
979	u_char *inp0;
980	lcp *_this;
981	int len;
982
983	if (inlen < 4)
984		return 0;
985
986	_this = &f->ppp->lcp;
987	inp0 = inp;
988	PUTLONG(_this->magic_number, inp)
989
990	len = MINIMUM(inlen, f->ppp->peer_mru - 8);
991	fsm_sdata(f, ECHOREP, id, inp0, len);
992
993	return 1;
994}
995
996static int
997lcp_ext(fsm *f, int code, int id, u_char *inp, int inlen)
998{
999	lcp *_this;
1000	uint32_t magic;
1001	char buf[256];
1002	int i, len;
1003
1004	_this = &f->ppp->lcp;
1005
1006	switch (code) {
1007	case IDENTIFICATION:
1008		/* RFC 1570 */
1009		if (inlen > 4) {
1010			GETLONG(magic, inp);
1011			inlen -= 4;
1012			memset(buf, 0, sizeof(buf));
1013			len = MINIMUM(inlen, sizeof(buf) - 1);
1014			memcpy(buf, inp, len);
1015			buf[len] = '\0';
1016			for (i = 0; i < len; i++) {
1017				if (!isprint((unsigned char)buf[i]))
1018					buf[i] = '.';
1019			}
1020			fsm_log(f, LOG_INFO,
1021			    "RecvId magic=%08x text=%s", magic, buf);
1022		}
1023		return 1;
1024	case PROTREJ:
1025		lcp_rcoderej(f, inp, inlen);
1026		return 1;
1027	case ECHOREP:
1028		if (f->state == OPENED) {
1029			if (inlen >= 4) {
1030				GETLONG(magic, inp);
1031				if (_this->peer_magic_number == magic) {
1032					_this->echo_failures = 0;
1033					lcp_reset_timeout(_this);
1034				}
1035			}
1036		}
1037		return 1;
1038	case ECHOREQ:
1039		if (f->state == OPENED)
1040			return lcp_rechoreq(f, id, inp, inlen);
1041		return 1;
1042	}
1043
1044	return 0;
1045}
1046
1047
1048/*
1049 * reading some authentication settings and storing ppp_order in
1050 * order of settings.
1051 */
1052static void
1053lcp_load_authconfig(fsm *f)
1054{
1055	int              i;
1056	lcp             *_this;
1057	struct tunnconf *conf;
1058
1059	i = 0;
1060	_this = &f->ppp->lcp;
1061	conf = ppp_get_tunnconf(f->ppp);
1062	if ((conf->auth_methods & NPPPD_AUTH_METHODS_MSCHAPV2) != 0) {
1063		_this->auth_order[i++] = PPP_AUTH_CHAP_MS_V2;
1064		psm_opt_set_enabled(_this,chapms_v2, 1);
1065	}
1066	if ((conf->auth_methods & NPPPD_AUTH_METHODS_CHAP) != 0) {
1067		_this->auth_order[i++] = PPP_AUTH_CHAP_MD5;
1068		psm_opt_set_enabled(_this, chap, 1);
1069	}
1070	if ((conf->auth_methods & NPPPD_AUTH_METHODS_PAP) != 0) {
1071		_this->auth_order[i++] = PPP_AUTH_PAP;
1072		psm_opt_set_enabled(_this, pap, 1);
1073	}
1074
1075	_this->auth_order[i] = -1;
1076}
1077
1078/***********************************************************************
1079 * related functions of Dialin Proxy
1080 **********************************************************************/
1081/**
1082 * This function set LCP status following dialin proxy information.
1083 * This returns non-zero value when LCP status is unacceptable.
1084 *
1085 */
1086int
1087lcp_dialin_proxy(lcp *_this, dialin_proxy_info *dpi, int renegotiation,
1088    int force_renegotiation)
1089{
1090	int i, authok;
1091
1092	_this->dialin_proxy = 1;
1093	lcp_load_authconfig(&_this->fsm);
1094
1095	/* whether authentication type is permitted by configuration or not. */
1096	authok = 0;
1097	if (dpi->auth_type != 0) {
1098		for (i = 0; _this->auth_order[i] > 0; i++) {
1099			if (_this->auth_order[i] != dpi->auth_type)
1100				continue;
1101			authok = 1;
1102			break;
1103		}
1104	}
1105	if (!authok) {
1106		if (!renegotiation) {
1107			fsm_log(&_this->fsm, LOG_NOTICE,
1108			    "dialin-proxy failed.  auth-method=%s is "
1109			    "not enabled.  Try 'l2tp.dialin.lcp_renegotion'",
1110			    lcp_auth_string(dpi->auth_type));
1111			return 1;
1112		}
1113		_this->dialin_proxy_lcp_renegotiation = 1;
1114	}
1115	if (force_renegotiation)
1116		_this->dialin_proxy_lcp_renegotiation = 1;
1117
1118	if (_this->dialin_proxy_lcp_renegotiation == 0) {
1119		_this->fsm.ppp->peer_auth = dpi->auth_type;
1120		/*
1121		 * Set the rejected flag to all options here for the moment,
1122		 * the agreeed options will be handled in lcp_proxy_sent_ci().
1123		 */
1124		psm_opt_set_rejected(_this, mru, 1);
1125		psm_opt_set_rejected(_this, pfc, 1);
1126		psm_opt_set_rejected(_this, acfc, 1);
1127		psm_opt_set_rejected(_this, pap, 1);
1128		psm_opt_set_rejected(_this, chap, 1);
1129		psm_opt_set_rejected(_this, chapms, 1);
1130		psm_opt_set_rejected(_this, chapms_v2, 1);
1131		psm_opt_set_rejected(_this, eap, 1);
1132
1133	}
1134	switch (dpi->auth_type) {
1135	case PPP_AUTH_PAP:
1136		pap_proxy_authen_prepare(&_this->fsm.ppp->pap, dpi);
1137		break;
1138	case PPP_AUTH_CHAP_MD5:
1139		chap_proxy_authen_prepare(&_this->fsm.ppp->chap, dpi);
1140		break;
1141	}
1142	if (lcp_proxy_sent_ci(&_this->fsm, dpi->last_sent_lcp.data,
1143	    dpi->last_sent_lcp.ldata) != 0) {
1144		fsm_log(&_this->fsm, LOG_NOTICE,
1145		    "dialin-proxy failed.  couldn't use proxied lcp.");
1146		return 1;
1147	}
1148	if (lcp_proxy_recv_ci(&_this->fsm, dpi->last_recv_lcp.data,
1149	    dpi->last_recv_lcp.ldata) != 0) {
1150		fsm_log(&_this->fsm, LOG_NOTICE,
1151		    "dialin-proxy failed.  couldn't use proxied lcp.");
1152		return 1;
1153	}
1154
1155	fsm_log(&_this->fsm, LOG_INFO,
1156	    "dialin-proxy user=%s auth-type=%s renegotiate=%s",
1157	    dpi->username,
1158	    (dpi->auth_type == 0)? "none" : lcp_auth_string(dpi->auth_type),
1159	    (_this->dialin_proxy_lcp_renegotiation != 0)? "yes" : "no");
1160
1161
1162	if (_this->dialin_proxy_lcp_renegotiation == 0)
1163		_this->fsm.flags |= OPT_SILENT;	/* It's ready to be "Opened" */
1164	else
1165		_this->fsm.flags &= ~OPT_SILENT;
1166
1167	return 0;
1168}
1169
1170/*
1171 * This function copies from lcp_reqci. It only differs as follows:
1172 *	- changes LCP_OPT_ACCEPTED.
1173 *	- Magic Number and MRU.
1174 */
1175static int
1176lcp_proxy_recv_ci(fsm *f, u_char *inp, int inlen)
1177{
1178	int type, mru, len;
1179	uint32_t magic;
1180	u_char *inp0;
1181	lcp *_this;
1182
1183#define	remlen()	(inlen - (inp - inp0))
1184#define	LCP_OPT_PEER_ACCEPTED(opt)				\
1185	psm_peer_opt_set_rejected(&f->ppp->lcp, opt, 0);	\
1186	psm_peer_opt_set_requested(&f->ppp->lcp, opt, 1);	\
1187	psm_peer_opt_set_accepted(&f->ppp->lcp, opt, 1);
1188
1189	_this = &f->ppp->lcp;
1190	inp0 = inp;
1191
1192	while (remlen() >= 2) {
1193		GETCHAR(type, inp);
1194		GETCHAR(len, inp);
1195		if (len <= 0 || remlen() + 2 < len)
1196			goto fail;
1197
1198		switch (type) {
1199		case PPP_LCP_MRU:
1200			if (len != 4)
1201				goto fail;
1202			GETSHORT(mru, inp);
1203			f->ppp->peer_mru = mru;
1204			if (mru < NPPPD_MIN_MRU)
1205				goto fail;
1206			else
1207				LCP_OPT_PEER_ACCEPTED(mru);
1208			break;
1209		case PPP_LCP_MAGICNUMBER:
1210			if (len != 6)
1211				goto fail;
1212			GETLONG(magic, inp);
1213			if (magic == _this->magic_number)
1214				goto fail;
1215			_this->peer_magic_number = magic;
1216			break;
1217		case PPP_LCP_PFC:
1218			if (len != 2)
1219				goto fail;
1220			LCP_OPT_PEER_ACCEPTED(pfc);
1221			break;
1222		case PPP_LCP_ACFC:
1223			if (len != 2)
1224				goto fail;
1225			LCP_OPT_PEER_ACCEPTED(acfc);
1226			break;
1227		case PPP_LCP_ACCM:
1228			if (len != 6)
1229				goto fail;
1230			/* we don't use async framing.  ignore this */
1231			inp += (len - 2);
1232			break;
1233		default:
1234			goto fail;
1235		}
1236	}
1237
1238#undef remlen
1239#undef LCP_OPT_PEER_ACCEPTED
1240	return 0;
1241fail:
1242	return 1;
1243}
1244
1245/*
1246 * This function copies from lcp_ackci. It only differs as follows:
1247 *	- Do not recv_reass++.
1248 *	- changes LCP_OPT_ACCEPTED.
1249 *	- Magic Number and MRU.
1250 */
1251static int
1252lcp_proxy_sent_ci(fsm *f, u_char *inp, int inlen)
1253{
1254	int chapalg, authproto, type, len, mru, magic;
1255	u_char *inp0;
1256
1257#define	remlen()	(inlen - (inp - inp0))
1258#define	LCP_OPT_ACCEPTED(opt)					\
1259	if (f->ppp->lcp.dialin_proxy_lcp_renegotiation == 0) {	\
1260		psm_opt_set_rejected(&f->ppp->lcp, opt, 0);	\
1261		psm_opt_set_requested(&f->ppp->lcp, opt, 1);	\
1262		psm_opt_set_accepted(&f->ppp->lcp, opt, 1);	\
1263	}
1264
1265	inp0 = inp;
1266	while (remlen() >= 2) {
1267		GETCHAR(type, inp);
1268		GETCHAR(len, inp);
1269
1270		if (len <= 0 || remlen() + 2 < len)
1271			goto fail;
1272
1273		switch (type) {
1274		case PPP_LCP_MAGICNUMBER:
1275			if (len != 6)
1276				goto fail;
1277			GETLONG(magic, inp);
1278			f->ppp->lcp.magic_number = magic;
1279			break;
1280		case PPP_LCP_MRU:
1281			if (len != 4)
1282				goto fail;
1283			LCP_OPT_ACCEPTED(mru);
1284			GETSHORT(mru, inp);
1285			f->ppp->lcp.xxxmru = mru;
1286			break;
1287		case PPP_LCP_AUTH_PROTOCOL:
1288			if (len < 4)
1289				goto fail;
1290			GETSHORT(authproto, inp);
1291			switch (authproto) {
1292			case PPP_AUTH_PAP:
1293				if (len != 4)
1294					goto fail;
1295				LCP_OPT_ACCEPTED(pap);
1296				break;
1297			case PPP_AUTH_CHAP:
1298				if (len != 5)
1299					goto fail;
1300				GETCHAR(chapalg, inp);
1301				switch (chapalg) {
1302				case PPP_AUTH_CHAP_MD5:
1303					LCP_OPT_ACCEPTED(chap);
1304					break;
1305				case PPP_AUTH_CHAP_MS:
1306					LCP_OPT_ACCEPTED(chapms);
1307					break;
1308				case PPP_AUTH_CHAP_MS_V2:
1309					LCP_OPT_ACCEPTED(chapms_v2);
1310					break;
1311				}
1312				break;
1313                        case PPP_AUTH_EAP:
1314                                if (len != 4)
1315                                     goto fail;
1316                                LCP_OPT_ACCEPTED(eap);
1317                                break;
1318			}
1319			break;
1320		case PPP_LCP_PFC:
1321			if (len != 2)
1322				goto fail;
1323			LCP_OPT_ACCEPTED(pfc);
1324			break;
1325		case PPP_LCP_ACFC:
1326			if (len != 2)
1327				goto fail;
1328			LCP_OPT_ACCEPTED(acfc);
1329			break;
1330		case PPP_LCP_ACCM:
1331			if (len != 6)
1332				goto fail;
1333			/* we don't use async framing.  ignore this */
1334			inp += (len - 2);
1335			break;
1336		default:
1337			goto fail;
1338		}
1339	}
1340	return 0;
1341fail:
1342	return 1;
1343#undef	LCP_OPT_ACCEPTED
1344}
1345