Пример #1
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
}
Пример #2
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
}
Пример #3
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
}
Пример #4
0
static int
lcp_reqci(fsm *f, u_char *inp, int *lenp, int reject_if_disagree)
{
	uint32_t magic;
	int type, len, rcode, mru, lrej;
	u_char *inp0, *rejbuf, *nakbuf, *nakbuf0;
	lcp *_this;

	_this = &f->ppp->lcp;
	rejbuf = NULL;
	rcode = -1;
	inp0 = inp;
	lrej = 0;

	if ((rejbuf = malloc(*lenp)) == NULL)
		return -1;
	if ((nakbuf0 = malloc(*lenp)) == NULL) {
		free(rejbuf);
		return -1;
	}
	nakbuf = nakbuf0;

#define	remlen()	(*lenp - (inp - inp0))
#define	LCP_OPT_PEER_ACCEPTED(opt)				\
	psm_peer_opt_set_accepted(&f->ppp->lcp, opt, 1);

	f->ppp->lcp.recv_reqs++;

	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);
			f->ppp->peer_mru = mru;
			if (mru < NPPPD_MIN_MRU) {
				if (reject_if_disagree) {
					inp -= 2;
					goto reject;
				}
				if (lrej > 0) {
				/* if there is a reject, will send Rej, not send Nak. */
				} else {
					inp -= 2;
					memcpy(nakbuf, inp, len);
					nakbuf += len;
					inp += 2;
					PUTSHORT(f->ppp->mru, nakbuf);

					rcode = CONFNAK;
				}
			} else
				LCP_OPT_PEER_ACCEPTED(mru);
			break;
		case PPP_LCP_MAGICNUMBER:
			if (len != 6)
				goto fail;
			GETLONG(magic, inp);
			if (magic == _this->magic_number) {
				inp -= 4;
				goto reject;
			}
			_this->peer_magic_number = magic;
			break;
		case PPP_LCP_PFC:
			if (len != 2)
				goto fail;
			LCP_OPT_PEER_ACCEPTED(pfc);
			break;
		case PPP_LCP_ACFC:
			if (len != 2)
				goto fail;
			LCP_OPT_PEER_ACCEPTED(acfc);
			break;
		case PPP_LCP_AUTH_PROTOCOL:
			/* currently never authenticate. */
		case PPP_LCP_QUALITY_PROTOCOL:	/* not used */
		default:
reject:
			inp -= 2;
			memcpy(rejbuf + lrej, inp, len);
			lrej += len;
			inp += len;
			rcode = CONFREJ;
		}
		continue;
	}
	if (rcode == -1)
		rcode = CONFACK;
fail:
	switch (rcode) {
	case CONFREJ:
		memcpy(inp0, rejbuf, lrej);
		*lenp = lrej;
		break;
	case CONFNAK:
		memcpy(inp0, nakbuf0, nakbuf - nakbuf0);
		*lenp = nakbuf - nakbuf0;
		break;
	}
	if (rcode != CONFACK) {
		psm_peer_opt_set_accepted(&f->ppp->lcp, mru, 0);
		psm_peer_opt_set_accepted(&f->ppp->lcp, pfc, 0);
		psm_peer_opt_set_accepted(&f->ppp->lcp, acfc, 0);
	}
	if (rejbuf != NULL)
		free(rejbuf);
	if (nakbuf0 != NULL)
		free(nakbuf0);

	return rcode;
#undef	remlen
#undef LCP_OPT_PEER_ACCEPTED
}
Пример #5
0
/*
 * This function copies from lcp_ackci. It only differs as follows:
 *	- Do not recv_reass++.
 *	- changes LCP_OPT_ACCEPTED.
 *	- Magic Number and MRU.
 */
static int
lcp_proxy_sent_ci(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 (f->ppp->lcp.dialin_proxy_lcp_renegotiation == 0) {	\
		psm_opt_set_rejected(&f->ppp->lcp, opt, 0);	\
		psm_opt_set_requested(&f->ppp->lcp, opt, 1);	\
		psm_opt_set_accepted(&f->ppp->lcp, opt, 1);	\
	}

	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);
			f->ppp->lcp.magic_number = magic;
			break;
		case PPP_LCP_MRU:
			if (len != 4)
				goto fail;
			LCP_OPT_ACCEPTED(mru);
			GETSHORT(mru, inp);
			f->ppp->lcp.xxxmru = mru;
			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;
		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;
		case PPP_LCP_ACCM:
			if (len != 6)
				goto fail;
			/* we don't use async framing.  ignore this */
			inp += (len - 2);
			break;
		default:
			goto fail;
		}
	}
	return 0;
fail:
	return 1;
#undef	LCP_OPT_ACCEPTED
}
Пример #6
0
/*
 * This function copies from lcp_reqci. It only differs as follows:
 *	- changes LCP_OPT_ACCEPTED.
 *	- Magic Number and MRU.
 */
