Example #1
0
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);
	}
}
Example #2
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 #3
0
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;
	}
}
Example #4
0
/**
 * Stop the PPP and destroy the npppd_ppp instance
 * @param reason	Reason of stopping the PPP.  Specify NULL if there is
 *			no special reason.  This reason will be used as a
 *			reason field of LCP Terminate-Request message and
 *			notified to the peer.
 */
void
ppp_stop(npppd_ppp *_this, const char *reason)
{

	PPP_ASSERT(_this != NULL);

#ifdef USE_NPPPD_RADIUS
	ppp_set_radius_terminate_cause(_this,
	    RADIUS_TERMNATE_CAUSE_ADMIN_RESET);
#endif
	ppp_set_disconnect_cause(_this, PPP_DISCON_NORMAL, 0, 2 /* by local */,
	    NULL);

	ppp_down_others(_this);
	fsm_close(&_this->lcp.fsm, reason);
}
Example #5
0
static void
lcp_down(fsm *f)
{
	lcp *_this;

	if (f->ppp->disconnect_code == PPP_DISCON_NO_INFORMATION) {
		/*
		 * disconnect code is set when we are closing the lcp, so
		 * 'no info' means the lcp is going down by peer's termreq.
		 */
		ppp_set_disconnect_cause(f->ppp, PPP_DISCON_NORMAL, 0,
		    1 /* peer */, NULL);
#ifdef USE_NPPPD_RADIUS
		ppp_set_radius_terminate_cause(f->ppp,
		    RADIUS_TERMNATE_CAUSE_USER_REQUEST);
#endif
	}

	_this = &f->ppp->lcp;
	UNTIMEOUT(lcp_timeout, _this);
}
Example #6
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 #7
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 #8
0
/** 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");
		}
	}
}
Example #9
0
static void
ppp_stop0(npppd_ppp *_this)
{
	char mppe_str[BUFSIZ];
	char label[512];

#ifdef USE_NPPPD_RADIUS
	ppp_set_radius_terminate_cause(_this, RADIUS_TERMNATE_CAUSE_NAS_ERROR);
#endif
	ppp_set_disconnect_cause(_this, PPP_DISCON_NORMAL, 0, 1 /* by local */,
	    NULL);

	_this->end_monotime = get_monosec();

	if (_this->phy_close != NULL)
		_this->phy_close(_this);
	_this->phy_close = NULL;

	/*
	 * NAT/Blackhole detection for PPTP(GRE)
	 */
	if (_this->lcp.dialin_proxy != 0 &&
	    _this->lcp.dialin_proxy_lcp_renegotiation == 0) {
		/* No LCP packets on dialin proxy without LCP renegotiation */
	} else if (_this->lcp.recv_ress == 0) {	/* No responses */
		if (_this->lcp.recv_reqs == 0)	/* No requests */
			ppp_log(_this, LOG_WARNING, "no PPP frames from the "
			    "peer.  router/NAT issue? (may have filtered out)");
		else
			ppp_log(_this, LOG_WARNING, "my PPP frames may not "
			    "have arrived at the peer.  router/NAT issue? (may "
			    "be the only-first-person problem)");
	}
#ifdef USE_NPPPD_PIPEX
	if (npppd_ppp_pipex_disable(_this->pppd, _this) != 0)
		ppp_log(_this, LOG_ERR,
		    "npppd_ppp_pipex_disable() failed: %m");
#endif

	ppp_set_tunnel_label(_this, label, sizeof(label));
#ifdef	USE_NPPPD_MPPE
	if (_this->mppe_started) {
		snprintf(mppe_str, sizeof(mppe_str),
		    "mppe=yes mppe_in=%dbits,%s mppe_out=%dbits,%s",
		    _this->mppe.recv.keybits,
		    (_this->mppe.recv.stateless)? "stateless" : "stateful",
		    _this->mppe.send.keybits,
		    (_this->mppe.send.stateless)? "stateless" : "stateful");
	} else
#endif
		snprintf(mppe_str, sizeof(mppe_str), "mppe=no");
	ppp_log(_this, LOG_NOTICE,
		"logtype=TUNNELUSAGE user=\"%s\" duration=%ldsec layer2=%s "
		"layer2from=%s auth=%s data_in=%llubytes,%upackets "
		"data_out=%llubytes,%upackets error_in=%u error_out=%u %s "
		"iface=%s",
		_this->username[0]? _this->username : "******",
		(long)(_this->end_monotime - _this->start_monotime),
		_this->phy_label,  label,
		_this->username[0]? ppp_peer_auth_string(_this) : "none",
		(unsigned long long)_this->ibytes, _this->ipackets,
		(unsigned long long)_this->obytes, _this->opackets,
		_this->ierrors, _this->oerrors, mppe_str,
		npppd_ppp_get_iface_name(_this->pppd, _this));

#ifdef USE_NPPPD_RADIUS
	npppd_ppp_radius_acct_stop(_this->pppd, _this);
#endif
	npppd_ppp_unbind_iface(_this->pppd, _this);
#ifdef	USE_NPPPD_MPPE
	mppe_fini(&_this->mppe);
#endif
	evtimer_del(&_this->idle_event);

	npppd_release_ip(_this->pppd, _this);
	ppp_destroy(_this);
}