Radcli library 1.5.3
A simple radius library
Loading...
Searching...
No Matches
avpair.c
1/*
2 * Copyright (C) 2015 Nikos Mavrogiannopoulos
3 * Copyright (C) 1995 Lars Fenneberg
4 *
5 * Copyright 1992 Livingston Enterprises, Inc.
6 *
7 * Copyright 1992,1993, 1994,1995 The Regents of the University of Michigan
8 * and Merit Network, Inc. All Rights Reserved
9 *
10 * See the file COPYRIGHT for the respective terms and conditions.
11 * If the file is missing contact me at lf@elemental.net
12 * and I'll send you a copy.
13 *
14 */
15#include <config.h>
16#include <includes.h>
17#include <radcli/radcli.h>
18#include "util.h"
19
20#define PARSE_MODE_NAME 0
21#define PARSE_MODE_EQUAL 1
22#define PARSE_MODE_VALUE 2
23#define PARSE_MODE_INVALID 3
24
31
46VALUE_PAIR *rc_avpair_add (rc_handle const *rh, VALUE_PAIR **list, uint32_t attrid, void const *pval, int len, uint32_t vendorspec)
47{
48 VALUE_PAIR *vp;
49
50 vp = rc_avpair_new (rh, attrid, pval, len, vendorspec);
51
52 if (vp != NULL)
53 {
54 rc_avpair_insert (list, NULL, vp);
55 }
56
57 return vp;
58
59}
60
69void rc_avpair_remove (VALUE_PAIR **list, uint32_t attrid, uint32_t vendorspec)
70{
71 VALUE_PAIR *vp, *prev, *tmp;
72 uint64_t vattrid;
73
74 if(vendorspec != VENDOR_NONE)
75 vattrid = RADCLI_VENDOR_ATTR_SET(attrid, vendorspec);
76 else
77 vattrid = attrid;
78
79 prev = NULL;
80 vp = *list;
81 while(vp != NULL) {
82 if (vp->attribute == vattrid) {
83 /* found */
84 if (prev == NULL) { /* first one */
85 tmp = vp;
86 vp = tmp->next;
87 free(tmp);
88 *list = vp;
89 } else { /* somewhere in the middle */
90 prev->next = vp->next;
91 free(vp);
92 }
93 break;
94 }
95
96 prev = vp;
97 vp = vp->next;
98 };
99
100 return;
101}
102
112VALUE_PAIR *rc_avpair_next (VALUE_PAIR *t)
113{
114 return t->next;
115}
116
135int rc_avpair_assign (VALUE_PAIR *vp, void const *pval, int len)
136{
137
138 switch (vp->type)
139 {
140 case PW_TYPE_STRING:
141 if (len == -1)
142 len = (uint32_t)strlen((char const *)pval);
143 /* Vendor-specific attributes use additionally 6 bytes of envelope
144 * (4 vendor-id + 1 sub-type + 1 sub-length) thus reduce the AUTH_STRING_LEN
145 * (253-byte value) to 247. */
146 if (len > (int)(VENDOR(vp->attribute) ? (AUTH_STRING_LEN - VSA_HDR_LEN) : (AUTH_STRING_LEN))) {
147 rc_log(LOG_ERR, "rc_avpair_assign: bad attribute length");
148 return -1;
149 }
150 memcpy(vp->strvalue, (char const *)pval, len);
151 vp->strvalue[len] = '\0';
152 vp->lvalue = len;
153 break;
154
155 case PW_TYPE_DATE:
156 case PW_TYPE_INTEGER:
157 case PW_TYPE_IPADDR:
158 vp->lvalue = * (uint32_t *) pval;
159 break;
160 case PW_TYPE_IPV6ADDR:
161 if (len != 16) {
162 rc_log(LOG_ERR, "rc_avpair_assign: bad IPv6 length");
163 return -1;
164 }
165 memcpy(vp->strvalue, (char const *)pval, len);
166 vp->lvalue = len;
167 break;
168
170 if (len < 2 || len > 18) {
171 rc_log(LOG_ERR, "rc_avpair_assign: bad IPv6 prefix length");
172 return -1;
173 }
174 memcpy(vp->strvalue, (char const *)pval, len);
175 vp->lvalue = len;
176 break;
177
178 default:
179 rc_log(LOG_ERR, "rc_avpair_assign: no attribute %d in dictionary", vp->type);
180 return -1;
181 }
182 return 0;
183}
184
196VALUE_PAIR *rc_avpair_new (rc_handle const *rh, uint32_t attrid, void const *pval, int len, uint32_t vendorspec)
197{
198 VALUE_PAIR *vp = NULL;
199 DICT_ATTR *pda;
200 uint64_t vattrid;
201
202 if(vendorspec != VENDOR_NONE) {
203 vattrid = RADCLI_VENDOR_ATTR_SET(attrid, vendorspec);
204 } else {
205 vattrid = attrid;
206 }
207
208 if ((pda = rc_dict_getattr (rh, vattrid)) == NULL)
209 {
210 rc_log(LOG_ERR,"rc_avpair_new: no attribute %d/%u in dictionary", vendorspec, attrid);
211 return NULL;
212 }
213 if (vendorspec != 0 && rc_dict_getvend(rh, vendorspec) == NULL)
214 {
215 rc_log(LOG_ERR,"rc_avpair_new: no Vendor-Id %d in dictionary", vendorspec);
216 return NULL;
217 }
218 if ((vp = malloc (sizeof (VALUE_PAIR))) != NULL)
219 {
220 strlcpy (vp->name, pda->name, sizeof (vp->name));
221 vp->attribute = vattrid;
222 vp->next = NULL;
223 vp->type = pda->type;
224 if (rc_avpair_assign (vp, pval, len) == 0)
225 {
226 /* XXX: Fix up Digest-Attributes */
227 switch (vp->attribute) {
228 case PW_DIGEST_REALM:
229 case PW_DIGEST_NONCE:
230 case PW_DIGEST_METHOD:
231 case PW_DIGEST_URI:
232 case PW_DIGEST_QOP:
235 case PW_DIGEST_CNONCE:
238 /* overlapping! */
239 if (vp->lvalue > AUTH_STRING_LEN - 2)
240 vp->lvalue = AUTH_STRING_LEN - 2;
241 memmove(&vp->strvalue[2], &vp->strvalue[0], vp->lvalue);
242 vp->strvalue[0] = vp->attribute - PW_DIGEST_REALM + 1;
243 vp->lvalue += 2;
244 vp->strvalue[1] = vp->lvalue;
245 vp->strvalue[vp->lvalue] = '\0';
247 default:
248 break;
249 }
250 return vp;
251 }
252 free (vp);
253 vp = NULL;
254 }
255 else
256 {
257 rc_log(LOG_CRIT,"rc_avpair_new: out of memory");
258 }
259
260 return vp;
261}
262
263/* Returns 0 on success (decoded list in *out, may be NULL if all attrs skipped),
264 * -1 on hard error (*out undefined, incoming pair list already freed). */
266static int rc_avpair_gen2(rc_handle const *rh, VALUE_PAIR *pair,
267 pkt_buf *pb, uint32_t vendorspec,
268 VALUE_PAIR **out)
269{
270 VALUE_PAIR *head = pair;
271 VALUE_PAIR **tail = &head;
272 const uint8_t *attr_data, *ptr;
273 int attrlen;
274 uint64_t attribute;
275 uint32_t lvalue;
276 DICT_ATTR *attr;
277 VALUE_PAIR *rpair;
278 char buffer[(AUTH_STRING_LEN * 2) + 1];
279
280 /* Advance tail to end of the initial list so we append in wire order */
281 while (*tail != NULL)
282 tail = &(*tail)->next;
283
284 while (pb_len(pb) > 0) {
285 if (pb_len(pb) < 2) {
286 rc_log(LOG_ERR, "rc_avpair_gen: received attribute with "
287 "invalid length");
288 goto error;
289 }
290 attrlen = pb->data[1];
291 if (attrlen < 2 || (size_t)attrlen > pb_len(pb)) {
292 rc_log(LOG_ERR, "rc_avpair_gen: received attribute with "
293 "invalid length");
294 goto error;
295 }
296
297 attr_data = pb->data;
298 assert(pb_pull(pb, attrlen) == 0);
299
300 attribute = RADCLI_VENDOR_ATTR_SET(attr_data[0], vendorspec);
301 ptr = attr_data + 2;
302 attrlen -= 2;
303
304 /* VSA */
305 if (attribute == PW_VENDOR_SPECIFIC) {
306 if (attrlen < 4) {
307 rc_log(LOG_ERR, "rc_avpair_gen: received VSA "
308 "attribute with invalid length");
309 continue;
310 }
311 memcpy(&lvalue, ptr, 4);
312 lvalue = ntohl(lvalue);
313 if (rc_dict_getvend(rh, lvalue) == NULL) {
314 rc_log(LOG_WARNING, "rc_avpair_gen: received VSA "
315 "attribute with unknown Vendor-Id %d", lvalue);
316 continue;
317 }
318 /* Process VSA sub-attributes; append results to tail */
319 {
320 pkt_buf vsa_pb;
321 VALUE_PAIR *vsa_list = NULL;
322 pb_init_read(&vsa_pb,
323 (void *)(uintptr_t)(ptr + 4),
324 attrlen - 4, attrlen - 4);
325 if (rc_avpair_gen2(rh, NULL, &vsa_pb, lvalue,
326 &vsa_list) < 0)
327 goto error;
328 /* vsa_list may be NULL if all sub-attrs skipped */
329 if (vsa_list != NULL) {
330 *tail = vsa_list;
331 while (*tail != NULL)
332 tail = &(*tail)->next;
333 }
334 }
335 continue;
336 }
337
338 /* Normal attribute */
339 attr = rc_dict_getattr(rh, attribute);
340 if (attr == NULL) {
341 rc_bin2hex(buffer, sizeof(buffer), ptr, (size_t)attrlen);
342 if (vendorspec == 0) {
343 rc_log(LOG_WARNING, "rc_avpair_gen: received "
344 "unknown attribute %d of length %d: 0x%s",
345 (unsigned)attribute, attrlen + 2, buffer);
346 } else {
347 rc_log(LOG_WARNING, "rc_avpair_gen: received "
348 "unknown VSA attribute %u, vendor %u of "
349 "length %d: 0x%s", (unsigned)ATTRID(attribute),
350 (unsigned)VENDOR(attribute), attrlen + 2, buffer);
351 }
352 continue;
353 }
354
355 rpair = calloc(1, sizeof(*rpair));
356 if (rpair == NULL) {
357 rc_log(LOG_CRIT, "rc_avpair_gen: out of memory");
358 goto error;
359 }
360 rpair->next = NULL;
361 strlcpy(rpair->name, attr->name, sizeof(rpair->name));
362 rpair->attribute = attr->value;
363 rpair->type = attr->type;
364
365 switch (attr->type) {
366 case PW_TYPE_STRING:
367 if (attrlen > AUTH_STRING_LEN) {
368 rc_log(LOG_ERR, "rc_avpair_gen: string attribute too long: %d", attrlen);
369 free(rpair);
370 goto error;
371 }
372 memcpy(rpair->strvalue, (char *)ptr, (size_t)attrlen);
373 rpair->strvalue[attrlen] = '\0';
374 rpair->lvalue = attrlen;
375 break;
376 case PW_TYPE_INTEGER:
377 case PW_TYPE_IPADDR:
378 if (attrlen != 4) {
379 rc_log(LOG_ERR, "rc_avpair_gen: received "
380 "INTEGER/IPADDR attribute with invalid length");
381 free(rpair);
382 continue;
383 }
384 memcpy((char *)&lvalue, (char *)ptr, 4);
385 rpair->lvalue = ntohl(lvalue);
386 break;
387 case PW_TYPE_IPV6ADDR:
388 if (attrlen != 16) {
389 rc_log(LOG_ERR, "rc_avpair_gen: received IPV6ADDR"
390 " attribute with invalid length");
391 free(rpair);
392 continue;
393 }
394 memcpy(rpair->strvalue, (char *)ptr, 16);
395 rpair->lvalue = attrlen;
396 break;
398 if (attrlen > 18 || attrlen < 2) {
399 rc_log(LOG_ERR, "rc_avpair_gen: received IPV6PREFIX"
400 " attribute with invalid length: %d", attrlen);
401 free(rpair);
402 continue;
403 }
404 memcpy(rpair->strvalue, (char *)ptr, attrlen);
405 rpair->lvalue = attrlen;
406 break;
407 case PW_TYPE_DATE:
408 if (attrlen != 4) {
409 rc_log(LOG_ERR, "rc_avpair_gen: received DATE "
410 "attribute with invalid length");
411 free(rpair);
412 continue;
413 }
414 memcpy((char *)&lvalue, (char *)ptr, 4);
415 rpair->lvalue = ntohl(lvalue);
416 break;
417 default:
418 rc_log(LOG_WARNING, "rc_avpair_gen: %s has unknown type",
419 attr->name);
420 free(rpair);
421 continue;
422 }
423
424 *tail = rpair;
425 tail = &rpair->next;
426 }
427
428 *out = head;
429 return 0;
430
431error:
432 rc_avpair_free(head);
433 return -1;
434}
436
459VALUE_PAIR *rc_avpair_gen(rc_handle const *rh, VALUE_PAIR *pair,
460 unsigned char const *ptr, int length,
461 uint32_t vendorspec)
462{
463 pkt_buf pb;
464 VALUE_PAIR *out = NULL;
465 if (length <= 0)
466 return pair;
467 pb_init_read(&pb, (void *)ptr, (size_t)length, (size_t)length);
468 if (rc_avpair_gen2(rh, pair, &pb, vendorspec, &out) < 0)
469 return NULL;
470 return out;
471}
472
480VALUE_PAIR *rc_avpair_get (VALUE_PAIR *vp, uint32_t attrid, uint32_t vendorspec)
481{
482 uint64_t attr = RADCLI_VENDOR_ATTR_SET(attrid, vendorspec);
483
484 for (; vp != NULL && !(attr == vp->attribute); vp = vp->next)
485 {
486 continue;
487 }
488 return vp;
489}
490
497VALUE_PAIR *rc_avpair_copy(VALUE_PAIR *p)
498{
499 VALUE_PAIR *vp, *fp = NULL, *lp = NULL;
500
501 while (p) {
502 vp = malloc(sizeof(VALUE_PAIR));
503 if (!vp) {
504 while(fp) { /* free allocated memory */
505 vp = fp;
506 fp = fp->next;
507 free(vp);
508 }
509 return NULL;
510 }
511 *vp = *p;
512 if (!fp)
513 fp = vp;
514 if (lp)
515 lp->next = vp;
516 lp = vp;
517 p = p->next;
518 }
519
520 return fp;
521}
522
532void rc_avpair_insert(VALUE_PAIR **a, VALUE_PAIR *p, VALUE_PAIR *b)
533{
534 VALUE_PAIR *this_node = NULL;
535 VALUE_PAIR *vp;
536
537 if (b->next != NULL)
538 {
539 rc_log(LOG_CRIT, "rc_avpair_insert: value pair (0x%p) next ptr. (0x%p) not NULL", b, b->next);
540 abort ();
541 }
542
543 if (*a == NULL)
544 {
545 *a = b;
546 return;
547 }
548
549 vp = *a;
550
551 if ( p == NULL) /* run to end of "a" list */
552 {
553 while (vp != NULL)
554 {
555 this_node = vp;
556 vp = vp->next;
557 }
558 }
559 else /* look for the "p" entry in the "a" list */
560 {
561 this_node = *a;
562 while (this_node != NULL)
563 {
564 if (this_node == p)
565 {
566 break;
567 }
568 this_node = this_node->next;
569 }
570 }
571
572 if (this_node) {
573 b->next = this_node->next;
574 this_node->next = b;
575 }
576
577 return;
578}
579
584void rc_avpair_free (VALUE_PAIR *pair)
585{
586 VALUE_PAIR *next;
587
588 while (pair != NULL)
589 {
590 next = pair->next;
591 free (pair);
592 pair = next;
593 }
594}
595
596/* Copy a data field from the buffer
597 *
598 * Advance the buffer past the data field. Ensure that no more than len - 1 bytes are copied and that resulting
599 * string is terminated with '\0'.
600 *
601 * @param string the provided string to copy.
602 * @param uptr the current position of the buffer.
603 * @param stopat characters to which parsing should stop.
604 * @param len the maximum length of string.
605 */
607static void rc_fieldcpy(char *string, char const **uptr, char const *stopat, size_t len)
608{
609 char const *ptr, *estring;
610
611 ptr = *uptr;
612 estring = string + len - 1;
613 if (*ptr == '"')
614 {
615 ptr++;
616 while (*ptr != '"' && *ptr != '\0' && *ptr != '\n')
617 {
618 if (string < estring)
619 *string++ = *ptr;
620 ptr++;
621 }
622 if (*ptr == '"')
623 {
624 ptr++;
625 }
626 *string = '\0';
627 *uptr = ptr;
628 return;
629 }
630
631 while (*ptr != '\0' && strchr(stopat, *ptr) == NULL)
632 {
633 if (string < estring)
634 *string++ = *ptr;
635 ptr++;
636 }
637 *string = '\0';
638 *uptr = ptr;
639 return;
640}
642
650int rc_avpair_parse (rc_handle const *rh, char const *buffer, VALUE_PAIR **first_pair)
651{
652 int mode;
653 char attrstr[AUTH_ID_LEN];
654 char valstr[AUTH_STRING_LEN + 1], *p;
655 DICT_ATTR *attr = NULL;
656 DICT_VALUE *dval;
657 VALUE_PAIR *pair;
658 VALUE_PAIR *link;
659 struct tm *tm, _tm;
660 time_t timeval;
661
662 mode = PARSE_MODE_NAME;
663 while (*buffer != '\n' && *buffer != '\0')
664 {
665 if (*buffer == ' ' || *buffer == '\t')
666 {
667 buffer++;
668 continue;
669 }
670
671 switch (mode)
672 {
673 case PARSE_MODE_NAME: /* Attribute Name */
674 rc_fieldcpy (attrstr, &buffer, " \t\n=,", sizeof(attrstr));
675 if ((attr =
676 rc_dict_findattr (rh, attrstr)) == NULL)
677 {
678 rc_log(LOG_ERR, "rc_avpair_parse: unknown attribute");
679 if (*first_pair) {
680 rc_avpair_free(*first_pair);
681 *first_pair = NULL;
682 }
683 return -1;
684 }
685 mode = PARSE_MODE_EQUAL;
686 break;
687
688 case PARSE_MODE_EQUAL: /* Equal sign */
689 if (*buffer == '=')
690 {
691 mode = PARSE_MODE_VALUE;
692 buffer++;
693 }
694 else
695 {
696 rc_log(LOG_ERR, "rc_avpair_parse: missing or misplaced equal sign");
697 if (*first_pair) {
698 rc_avpair_free(*first_pair);
699 *first_pair = NULL;
700 }
701 return -1;
702 }
703 break;
704
705 case PARSE_MODE_VALUE: /* Value */
706 rc_fieldcpy (valstr, &buffer, " \t\n,", sizeof(valstr));
707
708 if ((pair = malloc (sizeof (VALUE_PAIR))) == NULL)
709 {
710 rc_log(LOG_CRIT, "rc_avpair_parse: out of memory");
711 if (*first_pair) {
712 rc_avpair_free(*first_pair);
713 *first_pair = NULL;
714 }
715 return -1;
716 }
717 strlcpy (pair->name, attr->name, sizeof(pair->name));
718 pair->attribute = attr->value;
719 pair->type = attr->type;
720
721 switch (pair->type)
722 {
723
724 case PW_TYPE_STRING:
725 if (rc_avpair_assign(pair, valstr, strlen(valstr)) < 0) {
726 rc_log(LOG_ERR, "rc_avpair_parse: string value too long");
727 free(pair);
728 return -1;
729 }
730 break;
731
732 case PW_TYPE_INTEGER:
733 if (isdigit (*valstr))
734 {
735 pair->lvalue = atoi (valstr);
736 }
737 else
738 {
739 if ((dval = rc_dict_findval (rh, valstr))
740 == NULL)
741 {
742 rc_log(LOG_ERR, "rc_avpair_parse: unknown attribute value: %s", valstr);
743 if (*first_pair) {
744 rc_avpair_free(*first_pair);
745 *first_pair = NULL;
746 }
747 free (pair);
748 return -1;
749 }
750 else
751 {
752 pair->lvalue = dval->value;
753 }
754 }
755 break;
756
757 case PW_TYPE_IPADDR:
758 if (inet_pton(AF_INET, valstr, &pair->lvalue) == 0) {
759 rc_log(LOG_ERR, "rc_avpair_parse: invalid IPv4 address %s", valstr);
760 free(pair);
761 return -1;
762 }
763
764 pair->lvalue = ntohl(pair->lvalue);
765 break;
766
767 case PW_TYPE_IPV6ADDR:
768 if (inet_pton(AF_INET6, valstr, pair->strvalue) == 0) {
769 rc_log(LOG_ERR, "rc_avpair_parse: invalid IPv6 address %s", valstr);
770 free(pair);
771 return -1;
772 }
773 pair->lvalue = 16;
774 break;
775
777 p = strchr(valstr, '/');
778 if (p == NULL) {
779 rc_log(LOG_ERR, "rc_avpair_parse: invalid IPv6 prefix %s", valstr);
780 free(pair);
781 return -1;
782 }
783 *p = 0;
784 p++;
785 pair->strvalue[0] = 0;
786 pair->strvalue[1] = atoi(p);
787
788 if (inet_pton(AF_INET6, valstr, pair->strvalue+2) == 0) {
789 rc_log(LOG_ERR, "rc_avpair_parse: invalid IPv6 prefix %s", valstr);
790 free(pair);
791 return -1;
792 }
793 pair->lvalue = 2+16;
794 break;
795
796 case PW_TYPE_DATE:
797 timeval = time (0);
798 tm = localtime_r (&timeval, &_tm);
799 tm->tm_hour = 0;
800 tm->tm_min = 0;
801 tm->tm_sec = 0;
802 if (rc_str2tm (valstr, tm) < 0) {
803 rc_log(LOG_ERR, "rc_avpair_parse: invalid date %s", valstr);
804 free(pair);
805 return -1;
806 }
807 pair->lvalue = (uint32_t) mktime (tm);
808 break;
809
810 default:
811 rc_log(LOG_ERR, "rc_avpair_parse: unknown attribute type %d", pair->type);
812 if (*first_pair) {
813 rc_avpair_free(*first_pair);
814 *first_pair = NULL;
815 }
816 free (pair);
817 return -1;
818 }
819
820 /* XXX: Fix up Digest-Attributes */
821 switch (pair->attribute) {
822 case PW_DIGEST_REALM:
823 case PW_DIGEST_NONCE:
824 case PW_DIGEST_METHOD:
825 case PW_DIGEST_URI:
826 case PW_DIGEST_QOP:
829 case PW_DIGEST_CNONCE:
832 /* overlapping! */
833 if (pair->lvalue > AUTH_STRING_LEN - 2)
834 pair->lvalue = AUTH_STRING_LEN - 2;
835 memmove(&pair->strvalue[2], &pair->strvalue[0], pair->lvalue);
836 pair->strvalue[0] = pair->attribute - PW_DIGEST_REALM + 1;
837 pair->lvalue += 2;
838 pair->strvalue[1] = pair->lvalue;
839 pair->strvalue[pair->lvalue] = '\0';
841 break;
842 default:
843 break;
844 }
845
846 pair->next = NULL;
847
848 if (*first_pair == NULL)
849 {
850 *first_pair = pair;
851 }
852 else
853 {
854 link = *first_pair;
855 while (link->next != NULL)
856 {
857 link = link->next;
858 }
859 link->next = pair;
860 }
861
862 mode = PARSE_MODE_NAME;
863 break;
864
865 default:
866 mode = PARSE_MODE_NAME;
867 break;
868 }
869 }
870 return 0;
871}
872
883int rc_avpair_tostr (rc_handle const *rh, VALUE_PAIR *pair, char *name, int ln, char *value, int lv)
884{
885 DICT_VALUE *dval;
886 struct in_addr inad;
887 unsigned char *ptr;
888 unsigned int pos;
889 unsigned int slen;
890
891 *name = *value = '\0';
892
893 if (!pair || pair->name[0] == '\0') {
894 rc_log(LOG_ERR, "rc_avpair_tostr: pair is NULL or empty");
895 return -1;
896 }
897
898 strlcpy(name, pair->name, (size_t) ln);
899
900 switch (pair->type)
901 {
902 case PW_TYPE_STRING:
903 lv--;
904 pos = 0;
905 ptr = (unsigned char *) pair->strvalue;
906 if (pair->attribute == PW_DIGEST_ATTRIBUTES) {
907 slen = ptr[1] - 2;
908 ptr += 2;
909 } else {
910 slen = pair->lvalue;
911 }
912 while (slen-- > 0)
913 {
914 if (!(isprint (*ptr)))
915 {
916 if (lv >= 4) {
917 snprintf (&value[pos], lv, "\\%03o", *ptr);
918 pos += 4;
919 lv -= 4;
920 } else {
921 break;
922 }
923 }
924 else
925 {
926 if (lv > 0) {
927 value[pos++] = *ptr;
928 lv--;
929 } else {
930 break;
931 }
932 }
933 ptr++;
934 }
935 value[pos] = 0;
936 break;
937
938 case PW_TYPE_INTEGER:
939 dval = rc_dict_getval (rh, pair->lvalue, pair->name);
940 if (dval != NULL)
941 {
942 strlcpy(value, dval->name, (size_t) lv);
943 }
944 else
945 {
946 snprintf(value, lv, "%ld", (long int)pair->lvalue);
947 }
948 break;
949
950 case PW_TYPE_IPADDR:
951 inad.s_addr = htonl(pair->lvalue);
952 strlcpy (value, inet_ntoa (inad), (size_t) lv);
953 break;
954
955 case PW_TYPE_IPV6ADDR:
956 if (inet_ntop(AF_INET6, pair->strvalue, value, lv) == NULL)
957 return -1;
958 break;
959
960 case PW_TYPE_IPV6PREFIX: {
961 uint8_t ip[16];
962 uint8_t txt[48];
963 if (pair->lvalue < 2)
964 return -1;
965
966 memset(ip, 0, sizeof(ip));
967 memcpy(ip, pair->strvalue+2, pair->lvalue-2);
968
969 if (inet_ntop(AF_INET6, ip, (void*)txt, sizeof(txt)) == NULL)
970 return -1;
971 snprintf(value, lv, "%s/%u", txt, (unsigned)pair->strvalue[1]);
972
973 break;
974 }
975 case PW_TYPE_DATE: {
976 struct tm _tm;
977 struct tm *ptm = gmtime_r((time_t *) & pair->lvalue, &_tm);
978 if (ptm == NULL)
979 return -1;
980
981 strftime (value, lv, "%m/%d/%y %H:%M:%S", ptm);
982 break;
983 }
984
985 default:
986 rc_log(LOG_ERR, "rc_avpair_tostr: unknown attribute type %d", pair->type);
987 return -1;
988 break;
989 }
990
991 return 0;
992}
993
1004char *rc_avpair_log(rc_handle const *rh, VALUE_PAIR *pair, char *buf, size_t buf_len)
1005{
1006 size_t len;
1007 int n;
1008 VALUE_PAIR *vp;
1009 char name[RC_NAME_LENGTH + 1], value[256];
1010
1011 len = 0;
1012 for (vp = pair; vp != NULL; vp = vp->next) {
1013 if (rc_avpair_tostr(rh, vp, name, sizeof(name), value,
1014 sizeof(value)) == -1)
1015 return NULL;
1016 if (len >= buf_len)
1017 return buf;
1018 n = snprintf(buf + len, buf_len - len, "%-32s = '%s'\n", name, value);
1019 if (n < 0 || (size_t)n >= buf_len - len)
1020 return buf;
1021 len += (size_t)n;
1022 }
1023 return buf;
1024}
1025
1036int rc_avpair_get_uint32 (VALUE_PAIR *vp, uint32_t *res)
1037{
1038 if (vp->type == PW_TYPE_DATE || vp->type == PW_TYPE_IPADDR ||
1039 vp->type == PW_TYPE_INTEGER) {
1040 if (res)
1041 *res = vp->lvalue;
1042 return 0;
1043 } else {
1044 return -1;
1045 }
1046}
1047
1057int rc_avpair_get_in6 (VALUE_PAIR *vp, struct in6_addr *res, unsigned *prefix)
1058{
1059 if (vp->type == PW_TYPE_IPV6ADDR) {
1060 memcpy(res, vp->strvalue, 16);
1061 return 0;
1062 } else if (vp->type == PW_TYPE_IPV6PREFIX) {
1063 if (vp->lvalue < 2 || vp->lvalue > 18)
1064 return -1;
1065
1066 if (res) {
1067 memset(res, 0, 16);
1068 memcpy(res, vp->strvalue+2, vp->lvalue-2);
1069 }
1070
1071 if (prefix)
1072 *prefix = (unsigned char)vp->strvalue[1];
1073 return 0;
1074 }
1075
1076 return -1;
1077}
1078
1089int rc_avpair_get_raw (VALUE_PAIR *vp, char **res, unsigned *res_size)
1090{
1091 if (vp->type == PW_TYPE_STRING || vp->type == PW_TYPE_IPV6ADDR ||
1092 vp->type == PW_TYPE_IPV6PREFIX) {
1093 if (res)
1094 *res = vp->strvalue;
1095 if (res_size)
1096 *res_size = vp->lvalue;
1097 return 0;
1098 } else {
1099 return -1;
1100 }
1101}
1102
1109void rc_avpair_get_attr (VALUE_PAIR *vp, unsigned *type, unsigned *id)
1110{
1111 if (type)
1112 *type = vp->type;
1113 if (id)
1114 *id = vp->attribute;
1115}
1116
1118/*
1119 * Local Variables:
1120 * c-basic-offset:8
1121 * c-style: whitesmith
1122 * End:
1123 */
void rc_avpair_remove(VALUE_PAIR **list, uint32_t attrid, uint32_t vendorspec)
Removes an attribute-value pair from the given list.
Definition avpair.c:69
DICT_VALUE * rc_dict_getval(rc_handle const *rh, uint32_t value, char const *attrname)
Get DICT_VALUE based on attribute name and integer value number.
Definition dict.c:704
int rc_avpair_get_raw(VALUE_PAIR *vp, char **res, unsigned *res_size)
Get the raw value of the given attribute value-pair.
Definition avpair.c:1089
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.
Definition avpair.c:1004
VALUE_PAIR * rc_avpair_next(VALUE_PAIR *t)
Iterates through the attribute-value pairs.
Definition avpair.c:112
int rc_avpair_get_uint32(VALUE_PAIR *vp, uint32_t *res)
Get the integer value of the given attribute value-pair.
Definition avpair.c:1036
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.
Definition avpair.c:1057
void rc_avpair_get_attr(VALUE_PAIR *vp, unsigned *type, unsigned *id)
Get the attribute ID and type of the given attribute value-pair.
Definition avpair.c:1109
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.
Definition avpair.c:459
void rc_avpair_free(VALUE_PAIR *pair)
Frees all value_pairs in the list.
Definition avpair.c:584
VALUE_PAIR * rc_avpair_copy(VALUE_PAIR *p)
Return a copy of the existing list "p" ala strdup().
Definition avpair.c:497
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.
Definition avpair.c:883
int rc_avpair_assign(VALUE_PAIR *vp, void const *pval, int len)
Assigns the given value to an attribute-value pair.
Definition avpair.c:135
DICT_VALUE * rc_dict_findval(rc_handle const *rh, char const *valname)
Lookup a DICT_VALUE by its name.
Definition dict.c:650
int rc_avpair_parse(rc_handle const *rh, char const *buffer, VALUE_PAIR **first_pair)
Parses the buffer to extract the attribute-value pairs.
Definition avpair.c:650
DICT_VENDOR * rc_dict_getvend(rc_handle const *rh, uint32_t vendorspec)
Lookup a DICT_VENDOR by its IANA number.
Definition dict.c:687
DICT_ATTR * rc_dict_getattr(rc_handle const *rh, uint64_t attribute)
Lookup a DICT_ATTR by attribute number.
Definition dict.c:604
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.
Definition avpair.c:46
void rc_avpair_insert(VALUE_PAIR **a, VALUE_PAIR *p, VALUE_PAIR *b)
Insert a VALUE_PAIR into a list.
Definition avpair.c:532
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...
Definition avpair.c:480
DICT_ATTR * rc_dict_findattr(rc_handle const *rh, char const *attrname)
Lookup a DICT_ATTR by its name.
Definition dict.c:627
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.
Definition avpair.c:196
@ PW_DIGEST_NONCE
Its type is string.
Definition radcli.h:263
@ PW_DIGEST_REALM
Its type is string.
Definition radcli.h:262
@ PW_DIGEST_USER_NAME
Its type is string.
Definition radcli.h:271
@ PW_DIGEST_URI
Its type is string.
Definition radcli.h:265
@ PW_DIGEST_QOP
Its type is string.
Definition radcli.h:266
@ PW_DIGEST_BODY_DIGEST
Its type is string.
Definition radcli.h:268
@ PW_DIGEST_ATTRIBUTES
Its type is string.
Definition radcli.h:261
@ PW_DIGEST_NONCE_COUNT
Its type is string.
Definition radcli.h:270
@ PW_DIGEST_ALGORITHM
Its type is string.
Definition radcli.h:267
@ PW_DIGEST_CNONCE
Its type is string.
Definition radcli.h:269
@ PW_DIGEST_METHOD
Its type is string.
Definition radcli.h:264
@ PW_VENDOR_SPECIFIC
Its type is string.
Definition radcli.h:176
@ PW_TYPE_IPADDR
The attribute is an IPv4 address in host-byte order.
Definition radcli.h:123
@ PW_TYPE_IPV6ADDR
The attribute is an 128-bit IPv6 address.
Definition radcli.h:125
@ PW_TYPE_IPV6PREFIX
The attribute is an IPv6 prefix; the lvalue will indicate its size.
Definition radcli.h:126
@ PW_TYPE_INTEGER
The attribute is a 32-bit integer.
Definition radcli.h:122
@ PW_TYPE_DATE
The attribute contains a 32-bit number indicating the seconds since epoch.
Definition radcli.h:124
@ PW_TYPE_STRING
The attribute is a printable string.
Definition radcli.h:121
Public API of the radcli library.
rc_attr_type type
string, int, etc..
Definition radcli.h:445
uint64_t value
attribute index and vendor number; use VENDOR() and ATTRID() to separate.
Definition radcli.h:444
char name[RC_NAME_LENGTH+1]
attribute name.
Definition radcli.h:443
rc_attr_type type
attribute type.
Definition radcli.h:500
uint64_t attribute
attribute numeric value of type rc_attr_id including vendor; use VENDOR() and ATTRID() to separate.
Definition radcli.h:499
uint32_t lvalue
attribute value if type is PW_TYPE_INTEGER, PW_TYPE_DATE or PW_TYPE_IPADDR.
Definition radcli.h:501
char strvalue[AUTH_STRING_LEN+1]
contains attribute value in other cases.
Definition radcli.h:502
char name[RC_NAME_LENGTH+1]
attribute name if known.
Definition radcli.h:498