Example #1
0
static void
lcp_open(fsm *f)
{
	lcp *_this;
	int peer_auth = 0;

	LCP_ASSERT(f != NULL);
	_this = &f->ppp->lcp;

	if (psm_opt_is_accepted(_this, pap))
		peer_auth = PPP_AUTH_PAP;
	else if (psm_opt_is_accepted(_this, chap))
		peer_auth = PPP_AUTH_CHAP_MD5;
	else if (psm_opt_is_accepted(_this, chapms))
		peer_auth = PPP_AUTH_CHAP_MS;
	else if (psm_opt_is_accepted(_this, chapms_v2))
		peer_auth = PPP_AUTH_CHAP_MS_V2;
	else if (psm_opt_is_accepted(_this, eap))
		peer_auth = PPP_AUTH_EAP;
	else {
		if (_this->auth_order[0] > 0) {
			fsm_log(f, LOG_INFO,
			    "failed to negotiate a auth protocol.");
			fsm_close(f, "Authentication is required");
			ppp_set_disconnect_cause(f->ppp,
			    PPP_DISCON_AUTH_PROTOCOL_UNACCEPTABLE, 
			    _this->auth_order[0] /* first one */,
			    1 /* peer refused */, NULL);
			ppp_stop(f->ppp, "Authentication is required");
			return;
		}
	}
	f->ppp->peer_auth = peer_auth;

	if (_this->xxxmru > 0 && f->ppp->peer_mru <= 0)
		f->ppp->peer_mru = _this->xxxmru;
	if (f->ppp->peer_mru <= 0)
		f->ppp->peer_mru = f->ppp->mru;

	/* checking the size of ppp->peer_mru. */
	LCP_ASSERT(f->ppp->peer_mru > 500);

	fsm_log(f, LOG_INFO, "logtype=Opened mru=%d/%d auth=%s magic=%08x/%08x"
	    , f->ppp->mru, f->ppp->peer_mru
	    , lcp_auth_string(peer_auth)
	    , f->ppp->lcp.magic_number, f->ppp->lcp.peer_magic_number
	);
	lcp_reset_timeout(_this);

	ppp_lcp_up(f->ppp);
}
Example #2
0
static void
lcp_timeout(void *ctx)
{
	lcp *_this;
	u_char *cp, buf[32];

	_this = ctx;
	if (_this->echo_failures >= _this->echo_max_retries) {
		fsm_log(&_this->fsm, LOG_NOTICE, "keepalive failure.");
		if (_this->fsm.ppp != NULL) {
#ifdef USE_NPPPD_RADIUS
			ppp_set_radius_terminate_cause(_this->fsm.ppp,
			    RADIUS_TERMNATE_CAUSE_IDLE_TIMEOUT);
#endif
			ppp_stop(_this->fsm.ppp, NULL);
		}
		return;
	}
	cp = buf;
	PUTLONG(_this->magic_number, cp);
	fsm_sdata(&_this->fsm, ECHOREQ, _this->fsm.id++, buf, 4);
	_this->echo_failures++;

	lcp_reset_timeout(_this);
}
Example #3
0
static void
ccp_stop(fsm *f)
{
#ifdef USE_NPPPD_MPPE
	fsm_log(f, LOG_INFO, "CCP is stopped");
	ppp_ccp_stopped(f->ppp);
#endif
}
Example #4
0
static void
lcp_rcoderej(fsm *f, u_char *inp, int inlen)
{
	uint16_t proto;
	fsm *rejfsm;

	if (inlen < 2) {
		fsm_log(f, LOG_WARNING, "Received short ProtRej packet.");
		return;
	}
	GETSHORT(proto, inp);

	rejfsm = NULL;

	switch (proto) {
	case PPP_PROTO_LCP:
		rejfsm = &f->ppp->lcp.fsm;
		break;
	case PPP_PROTO_PAP:
		fsm_log(f, LOG_WARNING, "our PAP packet is rejected");
		return;
	case PPP_PROTO_CHAP:
		fsm_log(f, LOG_WARNING, "our CHAP packet is rejected");
		return;
        case PPP_PROTO_EAP:
                fsm_log(f, LOG_ERR, "our EAP packet is rejected");
                ppp_stop(f->ppp, "Authentication Required");
                break;
	case PPP_PROTO_NCP | NCP_IPCP:
		rejfsm = &f->ppp->ipcp.fsm;
		break;
	case PPP_PROTO_NCP | NCP_CCP:
		rejfsm = &f->ppp->ccp.fsm;
		break;
	}
	if (rejfsm == NULL) {
		fsm_log(f, LOG_WARNING,
		    "Received ProtRej packet for unknown protocol=(%d/%04x)",
		    proto, proto);
		return;
	}
	fsm_protreject(rejfsm);

	return;
}
Example #5
0
static int
ccp_ext(fsm *f, int code, int id, u_char *pktp, int lpktp)
{
	switch (code) {
	case RESET_REQ:
		fsm_log(f, LOG_DEBUG, "Received ResetReq %d", id);
#ifdef USE_NPPPD_MPPE
		mppe_recv_ccp_reset(&f->ppp->mppe);
#endif
		/*
		 * RFC 3078 says MPPE can be synchronized without Reset-Ack,
		 * but it doesn't tell about necessity of Reset-Ack.  But
		 * in fact, windows peer will complain Reset-Ack with
		 * Code-Reject.  So we don't send Reset-Ack.
		 */
		return 1;
	case RESET_ACK:
		fsm_log(f, LOG_DEBUG, "Received ResetAck %d", id);
		return 1;
	}
	return 0;
}
Example #6
0
static int
lcp_ext(fsm *f, int code, int id, u_char *inp, int inlen)
{
	lcp *_this;
	uint32_t magic;
	char buf[256];
	int i, len;

	_this = &f->ppp->lcp;

	switch (code) {
	case IDENTIFICATION:
		/* RFC 1570 */
		if (inlen > 4) {
			GETLONG(magic, inp);
			inlen -= 4;
			memset(buf, 0, sizeof(buf));
			len = MIN(inlen, sizeof(buf) - 1);
			memcpy(buf, inp, len);
			buf[len] = '\0';
			for (i = 0; i < len; i++) {
				if (!isprint((unsigned char)buf[i]))
					buf[i] = '.';
			}
			fsm_log(f, LOG_INFO,
			    "RecvId magic=%08x text=%s", magic, buf);
		}
		return 1;
	case PROTREJ:
		lcp_rcoderej(f, inp, inlen);
		return 1;
	case ECHOREP:
		if (f->state == OPENED) {
			if (inlen >= 4) {
				GETLONG(magic, inp);
				if (_this->peer_magic_number == magic) {
					_this->echo_failures = 0;
					lcp_reset_timeout(_this);
				}
			}
		}
		return 1;
	case ECHOREQ:
		if (f->state == OPENED)
			return lcp_rechoreq(f, id, inp, inlen);
		return 1;
	}

	return 0;
}
Example #7
0
void test_fsm_log_err(struct test *test)
{
	int res;
	test->name = "fsm_log error";
	test->result = 0;
	
	if (0 == (res = fsm_log(222, 80, 65, 89))) {
		test->result = 1;
	}
	else {
		test->result = 0;
		test->error_message = "fsm_log failed to return success";
	}
	if (OK != fsm_logger_flush_logs()) {
		test->result = 0;
		test->error_message = "fsm_log failed to flush results";
	}
	
	tests_print_res(*test);
}
Example #8
0
void test_fsm_log(struct test *test)
{
	int res;
	test->name = "fsm_log";
	test->result = 0;
	
	if (0 == (res = fsm_log(1000, 'S', 'U', ' '))) {
		test->result = 1;
	}
	else {
		test->result = 0;
		test->error_message = "fsm_log failed to return success";
	}
	if (OK != fsm_logger_flush_logs()) {
		test->result = 0;
		test->error_message = "fsm_log failed to flush results";
	}
	
	tests_print_res(*test);
}
Example #9
0
/**
 * receiving ConfRej.
 */
