aboutsummaryrefslogtreecommitdiff
path: root/lib/libradius
diff options
context:
space:
mode:
authorAlexander Motin <mav@FreeBSD.org>2009-09-11 11:42:56 +0000
committerAlexander Motin <mav@FreeBSD.org>2009-09-11 11:42:56 +0000
commit3fc0b61c51969c20551372e9c4adb4943e96dbd3 (patch)
tree62d154acac53838b9afff7d63c697fe60f8f19bc /lib/libradius
parent493d6f54bc85aee304350c1a063994471d7c2d2c (diff)
downloadsrc-3fc0b61c51969c20551372e9c4adb4943e96dbd3.tar.gz
src-3fc0b61c51969c20551372e9c4adb4943e96dbd3.zip
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
Notes
Notes: svn path=/head/; revision=197086
Diffstat (limited to 'lib/libradius')
-rw-r--r--lib/libradius/libradius.351
-rw-r--r--lib/libradius/radlib.c346
-rw-r--r--lib/libradius/radlib.h12
-rw-r--r--lib/libradius/radlib_private.h15
4 files changed, 334 insertions, 90 deletions
diff --git a/lib/libradius/libradius.3 b/lib/libradius/libradius.3
index 095d6e9a58aa..9a71521d8922 100644
--- a/lib/libradius/libradius.3
+++ b/lib/libradius/libradius.3
@@ -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 .
diff --git a/lib/libradius/radlib.c b/lib/libradius/radlib.c
index b21447ef9c41..8faaf7e12a60 100644
--- a/lib/libradius/radlib.c
+++ b/lib/libradius/radlib.c
@@ -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
@@ -588,22 +668,117 @@ rad_continue_send_request(struct rad_handle *h, int selected, int *fd,
}
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->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->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->req_len = POS_ATTRS;
+ 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->request_created = 1;
+ 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;
@@ -781,6 +960,19 @@ rad_acct_open(void)
}
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)
{
return rad_auth_open();
@@ -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);
diff --git a/lib/libradius/radlib.h b/lib/libradius/radlib.h
index 2c42c3a9f40e..b26be41d66ef 100644
--- a/lib/libradius/radlib.h
+++ b/lib/libradius/radlib.h
@@ -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 *,
diff --git a/lib/libradius/radlib_private.h b/lib/libradius/radlib_private.h
index d323cbd5fcc9..d886c740b3fd 100644
--- a/lib/libradius/radlib_private.h
+++ b/lib/libradius/radlib_private.h
@@ -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 */