예제 #1
0
int radius_send(int s, const RADIUS_PACKET* packet, int flags)
{
	ssize_t n;

	n = send(s, packet->pdata, radius_get_length(packet), flags);
	if(n != radius_get_length(packet))
		return 1;
	return 0;
}
예제 #2
0
int radius_sendto(int s, const RADIUS_PACKET* packet,
                  int flags, const struct sockaddr* addr, socklen_t len)
{
	ssize_t n;

	n = sendto(s, packet->pdata, radius_get_length(packet), flags, addr, len);
	if(n != radius_get_length(packet))
		return 1;
	return 0;
}
예제 #3
0
int radius_put_raw_attr_all(RADIUS_PACKET* packet, u_int8_t type,
                            caddr_t buf, int length)
{
	int off, len0;
	RADIUS_ATTRIBUTE* newattr;

	off = 0;
	while (off < length) {
		len0 = MIN(length - off, 255-2);

		if(radius_ensure_add_capacity(packet, len0+2) != 0)
			return 1;

		newattr = ATTRS_END(packet->pdata);
		newattr->type = type;
		newattr->length = len0 + 2;
		memcpy(newattr->data, buf, len0);
		packet->pdata->length = htons(radius_get_length(packet) +
		    len0 + 2);

		off += len0;
	}

	return 0;
}
예제 #4
0
int radius_put_vs_raw_attr_all(RADIUS_PACKET* packet, u_int32_t vendor,
                               u_int8_t vtype, const void* buf, int length)
{
	int off, len0;
	RADIUS_ATTRIBUTE* newattr;

	off = 0;
	while (off < length) {
		len0 = MIN(length - off, 255-8);

		if(radius_ensure_add_capacity(packet, len0+8) != 0)
			return 1;

		newattr = ATTRS_END(packet->pdata);
		newattr->type = RADIUS_TYPE_VENDOR_SPECIFIC;
		newattr->length = len0 + 8;
		newattr->vendor = htonl(vendor);
		newattr->vtype = vtype;
		newattr->vlength = len0 + 2;
		memcpy(newattr->vdata, buf, len0);
		packet->pdata->length = htons(radius_get_length(packet) +
		    len0 + 8);

		off += len0;
	}

	return 0;
}
예제 #5
0
void radius_set_response_authenticator(RADIUS_PACKET* packet,
                                       const char* secret)
{
	MD5_CTX ctx;

	MD5Init(&ctx);
	MD5Update(&ctx, (unsigned char*)packet->pdata, 4);
	MD5Update(&ctx,
		  (unsigned char*)packet->request->pdata->authenticator, 16);
	MD5Update(&ctx,
		  (unsigned char*)packet->pdata->attributes,
		  radius_get_length(packet) - 20);
	MD5Update(&ctx, (unsigned char*)secret, strlen(secret));
	MD5Final((unsigned char*)packet->pdata->authenticator ,&ctx);
}
예제 #6
0
void radius_set_request_authenticator(RADIUS_PACKET* packet,
                                       const char* secret)
{
	MD5_CTX ctx;
	u_char zero[16];

	memset(zero, 0, sizeof(zero));
	MD5Init(&ctx);
	MD5Update(&ctx, (unsigned char*)packet->pdata, 4);
	MD5Update(&ctx, zero, 16);
	MD5Update(&ctx,
		  (unsigned char*)packet->pdata->attributes,
		  radius_get_length(packet) - 20);
	MD5Update(&ctx, (unsigned char*)secret, strlen(secret));
	MD5Final((unsigned char*)packet->pdata->authenticator ,&ctx);
}
예제 #7
0
int radius_put_raw_attr(RADIUS_PACKET* packet, u_int8_t type,
                        const void* buf, u_int8_t length)
{
	RADIUS_ATTRIBUTE* newattr;

	if(length > 255-2)
		return 1;

	if(radius_ensure_add_capacity(packet, length+2) != 0)
		return 1;

	newattr = ATTRS_END(packet->pdata);
	newattr->type = type;
	newattr->length = length + 2;
	memcpy(newattr->data, buf, length);
	packet->pdata->length = htons(radius_get_length(packet) + length + 2);

	return 0;
}
예제 #8
0
int radius_put_vs_raw_attr(RADIUS_PACKET* packet, u_int32_t vendor,
                           u_int8_t vtype, const void* buf, u_int8_t length)
{
	RADIUS_ATTRIBUTE* newattr;

	if(length > 255-8)
		return 1;

	if(radius_ensure_add_capacity(packet, length+8) != 0)
		return 1;

	newattr = ATTRS_END(packet->pdata);
	newattr->type = RADIUS_TYPE_VENDOR_SPECIFIC;
	newattr->length = length + 8;
	newattr->vendor = htonl(vendor);
	newattr->vtype = vtype;
	newattr->vlength = length + 2;
	memcpy(newattr->vdata, buf, length);
	packet->pdata->length = htons(radius_get_length(packet) + length + 8);

	return 0;
}
예제 #9
0
int radius_check_response_authenticator(const RADIUS_PACKET* packet,
                                        const char* secret)
{
	MD5_CTX ctx;
	unsigned char authenticator0[16];

	/* Assume radius_set_request_packet() was called before calling */
	if (packet->request == NULL)
		return -1;

	MD5Init(&ctx);
	MD5Update(&ctx, (unsigned char*)packet->pdata, 4);
	MD5Update(&ctx, (unsigned char*)packet->request->pdata->authenticator,
	    	  16);
	MD5Update(&ctx,
		  (unsigned char*)packet->pdata->attributes,
		  radius_get_length(packet) - 20);
	MD5Update(&ctx, (unsigned char*)secret, strlen(secret));
	MD5Final((unsigned char *)authenticator0, &ctx);

	return memcmp(authenticator0, packet->pdata->authenticator, 16);
}
예제 #10
0
파일: test00.c 프로젝트: ajinkya93/OpenBSD
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);
}
예제 #11
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;
}