Exemple #1
0
int radius_put_uint32_attr(RADIUS_PACKET* packet, u_int8_t type, u_int32_t val)
{
	u_int32_t nval;

	nval = htonl(val);
	return radius_put_raw_attr(packet, type, &nval, sizeof(u_int32_t));
}
Exemple #2
0
/* RFC 3579 */
int radius_put_message_authenticator(RADIUS_PACKET *packet, const char *secret)
{
	int rval;
	u_char md5result[16];
	RADIUS_ATTRIBUTE* attr;
	RADIUS_ATTRIBUTE* end;

	if ((rval = radius_put_raw_attr(packet,
	    RADIUS_TYPE_MESSAGE_AUTHENTICATOR, md5result, sizeof(md5result)))
	    != 0)
		return rval;

	radius_hmac_md5(packet, secret, strlen(secret), (caddr_t)md5result, 0);

	attr = ATTRS_BEGIN(packet->pdata);
	end  = ATTRS_END(packet->pdata);

	for(; attr<end; ADVANCE(attr))
	{
		if (attr->type == RADIUS_TYPE_MESSAGE_AUTHENTICATOR)
		{
			memcpy(attr->data, md5result, sizeof(md5result));
			break;
		}
	}

	return 0;
}
Exemple #3
0
int radius_put_ipv4_attr(RADIUS_PACKET* packet, u_int8_t type, struct in_addr addr)
{
	return radius_put_raw_attr(packet, type, &addr, sizeof(struct in_addr));
}
Exemple #4
0
int radius_put_string_attr(RADIUS_PACKET* packet, u_int8_t type,
                           const char* str)
{
	return radius_put_raw_attr(packet, type, str, strlen(str));
}
Exemple #5
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;
}
Exemple #6
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);
}
Exemple #7
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;
}