17#include <radcli/radcli.h>
21#define PARSE_MODE_NAME 0
22#define PARSE_MODE_EQUAL 1
23#define PARSE_MODE_VALUE 2
24#define PARSE_MODE_INVALID 3
47VALUE_PAIR *
rc_avpair_add (rc_handle
const *rh, VALUE_PAIR **list, uint32_t attrid,
void const *pval,
int len, uint32_t vendorspec)
72 VALUE_PAIR *vp, *prev, *tmp;
75 if(vendorspec != VENDOR_NONE)
76 vattrid = RADCLI_VENDOR_ATTR_SET(attrid, vendorspec);
91 prev->next = vp->next;
143 len = (uint32_t)strlen((
char const *)pval);
147 if (len > (
int)(VENDOR(vp->
attribute) ? (AUTH_STRING_LEN - VSA_HDR_LEN) : (AUTH_STRING_LEN))) {
148 rc_log(LOG_ERR,
"rc_avpair_assign: bad attribute length");
151 memcpy(vp->
strvalue, (
char const *)pval, len);
159 vp->
lvalue = * (uint32_t *) pval;
163 rc_log(LOG_ERR,
"rc_avpair_assign: bad IPv6 length");
166 memcpy(vp->
strvalue, (
char const *)pval, len);
171 if (len < 2 || len > 18) {
172 rc_log(LOG_ERR,
"rc_avpair_assign: bad IPv6 prefix length");
175 memcpy(vp->
strvalue, (
char const *)pval, len);
180 rc_log(LOG_ERR,
"rc_avpair_assign: no attribute %d in dictionary", vp->
type);
197VALUE_PAIR *
rc_avpair_new (rc_handle
const *rh, uint32_t attrid,
void const *pval,
int len, uint32_t vendorspec)
199 VALUE_PAIR *vp = NULL;
200 struct radcli_dict_attr *pda;
203 if(vendorspec != VENDOR_NONE) {
204 vattrid = RADCLI_VENDOR_ATTR_SET(attrid, vendorspec);
209 if ((pda = radcli_dict_attr_by_id (rh, vattrid)) == NULL)
211 rc_log(LOG_ERR,
"rc_avpair_new: no attribute %d/%u in dictionary", vendorspec, attrid);
214 if (vendorspec != 0 && radcli_dict_vendor_by_pec(rh, vendorspec) == NULL)
216 rc_log(LOG_ERR,
"rc_avpair_new: no Vendor-Id %d in dictionary", vendorspec);
219 if ((vp = malloc (
sizeof (VALUE_PAIR))) != NULL)
221 strlcpy (vp->
name, pda->name, sizeof (vp->
name));
224 vp->
type = radcli_dict_type_to_legacy(pda->type);
234 rc_log(LOG_CRIT,
"rc_avpair_new: out of memory");
252static int rc_avpair_gen2(rc_handle
const *rh, VALUE_PAIR *pair,
253 pkt_buf *pb, uint32_t vendorspec,
256 VALUE_PAIR *head = pair;
257 VALUE_PAIR **tail = &head;
258 const uint8_t *attr_data, *ptr;
262 struct radcli_dict_attr *attr;
264 char buffer[(AUTH_STRING_LEN * 2) + 1];
267 while (*tail != NULL)
268 tail = &(*tail)->next;
270 while (pb_len(pb) > 0) {
271 if (pb_len(pb) < 2) {
272 rc_log(LOG_ERR,
"rc_avpair_gen: received attribute with "
276 attrlen = pb->data[1];
277 if (attrlen < 2 || (
size_t)attrlen > pb_len(pb)) {
278 rc_log(LOG_ERR,
"rc_avpair_gen: received attribute with "
283 attr_data = pb->data;
284 assert(pb_pull(pb, attrlen) == 0);
286 attribute = RADCLI_VENDOR_ATTR_SET(attr_data[0], vendorspec);
291 if (attribute == PW_VENDOR_SPECIFIC) {
293 rc_log(LOG_ERR,
"rc_avpair_gen: received VSA "
294 "attribute with invalid length");
297 memcpy(&lvalue, ptr, 4);
298 lvalue = ntohl(lvalue);
299 if (radcli_dict_vendor_by_pec(rh, lvalue) == NULL) {
300 rc_log(LOG_WARNING,
"rc_avpair_gen: received VSA "
301 "attribute with unknown Vendor-Id %d", lvalue);
307 VALUE_PAIR *vsa_list = NULL;
308 pb_init_read(&vsa_pb,
309 (
void *)(uintptr_t)(ptr + 4),
310 attrlen - 4, attrlen - 4);
311 if (rc_avpair_gen2(rh, NULL, &vsa_pb, lvalue,
315 if (vsa_list != NULL) {
317 while (*tail != NULL)
318 tail = &(*tail)->next;
325 attr = radcli_dict_attr_by_id(rh, attribute);
327 rc_bin2hex(buffer,
sizeof(buffer), ptr, (
size_t)attrlen);
328 if (vendorspec == 0) {
329 rc_log(LOG_WARNING,
"rc_avpair_gen: received "
330 "unknown attribute %d of length %d: 0x%s",
331 (
unsigned)attribute, attrlen + 2, buffer);
333 rc_log(LOG_WARNING,
"rc_avpair_gen: received "
334 "unknown VSA attribute %u, vendor %u of "
335 "length %d: 0x%s", (
unsigned)ATTRID(attribute),
336 (
unsigned)VENDOR(attribute), attrlen + 2, buffer);
341 rpair = calloc(1,
sizeof(*rpair));
343 rc_log(LOG_CRIT,
"rc_avpair_gen: out of memory");
347 strlcpy(rpair->
name, attr->name,
sizeof(rpair->
name));
349 rpair->
type = radcli_dict_type_to_legacy(attr->type);
351 switch (rpair->
type) {
353 if (attrlen > AUTH_STRING_LEN) {
354 rc_log(LOG_ERR,
"rc_avpair_gen: string attribute too long: %d", attrlen);
358 memcpy(rpair->
strvalue, (
char *)ptr, (
size_t)attrlen);
365 rc_log(LOG_ERR,
"rc_avpair_gen: received "
366 "INTEGER/IPADDR attribute with invalid length");
370 memcpy((
char *)&lvalue, (
char *)ptr, 4);
371 rpair->
lvalue = ntohl(lvalue);
375 rc_log(LOG_ERR,
"rc_avpair_gen: received IPV6ADDR"
376 " attribute with invalid length");
380 memcpy(rpair->
strvalue, (
char *)ptr, 16);
384 if (attrlen > 18 || attrlen < 2) {
385 rc_log(LOG_ERR,
"rc_avpair_gen: received IPV6PREFIX"
386 " attribute with invalid length: %d", attrlen);
390 memcpy(rpair->
strvalue, (
char *)ptr, attrlen);
395 rc_log(LOG_ERR,
"rc_avpair_gen: received DATE "
396 "attribute with invalid length");
400 memcpy((
char *)&lvalue, (
char *)ptr, 4);
401 rpair->
lvalue = ntohl(lvalue);
404 rc_log(LOG_WARNING,
"rc_avpair_gen: %s has unknown type",
445 unsigned char const *ptr,
int length,
449 VALUE_PAIR *out = NULL;
452 pb_init_read(&pb, (
void *)ptr, (
size_t)length, (
size_t)length);
453 if (rc_avpair_gen2(rh, pair, &pb, vendorspec, &out) < 0)
465VALUE_PAIR *
rc_avpair_get (VALUE_PAIR *vp, uint32_t attrid, uint32_t vendorspec)
467 uint64_t attr = RADCLI_VENDOR_ATTR_SET(attrid, vendorspec);
469 for (; vp != NULL && !(attr == vp->
attribute); vp = vp->next)
484 VALUE_PAIR *vp, *fp = NULL, *lp = NULL;
487 vp = malloc(
sizeof(VALUE_PAIR));
519 VALUE_PAIR *this_node = NULL;
524 rc_log(LOG_CRIT,
"rc_avpair_insert: value pair (0x%p) next ptr. (0x%p) not NULL", b, b->next);
547 while (this_node != NULL)
553 this_node = this_node->next;
558 b->next = this_node->next;
589static void rc_fieldcpy(
char *
string,
char const **uptr,
char const *stopat,
size_t len)
591 char const *ptr, *estring;
594 estring =
string + len - 1;
598 while (*ptr !=
'"' && *ptr !=
'\0' && *ptr !=
'\n')
600 if (
string < estring)
613 while (*ptr !=
'\0' && strchr(stopat, *ptr) == NULL)
615 if (
string < estring)
634 char attrstr[AUTH_ID_LEN];
635 char valstr[AUTH_STRING_LEN + 1], *p;
636 struct radcli_dict_attr *attr = NULL;
637 struct radcli_dict_value *dval;
643 mode = PARSE_MODE_NAME;
644 while (*buffer !=
'\n' && *buffer !=
'\0')
646 if (*buffer ==
' ' || *buffer ==
'\t')
654 case PARSE_MODE_NAME:
655 rc_fieldcpy (attrstr, &buffer,
" \t\n=,",
sizeof(attrstr));
657 radcli_dict_attr_by_name (rh, attrstr)) == NULL)
659 rc_log(LOG_ERR,
"rc_avpair_parse: unknown attribute");
666 mode = PARSE_MODE_EQUAL;
669 case PARSE_MODE_EQUAL:
672 mode = PARSE_MODE_VALUE;
677 rc_log(LOG_ERR,
"rc_avpair_parse: missing or misplaced equal sign");
686 case PARSE_MODE_VALUE:
687 rc_fieldcpy (valstr, &buffer,
" \t\n,",
sizeof(valstr));
689 if ((pair = malloc (
sizeof (VALUE_PAIR))) == NULL)
691 rc_log(LOG_CRIT,
"rc_avpair_parse: out of memory");
698 strlcpy (pair->
name, attr->name,
sizeof(pair->
name));
700 pair->
type = radcli_dict_type_to_legacy(attr->type);
707 rc_log(LOG_ERR,
"rc_avpair_parse: string value too long");
714 if (isdigit (*valstr))
716 pair->
lvalue = atoi (valstr);
720 if ((dval = radcli_dict_value_by_name (rh, valstr))
723 rc_log(LOG_ERR,
"rc_avpair_parse: unknown attribute value: %s", valstr);
733 pair->
lvalue = dval->value;
739 if (inet_pton(AF_INET, valstr, &pair->
lvalue) == 0) {
740 rc_log(LOG_ERR,
"rc_avpair_parse: invalid IPv4 address %s", valstr);
749 if (inet_pton(AF_INET6, valstr, pair->
strvalue) == 0) {
750 rc_log(LOG_ERR,
"rc_avpair_parse: invalid IPv6 address %s", valstr);
758 p = strchr(valstr,
'/');
760 rc_log(LOG_ERR,
"rc_avpair_parse: invalid IPv6 prefix %s", valstr);
769 if (inet_pton(AF_INET6, valstr, pair->
strvalue+2) == 0) {
770 rc_log(LOG_ERR,
"rc_avpair_parse: invalid IPv6 prefix %s", valstr);
779 tm = localtime_r (&timeval, &_tm);
783 if (rc_str2tm (valstr, tm) < 0) {
784 rc_log(LOG_ERR,
"rc_avpair_parse: invalid date %s", valstr);
788 pair->
lvalue = (uint32_t) mktime (tm);
792 rc_log(LOG_ERR,
"rc_avpair_parse: unknown attribute type %d", pair->
type);
803 if (*first_pair == NULL)
810 while (link->next != NULL)
817 mode = PARSE_MODE_NAME;
821 mode = PARSE_MODE_NAME;
838int rc_avpair_tostr (rc_handle
const *rh, VALUE_PAIR *pair,
char *name,
int ln,
char *value,
int lv)
840 struct radcli_dict_value *dval;
846 *name = *value =
'\0';
848 if (!pair || pair->
name[0] ==
'\0') {
849 rc_log(LOG_ERR,
"rc_avpair_tostr: pair is NULL or empty");
853 strlcpy(name, pair->
name, (
size_t) ln);
860 ptr = (
unsigned char *) pair->
strvalue;
864 if (!(isprint (*ptr)))
867 snprintf (&value[pos], lv,
"\\%03o", *ptr);
889 dval = radcli_dict_value_by_attr (rh, pair->
name, pair->
lvalue);
892 strlcpy(value, dval->name, (
size_t) lv);
896 snprintf(value, lv,
"%ld", (
long int)pair->
lvalue);
901 inad.s_addr = htonl(pair->
lvalue);
902 strlcpy (value, inet_ntoa (inad), (
size_t) lv);
906 if (inet_ntop(AF_INET6, pair->
strvalue, value, lv) == NULL)
916 memset(ip, 0,
sizeof(ip));
919 if (inet_ntop(AF_INET6, ip, (
void*)txt,
sizeof(txt)) == NULL)
921 snprintf(value, lv,
"%s/%u", txt, (
unsigned)pair->
strvalue[1]);
927 struct tm *ptm = gmtime_r((time_t *) & pair->
lvalue, &_tm);
931 strftime (value, lv,
"%m/%d/%y %H:%M:%S", ptm);
936 rc_log(LOG_ERR,
"rc_avpair_tostr: unknown attribute type %d", pair->
type);
954char *
rc_avpair_log(rc_handle
const *rh, VALUE_PAIR *pair,
char *buf,
size_t buf_len)
959 char name[RC_NAME_LENGTH + 1], value[256];
962 for (vp = pair; vp != NULL; vp = vp->next) {
964 sizeof(value)) == -1)
968 n = snprintf(buf + len, buf_len - len,
"%-32s = '%s'\n", name, value);
969 if (n < 0 || (
size_t)n >= buf_len - len)
1022 *prefix = (
unsigned char)vp->
strvalue[1];
void rc_avpair_remove(VALUE_PAIR **list, uint32_t attrid, uint32_t vendorspec)
Removes an attribute-value pair from the given list.
int rc_avpair_get_raw(VALUE_PAIR *vp, char **res, unsigned *res_size)
Get the raw value of the given attribute value-pair.
char * rc_avpair_log(rc_handle const *rh, VALUE_PAIR *pair, char *buf, size_t buf_len)
Format a sequence of attribute value pairs into a printable string.
VALUE_PAIR * rc_avpair_next(VALUE_PAIR *t)
Iterates through the attribute-value pairs.
int rc_avpair_get_uint32(VALUE_PAIR *vp, uint32_t *res)
Get the integer value of the given attribute value-pair.
int rc_avpair_get_in6(VALUE_PAIR *vp, struct in6_addr *res, unsigned *prefix)
Get the IPv6 address and prefix value of the given attribute value-pair.
void rc_avpair_get_attr(VALUE_PAIR *vp, unsigned *type, unsigned *id)
Get the attribute ID and type of the given attribute value-pair.
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.
void rc_avpair_free(VALUE_PAIR *pair)
Frees all value_pairs in the list.
VALUE_PAIR * rc_avpair_copy(VALUE_PAIR *p)
Return a copy of the existing list "p" ala strdup().
int rc_avpair_tostr(rc_handle const *rh, VALUE_PAIR *pair, char *name, int ln, char *value, int lv)
Translate an av_pair into printable strings.
int rc_avpair_assign(VALUE_PAIR *vp, void const *pval, int len)
Assigns the given value to an attribute-value pair.
int rc_avpair_parse(rc_handle const *rh, char const *buffer, VALUE_PAIR **first_pair)
Parses the buffer to extract the attribute-value pairs.
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.
void rc_avpair_insert(VALUE_PAIR **a, VALUE_PAIR *p, VALUE_PAIR *b)
Insert a VALUE_PAIR into a 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...
VALUE_PAIR * rc_avpair_new(rc_handle const *rh, uint32_t attrid, void const *pval, int len, uint32_t vendorspec)
Make a new attribute-value pair with given parameters.
@ 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.
char name[RC_NAME_LENGTH+1]
attribute name if known.