Пример #1
0
RADIUS_PACKET* radius_new_response_packet(u_int8_t code,
                                          const RADIUS_PACKET* request)
{
	RADIUS_PACKET* packet;

	packet = radius_new_request_packet(code);
	if(packet == NULL)
		return NULL;
	packet->request = request;
	packet->pdata->id = request->pdata->id;

	return packet;
}
Пример #2
0
void test00(void)
{
	RADIUS_PACKET *packet;
	uint8_t code;
	uint8_t id;
	const uint8_t *pdata;
	uint8_t authenticator[16];

	code = random();
	id = random();
	packet = radius_new_request_packet(code);
	radius_set_id(packet, id);
	pdata = (const uint8_t *)radius_get_data(packet);
	CHECK(pdata[0] == code);
	CHECK(radius_get_code(packet) == code);
	CHECK(pdata[1] == id);
	CHECK(radius_get_id(packet) == id);
	CHECK(((pdata[2] << 8) | pdata[3]) == 20);
	CHECK(radius_get_length(packet) == 20);

	CHECK(radius_get_authenticator_retval(packet) == pdata + 4);
	radius_get_authenticator(packet, authenticator);
	CHECK(memcmp(authenticator, radius_get_authenticator_retval(packet), 16) == 0);
}
Пример #3
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;
}
Пример #4
0
static void
radius_test(struct parse_result *res)
{
	struct addrinfo		 hints, *ai;
	int			 sock, retval;
	struct sockaddr_storage	 sockaddr;
	socklen_t		 sockaddrlen;
	RADIUS_PACKET		*reqpkt, *respkt;
	struct sockaddr_in	*sin4;
	struct sockaddr_in6	*sin6;
	uint32_t		 u32val;
	uint8_t			 id;

	reqpkt = radius_new_request_packet(RADIUS_CODE_ACCESS_REQUEST);
	if (reqpkt == NULL)
		err(1, "radius_new_request_packet");
	id = arc4random();
	radius_set_id(reqpkt, id);

	memset(&hints, 0, sizeof(hints));
	hints.ai_family = PF_UNSPEC;
	hints.ai_socktype = SOCK_DGRAM;

	retval = getaddrinfo(res->hostname, "radius", &hints, &ai);
	if (retval)
		errx(1, "%s %s", res->hostname, gai_strerror(retval));

	if (res->port != 0)
		((struct sockaddr_in *)ai->ai_addr)->sin_port =
		    htons(res->port);

	sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
	if (sock == -1)
		err(1, "socket");

	/* Prepare NAS-IP{,V6}-ADDRESS attribute */
	if (connect(sock, ai->ai_addr, ai->ai_addrlen) == -1)
		err(1, "connect");
	sockaddrlen = sizeof(sockaddr);
	if (getsockname(sock, (struct sockaddr *)&sockaddr, &sockaddrlen) == -1)
		err(1, "getsockname");
	sin4 = (struct sockaddr_in *)&sockaddr;
	sin6 = (struct sockaddr_in6 *)&sockaddr;
	switch (sockaddr.ss_family) {
	case AF_INET:
		radius_put_ipv4_attr(reqpkt, RADIUS_TYPE_NAS_IP_ADDRESS,
		    sin4->sin_addr);
		break;
	case AF_INET6:
		radius_put_raw_attr(reqpkt, RADIUS_TYPE_NAS_IPV6_ADDRESS,
		    sin6->sin6_addr.s6_addr, sizeof(sin6->sin6_addr.s6_addr));
		break;
	}

	/* User-Name and User-Password */
	radius_put_string_attr(reqpkt, RADIUS_TYPE_USER_NAME,
	    res->username);

	switch (res->auth_method) {
	case PAP:
		if (res->password != NULL)
			radius_put_user_password_attr(reqpkt, res->password,
			    res->secret);
		break;
	case CHAP:
	    {
		u_char	 chal[16];
		u_char	 resp[1 + MD5_DIGEST_LENGTH]; /* "1 + " for CHAP Id */
		MD5_CTX	 md5ctx;

		arc4random_buf(resp, 1);	/* CHAP Id is random */
		MD5Init(&md5ctx);
		MD5Update(&md5ctx, resp, 1);
		if (res->password != NULL)
			MD5Update(&md5ctx, res->password,
			    strlen(res->password));
		MD5Update(&md5ctx, chal, sizeof(chal));
		MD5Final(resp + 1, &md5ctx);
		radius_put_raw_attr(reqpkt, RADIUS_TYPE_CHAP_CHALLENGE,
		    chal, sizeof(chal));
		radius_put_raw_attr(reqpkt, RADIUS_TYPE_CHAP_PASSWORD,
		    resp, sizeof(resp));
	    }
		break;
	case MSCHAPV2:
	    {
		u_char	pass[256], chal[16];
		u_int	i, lpass;
		struct _resp {
			u_int8_t ident;
			u_int8_t flags;
			char peer_challenge[16];
			char reserved[8];
			char response[24];
		} __packed resp;

		if (res->password == NULL) {
			lpass = 0;
		} else {
			lpass = strlen(res->password);
			if (lpass * 2 >= sizeof(pass))
				err(1, "password too long");
			for (i = 0; i < lpass; i++) {
				pass[i * 2] = res->password[i];
				pass[i * 2 + 1] = 0;
			}
		}

		memset(&resp, 0, sizeof(resp));
		resp.ident = arc4random();
		arc4random_buf(chal, sizeof(chal));
		arc4random_buf(resp.peer_challenge,
		    sizeof(resp.peer_challenge));

		mschap_nt_response(chal, resp.peer_challenge,
		    (char *)res->username, strlen(res->username), pass,
		    lpass * 2, resp.response);

		radius_put_vs_raw_attr(reqpkt, RADIUS_VENDOR_MICROSOFT,
		    RADIUS_VTYPE_MS_CHAP_CHALLENGE, chal, sizeof(chal));
		radius_put_vs_raw_attr(reqpkt, RADIUS_VENDOR_MICROSOFT,
		    RADIUS_VTYPE_MS_CHAP2_RESPONSE, &resp, sizeof(resp));
		explicit_bzero(pass, sizeof(pass));
	    }
		break;

	}
	u32val = htonl(res->nas_port);
	radius_put_raw_attr(reqpkt, RADIUS_TYPE_NAS_PORT, &u32val, 4);

	radius_put_message_authenticator(reqpkt, res->secret);

	/* Send! */
	fprintf(stderr, "Sending:\n");
	radius_dump(stdout, reqpkt, false, res->secret);
	if (send(sock, radius_get_data(reqpkt), radius_get_length(reqpkt), 0)
	    == -1)
		warn("send");
	if ((respkt = radius_recv(sock, 0)) == NULL)
		warn("recv");
	else {
		radius_set_request_packet(respkt, reqpkt);
		fprintf(stderr, "\nReceived:\n");
		radius_dump(stdout, respkt, true, res->secret);
	}

	/* Release the resources */
	radius_delete_packet(reqpkt);
	if (respkt)
		radius_delete_packet(respkt);
	close(sock);
	freeaddrinfo(ai);

	explicit_bzero((char *)res->secret, strlen(res->secret));
	if (res->password)
		explicit_bzero((char *)res->password, strlen(res->password));

	return;
}
Пример #5
0
/************************************************************************
 * Functions for RADIUS
 * RFC 2058: RADIUS
 * RFC 2548: Microsoft Vendor-specific RADIUS Attributes
 ************************************************************************/