static int
lcp_proxy_recv_ci(fsm *f, u_char *inp, int inlen)
{
	int type, mru, len;
	uint32_t magic;
	u_char *inp0;
	lcp *_this;

#define	remlen()	(inlen - (inp - inp0))
#define	LCP_OPT_PEER_ACCEPTED(opt)				\
	psm_peer_opt_set_rejected(&f->ppp->lcp, opt, 0);	\
	psm_peer_opt_set_requested(&f->ppp->lcp, opt, 1);	\
	psm_peer_opt_set_accepted(&f->ppp->lcp, opt, 1);

	_this = &f->ppp->lcp;
	inp0 = inp;

	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);
			f->ppp->peer_mru = mru;
			if (mru < NPPPD_MIN_MRU)
				goto fail;
			else
				LCP_OPT_PEER_ACCEPTED(mru);
			break;
		case PPP_LCP_MAGICNUMBER:
			if (len != 6)
				goto fail;
			GETLONG(magic, inp);
			if (magic == _this->magic_number)
				goto fail;
			_this->peer_magic_number = magic;
			break;
		case PPP_LCP_PFC:
			if (len != 2)
				goto fail;
			LCP_OPT_PEER_ACCEPTED(pfc);
			break;
		case PPP_LCP_ACFC:
			if (len != 2)
				goto fail;
			LCP_OPT_PEER_ACCEPTED(acfc);
			break;
		case PPP_LCP_ACCM:
			if (len != 6)
				goto fail;
			/* we don't use async framing.  ignore this */
			inp += (len - 2);
			break;
		default:
			goto fail;
		}
	}

#undef remlen
#undef LCP_OPT_PEER_ACCEPTED
	return 0;
fail:
	return 1;
}
Пример #7
0
static int
ccp_nackackci(fsm *f, u_char *pktp, int lpkt, int is_nak, int is_rej)
{
	int type, len;
	u_char *pktp0;
#ifdef	USE_NPPPD_MPPE
	uint32_t peer_bits, our_bits;
#endif
	npppd_ppp *ppp;

	ppp = f->ppp;

	pktp0 = pktp;

#define	remlen()	(lpkt - (pktp - pktp0))
	while (remlen() >= 2) {
		GETCHAR(type, pktp);
		GETCHAR(len, pktp);
		if (len <= 0 || remlen() + 2 < len)
			goto fail;

		switch (type) {
#ifdef USE_NPPPD_MPPE
		case CCP_MPPE:
			if (len < 6)
				goto fail;
			if (is_rej) {
				f->ppp->ccp.mppe_rej = 1;
				return 1;
			}
			if (ppp->mppe_started != 0) {
				/* resend silently */
				return 1;
			}
			GETLONG(peer_bits, pktp);
			/*
			 * With Yamaha RTX-1000 that is configured as
			 * "ppp ccp mppe-any",
			 *
			 *	npppd ConfReq (40,56,128) => RTX 1000
			 *	npppd <= (40,128) ConfNAK    RTX 1000
			 *	npppd ConfReq (40,56,128) => RTX 1000
			 *	npppd <= (40,128) ConfNAK    RTX 1000
			 *
			 * both peers never decide the final bits.  We insist
			 * the longest bit if our request is nacked.
			 */
			our_bits = mppe_create_our_bits(&ppp->mppe, peer_bits);
			if (peer_bits == our_bits || is_nak)
				ppp->ccp.mppe_o_bits = our_bits;

			break;
#endif
		default:
			goto fail;
		}
	}
	return 1;
fail:
	return 0;
}
Пример #8
0
/** Request Command Interpreter */
static int
ccp_reqci(fsm *f, u_char *pktp, int *lpktp, int reject_if_disagree)
{
	int type, len, rcode, lrej, lnak;
	u_char *rejbuf, *nakbuf, *nakbuf0, *pktp0;
#ifdef USE_NPPPD_MPPE
	uint32_t peer_bits, our_bits;
#endif
	npppd_ppp *ppp;

	ppp = f->ppp;

	rejbuf = NULL;
	rcode = CONFACK;
	pktp0 = pktp;
	lrej = 0;
	lnak = 0;

	if ((rejbuf = malloc(*lpktp)) == NULL) {
		return rcode;
	}
	if ((nakbuf0 = malloc(*lpktp)) == NULL) {
		free(rejbuf);
		return rcode;
	}
	nakbuf = nakbuf0;
#define	remlen()	(*lpktp - (pktp - pktp0))

	while (remlen() >= 2) {
		GETCHAR(type, pktp);
		GETCHAR(len, pktp);
		if (len <= 0 || remlen() + 2 < len)
			goto fail;

		switch (type) {
#ifdef USE_NPPPD_MPPE
		case CCP_MPPE:
			if (len < 6)
				goto fail;

			if (ppp->mppe.enabled == 0)
				goto reject;
			GETLONG(peer_bits, pktp);
			our_bits = mppe_create_our_bits(&ppp->mppe, peer_bits);
			if (our_bits != peer_bits) {
				if (reject_if_disagree) {
					pktp -= 4;
					goto reject;
				}
				if (lrej > 0) {
				/* don't nak because we are doing rej */
				} else {
					PUTCHAR(type, nakbuf);
					PUTCHAR(6, nakbuf);
					PUTLONG(our_bits, nakbuf);
					rcode = CONFNAK;
				}
			} else
				ppp->ccp.mppe_p_bits = our_bits;
			break;
reject:
#endif
		default:
			pktp -= 2;
			memcpy(rejbuf + lrej, pktp, len);
			lrej += len;
			pktp += len;
			rcode = CONFREJ;
		}
		continue;
	}
fail:
	switch (rcode) {
	case CONFREJ:
		memcpy(pktp0, rejbuf, lrej);
		*lpktp = lrej;
		break;
	case CONFNAK:
		len = nakbuf - nakbuf0;
		memcpy(pktp0, nakbuf0, len);
		*lpktp = len;
		break;
	}
	free(rejbuf);
	free(nakbuf0);

	return rcode;
#undef	remlen
}