static int
lcp_rejci(fsm *f, u_char *inp, int inlen)
{
	int chapalg, authproto, type, len, mru;
	u_char *inp0;
	lcp *_this;

#define	remlen()	(inlen - (inp - inp0))
#define	LCP_OPT_REJECTED(opt)				\
	if (!psm_opt_is_requested(&f->ppp->lcp, opt))	\
		goto fail;				\
	psm_opt_set_rejected(&f->ppp->lcp, opt, 1);

	f->ppp->lcp.recv_ress++;
	inp0 = inp;
	_this = &f->ppp->lcp;
	while (remlen() >= 2) {
		GETCHAR(type, inp);
		GETCHAR(len, inp);

		if (len <= 0 || remlen() + 2 < len)
			goto fail;

		switch (type) {
		case PPP_LCP_MAGICNUMBER:
			if (f->ppp->lcp.echo_interval > 0)
				goto fail;
			inp += 4;
			break;
		case PPP_LCP_MRU:
			LCP_OPT_REJECTED(mru);
			GETSHORT(mru, inp);
			break;
		case PPP_LCP_AUTH_PROTOCOL:
			if (len < 4)
				goto fail;
			GETSHORT(authproto, inp);
			switch (authproto) {
			case PPP_AUTH_PAP:
                                if (len != 4)
                                        goto fail;
				LCP_OPT_REJECTED(pap);
				break;
			case PPP_AUTH_CHAP:
				chapalg = 0;
				if (len == 5)
					GETCHAR(chapalg, inp);
				switch (chapalg) {
				case PPP_AUTH_CHAP_MD5:
					LCP_OPT_REJECTED(chap);
					break;
				case PPP_AUTH_CHAP_MS:
					LCP_OPT_REJECTED(chapms);
					break;
				case PPP_AUTH_CHAP_MS_V2:
					LCP_OPT_REJECTED(chapms_v2);
					break;
				default:
					fsm_log(f, LOG_INFO,
					    "Rejected chap algorithm is "
					    "unknown(%d).", chapalg);
					break;
				}
				break;
                         case PPP_AUTH_EAP:
                                if (len != 4)
                                        goto fail;
                                LCP_OPT_REJECTED(eap);
                                break;
			}
			if (NO_AUTH_AGREEABLE(_this)) {
				fsm_log(f, LOG_INFO, "No authentication "
				    "protocols are agreeable.");
				ppp_set_disconnect_cause(f->ppp,
				    PPP_DISCON_AUTH_PROTOCOL_UNACCEPTABLE,
				    authproto, 1 /* rejected by peer */, NULL);
				ppp_stop(f->ppp, "Authentication is required");
				return 1;
			}
			break;
		case PPP_LCP_PFC:
			if (len != 2)
				goto fail;
			LCP_OPT_REJECTED(pfc);
			break;
		case PPP_LCP_ACFC:
			if (len != 2)
				goto fail;
			LCP_OPT_REJECTED(acfc);
			break;
		default:
			goto fail;
		}
	}
	return 1;
fail:
	log_printf(LOG_ERR, "Received unexpected ConfRej.");
	if (debug_get_debugfp() != NULL)
		show_hd(debug_get_debugfp(), inp, inlen);
	return 0;
#undef remlen
}
Example #10
0
/** receiving ConfNak. */
static int
lcp_nakci(fsm *f, u_char *inp, int inlen)
{
	int chapalg, authproto, type, len, mru;
	u_char *inp0;
	lcp *_this;
	const char *peer_auth = "unknown";

#define	remlen()	(inlen - (inp - inp0))
#define	LCP_OPT_REJECTED(opt)				\
	if (!psm_opt_is_requested(&f->ppp->lcp, opt))	\
		goto fail;				\
	psm_opt_set_rejected(&f->ppp->lcp, opt, 1);

	f->ppp->lcp.recv_ress++;
	inp0 = inp;
	_this = &f->ppp->lcp;
	while (remlen() >= 2) {
		GETCHAR(type, inp);
		GETCHAR(len, inp);

		if (len <= 0 || remlen() + 2 < len)
			goto fail;

		switch (type) {
		case PPP_LCP_MRU:
			if (len < 4)
				goto fail;
			GETSHORT(mru, inp);
			fsm_log(f, LOG_NOTICE,
			    "ignored ConfNak from the peer: mru=%d", mru);
			_this->xxxmru = mru;
			break;
		case PPP_LCP_AUTH_PROTOCOL:
			if (len < 4)
				goto fail;
			switch (_this->lastauth) {
			case PPP_AUTH_PAP:
				psm_opt_set_rejected(_this, pap, 1);
				break;
			case PPP_AUTH_CHAP_MD5:
				psm_opt_set_rejected(_this, chap, 1);
				break;
			case PPP_AUTH_CHAP_MS:
				psm_opt_set_rejected(_this, chapms, 1);
				break;
			case PPP_AUTH_CHAP_MS_V2:
				psm_opt_set_rejected(_this, chapms_v2, 1);
				break;
                        case PPP_AUTH_EAP:
                                psm_opt_set_rejected(_this, eap, 1);
                                break;
			}
			GETSHORT(authproto, inp);
			switch (authproto) {
			case PPP_AUTH_PAP:
				if (psm_opt_is_requested(_this, pap))
					psm_opt_set_accepted(_this, pap, 1);
				peer_auth = "pap";
				break;
			case PPP_AUTH_CHAP:
				chapalg = 0;
				if (len == 5)
					GETCHAR(chapalg, inp);
				switch (chapalg) {
				case PPP_AUTH_CHAP_MD5:
					if (psm_opt_is_requested(_this, chap))
						psm_opt_set_accepted(_this,
						    chap, 1);
					peer_auth = "chap";
					break;
				case PPP_AUTH_CHAP_MS:
					if (psm_opt_is_requested(_this, chapms))
						psm_opt_set_accepted(_this,
						    chapms, 1);
					peer_auth = "mschap";
					break;
				case PPP_AUTH_CHAP_MS_V2:
					if (psm_opt_is_requested(_this,
					    chapms_v2))
						psm_opt_set_accepted(_this,
						    chapms_v2, 1);
					peer_auth = "mschap_v2";
					break;
				default:
					fsm_log(f, LOG_INFO,
					    "Nacked chap algorithm is "
					    "unknown(%d).", chapalg);
					peer_auth = "unknown";
					break;
				}
				break;
                        case PPP_AUTH_EAP:
                                if (len != 4)
                                        goto fail;
                                peer_auth = "eap";
				if (psm_opt_is_requested(_this, eap))
					psm_opt_set_accepted(_this, eap, 1);
                                break;
			}
			if (NO_AUTH_AGREEABLE(_this)) {
				fsm_log(f, LOG_INFO, "No authentication "
				    "protocols are agreeable.  peer's "
				    "auth proto=%s",
				    peer_auth);
				ppp_set_disconnect_cause(f->ppp,
				    PPP_DISCON_AUTH_PROTOCOL_UNACCEPTABLE, 
				    authproto, 2 /* couldn't accept peer's */,
				    NULL);
				ppp_stop(f->ppp, "Authentication is required");
				return 1;
			}
			break;
		case PPP_LCP_PFC:
			if (len != 2)
				goto fail;
			LCP_OPT_REJECTED(pfc);
			break;
		case PPP_LCP_ACFC:
			if (len != 2)
				goto fail;
			LCP_OPT_REJECTED(acfc);
			break;
		default:
			goto fail;
		}
	}
	return 1;
fail:
	log_printf(LOG_ERR, "Received unexpected ConfNak.");
	if (debug_get_debugfp() != NULL)
		show_hd(debug_get_debugfp(), inp, inlen);
	return 0;
#undef remlen
#undef LCP_OPT_REJECTED
}
Example #11
0
/** receiving ConfAck. */
static int
lcp_ackci(fsm *f, u_char *inp, int inlen)
{
	int chapalg, authproto, type, len, mru, magic;
	u_char *inp0;

#define	remlen()	(inlen - (inp - inp0))
#define	LCP_OPT_ACCEPTED(opt)				\
	if (!psm_opt_is_requested(&f->ppp->lcp, opt))	\
		goto fail;				\
	psm_opt_set_accepted(&f->ppp->lcp, opt, 1);

	f->ppp->lcp.recv_ress++;
	inp0 = inp;
	while (remlen() >= 2) {
		GETCHAR(type, inp);
		GETCHAR(len, inp);

		if (len <= 0 || remlen() + 2 < len)
			goto fail;

		switch (type) {
		case PPP_LCP_MAGICNUMBER:
			if (len != 6)
				goto fail;
			GETLONG(magic, inp);
			if (f->ppp->lcp.magic_number != magic)
				goto fail;
			break;
		case PPP_LCP_MRU:
			if (len != 4)
				goto fail;
			LCP_OPT_ACCEPTED(mru);
			GETSHORT(mru, inp);
			break;
		case PPP_LCP_AUTH_PROTOCOL:
			if (len < 4)
				goto fail;
			GETSHORT(authproto, inp);
			switch (authproto) {
			case PPP_AUTH_PAP:
				if (len != 4)
					goto fail;
				LCP_OPT_ACCEPTED(pap);
				break;
			case PPP_AUTH_CHAP:
				if (len != 5)
					goto fail;
				GETCHAR(chapalg, inp);
				switch (chapalg) {
				case PPP_AUTH_CHAP_MD5:
					LCP_OPT_ACCEPTED(chap);
					break;
				case PPP_AUTH_CHAP_MS:
					LCP_OPT_ACCEPTED(chapms);
					break;
				case PPP_AUTH_CHAP_MS_V2:
					LCP_OPT_ACCEPTED(chapms_v2);
					break;
				}
				break;
                        case PPP_AUTH_EAP:
                                if (len != 4)
                                     goto fail;
                                LCP_OPT_ACCEPTED(eap);
                                break;
			}
			break;

		/*
		 * As RFC1661, ConfRej must be used for boolean options, but
		 * at least RouterTester uses ConfNak for them.
		 */
		case PPP_LCP_PFC:
			if (len != 2)
				goto fail;
			LCP_OPT_ACCEPTED(pfc);
			break;
		case PPP_LCP_ACFC:
			if (len != 2)
				goto fail;
			LCP_OPT_ACCEPTED(acfc);
			break;

		default:
			goto fail;
		}
	}
	return 1;
fail:
	fsm_log(f, LOG_ERR, "Received unexpected ConfAck.");
	if (debug_get_debugfp() != NULL)
		show_hd(debug_get_debugfp(), inp, remlen());
	return 0;
#undef	LCP_OPT_ACCEPTED
}
Example #12
0
/**
 * This function set LCP status following dialin proxy information.
 * This returns non-zero value when LCP status is unacceptable.
 *
 */
