All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
radius_decode.c
Go to the documentation of this file.
1 /*
2  * This library is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU Lesser General Public
4  * License as published by the Free Software Foundation; either
5  * version 2.1 of the License, or (at your option) any later version.
6  *
7  * This library is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10  * Lesser General Public License for more details.
11  *
12  * You should have received a copy of the GNU Lesser General Public
13  * License along with this library; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15  */
16 
17 /**
18  * $Id: c87ff4b1f04cb96329c944ae24be01d04793f8da $
19  *
20  * @file radius.c
21  * @brief Functions to decode RADIUS attributes
22  *
23  * @copyright 2000-2003,2006-2015 The FreeRADIUS server project
24  */
25 #include <freeradius-devel/libradius.h>
26 #include <freeradius-devel/md5.h>
27 
28 static uint8_t nullvector[AUTH_VECTOR_LEN] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* for CoA decode */
29 
30 /** Decode Tunnel-Password encrypted attributes
31  *
32  * Defined in RFC-2868, this uses a two char SALT along with the
33  * initial intermediate value, to differentiate it from the
34  * above.
35  */
36 ssize_t fr_radius_decode_tunnel_password(uint8_t *passwd, size_t *pwlen, char const *secret, uint8_t const *vector)
37 {
38  FR_MD5_CTX context, old;
39  uint8_t digest[AUTH_VECTOR_LEN];
40  int secretlen;
41  size_t i, n, encrypted_len, embedded_len;
42 
43  encrypted_len = *pwlen;
44 
45  /*
46  * We need at least a salt.
47  */
48  if (encrypted_len < 2) {
49  fr_strerror_printf("Tunnel password is too short");
50  return -1;
51  }
52 
53  /*
54  * There's a salt, but no password. Or, there's a salt
55  * and a 'data_len' octet. It's wrong, but at least we
56  * can figure out what it means: the password is empty.
57  *
58  * Note that this means we ignore the 'data_len' field,
59  * if the attribute length tells us that there's no
60  * more data. So the 'data_len' field may be wrong,
61  * but that's ok...
62  */
63  if (encrypted_len <= 3) {
64  passwd[0] = 0;
65  *pwlen = 0;
66  return 0;
67  }
68 
69  encrypted_len -= 2; /* discount the salt */
70 
71  /*
72  * Use the secret to setup the decryption digest
73  */
74  secretlen = strlen(secret);
75 
76  fr_md5_init(&context);
77  fr_md5_update(&context, (uint8_t const *) secret, secretlen);
78  fr_md5_copy(&old, &context); /* save intermediate work */
79 
80  /*
81  * Set up the initial key:
82  *
83  * b(1) = MD5(secret + vector + salt)
84  */
85  fr_md5_update(&context, vector, AUTH_VECTOR_LEN);
86  fr_md5_update(&context, passwd, 2);
87 
88  embedded_len = 0;
89  for (n = 0; n < encrypted_len; n += AUTH_PASS_LEN) {
90  size_t base;
91  size_t block_len = AUTH_PASS_LEN;
92 
93  /*
94  * Ensure we don't overflow the input on MD5
95  */
96  if ((n + 2 + AUTH_PASS_LEN) > *pwlen) {
97  block_len = *pwlen - n - 2;
98  }
99 
100  if (n == 0) {
101  base = 1;
102 
103  fr_md5_final(digest, &context);
104  fr_md5_copy(&context, &old);
105 
106  /*
107  * A quick check: decrypt the first octet
108  * of the password, which is the
109  * 'data_len' field. Ensure it's sane.
110  */
111  embedded_len = passwd[2] ^ digest[0];
112  if (embedded_len > encrypted_len) {
113  fr_strerror_printf("Tunnel password is too long for the attribute");
114  return -1;
115  }
116 
117  fr_md5_update(&context, passwd + 2, block_len);
118 
119  } else {
120  base = 0;
121 
122  fr_md5_final(digest, &context);
123 
124  fr_md5_copy(&context, &old);
125  fr_md5_update(&context, passwd + n + 2, block_len);
126  }
127 
128  for (i = base; i < block_len; i++) {
129  passwd[n + i - 1] = passwd[n + i + 2] ^ digest[i];
130  }
131  }
132 
133  *pwlen = embedded_len;
134  passwd[embedded_len] = '\0';
135 
136  return embedded_len;
137 }
138 
139 /** Decode password
140  *
141  */
142 ssize_t fr_radius_decode_password(char *passwd, size_t pwlen, char const *secret, uint8_t const *vector)
143 {
144  FR_MD5_CTX context, old;
145  uint8_t digest[AUTH_VECTOR_LEN];
146  int i;
147  size_t n, secretlen;
148 
149  /*
150  * The RFC's say that the maximum is 128.
151  * The buffer we're putting it into above is 254, so
152  * we don't need to do any length checking.
153  */
154  if (pwlen > 128) pwlen = 128;
155 
156  /*
157  * Catch idiots.
158  */
159  if (pwlen == 0) goto done;
160 
161  /*
162  * Use the secret to setup the decryption digest
163  */
164  secretlen = strlen(secret);
165 
166  fr_md5_init(&context);
167  fr_md5_update(&context, (uint8_t const *) secret, secretlen);
168  fr_md5_copy(&old, &context); /* save intermediate work */
169 
170  /*
171  * The inverse of the code above.
172  */
173  for (n = 0; n < pwlen; n += AUTH_PASS_LEN) {
174  if (n == 0) {
175  fr_md5_update(&context, vector, AUTH_VECTOR_LEN);
176  fr_md5_final(digest, &context);
177 
178  fr_md5_copy(&context, &old);
179  if (pwlen > AUTH_PASS_LEN) {
180  fr_md5_update(&context, (uint8_t *) passwd, AUTH_PASS_LEN);
181  }
182  } else {
183  fr_md5_final(digest, &context);
184 
185  fr_md5_copy(&context, &old);
186  if (pwlen > (n + AUTH_PASS_LEN)) {
187  fr_md5_update(&context, (uint8_t *) passwd + n, AUTH_PASS_LEN);
188  }
189  }
190 
191  for (i = 0; i < AUTH_PASS_LEN; i++) passwd[i + n] ^= digest[i];
192  }
193 
194  done:
195  passwd[pwlen] = '\0';
196  return strlen(passwd);
197 }
198 
199 /** Check if a set of RADIUS formatted TLVs are OK
200  *
201  */
202 int fr_radius_decode_tlv_ok(uint8_t const *data, size_t length, size_t dv_type, size_t dv_length)
203 {
204  uint8_t const *end = data + length;
205 
206  FR_PROTO_TRACE("Checking TLV %u/%u", (unsigned int) dv_type, (unsigned int) dv_length);
207 
208  FR_PROTO_HEX_DUMP("tlv_ok", data, length);
209 
210  if ((dv_length > 2) || (dv_type == 0) || (dv_type > 4)) {
211  fr_strerror_printf("%s: Invalid arguments", __FUNCTION__);
212  return -1;
213  }
214 
215  while (data < end) {
216  size_t attrlen;
217 
218  if ((data + dv_type + dv_length) > end) {
219  fr_strerror_printf("Attribute header overflow");
220  return -1;
221  }
222 
223  switch (dv_type) {
224  case 4:
225  if ((data[0] == 0) && (data[1] == 0) &&
226  (data[2] == 0) && (data[3] == 0)) {
227  zero:
228  fr_strerror_printf("Invalid attribute 0");
229  return -1;
230  }
231 
232  if (data[0] != 0) {
233  fr_strerror_printf("Invalid attribute > 2^24");
234  return -1;
235  }
236  break;
237 
238  case 2:
239  if ((data[0] == 0) && (data[1] == 0)) goto zero;
240  break;
241 
242  case 1:
243  /*
244  * Zero is allowed, because the Colubris
245  * people are dumb and use it.
246  */
247  break;
248 
249  default:
250  fr_strerror_printf("Internal sanity check failed");
251  return -1;
252  }
253 
254  switch (dv_length) {
255  case 0:
256  return 0;
257 
258  case 2:
259  if (data[dv_type] != 0) {
260  fr_strerror_printf("Attribute is longer than 256 octets");
261  return -1;
262  }
263  /* FALL-THROUGH */
264  case 1:
265  attrlen = data[dv_type + dv_length - 1];
266  break;
267 
268 
269  default:
270  fr_strerror_printf("Internal sanity check failed");
271  return -1;
272  }
273 
274  if (attrlen < (dv_type + dv_length)) {
275  fr_strerror_printf("Attribute header has invalid length");
276  return -1;
277  }
278 
279  if (attrlen > length) {
280  fr_strerror_printf("Attribute overflows container");
281  return -1;
282  }
283 
284  data += attrlen;
285  length -= attrlen;
286  }
287 
288  return 0;
289 }
290 
291 /** Convert a "concatenated" attribute to one long VP
292  *
293  */
294 static ssize_t decode_concat(TALLOC_CTX *ctx, vp_cursor_t *cursor,
295  fr_dict_attr_t const *parent, uint8_t const *data,
296  size_t const packet_len)
297 {
298  size_t total;
299  uint8_t attr;
300  uint8_t const *ptr = data;
301  uint8_t const *end = data + packet_len;
302  uint8_t *p;
303  VALUE_PAIR *vp;
304 
305  total = 0;
306  attr = ptr[0];
307 
308  /*
309  * The packet has already been sanity checked, so we
310  * don't care about walking off of the end of it.
311  */
312  while (ptr < end) {
313  total += ptr[1] - 2;
314 
315  ptr += ptr[1];
316 
317  /*
318  * Attributes MUST be consecutive.
319  */
320  if (ptr[0] != attr) break;
321  }
322 
323  vp = fr_pair_afrom_da(ctx, parent);
324  if (!vp) return -1;
325 
326  p = talloc_array(vp, uint8_t, total);
327  if (!p) {
328  fr_pair_list_free(&vp);
329  return -1;
330  }
331  fr_pair_value_memsteal(vp, p);
332 
333  total = 0;
334  ptr = data;
335  while (total < vp->vp_length) {
336  memcpy(p, ptr + 2, ptr[1] - 2);
337  p += ptr[1] - 2;
338  total += ptr[1] - 2;
339  ptr += ptr[1];
340  }
341  fr_cursor_insert(cursor, vp);
342  return ptr - data;
343 }
344 
345 
346 /** Convert TLVs to one or more VPs
347  *
348  */
349 ssize_t fr_radius_decode_tlv(TALLOC_CTX *ctx, vp_cursor_t *cursor,
350  fr_dict_attr_t const *parent, uint8_t const *data, size_t data_len,
351  void *decoder_ctx)
352 {
353  uint8_t const *p = data, *end = data + data_len;
354  fr_dict_attr_t const *child;
355  VALUE_PAIR *head = NULL;
356  vp_cursor_t tlv_cursor;
357 
358  if (data_len < 3) return -1; /* type, length, value */
359 
360  FR_PROTO_HEX_DUMP("tlvs", p, data_len);
361 
362  if (fr_radius_decode_tlv_ok(p, data_len, 1, 1) < 0) return -1;
363 
364  /*
365  * Record where we were in the list when this function was called
366  */
367  fr_cursor_init(&tlv_cursor, &head);
368  while (p < end) {
369  ssize_t tlv_len;
370 
371  child = fr_dict_attr_child_by_num(parent, p[0]);
372  if (!child) {
373  fr_dict_attr_t *unknown_child;
374 
375  FR_PROTO_TRACE("Failed to find child %u of TLV %s", p[0], parent->name);
376 
377  /*
378  * Build an unknown attr
379  */
380  unknown_child = fr_dict_unknown_afrom_fields(ctx, parent, parent->vendor, p[0]);
381  if (!unknown_child) {
382  error:
383  fr_pair_list_free(&head);
384  return -1;
385  }
386  child = unknown_child;
387  }
388  FR_PROTO_TRACE("decode context changed %s -> %s", parent->name, child->name);
389 
390  tlv_len = fr_radius_decode_pair_value(ctx, &tlv_cursor, child, p + 2, p[1] - 2, p[1] - 2, decoder_ctx);
391  if (tlv_len < 0) goto error;
392  p += p[1];
393  }
394  fr_cursor_merge(cursor, head); /* Wind to the end of the new pairs */
395 
396  return data_len;
397 }
398 
399 /** Convert a top-level VSA to a VP.
400  *
401  * "length" can be LONGER than just this sub-vsa.
402  */
403 static ssize_t decode_vsa_internal(TALLOC_CTX *ctx, vp_cursor_t *cursor,
404  fr_dict_attr_t const *parent,
405  uint8_t const *data, size_t data_len,
406  void *decoder_ctx, fr_dict_vendor_t const *dv)
407 {
408  unsigned int attribute;
409  ssize_t attrlen, my_len;
410  fr_dict_attr_t const *da;
411 
412  /*
413  * Parent must be a vendor
414  */
415  if (!fr_assert(parent->type == PW_TYPE_VENDOR)) {
416  fr_strerror_printf("%s: Internal sanity check failed", __FUNCTION__);
417  return -1;
418  }
419 
420  FR_PROTO_TRACE("Length %u", (unsigned int)data_len);
421 
422 #ifndef NDEBUG
423  if (data_len <= (dv->type + dv->length)) {
424  fr_strerror_printf("%s: Failure to call fr_radius_decode_tlv_ok", __FUNCTION__);
425  return -1;
426  }
427 #endif
428 
429  switch (dv->type) {
430  case 4:
431  /* data[0] must be zero */
432  attribute = data[1] << 16;
433  attribute |= data[2] << 8;
434  attribute |= data[3];
435  break;
436 
437  case 2:
438  attribute = data[0] << 8;
439  attribute |= data[1];
440  break;
441 
442  case 1:
443  attribute = data[0];
444  break;
445 
446  default:
447  fr_strerror_printf("%s: Internal sanity check failed", __FUNCTION__);
448  return -1;
449  }
450 
451  switch (dv->length) {
452  case 2:
453  /* data[dv->type] must be zero, from fr_radius_decode_tlv_ok() */
454  attrlen = data[dv->type + 1];
455  break;
456 
457  case 1:
458  attrlen = data[dv->type];
459  break;
460 
461  case 0:
462  attrlen = data_len;
463  break;
464 
465  default:
466  fr_strerror_printf("%s: Internal sanity check failed", __FUNCTION__);
467  return -1;
468  }
469 
470  /*
471  * See if the VSA is known.
472  */
473  da = fr_dict_attr_child_by_num(parent, attribute);
474  if (!da) da = fr_dict_unknown_afrom_fields(ctx, parent, dv->vendorpec, attribute);
475  if (!da) return -1;
476  FR_PROTO_TRACE("decode context changed %s -> %s", da->parent->name, da->name);
477 
478  my_len = fr_radius_decode_pair_value(ctx, cursor, da, data + dv->type + dv->length,
479  attrlen - (dv->type + dv->length), attrlen - (dv->type + dv->length),
480  decoder_ctx);
481  if (my_len < 0) return my_len;
482 
483  return attrlen;
484 }
485 
486 
487 /** Convert a fragmented extended attr to a VP
488  *
489  * Format is:
490  *
491  * attr
492  * length
493  * extended-attr
494  * flag
495  * data...
496  *
497  * But for the first fragment, we get passed a pointer to the "extended-attr"
498  */
499 static ssize_t decode_extended(TALLOC_CTX *ctx, vp_cursor_t *cursor,
500  fr_dict_attr_t const *parent,
501  uint8_t const *data, size_t attr_len, size_t packet_len,
502  void *decoder_ctx)
503 {
504  ssize_t rcode;
505  size_t fraglen;
506  uint8_t *head, *tail;
507  uint8_t const *frag, *end;
508  uint8_t const *attr;
509  int fragments;
510  bool last_frag;
511 
512  if (attr_len < 3) return -1;
513 
514  /*
515  * Calculate the length of all of the fragments. For
516  * now, they MUST be contiguous in the packet, and they
517  * MUST be all of the same TYPE and EXTENDED-TYPE
518  */
519  attr = data - 2;
520  fraglen = attr_len - 2;
521  frag = data + attr_len;
522  end = data + packet_len;
523  fragments = 1;
524  last_frag = false;
525 
526  while (frag < end) {
527  if (last_frag ||
528  (frag[0] != attr[0]) ||
529  (frag[1] < 4) || /* too short for long-extended */
530  (frag[2] != attr[2]) ||
531  ((frag + frag[1]) > end)) { /* overflow */
532  end = frag;
533  break;
534  }
535 
536  last_frag = ((frag[3] & 0x80) == 0);
537 
538  fraglen += frag[1] - 4;
539  frag += frag[1];
540  fragments++;
541  }
542 
543  head = tail = talloc_array(ctx, uint8_t, fraglen);
544  if (!head) return -1;
545 
546  FR_PROTO_TRACE("Fragments %d, total length %d", fragments, (int) fraglen);
547 
548  /*
549  * And again, but faster and looser.
550  *
551  * We copy the first fragment, followed by the rest of
552  * the fragments.
553  */
554  frag = attr;
555 
556  while (fragments > 0) {
557  memcpy(tail, frag + 4, frag[1] - 4);
558  tail += frag[1] - 4;
559  frag += frag[1];
560  fragments--;
561  }
562 
563  FR_PROTO_HEX_DUMP("long-extended fragments", head, fraglen);
564 
565  rcode = fr_radius_decode_pair_value(ctx, cursor, parent, head, fraglen, fraglen, decoder_ctx);
566  talloc_free(head);
567  if (rcode < 0) return rcode;
568 
569  return end - data;
570 }
571 
572 /** Convert a Vendor-Specific WIMAX to vps
573  *
574  * @note Called ONLY for Vendor-Specific
575  */
576 static ssize_t decode_wimax(TALLOC_CTX *ctx, vp_cursor_t *cursor,
577  fr_dict_attr_t const *parent,
578  uint8_t const *data, size_t attr_len, size_t packet_len, void *decoder_ctx, uint32_t vendor)
579 {
580  ssize_t rcode;
581  size_t fraglen;
582  bool last_frag;
583  uint8_t *head, *tail;
584  uint8_t const *frag, *end;
585  fr_dict_attr_t const *da;
586 
587  if (attr_len < 8) return -1;
588 
589  if (((size_t) (data[5] + 4)) != attr_len) return -1;
590 
591  da = fr_dict_attr_child_by_num(parent, data[4]);
592  if (!da) da = fr_dict_unknown_afrom_fields(ctx, parent, vendor, data[4]);
593  if (!da) return -1;
594  FR_PROTO_TRACE("decode context changed %s -> %s", da->parent->name, da->name);
595 
596  if ((data[6] & 0x80) == 0) {
597  rcode = fr_radius_decode_pair_value(ctx, cursor, da, data + 7, data[5] - 3, data[5] - 3, decoder_ctx);
598  if (rcode < 0) return -1;
599  return 7 + rcode;
600  }
601 
602  /*
603  * Calculate the length of all of the fragments. For
604  * now, they MUST be contiguous in the packet, and they
605  * MUST be all of the same VSA, WiMAX, and WiMAX-attr.
606  *
607  * The first fragment doesn't have a RADIUS attribute
608  * header, so it needs to be treated a little special.
609  */
610  fraglen = data[5] - 3;
611  frag = data + attr_len;
612  end = data + packet_len;
613  last_frag = false;
614 
615  while (frag < end) {
616  if (last_frag ||
617  (frag[0] != PW_VENDOR_SPECIFIC) ||
618  (frag[1] < 9) || /* too short for wimax */
619  ((frag + frag[1]) > end) || /* overflow */
620  (memcmp(frag + 2, data, 4) != 0) || /* not wimax */
621  (frag[6] != data[4]) || /* not the same wimax attr */
622  ((frag[7] + 6) != frag[1])) { /* doesn't fill the attr */
623  end = frag;
624  break;
625  }
626 
627  last_frag = ((frag[8] & 0x80) == 0);
628 
629  fraglen += frag[7] - 3;
630  frag += frag[1];
631  }
632 
633  head = tail = talloc_array(ctx, uint8_t, fraglen);
634  if (!head) return -1;
635 
636  /*
637  * And again, but faster and looser.
638  *
639  * We copy the first fragment, followed by the rest of
640  * the fragments.
641  */
642  frag = data;
643 
644  memcpy(tail, frag + 4 + 3, frag[4 + 1] - 3);
645  tail += frag[4 + 1] - 3;
646  frag += attr_len; /* should be frag[1] - 7 */
647 
648  /*
649  * frag now points to RADIUS attributes
650  */
651  do {
652  memcpy(tail, frag + 2 + 4 + 3, frag[2 + 4 + 1] - 3);
653  tail += frag[2 + 4 + 1] - 3;
654  frag += frag[1];
655  } while (frag < end);
656 
657  FR_PROTO_HEX_DUMP("Wimax fragments", head, fraglen);
658 
659  rcode = fr_radius_decode_pair_value(ctx, cursor, da, head, fraglen, fraglen, decoder_ctx);
660  talloc_free(head);
661  if (rcode < 0) return rcode;
662 
663  return end - data;
664 }
665 
666 
667 /** Convert a top-level VSA to one or more VPs
668  *
669  */
670 static ssize_t decode_vsa(TALLOC_CTX *ctx, vp_cursor_t *cursor, fr_dict_attr_t const *parent,
671  uint8_t const *data, size_t attr_len, size_t packet_len,
672  void *decoder_ctx)
673 {
674  size_t total;
675  ssize_t rcode;
676  uint32_t vendor;
677  fr_dict_vendor_t const *dv;
678  VALUE_PAIR *head = NULL;
679  fr_dict_vendor_t my_dv;
680  fr_dict_attr_t const *vendor_da;
681  vp_cursor_t tlv_cursor;
682 
683  /*
684  * Container must be a VSA
685  */
686  if (!fr_assert(parent->type == PW_TYPE_VSA)) return -1;
687 
688  if (attr_len > packet_len) return -1;
689  if (attr_len < 5) return -1; /* vid, value */
690  if (data[0] != 0) return -1; /* we require 24-bit VIDs */
691 
692  FR_PROTO_TRACE("Decoding VSA");
693 
694  memcpy(&vendor, data, 4);
695  vendor = ntohl(vendor);
696 
697  /*
698  * Verify that the parent (which should be a VSA)
699  * contains a fake attribute representing the vendor.
700  *
701  * If it doesn't then this vendor is unknown, but
702  * (unlike DHCP) we know vendor attributes have a
703  * standard format, so we can decode the data anyway.
704  */
705  vendor_da = fr_dict_attr_child_by_num(parent, vendor);
706  if (!vendor_da) {
707  /*
708  * RFC format is 1 octet type, 1 octet length
709  */
710  if (fr_radius_decode_tlv_ok(data + 4, attr_len - 4, 1, 1) < 0) {
711  FR_PROTO_TRACE("Unknown TLVs not OK: %s", fr_strerror());
712  return -1;
713  }
714 
715  if (fr_dict_unknown_vendor_afrom_num(ctx, &vendor_da, parent, vendor) < 0) return -1;
716 
717  /*
718  * Create an unknown DV too...
719  */
720  memset(&my_dv, 0, sizeof(my_dv));
721 
722  my_dv.vendorpec = vendor;
723  my_dv.type = 1;
724  my_dv.length = 1;
725 
726  dv = &my_dv;
727 
728  goto create_attrs;
729  } else {
730  /*
731  * We found an attribute representing the vendor
732  * so it *MUST* exist in the vendor tree.
733  */
734  dv = fr_dict_vendor_by_num(NULL, vendor);
735  if (!fr_assert(dv)) return -1;
736  }
737  FR_PROTO_TRACE("decode context %s -> %s", parent->name, vendor_da->name);
738 
739  /*
740  * WiMAX craziness
741  */
742  if ((vendor == VENDORPEC_WIMAX) && dv->flags) {
743  rcode = decode_wimax(ctx, cursor, vendor_da, data, attr_len, packet_len, decoder_ctx, vendor);
744  return rcode;
745  }
746 
747  /*
748  * VSAs should normally be in TLV format.
749  */
750  if (fr_radius_decode_tlv_ok(data + 4, attr_len - 4, dv->type, dv->length) < 0) {
751  FR_PROTO_TRACE("TLVs not OK: %s", fr_strerror());
752  return -1;
753  }
754 
755  /*
756  * There may be more than one VSA in the
757  * Vendor-Specific. If so, loop over them all.
758  */
759 create_attrs:
760  data += 4;
761  attr_len -= 4;
762  packet_len -= 4;
763  total = 4;
764 
765  fr_cursor_init(&tlv_cursor, &head);
766  while (attr_len > 0) {
767  ssize_t vsa_len;
768 
769  /*
770  * Vendor attributes can have subattributes (if you hadn't guessed)
771  */
772  vsa_len = decode_vsa_internal(ctx, &tlv_cursor, vendor_da, data, attr_len, decoder_ctx, dv);
773  if (vsa_len < 0) {
774  fr_strerror_printf("%s: Internal sanity check %d", __FUNCTION__, __LINE__);
775  fr_pair_list_free(&head);
776  fr_dict_unknown_free(&vendor_da);
777  return -1;
778  }
779 
780  data += vsa_len;
781  attr_len -= vsa_len;
782  packet_len -= vsa_len;
783  total += vsa_len;
784  }
785  fr_cursor_merge(cursor, head);
786 
787  /*
788  * When the unknown attributes were created by
789  * decode_vsa_internal, the hierachy between that unknown
790  * attribute and first known attribute was cloned
791  * meaning we can now free the unknown vendor.
792  */
793  fr_dict_unknown_free(&vendor_da); /* Only frees unknown vendors */
794 
795  return total;
796 }
797 
798 /** Create any kind of VP from the attribute contents
799  *
800  * "length" is AT LEAST the length of this attribute, as we
801  * expect the caller to have verified the data with
802  * fr_radius_ok(). "length" may be up to the length of the
803  * packet.
804  *
805  * @return
806  * - Length on success.
807  * - -1 on failure.
808  */
809 ssize_t fr_radius_decode_pair_value(TALLOC_CTX *ctx, vp_cursor_t *cursor, fr_dict_attr_t const *parent,
810  uint8_t const *data, size_t const attr_len, size_t const packet_len,
811  void *decoder_ctx)
812 {
813  int8_t tag = TAG_NONE;
814  size_t datalen;
815  ssize_t rcode;
816  uint32_t vendor;
817  fr_dict_attr_t const *child;
818  VALUE_PAIR *vp;
819  uint8_t const *p = data;
820  uint8_t buffer[256];
821  fr_radius_ctx_t *this = decoder_ctx;
822 
823  /*
824  * FIXME: Attrlen can be larger than 253 for extended attrs!
825  */
826  if (!parent || (attr_len > packet_len) ||
827  ((attr_len > 253) && (attr_len != packet_len)) ||
828  (attr_len > 128 * 1024)) {
829  fr_strerror_printf("%s: Invalid arguments", __FUNCTION__);
830  return -1;
831  }
832 
833  FR_PROTO_HEX_DUMP(__FUNCTION__ , data, attr_len);
834 
835  FR_PROTO_TRACE("Parent %s len %zu ... %zu", parent->name, attr_len, packet_len);
836 
837  datalen = attr_len;
838 
839  /*
840  * Hacks for CUI. The WiMAX spec says that it can be
841  * zero length, even though this is forbidden by the
842  * RADIUS specs. So... we make a special case for it.
843  */
844  if (attr_len == 0) {
845  if (!((parent->vendor == 0) && (parent->attr == PW_CHARGEABLE_USER_IDENTITY))) return 0;
846 
847 #ifndef NDEBUG
848  /*
849  * Hacks for Coverity. Editing the dictionary
850  * will break assumptions about CUI. We know
851  * this, but Coverity doesn't.
852  */
853  if (parent->type != PW_TYPE_OCTETS) return -1;
854 #endif
855 
856  p = NULL;
857  datalen = 0;
858  goto alloc_cui; /* skip everything */
859  }
860 
861  /*
862  * Hacks for tags. If the attribute is capable of
863  * encoding a tag, and there's room for the tag, and
864  * there is a tag, or it's encrypted with Tunnel-Password,
865  * then decode the tag.
866  */
867  if (parent->flags.has_tag && (datalen > 1) && ((p[0] < 0x20) ||
868  (parent->flags.encrypt == FLAG_ENCRYPT_TUNNEL_PASSWORD))) {
869  /*
870  * Only "short" attributes can be encrypted.
871  */
872  if (datalen >= sizeof(buffer)) return -1;
873 
874  if (parent->type == PW_TYPE_STRING) {
875  memcpy(buffer, p + 1, datalen - 1);
876  tag = p[0];
877  datalen -= 1;
878 
879  } else if (parent->type == PW_TYPE_INTEGER) {
880  memcpy(buffer, p, attr_len);
881  tag = buffer[0];
882  buffer[0] = 0;
883 
884  } else {
885  return -1; /* only string and integer can have tags */
886  }
887 
888  p = buffer;
889  }
890 
891  /*
892  * Decrypt the attribute.
893  */
894  if (this && this->secret && this->packet && (parent->flags.encrypt != FLAG_ENCRYPT_NONE)) {
895  FR_PROTO_TRACE("Decrypting type %u", parent->flags.encrypt);
896  /*
897  * Encrypted attributes can only exist for the
898  * old-style format. Extended attributes CANNOT
899  * be encrypted.
900  */
901  if (attr_len > 253) return -1;
902 
903  if (p == data) memcpy(buffer, p, attr_len);
904  p = buffer;
905 
906  switch (parent->flags.encrypt) { /* can't be tagged */
907  /*
908  * User-Password
909  */
910  case FLAG_ENCRYPT_USER_PASSWORD:
911  if (this->original) {
912  fr_radius_decode_password((char *)buffer, attr_len,
913  this->secret, this->original->vector);
914  } else {
915  fr_radius_decode_password((char *)buffer, attr_len,
916  this->secret, this->packet->vector);
917  }
918  buffer[253] = '\0';
919 
920  /*
921  * MS-CHAP-MPPE-Keys are 24 octets, and
922  * encrypted. Since it's binary, we can't
923  * look for trailing zeros.
924  */
925  if (parent->flags.length) {
926  if (datalen > parent->flags.length) {
927  datalen = parent->flags.length;
928  } /* else leave datalen alone */
929  } else {
930  /*
931  * Take off trailing zeros from the END.
932  * This allows passwords to have zeros in
933  * the middle of a field.
934  *
935  * However, if the password has a zero at
936  * the end, it will get mashed by this
937  * code. There's really no way around
938  * that.
939  */
940  while ((datalen > 0) && (buffer[datalen - 1] == '\0')) datalen--;
941  }
942  break;
943 
944  /*
945  * Tunnel-Password's may go ONLY in response
946  * packets. They can have a tag, so datalen is
947  * not the same as attrlen.
948  */
949  case FLAG_ENCRYPT_TUNNEL_PASSWORD:
950  if (fr_radius_decode_tunnel_password(buffer, &datalen, this->secret,
951  this->original ? this->original->vector : nullvector) < 0) {
952  goto raw;
953  }
954  break;
955 
956  /*
957  * Ascend-Send-Secret
958  * Ascend-Receive-Secret
959  */
960  case FLAG_ENCRYPT_ASCEND_SECRET:
961  if (!this->original) goto raw;
962  else {
963  uint8_t my_digest[AUTH_VECTOR_LEN];
964  fr_radius_make_secret(my_digest, this->original->vector, this->secret, p);
965  memcpy(buffer, my_digest, AUTH_VECTOR_LEN );
966  buffer[AUTH_VECTOR_LEN] = '\0';
967  datalen = strlen((char *) buffer);
968  }
969  break;
970 
971  default:
972  /*
973  * Chop the attribute to its maximum length.
974  */
975  if ((parent->type == PW_TYPE_OCTETS) &&
976  (parent->flags.length && (datalen > parent->flags.length))) {
977  datalen = parent->flags.length;
978  }
979  break;
980  } /* switch over encryption flags */
981  }
982 
983  /*
984  * Double-check the length after decrypting the
985  * attribute.
986  */
987  FR_PROTO_TRACE("Type \"%s\" (%u)", fr_int2str(dict_attr_types, parent->type, "?Unknown?"), parent->type);
988  switch (parent->type) {
989  case PW_TYPE_STRING:
990  case PW_TYPE_OCTETS:
991  break;
992 
993  case PW_TYPE_ABINARY:
994  if (datalen > sizeof(vp->vp_filter)) goto raw;
995  break;
996 
997  case PW_TYPE_INTEGER:
998  case PW_TYPE_IPV4_ADDR:
999  case PW_TYPE_DATE:
1000  case PW_TYPE_SIGNED:
1001  if (datalen != 4) goto raw;
1002  break;
1003 
1004  case PW_TYPE_INTEGER64:
1005  case PW_TYPE_IFID:
1006  if (datalen != 8) goto raw;
1007  break;
1008 
1009  case PW_TYPE_IPV6_ADDR:
1010  if (datalen != 16) goto raw;
1011  break;
1012 
1013  case PW_TYPE_IPV6_PREFIX:
1014  if ((datalen < 2) || (datalen > 18)) goto raw;
1015  if (p[1] > 128) goto raw;
1016  break;
1017 
1018  case PW_TYPE_BYTE:
1019  if (datalen != 1) goto raw;
1020  break;
1021 
1022  case PW_TYPE_SHORT:
1023  if (datalen != 2) goto raw;
1024  break;
1025 
1026  case PW_TYPE_ETHERNET:
1027  if (datalen != 6) goto raw;
1028  break;
1029 
1030  case PW_TYPE_COMBO_IP_ADDR:
1031  if (datalen == 4) {
1032  child = fr_dict_attr_by_type(NULL, parent->vendor, parent->attr, PW_TYPE_IPV4_ADDR);
1033  } else if (datalen == 16) {
1034  child = fr_dict_attr_by_type(NULL, parent->vendor, parent->attr, PW_TYPE_IPV6_ADDR);
1035  } else {
1036  goto raw;
1037  }
1038  if (!child) goto raw;
1039  parent = child; /* re-write it */
1040  break;
1041 
1042  case PW_TYPE_IPV4_PREFIX:
1043  if (datalen != 6) goto raw;
1044  if ((p[1] & 0x3f) > 32) goto raw;
1045  break;
1046 
1047  /*
1048  * The rest of the p types can cause
1049  * recursion! Ask yourself, "is recursion OK?"
1050  */
1051 
1052  case PW_TYPE_EXTENDED:
1053  if (datalen < 2) goto raw; /* etype, value */
1054 
1055  child = fr_dict_attr_child_by_num(parent, p[0]);
1056  if (!child) goto raw;
1057  FR_PROTO_TRACE("decode context changed %s->%s", child->name, parent->name);
1058 
1059  /*
1060  * Recurse to decode the contents, which could be
1061  * a TLV, IPaddr, etc. Note that we decode only
1062  * the current attribute, and we ignore any extra
1063  * p after it.
1064  */
1065  rcode = fr_radius_decode_pair_value(ctx, cursor, child, p + 1, attr_len - 1, attr_len - 1,
1066  decoder_ctx);
1067  if (rcode < 0) goto raw;
1068  return 1 + rcode;
1069 
1070  case PW_TYPE_LONG_EXTENDED:
1071  if (datalen < 3) goto raw; /* etype, flags, value */
1072 
1073  child = fr_dict_attr_child_by_num(parent, p[0]);
1074  if (!child) {
1075  fr_dict_attr_t *new;
1076 
1077  if ((p[0] != PW_VENDOR_SPECIFIC) || (datalen < (3 + 4 + 1))) {
1078  /* da->attr < 255, da->vendor == 0 */
1079  new = fr_dict_unknown_afrom_fields(ctx, parent, 0, p[0]);
1080  } else {
1081  /*
1082  * Try to find the VSA.
1083  */
1084  memcpy(&vendor, p + 3, 4);
1085  vendor = ntohl(vendor);
1086 
1087  if (vendor == 0) goto raw;
1088 
1089  new = fr_dict_unknown_afrom_fields(ctx, parent, vendor, p[7]);
1090  }
1091  child = new;
1092 
1093  if (!child) {
1094  fr_strerror_printf("%s: Internal sanity check %d", __FUNCTION__, __LINE__);
1095  return -1;
1096  }
1097  }
1098  FR_PROTO_TRACE("decode context changed %s -> %s", parent->name, child->name);
1099 
1100  /*
1101  * If there no more fragments, then the contents
1102  * have to be a well-known p type.
1103  *
1104  */
1105  if ((p[1] & 0x80) == 0) {
1106  rcode = fr_radius_decode_pair_value(ctx, cursor, child, p + 2, attr_len - 2, attr_len - 2,
1107  decoder_ctx);
1108  if (rcode < 0) goto raw;
1109  return 2 + rcode;
1110  }
1111 
1112  /*
1113  * This requires a whole lot more work.
1114  */
1115  return decode_extended(ctx, cursor, child, data, attr_len, packet_len, decoder_ctx);
1116 
1117  case PW_TYPE_EVS:
1118  {
1119  fr_dict_attr_t const *vendor_child;
1120 
1121  if (datalen < 6) goto raw; /* vid, vtype, value */
1122 
1123  memcpy(&vendor, p, 4);
1124  vendor = ntohl(vendor);
1125 
1126  /*
1127  * For simplicity in our attribute tree, vendors are
1128  * represented as a subtlv(ish) of an EVS or VSA
1129  * attribute.
1130  */
1131  vendor_child = fr_dict_attr_child_by_num(parent, vendor);
1132  if (!vendor_child) {
1133  /*
1134  * If there's no child, it means the vendor is unknown
1135  * which means the child attribute is unknown too.
1136  *
1137  * fr_dict_unknown_afrom_fields will do the right thing
1138  * and create both an unknown vendor and an unknown
1139  * attr.
1140  *
1141  * This can be used later by the encoder to rebuild
1142  * the attribute header.
1143  */
1144  parent = fr_dict_unknown_afrom_fields(ctx, parent, vendor, p[4]);
1145  p += 5;
1146  datalen -= 5;
1147  break;
1148  }
1149 
1150  child = fr_dict_attr_child_by_num(vendor_child, p[4]);
1151  if (!child) {
1152  /*
1153  * Vendor exists but child didn't, again
1154  * fr_dict_unknown_afrom_fields will do the right thing
1155  * and only create the unknown attr.
1156  */
1157  parent = fr_dict_unknown_afrom_fields(ctx, parent, vendor, p[4]);
1158  p += 5;
1159  datalen -= 5;
1160  break;
1161  }
1162 
1163  /*
1164  * Everything was found in the dictionary, we can
1165  * now recurse to decode the value.
1166  */
1167  rcode = fr_radius_decode_pair_value(ctx, cursor, child, p + 5, attr_len - 5, attr_len - 5,
1168  decoder_ctx);
1169  if (rcode < 0) goto raw;
1170  return 5 + rcode;
1171  }
1172 
1173  case PW_TYPE_TLV:
1174  /*
1175  * We presume that the TLVs all fit into one
1176  * attribute, OR they've already been grouped
1177  * into a contiguous memory buffer.
1178  */
1179  rcode = fr_radius_decode_tlv(ctx, cursor, parent, p, attr_len, decoder_ctx);
1180  if (rcode < 0) goto raw;
1181  return rcode;
1182 
1183  case PW_TYPE_VSA:
1184  /*
1185  * VSAs can be WiMAX, in which case they don't
1186  * fit into one attribute.
1187  */
1188  rcode = decode_vsa(ctx, cursor, parent, p, attr_len, packet_len, decoder_ctx);
1189  if (rcode < 0) goto raw;
1190  return rcode;
1191 
1192  default:
1193  raw:
1194  /*
1195  * Re-write the attribute to be "raw". It is
1196  * therefore of type "octets", and will be
1197  * handled below.
1198  */
1199  parent = fr_dict_unknown_afrom_fields(ctx, parent->parent, parent->vendor, parent->attr);
1200  if (!parent) {
1201  fr_strerror_printf("%s: Internal sanity check %d", __FUNCTION__, __LINE__);
1202  return -1;
1203  }
1204  tag = TAG_NONE;
1205 #ifndef NDEBUG
1206  /*
1207  * Fix for Coverity.
1208  */
1209  if (parent->type != PW_TYPE_OCTETS) {
1210  fr_dict_unknown_free(&parent);
1211  return -1;
1212  }
1213 #endif
1214  break;
1215  }
1216 
1217  /*
1218  * And now that we've verified the basic type
1219  * information, decode the actual p.
1220  */
1221  alloc_cui:
1222  vp = fr_pair_afrom_da(ctx, parent);
1223  if (!vp) return -1;
1224 
1225  vp->vp_length = datalen;
1226  vp->tag = tag;
1227 
1228  switch (parent->type) {
1229  case PW_TYPE_STRING:
1230  fr_pair_value_bstrncpy(vp, p, datalen);
1231  break;
1232 
1233  case PW_TYPE_OCTETS:
1234  fr_pair_value_memcpy(vp, p, datalen);
1235  break;
1236 
1237  case PW_TYPE_ABINARY:
1238  if (vp->vp_length > sizeof(vp->vp_filter)) {
1239  vp->vp_length = sizeof(vp->vp_filter);
1240  }
1241  memcpy(vp->vp_filter, p, vp->vp_length);
1242  break;
1243 
1244  case PW_TYPE_BYTE:
1245  vp->vp_byte = p[0];
1246  break;
1247 
1248  case PW_TYPE_SHORT:
1249  vp->vp_short = (p[0] << 8) | p[1];
1250  break;
1251 
1252  case PW_TYPE_INTEGER:
1253  memcpy(&vp->vp_integer, p, 4);
1254  vp->vp_integer = ntohl(vp->vp_integer);
1255  break;
1256 
1257  case PW_TYPE_INTEGER64:
1258  memcpy(&vp->vp_integer64, p, 8);
1259  vp->vp_integer64 = ntohll(vp->vp_integer64);
1260  break;
1261 
1262  case PW_TYPE_DATE:
1263  memcpy(&vp->vp_date, p, 4);
1264  vp->vp_date = ntohl(vp->vp_date);
1265  break;
1266 
1267  case PW_TYPE_ETHERNET:
1268  memcpy(vp->vp_ether, p, 6);
1269  break;
1270 
1271  case PW_TYPE_IPV4_ADDR:
1272  memcpy(&vp->vp_ipaddr, p, 4);
1273  break;
1274 
1275  case PW_TYPE_IFID:
1276  memcpy(vp->vp_ifid, p, 8);
1277  break;
1278 
1279  case PW_TYPE_IPV6_ADDR:
1280  memcpy(&vp->vp_ipv6addr, p, 16);
1281  break;
1282 
1283  case PW_TYPE_IPV6_PREFIX:
1284  /*
1285  * FIXME: double-check that
1286  * (vp->vp_octets[1] >> 3) matches vp->vp_length + 2
1287  */
1288  memcpy(vp->vp_ipv6prefix, p, vp->vp_length);
1289  if (vp->vp_length < 18) {
1290  memset(((uint8_t *)vp->vp_ipv6prefix) + vp->vp_length, 0,
1291  18 - vp->vp_length);
1292  }
1293  break;
1294 
1295  case PW_TYPE_IPV4_PREFIX:
1296  /* FIXME: do the same double-check as for IPv6Prefix */
1297  memcpy(vp->vp_ipv4prefix, p, vp->vp_length);
1298 
1299  /*
1300  * /32 means "keep all bits". Otherwise, mask
1301  * them out.
1302  */
1303  if ((p[1] & 0x3f) > 32) {
1304  uint32_t addr, mask;
1305 
1306  memcpy(&addr, vp->vp_octets + 2, sizeof(addr));
1307  mask = 1;
1308  mask <<= (32 - (p[1] & 0x3f));
1309  mask--;
1310  mask = ~mask;
1311  mask = htonl(mask);
1312  addr &= mask;
1313  memcpy(vp->vp_ipv4prefix + 2, &addr, sizeof(addr));
1314  }
1315  break;
1316 
1317  case PW_TYPE_SIGNED: /* overloaded with vp_integer */
1318  memcpy(&vp->vp_integer, p, 4);
1319  vp->vp_integer = ntohl(vp->vp_integer);
1320  break;
1321 
1322  default:
1323  fr_pair_list_free(&vp);
1324  fr_strerror_printf("%s: Internal sanity check %d", __FUNCTION__, __LINE__);
1325  return -1;
1326  }
1327  vp->type = VT_DATA;
1328  fr_cursor_insert(cursor, vp);
1329 
1330  return attr_len;
1331 }
1332 
1333 
1334 /** Create a "normal" VALUE_PAIR from the given data
1335  *
1336  */
1337 ssize_t fr_radius_decode_pair(TALLOC_CTX *ctx, vp_cursor_t *cursor, fr_dict_attr_t const *parent,
1338  uint8_t const *data, size_t data_len,
1339  void *decoder_ctx)
1340 {
1341  ssize_t rcode;
1342 
1343  fr_dict_attr_t const *da;
1344 
1345  if ((data_len < 2) || (data[1] < 2) || (data[1] > data_len)) {
1346  fr_strerror_printf("%s: Insufficient data", __FUNCTION__);
1347  return -1;
1348  }
1349 
1350  da = fr_dict_attr_child_by_num(parent, data[0]);
1351  if (!da) {
1352  FR_PROTO_TRACE("Unknown attribute %u", data[0]);
1353  da = fr_dict_unknown_afrom_fields(ctx, parent, 0, data[0]);
1354  }
1355  if (!da) return -1;
1356  FR_PROTO_TRACE("decode context changed %s -> %s",da->parent->name, da->name);
1357 
1358  /*
1359  * Pass the entire thing to the decoding function
1360  */
1361  if (da->flags.concat) {
1362  FR_PROTO_TRACE("Concat attribute");
1363  return decode_concat(ctx, cursor, da, data, data_len);
1364  }
1365 
1366  /*
1367  * Note that we pass the entire length, not just the
1368  * length of this attribute. The Extended or WiMAX
1369  * attributes may have the "continuation" bit set, and
1370  * will thus be more than one attribute in length.
1371  */
1372  rcode = fr_radius_decode_pair_value(ctx, cursor, da, data + 2, data[1] - 2, data_len - 2, decoder_ctx);
1373  if (rcode < 0) return rcode;
1374 
1375  return 2 + rcode;
1376 }
void fr_pair_list_free(VALUE_PAIR **)
Free memory used by a valuepair list.
Definition: pair.c:544
fr_dict_attr_t const * fr_dict_attr_child_by_num(fr_dict_attr_t const *parent, unsigned int attr)
Check if a child attribute exists in a parent using an attribute number.
Definition: dict.c:3611
VALUE_PAIR has a single value.
Definition: pair.h:101
void fr_dict_unknown_free(fr_dict_attr_t const **da)
Free dynamically allocated (unknown attributes)
Definition: dict.c:2426
128 Bit IPv6 Address.
Definition: radius.h:40
fr_dict_attr_t * fr_dict_unknown_afrom_fields(TALLOC_CTX *ctx, fr_dict_attr_t const *parent, unsigned int vendor, unsigned int attr) CC_HINT(nonnull)
Allocates an unknown attribute.
Definition: dict.c:2613
static uint8_t nullvector[AUTH_VECTOR_LEN]
Definition: radius_decode.c:28
Dictionary attribute.
Definition: dict.h:77
Ascend binary format a packed data structure.
Definition: radius.h:37
32 Bit signed integer.
Definition: radius.h:45
WiMAX IPv4 or IPv6 address depending on length.
Definition: radius.h:46
uint8_t length
length of the attribute
Definition: dict.h:64
size_t length
Length of length data.
Definition: dict.h:105
void fr_radius_make_secret(uint8_t *digest, uint8_t const *vector, char const *secret, uint8_t const *value)
Build an encrypted secret value to return in a reply packet.
Definition: radius.c:272
int8_t tag
Tag value used to group valuepairs.
Definition: pair.h:121
void fr_md5_init(FR_MD5_CTX *ctx)
Initialise a new MD5 context.
Definition: md5.c:84
IPv6 Prefix.
Definition: radius.h:41
VALUE_PAIR * fr_cursor_init(vp_cursor_t *cursor, VALUE_PAIR *const *node)
Setup a cursor to iterate over attribute pairs.
Definition: cursor.c:60
size_t flags
Vendor flags.
Definition: dict.h:106
uint8_t length
Definition: proto_bfd.c:203
Long extended attribute space attribute.
Definition: radius.h:49
ssize_t fr_radius_decode_tlv(TALLOC_CTX *ctx, vp_cursor_t *cursor, fr_dict_attr_t const *parent, uint8_t const *data, size_t data_len, void *decoder_ctx)
Convert TLVs to one or more VPs.
Abstraction to allow iterating over different configurations of VALUE_PAIRs.
Definition: pair.h:144
fr_dict_attr_flags_t flags
Flags.
Definition: dict.h:88
fr_dict_vendor_t const * fr_dict_vendor_by_num(fr_dict_t *dict, int vendor)
Look up a vendor by its PEN.
Definition: dict.c:3412
void fr_md5_update(FR_MD5_CTX *ctx, uint8_t const *in, size_t inlen) CC_BOUNDED(__string__
static ssize_t decode_vsa_internal(TALLOC_CTX *ctx, vp_cursor_t *cursor, fr_dict_attr_t const *parent, uint8_t const *data, size_t data_len, void *decoder_ctx, fr_dict_vendor_t const *dv)
Convert a top-level VSA to a VP.
8 Bit unsigned integer.
Definition: radius.h:42
#define AUTH_VECTOR_LEN
Definition: libradius.h:118
#define AUTH_PASS_LEN
Definition: libradius.h:230
void fr_cursor_merge(vp_cursor_t *cursor, VALUE_PAIR *vp)
Merges multiple VALUE_PAIR into the cursor.
Definition: cursor.c:394
static uint32_t mask
Definition: rbmonkey.c:75
static ssize_t decode_extended(TALLOC_CTX *ctx, vp_cursor_t *cursor, fr_dict_attr_t const *parent, uint8_t const *data, size_t attr_len, size_t packet_len, void *decoder_ctx)
Convert a fragmented extended attr to a VP.
Interface ID.
Definition: radius.h:39
void fr_cursor_insert(vp_cursor_t *cursor, VALUE_PAIR *vp)
Insert a single VALUE_PAIR at the end of the list.
Definition: cursor.c:321
const FR_NAME_NUMBER dict_attr_types[]
Map data types to names representing those types.
Definition: dict.c:85
unsigned int attr
Attribute number.
Definition: dict.h:79
static bool done
Definition: radclient.c:53
ssize_t fr_radius_decode_password(char *passwd, size_t pwlen, char const *secret, uint8_t const *vector)
Decode password.
#define FR_PROTO_TRACE(_x,...)
Definition: proto.h:36
#define fr_assert(_x)
Definition: libradius.h:505
unsigned int vendor
Vendor that defines this attribute.
Definition: dict.h:78
48 Bit Mac-Address.
Definition: radius.h:44
Stores an attribute, a value and various bits of other data.
Definition: pair.h:112
fr_dict_attr_t const * parent
Immediate parent of this attribute.
Definition: dict.h:82
enum attr_flags::@0 encrypt
Attribute that represents a vendor in the attribute tree.
Definition: radius.h:54
unsigned int concat
concatenate multiple instances
Definition: dict.h:50
static ssize_t decode_wimax(TALLOC_CTX *ctx, vp_cursor_t *cursor, fr_dict_attr_t const *parent, uint8_t const *data, size_t attr_len, size_t packet_len, void *decoder_ctx, uint32_t vendor)
Convert a Vendor-Specific WIMAX to vps.
32 Bit unsigned integer.
Definition: radius.h:34
char const * fr_strerror(void)
Get the last library error.
Definition: log.c:212
#define FR_PROTO_HEX_DUMP(_x, _y, _z)
Definition: proto.h:37
Private enterprise.
Definition: dict.h:102
64 Bit unsigned integer.
Definition: radius.h:51
fr_dict_attr_t const * fr_dict_attr_by_type(fr_dict_t *dict, unsigned int vendor, unsigned int attr, PW_TYPE type)
Lookup a attribute by its its vendor and attribute numbers and data type.
Definition: dict.c:3549
Vendor-Specific, for RADIUS attribute 26.
Definition: radius.h:53
char name[1]
Attribute name.
Definition: dict.h:89
uint8_t data[]
Definition: eap_pwd.h:625
void fr_pair_value_memsteal(VALUE_PAIR *vp, uint8_t const *src)
Reparent an allocated octet buffer to a VALUE_PAIR.
Definition: pair.c:1933
value_type_t type
Type of pointer in value union.
Definition: pair.h:132
32 Bit Unix timestamp.
Definition: radius.h:36
Extended attribute space attribute.
Definition: radius.h:48
#define fr_md5_copy(_out, _in)
Definition: md5.h:69
static ssize_t decode_vsa(TALLOC_CTX *ctx, vp_cursor_t *cursor, fr_dict_attr_t const *parent, uint8_t const *data, size_t attr_len, size_t packet_len, void *decoder_ctx)
Convert a top-level VSA to one or more VPs.
ssize_t fr_radius_decode_pair_value(TALLOC_CTX *ctx, vp_cursor_t *cursor, fr_dict_attr_t const *parent, uint8_t const *data, size_t const attr_len, size_t const packet_len, void *decoder_ctx)
Create any kind of VP from the attribute contents.
int fr_radius_decode_tlv_ok(uint8_t const *data, size_t length, size_t dv_type, size_t dv_length)
Check if a set of RADIUS formatted TLVs are OK.
unsigned int vendorpec
Private enterprise number.
Definition: dict.h:103
static char const * secret
Definition: radclient.c:44
void fr_strerror_printf(char const *,...) CC_HINT(format(printf
unsigned int has_tag
Tagged attribute.
Definition: dict.h:46
static ssize_t decode_concat(TALLOC_CTX *ctx, vp_cursor_t *cursor, fr_dict_attr_t const *parent, uint8_t const *data, size_t const packet_len)
Convert a "concatenated" attribute to one long VP.
int fr_dict_unknown_vendor_afrom_num(TALLOC_CTX *ctx, fr_dict_attr_t const **out, fr_dict_attr_t const *parent, unsigned int vendor)
Build an unknown vendor, parented by a VSA or EVS attribute.
Definition: dict.c:2459
size_t type
Length of type data.
Definition: dict.h:104
IPv4 Prefix.
Definition: radius.h:52
#define TAG_NONE
Definition: pair.h:192
ssize_t fr_radius_decode_pair(TALLOC_CTX *ctx, vp_cursor_t *cursor, fr_dict_attr_t const *parent, uint8_t const *data, size_t data_len, void *decoder_ctx)
Create a "normal" VALUE_PAIR from the given data.
void void fr_md5_final(uint8_t out[MD5_DIGEST_LENGTH], FR_MD5_CTX *ctx) CC_BOUNDED(__minbytes__
VALUE_PAIR * fr_pair_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
Dynamically allocate a new attribute.
Definition: pair.c:58
char const * fr_int2str(FR_NAME_NUMBER const *table, int number, char const *def)
Definition: token.c:506
void fr_pair_value_bstrncpy(VALUE_PAIR *vp, void const *src, size_t len)
Copy data into an "string" data type.
Definition: pair.c:2043
String of printable characters.
Definition: radius.h:33
Contains nested attributes.
Definition: radius.h:47
#define vp_length
Definition: pair.h:182
PW_TYPE type
Value type.
Definition: dict.h:80
ssize_t fr_radius_decode_tunnel_password(uint8_t *passwd, size_t *pwlen, char const *secret, uint8_t const *vector)
Decode Tunnel-Password encrypted attributes.
Definition: radius_decode.c:36
32 Bit IPv4 Address.
Definition: radius.h:35
16 Bit unsigned integer.
Definition: radius.h:43
Raw octets.
Definition: radius.h:38
void fr_pair_value_memcpy(VALUE_PAIR *vp, uint8_t const *src, size_t len)
Copy data into an "octets" data type.
Definition: pair.c:1905
#define VENDORPEC_WIMAX
Definition: radius.h:202
Extended attribute, vendor specific.
Definition: radius.h:50