コード例 #1
0
ファイル: pap.c プロジェクト: darksoul42/bitrig
static void
pap_response(pap *_this, int authok, const char *mes)
{
	int lpktp, lmes;
	u_char *pktp, *pktp1;
	const char *realm;

	pktp = ppp_packetbuf(_this->ppp, PPP_PROTO_PAP) + HEADERLEN;
	lpktp = _this->ppp->mru - HEADERLEN;
	realm = npppd_ppp_get_realm_name(_this->ppp->pppd, _this->ppp);

	pktp1 = pktp;
	if (mes == NULL)
		lmes = 0;
	else
		lmes = strlen(mes);
	lmes = MINIMUM(lmes, lpktp - 1);

	PUTCHAR(lmes, pktp1);
	if (lmes > 0)
		memcpy(pktp1, mes, lmes);
	lpktp = lmes + 1;

	if (authok)
		ppp_output(_this->ppp, PPP_PROTO_PAP, AUTHACK, _this->auth_id,
		    pktp, lpktp);
	else
		ppp_output(_this->ppp, PPP_PROTO_PAP, AUTHNAK, _this->auth_id,
		    pktp, lpktp);

	if (!authok) {
		pap_log(_this, LOG_ALERT,
		    "logtype=Failure username=\"%s\" realm=%s", _this->name,
		    realm);
		pap_stop(_this);
		ppp_set_disconnect_cause(_this->ppp, 
		    PPP_DISCON_AUTH_FAILED, PPP_PROTO_PAP, 1 /* peer */, NULL);
		ppp_stop(_this->ppp, "Authentication Required");
	} else {
		strlcpy(_this->ppp->username, _this->name,
		    sizeof(_this->ppp->username));
		pap_log(_this, LOG_INFO,
		    "logtype=Success username=\"%s\" realm=%s", _this->name,
		    realm);
		pap_stop(_this);
		ppp_auth_ok(_this->ppp);
		/* reset the state to response request of retransmision. */
		_this->state = PAP_STATE_SENT_RESPONSE;
	}
}
コード例 #2
0
ファイル: npppd_iface.c プロジェクト: SylvestreG/bitrig
/** callback function which works for each PPP session */
static int
npppd_iface_network_input_delegate(struct radish *radish, void *args0)
{
	npppd_ppp *ppp;
	struct sockaddr_npppd *snp;
	struct npppd_iface_network_input_arg *args;

	snp = radish->rd_rtent;

	if (snp->snp_type == SNP_PPP) {
		args = args0;
		ppp = snp->snp_data_ptr;
		if (ppp_iface(ppp) != args->_this)
			return 0;
#ifdef	USE_NPPPD_MPPE
		if (MPPE_SEND_READY(ppp)) {
			/* output via MPPE if MPPE started */
			mppe_pkt_output(&ppp->mppe, PPP_PROTO_IP, args->pktp,
			    args->lpktp);
		} else if (MPPE_IS_REQUIRED(ppp)) {
			/* in case MPPE not started but MPPE is mandatory, */
			/* it is not necessary to log because of multicast. */
			return 0;
		}
#endif
		ppp_output(ppp, PPP_PROTO_IP, 0, 0, args->pktp, args->lpktp);
	}

	return 0;
}
コード例 #3
0
ファイル: chap.c プロジェクト: darksoul42/bitrig
static void
chap_response(chap *_this, int authok, u_char *pktp, int lpktp)
{
	const char *realm_name;

	CHAP_ASSERT(_this != NULL);
	CHAP_ASSERT(pktp != NULL);
	CHAP_ASSERT(_this->type == PPP_AUTH_CHAP_MD5 ||
	    _this->type == PPP_AUTH_CHAP_MS_V2);

	ppp_output(_this->ppp, PPP_PROTO_CHAP, (authok)? 3 : 4, _this->challid,
	    pktp, lpktp);

	realm_name = npppd_ppp_get_realm_name(_this->ppp->pppd, _this->ppp);
	if (!authok) {
		chap_log(_this, LOG_ALERT,
		    "logtype=Failure username=\"%s\" realm=%s", _this->name,
		    realm_name);
		chap_stop(_this);
		/* Stop the PPP if the authentication is failed. */
		ppp_set_disconnect_cause(_this->ppp,
		    PPP_DISCON_AUTH_FAILED, PPP_PROTO_CHAP, 1 /* peer */, NULL);
		ppp_stop(_this->ppp, "Authentication Required");
	} else {
		strlcpy(_this->ppp->username, _this->name,
		    sizeof(_this->ppp->username));
		chap_log(_this, LOG_INFO,
		    "logtype=Success username=\"%s\" "
		    "realm=%s", _this->name, realm_name);
		chap_stop(_this);
		/* We change our state to prepare to resend requests. */
		_this->state = CHAP_STATE_SENT_RESPONSE;
		ppp_auth_ok(_this->ppp);
	}
}
コード例 #4
0
ファイル: npppd_iface.c プロジェクト: SylvestreG/bitrig
static void
npppd_iface_network_input_ipv4(npppd_iface *_this, u_char *pktp, int lpktp)
{
	struct ip *iphdr;
	npppd *_npppd;
	npppd_ppp *ppp;
	struct npppd_iface_network_input_arg input_arg;

	NPPPD_IFACE_ASSERT(_this != NULL);
	NPPPD_IFACE_ASSERT(pktp != NULL);

	iphdr = (struct ip *)pktp;
	_npppd = _this->npppd;

	if (lpktp < sizeof(iphdr)) {
		npppd_iface_log(_this, LOG_ERR, "Received short packet.");
		return;
	}
	if (IN_MULTICAST(ntohl(iphdr->ip_dst.s_addr))) {
		NPPPD_IFACE_ASSERT(((npppd *)(_this->npppd))->rd != NULL);
		input_arg._this = _this;
		input_arg.pktp = pktp;
		input_arg.lpktp = lpktp;
		/* delegate */
		rd_walktree(((npppd *)(_this->npppd))->rd,
		    npppd_iface_network_input_delegate, &input_arg);
		return;
	}
	ppp = npppd_get_ppp_by_ip(_npppd, iphdr->ip_dst);
	if (ppp == NULL) {
#ifdef NPPPD_DEBUG
		log_printf(LOG_INFO, "%s received a packet to unknown "
		    "%s.", _this->ifname, inet_ntoa(iphdr->ip_dst));
#endif
		return;
	}
#ifndef NO_ADJUST_MSS
	if (ppp->adjust_mss) {
		adjust_tcp_mss(pktp, lpktp, MRU_IPMTU(ppp->peer_mru));
	}
#endif
	if (ppp->timeout_sec > 0 && !ip_is_idle_packet(iphdr, lpktp))
		ppp_reset_idle_timeout(ppp);

#ifdef	USE_NPPPD_MPPE
	if (MPPE_SEND_READY(ppp)) {
		/* output via MPPE if MPPE started */
		mppe_pkt_output(&ppp->mppe, PPP_PROTO_IP, pktp, lpktp);
		return;
	} else if (MPPE_IS_REQUIRED(ppp)) {
		/* in case MPPE not started but MPPE is mandatory */
		ppp_log(ppp, LOG_WARNING, "A packet received from network, "
		    "but MPPE is not started.");
		return;
	}
#endif
	ppp_output(ppp, PPP_PROTO_IP, 0, 0, pktp, lpktp);
}
コード例 #5
0
ファイル: mppe.c プロジェクト: SylvestreG/bitrig
/**
 * sending packet via MPPE.
 */