int
lcp_dialin_proxy(lcp *_this, dialin_proxy_info *dpi, int renegotiation,
    int force_renegotiation)
{
	int i, authok;

	_this->dialin_proxy = 1;
	lcp_load_authconfig(&_this->fsm);

	/* whether authentication type is permitted by configuration or not. */
	authok = 0;
	if (dpi->auth_type != 0) {
		for (i = 0; _this->auth_order[i] > 0; i++) {
			if (_this->auth_order[i] != dpi->auth_type)
				continue;
			authok = 1;
			break;
		}
	}
	if (!authok) {
		if (!renegotiation) {
			fsm_log(&_this->fsm, LOG_NOTICE,
			    "dialin-proxy failed.  auth-method=%s is "
			    "not enabled.  Try 'l2tp.dialin.lcp_renegotion'",
			    lcp_auth_string(dpi->auth_type));
			return 1;
		}
		_this->dialin_proxy_lcp_renegotiation = 1;
	}
	if (force_renegotiation)
		_this->dialin_proxy_lcp_renegotiation = 1;

	if (_this->dialin_proxy_lcp_renegotiation == 0) {
		_this->fsm.ppp->peer_auth = dpi->auth_type;
		/*
		 * It changes status which all options are rejected, and
		 * accepts agreed options in lcp_proxy_send_ci.
		 */
		psm_opt_set_rejected(_this, mru, 1);
		psm_opt_set_rejected(_this, pfc, 1);
		psm_opt_set_rejected(_this, acfc, 1);
		psm_opt_set_rejected(_this, pap, 1);
		psm_opt_set_rejected(_this, chap, 1);
		psm_opt_set_rejected(_this, chapms, 1);
		psm_opt_set_rejected(_this, chapms_v2, 1);
		psm_opt_set_rejected(_this, eap, 1);

	}
	switch (dpi->auth_type) {
	case PPP_AUTH_PAP:
		pap_proxy_authen_prepare(&_this->fsm.ppp->pap, dpi);
		break;
	case PPP_AUTH_CHAP_MD5:
		chap_proxy_authen_prepare(&_this->fsm.ppp->chap, dpi);
		break;
	}
	if (lcp_proxy_sent_ci(&_this->fsm, dpi->last_sent_lcp.data,
	    dpi->last_sent_lcp.ldata) != 0) {
		fsm_log(&_this->fsm, LOG_NOTICE,
		    "dialin-proxy failed.  couldn't use proxied lcp.");
		return 1;
	}
	if (lcp_proxy_recv_ci(&_this->fsm, dpi->last_recv_lcp.data,
	    dpi->last_recv_lcp.ldata) != 0) {
		fsm_log(&_this->fsm, LOG_NOTICE,
		    "dialin-proxy failed.  couldn't use proxied lcp.");
		return 1;
	}

	fsm_log(&_this->fsm, LOG_INFO,
	    "dialin-proxy user=%s auth-type=%s renegotiate=%s",
	    dpi->username,
	    (dpi->auth_type == 0)? "none" : lcp_auth_string(dpi->auth_type),
	    (_this->dialin_proxy_lcp_renegotiation != 0)? "yes" : "no");


	if (_this->dialin_proxy_lcp_renegotiation == 0) {
		/* call lcp_open by another event handler */
		TIMEOUT(lcp_dialin_proxy_open, _this, 0);
	} else
		_this->fsm.flags &= ~OPT_SILENT;

	return 0;
}