22#include <radcli/radcli.h>
30#if defined(HAVE_GNUTLS)
31# include <gnutls/gnutls.h>
32# include <gnutls/crypto.h>
42#define SCLOSE(fd) do { if (sfuncs->close_fd) sfuncs->close_fd(fd); (fd) = -1; } while (0)
73int rc_pack_list(rc_handle *rh, VALUE_PAIR * vp,
char *secret, AUTH_HDR * auth,
int max_len)
75 int length, i, pc, padded_length;
77 uint32_t lvalue, vendor;
78 unsigned char passbuf[RC_MAX(AUTH_PASS_LEN, CHAP_VALUE_LENGTH)];
79 unsigned char md5buf[MAX_SECRET_LENGTH + AUTH_VECTOR_LEN];
80 unsigned char *vector;
82 uint8_t *attr_start, *attr_len_ptr, *vsa_len_ptr;
86 pb.head = (uint8_t *)auth;
87 pb.data = (uint8_t *)auth;
89 pb.end = (uint8_t *)auth + max_len;
93 unsigned max_vlen = AUTH_STRING_LEN;
106 struct radcli_dict_attr *def = radcli_dict_attr_by_id(rh, vp->
attribute);
107 struct radcli_dict_flags *fl = def != NULL ? radcli_dict_flags_by_id(rh, def->value) : NULL;
109 if (fl != NULL && fl->encrypt_type != 0) {
110 rc_log(LOG_ERR,
"rc_pack_list: %s requires encryption this "
111 "function does not implement; refusing to send it "
112 "unencrypted", def->name);
118 max_vlen = AUTH_STRING_LEN - VSA_HDR_LEN;
119 if (pb_put_byte(&pb, PW_VENDOR_SPECIFIC) < 0)
goto too_large;
120 vsa_len_ptr = pb.tail;
121 if (pb_put_byte(&pb, 6) < 0)
goto too_large;
123 if (pb_put_bytes(&pb, &vendor,
sizeof(uint32_t)) < 0)
goto too_large;
126 attr_start = pb.tail;
127 if (pb_put_byte(&pb, vp->
attribute & 0xff) < 0)
goto too_large;
128 attr_len_ptr = pb.tail;
129 if (pb_put_byte(&pb, 2) < 0)
goto too_large;
132 case PW_USER_PASSWORD:
134 if (length > AUTH_PASS_LEN)
135 length = AUTH_PASS_LEN;
137 (length + (AUTH_VECTOR_LEN - 1)) & ~(AUTH_VECTOR_LEN - 1);
139 if (pb.tail + padded_length > pb.end)
goto too_large;
142 memset((
char *)passbuf,
'\0', AUTH_PASS_LEN);
143 memcpy((
char *)passbuf, vp->
strvalue, (
size_t) length);
145 secretlen = rc_secret_len(secret);
146 vector = (
unsigned char *)auth->vector;
147 for (i = 0; i < padded_length; i += AUTH_VECTOR_LEN) {
149 memcpy(md5buf, secret, secretlen);
150 memcpy(md5buf + secretlen, vector, AUTH_VECTOR_LEN);
151 rc_md5_calc(pb.tail, md5buf, secretlen + AUTH_VECTOR_LEN);
157 for (pc = i; pc < (i + AUTH_VECTOR_LEN); pc++)
158 *pb.tail++ ^= passbuf[pc];
166 if (vp->
lvalue > max_vlen)
goto too_large;
172 if (pb_put_bytes(&pb, vp->
strvalue, 16) < 0)
179 lvalue = htonl(vp->
lvalue);
180 if (pb_put_bytes(&pb, &lvalue,
sizeof(uint32_t)) < 0)
191 *attr_len_ptr = (uint8_t)(pb.tail - attr_start);
192 if (vsa_len_ptr != NULL)
193 *vsa_len_ptr += *attr_len_ptr;
197 return (
int)pb_written(&pb);
200 rc_log(LOG_ERR,
"rc_pack_list: attribute value too large or packet would exceed %d bytes", max_len);
211static void strappend(
char *dest,
unsigned max_size,
int *pos,
const char *src)
213 unsigned len = strlen(src) + 1;
218 if (len + *pos > max_size) {
223 memcpy(&dest[*pos], src, len);
240 return rc_send_server_ctx(rh, NULL, data, msg, type, 0);
267int rc_send_server_ctx(rc_handle * rh,
RC_AAA_CTX ** ctx, SEND_DATA * data,
268 char *msg,
rc_type type,
int no_wait)
271 char *server_name, *p;
272 struct sockaddr_storage our_sockaddr;
273 struct addrinfo *auth_addr = NULL;
277 const rc_sockets_override *sfuncs;
278 unsigned discover_local_ip;
280 char secret[MAX_SECRET_LENGTH + 1];
281 unsigned char vector[AUTH_VECTOR_LEN];
282 uint8_t recv_buffer[RC_BUFFER_LEN];
283 uint8_t send_buffer[RC_BUFFER_LEN];
287 struct sockaddr_storage *ss_set = NULL;
289 radcli_avp_list *avp_list;
292 server_name = data->
server;
293 if (server_name == NULL || server_name[0] ==
'\0')
297 (vp->
lvalue == PW_ADMINISTRATIVE)) {
299 strlcpy(secret, MGMT_POLL_SECRET,
sizeof(secret));
301 rc_getaddrinfo(server_name,
302 type ==
AUTH ? PW_AI_AUTH : PW_AI_ACCT);
303 if (auth_addr == NULL)
306 if (data->
secret != NULL) {
307 strlcpy(secret, data->
secret,
sizeof(secret));
309 if (radcli2_priv_find_server_addr
310 (rh, server_name, &auth_addr, secret, type) != 0) {
312 "rc_send_server: unable to find server: %s",
320 if (sfuncs->static_secret) {
322 strlcpy(secret, sfuncs->static_secret,
sizeof(secret));
330 rc_own_bind_addr(rh, &our_sockaddr);
331 discover_local_ip = 0;
332 if (our_sockaddr.ss_family == AF_INET) {
333 if (((
struct sockaddr_in *)(&our_sockaddr))->sin_addr.s_addr ==
335 discover_local_ip = 1;
339 if (discover_local_ip) {
340 result = rc_get_srcaddr(SA(&our_sockaddr), auth_addr->ai_addr);
341 if (result != OK_RC) {
342 memset(secret,
'\0',
sizeof(secret));
344 "rc_send_server: cannot figure our own address");
345 freeaddrinfo(auth_addr);
350 freeaddrinfo(auth_addr);
356 if (rh->nas_addr_set) {
360 ss_set = &rh->nas_addr;
364 ss_set = &our_sockaddr;
368 if (ss_set->ss_family == AF_INET) {
371 *) (&((
struct sockaddr_in *)ss_set)->
376 PW_NAS_IP_ADDRESS, &ip, 0, 0);
379 p2 = &((
struct sockaddr_in6 *)ss_set)->sin6_addr;
382 PW_NAS_IPV6_ADDRESS, p2, 16, 0);
389 p = rc_conf_str(rh,
"nas-identifier");
393 PW_NAS_IDENTIFIER, p, -1, 0);
406 if (radcli_value_pairs_to_avp_list(rh, data->
send_pairs, &avp_list) != 0) {
407 memset(secret,
'\0',
sizeof(secret));
411 auth = (AUTH_HDR *) send_buffer;
412 auth->code = data->
code;
415 if (data->
code == PW_ACCOUNTING_REQUEST) {
416 encoded_len = radcli_avp_encode(rh, avp_list, secret, auth->vector,
417 auth->data, RC_MAX_PACKET_LEN - AUTH_HDR_LEN, NULL);
418 radcli_avp_list_free(avp_list);
419 if (encoded_len < 0) {
420 memset(secret,
'\0',
sizeof(secret));
423 total_length = AUTH_HDR_LEN + encoded_len;
425 tlen = htons((
unsigned short)total_length);
426 memcpy(&auth->length, &tlen,
sizeof(uint16_t));
428 memset((
char *)auth->vector, 0, AUTH_VECTOR_LEN);
429 secretlen = rc_secret_len(secret);
430 memcpy((
char *)auth + total_length, secret, secretlen);
431 rc_md5_calc(vector, (
unsigned char *)auth,
432 total_length + secretlen);
433 memcpy((
char *)auth->vector, (
char *)vector, AUTH_VECTOR_LEN);
435 rc_get_random_bytes(vector, AUTH_VECTOR_LEN);
436 memcpy((
char *)auth->vector, (
char *)vector, AUTH_VECTOR_LEN);
439 encoded_len = radcli_avp_encode(rh, avp_list, secret, vector, auth->data,
440 RC_MAX_PACKET_LEN - AUTH_HDR_LEN - (2 + MD5_DIGEST_SIZE), NULL);
441 radcli_avp_list_free(avp_list);
442 if (encoded_len < 0) {
443 memset(secret,
'\0',
sizeof(secret));
446 total_length = AUTH_HDR_LEN + encoded_len;
448 total_length = add_msg_auth_attr(rh, secret, auth, total_length);
450 auth->length = htons((
unsigned short)total_length);
453 result = radcli_transport_exchange(rh, ctx, server_name,
456 data->
timeout, data->retries, no_wait, type,
457 send_buffer, total_length,
458 recv_buffer,
sizeof(recv_buffer), &recv_len, NULL);
465 memset(secret,
'\0',
sizeof(secret));
468 (result != OK_RC && result != CHALLENGE_RC &&
469 result != REJECT_RC && result != BADRESP_RC)) {
473 length = (int)recv_len;
487 strappend(msg, PW_MAX_MSG_SIZE, &pos,
489 strappend(msg, PW_MAX_MSG_SIZE, &pos,
"\n");
void rc_avpair_remove(VALUE_PAIR **list, uint32_t attrid, uint32_t vendorspec)
Removes an attribute-value pair from the given list.
struct rc_aaa_ctx_st RC_AAA_CTX
VALUE_PAIR * rc_avpair_gen(rc_handle const *rh, VALUE_PAIR *pair, unsigned char const *ptr, int length, uint32_t vendorspec)
Decode a raw RADIUS attribute buffer into a VALUE_PAIR list.
int rc_send_server(rc_handle *rh, SEND_DATA *data, char *msg, rc_type type)
Sends a request to a RADIUS server and waits for the reply.
VALUE_PAIR * rc_avpair_add(rc_handle const *rh, VALUE_PAIR **list, uint32_t attrid, void const *pval, int len, uint32_t vendorspec)
Adds an attribute-value pair to the given list.
VALUE_PAIR * rc_avpair_get(VALUE_PAIR *vp, uint32_t attrid, uint32_t vendorspec)
Find the first attribute value-pair (which matches the given attribute) from the specified value-pair...
@ AUTH
Request for authentication server.
@ PW_TYPE_IPADDR
The attribute is an IPv4 address in host-byte order.
@ PW_TYPE_IPV6ADDR
The attribute is an 128-bit IPv6 address.
@ PW_TYPE_IPV6PREFIX
The attribute is an IPv6 prefix; the lvalue will indicate its size.
@ PW_TYPE_INTEGER
The attribute is a 32-bit integer.
@ PW_TYPE_DATE
The attribute contains a 32-bit number indicating the seconds since epoch.
@ PW_TYPE_STRING
The attribute is a printable string.
rc_attr_type type
attribute type.
uint64_t attribute
attribute numeric value of type rc_attr_id including vendor; use VENDOR() and ATTRID() to separate.
uint32_t lvalue
attribute value if type is PW_TYPE_INTEGER, PW_TYPE_DATE or PW_TYPE_IPADDR.
char strvalue[AUTH_STRING_LEN+1]
contains attribute value in other cases.
int timeout
Session timeout in seconds.
char * secret
Shared secret of RADIUS server.
uint8_t seq_nbr
Packet sequence number.
int svc_port
RADIUS protocol destination port.
char * server
Name/address of RADIUS server.
VALUE_PAIR * send_pairs
More a/v pairs to send.
VALUE_PAIR * receive_pairs
Where to place received a/v pairs.
uint8_t code
RADIUS packet code.