Add simple embedded RADIUS server support to libradius, by extending existing

API, keeping backward compatibility.

First consumer for this functionality is going to become forthcoming MPD-5.4,
supporting CoA and DR of RFC 3576: Dynamic Authorization Extensions to RADIUS.

MFC after:	1 month
This commit is contained in:
Alexander Motin 2009-09-11 11:42:56 +00:00
parent 493d6f54bc
commit 3fc0b61c51
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=197086
4 changed files with 334 additions and 90 deletions

View File

@ -1,4 +1,5 @@
.\" Copyright 1998 Juniper Networks, Inc.
.\" Copyright 2009 Alexander Motin <mav@FreeBSD.org>.
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
@ -24,12 +25,12 @@
.\"
.\" $FreeBSD$
.\"
.Dd April 27, 2004
.Dd August 5, 2009
.Dt LIBRADIUS 3
.Os
.Sh NAME
.Nm libradius
.Nd RADIUS client library
.Nd RADIUS client/server library
.Sh SYNOPSIS
.In radlib.h
.Ft "struct rad_handle *"
@ -46,6 +47,8 @@
.Fn rad_continue_send_request "struct rad_handle *h" "int selected" "int *fd" "struct timeval *tv"
.Ft int
.Fn rad_create_request "struct rad_handle *h" "int code"
.Ft int
.Fn rad_create_response "struct rad_handle *h" "int code"
.Ft "struct in_addr"
.Fn rad_cvt_addr "const void *data"
.Ft u_int32_t
@ -79,7 +82,13 @@
.Ft ssize_t
.Fn rad_request_authenticator "struct rad_handle *h" "char *buf" "size_t len"
.Ft int
.Fn rad_receive_request "struct rad_handle *h"
.Ft int
.Fn rad_send_request "struct rad_handle *h"
.Ft int
.Fn rad_send_response "struct rad_handle *h"
.Ft "struct rad_handle *"
.Fn rad_server_open "int fd"
.Ft "const char *"
.Fn rad_server_secret "struct rad_handle *h"
.Ft u_char *
@ -91,16 +100,17 @@
.Sh DESCRIPTION
The
.Nm
library implements the client side of the Remote Authentication Dial
In User Service (RADIUS).
library implements the Remote Authentication Dial In User Service (RADIUS).
RADIUS, defined in RFCs 2865 and 2866,
allows clients to perform authentication and accounting by means of
network requests to remote servers.
.Ss Initialization
To use the library, an application must first call
.Fn rad_auth_open
or
,
.Fn rad_acct_open
or
.Fn rad_server_open
to obtain a
.Vt "struct rad_handle *" ,
which provides the context for subsequent operations.
@ -108,8 +118,10 @@ The former function is used for RADIUS authentication and the
latter is used for RADIUS accounting.
Calls to
.Fn rad_auth_open
and
,
.Fn rad_acct_open
and
.Fn rad_server_open
always succeed unless insufficient virtual memory is available.
If
the necessary memory cannot be allocated, the functions return
@ -451,6 +463,25 @@ subsequent library calls using the same handle.
.Ss Cleanup
To free the resources used by the RADIUS library, call
.Fn rad_close .
.Ss Server operation
Server mode operates much alike to client mode, except packet send and receieve
steps are swapped. To operate as server you should obtain server context with
.Fn rad_server_open
function, passing opened and bound UDP socket file descriptor as argument.
You should define allowed clients and their secrets using
.Fn rad_add_server
function. port, timeout and max_tries arguments are ignored in server mode.
You should call
.Fn rad_receive_request
function to receive request from client. If you do not want to block on socket
read, you are free to use any poll(), select() or non-blocking sockets for
the socket.
Received request can be parsed with same parsing functions as for client.
To respond to the request you should call
.Fn rad_create_response
and fill response content with same packet writing functions as for client.
When packet is ready, it should be sent with
.Fn rad_send_response
.Sh RETURN VALUES
The following functions return a non-negative value on success.
If
@ -466,6 +497,8 @@ which can be retrieved using
.It
.Fn rad_create_request
.It
.Fn rad_create_response
.It
.Fn rad_get_attr
.It
.Fn rad_put_addr
@ -483,6 +516,8 @@ which can be retrieved using
.Fn rad_continue_send_request
.It
.Fn rad_send_request
.It
.Fn rad_send_response
.El
.Pp
The following functions return a
@ -499,6 +534,8 @@ without recording an error message.
.It
.Fn rad_auth_open
.It
.Fn rad_server_open
.It
.Fn rad_cvt_string
.El
.Pp
@ -553,3 +590,5 @@ subsequently added the ability to perform RADIUS
accounting.
Later additions and changes by
.An Michael Bretterklieber .
Server mode support was added by
.An Alexander Motin .