static void
chap_radius_authenticate(chap *_this, int id, char *username,
    u_char *challenge, int lchallenge, u_char *response)
{
	void *radctx;
	RADIUS_PACKET *radpkt;
	radius_req_setting *rad_setting;
	int lpkt;
	u_char *pkt;
	char buf0[MAX_USERNAME_LENGTH];

	radpkt = NULL;
	radctx = NULL;

	if ((rad_setting = npppd_get_radius_auth_setting(_this->ppp->pppd,
	    _this->ppp)) == NULL) {
		goto fail;	/* no radius server */
	}
	pkt = ppp_packetbuf(_this->ppp, PPP_PROTO_CHAP) + HEADERLEN;
	lpkt = _this->ppp->mru - HEADERLEN;

	if ((radpkt = radius_new_request_packet(RADIUS_CODE_ACCESS_REQUEST))
	    == NULL)
		goto fail;
	if (radius_prepare(rad_setting, _this, &radctx, chap_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;

	switch (_this->type) {
	case PPP_AUTH_CHAP_MD5:
	    {
		u_char md5response[17];

		md5response[0] = _this->challid;
		memcpy(&md5response[1], response, 16);
		if (radius_put_raw_attr(radpkt,
		    RADIUS_TYPE_CHAP_PASSWORD, md5response, 17) != 0)
			goto fail;
		if (radius_put_raw_attr(radpkt,
		    RADIUS_TYPE_CHAP_CHALLENGE, challenge, lchallenge) != 0)
			goto fail;
		break;
	    }
	case PPP_AUTH_CHAP_MS_V2:
	    {
		struct RADIUS_MS_CHAP2_RESPONSE msresponse;

		/* Preparing RADIUS_MS_CHAP2_RESPONSE  */
		memset(&msresponse, 0, sizeof(msresponse));
		msresponse.ident = id;
		msresponse.flags = response[48];
		memcpy(&msresponse.peer_challenge, response, 16);
		memcpy(&msresponse.response, response + 24, 24);

		if (radius_put_vs_raw_attr(radpkt, RADIUS_VENDOR_MICROSOFT,
		    RADIUS_VTYPE_MS_CHAP_CHALLENGE, challenge, 16) != 0)
			goto fail;
		if (radius_put_vs_raw_attr(radpkt, RADIUS_VENDOR_MICROSOFT,
		    RADIUS_VTYPE_MS_CHAP2_RESPONSE, &msresponse,
		    sizeof(msresponse)) != 0)
			goto fail;
		break;
	    }

	}
	radius_get_authenticator(radpkt, _this->authenticator);

	/* Cancel previous request */
	if (_this->radctx != NULL)
		radius_cancel_request(_this->radctx);

	/* Send a request */
	_this->radctx = radctx;
	radius_request(radctx, radpkt);

	return;
fail:
	switch (_this->type) {
	case PPP_AUTH_CHAP_MD5:
		/* No extra information, just "FAILED" */
		chap_send_error(_this, "FAILED");
		break;
	case PPP_AUTH_CHAP_MS_V2:
		/* No extra information */
		mschapv2_send_error(_this, ERROR_AUTHENTICATION_FAILURE, 0);
		break;
	}
	if (radctx != NULL)
		radius_cancel_request(radctx);
}
Пример #6
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;
}