void
mppe_pkt_output(mppe *_this, uint16_t proto, u_char *pktp, int len)
{
	int encrypt, flushed;
	uint16_t coher_cnt;
	u_char *outp, *outp0;

	MPPE_ASSERT(proto == PPP_PROTO_IP);

	flushed = 0;
	encrypt = 1;

	outp = ppp_packetbuf(_this->ppp, PPP_PROTO_MPPE);
	outp0 = outp;

	if (_this->send.stateless != 0) {
		flushed = 1;
		mppe_key_change(_this, &_this->send);
	} else {
		if ((_this->send.coher_cnt % 0x100) == 0xff) {
			flushed = 1;
			mppe_key_change(_this, &_this->send);
		} else if (_this->send.resetreq != 0) {
			flushed = 1;
			_this->send.resetreq = 0;
		}
	}

	if (flushed) {
		mppe_rc4_setkey(_this, &_this->send);
	}

	MPPE_DBG((_this, DEBUG_LEVEL_2, "out coher_cnt=%03x %s%s",
	    _this->send.coher_cnt, (flushed)? "[flushed]" : "",
	    (encrypt)? "[encrypt]" : ""));

	coher_cnt = _this->send.coher_cnt & COHERENCY_CNT_MASK;
	if (flushed)
		coher_cnt |= 0x8000;
	if (encrypt)
		coher_cnt |= 0x1000;

	PUTSHORT(coher_cnt, outp);
	proto = htons(proto);
	mppe_rc4_encrypt(_this, &_this->send, 2, (u_char *)&proto, outp);
	mppe_rc4_encrypt(_this, &_this->send, len, pktp, outp + 2);

	ppp_output(_this->ppp, PPP_PROTO_MPPE, 0, 0, outp0, len + 4);
	_this->send.coher_cnt++;
	_this->send.coher_cnt &= COHERENCY_CNT_MASK;
}
コード例 #6
0
ファイル: mppe.c プロジェクト: SylvestreG/bitrig
/**
 * receiving packets via MPPE.
 * len must be 4 at least.
 */
