Radcli library 1.5.1
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
274/* Returns 0 on success (decoded list in *out, may be NULL if all attrs skipped),
275 * -1 on hard error (*out undefined, incoming pair list already freed). */
276static int rc_avpair_gen2(rc_handle const *rh, VALUE_PAIR *pair,
277 pkt_buf *pb, uint32_t vendorspec,
278 VALUE_PAIR **out)
279{
280 VALUE_PAIR *head = pair;
281 VALUE_PAIR **tail = &head;
282 const uint8_t *attr_data, *ptr;
283 int attrlen;
284 uint64_t attribute;
285 uint32_t lvalue;
286 DICT_ATTR *attr;
287 VALUE_PAIR *rpair;
288 char buffer[(AUTH_STRING_LEN * 2) + 1];
289
290 /* Advance tail to end of the initial list so we append in wire order */
291 while (*tail != NULL)
292 tail = &(*tail)->next;
293
294 while (pb_len(pb) > 0) {
295 if (pb_len(pb) < 2) {
296 rc_log(LOG_ERR, "rc_avpair_gen: received attribute with "
297 "invalid length");
298 goto error;
299 }
300 attrlen = pb->data[1];
301 if (attrlen < 2 || (size_t)attrlen > pb_len(pb)) {
302 rc_log(LOG_ERR, "rc_avpair_gen: received attribute with "
303 "invalid length");
304 goto error;
305 }
306
307 attr_data = pb->data;
308 assert(pb_pull(pb, attrlen) == 0);
309
310 attribute = RADCLI_VENDOR_ATTR_SET(attr_data[0], vendorspec);
311 ptr = attr_data + 2;
312 attrlen -= 2;
313
314 /* VSA */
315 if (attribute == PW_VENDOR_SPECIFIC) {
316 if (attrlen < 4) {
317 rc_log(LOG_ERR, "rc_avpair_gen: received VSA "
318 "attribute with invalid length");
319 continue;
320 }
321 memcpy(&lvalue, ptr, 4);
322 lvalue = ntohl(lvalue);
323 if (rc_dict_getvend(rh, lvalue) == NULL) {
324 rc_log(LOG_WARNING, "rc_avpair_gen: received VSA "
325 "attribute with unknown Vendor-Id %d", lvalue);
326 continue;
327 }
328 /* Process VSA sub-attributes; append results to tail */
329 {
330 pkt_buf vsa_pb;
331 VALUE_PAIR *vsa_list = NULL;
332 pb_init_read(&vsa_pb,
333 (void *)(uintptr_t)(ptr + 4),
334 attrlen - 4, attrlen - 4);
335 if (rc_avpair_gen2(rh, NULL, &vsa_pb, lvalue,
336 &vsa_list) < 0)
337 goto error;
338 /* vsa_list may be NULL if all sub-attrs skipped */
339 if (vsa_list != NULL) {
340 *tail = vsa_list;
341 while (*tail != NULL)
342 tail = &(*tail)->next;
343 }
344 }
345 continue;
346 }
347
348 /* Normal attribute */
349 attr = rc_dict_getattr(rh, attribute);
350 if (attr == NULL) {
351 rc_bin2hex(buffer, sizeof(buffer), ptr, (size_t)attrlen);
352 if (vendorspec == 0) {
353 rc_log(LOG_WARNING, "rc_avpair_gen: received "
354 "unknown attribute %d of length %d: 0x%s",
355 (unsigned)attribute, attrlen + 2, buffer);
356 } else {
357 rc_log(LOG_WARNING, "rc_avpair_gen: received "
358 "unknown VSA attribute %u, vendor %u of "
359 "length %d: 0x%s", (unsigned)ATTRID(attribute),
360 (unsigned)VENDOR(attribute), attrlen + 2, buffer);
361 }
362 continue;
363 }
364
365 rpair = calloc(1, sizeof(*rpair));
366 if (rpair == NULL) {
367 rc_log(LOG_CRIT, "rc_avpair_gen: out of memory");
368 goto error;
369 }
370 rpair->next = NULL;
371 strlcpy(rpair->name, attr->name, sizeof(rpair->name));
372 rpair->attribute = attr->value;
373 rpair->type = attr->type;
374
375 switch (attr->type) {
376 case PW_TYPE_STRING:
377 if (attrlen > AUTH_STRING_LEN) {
378 rc_log(LOG_ERR, "rc_avpair_gen: string attribute too long: %d", attrlen);
379 free(rpair);
380 goto error;
381 }
382 memcpy(rpair->strvalue, (char *)ptr, (size_t)attrlen);
383 rpair->strvalue[attrlen] = '\0';
384 rpair->lvalue = attrlen;
385 break;
386 case PW_TYPE_INTEGER:
387 case PW_TYPE_IPADDR:
388 if (attrlen != 4) {
389 rc_log(LOG_ERR, "rc_avpair_gen: received "
390 "INTEGER/IPADDR attribute with invalid length");
391 free(rpair);
392 continue;
393 }
394 memcpy((char *)&lvalue, (char *)ptr, 4);
395 rpair->lvalue = ntohl(lvalue);
396 break;
397 case PW_TYPE_IPV6ADDR:
398 if (attrlen != 16) {
399 rc_log(LOG_ERR, "rc_avpair_gen: received IPV6ADDR"
400 " attribute with invalid length");
401 free(rpair);
402 continue;
403 }
404 memcpy(rpair->strvalue, (char *)ptr, 16);
405 rpair->lvalue = attrlen;
406 break;
408 if (attrlen > 18 || attrlen < 2) {
409 rc_log(LOG_ERR, "rc_avpair_gen: received IPV6PREFIX"
410 " attribute with invalid length: %d", attrlen);
411 free(rpair);
412 continue;
413 }
414 memcpy(rpair->strvalue, (char *)ptr, attrlen);
415 rpair->lvalue = attrlen;
416 break;
417 case PW_TYPE_DATE:
418 if (attrlen != 4) {
419 rc_log(LOG_ERR, "rc_avpair_gen: received DATE "
420 "attribute with invalid length");
421 free(rpair);
422 continue;
423 }
424 memcpy((char *)&lvalue, (char *)ptr, 4);
425 rpair->lvalue = ntohl(lvalue);
426 break;
427 default:
428 rc_log(LOG_WARNING, "rc_avpair_gen: %s has unknown type",
429 attr->name);
430 free(rpair);
431 continue;
432 }
433
434 *tail = rpair;
435 tail = &rpair->next;
436 }
437
438 *out = head;
439 return 0;
440
441error:
442 rc_avpair_free(head);
443 return -1;
444}
445
446VALUE_PAIR *rc_avpair_gen(rc_handle const *rh, VALUE_PAIR *pair,
447 unsigned char const *ptr, int length,
448 uint32_t vendorspec)
449{
450 pkt_buf pb;
451 VALUE_PAIR *out = NULL;
452 if (length <= 0)
453 return pair;
454 pb_init_read(&pb, (void *)ptr, (size_t)length, (size_t)length);
455 if (rc_avpair_gen2(rh, pair, &pb, vendorspec, &out) < 0)
456 return NULL;
457 return out;
458}
459
467VALUE_PAIR *rc_avpair_get (VALUE_PAIR *vp, uint32_t attrid, uint32_t vendorspec)
468{
469 uint64_t attr = RADCLI_VENDOR_ATTR_SET(attrid, vendorspec);
470
471 for (; vp != NULL && !(attr == vp->attribute); vp = vp->next)
472 {
473 continue;
474 }
475 return vp;
476}
477
484VALUE_PAIR *rc_avpair_copy(VALUE_PAIR *p)
485{
486 VALUE_PAIR *vp, *fp = NULL, *lp = NULL;
487
488 while (p) {
489 vp = malloc(sizeof(VALUE_PAIR));
490 if (!vp) {
491 while(fp) { /* free allocated memory */
492 vp = fp;
493 fp = fp->next;
494 free(vp);
495 }
496 return NULL;
497 }
498 *vp = *p;
499 if (!fp)
500 fp = vp;
501 if (lp)
502 lp->next = vp;
503 lp = vp;
504 p = p->next;
505 }
506
507 return fp;
508}
509
519void rc_avpair_insert(VALUE_PAIR **a, VALUE_PAIR *p, VALUE_PAIR *b)
520{
521 VALUE_PAIR *this_node = NULL;
522 VALUE_PAIR *vp;
523
524 if (b->next != NULL)
525 {
526 rc_log(LOG_CRIT, "rc_avpair_insert: value pair (0x%p) next ptr. (0x%p) not NULL", b, b->next);
527 abort ();
528 }
529
530 if (*a == NULL)
531 {
532 *a = b;
533 return;
534 }
535
536 vp = *a;
537
538 if ( p == NULL) /* run to end of "a" list */
539 {
540 while (vp != NULL)
541 {
542 this_node = vp;
543 vp = vp->next;
544 }
545 }
546 else /* look for the "p" entry in the "a" list */
547 {
548 this_node = *a;
549 while (this_node != NULL)
550 {
551 if (this_node == p)
552 {
553 break;
554 }
555 this_node = this_node->next;
556 }
557 }
558
559 if (this_node) {
560 b->next = this_node->next;
561 this_node->next = b;
562 }
563
564 return;
565}
566
571void rc_avpair_free (VALUE_PAIR *pair)
572{
573 VALUE_PAIR *next;
574
575 while (pair != NULL)
576 {
577 next = pair->next;
578 free (pair);
579 pair = next;
580 }
581}
582
593static void rc_fieldcpy(char *string, char const **uptr, char const *stopat, size_t len)
594{
595 char const *ptr, *estring;
596
597 ptr = *uptr;
598 estring = string + len - 1;
599 if (*ptr == '"')
600 {
601 ptr++;
602 while (*ptr != '"' && *ptr != '\0' && *ptr != '\n')
603 {
604 if (string < estring)
605 *string++ = *ptr;
606 ptr++;
607 }
608 if (*ptr == '"')
609 {
610 ptr++;
611 }
612 *string = '\0';
613 *uptr = ptr;
614 return;
615 }
616
617 while (*ptr != '\0' && strchr(stopat, *ptr) == NULL)
618 {
619 if (string < estring)
620 *string++ = *ptr;
621 ptr++;
622 }
623 *string = '\0';
624 *uptr = ptr;
625 return;
626}
627
635int rc_avpair_parse (rc_handle const *rh, char const *buffer, VALUE_PAIR **first_pair)
636{
637 int mode;
638 char attrstr[AUTH_ID_LEN];
639 char valstr[AUTH_STRING_LEN + 1], *p;
640 DICT_ATTR *attr = NULL;
641 DICT_VALUE *dval;
642 VALUE_PAIR *pair;
643 VALUE_PAIR *link;
644 struct tm *tm, _tm;
645 time_t timeval;
646
647 mode = PARSE_MODE_NAME;
648 while (*buffer != '\n' && *buffer != '\0')
649 {
650 if (*buffer == ' ' || *buffer == '\t')
651 {
652 buffer++;
653 continue;
654 }
655
656 switch (mode)
657 {
658 case PARSE_MODE_NAME: /* Attribute Name */
659 rc_fieldcpy (attrstr, &buffer, " \t\n=,", sizeof(attrstr));
660 if ((attr =
661 rc_dict_findattr (rh, attrstr)) == NULL)
662 {
663 rc_log(LOG_ERR, "rc_avpair_parse: unknown attribute");
664 if (*first_pair) {
665 rc_avpair_free(*first_pair);
666 *first_pair = NULL;
667 }
668 return -1;
669 }
670 mode = PARSE_MODE_EQUAL;
671 break;
672
673 case PARSE_MODE_EQUAL: /* Equal sign */
674 if (*buffer == '=')
675 {
676 mode = PARSE_MODE_VALUE;
677 buffer++;
678 }
679 else
680 {
681 rc_log(LOG_ERR, "rc_avpair_parse: missing or misplaced equal sign");
682 if (*first_pair) {
683 rc_avpair_free(*first_pair);
684 *first_pair = NULL;
685 }
686 return -1;
687 }
688 break;
689
690 case PARSE_MODE_VALUE: /* Value */
691 rc_fieldcpy (valstr, &buffer, " \t\n,", sizeof(valstr));
692
693 if ((pair = malloc (sizeof (VALUE_PAIR))) == NULL)
694 {
695 rc_log(LOG_CRIT, "rc_avpair_parse: out of memory");
696 if (*first_pair) {
697 rc_avpair_free(*first_pair);
698 *first_pair = NULL;
699 }
700 return -1;
701 }
702 strlcpy (pair->name, attr->name, sizeof(pair->name));
703 pair->attribute = attr->value;
704 pair->type = attr->type;
705
706 switch (pair->type)
707 {
708
709 case PW_TYPE_STRING:
710 if (rc_avpair_assign(pair, valstr, strlen(valstr)) < 0) {
711 rc_log(LOG_ERR, "rc_avpair_parse: string value too long");
712 free(pair);
713 return -1;
714 }
715 break;
716
717 case PW_TYPE_INTEGER:
718 if (isdigit (*valstr))
719 {
720 pair->lvalue = atoi (valstr);
721 }
722 else
723 {
724 if ((dval = rc_dict_findval (rh, valstr))
725 == NULL)
726 {
727 rc_log(LOG_ERR, "rc_avpair_parse: unknown attribute value: %s", valstr);
728 if (*first_pair) {
729 rc_avpair_free(*first_pair);
730 *first_pair = NULL;
731 }
732 free (pair);
733 return -1;
734 }
735 else
736 {
737 pair->lvalue = dval->value;
738 }
739 }
740 break;
741
742 case PW_TYPE_IPADDR:
743 if (inet_pton(AF_INET, valstr, &pair->lvalue) == 0) {
744 rc_log(LOG_ERR, "rc_avpair_parse: invalid IPv4 address %s", valstr);
745 free(pair);
746 return -1;
747 }
748
749 pair->lvalue = ntohl(pair->lvalue);
750 break;
751
752 case PW_TYPE_IPV6ADDR:
753 if (inet_pton(AF_INET6, valstr, pair->strvalue) == 0) {
754 rc_log(LOG_ERR, "rc_avpair_parse: invalid IPv6 address %s", valstr);
755 free(pair);
756 return -1;
757 }
758 pair->lvalue = 16;
759 break;
760
762 p = strchr(valstr, '/');
763 if (p == NULL) {
764 rc_log(LOG_ERR, "rc_avpair_parse: invalid IPv6 prefix %s", valstr);
765 free(pair);
766 return -1;
767 }
768 *p = 0;
769 p++;
770 pair->strvalue[0] = 0;
771 pair->strvalue[1] = atoi(p);
772
773 if (inet_pton(AF_INET6, valstr, pair->strvalue+2) == 0) {
774 rc_log(LOG_ERR, "rc_avpair_parse: invalid IPv6 prefix %s", valstr);
775 free(pair);
776 return -1;
777 }
778 pair->lvalue = 2+16;
779 break;
780
781 case PW_TYPE_DATE:
782 timeval = time (0);
783 tm = localtime_r (&timeval, &_tm);
784 tm->tm_hour = 0;
785 tm->tm_min = 0;
786 tm->tm_sec = 0;
787 rc_str2tm (valstr, tm);
788 pair->lvalue = (uint32_t) mktime (tm);
789 break;
790
791 default:
792 rc_log(LOG_ERR, "rc_avpair_parse: unknown attribute type %d", pair->type);
793 if (*first_pair) {
794 rc_avpair_free(*first_pair);
795 *first_pair = NULL;
796 }
797 free (pair);
798 return -1;
799 }
800
801 /* XXX: Fix up Digest-Attributes */
802 switch (pair->attribute) {
803 case PW_DIGEST_REALM:
804 case PW_DIGEST_NONCE:
805 case PW_DIGEST_METHOD:
806 case PW_DIGEST_URI:
807 case PW_DIGEST_QOP:
810 case PW_DIGEST_CNONCE:
813 /* overlapping! */
814 if (pair->lvalue > AUTH_STRING_LEN - 2)
815 pair->lvalue = AUTH_STRING_LEN - 2;
816 memmove(&pair->strvalue[2], &pair->strvalue[0], pair->lvalue);
817 pair->strvalue[0] = pair->attribute - PW_DIGEST_REALM + 1;
818 pair->lvalue += 2;
819 pair->strvalue[1] = pair->lvalue;
820 pair->strvalue[pair->lvalue] = '\0';
822 break;
823 default:
824 break;
825 }
826
827 pair->next = NULL;
828
829 if (*first_pair == NULL)
830 {
831 *first_pair = pair;
832 }
833 else
834 {
835 link = *first_pair;
836 while (link->next != NULL)
837 {
838 link = link->next;
839 }
840 link->next = pair;
841 }
842
843 mode = PARSE_MODE_NAME;
844 break;
845
846 default:
847 mode = PARSE_MODE_NAME;
848 break;
849 }
850 }
851 return 0;
852}
853
864int rc_avpair_tostr (rc_handle const *rh, VALUE_PAIR *pair, char *name, int ln, char *value, int lv)
865{
866 DICT_VALUE *dval;
867 struct in_addr inad;
868 unsigned char *ptr;
869 unsigned int pos;
870 unsigned int slen;
871
872 *name = *value = '\0';
873
874 if (!pair || pair->name[0] == '\0') {
875 rc_log(LOG_ERR, "rc_avpair_tostr: pair is NULL or empty");
876 return -1;
877 }
878
879 strlcpy(name, pair->name, (size_t) ln);
880
881 switch (pair->type)
882 {
883 case PW_TYPE_STRING:
884 lv--;
885 pos = 0;
886 ptr = (unsigned char *) pair->strvalue;
887 if (pair->attribute == PW_DIGEST_ATTRIBUTES) {
888 slen = ptr[1] - 2;
889 ptr += 2;
890 } else {
891 slen = pair->lvalue;
892 }
893 while (slen-- > 0)
894 {
895 if (!(isprint (*ptr)))
896 {
897 if (lv >= 4) {
898 snprintf (&value[pos], lv, "\\%03o", *ptr);
899 pos += 4;
900 lv -= 4;
901 } else {
902 break;
903 }
904 }
905 else
906 {
907 if (lv > 0) {
908 value[pos++] = *ptr;
909 lv--;
910 } else {
911 break;
912 }
913 }
914 ptr++;
915 }
916 value[pos] = 0;
917 break;
918
919 case PW_TYPE_INTEGER:
920 dval = rc_dict_getval (rh, pair->lvalue, pair->name);
921 if (dval != NULL)
922 {
923 strlcpy(value, dval->name, (size_t) lv);
924 }
925 else
926 {
927 snprintf(value, lv, "%ld", (long int)pair->lvalue);
928 }
929 break;
930
931 case PW_TYPE_IPADDR:
932 inad.s_addr = htonl(pair->lvalue);
933 strlcpy (value, inet_ntoa (inad), (size_t) lv);
934 break;
935
936 case PW_TYPE_IPV6ADDR:
937 if (inet_ntop(AF_INET6, pair->strvalue, value, lv) == NULL)
938 return -1;
939 break;
940
941 case PW_TYPE_IPV6PREFIX: {
942 uint8_t ip[16];
943 uint8_t txt[48];
944 if (pair->lvalue < 2)
945 return -1;
946
947 memset(ip, 0, sizeof(ip));
948 memcpy(ip, pair->strvalue+2, pair->lvalue-2);
949
950 if (inet_ntop(AF_INET6, ip, (void*)txt, sizeof(txt)) == NULL)
951 return -1;
952 snprintf(value, lv, "%s/%u", txt, (unsigned)pair->strvalue[1]);
953
954 break;
955 }
956 case PW_TYPE_DATE: {
957 struct tm _tm;
958 struct tm *ptm = gmtime_r((time_t *) & pair->lvalue, &_tm);
959 if (ptm == NULL)
960 return -1;
961
962 strftime (value, lv, "%m/%d/%y %H:%M:%S", ptm);
963 break;
964 }
965
966 default:
967 rc_log(LOG_ERR, "rc_avpair_tostr: unknown attribute type %d", pair->type);
968 return -1;
969 break;
970 }
971
972 return 0;
973}
974
985char *rc_avpair_log(rc_handle const *rh, VALUE_PAIR *pair, char *buf, size_t buf_len)
986{
987 size_t len, nlen;
988 VALUE_PAIR *vp;
989 char name[RC_NAME_LENGTH + 1], value[256];
990
991 len = 0;
992 for (vp = pair; vp != NULL; vp = vp->next) {
993 if (rc_avpair_tostr(rh, vp, name, sizeof(name), value,
994 sizeof(value)) == -1)
995 return NULL;
996 nlen = len + 32 + 3 + strlen(value) + 2 + 2;
997 if(nlen<buf_len-1) {
998 sprintf(buf + len, "%-32s = '%s'\n", name, value);
999 } else return buf;
1000 len = nlen - 1;
1001 }
1002 return buf;
1003}
1004
1015int rc_avpair_get_uint32 (VALUE_PAIR *vp, uint32_t *res)
1016{
1017 if (vp->type == PW_TYPE_DATE || vp->type == PW_TYPE_IPADDR ||
1018 vp->type == PW_TYPE_INTEGER) {
1019 if (res)
1020 *res = vp->lvalue;
1021 return 0;
1022 } else {
1023 return -1;
1024 }
1025}
1026
1036int rc_avpair_get_in6 (VALUE_PAIR *vp, struct in6_addr *res, unsigned *prefix)
1037{
1038 if (vp->type == PW_TYPE_IPV6ADDR) {
1039 memcpy(res, vp->strvalue, 16);
1040 return 0;
1041 } else if (vp->type == PW_TYPE_IPV6PREFIX) {
1042 if (vp->lvalue < 2 || vp->lvalue > 18)
1043 return -1;
1044
1045 if (res) {
1046 memset(res, 0, 16);
1047 memcpy(res, vp->strvalue+2, vp->lvalue-2);
1048 }
1049
1050 if (prefix)
1051 *prefix = (unsigned char)vp->strvalue[1];
1052 return 0;
1053 }
1054
1055 return -1;
1056}
1057
1068int rc_avpair_get_raw (VALUE_PAIR *vp, char **res, unsigned *res_size)
1069{
1070 if (vp->type == PW_TYPE_STRING || vp->type == PW_TYPE_IPV6ADDR ||
1071 vp->type == PW_TYPE_IPV6PREFIX) {
1072 if (res)
1073 *res = vp->strvalue;
1074 if (res_size)
1075 *res_size = vp->lvalue;
1076 return 0;
1077 } else {
1078 return -1;
1079 }
1080}
1081
1088void rc_avpair_get_attr (VALUE_PAIR *vp, unsigned *type, unsigned *id)
1089{
1090 if (type)
1091 *type = vp->type;
1092 if (id)
1093 *id = vp->attribute;
1094}
1095
1097/*
1098 * Local Variables:
1099 * c-basic-offset:8
1100 * c-style: whitesmith
1101 * End:
1102 */
void rc_avpair_remove(VALUE_PAIR **list, uint32_t attrid, uint32_t vendorspec)
Definition avpair.c:69
DICT_VALUE * rc_dict_getval(rc_handle const *rh, uint32_t value, char const *attrname)
Definition dict.c:632
int rc_avpair_get_raw(VALUE_PAIR *vp, char **res, unsigned *res_size)
Definition avpair.c:1068
char * rc_avpair_log(rc_handle const *rh, VALUE_PAIR *pair, char *buf, size_t buf_len)
Definition avpair.c:985
VALUE_PAIR * rc_avpair_next(VALUE_PAIR *t)
Definition avpair.c:112
int rc_avpair_get_uint32(VALUE_PAIR *vp, uint32_t *res)
Definition avpair.c:1015
int rc_avpair_get_in6(VALUE_PAIR *vp, struct in6_addr *res, unsigned *prefix)
Definition avpair.c:1036
void rc_avpair_get_attr(VALUE_PAIR *vp, unsigned *type, unsigned *id)
Definition avpair.c:1088
void rc_avpair_free(VALUE_PAIR *pair)
Definition avpair.c:571
VALUE_PAIR * rc_avpair_copy(VALUE_PAIR *p)
Definition avpair.c:484
int rc_avpair_tostr(rc_handle const *rh, VALUE_PAIR *pair, char *name, int ln, char *value, int lv)
Definition avpair.c:864
int rc_avpair_assign(VALUE_PAIR *vp, void const *pval, int len)
Definition avpair.c:135
DICT_VALUE * rc_dict_findval(rc_handle const *rh, char const *valname)
Definition dict.c:578
int rc_avpair_parse(rc_handle const *rh, char const *buffer, VALUE_PAIR **first_pair)
Definition avpair.c:635
DICT_VENDOR * rc_dict_getvend(rc_handle const *rh, uint32_t vendorspec)
Definition dict.c:615
DICT_ATTR * rc_dict_getattr(rc_handle const *rh, uint64_t attribute)
Definition dict.c:532
VALUE_PAIR * rc_avpair_add(rc_handle const *rh, VALUE_PAIR **list, uint32_t attrid, void const *pval, int len, uint32_t vendorspec)
Definition avpair.c:46
void rc_avpair_insert(VALUE_PAIR **a, VALUE_PAIR *p, VALUE_PAIR *b)
Definition avpair.c:519
VALUE_PAIR * rc_avpair_get(VALUE_PAIR *vp, uint32_t attrid, uint32_t vendorspec)
Definition avpair.c:467
DICT_ATTR * rc_dict_findattr(rc_handle const *rh, char const *attrname)
Definition dict.c:555
VALUE_PAIR * rc_avpair_new(rc_handle const *rh, uint32_t attrid, void const *pval, int len, uint32_t vendorspec)
Definition avpair.c:196
@ PW_DIGEST_NONCE
Its type is string.
Definition radcli.h:259
@ PW_DIGEST_REALM
Its type is string.
Definition radcli.h:258
@ PW_DIGEST_USER_NAME
Its type is string.
Definition radcli.h:267
@ PW_DIGEST_URI
Its type is string.
Definition radcli.h:261
@ PW_DIGEST_QOP
Its type is string.
Definition radcli.h:262
@ PW_DIGEST_BODY_DIGEST
Its type is string.
Definition radcli.h:264
@ PW_DIGEST_ATTRIBUTES
Its type is string.
Definition radcli.h:257
@ PW_DIGEST_NONCE_COUNT
Its type is string.
Definition radcli.h:266
@ PW_DIGEST_ALGORITHM
Its type is string.
Definition radcli.h:263
@ PW_DIGEST_CNONCE
Its type is string.
Definition radcli.h:265
@ PW_DIGEST_METHOD
Its type is string.
Definition radcli.h:260
@ PW_VENDOR_SPECIFIC
Its type is string.
Definition radcli.h:172
@ PW_TYPE_IPADDR
The attribute is an IPv4 address in host-byte order.
Definition radcli.h:119
@ PW_TYPE_IPV6ADDR
The attribute is an 128-bit IPv6 address.
Definition radcli.h:121
@ PW_TYPE_IPV6PREFIX
The attribute is an IPv6 prefix; the lvalue will indicate its size.
Definition radcli.h:122
@ PW_TYPE_INTEGER
The attribute is a 32-bit integer.
Definition radcli.h:118
@ PW_TYPE_DATE
The attribute contains a 32-bit number indicating the seconds since epoch.
Definition radcli.h:120
@ PW_TYPE_STRING
The attribute is a printable string.
Definition radcli.h:117
rc_attr_type type
string, int, etc..
Definition radcli.h:438
uint64_t value
attribute index and vendor number; use VENDOR() and ATTRID() to separate.
Definition radcli.h:437
char name[RC_NAME_LENGTH+1]
attribute name.
Definition radcli.h:436
rc_attr_type type
attribute type.
Definition radcli.h:483
uint64_t attribute
attribute numeric value of type rc_attr_id including vendor; use VENDOR() and ATTRID() to separate.
Definition radcli.h:482
uint32_t lvalue
attribute value if type is PW_TYPE_INTEGER, PW_TYPE_DATE or PW_TYPE_IPADDR.
Definition radcli.h:484
char strvalue[AUTH_STRING_LEN+1]
contains attribute value in other cases.
Definition radcli.h:485
char name[RC_NAME_LENGTH+1]
attribute name if known.
Definition radcli.h:481