Example #1
0
static void
chap_radius_response(void *context, RADIUS_PACKET *pkt, int flags,
    RADIUS_REQUEST_CTX reqctx)
{
	int code, lrespkt;
	const char *secret, *reason = "";
	chap *_this;
	u_char *respkt, *respkt0;
	int errorCode;
	RADIUS_REQUEST_CTX radctx;

	CHAP_ASSERT(context != NULL);

	reason = "";
	errorCode = ERROR_AUTH_SERVER_TIMEOUT;
	_this = context;
	secret = radius_get_server_secret(_this->radctx);
	radctx = _this->radctx;
	_this->radctx = NULL;	/* IMPORTANT */

	respkt = respkt0 = ppp_packetbuf(_this->ppp, PPP_PROTO_CHAP)
	    + HEADERLEN;
	lrespkt = _this->ppp->mru - HEADERLEN;
	if (pkt == NULL) {
		if (flags & RADIUS_REQUEST_TIMEOUT)
			reason = "timeout";
		else if (flags & RADIUS_REQUEST_ERROR)
			reason = strerror(errno);
		else
			reason = "error";
		goto auth_failed;
	}

	code = radius_get_code(pkt);
	if (code == RADIUS_CODE_ACCESS_REJECT) {
		reason="reject";
		errorCode = ERROR_AUTHENTICATION_FAILURE;
		/* Windows peer will reset the password by this error code */
		goto auth_failed;
	} else if (code != RADIUS_CODE_ACCESS_ACCEPT) {
		reason="error";
		goto auth_failed;
	}
	if ((flags & RADIUS_REQUEST_CHECK_AUTHENTICATOR_OK) == 0 &&
	    (flags & RADIUS_REQUEST_CHECK_AUTHENTICATOR_NO_CHECK) == 0) {
		reason="bad_authenticator";
		goto auth_failed;
	}
	/*
	 * Authetication OK
	 */
	switch (_this->type) {
	case PPP_AUTH_CHAP_MD5:
	    chap_response(_this, 1, "OK", 2);
	    break;
	case PPP_AUTH_CHAP_MS_V2:
	    {
		struct RADIUS_MS_CHAP2_SUCCESS success;
#ifdef USE_NPPPD_MPPE
		struct RADIUS_MPPE_KEY sendkey, recvkey;
#endif
		size_t len;

		len = sizeof(success);
		if (radius_get_vs_raw_attr(pkt, RADIUS_VENDOR_MICROSOFT,
		    RADIUS_VTYPE_MS_CHAP2_SUCCESS, &success, &len) != 0) {
			chap_log(_this, LOG_ERR, "no ms_chap2_success");
			goto auth_failed;
		}
#ifdef	USE_NPPPD_MPPE
		if (_this->ppp->mppe.enabled != 0) {
			len = sizeof(sendkey);
			if (radius_get_vs_raw_attr(pkt, RADIUS_VENDOR_MICROSOFT,
			    RADIUS_VTYPE_MPPE_SEND_KEY, &sendkey, &len) != 0) {
				chap_log(_this, LOG_ERR, "no mppe_send_key");
				goto auth_failed;
			}
			len = sizeof(recvkey);
			if (radius_get_vs_raw_attr(pkt, RADIUS_VENDOR_MICROSOFT,
			    RADIUS_VTYPE_MPPE_RECV_KEY, &recvkey, &len) != 0) {
				chap_log(_this, LOG_ERR, "no mppe_recv_key");
				goto auth_failed;
			}

			mschap_radiuskey(_this->ppp->mppe.send.master_key,
			    sendkey.salt, _this->authenticator, secret);

			mschap_radiuskey(_this->ppp->mppe.recv.master_key,
			    recvkey.salt, _this->authenticator, secret);
		}
#endif
		chap_response(_this, 1, success.str, sizeof(success.str));
		break;
	    }
	}
	ppp_process_radius_framed_ip(_this->ppp, pkt);

	return;
auth_failed:
	chap_log(_this, LOG_WARNING, "Radius authentication request failed: %s",
	    reason);
	/* No extra information */
	chap_failure(_this, "FAILED", errorCode);
}
Example #2
0
static int
radius_acct_request(npppd *pppd, npppd_ppp *ppp, int stop)
{
	RADIUS_PACKET *radpkt;
	RADIUS_REQUEST_CTX radctx;
	radius_req_setting *rad_setting;
	char buf[128];

	if (ppp->username[0] == '\0')
		return 0;

	radpkt = NULL;
	radctx = NULL;
	rad_setting = npppd_auth_radius_get_radius_acct_setting(ppp->realm);
	if (!radius_req_setting_has_server(rad_setting))
		return 0;
	if ((radpkt = radius_new_request_packet(RADIUS_CODE_ACCOUNTING_REQUEST))
	    == NULL)
		goto fail;

	if (radius_prepare(rad_setting, (void *)(uintptr_t)ppp->id, &radctx,
	    npppd_ppp_radius_acct_reqcb, 0) != 0)
		goto fail;

    /* NAS Information */
	/*
	 * RFC 2865 "5.4.  NAS-IP-Address" or RFC 3162 "2.1. NAS-IPv6-Address"
	 */
	if (radius_prepare_nas_address(rad_setting, radpkt) != 0)
		goto fail;

	/* RFC 2865 "5.41. NAS-Port-Type" */
	ATTR_INT32(RADIUS_TYPE_NAS_PORT_TYPE, RADIUS_NAS_PORT_TYPE_VIRTUAL);

	/* RFC 2865 "5.5. NAS-Port" */
	ATTR_INT32(RADIUS_TYPE_NAS_PORT, ppp->id);
	    /* npppd has no physical / virtual ports in design. */

	/* RFC 2865 5.31. Calling-Station-Id */
	if (ppp->calling_number[0] != '\0')
		ATTR_STR(RADIUS_TYPE_CALLING_STATION_ID, ppp->calling_number);

    /* Tunnel Protocol Information */
	switch (ppp->tunnel_type) {
	case PPP_TUNNEL_L2TP:
		/* RFC 2868 3.1. Tunnel-Type */
		ATTR_INT32(RADIUS_TYPE_TUNNEL_TYPE, RADIUS_TUNNEL_TYPE_L2TP);
		if (l2tp_put_tunnel_attributes(radpkt, ppp->phy_context) != 0)
			goto fail;
		break;
	case PPP_TUNNEL_PPTP:
		/* RFC 2868 3.1. Tunnel-Type */
		ATTR_INT32(RADIUS_TYPE_TUNNEL_TYPE, RADIUS_TUNNEL_TYPE_PPTP);
		if (pptp_put_tunnel_attributes(radpkt, ppp->phy_context) != 0)
			goto fail;
		break;
	}

    /* Framed Protocol (PPP) Information */
	/* RFC 2865 5.1 User-Name */
	ATTR_STR(RADIUS_TYPE_USER_NAME, ppp->username);

	/* RFC 2865 "5.7. Service-Type" */
	ATTR_INT32(RADIUS_TYPE_SERVICE_TYPE, RADIUS_SERVICE_TYPE_FRAMED);

	/* RFC 2865 "5.8. Framed-Protocol" */
	ATTR_INT32(RADIUS_TYPE_FRAMED_PROTOCOL, RADIUS_FRAMED_PROTOCOL_PPP);

	/* RFC 2865 "5.8. Framed-IP-Address" */
	if (ppp_ip_assigned(ppp) && !stop)
		ppp->realm_framed_ip_address = ppp->ppp_framed_ip_address;
	if (ppp->realm_framed_ip_address.s_addr != INADDR_ANY) {
		ATTR_INT32(RADIUS_TYPE_FRAMED_IP_ADDRESS,
		    ntohl(ppp->realm_framed_ip_address.s_addr));
	}

    /* Accounting */
	/* RFC 2866  5.1. Acct-Status-Type */
	ATTR_INT32(RADIUS_TYPE_ACCT_STATUS_TYPE, (stop)
	    ? RADIUS_ACCT_STATUS_TYPE_STOP : RADIUS_ACCT_STATUS_TYPE_START);

	/* RFC 2866  5.2.  Acct-Delay-Time */
	ATTR_INT32(RADIUS_TYPE_ACCT_DELAY_TIME, 0);

	if (stop) {
		/* RFC 2866  5.3 Acct-Input-Octets */
		ATTR_INT32(RADIUS_TYPE_ACCT_INPUT_OCTETS,
		    (uint32_t)(ppp->ibytes & 0xFFFFFFFFU));	/* LSB 32bit */

		/* RFC 2866  5.4 Acct-Output-Octets */
		ATTR_INT32(RADIUS_TYPE_ACCT_OUTPUT_OCTETS,
		    (uint32_t)(ppp->obytes & 0xFFFFFFFFU));	/* LSB 32bit */
	}

	/* RFC 2866  5.5 Acct-Session-Id */
	snprintf(buf, sizeof(buf), "%08X%08X", pppd->boot_id, ppp->id);
	ATTR_STR(RADIUS_TYPE_ACCT_SESSION_ID, buf);

	/* RFC 2866 5.6.  Acct-Authentic */
	ATTR_INT32(RADIUS_TYPE_ACCT_AUTHENTIC, RADIUS_ACCT_AUTHENTIC_RADIUS);

	if (stop) {
		/* RFC 2866 5.7. Acct-Session-Time */
		ATTR_INT32(RADIUS_TYPE_ACCT_SESSION_TIME,
		    ppp->end_monotime - ppp->start_monotime);

		/* RFC 2866  5.8 Acct-Input-Packets */
		ATTR_INT32(RADIUS_TYPE_ACCT_INPUT_PACKETS, ppp->ipackets);

		/* RFC 2866  5.9 Acct-Output-Packets */
		ATTR_INT32(RADIUS_TYPE_ACCT_OUTPUT_PACKETS, ppp->opackets);

		/* RFC 2866  5.10. Acct-Terminate-Cause */
		if (ppp->terminate_cause != 0)
			ATTR_INT32(RADIUS_TYPE_ACCT_TERMINATE_CAUSE,
			    ppp->terminate_cause);

		/* RFC 2869  5.1 Acct-Input-Gigawords */
		ATTR_INT32(RADIUS_TYPE_ACCT_INPUT_GIGAWORDS, ppp->ibytes >> 32);

		/* RFC 2869  5.2 Acct-Output-Gigawords */
		ATTR_INT32(RADIUS_TYPE_ACCT_OUTPUT_GIGAWORDS,
		    ppp->obytes >> 32);
	}

	radius_set_request_authenticator(radpkt,
	    radius_get_server_secret(radctx));

	/* Send the request */
	radius_request(radctx, radpkt);

	return 0;

fail:
	ppp_log(ppp, LOG_WARNING, "radius accounting request failed: %m");

	if (radctx != NULL)
		radius_cancel_request(radctx);
	if (radpkt != NULL)
		radius_delete_packet(radpkt);

	return -1;
}
Example #3
0
static void
pap_radius_authenticate(pap *_this, const char *username, const char *password)
{
	void *radctx;
	RADIUS_PACKET *radpkt;
	MD5_CTX md5ctx;
	int i, j, s_len, passlen;
	u_char ra[16], digest[16], pass[128];
	const char *s;
	radius_req_setting *rad_setting = NULL;
	char buf0[MAX_USERNAME_LENGTH];

	if ((rad_setting = npppd_get_radius_auth_setting(_this->ppp->pppd,
	    _this->ppp)) == NULL)
		goto fail;

	if ((radpkt = radius_new_request_packet(RADIUS_CODE_ACCESS_REQUEST))
	    == NULL)
		goto fail;

	if (radius_prepare(rad_setting, _this, &radctx, pap_radius_response)
	    != 0) {
		radius_delete_packet(radpkt);
		goto fail;
	}

	if (ppp_set_radius_attrs_for_authreq(_this->ppp, rad_setting, radpkt)
	    != 0)
		goto fail;

	if (radius_put_string_attr(radpkt, RADIUS_TYPE_USER_NAME,
	    npppd_ppp_get_username_for_auth(_this->ppp->pppd, _this->ppp,
	    username, buf0)) != 0)
		goto fail;

	if (_this->radctx != NULL)
		radius_cancel_request(_this->radctx);

	_this->radctx = radctx;

	/* Create RADIUS User-Password Attribute (RFC 2865, 5.2.) */
	s = radius_get_server_secret(_this->radctx);
	s_len = strlen(s);

	memset(pass, 0, sizeof(pass)); /* null padding */
	passlen = MINIMUM(strlen(password), sizeof(pass));
	memcpy(pass, password, passlen);
	if ((passlen % 16) != 0)
		passlen += 16 - (passlen % 16);

	radius_get_authenticator(radpkt, ra);

	MD5Init(&md5ctx);
	MD5Update(&md5ctx, s, s_len);
	MD5Update(&md5ctx, ra, 16);
	MD5Final(digest, &md5ctx);

	for (i = 0; i < 16; i++)
		pass[i] ^= digest[i];

	while (i < passlen) {
		MD5Init(&md5ctx);
		MD5Update(&md5ctx, s, s_len);
		MD5Update(&md5ctx, &pass[i - 16], 16);
		MD5Final(digest, &md5ctx);

		for (j = 0; j < 16; j++, i++)
			pass[i] ^= digest[j];
	}

	if (radius_put_raw_attr(radpkt, RADIUS_TYPE_USER_PASSWORD, pass,
	    passlen) != 0)
		goto fail;

	radius_request(_this->radctx, radpkt);

	return;
fail:
	if (_this->radctx != NULL)
		radius_cancel_request(_this->radctx);
	pap_log(_this, LOG_ERR, "%s() failed: %m", __func__);
	pap_response(_this, 0, DEFAULT_ERROR_MESSAGE);

	return;
}