void
mppe_input(mppe *_this, u_char *pktp, int len)
{
	int pktloss, encrypt, flushed, m, n;
	uint16_t coher_cnt;
	u_char *pktp0, *opktp, *opktp0;
	uint16_t proto;
	int delayed = 0;

	encrypt = 0;
	flushed = 0;

	MPPE_ASSERT(len >= 4);

	pktp0 = pktp;
	GETSHORT(coher_cnt, pktp);

	flushed = (coher_cnt & 0x8000)? 1 : 0;
	encrypt = (coher_cnt & 0x1000)? 1 : 0;
	coher_cnt &= COHERENCY_CNT_MASK;
	pktloss = 0;

	MPPE_DBG((_this, DEBUG_LEVEL_2, "in coher_cnt=%03x/%03x %s%s",
	    _this->recv.coher_cnt, coher_cnt, (flushed)? "[flushed]" : "",
	    (encrypt)? "[encrypt]" : ""));

	if (encrypt == 0) {
		mppe_log(_this, LOG_WARNING,
		    "Received unexpected MPPE packet.  (no encrypt)");
		return;
	}

	/*
	 * In L2TP/IPsec implementation, in case that the ppp frame sequence
	 * is not able to reconstruct and the ppp frame is out of sequence, it
	 * is unable to identify with many packets losing. If it does so, MPPE
	 * key is out of place.
	 * To avoid this problem, when it seems that more than 4096-256 packets
	 * drops, it assumes that the packet doesn't lose but the packet is out
	 * of sequence.
	 */
    {
	int coher_cnt0;

	coher_cnt0 = coher_cnt;
	if (coher_cnt < _this->recv.coher_cnt)
		coher_cnt0 += 0x1000;
	if (coher_cnt0 - _this->recv.coher_cnt > 0x0f00) {
		if (!_this->recv.stateless ||
		    coher_cnt0 - _this->recv.coher_cnt
		    <= 0x1000 - MPPE_NOLDKEY) {
			mppe_log(_this, LOG_INFO,
			    "Workaround the out-of-sequence PPP framing problem: "
			    "%d => %d", _this->recv.coher_cnt, coher_cnt);
			return;
		}
		delayed = 1;
	}
    }

	if (_this->recv.stateless != 0) {
		if (!delayed) {
			mppe_key_change(_this, &_this->recv);
			while (_this->recv.coher_cnt != coher_cnt) {
				_this->recv.coher_cnt++;
				_this->recv.coher_cnt &= COHERENCY_CNT_MASK;
				mppe_key_change(_this, &_this->recv);
				pktloss++;
			}
		}
		mppe_rc4_setoldkey(_this, &_this->recv, coher_cnt);
		flushed = 1;
	} else {
		if (flushed) {
			if (coher_cnt < _this->recv.coher_cnt) {
				/* in case of carrying up. */
				coher_cnt += 0x1000;
			}
			pktloss += coher_cnt - _this->recv.coher_cnt;
			m = _this->recv.coher_cnt / 256;
			n = coher_cnt / 256;
			while (m++ < n)
				mppe_key_change(_this, &_this->recv);

			coher_cnt &= COHERENCY_CNT_MASK;
			_this->recv.coher_cnt = coher_cnt;
		} else if (_this->recv.coher_cnt != coher_cnt) {
			_this->recv.resetreq = 1;

			opktp0 = ppp_packetbuf(_this->ppp,
			    PPP_PROTO_NCP | NCP_CCP);
			opktp = opktp0;

			PUTLONG(_this->ppp->ccp.mppe_p_bits, opktp);

			ppp_output(_this->ppp, PPP_PROTO_NCP | NCP_CCP,
			    RESETREQ, _this->recv.resetreq, opktp0,
				opktp - opktp0);
			return;
		}
		if ((coher_cnt & 0xff) == 0xff) {
			mppe_key_change(_this, &_this->recv);
			flushed = 1;
		}
		if (flushed) {
			mppe_rc4_setkey(_this, &_this->recv);
		}
	}

	if (pktloss > 1000) {
		/*
		 * In case of many packets losing or out of sequence.
		 * The latter is not able to communicate because the key is
		 * out of place soon.
		 *
		 */
		mppe_log(_this, LOG_WARNING, "%d packets loss", pktloss);
	}

	mppe_rc4_encrypt(_this, &_this->recv, len - 2, pktp, pktp);

	if (!delayed) {
		_this->recv.coher_cnt++;
		_this->recv.coher_cnt &= COHERENCY_CNT_MASK;
	}

	if (pktp[0] & 1)
		proto = pktp[0];
	else
		proto = pktp[0] << 8 | pktp[1];
	/*
	 * According to RFC3078 section 3,
	 * MPPE only accept protocol number 0021-00FA.
	 * If decrypted protocol number is out of range,
	 * it indicates loss of coherency.
	 */
	if (!(proto & 1) || proto < 0x21 || proto > 0xfa) {
		mppe_log(_this, LOG_INFO, "MPPE coherency is lost");
		return; /* drop frame */
	}

	_this->ppp->recv_packet(_this->ppp, pktp, len - 2,
	    PPP_IO_FLAGS_MPPE_ENCRYPTED);
}
コード例 #7
0
ファイル: chap.c プロジェクト: darksoul42/bitrig
/** Start CHAP as a authenticator.  Send a challenge */
void
chap_start(chap *_this)
{
	u_char *challp, *challp0;
	int lmyname;

	CHAP_ASSERT(_this != NULL);
	CHAP_ASSERT(_this->ppp != NULL);

	if (_this->state == CHAP_STATE_PROXY_AUTHENTICATION) {
		_this->type = PPP_AUTH_CHAP_MD5;
		_this->state = CHAP_STATE_AUTHENTICATING;
		chap_authenticate(_this, _this->ppp->proxy_authen_resp,
		    _this->ppp->lproxy_authen_resp);
		return;
	}

	if (_this->state == CHAP_STATE_INITIAL ||
	    _this->state == CHAP_STATE_SENT_CHALLENGE) {
		if (_this->ntry > 0) {
			_this->ntry--;
			_this->type = _this->ppp->peer_auth;

			/* The type is supported? */
			if (_this->type != PPP_AUTH_CHAP_MS_V2 &&
			    _this->type != PPP_AUTH_CHAP_MD5) {
				chap_log(_this, LOG_ALERT,
				    "Requested authentication type(0x%x) "
				    "is not supported.", _this->type);
				ppp_set_disconnect_cause(_this->ppp, 
				    PPP_DISCON_AUTH_PROTOCOL_UNACCEPTABLE,
				    PPP_PROTO_CHAP, 2 /* local */, NULL);
				ppp_stop(_this->ppp, "Authentication Required");
				return;
			}


#ifdef USE_NPPPD_MPPE
			/* The peer must use MS-CHAP-V2 as the type */
			if (MPPE_IS_REQUIRED(_this->ppp) &&
			    _this->type != PPP_AUTH_CHAP_MS_V2) {
				chap_log(_this, LOG_ALERT,
				    "mppe is required but try to start chap "
				    "type=0x%02x", _this->type);
				ppp_set_disconnect_cause(_this->ppp,
				    PPP_DISCON_AUTH_PROTOCOL_UNACCEPTABLE,
				    PPP_PROTO_CHAP, 2 /* local */, NULL);
				ppp_stop(_this->ppp, "Authentication Required");
				return;
			}
#endif
			/* Generate a challenge packet and send it */
			challp = ppp_packetbuf(_this->ppp, PPP_AUTH_CHAP);
			challp += HEADERLEN;
			challp0 = challp;

			chap_create_challenge(_this);

			PUTCHAR(_this->lchall, challp);
			memcpy(challp, &_this->chall, _this->lchall);
			challp += _this->lchall;

			lmyname = strlen(_this->myname);

			memcpy(challp, _this->myname, lmyname);
			challp += lmyname;

			_this->challid = ++_this->pktid;

			ppp_output(_this->ppp, PPP_PROTO_CHAP, CHAP_CHALLENGE,
			    _this->challid, challp0, challp - challp0);

			_this->state = CHAP_STATE_SENT_CHALLENGE;

			TIMEOUT((void (*)(void *))chap_start, _this,
			    CHAP_TIMEOUT);
		} else {
			chap_log(_this, LOG_INFO,
			    "Client did't respond our challenage.");
			ppp_set_disconnect_cause(_this->ppp, 
			    PPP_DISCON_AUTH_FSM_TIMEOUT,
			    PPP_PROTO_CHAP, 0, NULL);
			ppp_stop(_this->ppp, "Authentication Required");
		}
	}
}