Radcli library 1.5.2
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
468VALUE_PAIR *rc_avpair_gen(rc_handle const *rh, VALUE_PAIR *pair,
469 unsigned char const *ptr, int length,
470 uint32_t vendorspec)
471{
472 pkt_buf pb;
473 VALUE_PAIR *out = NULL;
474 if (length <= 0)
475 return pair;
476 pb_init_read(&pb, (void *)ptr, (size_t)length, (size_t)length);
477 if (rc_avpair_gen2(rh, pair, &pb, vendorspec, &out) < 0)
478 return NULL;
479 return out;
480}
481
489VALUE_PAIR *rc_avpair_get (VALUE_PAIR *vp, uint32_t attrid, uint32_t vendorspec)
490{
491 uint64_t attr = RADCLI_VENDOR_ATTR_SET(attrid, vendorspec);
492
493 for (; vp != NULL && !(attr == vp->attribute); vp = vp->next)
494 {
495 continue;
496 }
497 return vp;
498}
499
506VALUE_PAIR *rc_avpair_copy(VALUE_PAIR *p)
507{
508 VALUE_PAIR *vp, *fp = NULL, *lp = NULL;
509
510 while (p) {
511 vp = malloc(sizeof(VALUE_PAIR));
512 if (!vp) {
513 while(fp) { /* free allocated memory */
514 vp = fp;
515 fp = fp->next;
516 free(vp);
517 }
518 return NULL;
519 }
520 *vp = *p;
521 if (!fp)
522 fp = vp;
523 if (lp)
524 lp->next = vp;
525 lp = vp;
526 p = p->next;
527 }
528
529 return fp;
530}
531
541void rc_avpair_insert(VALUE_PAIR **a, VALUE_PAIR *p, VALUE_PAIR *b)
542{
543 VALUE_PAIR *this_node = NULL;
544 VALUE_PAIR *vp;
545
546 if (b->next != NULL)
547 {
548 rc_log(LOG_CRIT, "rc_avpair_insert: value pair (0x%p) next ptr. (0x%p) not NULL", b, b->next);
549 abort ();
550 }
551
552 if (*a == NULL)
553 {
554 *a = b;
555 return;
556 }
557
558 vp = *a;
559
560 if ( p == NULL) /* run to end of "a" list */
561 {
562 while (vp != NULL)
563 {
564 this_node = vp;
565 vp = vp->next;
566 }
567 }
568 else /* look for the "p" entry in the "a" list */
569 {
570 this_node = *a;
571 while (this_node != NULL)
572 {
573 if (this_node == p)
574 {
575 break;
576 }
577 this_node = this_node->next;
578 }
579 }
580
581 if (this_node) {
582 b->next = this_node->next;
583 this_node->next = b;
584 }
585
586 return;
587}
588
593void rc_avpair_free (VALUE_PAIR *pair)
594{
595 VALUE_PAIR *next;
596
597 while (pair != NULL)
598 {
599 next = pair->next;
600 free (pair);
601 pair = next;
602 }
603}
604
615static void rc_fieldcpy(char *string, char const **uptr, char const *stopat, size_t len)
616{
617 char const *ptr, *estring;
618
619 ptr = *uptr;
620 estring = string + len - 1;
621 if (*ptr == '"')
622 {
623 ptr++;
624 while (*ptr != '"' && *ptr != '\0' && *ptr != '\n')
625 {
626 if (string < estring)
627 *string++ = *ptr;
628 ptr++;
629 }
630 if (*ptr == '"')
631 {
632 ptr++;
633 }
634 *string = '\0';
635 *uptr = ptr;
636 return;
637 }
638
639 while (*ptr != '\0' && strchr(stopat, *ptr) == NULL)
640 {
641 if (string < estring)
642 *string++ = *ptr;
643 ptr++;
644 }
645 *string = '\0';
646 *uptr = ptr;
647 return;
648}
649
657int rc_avpair_parse (rc_handle const *rh, char const *buffer, VALUE_PAIR **first_pair)
658{
659 int mode;
660 char attrstr[AUTH_ID_LEN];
661 char valstr[AUTH_STRING_LEN + 1], *p;
662 DICT_ATTR *attr = NULL;
663 DICT_VALUE *dval;
664 VALUE_PAIR *pair;
665 VALUE_PAIR *link;
666 struct tm *tm, _tm;
667 time_t timeval;
668
669 mode = PARSE_MODE_NAME;
670 while (*buffer != '\n' && *buffer != '\0')
671 {
672 if (*buffer == ' ' || *buffer == '\t')
673 {
674 buffer++;
675 continue;
676 }
677
678 switch (mode)
679 {
680 case PARSE_MODE_NAME: /* Attribute Name */
681 rc_fieldcpy (attrstr, &buffer, " \t\n=,", sizeof(attrstr));
682 if ((attr =
683 rc_dict_findattr (rh, attrstr)) == NULL)
684 {
685 rc_log(LOG_ERR, "rc_avpair_parse: unknown attribute");
686 if (*first_pair) {
687 rc_avpair_free(*first_pair);
688 *first_pair = NULL;
689 }
690 return -1;
691 }
692 mode = PARSE_MODE_EQUAL;
693 break;
694
695 case PARSE_MODE_EQUAL: /* Equal sign */
696 if (*buffer == '=')
697 {
698 mode = PARSE_MODE_VALUE;
699 buffer++;
700 }
701 else
702 {
703 rc_log(LOG_ERR, "rc_avpair_parse: missing or misplaced equal sign");
704 if (*first_pair) {
705 rc_avpair_free(*first_pair);
706 *first_pair = NULL;
707 }
708 return -1;
709 }
710 break;
711
712 case PARSE_MODE_VALUE: /* Value */
713 rc_fieldcpy (valstr, &buffer, " \t\n,", sizeof(valstr));
714
715 if ((pair = malloc (sizeof (VALUE_PAIR))) == NULL)
716 {
717 rc_log(LOG_CRIT, "rc_avpair_parse: out of memory");
718 if (*first_pair) {
719 rc_avpair_free(*first_pair);
720 *first_pair = NULL;
721 }
722 return -1;
723 }
724 strlcpy (pair->name, attr->name, sizeof(pair->name));
725 pair->attribute = attr->value;
726 pair->type = attr->type;
727
728 switch (pair->type)
729 {
730
731 case PW_TYPE_STRING:
732 if (rc_avpair_assign(pair, valstr, strlen(valstr)) < 0) {
733 rc_log(LOG_ERR, "rc_avpair_parse: string value too long");
734 free(pair);
735 return -1;
736 }
737 break;
738
739 case PW_TYPE_INTEGER:
740 if (isdigit (*valstr))
741 {
742 pair->lvalue = atoi (valstr);
743 }
744 else
745 {
746 if ((dval = rc_dict_findval (rh, valstr))
747 == NULL)
748 {
749 rc_log(LOG_ERR, "rc_avpair_parse: unknown attribute value: %s", valstr);
750 if (*first_pair) {
751 rc_avpair_free(*first_pair);
752 *first_pair = NULL;
753 }
754 free (pair);
755 return -1;
756 }
757 else
758 {
759 pair->lvalue = dval->value;
760 }
761 }
762 break;
763
764 case PW_TYPE_IPADDR:
765 if (inet_pton(AF_INET, valstr, &pair->lvalue) == 0) {
766 rc_log(LOG_ERR, "rc_avpair_parse: invalid IPv4 address %s", valstr);
767 free(pair);
768 return -1;
769 }
770
771 pair->lvalue = ntohl(pair->lvalue);
772 break;
773
774 case PW_TYPE_IPV6ADDR:
775 if (inet_pton(AF_INET6, valstr, pair->strvalue) == 0) {
776 rc_log(LOG_ERR, "rc_avpair_parse: invalid IPv6 address %s", valstr);
777 free(pair);
778 return -1;
779 }
780 pair->lvalue = 16;
781 break;
782
784 p = strchr(valstr, '/');
785 if (p == NULL) {
786 rc_log(LOG_ERR, "rc_avpair_parse: invalid IPv6 prefix %s", valstr);
787 free(pair);
788 return -1;
789 }
790 *p = 0;
791 p++;
792 pair->strvalue[0] = 0;
793 pair->strvalue[1] = atoi(p);
794
795 if (inet_pton(AF_INET6, valstr, pair->strvalue+2) == 0) {
796 rc_log(LOG_ERR, "rc_avpair_parse: invalid IPv6 prefix %s", valstr);
797 free(pair);
798 return -1;
799 }
800 pair->lvalue = 2+16;
801 break;
802
803 case PW_TYPE_DATE:
804 timeval = time (0);
805 tm = localtime_r (&timeval, &_tm);
806 tm->tm_hour = 0;
807 tm->tm_min = 0;
808 tm->tm_sec = 0;
809 rc_str2tm (valstr, tm);
810 pair->lvalue = (uint32_t) mktime (tm);
811 break;
812
813 default:
814 rc_log(LOG_ERR, "rc_avpair_parse: unknown attribute type %d", pair->type);
815 if (*first_pair) {
816 rc_avpair_free(*first_pair);
817 *first_pair = NULL;
818 }
819 free (pair);
820 return -1;
821 }
822
823 /* XXX: Fix up Digest-Attributes */
824 switch (pair->attribute) {
825 case PW_DIGEST_REALM:
826 case PW_DIGEST_NONCE:
827 case PW_DIGEST_METHOD:
828 case PW_DIGEST_URI:
829 case PW_DIGEST_QOP:
832 case PW_DIGEST_CNONCE:
835 /* overlapping! */
836 if (pair->lvalue > AUTH_STRING_LEN - 2)
837 pair->lvalue = AUTH_STRING_LEN - 2;
838 memmove(&pair->strvalue[2], &pair->strvalue[0], pair->lvalue);
839 pair->strvalue[0] = pair->attribute - PW_DIGEST_REALM + 1;
840 pair->lvalue += 2;
841 pair->strvalue[1] = pair->lvalue;
842 pair->strvalue[pair->lvalue] = '\0';
844 break;
845 default:
846 break;
847 }
848
849 pair->next = NULL;
850
851 if (*first_pair == NULL)
852 {
853 *first_pair = pair;
854 }
855 else
856 {
857 link = *first_pair;
858 while (link->next != NULL)
859 {
860 link = link->next;
861 }
862 link->next = pair;
863 }
864
865 mode = PARSE_MODE_NAME;
866 break;
867
868 default:
869 mode = PARSE_MODE_NAME;
870 break;
871 }
872 }
873 return 0;
874}
875
886int rc_avpair_tostr (rc_handle const *rh, VALUE_PAIR *pair, char *name, int ln, char *value, int lv)
887{
888 DICT_VALUE *dval;
889 struct in_addr inad;
890 unsigned char *ptr;
891 unsigned int pos;
892 unsigned int slen;
893
894 *name = *value = '\0';
895
896 if (!pair || pair->name[0] == '\0') {
897 rc_log(LOG_ERR, "rc_avpair_tostr: pair is NULL or empty");
898 return -1;
899 }
900
901 strlcpy(name, pair->name, (size_t) ln);
902
903 switch (pair->type)
904 {
905 case PW_TYPE_STRING:
906 lv--;
907 pos = 0;
908 ptr = (unsigned char *) pair->strvalue;
909 if (pair->attribute == PW_DIGEST_ATTRIBUTES) {
910 slen = ptr[1] - 2;
911 ptr += 2;
912 } else {
913 slen = pair->lvalue;
914 }
915 while (slen-- > 0)
916 {
917 if (!(isprint (*ptr)))
918 {
919 if (lv >= 4) {
920 snprintf (&value[pos], lv, "\\%03o", *ptr);
921 pos += 4;
922 lv -= 4;
923 } else {
924 break;
925 }
926 }
927 else
928 {
929 if (lv > 0) {
930 value[pos++] = *ptr;
931 lv--;
932 } else {
933 break;
934 }
935 }
936 ptr++;
937 }
938 value[pos] = 0;
939 break;
940
941 case PW_TYPE_INTEGER:
942 dval = rc_dict_getval (rh, pair->lvalue, pair->name);
943 if (dval != NULL)
944 {
945 strlcpy(value, dval->name, (size_t) lv);
946 }
947 else
948 {
949 snprintf(value, lv, "%ld", (long int)pair->lvalue);
950 }
951 break;
952
953 case PW_TYPE_IPADDR:
954 inad.s_addr = htonl(pair->lvalue);
955 strlcpy (value, inet_ntoa (inad), (size_t) lv);
956 break;
957
958 case PW_TYPE_IPV6ADDR:
959 if (inet_ntop(AF_INET6, pair->strvalue, value, lv) == NULL)
960 return -1;
961 break;
962
963 case PW_TYPE_IPV6PREFIX: {
964 uint8_t ip[16];
965 uint8_t txt[48];
966 if (pair->lvalue < 2)
967 return -1;
968
969 memset(ip, 0, sizeof(ip));
970 memcpy(ip, pair->strvalue+2, pair->lvalue-2);
971
972 if (inet_ntop(AF_INET6, ip, (void*)txt, sizeof(txt)) == NULL)
973 return -1;
974 snprintf(value, lv, "%s/%u", txt, (unsigned)pair->strvalue[1]);
975
976 break;
977 }
978 case PW_TYPE_DATE: {
979 struct tm _tm;
980 struct tm *ptm = gmtime_r((time_t *) & pair->lvalue, &_tm);
981 if (ptm == NULL)
982 return -1;
983
984 strftime (value, lv, "%m/%d/%y %H:%M:%S", ptm);
985 break;
986 }
987
988 default:
989 rc_log(LOG_ERR, "rc_avpair_tostr: unknown attribute type %d", pair->type);
990 return -1;
991 break;
992 }
993
994 return 0;
995}
996
1007char *rc_avpair_log(rc_handle const *rh, VALUE_PAIR *pair, char *buf, size_t buf_len)
1008{
1009 size_t len, nlen;
1010 VALUE_PAIR *vp;
1011 char name[RC_NAME_LENGTH + 1], value[256];
1012
1013 len = 0;
1014 for (vp = pair; vp != NULL; vp = vp->next) {
1015 if (rc_avpair_tostr(rh, vp, name, sizeof(name), value,
1016 sizeof(value)) == -1)
1017 return NULL;
1018 nlen = len + 32 + 3 + strlen(value) + 2 + 2;
1019 if(nlen<buf_len-1) {
1020 sprintf(buf + len, "%-32s = '%s'\n", name, value);
1021 } else return buf;
1022 len = nlen - 1;
1023 }
1024 return buf;
1025}
1026
1037int rc_avpair_get_uint32 (VALUE_PAIR *vp, uint32_t *res)
1038{
1039 if (vp->type == PW_TYPE_DATE || vp->type == PW_TYPE_IPADDR ||
1040 vp->type == PW_TYPE_INTEGER) {
1041 if (res)
1042 *res = vp->lvalue;
1043 return 0;
1044 } else {
1045 return -1;
1046 }
1047}
1048
1058int rc_avpair_get_in6 (VALUE_PAIR *vp, struct in6_addr *res, unsigned *prefix)
1059{
1060 if (vp->type == PW_TYPE_IPV6ADDR) {
1061 memcpy(res, vp->strvalue, 16);
1062 return 0;
1063 } else if (vp->type == PW_TYPE_IPV6PREFIX) {
1064 if (vp->lvalue < 2 || vp->lvalue > 18)
1065 return -1;
1066
1067 if (res) {
1068 memset(res, 0, 16);
1069 memcpy(res, vp->strvalue+2, vp->lvalue-2);
1070 }
1071
1072 if (prefix)
1073 *prefix = (unsigned char)vp->strvalue[1];
1074 return 0;
1075 }
1076
1077 return -1;
1078}
1079
1090int rc_avpair_get_raw (VALUE_PAIR *vp, char **res, unsigned *res_size)
1091{
1092 if (vp->type == PW_TYPE_STRING || vp->type == PW_TYPE_IPV6ADDR ||
1093 vp->type == PW_TYPE_IPV6PREFIX) {
1094 if (res)
1095 *res = vp->strvalue;
1096 if (res_size)
1097 *res_size = vp->lvalue;
1098 return 0;
1099 } else {
1100 return -1;
1101 }
1102}
1103
1110void rc_avpair_get_attr (VALUE_PAIR *vp, unsigned *type, unsigned *id)
1111{
1112 if (type)
1113 *type = vp->type;
1114 if (id)
1115 *id = vp->attribute;
1116}
1117
1119/*
1120 * Local Variables:
1121 * c-basic-offset:8
1122 * c-style: whitesmith
1123 * End:
1124 */
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:1090
char * rc_avpair_log(rc_handle const *rh, VALUE_PAIR *pair, char *buf, size_t buf_len)
Definition avpair.c:1007
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:1037
int rc_avpair_get_in6(VALUE_PAIR *vp, struct in6_addr *res, unsigned *prefix)
Definition avpair.c:1058
void rc_avpair_get_attr(VALUE_PAIR *vp, unsigned *type, unsigned *id)
Definition avpair.c:1110
VALUE_PAIR * rc_avpair_gen(rc_handle const *rh, VALUE_PAIR *pair, unsigned char const *ptr, int length, uint32_t vendorspec)
Definition avpair.c:468
void rc_avpair_free(VALUE_PAIR *pair)
Definition avpair.c:593
VALUE_PAIR * rc_avpair_copy(VALUE_PAIR *p)
Definition avpair.c:506
int rc_avpair_tostr(rc_handle const *rh, VALUE_PAIR *pair, char *name, int ln, char *value, int lv)
Definition avpair.c:886
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:657
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:541
VALUE_PAIR * rc_avpair_get(VALUE_PAIR *vp, uint32_t attrid, uint32_t vendorspec)
Definition avpair.c:489
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:487
uint64_t attribute
attribute numeric value of type rc_attr_id including vendor; use VENDOR() and ATTRID() to separate.
Definition radcli.h:486
uint32_t lvalue
attribute value if type is PW_TYPE_INTEGER, PW_TYPE_DATE or PW_TYPE_IPADDR.
Definition radcli.h:488
char strvalue[AUTH_STRING_LEN+1]
contains attribute value in other cases.
Definition radcli.h:489
char name[RC_NAME_LENGTH+1]
attribute name if known.
Definition radcli.h:485