View File

@ -103,7 +103,7 @@ insert_scrambled_password(struct rad_handle *h, int srv)
srvp = &h->servers[srv];
padded_len = h->pass_len == 0 ? 16 : (h->pass_len+15) & ~0xf;
memcpy(md5, &h->request[POS_AUTH], LEN_AUTH);
memcpy(md5, &h->out[POS_AUTH], LEN_AUTH);
for (pos = 0; pos < padded_len; pos += 16) {
int i;
@ -120,49 +120,55 @@ insert_scrambled_password(struct rad_handle *h, int srv)
* in calculating the scrambler for next time.
*/
for (i = 0; i < 16; i++)
h->request[h->pass_pos + pos + i] =
h->out[h->pass_pos + pos + i] =
md5[i] ^= h->pass[pos + i];
}
}
static void
insert_request_authenticator(struct rad_handle *h, int srv)
insert_request_authenticator(struct rad_handle *h, int resp)
{
MD5_CTX ctx;
const struct rad_server *srvp;
srvp = &h->servers[srv];
srvp = &h->servers[h->srv];
/* Create the request authenticator */
MD5Init(&ctx);
MD5Update(&ctx, &h->request[POS_CODE], POS_AUTH - POS_CODE);
MD5Update(&ctx, memset(&h->request[POS_AUTH], 0, LEN_AUTH), LEN_AUTH);
MD5Update(&ctx, &h->request[POS_ATTRS], h->req_len - POS_ATTRS);
MD5Update(&ctx, &h->out[POS_CODE], POS_AUTH - POS_CODE);
if (resp)
MD5Update(&ctx, &h->in[POS_AUTH], LEN_AUTH);
else
MD5Update(&ctx, &h->out[POS_AUTH], LEN_AUTH);
MD5Update(&ctx, &h->out[POS_ATTRS], h->out_len - POS_ATTRS);
MD5Update(&ctx, srvp->secret, strlen(srvp->secret));
MD5Final(&h->request[POS_AUTH], &ctx);
MD5Final(&h->out[POS_AUTH], &ctx);
}
static void
insert_message_authenticator(struct rad_handle *h, int srv)
insert_message_authenticator(struct rad_handle *h, int resp)
{
#ifdef WITH_SSL
u_char md[EVP_MAX_MD_SIZE];
u_int md_len;
const struct rad_server *srvp;
HMAC_CTX ctx;
srvp = &h->servers[srv];
srvp = &h->servers[h->srv];
if (h->authentic_pos != 0) {
HMAC_CTX_init(&ctx);
HMAC_Init(&ctx, srvp->secret, strlen(srvp->secret), EVP_md5());
HMAC_Update(&ctx, &h->request[POS_CODE], POS_AUTH - POS_CODE);
HMAC_Update(&ctx, &h->request[POS_AUTH], LEN_AUTH);
HMAC_Update(&ctx, &h->request[POS_ATTRS],
h->req_len - POS_ATTRS);
HMAC_Update(&ctx, &h->out[POS_CODE], POS_AUTH - POS_CODE);
if (resp)
HMAC_Update(&ctx, &h->in[POS_AUTH], LEN_AUTH);
else
HMAC_Update(&ctx, &h->out[POS_AUTH], LEN_AUTH);
HMAC_Update(&ctx, &h->out[POS_ATTRS],
h->out_len - POS_ATTRS);
HMAC_Final(&ctx, md, &md_len);
HMAC_CTX_cleanup(&ctx);
HMAC_cleanup(&ctx);
memcpy(&h->request[h->authentic_pos + 2], md, md_len);
memcpy(&h->out[h->authentic_pos + 2], md, md_len);
}
#endif
}
@ -195,20 +201,20 @@ is_valid_response(struct rad_handle *h, int srv,
return 0;
/* Check the message length */
if (h->resp_len < POS_ATTRS)
if (h->in_len < POS_ATTRS)
return 0;
len = h->response[POS_LENGTH] << 8 | h->response[POS_LENGTH+1];
if (len > h->resp_len)
len = h->in[POS_LENGTH] << 8 | h->in[POS_LENGTH+1];
if (len > h->in_len)
return 0;
/* Check the response authenticator */
MD5Init(&ctx);
MD5Update(&ctx, &h->response[POS_CODE], POS_AUTH - POS_CODE);
MD5Update(&ctx, &h->request[POS_AUTH], LEN_AUTH);
MD5Update(&ctx, &h->response[POS_ATTRS], len - POS_ATTRS);
MD5Update(&ctx, &h->in[POS_CODE], POS_AUTH - POS_CODE);
MD5Update(&ctx, &h->out[POS_AUTH], LEN_AUTH);
MD5Update(&ctx, &h->in[POS_ATTRS], len - POS_ATTRS);
MD5Update(&ctx, srvp->secret, strlen(srvp->secret));
MD5Final(md5, &ctx);
if (memcmp(&h->response[POS_AUTH], md5, sizeof md5) != 0)
if (memcmp(&h->in[POS_AUTH], md5, sizeof md5) != 0)
return 0;
#ifdef WITH_SSL
@ -216,42 +222,111 @@ is_valid_response(struct rad_handle *h, int srv,
* For non accounting responses check the message authenticator,
* if any.
*/
if (h->response[POS_CODE] != RAD_ACCOUNTING_RESPONSE) {
if (h->in[POS_CODE] != RAD_ACCOUNTING_RESPONSE) {
memcpy(resp, h->response, MSGSIZE);
memcpy(resp, h->in, MSGSIZE);
pos = POS_ATTRS;
/* Search and verify the Message-Authenticator */
while (pos < len - 2) {
if (h->response[pos] == RAD_MESSAGE_AUTHENTIC) {
if (h->in[pos] == RAD_MESSAGE_AUTHENTIC) {
/* zero fill the Message-Authenticator */
memset(&resp[pos + 2], 0, MD5_DIGEST_LENGTH);
HMAC_CTX_init(&hctx);
HMAC_Init(&hctx, srvp->secret,
strlen(srvp->secret), EVP_md5());
HMAC_Update(&hctx, &h->response[POS_CODE],
HMAC_Update(&hctx, &h->in[POS_CODE],
POS_AUTH - POS_CODE);
HMAC_Update(&hctx, &h->request[POS_AUTH],
HMAC_Update(&hctx, &h->out[POS_AUTH],
LEN_AUTH);
HMAC_Update(&hctx, &resp[POS_ATTRS],
h->resp_len - POS_ATTRS);
h->in_len - POS_ATTRS);
HMAC_Final(&hctx, md, &md_len);
HMAC_CTX_cleanup(&hctx);
HMAC_cleanup(&hctx);
if (memcmp(md, &h->response[pos + 2],
if (memcmp(md, &h->in[pos + 2],
MD5_DIGEST_LENGTH) != 0)
return 0;
break;
}
pos += h->response[pos + 1];
pos += h->in[pos + 1];
}
}
#endif
return 1;
}
/*
* Return true if the current request is valid for the specified server.
*/
static int
is_valid_request(struct rad_handle *h)
{
MD5_CTX ctx;
unsigned char md5[MD5_DIGEST_LENGTH];
const struct rad_server *srvp;
int len;
#ifdef WITH_SSL
HMAC_CTX hctx;
u_char resp[MSGSIZE], md[EVP_MAX_MD_SIZE];
u_int md_len;
int pos;
#endif
srvp = &h->servers[h->srv];
/* Check the message length */
if (h->in_len < POS_ATTRS)
return (0);
len = h->in[POS_LENGTH] << 8 | h->in[POS_LENGTH+1];
if (len > h->in_len)
return (0);
if (h->in[POS_CODE] != RAD_ACCESS_REQUEST) {
uint32_t zeroes[4] = { 0, 0, 0, 0 };
/* Check the request authenticator */
MD5Init(&ctx);
MD5Update(&ctx, &h->in[POS_CODE], POS_AUTH - POS_CODE);
MD5Update(&ctx, zeroes, LEN_AUTH);
MD5Update(&ctx, &h->in[POS_ATTRS], len - POS_ATTRS);
MD5Update(&ctx, srvp->secret, strlen(srvp->secret));
MD5Final(md5, &ctx);
if (memcmp(&h->in[POS_AUTH], md5, sizeof md5) != 0)
return (0);
}
#ifdef WITH_SSL
/* Search and verify the Message-Authenticator */
pos = POS_ATTRS;
while (pos < len - 2) {
if (h->in[pos] == RAD_MESSAGE_AUTHENTIC) {
memcpy(resp, h->in, MSGSIZE);
/* zero fill the Request-Authenticator */
if (h->in[POS_CODE] != RAD_ACCESS_REQUEST)
memset(&resp[POS_AUTH], 0, LEN_AUTH);
/* zero fill the Message-Authenticator */
memset(&resp[pos + 2], 0, MD5_DIGEST_LENGTH);
HMAC_CTX_init(&hctx);
HMAC_Init(&hctx, srvp->secret,
strlen(srvp->secret), EVP_md5());
HMAC_Update(&hctx, resp, h->in_len);
HMAC_Final(&hctx, md, &md_len);
HMAC_CTX_cleanup(&hctx);
HMAC_cleanup(&hctx);
if (memcmp(md, &h->in[pos + 2],
MD5_DIGEST_LENGTH) != 0)
return (0);
break;
}
pos += h->in[pos + 1];
}
#endif
return (1);
}
static int
put_password_attr(struct rad_handle *h, int type, const void *value, size_t len)
{
@ -273,7 +348,7 @@ put_password_attr(struct rad_handle *h, int type, const void *value, size_t len)
*/
clear_password(h);
put_raw_attr(h, type, h->pass, padded_len);
h->pass_pos = h->req_len - padded_len;
h->pass_pos = h->out_len - padded_len;
/* Save the cleartext password, padded as necessary */
memcpy(h->pass, value, len);
@ -289,14 +364,14 @@ put_raw_attr(struct rad_handle *h, int type, const void *value, size_t len)
generr(h, "Attribute too long");
return -1;
}
if (h->req_len + 2 + len > MSGSIZE) {
if (h->out_len + 2 + len > MSGSIZE) {
generr(h, "Maximum message length exceeded");
return -1;
}
h->request[h->req_len++] = type;
h->request[h->req_len++] = len + 2;
memcpy(&h->request[h->req_len], value, len);
h->req_len += len;
h->out[h->out_len++] = type;
h->out[h->out_len++] = len + 2;
memcpy(&h->out[h->out_len], value, len);
h->out_len += len;
return 0;
}
@ -523,22 +598,26 @@ rad_continue_send_request(struct rad_handle *h, int selected, int *fd,
{
int n;
if (h->type == RADIUS_SERVER) {
generr(h, "denied function call");
return (-1);
}
if (selected) {
struct sockaddr_in from;
socklen_t fromlen;
fromlen = sizeof from;
h->resp_len = recvfrom(h->fd, h->response,
h->in_len = recvfrom(h->fd, h->in,
MSGSIZE, MSG_WAITALL, (struct sockaddr *)&from, &fromlen);
if (h->resp_len == -1) {
if (h->in_len == -1) {
generr(h, "recvfrom: %s", strerror(errno));
return -1;
}
if (is_valid_response(h, h->srv, &from)) {
h->resp_len = h->response[POS_LENGTH] << 8 |
h->response[POS_LENGTH+1];
h->resp_pos = POS_ATTRS;
return h->response[POS_CODE];
h->in_len = h->in[POS_LENGTH] << 8 |
h->in[POS_LENGTH+1];
h->in_pos = POS_ATTRS;
return h->in[POS_CODE];
}
}
@ -556,21 +635,22 @@ rad_continue_send_request(struct rad_handle *h, int selected, int *fd,
if (++h->srv >= h->num_servers)
h->srv = 0;
if (h->request[POS_CODE] == RAD_ACCOUNTING_REQUEST)
/* Insert the request authenticator into the request */
insert_request_authenticator(h, h->srv);
else
if (h->out[POS_CODE] == RAD_ACCESS_REQUEST) {
/* Insert the scrambled password into the request */
if (h->pass_pos != 0)
insert_scrambled_password(h, h->srv);
insert_message_authenticator(h, h->srv);
}
insert_message_authenticator(h, 0);
if (h->out[POS_CODE] != RAD_ACCESS_REQUEST) {
/* Insert the request authenticator into the request */
insert_request_authenticator(h, h->srv);
}
/* Send the request */
n = sendto(h->fd, h->request, h->req_len, 0,
n = sendto(h->fd, h->out, h->out_len, 0,
(const struct sockaddr *)&h->servers[h->srv].addr,
sizeof h->servers[h->srv].addr);
if (n != h->req_len) {
if (n != h->out_len) {
if (n == -1)
generr(h, "sendto: %s", strerror(errno));
else
@ -587,23 +667,118 @@ rad_continue_send_request(struct rad_handle *h, int selected, int *fd,
return 0;
}
int
rad_receive_request(struct rad_handle *h)
{
struct sockaddr_in from;
socklen_t fromlen;
int n;
if (h->type != RADIUS_SERVER) {
generr(h, "denied function call");
return (-1);
}
h->srv = -1;
fromlen = sizeof(from);
h->in_len = recvfrom(h->fd, h->in,
MSGSIZE, MSG_WAITALL, (struct sockaddr *)&from, &fromlen);
if (h->in_len == -1) {
generr(h, "recvfrom: %s", strerror(errno));
return (-1);
}
for (n = 0; n < h->num_servers; n++) {
if (h->servers[n].addr.sin_addr.s_addr == from.sin_addr.s_addr) {
h->servers[n].addr.sin_port = from.sin_port;
h->srv = n;
break;
}
}
if (h->srv == -1)
return (-2);
if (is_valid_request(h)) {
h->in_len = h->in[POS_LENGTH] << 8 |
h->in[POS_LENGTH+1];
h->in_pos = POS_ATTRS;
return (h->in[POS_CODE]);
}
return (-3);
}
int
rad_send_response(struct rad_handle *h)
{
int n;
if (h->type != RADIUS_SERVER) {
generr(h, "denied function call");
return (-1);
}
/* Fill in the length field in the message */
h->out[POS_LENGTH] = h->out_len >> 8;
h->out[POS_LENGTH+1] = h->out_len;
insert_message_authenticator(h,
(h->in[POS_CODE] == RAD_ACCESS_REQUEST) ? 1 : 0);
insert_request_authenticator(h, 1);
/* Send the request */
n = sendto(h->fd, h->out, h->out_len, 0,
(const struct sockaddr *)&h->servers[h->srv].addr,
sizeof h->servers[h->srv].addr);
if (n != h->out_len) {
if (n == -1)
generr(h, "sendto: %s", strerror(errno));
else
generr(h, "sendto: short write");
return -1;
}
return 0;
}
int
rad_create_request(struct rad_handle *h, int code)
{
int i;
h->request[POS_CODE] = code;
h->request[POS_IDENT] = ++h->ident;
/* Create a random authenticator */
for (i = 0; i < LEN_AUTH; i += 2) {
long r;
r = random();
h->request[POS_AUTH+i] = (u_char)r;
h->request[POS_AUTH+i+1] = (u_char)(r >> 8);
if (h->type == RADIUS_SERVER) {
generr(h, "denied function call");
return (-1);
}
h->req_len = POS_ATTRS;
h->out[POS_CODE] = code;
h->out[POS_IDENT] = ++h->ident;
if (code == RAD_ACCESS_REQUEST) {
/* Create a random authenticator */
for (i = 0; i < LEN_AUTH; i += 2) {
long r;
r = random();
h->out[POS_AUTH+i] = (u_char)r;
h->out[POS_AUTH+i+1] = (u_char)(r >> 8);
}
} else
memset(&h->out[POS_AUTH], 0, LEN_AUTH);
h->out_len = POS_ATTRS;
clear_password(h);
h->request_created = 1;
h->authentic_pos = 0;
h->out_created = 1;
return 0;
}
int
rad_create_response(struct rad_handle *h, int code)
{
if (h->type != RADIUS_SERVER) {
generr(h, "denied function call");
return (-1);
}
h->out[POS_CODE] = code;
h->out[POS_IDENT] = h->in[POS_IDENT];
memset(&h->out[POS_AUTH], 0, LEN_AUTH);
h->out_len = POS_ATTRS;
clear_password(h);
h->authentic_pos = 0;
h->out_created = 1;
return 0;
}
@ -647,20 +822,20 @@ rad_get_attr(struct rad_handle *h, const void **value, size_t *len)
{
int type;
if (h->resp_pos >= h->resp_len)
if (h->in_pos >= h->in_len)
return 0;
if (h->resp_pos + 2 > h->resp_len) {
if (h->in_pos + 2 > h->in_len) {
generr(h, "Malformed attribute in response");
return -1;
}
type = h->response[h->resp_pos++];
*len = h->response[h->resp_pos++] - 2;
if (h->resp_pos + (int)*len > h->resp_len) {
type = h->in[h->in_pos++];
*len = h->in[h->in_pos++] - 2;
if (h->in_pos + (int)*len > h->in_len) {
generr(h, "Malformed attribute in response");
return -1;
}
*value = &h->response[h->resp_pos];
h->resp_pos += *len;
*value = &h->in[h->in_pos];
h->in_pos += *len;
return type;
}
@ -672,6 +847,10 @@ rad_init_send_request(struct rad_handle *h, int *fd, struct timeval *tv)
{
int srv;
if (h->type == RADIUS_SERVER) {
generr(h, "denied function call");
return (-1);
}
/* Make sure we have a socket to use */
if (h->fd == -1) {
struct sockaddr_in sin;
@ -694,7 +873,7 @@ rad_init_send_request(struct rad_handle *h, int *fd, struct timeval *tv)
}
}
if (h->request[POS_CODE] == RAD_ACCOUNTING_REQUEST) {
if (h->out[POS_CODE] != RAD_ACCESS_REQUEST) {
/* Make sure no password given */
if (h->pass_pos || h->chap_pass) {
generr(h, "User or Chap Password"
@ -718,8 +897,8 @@ rad_init_send_request(struct rad_handle *h, int *fd, struct timeval *tv)
}
/* Fill in the length field in the message */
h->request[POS_LENGTH] = h->req_len >> 8;
h->request[POS_LENGTH+1] = h->req_len;
h->out[POS_LENGTH] = h->out_len >> 8;
h->out[POS_LENGTH+1] = h->out_len;
/*
* Count the total number of tries we will make, and zero the
@ -763,7 +942,7 @@ rad_auth_open(void)
h->chap_pass = 0;
h->authentic_pos = 0;
h->type = RADIUS_AUTH;
h->request_created = 0;
h->out_created = 0;
h->eap_msg = 0;
}
return h;
@ -780,6 +959,19 @@ rad_acct_open(void)
return h;
}
struct rad_handle *
rad_server_open(int fd)
{
struct rad_handle *h;
h = rad_open();
if (h != NULL) {
h->type = RADIUS_SERVER;
h->fd = fd;
}
return h;
}
struct rad_handle *
rad_open(void)
{
@ -797,13 +989,13 @@ rad_put_attr(struct rad_handle *h, int type, const void *value, size_t len)
{
int result;
if (!h->request_created) {
if (!h->out_created) {
generr(h, "Please call rad_create_request()"
" before putting attributes");
return -1;
}
if (h->request[POS_CODE] == RAD_ACCOUNTING_REQUEST) {
if (h->out[POS_CODE] == RAD_ACCOUNTING_REQUEST) {
if (type == RAD_EAP_MESSAGE) {
generr(h, "EAP-Message attribute is not valid"
" in accounting requests");
@ -858,14 +1050,14 @@ rad_put_message_authentic(struct rad_handle *h)
#ifdef WITH_SSL
u_char md_zero[MD5_DIGEST_LENGTH];
if (h->request[POS_CODE] == RAD_ACCOUNTING_REQUEST) {
if (h->out[POS_CODE] == RAD_ACCOUNTING_REQUEST) {
generr(h, "Message-Authenticator is not valid"
" in accounting requests");
return -1;
}
if (h->authentic_pos == 0) {
h->authentic_pos = h->req_len;
h->authentic_pos = h->out_len;
memset(md_zero, 0, sizeof(md_zero));
return (put_raw_attr(h, RAD_MESSAGE_AUTHENTIC, md_zero,
sizeof(md_zero)));
@ -1041,7 +1233,7 @@ rad_put_vendor_attr(struct rad_handle *h, int vendor, int type,
struct vendor_attribute *attr;
int res;
if (!h->request_created) {
if (!h->out_created) {
generr(h, "Please call rad_create_request()"
" before putting attributes");
return -1;
@ -1088,7 +1280,7 @@ rad_request_authenticator(struct rad_handle *h, char *buf, size_t len)
{
if (len < LEN_AUTH)
return (-1);
memcpy(buf, h->request + POS_AUTH, LEN_AUTH);
memcpy(buf, h->out + POS_AUTH, LEN_AUTH);
if (len > LEN_AUTH)
buf[LEN_AUTH] = '\0';
return (LEN_AUTH);

View File

@ -42,6 +42,12 @@
#define RAD_ACCOUNTING_REQUEST 4
#define RAD_ACCOUNTING_RESPONSE 5
#define RAD_ACCESS_CHALLENGE 11
#define RAD_DISCONNECT_REQUEST 40
#define RAD_DISCONNECT_ACK 41
#define RAD_DISCONNECT_NAK 42
#define RAD_COA_REQUEST 43
#define RAD_COA_ACK 44
#define RAD_COA_NAK 45
/* Attribute types and values */
#define RAD_USER_NAME 1 /* String */
@ -179,6 +185,8 @@
#define RAD_ACCT_MULTI_SESSION_ID 50 /* String */
#define RAD_ACCT_LINK_COUNT 51 /* Integer */
#define RAD_ERROR_CAUSE 101 /* Integer */
struct rad_handle;
struct timeval;
@ -192,6 +200,7 @@ int rad_config(struct rad_handle *, const char *);
int rad_continue_send_request(struct rad_handle *, int,
int *, struct timeval *);
int rad_create_request(struct rad_handle *, int);
int rad_create_response(struct rad_handle *, int);
struct in_addr rad_cvt_addr(const void *);
u_int32_t rad_cvt_int(const void *);
char *rad_cvt_string(const void *, size_t);
@ -209,7 +218,10 @@ int rad_put_string(struct rad_handle *, int,
int rad_put_message_authentic(struct rad_handle *);
ssize_t rad_request_authenticator(struct rad_handle *, char *,
size_t);
int rad_receive_request(struct rad_handle *);
int rad_send_request(struct rad_handle *);
int rad_send_response(struct rad_handle *);
struct rad_handle *rad_server_open(int fd);
const char *rad_server_secret(struct rad_handle *);
const char *rad_strerror(struct rad_handle *);
u_char *rad_demangle(struct rad_handle *, const void *,

View File

@ -38,6 +38,7 @@
/* Handle types */
#define RADIUS_AUTH 0 /* RADIUS authentication, default */
#define RADIUS_ACCT 1 /* RADIUS accounting */
#define RADIUS_SERVER 2 /* RADIUS server */
/* Defaults */
#define MAXTRIES 3
@ -75,18 +76,18 @@ struct rad_handle {
int num_servers; /* Number of valid server entries */
int ident; /* Current identifier value */
char errmsg[ERRSIZE]; /* Most recent error message */
unsigned char request[MSGSIZE]; /* Request to send */
char request_created; /* rad_create_request() called? */
int req_len; /* Length of request */
unsigned char out[MSGSIZE]; /* Request to send */
char out_created; /* rad_create_request() called? */
int out_len; /* Length of request */
char pass[PASSSIZE]; /* Cleartext password */
int pass_len; /* Length of cleartext password */
int pass_pos; /* Position of scrambled password */
char chap_pass; /* Have we got a CHAP_PASSWORD ? */
char chap_pass; /* Have we got a CHAP_PASSWORD ? */
int authentic_pos; /* Position of message authenticator */
char eap_msg; /* Are we an EAP Proxy? */
unsigned char response[MSGSIZE]; /* Response received */
int resp_len; /* Length of response */
int resp_pos; /* Current position scanning attrs */
unsigned char in[MSGSIZE]; /* Response received */
int in_len; /* Length of response */
int in_pos; /* Current position scanning attrs */
int total_tries; /* How many requests we'll send */
int try; /* How many requests we've sent */
int srv; /* Server number we did last */