- Rewrite radius servers traversal algorithm.
- Add functions for working with IPv6 attributes. Approved by: ae
This commit is contained in:
parent
38ce9496fe
commit
bf5a1b6502
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=243956
@ -35,6 +35,7 @@ MAN= libradius.3 radius.conf.5
|
|||||||
|
|
||||||
MLINKS+=libradius.3 rad_acct_open.3 \
|
MLINKS+=libradius.3 rad_acct_open.3 \
|
||||||
libradius.3 rad_add_server.3 \
|
libradius.3 rad_add_server.3 \
|
||||||
|
libradius.3 rad_add_server_ex.3 \
|
||||||
libradius.3 rad_auth_open.3 \
|
libradius.3 rad_auth_open.3 \
|
||||||
libradius.3 rad_bind_to.3 \
|
libradius.3 rad_bind_to.3 \
|
||||||
libradius.3 rad_close.3 \
|
libradius.3 rad_close.3 \
|
||||||
|
@ -37,6 +37,8 @@
|
|||||||
.Fn rad_acct_open "void"
|
.Fn rad_acct_open "void"
|
||||||
.Ft int
|
.Ft int
|
||||||
.Fn rad_add_server "struct rad_handle *h" "const char *host" "int port" "const char *secret" "int timeout" "int max_tries"
|
.Fn rad_add_server "struct rad_handle *h" "const char *host" "int port" "const char *secret" "int timeout" "int max_tries"
|
||||||
|
.Ft int
|
||||||
|
.Fn rad_add_server_ex "struct rad_handle *h" "const char *host" "int port" "const char *secret" "int timeout" "int max_tries" "int dead_time" "struct in_addr bindto"
|
||||||
.Ft "struct rad_handle *"
|
.Ft "struct rad_handle *"
|
||||||
.Fn rad_auth_open "void"
|
.Fn rad_auth_open "void"
|
||||||
.Ft void
|
.Ft void
|
||||||
@ -153,7 +155,12 @@ is used.
|
|||||||
returns 0 on success, or \-1 if an error occurs.
|
returns 0 on success, or \-1 if an error occurs.
|
||||||
.Pp
|
.Pp
|
||||||
The library can also be configured programmatically by calls to
|
The library can also be configured programmatically by calls to
|
||||||
.Fn rad_add_server .
|
.Fn rad_add_server
|
||||||
|
or
|
||||||
|
.Fn rad_add_server_ex .
|
||||||
|
.Fn rad_add_server
|
||||||
|
is a backward compatible function, implemented via
|
||||||
|
.Fn rad_add_server_ex .
|
||||||
The
|
The
|
||||||
.Fa host
|
.Fa host
|
||||||
parameter specifies the server host, either as a fully qualified
|
parameter specifies the server host, either as a fully qualified
|
||||||
@ -188,11 +195,20 @@ The maximum number of repeated
|
|||||||
requests to make before giving up is passed into the
|
requests to make before giving up is passed into the
|
||||||
.Fa max_tries
|
.Fa max_tries
|
||||||
parameter.
|
parameter.
|
||||||
|
Time interval in seconds when the server will not be requested
|
||||||
|
if it is marked as dead (did not answer on the last try) set with
|
||||||
|
.Fa dead_time
|
||||||
|
parameter.
|
||||||
|
.Fa bindto
|
||||||
|
parameter is an IP address on the multihomed host that is used as
|
||||||
|
a source address for all requests.
|
||||||
.Fn rad_add_server
|
.Fn rad_add_server
|
||||||
returns 0 on success, or \-1 if an error occurs.
|
returns 0 on success, or \-1 if an error occurs.
|
||||||
.Pp
|
.Pp
|
||||||
.Fn rad_add_server
|
.Fn rad_add_server
|
||||||
may be called multiple times, and it may be used together with
|
or
|
||||||
|
.Fn rad_add_server_ex
|
||||||
|
may be called multiple times, and they may be used together with
|
||||||
.Fn rad_config .
|
.Fn rad_config .
|
||||||
At most 10 servers may be specified.
|
At most 10 servers may be specified.
|
||||||
When multiple servers are given, they are tried in round-robin
|
When multiple servers are given, they are tried in round-robin
|
||||||
|
@ -44,7 +44,7 @@ Leading
|
|||||||
white space is ignored, as are empty lines and lines containing
|
white space is ignored, as are empty lines and lines containing
|
||||||
only comments.
|
only comments.
|
||||||
.Pp
|
.Pp
|
||||||
A RADIUS server is described by three to five fields on a line:
|
A RADIUS server is described by three to seven fields on a line:
|
||||||
.Pp
|
.Pp
|
||||||
.Bl -item -offset indent -compact
|
.Bl -item -offset indent -compact
|
||||||
.It
|
.It
|
||||||
@ -57,6 +57,10 @@ Shared secret
|
|||||||
Timeout
|
Timeout
|
||||||
.It
|
.It
|
||||||
Retries
|
Retries
|
||||||
|
.It
|
||||||
|
Dead time
|
||||||
|
.It
|
||||||
|
Bind address
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
The fields are separated by white space.
|
The fields are separated by white space.
|
||||||
@ -139,6 +143,13 @@ If omitted, it defaults to 3 attempts.
|
|||||||
Note,
|
Note,
|
||||||
this is the total number of attempts and not the number of retries.
|
this is the total number of attempts and not the number of retries.
|
||||||
.Pp
|
.Pp
|
||||||
|
The sixth field contains a decimal integer specifying a time interval
|
||||||
|
in seconds when the server will not requested if it was inaccessible
|
||||||
|
on the last try. 0 means ask always.
|
||||||
|
.Pp
|
||||||
|
The seventh field contains an IP address on multihomed host. All
|
||||||
|
requests will be binded to this IP.
|
||||||
|
.Pp
|
||||||
Up to 10 RADIUS servers may be specified for each service type.
|
Up to 10 RADIUS servers may be specified for each service type.
|
||||||
The servers are tried in
|
The servers are tried in
|
||||||
round-robin fashion, until a valid response is received or the
|
round-robin fashion, until a valid response is received or the
|
||||||
@ -161,6 +172,9 @@ acct radius1.domain.com OurLittleSecret
|
|||||||
# timeout and maximum tries:
|
# timeout and maximum tries:
|
||||||
auth auth.domain.com:1645 "I can't see you" 5 4
|
auth auth.domain.com:1645 "I can't see you" 5 4
|
||||||
|
|
||||||
|
# As above but set dead time and bind address
|
||||||
|
auth auth.domain.com:1645 "I can't see you" 5 4 60 192.168.1.8
|
||||||
|
|
||||||
# A server specified by its IP address:
|
# A server specified by its IP address:
|
||||||
auth 192.168.27.81 $X*#..38947ax-+=
|
auth 192.168.27.81 $X*#..38947ax-+=
|
||||||
.Ed
|
.Ed
|
||||||
|
@ -43,6 +43,8 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <md5.h>
|
#include <md5.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define MAX_FIELDS 7
|
||||||
|
|
||||||
/* We need the MPPE_KEY_LEN define */
|
/* We need the MPPE_KEY_LEN define */
|
||||||
#include <netgraph/ng_mppc.h>
|
#include <netgraph/ng_mppc.h>
|
||||||
|
|
||||||
@ -378,6 +380,18 @@ put_raw_attr(struct rad_handle *h, int type, const void *value, size_t len)
|
|||||||
int
|
int
|
||||||
rad_add_server(struct rad_handle *h, const char *host, int port,
|
rad_add_server(struct rad_handle *h, const char *host, int port,
|
||||||
const char *secret, int timeout, int tries)
|
const char *secret, int timeout, int tries)
|
||||||
|
{
|
||||||
|
struct in_addr bindto;
|
||||||
|
bindto.s_addr = INADDR_ANY;
|
||||||
|
|
||||||
|
return rad_add_server_ex(h, host, port, secret, timeout, tries,
|
||||||
|
DEAD_TIME, &bindto);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rad_add_server_ex(struct rad_handle *h, const char *host, int port,
|
||||||
|
const char *secret, int timeout, int tries, int dead_time,
|
||||||
|
struct in_addr *bindto)
|
||||||
{
|
{
|
||||||
struct rad_server *srvp;
|
struct rad_server *srvp;
|
||||||
|
|
||||||
@ -421,6 +435,10 @@ rad_add_server(struct rad_handle *h, const char *host, int port,
|
|||||||
srvp->timeout = timeout;
|
srvp->timeout = timeout;
|
||||||
srvp->max_tries = tries;
|
srvp->max_tries = tries;
|
||||||
srvp->num_tries = 0;
|
srvp->num_tries = 0;
|
||||||
|
srvp->is_dead = 0;
|
||||||
|
srvp->dead_time = dead_time;
|
||||||
|
srvp->next_probe = 0;
|
||||||
|
srvp->bindto = bindto->s_addr;
|
||||||
h->num_servers++;
|
h->num_servers++;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -441,6 +459,13 @@ rad_close(struct rad_handle *h)
|
|||||||
free(h);
|
free(h);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rad_bind_to(struct rad_handle *h, in_addr_t addr)
|
||||||
|
{
|
||||||
|
|
||||||
|
h->bindto = addr;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
rad_config(struct rad_handle *h, const char *path)
|
rad_config(struct rad_handle *h, const char *path)
|
||||||
{
|
{
|
||||||
@ -468,11 +493,15 @@ rad_config(struct rad_handle *h, const char *path)
|
|||||||
char *secret;
|
char *secret;
|
||||||
char *timeout_str;
|
char *timeout_str;
|
||||||
char *maxtries_str;
|
char *maxtries_str;
|
||||||
|
char *dead_time_str;
|
||||||
|
char *bindto_str;
|
||||||
char *end;
|
char *end;
|
||||||
char *wanttype;
|
char *wanttype;
|
||||||
unsigned long timeout;
|
unsigned long timeout;
|
||||||
unsigned long maxtries;
|
unsigned long maxtries;
|
||||||
|
unsigned long dead_time;
|
||||||
int port;
|
int port;
|
||||||
|
struct in_addr bindto;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
linenum++;
|
linenum++;
|
||||||
@ -491,7 +520,7 @@ rad_config(struct rad_handle *h, const char *path)
|
|||||||
buf[len - 1] = '\0';
|
buf[len - 1] = '\0';
|
||||||
|
|
||||||
/* Extract the fields from the line. */
|
/* Extract the fields from the line. */
|
||||||
nfields = split(buf, fields, 5, msg, sizeof msg);
|
nfields = split(buf, fields, MAX_FIELDS, msg, sizeof msg);
|
||||||
if (nfields == -1) {
|
if (nfields == -1) {
|
||||||
generr(h, "%s:%d: %s", path, linenum, msg);
|
generr(h, "%s:%d: %s", path, linenum, msg);
|
||||||
retval = -1;
|
retval = -1;
|
||||||
@ -507,7 +536,7 @@ rad_config(struct rad_handle *h, const char *path)
|
|||||||
*/
|
*/
|
||||||
if (strcmp(fields[0], "auth") != 0 &&
|
if (strcmp(fields[0], "auth") != 0 &&
|
||||||
strcmp(fields[0], "acct") != 0) {
|
strcmp(fields[0], "acct") != 0) {
|
||||||
if (nfields >= 5) {
|
if (nfields >= MAX_FIELDS) {
|
||||||
generr(h, "%s:%d: invalid service type", path,
|
generr(h, "%s:%d: invalid service type", path,
|
||||||
linenum);
|
linenum);
|
||||||
retval = -1;
|
retval = -1;
|
||||||
@ -529,6 +558,8 @@ rad_config(struct rad_handle *h, const char *path)
|
|||||||
secret = fields[2];
|
secret = fields[2];
|
||||||
timeout_str = fields[3];
|
timeout_str = fields[3];
|
||||||
maxtries_str = fields[4];
|
maxtries_str = fields[4];
|
||||||
|
dead_time_str = fields[5];
|
||||||
|
bindto_str = fields[6];
|
||||||
|
|
||||||
/* Ignore the line if it is for the wrong service type. */
|
/* Ignore the line if it is for the wrong service type. */
|
||||||
wanttype = h->type == RADIUS_AUTH ? "auth" : "acct";
|
wanttype = h->type == RADIUS_AUTH ? "auth" : "acct";
|
||||||
@ -570,8 +601,30 @@ rad_config(struct rad_handle *h, const char *path)
|
|||||||
} else
|
} else
|
||||||
maxtries = MAXTRIES;
|
maxtries = MAXTRIES;
|
||||||
|
|
||||||
if (rad_add_server(h, host, port, secret, timeout, maxtries) ==
|
if (dead_time_str != NULL) {
|
||||||
-1) {
|
dead_time = strtoul(dead_time_str, &end, 10);
|
||||||
|
if (*end != '\0') {
|
||||||
|
generr(h, "%s:%d: invalid dead_time", path,
|
||||||
|
linenum);
|
||||||
|
retval = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
dead_time = DEAD_TIME;
|
||||||
|
|
||||||
|
if (bindto_str != NULL) {
|
||||||
|
bindto.s_addr = inet_addr(bindto_str);
|
||||||
|
if (bindto.s_addr == INADDR_NONE) {
|
||||||
|
generr(h, "%s:%d: invalid bindto", path,
|
||||||
|
linenum);
|
||||||
|
retval = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
bindto.s_addr = INADDR_ANY;
|
||||||
|
|
||||||
|
if (rad_add_server_ex(h, host, port, secret, timeout, maxtries,
|
||||||
|
dead_time, &bindto) == -1) {
|
||||||
strcpy(msg, h->errmsg);
|
strcpy(msg, h->errmsg);
|
||||||
generr(h, "%s:%d: %s", path, linenum, msg);
|
generr(h, "%s:%d: %s", path, linenum, msg);
|
||||||
retval = -1;
|
retval = -1;
|
||||||
@ -596,7 +649,9 @@ int
|
|||||||
rad_continue_send_request(struct rad_handle *h, int selected, int *fd,
|
rad_continue_send_request(struct rad_handle *h, int selected, int *fd,
|
||||||
struct timeval *tv)
|
struct timeval *tv)
|
||||||
{
|
{
|
||||||
int n;
|
int n, cur_srv;
|
||||||
|
time_t now;
|
||||||
|
struct sockaddr_in sin;
|
||||||
|
|
||||||
if (h->type == RADIUS_SERVER) {
|
if (h->type == RADIUS_SERVER) {
|
||||||
generr(h, "denied function call");
|
generr(h, "denied function call");
|
||||||
@ -621,19 +676,61 @@ rad_continue_send_request(struct rad_handle *h, int selected, int *fd,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (h->try == h->total_tries) {
|
|
||||||
generr(h, "No valid RADIUS responses received");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Scan round-robin to the next server that has some
|
* Scan round-robin to the next server that has some
|
||||||
* tries left. There is guaranteed to be one, or we
|
* tries left. There is guaranteed to be one, or we
|
||||||
* would have exited this loop by now.
|
* would have exited this loop by now.
|
||||||
*/
|
*/
|
||||||
while (h->servers[h->srv].num_tries >= h->servers[h->srv].max_tries)
|
cur_srv = h->srv;
|
||||||
if (++h->srv >= h->num_servers)
|
now = time(NULL);
|
||||||
h->srv = 0;
|
if (h->servers[h->srv].num_tries >= h->servers[h->srv].max_tries) {
|
||||||
|
/* Set next probe time for this server */
|
||||||
|
if (h->servers[h->srv].dead_time) {
|
||||||
|
h->servers[h->srv].is_dead = 1;
|
||||||
|
h->servers[h->srv].next_probe = now +
|
||||||
|
h->servers[h->srv].dead_time;
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
h->srv++;
|
||||||
|
if (h->srv >= h->num_servers)
|
||||||
|
h->srv = 0;
|
||||||
|
if (h->servers[h->srv].is_dead == 0)
|
||||||
|
break;
|
||||||
|
if (h->servers[h->srv].dead_time &&
|
||||||
|
h->servers[h->srv].next_probe <= now) {
|
||||||
|
h->servers[h->srv].is_dead = 0;
|
||||||
|
h->servers[h->srv].num_tries = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (h->srv != cur_srv);
|
||||||
|
|
||||||
|
if (h->srv == cur_srv) {
|
||||||
|
generr(h, "No valid RADIUS responses received");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Rebind */
|
||||||
|
if (h->bindto != h->servers[h->srv].bindto) {
|
||||||
|
h->bindto = h->servers[h->srv].bindto;
|
||||||
|
close(h->fd);
|
||||||
|
if ((h->fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
|
||||||
|
generr(h, "Cannot create socket: %s", strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memset(&sin, 0, sizeof sin);
|
||||||
|
sin.sin_len = sizeof sin;
|
||||||
|
sin.sin_family = AF_INET;
|
||||||
|
sin.sin_addr.s_addr = h->bindto;
|
||||||
|
sin.sin_port = 0;
|
||||||
|
if (bind(h->fd, (const struct sockaddr *)&sin,
|
||||||
|
sizeof sin) == -1) {
|
||||||
|
generr(h, "bind: %s", strerror(errno));
|
||||||
|
close(h->fd);
|
||||||
|
h->fd = -1;
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (h->out[POS_CODE] == RAD_ACCESS_REQUEST) {
|
if (h->out[POS_CODE] == RAD_ACCESS_REQUEST) {
|
||||||
/* Insert the scrambled password into the request */
|
/* Insert the scrambled password into the request */
|
||||||
@ -641,9 +738,11 @@ rad_continue_send_request(struct rad_handle *h, int selected, int *fd,
|
|||||||
insert_scrambled_password(h, h->srv);
|
insert_scrambled_password(h, h->srv);
|
||||||
}
|
}
|
||||||
insert_message_authenticator(h, 0);
|
insert_message_authenticator(h, 0);
|
||||||
|
|
||||||
if (h->out[POS_CODE] != RAD_ACCESS_REQUEST) {
|
if (h->out[POS_CODE] != RAD_ACCESS_REQUEST) {
|
||||||
/* Insert the request authenticator into the request */
|
/* Insert the request authenticator into the request */
|
||||||
insert_request_authenticator(h, h->srv);
|
memset(&h->out[POS_AUTH], 0, LEN_AUTH);
|
||||||
|
insert_request_authenticator(h, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send the request */
|
/* Send the request */
|
||||||
@ -654,7 +753,6 @@ rad_continue_send_request(struct rad_handle *h, int selected, int *fd,
|
|||||||
tv->tv_sec = 1; /* Do not wait full timeout if send failed. */
|
tv->tv_sec = 1; /* Do not wait full timeout if send failed. */
|
||||||
else
|
else
|
||||||
tv->tv_sec = h->servers[h->srv].timeout;
|
tv->tv_sec = h->servers[h->srv].timeout;
|
||||||
h->try++;
|
|
||||||
h->servers[h->srv].num_tries++;
|
h->servers[h->srv].num_tries++;
|
||||||
tv->tv_usec = 0;
|
tv->tv_usec = 0;
|
||||||
*fd = h->fd;
|
*fd = h->fd;
|
||||||
@ -740,6 +838,10 @@ rad_create_request(struct rad_handle *h, int code)
|
|||||||
generr(h, "denied function call");
|
generr(h, "denied function call");
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
if (h->num_servers == 0) {
|
||||||
|
generr(h, "No RADIUS servers specified");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
h->out[POS_CODE] = code;
|
h->out[POS_CODE] = code;
|
||||||
h->out[POS_IDENT] = ++h->ident;
|
h->out[POS_IDENT] = ++h->ident;
|
||||||
if (code == RAD_ACCESS_REQUEST) {
|
if (code == RAD_ACCESS_REQUEST) {
|
||||||
@ -756,16 +858,9 @@ rad_create_request(struct rad_handle *h, int code)
|
|||||||
clear_password(h);
|
clear_password(h);
|
||||||
h->authentic_pos = 0;
|
h->authentic_pos = 0;
|
||||||
h->out_created = 1;
|
h->out_created = 1;
|
||||||
h->bindto = INADDR_ANY;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
rad_bind_to(struct rad_handle *h, in_addr_t addr)
|
|
||||||
{
|
|
||||||
h->bindto = addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
rad_create_response(struct rad_handle *h, int code)
|
rad_create_response(struct rad_handle *h, int code)
|
||||||
{
|
{
|
||||||
@ -793,6 +888,15 @@ rad_cvt_addr(const void *data)
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct in6_addr
|
||||||
|
rad_cvt_addr6(const void *data)
|
||||||
|
{
|
||||||
|
struct in6_addr value;
|
||||||
|
|
||||||
|
memcpy(&value.s6_addr, data, sizeof value.s6_addr);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
u_int32_t
|
u_int32_t
|
||||||
rad_cvt_int(const void *data)
|
rad_cvt_int(const void *data)
|
||||||
{
|
{
|
||||||
@ -848,6 +952,8 @@ int
|
|||||||
rad_init_send_request(struct rad_handle *h, int *fd, struct timeval *tv)
|
rad_init_send_request(struct rad_handle *h, int *fd, struct timeval *tv)
|
||||||
{
|
{
|
||||||
int srv;
|
int srv;
|
||||||
|
time_t now;
|
||||||
|
struct sockaddr_in sin;
|
||||||
|
|
||||||
if (h->type == RADIUS_SERVER) {
|
if (h->type == RADIUS_SERVER) {
|
||||||
generr(h, "denied function call");
|
generr(h, "denied function call");
|
||||||
@ -855,8 +961,6 @@ rad_init_send_request(struct rad_handle *h, int *fd, struct timeval *tv)
|
|||||||
}
|
}
|
||||||
/* Make sure we have a socket to use */
|
/* Make sure we have a socket to use */
|
||||||
if (h->fd == -1) {
|
if (h->fd == -1) {
|
||||||
struct sockaddr_in sin;
|
|
||||||
|
|
||||||
if ((h->fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
|
if ((h->fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
|
||||||
generr(h, "Cannot create socket: %s", strerror(errno));
|
generr(h, "Cannot create socket: %s", strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
@ -902,21 +1006,30 @@ rad_init_send_request(struct rad_handle *h, int *fd, struct timeval *tv)
|
|||||||
h->out[POS_LENGTH] = h->out_len >> 8;
|
h->out[POS_LENGTH] = h->out_len >> 8;
|
||||||
h->out[POS_LENGTH+1] = h->out_len;
|
h->out[POS_LENGTH+1] = h->out_len;
|
||||||
|
|
||||||
/*
|
h->srv = 0;
|
||||||
* Count the total number of tries we will make, and zero the
|
now = time(NULL);
|
||||||
* counter for each server.
|
for (srv = 0; srv < h->num_servers; srv++)
|
||||||
*/
|
|
||||||
h->total_tries = 0;
|
|
||||||
for (srv = 0; srv < h->num_servers; srv++) {
|
|
||||||
h->total_tries += h->servers[srv].max_tries;
|
|
||||||
h->servers[srv].num_tries = 0;
|
h->servers[srv].num_tries = 0;
|
||||||
}
|
/* Find a first good server. */
|
||||||
if (h->total_tries == 0) {
|
for (srv = 0; srv < h->num_servers; srv++) {
|
||||||
generr(h, "No RADIUS servers specified");
|
if (h->servers[srv].is_dead == 0)
|
||||||
return -1;
|
break;
|
||||||
|
if (h->servers[srv].dead_time &&
|
||||||
|
h->servers[srv].next_probe <= now) {
|
||||||
|
h->servers[srv].is_dead = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
h->srv++;
|
||||||
}
|
}
|
||||||
|
|
||||||
h->try = h->srv = 0;
|
/* If all servers was dead on the last probe, try from beginning */
|
||||||
|
if (h->srv == h->num_servers) {
|
||||||
|
for (srv = 0; srv < h->num_servers; srv++) {
|
||||||
|
h->servers[srv].is_dead = 0;
|
||||||
|
h->servers[srv].next_probe = 0;
|
||||||
|
}
|
||||||
|
h->srv = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return rad_continue_send_request(h, 0, fd, tv);
|
return rad_continue_send_request(h, 0, fd, tv);
|
||||||
}
|
}
|
||||||
@ -946,6 +1059,7 @@ rad_auth_open(void)
|
|||||||
h->type = RADIUS_AUTH;
|
h->type = RADIUS_AUTH;
|
||||||
h->out_created = 0;
|
h->out_created = 0;
|
||||||
h->eap_msg = 0;
|
h->eap_msg = 0;
|
||||||
|
h->bindto = INADDR_ANY;
|
||||||
}
|
}
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
@ -986,6 +1100,13 @@ rad_put_addr(struct rad_handle *h, int type, struct in_addr addr)
|
|||||||
return rad_put_attr(h, type, &addr.s_addr, sizeof addr.s_addr);
|
return rad_put_attr(h, type, &addr.s_addr, sizeof addr.s_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rad_put_addr6(struct rad_handle *h, int type, struct in6_addr addr)
|
||||||
|
{
|
||||||
|
|
||||||
|
return rad_put_attr(h, type, &addr.s6_addr, sizeof addr.s6_addr);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
rad_put_attr(struct rad_handle *h, int type, const void *value, size_t len)
|
rad_put_attr(struct rad_handle *h, int type, const void *value, size_t len)
|
||||||
{
|
{
|
||||||
@ -1228,6 +1349,15 @@ rad_put_vendor_addr(struct rad_handle *h, int vendor, int type,
|
|||||||
sizeof addr.s_addr));
|
sizeof addr.s_addr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rad_put_vendor_addr6(struct rad_handle *h, int vendor, int type,
|
||||||
|
struct in6_addr addr)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (rad_put_vendor_attr(h, vendor, type, &addr.s6_addr,
|
||||||
|
sizeof addr.s6_addr));
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
rad_put_vendor_attr(struct rad_handle *h, int vendor, int type,
|
rad_put_vendor_attr(struct rad_handle *h, int vendor, int type,
|
||||||
const void *value, size_t len)
|
const void *value, size_t len)
|
||||||
|
@ -194,6 +194,9 @@ __BEGIN_DECLS
|
|||||||
struct rad_handle *rad_acct_open(void);
|
struct rad_handle *rad_acct_open(void);
|
||||||
int rad_add_server(struct rad_handle *,
|
int rad_add_server(struct rad_handle *,
|
||||||
const char *, int, const char *, int, int);
|
const char *, int, const char *, int, int);
|
||||||
|
int rad_add_server_ex(struct rad_handle *,
|
||||||
|
const char *, int, const char *, int, int,
|
||||||
|
int, struct in_addr *);
|
||||||
struct rad_handle *rad_auth_open(void);
|
struct rad_handle *rad_auth_open(void);
|
||||||
void rad_bind_to(struct rad_handle *, in_addr_t);
|
void rad_bind_to(struct rad_handle *, in_addr_t);
|
||||||
void rad_close(struct rad_handle *);
|
void rad_close(struct rad_handle *);
|
||||||
@ -203,6 +206,7 @@ int rad_continue_send_request(struct rad_handle *, int,
|
|||||||
int rad_create_request(struct rad_handle *, int);
|
int rad_create_request(struct rad_handle *, int);
|
||||||
int rad_create_response(struct rad_handle *, int);
|
int rad_create_response(struct rad_handle *, int);
|
||||||
struct in_addr rad_cvt_addr(const void *);
|
struct in_addr rad_cvt_addr(const void *);
|
||||||
|
struct in6_addr rad_cvt_addr6(const void *);
|
||||||
u_int32_t rad_cvt_int(const void *);
|
u_int32_t rad_cvt_int(const void *);
|
||||||
char *rad_cvt_string(const void *, size_t);
|
char *rad_cvt_string(const void *, size_t);
|
||||||
int rad_get_attr(struct rad_handle *, const void **,
|
int rad_get_attr(struct rad_handle *, const void **,
|
||||||
@ -211,6 +215,7 @@ int rad_init_send_request(struct rad_handle *, int *,
|
|||||||
struct timeval *);
|
struct timeval *);
|
||||||
struct rad_handle *rad_open(void); /* Deprecated, == rad_auth_open */
|
struct rad_handle *rad_open(void); /* Deprecated, == rad_auth_open */
|
||||||
int rad_put_addr(struct rad_handle *, int, struct in_addr);
|
int rad_put_addr(struct rad_handle *, int, struct in_addr);
|
||||||
|
int rad_put_addr6(struct rad_handle *, int, struct in6_addr);
|
||||||
int rad_put_attr(struct rad_handle *, int,
|
int rad_put_attr(struct rad_handle *, int,
|
||||||
const void *, size_t);
|
const void *, size_t);
|
||||||
int rad_put_int(struct rad_handle *, int, u_int32_t);
|
int rad_put_int(struct rad_handle *, int, u_int32_t);
|
||||||
|
@ -46,6 +46,7 @@
|
|||||||
#define RADIUS_PORT 1812
|
#define RADIUS_PORT 1812
|
||||||
#define RADACCT_PORT 1813
|
#define RADACCT_PORT 1813
|
||||||
#define TIMEOUT 3 /* In seconds */
|
#define TIMEOUT 3 /* In seconds */
|
||||||
|
#define DEAD_TIME 0
|
||||||
|
|
||||||
/* Limits */
|
/* Limits */
|
||||||
#define ERRSIZE 128 /* Maximum error message length */
|
#define ERRSIZE 128 /* Maximum error message length */
|
||||||
@ -68,6 +69,10 @@ struct rad_server {
|
|||||||
int timeout; /* Timeout in seconds */
|
int timeout; /* Timeout in seconds */
|
||||||
int max_tries; /* Number of tries before giving up */
|
int max_tries; /* Number of tries before giving up */
|
||||||
int num_tries; /* Number of tries so far */
|
int num_tries; /* Number of tries so far */
|
||||||
|
int is_dead; /* The server did not answer last time */
|
||||||
|
time_t dead_time; /* Don't try this server for the time period if it is dead */
|
||||||
|
time_t next_probe; /* Time of a next probe after failure */
|
||||||
|
in_addr_t bindto; /* Bind to address */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rad_handle {
|
struct rad_handle {
|
||||||
@ -88,11 +93,9 @@ struct rad_handle {
|
|||||||
unsigned char in[MSGSIZE]; /* Response received */
|
unsigned char in[MSGSIZE]; /* Response received */
|
||||||
int in_len; /* Length of response */
|
int in_len; /* Length of response */
|
||||||
int in_pos; /* Current position scanning attrs */
|
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 */
|
int srv; /* Server number we did last */
|
||||||
int type; /* Handle type */
|
int type; /* Handle type */
|
||||||
in_addr_t bindto; /* Bind to address */
|
in_addr_t bindto; /* Current bind address */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct vendor_attribute {
|
struct vendor_attribute {
|
||||||
|
@ -73,6 +73,7 @@ struct rad_handle;
|
|||||||
__BEGIN_DECLS
|
__BEGIN_DECLS
|
||||||
int rad_get_vendor_attr(u_int32_t *, const void **, size_t *);
|
int rad_get_vendor_attr(u_int32_t *, const void **, size_t *);
|
||||||
int rad_put_vendor_addr(struct rad_handle *, int, int, struct in_addr);
|
int rad_put_vendor_addr(struct rad_handle *, int, int, struct in_addr);
|
||||||
|
int rad_put_vendor_addr6(struct rad_handle *, int, int, struct in6_addr);
|
||||||
int rad_put_vendor_attr(struct rad_handle *, int, int, const void *,
|
int rad_put_vendor_attr(struct rad_handle *, int, int, const void *,
|
||||||
size_t);
|
size_t);
|
||||||
int rad_put_vendor_int(struct rad_handle *, int, int, u_int32_t);
|
int rad_put_vendor_int(struct rad_handle *, int, int, u_int32_t);
|
||||||
|
Loading…
Reference in New Issue
Block a user