The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
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: b7f3826f8b5e98db220c85f768f02ce890fc6f3a $
19 *
20 * @file protocols/radius/decode.c
21 * @brief Functions to decode RADIUS attributes
22 *
23 * @copyright 2000-2003,2006-2015 The FreeRADIUS server project
24 */
25RCSID("$Id: b7f3826f8b5e98db220c85f768f02ce890fc6f3a $")
26
27#include <freeradius-devel/util/md5.h>
28#include <freeradius-devel/util/struct.h>
29#include <freeradius-devel/io/test_point.h>
30#include <freeradius-devel/protocol/radius/freeradius.internal.h>
31
32#include "attrs.h"
33
34/*
35 * For all of the concat/extended attributes.
36 */
37#include <freeradius-devel/protocol/radius/rfc2869.h>
38#include <freeradius-devel/protocol/radius/rfc5904.h>
39#include <freeradius-devel/protocol/radius/rfc6929.h>
40#include <freeradius-devel/protocol/radius/rfc7268.h>
41
42static void memcpy_bounded(void * restrict dst, const void * restrict src, size_t n, const void * restrict end)
43{
44 size_t len = n;
45
46 if (!fr_cond_assert(n <= 65535)) {
47 return;
48 }
49
50 if (!fr_cond_assert(src <= end)) {
51 return;
52 }
53
54 if (len == 0) return;
55
56 if (!fr_cond_assert(((uint8_t const * restrict) src + len) <= (uint8_t const * restrict) end)) {
57 len = (uint8_t const * restrict) end - (uint8_t const * restrict) src;
58 }
59
60 memcpy(dst, src, len);
61}
62
63
64/** Decode Tunnel-Password encrypted attributes
65 *
66 * Defined in RFC-2868, this uses a two char SALT along with the
67 * initial intermediate value, to differentiate it from the
68 * above.
69 */
71{
72 fr_md5_ctx_t *md5_ctx, *md5_ctx_old;
74 size_t i, n, encrypted_len, embedded_len;
75
76 encrypted_len = *pwlen;
77
78 /*
79 * We need at least a salt.
80 */
81 if (encrypted_len < 2) {
82 fr_strerror_const("Tunnel password is too short");
83 return -1;
84 }
85
86 /*
87 * There's a salt, but no password. Or, there's a salt
88 * and a 'data_len' octet. It's wrong, but at least we
89 * can figure out what it means: the password is empty.
90 *
91 * Note that this means we ignore the 'data_len' field,
92 * if the attribute length tells us that there's no
93 * more data. So the 'data_len' field may be wrong,
94 * but that's ok...
95 */
96 if (encrypted_len <= 3) {
97 passwd[0] = 0;
98 *pwlen = 0;
99 return 0;
100 }
101
102 encrypted_len -= 2; /* discount the salt */
103
104 md5_ctx = fr_md5_ctx_alloc_from_list();
105 md5_ctx_old = fr_md5_ctx_alloc_from_list();
106
107 fr_md5_update(md5_ctx, (uint8_t const *) packet_ctx->common->secret, packet_ctx->common->secret_length);
108 fr_md5_ctx_copy(md5_ctx_old, md5_ctx); /* save intermediate work */
109
110 /*
111 * Set up the initial key:
112 *
113 * b(1) = MD5(secret + vector + salt)
114 */
116 fr_md5_update(md5_ctx, passwd, 2);
117
118 embedded_len = 0;
119 for (n = 0; n < encrypted_len; n += AUTH_PASS_LEN) {
120 size_t base;
121 size_t block_len = AUTH_PASS_LEN;
122
123 /*
124 * Ensure we don't overflow the input on MD5
125 */
126 if ((n + 2 + AUTH_PASS_LEN) > *pwlen) {
127 block_len = *pwlen - n - 2;
128 }
129
130 if (n == 0) {
131 base = 1;
132
133 fr_md5_final(digest, md5_ctx);
134 fr_md5_ctx_copy(md5_ctx, md5_ctx_old);
135
136 /*
137 * A quick check: decrypt the first octet
138 * of the password, which is the
139 * 'data_len' field. Ensure it's sane.
140 */
141 embedded_len = passwd[2] ^ digest[0];
142 if (embedded_len > encrypted_len) {
143 fr_strerror_printf("Tunnel Password is too long for the attribute "
144 "(shared secret is probably incorrect!)");
146 fr_md5_ctx_free_from_list(&md5_ctx_old);
147 return -1;
148 }
149
150 fr_md5_update(md5_ctx, passwd + 2, block_len);
151
152 } else {
153 base = 0;
154
155 fr_md5_final(digest, md5_ctx);
156
157 fr_md5_ctx_copy(md5_ctx, md5_ctx_old);
158 fr_md5_update(md5_ctx, passwd + n + 2, block_len);
159 }
160
161 for (i = base; i < block_len; i++) {
162 passwd[n + i - 1] = passwd[n + i + 2] ^ digest[i];
163 }
164 }
165
167 fr_md5_ctx_free_from_list(&md5_ctx_old);
168
169 /*
170 * Check trailing bytes
171 */
172 if (packet_ctx->tunnel_password_zeros) for (i = embedded_len; i < (encrypted_len - 1); i++) { /* -1 for length field */
173 if (passwd[i] != 0) {
174 fr_strerror_printf("Trailing garbage in Tunnel Password "
175 "(shared secret is probably incorrect!)");
176
177 return -1;
178 }
179 }
180
181 *pwlen = embedded_len;
182
183 passwd[embedded_len] = '\0';
184
185 return embedded_len;
186}
187
188/** Decode password
189 *
190 */
191static ssize_t fr_radius_decode_password(char *passwd, size_t pwlen, fr_radius_decode_ctx_t *packet_ctx)
192{
193 fr_md5_ctx_t *md5_ctx, *md5_ctx_old;
195 int i;
196 size_t n;
197
198 /*
199 * The RFC's say that the maximum is 128, but where we
200 * come from, we don't need limits.
201 */
203
204 /*
205 * Catch idiots.
206 */
207 if (pwlen == 0) goto done;
208
209 md5_ctx = fr_md5_ctx_alloc_from_list();
210 md5_ctx_old = fr_md5_ctx_alloc_from_list();
211
212 fr_md5_update(md5_ctx, (uint8_t const *) packet_ctx->common->secret, packet_ctx->common->secret_length);
213 fr_md5_ctx_copy(md5_ctx_old, md5_ctx); /* save intermediate work */
214
215 /*
216 * The inverse of the code above.
217 */
218 for (n = 0; n < pwlen; n += AUTH_PASS_LEN) {
219 if (n == 0) {
221 fr_md5_final(digest, md5_ctx);
222
223 fr_md5_ctx_copy(md5_ctx, md5_ctx_old);
224 if (pwlen > AUTH_PASS_LEN) {
225 fr_md5_update(md5_ctx, (uint8_t *) passwd, AUTH_PASS_LEN);
226 }
227 } else {
228 fr_md5_final(digest, md5_ctx);
229
230 fr_md5_ctx_copy(md5_ctx, md5_ctx_old);
231 if (pwlen > (n + AUTH_PASS_LEN)) {
232 fr_md5_update(md5_ctx, (uint8_t *) passwd + n, AUTH_PASS_LEN);
233 }
234 }
235
236 for (i = 0; i < AUTH_PASS_LEN; i++) passwd[i + n] ^= digest[i];
237 }
238
240 fr_md5_ctx_free_from_list(&md5_ctx_old);
241
242 done:
243 passwd[pwlen] = '\0';
244 return strlen(passwd);
245}
246
247/** Check if a set of RADIUS formatted TLVs are OK
248 *
249 */
250int fr_radius_decode_tlv_ok(uint8_t const *data, size_t length, size_t dv_type, size_t dv_length)
251{
252 uint8_t const *end = data + length;
253
254 FR_PROTO_TRACE("Checking TLV %u/%u", (unsigned int) dv_type, (unsigned int) dv_length);
255
256 FR_PROTO_HEX_DUMP(data, length, "tlv_ok");
257
258 if ((dv_length > 2) || (dv_type == 0) || (dv_type > 4)) {
259 fr_strerror_printf("%s: Invalid arguments", __FUNCTION__);
260 return -1;
261 }
262
263 while (data < end) {
264 size_t attrlen;
265
266 if ((data + dv_type + dv_length) > end) {
267 fr_strerror_const("Attribute header overflow");
268 return -1;
269 }
270
271 switch (dv_type) {
272 case 4:
273 if ((data[0] == 0) && (data[1] == 0) &&
274 (data[2] == 0) && (data[3] == 0)) {
275 zero:
276 fr_strerror_const("Invalid attribute 0");
277 return -1;
278 }
279
280 if (data[0] != 0) {
281 fr_strerror_const("Invalid attribute > 2^24");
282 return -1;
283 }
284 break;
285
286 case 2:
287 if ((data[0] == 0) && (data[1] == 0)) goto zero;
288 break;
289
290 case 1:
291 /*
292 * Zero is allowed, because the Colubris
293 * people are dumb and use it.
294 */
295 break;
296
297 default:
298 fr_strerror_printf("%s: Internal sanity check failed", __FUNCTION__);
299 return -1;
300 }
301
302 switch (dv_length) {
303 case 0:
304 return 0;
305
306 case 2:
307 if (data[dv_type] != 0) {
308 fr_strerror_const("Attribute is longer than 256 octets");
309 return -1;
310 }
312 case 1:
313 attrlen = data[dv_type + dv_length - 1];
314 break;
315
316
317 default:
318 fr_strerror_printf("%s: Internal sanity check failed", __FUNCTION__);
319 return -1;
320 }
321
322 if (attrlen < (dv_type + dv_length)) {
323 fr_strerror_const("Attribute header has invalid length");
324 return -1;
325 }
326
327 if (attrlen > length) {
328 fr_strerror_const("Attribute overflows container");
329 return -1;
330 }
331
332 data += attrlen;
333 length -= attrlen;
334 }
335
336 return 0;
337}
338
339/** Convert a "concatenated" attribute to one long VP
340 *
341 */
342static ssize_t decode_concat(TALLOC_CTX *ctx, fr_pair_list_t *list,
343 fr_dict_attr_t const *parent, uint8_t const *data,
344 uint8_t const *end)
345{
346 size_t total;
347 uint8_t attr;
348 uint8_t const *ptr = data;
349 uint8_t *p;
350 fr_pair_t *vp;
351
353
354 total = 0;
355 attr = ptr[0];
356
357 /*
358 * See how many consecutive attributes there are.
359 */
360 while (ptr < end) {
361 if ((ptr + 2) == end) break;
362 if ((ptr + 2) > end) return -1;
363 if (ptr[1] <= 2) return -1;
364 if ((ptr + ptr[1]) > end) return -1;
365
366 total += ptr[1] - 2;
367
368 ptr += ptr[1];
369
370 if (ptr == end) break;
371
372 /*
373 * Attributes MUST be consecutive.
374 */
375 if (ptr[0] != attr) break;
376 }
377
378 /*
379 * Reset the end of the data we're trying to parse
380 */
381 end = ptr;
382
383 /*
384 * If there's no data, just return that we skipped the
385 * attribute header.
386 */
387 if (!total) return 2;
388
389 vp = fr_pair_afrom_da(ctx, parent);
390 if (!vp) return -1;
391
392 if (fr_pair_value_mem_alloc(vp, &p, total, true) != 0) {
394 return -1;
395 }
396
397 ptr = data;
398 while (ptr < end) {
399 memcpy_bounded(p, ptr + 2, ptr[1] - 2, end);
400 p += ptr[1] - 2;
401 ptr += ptr[1];
402 }
403 fr_pair_append(list, vp);
404 return ptr - data;
405}
406
407/*
408 * Short-term hack to help clean things up.
409 */
410#define decode_value fr_radius_decode_pair_value
411
412/** decode an RFC-format TLV
413 *
414 */
415static ssize_t decode_rfc(TALLOC_CTX *ctx, fr_pair_list_t *out,
416 fr_dict_attr_t const *parent,
417 uint8_t const *data, size_t const data_len, void *decode_ctx)
418{
419 unsigned int attr;
420 size_t len;
421 ssize_t slen;
422 fr_dict_attr_t const *da;
423 fr_radius_decode_ctx_t *packet_ctx = decode_ctx;
424
425#ifdef STATIC_ANALYZER
426 if (!packet_ctx || !packet_ctx->tmp_ctx) return PAIR_DECODE_FATAL_ERROR;
427#endif
428
429 fr_assert(parent != NULL);
430
431 /*
432 * Must have at least a header.
433 */
434 if ((data_len < 2) || (data[1] < 2)) {
435 fr_strerror_printf("%s: Insufficient data", __FUNCTION__);
436 return -(data_len);
437 }
438
439 /*
440 * Empty attributes are ignored.
441 */
442 if (data[1] == 2) return 2;
443
444 attr = data[0];
445 len = data[1];
446 if (len > data_len) {
447 fr_strerror_printf("%s: Attribute overflows input. "
448 "Length must be less than %zu bytes, got %zu bytes",
449 __FUNCTION__, data_len - 2, len - 2);
451 }
452
454 if (!da) {
455 da = fr_dict_attr_unknown_raw_afrom_num(packet_ctx->tmp_ctx, parent, attr);
456 if (!da) return PAIR_DECODE_FATAL_ERROR;
457 slen = fr_pair_raw_from_network(ctx, out, da, data + 2, len - 2);
458 if (slen < 0) return slen;
459 return len;
460 }
461 FR_PROTO_TRACE("decode context changed %s -> %s",da->parent->name, da->name);
462
463 if (da->flags.array) {
464 slen = fr_pair_array_from_network(ctx, out, da, data + 2, len - 2, decode_ctx, decode_value);
465
466 } else if (da->type == FR_TYPE_TLV) {
467 slen = fr_pair_tlvs_from_network(ctx, out, da, data + 2, len - 2, decode_ctx, decode_rfc, NULL, true);
468
469 } else {
470 slen = decode_value(ctx, out, da, data + 2, len - 2, decode_ctx);
471 }
472
473 if (slen < 0) return slen;
474
475 return len;
476}
477
478
479/** Decode NAS-Filter-Rule
480 *
481 * Similar to decode_concat, but contains multiple values instead of
482 * one.
483 */
485 fr_dict_attr_t const *parent, uint8_t const *data,
486 size_t const data_len, fr_radius_decode_ctx_t *packet_ctx)
487{
488 uint8_t const *ptr = data;
489 uint8_t const *end = data + data_len;
490 uint8_t const *decode, *decode_end;
491 uint8_t *buffer = NULL;
492 size_t total = 0;
493
494 /*
495 * Figure out how long the total length of the data is.
496 * This is so that we can do the decoding from a
497 * temporary buffer. Which means that we coalesce data
498 * across multiple attributes, separately from chopping
499 * the data at zero bytes.
500 */
501 while (ptr < end) {
502 if ((ptr + 2) == end) break;
503 if ((ptr + 2) > end) return -1;
504 if ((ptr[0] != FR_NAS_FILTER_RULE)) break;
505 if (ptr[1] <= 2) return -1;
506 if ((ptr + ptr[1]) > end) return -1;
507
508 total += ptr[1] - 2;
509 ptr += ptr[1];
510 }
511 end = ptr;
512
513 FR_PROTO_TRACE("Coalesced NAS-Filter-Rule has %lu octets", total);
514
515 /*
516 * More than one attribute, create a temporary buffer,
517 * and copy all of the data over to it.
518 */
519 if (total > RADIUS_MAX_STRING_LENGTH) {
520 uint8_t *p;
521
522 buffer = talloc_array(packet_ctx->tmp_ctx, uint8_t, total);
523 if (!buffer) return PAIR_DECODE_OOM;
524
525 p = buffer;
526 ptr = data;
527
528 /*
529 * Don't bother doing sanity checks, as they were
530 * already done above.
531 */
532 while (ptr < end) {
533 fr_assert(p < (buffer + total));
534 memcpy(p, ptr + 2, ptr[1] - 2);
535 p += ptr[1] - 2;
536 ptr += ptr[1];
537 }
538
539 decode = buffer;
540 decode_end = buffer + total;
541 } else {
542 decode = data + 2;
543 decode_end = data + data[1];
544 }
545
546 FR_PROTO_HEX_DUMP(decode, decode_end - decode, "NAS-Filter-Rule coalesced");
547
548 /*
549 * And now walk through "decode", decoding to VPs.
550 */
551 while (decode < decode_end) {
552 size_t len;
553 uint8_t const *p;
554
555 p = decode;
556
557 while (p < decode_end) {
558 if (*p == 0x00) break;
559 p++;
560 }
561
562 len = (p - decode);
563 if (len) {
564 fr_pair_t *vp;
565
566 FR_PROTO_TRACE("This NAS-Filter-Rule has %lu octets", len);
567 FR_PROTO_HEX_DUMP(decode, len, "This NAS-Filter-Rule");
568 vp = fr_pair_afrom_da(ctx, parent);
569 if (!vp) {
571 return -1;
572 }
573
574 if (fr_pair_value_bstrndup(vp, (char const *) decode, len, true) != 0) {
577 return -1;
578 }
580 }
581
582 /*
583 * Skip the zero byte
584 */
585 decode = p + 1;
586 }
587
589 return end - data; /* end of the NAS-Filter-Rule */
590}
591
592
593/** Decode Digest-Attributes
594 *
595 * The VPs are nested, and consecutive Digest-Attributes attributes are decoded into the same parent.
596 */
598 fr_dict_attr_t const *parent, uint8_t const *data,
599 size_t const data_len, fr_radius_decode_ctx_t *packet_ctx)
600{
601 ssize_t slen;
602 fr_pair_t *vp;
603 uint8_t const *p = data;
604 uint8_t const *end = data + data_len;
605
606 fr_assert(parent->type == FR_TYPE_TLV);
607
608 vp = fr_pair_afrom_da(ctx, parent);
609 if (!vp) return PAIR_DECODE_OOM;
610
611redo:
612 FR_PROTO_HEX_DUMP(p, end - p, "decode_digest_attributes");
613
614 if (((size_t) (p - end) < 2) || (p[1] > (size_t) (end - p))) {
615 slen = fr_pair_raw_from_network(vp, &vp->vp_group, parent, p, end - p);
616 if (slen < 0) {
618 return slen;
619 }
620
621 goto done;
622 }
623
624 slen = fr_pair_tlvs_from_network(vp, &vp->vp_group, parent, p + 2, p[1] - 2, packet_ctx, decode_rfc, NULL, false);
625 if (slen <= 0) {
627 return slen;
628 }
629
630 /*
631 * Decode consecutive ones into the same parent.
632 */
633 p += p[1];
634 if (((p + 2) < end) && ((p[0] == FR_DIGEST_ATTRIBUTES) && (p[1] > 2))) {
635 goto redo;
636 }
637
638done:
640 return p - data;
641}
642
643
644/** Convert TLVs to one or more VPs
645 *
646 */
648 fr_dict_attr_t const *parent, uint8_t const *data, size_t data_len,
649 fr_radius_decode_ctx_t *packet_ctx)
650{
651 uint8_t const *p = data, *end = data + data_len;
652 fr_dict_attr_t const *child;
654 fr_pair_list_t tlv_tmp;
655 fr_pair_t *vp;
656
658 if (data_len < 3) return -1; /* type, length, value */
659
660#ifdef STATIC_ANALYZER
661 if (!packet_ctx->tmp_ctx) return -1;
662#endif
663
664 FR_PROTO_HEX_DUMP(p, data_len, "tlvs");
665
666 if (fr_radius_decode_tlv_ok(p, data_len, 1, 1) < 0) return -1;
667
668 vp = fr_pair_afrom_da(ctx, parent);
669 if (!vp) return PAIR_DECODE_OOM;
670
671 /*
672 * Record where we were in the list when this function was called
673 * Create a temporary sub-list, so decode errors don't
674 * affect the main list.
675 */
676 fr_pair_list_init(&tlv_tmp);
677 while (p < end) {
678 ssize_t tlv_len;
679
680 child = fr_dict_attr_child_by_num(parent, p[0]);
681 if (!child) {
682 FR_PROTO_TRACE("Failed to find child %u of TLV %s", p[0], parent->name);
683
684 /*
685 * Child is unknown and not a TLV: build an unknown attr
686 */
687 if (fr_radius_decode_tlv_ok(p + 2, p[1] - 2, 1, 1) < 0) {
688 child = fr_dict_attr_unknown_raw_afrom_num(packet_ctx->tmp_ctx, parent, p[0]);
689 if (!child) {
690 error:
692 return -1;
693 }
694 } else {
695 /*
696 * Child is formed as a TLV, decode it as such
697 */
699 if (!child) goto error;
700
701 FR_PROTO_TRACE("decode context changed %s -> %s", parent->name, child->name);
702 tlv_len = fr_radius_decode_tlv(vp, &tlv_tmp, child, p + 2, p[1] - 2, packet_ctx);
703 goto check;
704 }
705 }
706 FR_PROTO_TRACE("decode context changed %s -> %s", parent->name, child->name);
707
708 tlv_len = fr_radius_decode_pair_value(vp, &tlv_tmp,
709 child, p + 2, p[1] - 2,
710 packet_ctx);
711 check:
712 if (tlv_len < 0) goto error;
713 p += p[1];
714 }
715
716 fr_pair_list_append(&vp->vp_group, &tlv_tmp);
718
719 return data_len;
720}
721
722/** Convert a top-level VSA to a VP.
723 *
724 * "length" can be LONGER than just this sub-vsa.
725 */
727 fr_dict_attr_t const *parent,
728 uint8_t const *data, size_t data_len,
729 fr_radius_decode_ctx_t *packet_ctx, fr_dict_vendor_t const *dv)
730{
731 unsigned int attribute;
732 ssize_t attrlen, my_len;
733 fr_dict_attr_t const *da;
734
735#ifdef STATIC_ANALYZER
736 if (!packet_ctx->tmp_ctx) return -1;
737#endif
738
739 /*
740 * Parent must be a vendor
741 */
742 if (!fr_cond_assert(parent->type == FR_TYPE_VENDOR)) {
743 fr_strerror_printf("%s: Internal sanity check failed", __FUNCTION__);
744 return -1;
745 }
746
747 FR_PROTO_TRACE("Length %u", (unsigned int)data_len);
748
749#ifndef NDEBUG
750 if (data_len <= (dv->type + dv->length)) {
751 fr_strerror_printf("%s: Failure to call fr_radius_decode_tlv_ok", __FUNCTION__);
752 return -1;
753 }
754#endif
755
756 switch (dv->type) {
757 case 4:
758 /* data[0] must be zero */
759 attribute = data[1] << 16;
760 attribute |= data[2] << 8;
761 attribute |= data[3];
762 break;
763
764 case 2:
765 attribute = data[0] << 8;
766 attribute |= data[1];
767 break;
768
769 case 1:
770 attribute = data[0];
771 break;
772
773 default:
774 fr_strerror_printf("%s: Internal sanity check failed", __FUNCTION__);
775 return -1;
776 }
777
778 switch (dv->length) {
779 case 2:
780 /* data[dv->type] must be zero, from fr_radius_decode_tlv_ok() */
781 attrlen = data[dv->type + 1];
782 break;
783
784 case 1:
785 attrlen = data[dv->type];
786 break;
787
788 case 0:
789 attrlen = data_len;
790 break;
791
792 default:
793 fr_strerror_printf("%s: Internal sanity check failed", __FUNCTION__);
794 return -1;
795 }
796
797 /*
798 * See if the VSA is known.
799 */
800 da = fr_dict_attr_child_by_num(parent, attribute);
801 if (da) {
802 decode:
803 FR_PROTO_TRACE("decode context changed %s -> %s", da->parent->name, da->name);
804
805 my_len = fr_radius_decode_pair_value(ctx, out,
806 da, data + dv->type + dv->length,
807 attrlen - (dv->type + dv->length),
808 packet_ctx);
809 if (my_len < 0) return my_len;
810
811 /*
812 * It's unknown. Let's see if we can decode it as a TLV. While this check can sometimes
813 * (rarely) decode non-TLVs as TLVs, that situation will be rare. And it's very useful
814 * to be able to decode nested unknown TLVs.
815 *
816 * Note that if the TLV length is zero, then we have no real way to tell if the TLV is
817 * well formed, so we just go create a raw VP.
818 */
819 } else if ((dv->length == 0) || (fr_radius_decode_tlv_ok(data + dv->type + dv->length, attrlen - (dv->type + dv->length), dv->type, dv->length) < 0)) {
820 da = fr_dict_attr_unknown_raw_afrom_num(packet_ctx->tmp_ctx, parent, attribute);
821 if (!da) return -1;
822
823 goto decode;
824
825 } else {
826 da = fr_dict_attr_unknown_typed_afrom_num(packet_ctx->tmp_ctx, parent, attribute, FR_TYPE_TLV);
827 if (!da) return -1;
828
829 goto decode;
830 }
831
832 return attrlen;
833}
834
835
836/** Convert a fragmented extended attr to a VP
837 *
838 * Format is:
839 *
840 * attr
841 * length
842 * extended-attr
843 * flag
844 * data...
845 *
846 * But for the first fragment, we get passed a pointer to the "extended-attr"
847 */
849 fr_dict_attr_t const *parent,
850 uint8_t const *data, size_t attr_len,
851 fr_radius_decode_ctx_t *packet_ctx)
852{
853 ssize_t ret;
854 size_t fraglen;
855 uint8_t *head, *tail;
856 uint8_t const *frag, *end;
857 uint8_t const *attr;
858 int fragments;
859 bool last_frag;
860
861 /*
862 * data = Ext-Attr Flag ...
863 */
864
865 if (attr_len < 3) return -1;
866
867 /*
868 * No continuation, just decode the attribute in place.
869 */
870 if ((data[1] & 0x80) == 0) {
872 parent, data + 2, attr_len - 2, packet_ctx);
873 if (ret < 0) return -1;
874 return attr_len;
875 }
876
877 /*
878 * Calculate the length of all of the fragments. For
879 * now, they MUST be contiguous in the packet, and they
880 * MUST be all of the same TYPE and EXTENDED-TYPE
881 */
882 attr = data - 2;
883 fraglen = attr_len - 2;
884 frag = data + attr_len;
885 end = packet_ctx->end;
886 fragments = 1;
887 last_frag = false;
888
889 while (frag < end) {
890 if (last_frag || ((end - frag) < 4) ||
891 (frag[0] != attr[0]) ||
892 (frag[1] < 4) || /* too short for long_extended */
893 (frag[2] != attr[2]) ||
894 ((frag + frag[1]) > end)) { /* overflow */
895 end = frag;
896 break;
897 }
898
899 last_frag = ((frag[3] & 0x80) == 0);
900
901 fraglen += frag[1] - 4;
902 frag += frag[1];
903 fragments++;
904 }
905
906 head = tail = talloc_array(ctx, uint8_t, fraglen);
907 if (!head) return -1;
908
909 FR_PROTO_TRACE("Fragments %d, total length %d", fragments, (int) fraglen);
910
911 /*
912 * And again, but faster and looser.
913 *
914 * We copy the first fragment, followed by the rest of
915 * the fragments.
916 */
917 frag = attr;
918
919 while (fragments > 0) {
920 if (frag[1] > 4) memcpy_bounded(tail, frag + 4, frag[1] - 4, end);
921 tail += frag[1] - 4;
922 frag += frag[1];
923 fragments--;
924 }
925
926 FR_PROTO_HEX_DUMP(head, fraglen, "long_extended fragments");
927
928 /*
929 * Reset the "end" pointer, because we're not passing in
930 * the real data.
931 */
932 {
933 uint8_t const *tmp = packet_ctx->end;
934 packet_ctx->end = head + fraglen;
935
937 parent, head, fraglen, packet_ctx);
938
939 packet_ctx->end = tmp;
940 }
941
943 if (ret < 0) return ret;
944
945 return end - data;
946}
947
948/** Fast path for most extended attributes.
949 *
950 * data_len has already been checked by the caller, so we don't care
951 * about it here.
952 */
953static ssize_t decode_extended(TALLOC_CTX *ctx, fr_pair_list_t *out,
954 fr_dict_attr_t const *da,
955 uint8_t const *data, UNUSED size_t data_len,
956 fr_radius_decode_ctx_t *packet_ctx)
957{
958 ssize_t slen;
959 fr_dict_attr_t const *child;
960 fr_pair_t *vp;
961
962 /*
963 * They MUST have one byte of Extended-Type. The
964 * case of "2" is already handled above with CUI.
965 */
966 if (data[1] == 3) {
967 slen = fr_pair_raw_from_network(ctx, out, da, data + 2, 1);
968 if (slen <= 0) return slen;
969 return 2 + slen;
970 }
971
972 /*
973 * Get a new child.
974 */
975 child = fr_dict_attr_child_by_num(da, data[2]);
976 if (!child) {
977 fr_dict_attr_t *unknown;
978 FR_PROTO_TRACE("Unknown extended attribute %u.%u", data[0], data[2]);
979 unknown = fr_dict_attr_unknown_raw_afrom_num(packet_ctx->tmp_ctx, da, data[2]);
980 if (!unknown) return -1;
981
982 child = unknown;
983 }
984
985 /*
986 * One byte of type, and N bytes of data.
987 */
989 if (fr_pair_find_or_append_by_da(ctx, &vp, out, da) < 0) return PAIR_DECODE_OOM;
990
991 slen = fr_radius_decode_pair_value(vp, &vp->vp_group, child, data + 3, data[1] - 3, packet_ctx);
993 if (slen < 0 ) return slen;
994
995 fr_assert(slen < (1 << 16));
996 return 3 + slen;
997 }
998
999 /*
1000 * It MUST have one byte of type, and one byte of
1001 * flags. If there's no data here, we just
1002 * ignore it, whether or not the "More" bit is
1003 * set.
1004 */
1005 if (data[1] == 4) {
1007 slen = fr_pair_raw_from_network(ctx, out, da, data + 2, 2);
1008 if (slen < 0) return slen;
1009 return 4;
1010 }
1011
1012 if (fr_pair_find_or_append_by_da(ctx, &vp, out, da) < 0) return PAIR_DECODE_OOM;
1013
1014 /*
1015 * No continuation - just decode as-is.
1016 */
1017 if ((data[3] & 0x80) == 0) {
1018 slen = fr_radius_decode_pair_value(vp, &vp->vp_group, child, data + 4, data[1] - 4, packet_ctx);
1020 if (slen < 0 ) return slen;
1021 return 4 + slen;
1022 }
1023
1024 /*
1025 * Concatenate all of the fragments together, and decode the resulting thing.
1026 */
1027 slen = decode_extended_fragments(vp, &vp->vp_group, child, data + 2, data[1] - 2, packet_ctx);
1029 if (slen < 0) return slen;
1030 return 2 + slen;
1031}
1032
1033/** Convert a Vendor-Specific WIMAX to vps
1034 *
1035 * @note Called ONLY for Vendor-Specific
1036 */
1037static ssize_t decode_wimax(TALLOC_CTX *ctx, fr_pair_list_t *out,
1038 fr_dict_attr_t const *parent,
1039 uint8_t const *data, size_t attr_len,
1040 fr_radius_decode_ctx_t *packet_ctx)
1041{
1042 ssize_t ret;
1043 size_t wimax_len;
1044 bool more;
1045 uint8_t *head, *tail;
1046 uint8_t const *attr, *end;
1047 fr_dict_attr_t const *da;
1048 fr_pair_t *vsa, *vendor;
1049
1050#ifdef STATIC_ANALYZER
1051 if (!packet_ctx->tmp_ctx) return -1;
1052#endif
1053
1054 fr_assert(packet_ctx->end != NULL);
1055 fr_assert((data + attr_len) <= packet_ctx->end);
1056
1057 /*
1058 * data = VID VID VID VID WiMAX-Attr WiMAX-Len Continuation ...
1059 */
1060 if (attr_len < 8) {
1061 FR_PROTO_TRACE("attribute is too small to be WiMAX");
1062 return -1;
1063 }
1064
1065 /*
1066 * WiMAX-Attr WiMAX-Len Continuation
1067 */
1068 if (data[5] < 3) {
1069 FR_PROTO_TRACE("attribute is too small to be WiMAX-Attr-WiMAX-Len Continuation");
1070 return -1;
1071 }
1072
1073 /*
1074 * The WiMAX-Len + 4 VID must exactly fill the attribute.
1075 */
1076 if (((size_t) (data[5] + 4)) != attr_len) {
1077 FR_PROTO_TRACE("WiMAX VSA does not exactly fill the attribute");
1078 return -1;
1079 }
1080
1082
1083 if (fr_pair_find_or_append_by_da(vsa, &vendor, &vsa->vp_group, parent) < 0) return PAIR_DECODE_OOM;
1084
1086 if (!da) da = fr_dict_attr_unknown_raw_afrom_num(packet_ctx->tmp_ctx, parent, data[4]);
1087 if (!da) return -1;
1088 FR_PROTO_TRACE("decode context changed %s -> %s", da->parent->name, da->name);
1089
1090 /*
1091 * No continuation, just decode the attribute in place.
1092 */
1093 if ((data[6] & 0x80) == 0) {
1094 FR_PROTO_TRACE("WiMAX no continuation");
1095 ret = fr_radius_decode_pair_value(vendor, &vendor->vp_group,
1096 da, data + 7, data[5] - 3, packet_ctx);
1097 if (ret < 0) return ret;
1098
1099 return attr_len;
1100 }
1101
1102 /*
1103 * Calculate the length of all of the fragments. For
1104 * now, they MUST be contiguous in the packet, and they
1105 * MUST be all of the same VSA, WiMAX, and WiMAX-attr.
1106 *
1107 * The first fragment doesn't have a RADIUS attribute
1108 * header.
1109 */
1110 wimax_len = 0;
1111 attr = data + 4;
1112 end = packet_ctx->end;
1113
1114 while (attr < end) {
1115 /*
1116 * Not enough room for Attribute + length +
1117 * continuation, it's bad.
1118 */
1119 if ((end - attr) < 3) {
1120 FR_PROTO_TRACE("end - attr < 3");
1121 return -1;
1122 }
1123
1124 /*
1125 * Must have non-zero data in the attribute.
1126 */
1127 if (attr[1] <= 3) {
1128 FR_PROTO_TRACE("attr[1] <= 3");
1129 return -1;
1130 }
1131
1132 /*
1133 * If the WiMAX attribute overflows the packet,
1134 * it's bad.
1135 */
1136 if ((attr + attr[1]) > end) {
1137 FR_PROTO_TRACE("attr + attr[1]) > end");
1138 return -1;
1139 }
1140
1141 /*
1142 * Check the continuation flag.
1143 */
1144 more = ((attr[2] & 0x80) != 0);
1145
1146 /*
1147 * Or, there's no more data, in which case we
1148 * shorten "end" to finish at this attribute.
1149 */
1150 if (!more) end = attr + attr[1];
1151
1152 /*
1153 * There's more data, but we're at the end of the
1154 * packet. The attribute is malformed!
1155 */
1156 if (more && ((attr + attr[1]) == end)) {
1157 FR_PROTO_TRACE("more && ((attr + attr[1]) == end)");
1158 return -1;
1159 }
1160
1161 /*
1162 * Add in the length of the data we need to
1163 * concatenate together.
1164 */
1165 wimax_len += attr[1] - 3;
1166
1167 /*
1168 * Go to the next attribute, and stop if there's
1169 * no more.
1170 */
1171 attr += attr[1];
1172 if (!more) break;
1173
1174 /*
1175 * data = VID VID VID VID WiMAX-Attr WimAX-Len Continuation ...
1176 *
1177 * attr = Vendor-Specific VSA-Length VID VID VID VID WiMAX-Attr WimAX-Len Continuation ...
1178 *
1179 */
1180
1181 /*
1182 * No room for Vendor-Specific + length +
1183 * Vendor(4) + attr + length + continuation + data
1184 */
1185 if ((end - attr) < 9) {
1186 FR_PROTO_TRACE("(end - attr) < 9");
1187 return -1;
1188 }
1189
1190 if (attr[0] != FR_VENDOR_SPECIFIC) {
1191 FR_PROTO_TRACE("attr[0] != FR_VENDOR_SPECIFIC");
1192 return -1;
1193 }
1194
1195 if (attr[1] < 9) {
1196 FR_PROTO_TRACE("attr[1] < 9");
1197 return -1;
1198 }
1199
1200 if ((attr + attr[1]) > end) {
1201 FR_PROTO_TRACE("(attr + attr[1]) > end");
1202 return -1;
1203 }
1204
1205 if (memcmp(data, attr + 2, 4) != 0) {
1206 FR_PROTO_TRACE("not the same vendor");
1207 return -1; /* not WiMAX Vendor ID */
1208 }
1209
1210 if (attr[1] != (attr[7] + 6)) {
1211 FR_PROTO_TRACE("attr[1] != (attr[7] + 6)");
1212 return -1; /* WiMAX attr doesn't exactly fill the VSA */
1213 }
1214
1215 if (data[4] != attr[6]) {
1216 FR_PROTO_TRACE("data[4] != attr[6]");
1217 return -1; /* different WiMAX attribute */
1218 }
1219
1220 /*
1221 * Skip over the Vendor-Specific header, and
1222 * continue with the WiMAX attributes.
1223 */
1224 attr += 6;
1225 }
1226
1227 /*
1228 * No data in the WiMAX attribute, make a "raw" one.
1229 */
1230 if (!wimax_len) {
1231 FR_PROTO_TRACE("!wimax_len");
1232 return -1;
1233 }
1234
1235 head = tail = talloc_array(ctx, uint8_t, wimax_len);
1236 if (!head) return -1;
1237
1238 /*
1239 * Copy the data over, this time trusting the attribute
1240 * contents.
1241 */
1242 attr = data;
1243 while (attr < end) {
1244 memcpy_bounded(tail, attr + 4 + 3, attr[4 + 1] - 3, end);
1245 tail += attr[4 + 1] - 3;
1246 attr += 4 + attr[4 + 1]; /* skip VID+WiMax header */
1247 attr += 2; /* skip Vendor-Specific header */
1248 }
1249
1250 FR_PROTO_HEX_DUMP(head, wimax_len, "Wimax fragments");
1251
1252 /*
1253 * Reset the "end" pointer, because we're not passing in
1254 * the real data.
1255 */
1256 {
1257 uint8_t const *tmp = packet_ctx->end;
1258 packet_ctx->end = head + wimax_len;
1259
1260 FR_PROTO_TRACE("WiMAX decode concatenated");
1261 FR_PROTO_HEX_DUMP(head, wimax_len, "%s", __FUNCTION__ );
1263 da, head, wimax_len, packet_ctx);
1264
1265 packet_ctx->end = tmp;
1266 }
1267
1269 if (ret < 0) return ret;
1270
1271 return end - data;
1272}
1273
1274
1275/** Convert a top-level VSA to one or more VPs
1276 *
1277 */
1278static ssize_t CC_HINT(nonnull) decode_vsa(TALLOC_CTX *ctx, fr_pair_list_t *out,
1279 fr_dict_attr_t const *parent,
1280 uint8_t const *data, size_t attr_len,
1281 fr_radius_decode_ctx_t *packet_ctx)
1282{
1283 size_t total;
1284 ssize_t ret;
1285 uint32_t vendor_pen;
1286 fr_dict_vendor_t const *dv;
1288 fr_dict_vendor_t my_dv;
1289 fr_dict_attr_t const *vendor_da;
1290 fr_pair_list_t tlv_tmp;
1291 fr_pair_t *vsa, *vendor;
1292
1294
1295#ifdef STATIC_ANALYZER
1296 if (!packet_ctx->tmp_ctx) return -1;
1297#endif
1298
1299 /*
1300 * Container must be a VSA
1301 */
1302 if (!fr_cond_assert(parent->type == FR_TYPE_VSA)) return -1;
1303
1304 if ((data + attr_len) > packet_ctx->end) return -1;
1305 if (attr_len < 5) return -1; /* vid, value */
1306 if (data[0] != 0) return -1; /* we require 24-bit VIDs */
1307
1308 FR_PROTO_TRACE("Decoding VSA");
1309
1310 memcpy(&vendor_pen, data, 4);
1311 vendor_pen = ntohl(vendor_pen);
1312
1313 /*
1314 * Verify that the parent (which should be a VSA)
1315 * contains a fake attribute representing the vendor.
1316 *
1317 * If it doesn't then this vendor is unknown, but
1318 * (unlike DHCP) we know vendor attributes have a
1319 * standard format, so we can decode the data anyway.
1320 */
1321 vendor_da = fr_dict_attr_child_by_num(parent, vendor_pen);
1322 if (!vendor_da) {
1324 /*
1325 * RFC format is 1 octet type, 1 octet length
1326 */
1327 if (fr_radius_decode_tlv_ok(data + 4, attr_len - 4, 1, 1) < 0) {
1328 FR_PROTO_TRACE("Unknown TLVs not OK: %s", fr_strerror());
1329 return -1;
1330 }
1331
1332 n = fr_dict_attr_unknown_vendor_afrom_num(packet_ctx->tmp_ctx, parent, vendor_pen);
1333 if (!n) return -1;
1334 vendor_da = n;
1335
1336 fr_assert(vendor_da->flags.type_size == 1);
1337
1338 /*
1339 * Create an unknown DV too...
1340 */
1341 memset(&my_dv, 0, sizeof(my_dv));
1342
1343 my_dv.pen = vendor_pen;
1344 my_dv.type = 1;
1345 my_dv.length = 1;
1346
1347 dv = &my_dv;
1348
1349 goto create_attrs;
1350 }
1351
1352 /*
1353 * We found an attribute representing the vendor
1354 * so it *MUST* exist in the vendor tree.
1355 */
1356 dv = fr_dict_vendor_by_num(dict_radius, vendor_pen);
1357 if (!fr_cond_assert(dv)) return -1;
1358 FR_PROTO_TRACE("decode context %s -> %s", parent->name, vendor_da->name);
1359
1360 /*
1361 * WiMAX craziness
1362 */
1363 if (dv->continuation) {
1364 ret = decode_wimax(ctx, out, vendor_da, data, attr_len, packet_ctx);
1365 return ret;
1366 }
1367
1368 /*
1369 * VSAs should normally be in TLV format.
1370 */
1371 if (fr_radius_decode_tlv_ok(data + 4, attr_len - 4, dv->type, dv->length) < 0) {
1372 FR_PROTO_TRACE("TLVs not OK: %s", fr_strerror());
1373 return -1;
1374 }
1375
1376 /*
1377 * There may be more than one VSA in the
1378 * Vendor-Specific. If so, loop over them all.
1379 */
1380create_attrs:
1381 if (fr_pair_find_or_append_by_da(ctx, &vsa, out, parent) < 0) return PAIR_DECODE_OOM;
1382
1383 if (fr_pair_find_or_append_by_da(vsa, &vendor, &vsa->vp_group, vendor_da) < 0) return PAIR_DECODE_OOM;
1384
1385 data += 4;
1386 attr_len -= 4;
1387 total = 4;
1388
1389 fr_pair_list_init(&tlv_tmp);
1390 while (attr_len > 0) {
1391 ssize_t vsa_len;
1392
1393 /*
1394 * Vendor attributes can have subattributes (if you hadn't guessed)
1395 */
1396 vsa_len = decode_vsa_internal(vendor, &tlv_tmp,
1397 vendor_da, data, attr_len, packet_ctx, dv);
1398 if (vsa_len < 0) {
1399 FR_PROTO_TRACE("TLV decode failed: %s", fr_strerror());
1400 fr_strerror_printf("%s: Internal sanity check %d", __FUNCTION__, __LINE__);
1401 fr_pair_list_free(&tlv_tmp);
1402 return -1;
1403 }
1404
1405 data += vsa_len;
1406 attr_len -= vsa_len;
1407 total += vsa_len;
1408 }
1409 fr_pair_list_append(&vendor->vp_group, &tlv_tmp);
1410
1411 /*
1412 * Hacks for tags. The tagged VSAs don't go into the
1413 * root, they go into the Tag-# attribute. But we only
1414 * know that after we've created the parents. So clean up if necessary.
1415 *
1416 * @todo - maybe cache these somewhere to avoid bouncing.
1417 */
1418 if (fr_pair_list_num_elements(&vendor->vp_group) == 0) {
1419 if (fr_pair_list_num_elements(&vsa->vp_group) == 1) { /* only the vendor */
1420 fr_pair_delete(out, vsa);
1421 } else {
1422 fr_pair_delete(&vsa->vp_group, vendor);
1423 }
1424 }
1425
1426 /*
1427 * When the unknown attributes were created by
1428 * decode_vsa_internal, the hierarchy between that unknown
1429 * attribute and first known attribute was cloned
1430 * meaning we can now free the unknown vendor.
1431 */
1432
1433 return total;
1434}
1435
1436/** Wrapper called by fr_struct_from_network()
1437 *
1438 * Because extended attributes can continue across the current value.
1439 * So that function needs to know both the value length, *and* the
1440 * packet length. But when we're decoding values inside of a struct,
1441 * we're not using extended attributes.
1442 */
1444 fr_dict_attr_t const *parent,
1445 uint8_t const *data, size_t data_len, void *decode_ctx)
1446{
1447 return fr_radius_decode_pair_value(ctx, out, parent, data, data_len, decode_ctx);
1448}
1449
1450/** Wrapper called by fr_struct_from_network()
1451 */
1453 fr_dict_attr_t const *parent,
1454 uint8_t const *data, size_t data_len, void *decode_ctx)
1455{
1456 FR_PROTO_HEX_DUMP(data, data_len, "%s", __FUNCTION__ );
1457
1458 return fr_radius_decode_tlv(ctx, out, parent, data, data_len, decode_ctx);
1459}
1460
1461
1462/** Create any kind of VP from the attribute contents
1463 *
1464 * "length" is AT LEAST the length of this attribute, as we
1465 * expect the caller to have verified the data with
1466 * fr_packet_ok(). "length" may be up to the length of the
1467 * packet.
1468 *
1469 * This function will ONLY return -1 on programmer error or OOM. If
1470 * there's anything wrong with the attribute, it will ALWAYS create a
1471 * "raw" attribute.
1472 *
1473 * @return
1474 * - Length on success.
1475 * - -1 on failure.
1476 */
1478 fr_dict_attr_t const *parent,
1479 uint8_t const *data, size_t const attr_len,
1480 void *decode_ctx)
1481{
1482 int8_t tag = 0;
1483 size_t data_len;
1484 ssize_t ret;
1485 fr_dict_attr_t const *child;
1486 fr_pair_t *vp = NULL;
1487 uint8_t const *p = data;
1488 uint8_t buffer[256];
1490 fr_radius_decode_ctx_t *packet_ctx = decode_ctx;
1491
1492 if (attr_len > 128 * 1024) {
1493 fr_strerror_printf("%s: packet is too large to be RADIUS", __FUNCTION__);
1494 return -1;
1495 }
1496
1497 if ((data + attr_len) > packet_ctx->end) {
1498 fr_strerror_printf("%s: input overflows packet", __FUNCTION__);
1499 return -1;
1500 }
1501
1502 FR_PROTO_HEX_DUMP(data, attr_len, "%s", __FUNCTION__ );
1503
1504 FR_PROTO_TRACE("Parent %s len %zu ... %zu", parent->name, attr_len, (size_t) (packet_ctx->end - data));
1505
1506 data_len = attr_len;
1507
1508 /*
1509 * Silently ignore zero-length attributes.
1510 */
1511 if (attr_len == 0) return 0;
1512
1513 /*
1514 * Hacks for tags.
1515 */
1517 /*
1518 * Check for valid tags and data types.
1519 */
1520 if (parent->type == FR_TYPE_UINT32) {
1521 if ((attr_len != 4) || (p[0] >= 0x20)) {
1522 goto raw;
1523 }
1524
1525 } else if (parent->type != FR_TYPE_STRING) {
1526 goto raw;
1527 }
1528
1529 /*
1530 * Tag values MUST be less than 32.
1531 */
1532 if (p[0] < 0x20) {
1533 /*
1534 * Only "short" attributes can be encrypted.
1535 */
1536 if (data_len >= sizeof(buffer)) goto raw;
1537
1538 if (parent->type == FR_TYPE_STRING) {
1539 memcpy(buffer, p + 1, data_len - 1);
1540 tag = p[0];
1541 data_len -= 1;
1542
1543 } else if (parent->type == FR_TYPE_UINT32) {
1544 memcpy(buffer, p, attr_len);
1545 tag = buffer[0];
1546 buffer[0] = 0;
1547 }
1548
1549 p = buffer;
1550
1551 } /* else the field is >=0x20, so it's not a tag */
1552 }
1553
1554 if (tag) {
1555 fr_radius_tag_ctx_t **new_tag_ctx = NULL;
1556
1557 if (!packet_ctx->tags) {
1558 /*
1559 * This should NOT be packet_ctx.tmp_ctx,
1560 * as that is freed after decoding every
1561 * packet. We wish to aggregate the tags
1562 * across multiple attributes.
1563 */
1564 new_tag_ctx = talloc_zero_array(NULL, fr_radius_tag_ctx_t *, 32);
1565 if (unlikely(!new_tag_ctx)) return PAIR_DECODE_OOM;
1566
1567 FR_PROTO_TRACE("Allocated tag cache %p", new_tag_ctx);
1568
1569 packet_ctx->tags = new_tag_ctx;
1570 }
1571
1572 fr_assert(tag < 0x20);
1573
1574 if (!packet_ctx->tags[tag]) {
1575 fr_pair_t *group;
1576 fr_dict_attr_t const *group_da;
1577
1578 packet_ctx->tags[tag] = talloc_zero(packet_ctx->tags, fr_radius_tag_ctx_t);
1579 if (unlikely(!packet_ctx->tags[tag])) {
1580 if (new_tag_ctx) TALLOC_FREE(packet_ctx->tags);
1581 return PAIR_DECODE_OOM;
1582 }
1583
1584 group_da = fr_dict_attr_child_by_num(fr_dict_root(dict_radius), FR_TAG_BASE + tag);
1585 if (unlikely(!group_da)) {
1586 tag_alloc_error:
1587 TALLOC_FREE(packet_ctx->tags[tag]);
1588 return PAIR_DECODE_OOM;
1589 }
1590
1591 group = fr_pair_afrom_da(packet_ctx->tag_root_ctx, group_da);
1592 if (unlikely(!group)) goto tag_alloc_error;
1593
1594 packet_ctx->tags[tag]->parent = group;
1595
1596 FR_PROTO_TRACE("Allocated tag attribute %p (%u)", group, tag);
1597
1598 fr_pair_append(packet_ctx->tag_root, group);
1599#ifdef TALLOC_GET_TYPE_ABORT_NOOP
1600 }
1601#else
1602 } else {
1603 talloc_get_type_abort(packet_ctx->tags, fr_radius_tag_ctx_t *);
1604 talloc_get_type_abort(packet_ctx->tags[tag], fr_radius_tag_ctx_t);
1605 talloc_get_type_abort(packet_ctx->tags[tag]->parent, fr_pair_t);
1606 }
1607#endif
1608 }
1609
1611 /*
1612 * Decrypt the attribute.
1613 */
1614 if (encrypt) {
1615 FR_PROTO_TRACE("Decrypting type %d", encrypt);
1616 /*
1617 * Encrypted attributes can only exist for the
1618 * old-style format. Extended attributes CANNOT
1619 * be encrypted.
1620 */
1621 if (attr_len > 253) goto raw;
1622
1623 if (p == data) memcpy(buffer, p, attr_len);
1624 p = buffer;
1625
1626 switch (encrypt) { /* can't be tagged */
1627 /*
1628 * User-Password
1629 */
1631 if (!packet_ctx->request_authenticator) goto raw;
1632
1633 fr_radius_decode_password((char *)buffer, attr_len, packet_ctx);
1634 buffer[253] = '\0';
1635
1636 /*
1637 * MS-CHAP-MPPE-Keys are 24 octets, and
1638 * encrypted. Since it's binary, we can't
1639 * look for trailing zeros.
1640 */
1641 if (parent->flags.length) {
1642 if (data_len > parent->flags.length) {
1643 data_len = parent->flags.length;
1644 } /* else leave data_len alone */
1645 } else {
1646 /*
1647 * Take off trailing zeros from the END.
1648 * This allows passwords to have zeros in
1649 * the middle of a field.
1650 *
1651 * However, if the password has a zero at
1652 * the end, it will get mashed by this
1653 * code. There's really no way around
1654 * that.
1655 */
1656 while ((data_len > 0) && (buffer[data_len - 1] == '\0')) data_len--;
1657 }
1658 break;
1659
1660 /*
1661 * Tunnel-Password's go in response packets,
1662 * except for CoA-Requests. They can have a tag,
1663 * so data_len is not the same as attrlen.
1664 */
1666 if (!packet_ctx->request_authenticator) goto raw;
1667
1668 if (fr_radius_decode_tunnel_password(buffer, &data_len, packet_ctx) < 0) {
1669 goto raw;
1670 }
1671 break;
1672
1673 /*
1674 * Ascend-Send-Secret
1675 * Ascend-Receive-Secret
1676 */
1678 if (!packet_ctx->request_authenticator) goto raw;
1679
1680 fr_radius_ascend_secret(&FR_DBUFF_TMP(buffer, sizeof(buffer)), p, data_len,
1681 packet_ctx->common->secret, packet_ctx->request_authenticator);
1683 data_len = strlen((char *) buffer);
1684 break;
1685
1686 default:
1687 /*
1688 * Chop the attribute to its maximum length.
1689 */
1690 if ((parent->type == FR_TYPE_OCTETS) &&
1691 (parent->flags.length && (data_len > parent->flags.length))) {
1692 data_len = parent->flags.length;
1693 }
1694 break;
1695 } /* switch over encryption flags */
1696 }
1697
1698 /*
1699 * Double-check the length after decrypting the
1700 * attribute.
1701 */
1702 FR_PROTO_TRACE("Type \"%s\" (%u)", fr_type_to_str(parent->type), parent->type);
1703
1704 switch (parent->type) {
1705 case FR_TYPE_LEAF:
1706 break;
1707
1708 case FR_TYPE_VSA:
1709 /*
1710 * VSAs in the RFC space are encoded one way.
1711 * VSAs in the "extended" space are different.
1712 */
1713 if (!parent->parent || !fr_radius_flag_extended(parent->parent)) {
1714 /*
1715 * VSAs can be WiMAX, in which case they don't
1716 * fit into one attribute.
1717 */
1718 ret = decode_vsa(ctx, out, parent, p, attr_len, packet_ctx);
1719 if (ret < 0) goto raw;
1720 return ret;
1721
1722 } else {
1723 fr_dict_attr_t const *vendor_da;
1724 fr_pair_t *vsa, *vendor;
1725 uint32_t vendor_pen;
1726
1727
1728 if (data_len < 6) goto raw; /* vid, vtype, value */
1729
1730 memcpy(&vendor_pen, p, 4);
1731 vendor_pen = ntohl(vendor_pen);
1732
1733 /*
1734 * For simplicity in our attribute tree, vendors are
1735 * represented as a subtlv(ish) of an EVS or VSA
1736 * attribute.
1737 */
1738 vendor_da = fr_dict_attr_child_by_num(parent, vendor_pen);
1739 if (!vendor_da) {
1740 /*
1741 * If there's no child, it means the vendor is unknown. Create a
1742 * temporary vendor in the packet_ctx. This will be cleaned up when the
1743 * decoder exists, which is fine. Because any unknown attributes which
1744 * depend on it will copy the entire hierarchy.
1745 */
1746 vendor_da = fr_dict_attr_unknown_vendor_afrom_num(packet_ctx->tmp_ctx, parent, vendor_pen);
1747 if (!vendor_da) return PAIR_DECODE_OOM;
1748 }
1749
1750 child = fr_dict_attr_child_by_num(vendor_da, p[4]);
1751 if (!child) {
1752 /*
1753 * Vendor exists but child didn't, create an unknown child.
1754 */
1755 child = fr_dict_attr_unknown_raw_afrom_num(packet_ctx->tmp_ctx, vendor_da, p[4]);
1756 if (!child) {
1757 fr_strerror_printf_push("decoder failed creating unknown attribute in %s",
1758 parent->name);
1759 return -1;
1760 }
1761 }
1762
1763 if (fr_pair_find_or_append_by_da(ctx, &vsa, out, parent) < 0) return PAIR_DECODE_OOM;
1764
1765 if (fr_pair_find_or_append_by_da(vsa, &vendor, &vsa->vp_group, vendor_da) < 0) return PAIR_DECODE_OOM;
1766
1767 /*
1768 * Everything was found in the dictionary, we can
1769 * now recurse to decode the value.
1770 */
1771 ret = fr_radius_decode_pair_value(vendor, &vendor->vp_group,
1772 child, p + 5, attr_len - 5,
1773 packet_ctx);
1774 if (ret < 0) goto raw;
1775 return attr_len;
1776 }
1777
1778 case FR_TYPE_TLV:
1779 /*
1780 * We presume that the TLVs all fit into one
1781 * attribute, OR they've already been grouped
1782 * into a contiguous memory buffer.
1783 */
1784 ret = fr_radius_decode_tlv(ctx, out, parent, p, attr_len, packet_ctx);
1785 if (ret < 0) goto raw;
1786 return attr_len;
1787
1788 case FR_TYPE_STRUCT:
1789 /*
1790 * We presume that the struct fits into one
1791 * attribute, OR it's already been grouped
1792 * into a contiguous memory buffer.
1793 */
1794 ret = fr_struct_from_network(ctx, out, parent, p, attr_len,
1796 if (ret < 0) goto raw;
1797 return attr_len;
1798
1799 case FR_TYPE_GROUP:
1800 {
1801 fr_dict_attr_t const *ref;
1802 fr_dict_protocol_t const *proto;
1803
1804 ref = fr_dict_attr_ref(parent);
1805 if (!ref) goto raw;
1806
1807 fr_assert(ref->dict != parent->dict);
1808
1809 proto = fr_dict_protocol(ref->dict);
1810 fr_assert(proto != NULL);
1811
1812 if (!proto->decode) goto raw;
1813
1814 vp = fr_pair_afrom_da(ctx, parent);
1815 if (!vp) return -1;
1816
1817 ret = proto->decode(vp, &vp->vp_group, p, attr_len);
1818 if (ret < 0) goto raw;
1819
1820 vp->vp_tainted = true;
1821
1823 return attr_len;
1824 }
1825
1826 default:
1827 raw:
1828 if (vp) talloc_free(vp);
1829
1830 return fr_pair_raw_from_network(ctx, out, parent, data, attr_len);
1831 }
1832
1833 /*
1834 * And now that we've verified the basic type
1835 * information, decode the actual p.
1836 */
1837 if (!tag) {
1838 vp = fr_pair_afrom_da(ctx, parent);
1839 } else {
1840 fr_assert(packet_ctx->tags != NULL);
1841 fr_assert(packet_ctx->tags[tag] != NULL);
1842 vp = fr_pair_afrom_da_nested(packet_ctx->tags[tag]->parent, &packet_ctx->tags[tag]->parent->vp_group, parent);
1843 }
1844 if (!vp) return -1;
1845
1846 switch (parent->type) {
1847 /*
1848 * Magic RADIUS format IPv4 prefix
1849 *
1850 * 0 1 2 3
1851 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
1852 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1853 * | Reserved | Prefix-Length | Prefix ...
1854 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1855 * ... Prefix |
1856 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1857 *
1858 * RFC does not require non-masked bits to be zero.
1859 */
1861 if (data_len != 6) goto raw;
1862 if (p[0] != 0) goto raw;
1863 if ((p[1] & 0x3f) > 32) goto raw;
1864
1865 vp->vp_ip.af = AF_INET;
1866 vp->vp_ip.scope_id = 0;
1867 vp->vp_ip.prefix = p[1] & 0x3f;
1868 memcpy((uint8_t *)&vp->vp_ipv4addr, p + 2, data_len - 2);
1869 fr_ipaddr_mask(&vp->vp_ip, p[1] & 0x3f);
1870 break;
1871
1872 /*
1873 * Magic RADIUS format IPv6 prefix
1874 *
1875 * 0 1 2 3
1876 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
1877 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1878 * | Type | Length | Reserved | Prefix-Length |
1879 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1880 * Prefix
1881 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1882 * Prefix
1883 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1884 * Prefix
1885 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1886 * Prefix |
1887 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1888 *
1889 * RFC says non-masked bits MUST be zero.
1890 */
1892 {
1893 if (data_len > 18) goto raw;
1894 if (data_len < 2) goto raw;
1895 if (p[0] != 0) goto raw; /* First byte is always 0 */
1896 if (p[1] > 128) goto raw;
1897
1898 /*
1899 * Convert prefix bits to bytes to check that
1900 * we have sufficient data.
1901 *
1902 * If Prefix has more data than Prefix-Length
1903 * indicates, we just ignore the rest.
1904 */
1905 if (fr_bytes_from_bits(p[1]) > (data_len - 2)) goto raw;
1906
1907 vp->vp_ip.af = AF_INET6;
1908 vp->vp_ip.scope_id = 0;
1909 vp->vp_ip.prefix = p[1];
1910
1911 memcpy((uint8_t *)&vp->vp_ipv6addr, p + 2, data_len - 2);
1912 fr_ipaddr_mask(&vp->vp_ip, p[1]);
1913
1914 /*
1915 * Check the prefix data is the same before
1916 * and after casting (it should be).
1917 */
1918 if (memcmp(p + 2, (uint8_t *)&vp->vp_ipv6addr, data_len - 2) != 0) goto raw;
1919 }
1920 break;
1921
1922 case FR_TYPE_STRING:
1924
1925 if (fr_radius_decode_abinary(vp, p, data_len) < 0) goto raw;
1926 break;
1927
1928 case FR_TYPE_OCTETS:
1929 /*
1930 * This attribute SHOULD have fixed size, but it
1931 * doesn't. Therefore it's malformed.
1932 */
1933 if (parent->flags.length && (data_len != parent->flags.length)) goto raw;
1935
1936 default:
1937 decode:
1938 ret = fr_value_box_from_network(vp, &vp->data, vp->vp_type, vp->da,
1939 &FR_DBUFF_TMP(p, data_len), data_len, true);
1940 if (ret < 0) {
1941 /*
1942 * Paranoid loop prevention
1943 */
1944 if (vp->da->flags.is_unknown) {
1945 talloc_free(vp);
1946 return -1;
1947 }
1948 goto raw;
1949 }
1950 break;
1951 }
1952
1953 vp->vp_tainted = true;
1954
1955 if (!tag) fr_pair_append(out, vp);
1956
1957 return attr_len;
1958}
1959
1960/*
1961 * Let's try to help the CPU as much as possible. If we have a
1962 * check on a buffer, that's less work than a series of if / then
1963 * / else conditions.
1964 */
1965static const bool special[UINT8_MAX + 1] = {
1966 [FR_NAS_FILTER_RULE] = true, /* magic rules */
1967 [FR_DIGEST_ATTRIBUTES] = true, /* magic rules */
1968
1969 [FR_EAP_MESSAGE] = true, /* concat */
1970 [FR_PKM_SS_CERT] = true, /* concat */
1971 [FR_PKM_CA_CERT] = true, /* concat */
1972 [FR_EAPOL_ANNOUNCEMENT] = true, /* concat */
1973
1974 [FR_EXTENDED_ATTRIBUTE_1] = true,
1975 [FR_EXTENDED_ATTRIBUTE_2] = true,
1976 [FR_EXTENDED_ATTRIBUTE_3] = true,
1977 [FR_EXTENDED_ATTRIBUTE_4] = true,
1978 [FR_EXTENDED_ATTRIBUTE_5] = true,
1979 [FR_EXTENDED_ATTRIBUTE_6] = true,
1980};
1981
1982/** Create a "normal" fr_pair_t from the given data
1983 *
1984 */
1986 uint8_t const *data, size_t data_len, fr_radius_decode_ctx_t *packet_ctx)
1987{
1988 ssize_t ret;
1989 fr_dict_attr_t const *da;
1990
1991 if ((data_len < 2) || (data[1] < 2) || (data[1] > data_len)) {
1992 fr_strerror_printf("%s: Insufficient data", __FUNCTION__);
1993 return -1;
1994 }
1995
1996 /*
1997 * If we don't have a tag root already, then record where
1998 * we're putting the top level attributes and add the tags
1999 * there.
2000 */
2001 if (!packet_ctx->tag_root) {
2002 packet_ctx->tag_root = out;
2003 packet_ctx->tag_root_ctx = ctx;
2004 }
2005
2007 if (!da) {
2008 FR_PROTO_TRACE("Unknown attribute %u", data[0]);
2010 }
2011 if (!da) return -1;
2012 FR_PROTO_TRACE("decode context changed %s -> %s",da->parent->name, da->name);
2013
2014 /*
2015 * Empty attributes are silently ignored, except for CUI.
2016 */
2017 if (data[1] == 2) {
2018 fr_pair_t *vp;
2019
2020 if (data[0] != FR_CHARGEABLE_USER_IDENTITY) {
2021 return 2;
2022 }
2023
2024 /*
2025 * Hacks for CUI. The WiMAX spec says that it can be
2026 * zero length, even though this is forbidden by the
2027 * RADIUS specs. So... we make a special case for it.
2028 *
2029 * We can't create a zero length attribute,
2030 * because the talloc API won't let us. So, we
2031 * just create a fake attribute.
2032 */
2033 vp = fr_pair_afrom_da(ctx, da);
2034 if (!vp) return -1;
2035
2037 vp->vp_tainted = true; /* not REALLY necessary, but what the heck */
2038
2039 return 2;
2040 }
2041
2042 /*
2043 * A few attributes are special, but they're rare.
2044 */
2045 if (unlikely(special[data[0]])) {
2046 if (data[0] == FR_NAS_FILTER_RULE) {
2047 return decode_nas_filter_rule(ctx, out, da, data, data_len, packet_ctx);
2048 }
2049
2050 if (data[0] == FR_DIGEST_ATTRIBUTES) {
2051 return decode_digest_attributes(ctx, out, da, data, data_len, packet_ctx);
2052 }
2053
2054 /*
2055 * Concatenate consecutive top-level attributes together.
2056 */
2057 if (fr_radius_flag_concat(da)) {
2058 FR_PROTO_TRACE("Concat attribute");
2059 return decode_concat(ctx, out, da, data, packet_ctx->end);
2060 }
2061
2062 /*
2063 * Extended attributes have a horrible format.
2064 * Try to deal with that here, so that the rest
2065 * of the code doesn't have to.
2066 */
2067 if (fr_radius_flag_extended(da)) {
2068 return decode_extended(ctx, out, da, data, data_len, packet_ctx);
2069 }
2070
2071 /*
2072 * @todo - pre-concatenate WiMAX, if 26, and dv->continuation, too.
2073 */
2074 }
2075
2076 /*
2077 * Note that we pass the entire length, not just the
2078 * length of this attribute. The Extended or WiMAX
2079 * attributes may have the "continuation" bit set, and
2080 * will thus be more than one attribute in length.
2081 */
2083 da, data + 2, data[1] - 2,
2084 packet_ctx);
2085 if (ret < 0) return ret;
2086
2087 fr_assert(ret < (1 << 16));
2088
2089 return 2 + ret;
2090}
2091
2093 uint8_t const *data, size_t data_len)
2094{
2095 ssize_t slen;
2096 uint8_t const *attr, *end;
2097
2098 fr_radius_ctx_t common_ctx = {};
2099 fr_radius_decode_ctx_t decode_ctx = {
2100 .common = &common_ctx,
2101 .tmp_ctx = talloc(ctx, uint8_t),
2102 .end = data + data_len,
2103 };
2104
2105 fr_assert(dict_radius != NULL);
2106
2107 attr = data;
2108 end = decode_ctx.end;
2109
2110 while (attr < end) {
2111 slen = fr_radius_decode_pair(ctx, out, attr, (end - attr), &decode_ctx);
2112 if (slen < 0) {
2113// fail:
2114 talloc_free(decode_ctx.tmp_ctx);
2115 talloc_free(decode_ctx.tags);
2116 return slen;
2117 }
2118
2119#if 0
2120 /*
2121 * If slen is larger than the room in the packet,
2122 * all kinds of bad things happen.
2123 */
2124 if (!fr_cond_assert(slen <= (end - attr))) {
2125 goto fail;
2126 }
2127#endif
2128
2129 attr += slen;
2130 talloc_free_children(decode_ctx.tmp_ctx);
2131 }
2132
2133 talloc_free(decode_ctx.tmp_ctx);
2134 talloc_free(decode_ctx.tags);
2135 return data_len;
2136}
2137
2139{
2140 TALLOC_FREE(ctx->tags);
2141
2142 return 0;
2143}
2144
2145static int decode_test_ctx(void **out, TALLOC_CTX *ctx, UNUSED fr_dict_t const *dict)
2146{
2147 static uint8_t vector[RADIUS_AUTH_VECTOR_LENGTH] = {
2148 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
2149 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
2150
2151 fr_radius_decode_ctx_t *test_ctx;
2152 fr_radius_ctx_t *common;
2153
2154 test_ctx = talloc_zero(ctx, fr_radius_decode_ctx_t);
2155 test_ctx->common = common = talloc_zero(test_ctx, fr_radius_ctx_t);
2156
2157 common->secret = talloc_strdup(test_ctx->common, "testing123");
2158 common->secret_length = talloc_array_length(test_ctx->common->secret) - 1;
2159
2160 test_ctx->request_authenticator = vector;
2161 test_ctx->tmp_ctx = talloc_zero(test_ctx, uint8_t);
2162 talloc_set_destructor(test_ctx, _test_ctx_free);
2163
2164 *out = test_ctx;
2165
2166 return 0;
2167}
2168
2169static const char *reason_name[DECODE_FAIL_MAX] = {
2170 [ DECODE_FAIL_NONE ] = "all OK",
2171 [ DECODE_FAIL_MIN_LENGTH_PACKET ] = "packet is too small",
2172 [ DECODE_FAIL_MAX_LENGTH_PACKET ] = "packet is too large",
2173 [ DECODE_FAIL_MIN_LENGTH_FIELD ] = "length field is too small",
2174 [ DECODE_FAIL_MIN_LENGTH_MISMATCH ] = "length mismatch",
2175 [ DECODE_FAIL_HEADER_OVERFLOW ] = "header overflow",
2176 [ DECODE_FAIL_UNKNOWN_PACKET_CODE ] = "unknown packet code",
2177 [ DECODE_FAIL_INVALID_ATTRIBUTE ] = "invalid attribute",
2178 [ DECODE_FAIL_ATTRIBUTE_TOO_SHORT ] = "attribute too short",
2179 [ DECODE_FAIL_ATTRIBUTE_OVERFLOW ] = "attribute overflows the packet",
2180 [ DECODE_FAIL_MA_INVALID_LENGTH ] = "invalid length for Message-Authenticator",
2181 [ DECODE_FAIL_ATTRIBUTE_UNDERFLOW ] = "attribute underflows the packet",
2182 [ DECODE_FAIL_TOO_MANY_ATTRIBUTES ] = "too many attributes",
2183 [ DECODE_FAIL_MA_MISSING ] = "Message-Authenticator is required, but missing",
2184 [ DECODE_FAIL_MA_INVALID ] = "Message-Authenticator is invalid",
2185 [ DECODE_FAIL_UNKNOWN ] = "unknown",
2186};
2187
2189 uint8_t const *data, size_t data_len, void *proto_ctx)
2190{
2191 fr_radius_decode_ctx_t *test_ctx = talloc_get_type_abort(proto_ctx, fr_radius_decode_ctx_t);
2193 fr_pair_t *vp;
2194 size_t packet_len = data_len;
2195
2196 if (!fr_radius_ok(data, &packet_len, 200, false, &reason)) {
2197 fr_strerror_printf("Packet failed verification - %s", reason_name[reason]);
2198 return -1;
2199 }
2200
2201 /*
2202 * Decode the header
2203 */
2205 if (!vp) {
2206 fr_strerror_const("Failed creating Packet-Type");
2207 return -1;
2208 }
2209 vp->vp_uint32 = data[0];
2211
2213 if (!vp) {
2214 fr_strerror_const("Failed creating Packet-Authentication-Vector");
2215 return -1;
2216 }
2217 (void) fr_pair_value_memdup(vp, data + 4, 16, true);
2219
2220 test_ctx->end = data + packet_len;
2221
2222 return fr_radius_decode(ctx, out, UNCONST(uint8_t *, data), packet_len, test_ctx);
2223}
2224
2226 uint8_t const *data, size_t data_len, void *decode_ctx)
2227{
2228 fr_radius_decode_ctx_t *packet_ctx = decode_ctx;
2229
2231
2232 packet_ctx->end = data + data_len;
2233 return fr_radius_decode_pair(ctx, out, data, data_len, decode_ctx);
2234}
2235
2236
2237/*
2238 * Test points
2239 */
2245
ssize_t fr_radius_decode_abinary(fr_pair_t *vp, uint8_t const *data, size_t data_len)
Print an Ascend binary filter attribute to a string,.
Definition abinary.c:1316
static int const char char buffer[256]
Definition acutest.h:576
int n
Definition acutest.h:577
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
Definition build.h:167
#define RCSID(id)
Definition build.h:483
#define NDEBUG_UNUSED
Definition build.h:326
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
Definition build.h:322
#define unlikely(_x)
Definition build.h:381
#define UNUSED
Definition build.h:315
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
Definition dbuff.h:514
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition debug.h:139
#define FR_DIGEST_ATTRIBUTES
Definition defs.h:110
static fr_dict_attr_t const * attr_packet_type
Definition dhcpclient.c:89
bool continuation
we only have one flag for now, for WiMAX
Definition dict.h:247
size_t type
Length of type data.
Definition dict.h:248
fr_dict_attr_decode_func_t decode
for decoding attributes.
Definition dict.h:460
static fr_dict_attr_t * fr_dict_attr_unknown_vendor_afrom_num(TALLOC_CTX *ctx, fr_dict_attr_t const *parent, unsigned int vendor)
Definition dict.h:572
fr_dict_protocol_t const * fr_dict_protocol(fr_dict_t const *dict)
Return the protocol descriptor for the dictionary.
Definition dict_util.c:4952
static fr_dict_attr_t * fr_dict_attr_unknown_raw_afrom_num(TALLOC_CTX *ctx, fr_dict_attr_t const *parent, unsigned int attr)
Definition dict.h:579
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
Definition dict_util.c:2404
uint32_t pen
Private enterprise number.
Definition dict.h:246
void fr_dict_attr_unknown_free(fr_dict_attr_t const **da)
Free dynamically allocated (unknown attributes)
size_t length
Length of length data.
Definition dict.h:249
static fr_dict_attr_t * fr_dict_attr_unknown_typed_afrom_num(TALLOC_CTX *ctx, fr_dict_attr_t const *parent, unsigned int num, fr_type_t type)
Definition dict.h:564
fr_dict_vendor_t const * fr_dict_vendor_by_num(fr_dict_t const *dict, uint32_t vendor_pen)
Look up a vendor by its PEN.
Definition dict_util.c:2684
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_util.c:3332
Protocol-specific callbacks in libfreeradius-PROTOCOL.
Definition dict.h:428
Private enterprise.
Definition dict.h:245
static fr_dict_attr_t const * fr_dict_attr_ref(fr_dict_attr_t const *da)
Return the reference associated with a group type attribute.
Definition dict_ext.h:184
void fr_ipaddr_mask(fr_ipaddr_t *addr, uint8_t prefix)
Zeroes out the host portion of an fr_ipaddr_t.
Definition inet.c:217
#define PAIR_DECODE_OOM
Fatal error - Out of memory.
Definition pair.h:45
#define PAIR_DECODE_FATAL_ERROR
Fatal error - Failed decoding the packet.
Definition pair.h:49
static int _test_ctx_free(UNUSED fr_aka_sim_ctx_t *ctx)
Definition decode.c:1004
ssize_t fr_pair_tlvs_from_network(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, uint8_t const *data, size_t const data_len, void *decode_ctx, fr_pair_decode_value_t decode_tlv, fr_pair_tlvs_verify_t verify_tlvs, bool nested)
Decode a list of pairs from the network.
Definition decode.c:148
ssize_t fr_pair_array_from_network(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, uint8_t const *data, size_t data_len, void *decode_ctx, fr_pair_decode_value_t decode_value)
Decode an array of values from the network.
Definition decode.c:41
ssize_t fr_pair_raw_from_network(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, uint8_t const *data, size_t data_len)
Create a "raw" pair from the network data.
Definition decode.c:79
talloc_free(reap)
static const uint8_t * zero
Definition md4.c:358
fr_md5_update_t fr_md5_update
Definition md5.c:442
fr_md5_final_t fr_md5_final
Definition md5.c:443
void fr_md5_ctx_free_from_list(fr_md5_ctx_t **ctx)
Definition md5.c:522
fr_md5_ctx_copy_t fr_md5_ctx_copy
Definition md5.c:439
fr_md5_ctx_t * fr_md5_ctx_alloc_from_list(void)
Definition md5.c:477
void fr_md5_ctx_t
Definition md5.h:28
bool fr_radius_ok(uint8_t const *packet, size_t *packet_len_p, uint32_t max_attributes, bool require_message_authenticator, decode_fail_t *reason)
@ FR_TYPE_TLV
Contains nested attributes.
@ FR_TYPE_IPV6_PREFIX
IPv6 Prefix.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_STRUCT
like TLV, but without T or L, and fixed-width children
@ FR_TYPE_VENDOR
Attribute that represents a vendor in the attribute tree.
@ FR_TYPE_IPV4_PREFIX
IPv4 Prefix.
@ FR_TYPE_VSA
Vendor-Specific, for RADIUS attribute 26.
@ FR_TYPE_OCTETS
Raw octets.
@ FR_TYPE_GROUP
A grouping of other attributes.
unsigned int uint32_t
long int ssize_t
unsigned char uint8_t
#define UINT8_MAX
static fr_radius_decode_fail_t decode(TALLOC_CTX *ctx, fr_pair_list_t *reply, uint8_t *response_code, bio_handle_t *h, request_t *request, bio_request_t *u, uint8_t const request_authenticator[static RADIUS_AUTH_VECTOR_LENGTH], uint8_t *data, size_t data_len)
Decode response packet data, extracting relevant information and validating the packet.
Definition bio.c:1096
#define check(_handle, _len_p)
Definition bio.c:44
static unsigned int fr_bytes_from_bits(unsigned int bits)
Convert bits (as in prefix length) to bytes, rounding up.
Definition nbo.h:237
#define RADIUS_AUTH_VECTOR_LENGTH
Definition net.h:89
int fr_pair_value_memdup(fr_pair_t *vp, uint8_t const *src, size_t len, bool tainted)
Copy data into an "octets" data type.
Definition pair.c:2981
int fr_pair_append(fr_pair_list_t *list, fr_pair_t *to_add)
Add a VP to the end of the list.
Definition pair.c:1345
fr_pair_t * fr_pair_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
Dynamically allocate a new attribute and assign a fr_dict_attr_t.
Definition pair.c:283
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
Definition pair.c:46
int fr_pair_value_bstrndup(fr_pair_t *vp, char const *src, size_t len, bool tainted)
Copy data into a "string" type value pair.
Definition pair.c:2784
int fr_pair_delete(fr_pair_list_t *list, fr_pair_t *vp)
Remove fr_pair_t from a list and free.
Definition pair.c:1826
int fr_pair_value_mem_alloc(fr_pair_t *vp, uint8_t **out, size_t size, bool tainted)
Pre-allocate a memory buffer for a "octets" type value pair.
Definition pair.c:2930
fr_pair_t * fr_pair_afrom_da_nested(TALLOC_CTX *ctx, fr_pair_list_t *list, fr_dict_attr_t const *da)
Create a pair (and all intermediate parents), and append it to the list.
Definition pair.c:467
static int decode_test_ctx(void **out, TALLOC_CTX *ctx, UNUSED fr_dict_t const *dict)
Definition decode.c:102
static ssize_t decode_value_trampoline(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, uint8_t const *data, size_t const data_len, void *decode_ctx)
Handle arrays of DNS labels for fr_struct_from_network()
Definition decode.c:70
static ssize_t decode_vsa(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, uint8_t const *data, size_t const data_len, void *decode_ctx)
RFC 4243 Vendor Specific Suboptions.
Definition decode.c:349
static ssize_t decode_tlv_trampoline(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, uint8_t const *data, size_t const data_len, void *decode_ctx)
Definition decode.c:57
static ssize_t decode_pair(TALLOC_CTX *ctx, fr_pair_list_t *out, NDEBUG_UNUSED fr_dict_attr_t const *parent, uint8_t const *data, size_t data_len, void *decode_ctx)
Definition decode.c:502
HIDDEN fr_dict_attr_t const * attr_packet_authentication_vector
Definition base.c:54
ssize_t fr_radius_ascend_secret(fr_dbuff_t *dbuff, uint8_t const *in, size_t inlen, char const *secret, uint8_t const *vector)
Do Ascend-Send / Recv-Secret calculation.
Definition base.c:247
ssize_t fr_radius_decode(TALLOC_CTX *ctx, fr_pair_list_t *out, uint8_t *packet, size_t packet_len, fr_radius_decode_ctx_t *decode_ctx)
Definition base.c:1088
fr_test_point_proto_decode_t radius_tp_decode_proto
Definition decode.c:2247
ssize_t fr_radius_decode_foreign(TALLOC_CTX *ctx, fr_pair_list_t *out, uint8_t const *data, size_t data_len)
Definition decode.c:2092
static ssize_t decode_concat(TALLOC_CTX *ctx, fr_pair_list_t *list, fr_dict_attr_t const *parent, uint8_t const *data, uint8_t const *end)
Convert a "concatenated" attribute to one long VP.
Definition decode.c:342
static ssize_t decode_extended(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *da, uint8_t const *data, UNUSED size_t data_len, fr_radius_decode_ctx_t *packet_ctx)
Fast path for most extended attributes.
Definition decode.c:953
static ssize_t decode_digest_attributes(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, uint8_t const *data, size_t const data_len, fr_radius_decode_ctx_t *packet_ctx)
Decode Digest-Attributes.
Definition decode.c:597
static ssize_t decode_wimax(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, uint8_t const *data, size_t attr_len, fr_radius_decode_ctx_t *packet_ctx)
Convert a Vendor-Specific WIMAX to vps.
Definition decode.c:1037
ssize_t fr_radius_decode_tlv(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, uint8_t const *data, size_t data_len, fr_radius_decode_ctx_t *packet_ctx)
Convert TLVs to one or more VPs.
Definition decode.c:647
static const char * reason_name[DECODE_FAIL_MAX]
Definition decode.c:2169
fr_test_point_pair_decode_t radius_tp_decode_pair
Definition decode.c:2241
#define decode_value
Definition decode.c:410
static void memcpy_bounded(void *restrict dst, const void *restrict src, size_t n, const void *restrict end)
Definition decode.c:42
static ssize_t fr_radius_decode_password(char *passwd, size_t pwlen, fr_radius_decode_ctx_t *packet_ctx)
Decode password.
Definition decode.c:191
ssize_t fr_radius_decode_pair_value(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, uint8_t const *data, size_t const attr_len, void *decode_ctx)
Create any kind of VP from the attribute contents.
Definition decode.c:1477
static ssize_t decode_extended_fragments(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, uint8_t const *data, size_t attr_len, fr_radius_decode_ctx_t *packet_ctx)
Convert a fragmented extended attr to a VP.
Definition decode.c:848
static const bool special[UINT8_MAX+1]
Definition decode.c:1965
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.
Definition decode.c:250
ssize_t fr_radius_decode_pair(TALLOC_CTX *ctx, fr_pair_list_t *out, uint8_t const *data, size_t data_len, fr_radius_decode_ctx_t *packet_ctx)
Create a "normal" fr_pair_t from the given data.
Definition decode.c:1985
static ssize_t decode_vsa_internal(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, uint8_t const *data, size_t data_len, fr_radius_decode_ctx_t *packet_ctx, fr_dict_vendor_t const *dv)
Convert a top-level VSA to a VP.
Definition decode.c:726
static ssize_t decode_rfc(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, uint8_t const *data, size_t const data_len, void *decode_ctx)
decode an RFC-format TLV
Definition decode.c:415
static ssize_t decode_nas_filter_rule(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, uint8_t const *data, size_t const data_len, fr_radius_decode_ctx_t *packet_ctx)
Decode NAS-Filter-Rule.
Definition decode.c:484
static ssize_t fr_radius_decode_tunnel_password(uint8_t *passwd, size_t *pwlen, fr_radius_decode_ctx_t *packet_ctx)
Decode Tunnel-Password encrypted attributes.
Definition decode.c:70
static ssize_t fr_radius_decode_proto(TALLOC_CTX *ctx, fr_pair_list_t *out, uint8_t const *data, size_t data_len, void *proto_ctx)
Definition decode.c:2188
VQP attributes.
#define fr_assert(_expr)
Definition rad_assert.h:38
static fr_dict_t const * dict_radius
static bool done
Definition radclient.c:80
fr_pair_t * parent
Definition radius.h:90
fr_radius_tag_ctx_t ** tags
for decoding tagged attributes
Definition radius.h:139
#define fr_radius_flag_concat(_da)
Definition radius.h:192
#define fr_radius_flag_has_tag(_da)
Definition radius.h:191
uint8_t const * request_authenticator
Definition radius.h:127
#define AUTH_PASS_LEN
Definition radius.h:54
fr_radius_decode_fail_t
Failure reasons.
Definition radius.h:162
@ DECODE_FAIL_UNKNOWN
Definition radius.h:178
@ DECODE_FAIL_INVALID_ATTRIBUTE
Definition radius.h:170
@ DECODE_FAIL_ATTRIBUTE_UNDERFLOW
Definition radius.h:174
@ DECODE_FAIL_MIN_LENGTH_FIELD
Definition radius.h:166
@ DECODE_FAIL_MAX_LENGTH_PACKET
Definition radius.h:165
@ DECODE_FAIL_HEADER_OVERFLOW
Definition radius.h:168
@ DECODE_FAIL_ATTRIBUTE_TOO_SHORT
Definition radius.h:171
@ DECODE_FAIL_MA_INVALID
Definition radius.h:177
@ DECODE_FAIL_ATTRIBUTE_OVERFLOW
Definition radius.h:172
@ DECODE_FAIL_TOO_MANY_ATTRIBUTES
Definition radius.h:175
@ DECODE_FAIL_NONE
Definition radius.h:163
@ DECODE_FAIL_MIN_LENGTH_PACKET
Definition radius.h:164
@ DECODE_FAIL_MIN_LENGTH_MISMATCH
Definition radius.h:167
@ DECODE_FAIL_MA_INVALID_LENGTH
Definition radius.h:173
@ DECODE_FAIL_MAX
Definition radius.h:179
@ DECODE_FAIL_MA_MISSING
Definition radius.h:176
@ DECODE_FAIL_UNKNOWN_PACKET_CODE
Definition radius.h:169
char const * secret
Definition radius.h:95
uint8_t const * end
end of the packet
Definition radius.h:130
#define RADIUS_MAX_STRING_LENGTH
Definition radius.h:35
#define fr_radius_flag_encrypted(_da)
Definition radius.h:194
static bool fr_radius_flag_extended(fr_dict_attr_t const *da)
Definition radius.h:196
TALLOC_CTX * tag_root_ctx
Where to allocate new tag attributes.
Definition radius.h:141
size_t secret_length
Definition radius.h:96
#define RADIUS_MAX_PASS_LENGTH
Definition radius.h:39
fr_radius_ctx_t const * common
Definition radius.h:125
#define fr_radius_flag_long_extended(_da)
Definition radius.h:203
fr_radius_attr_flags_encrypt_t
Definition radius.h:144
@ RADIUS_FLAG_ENCRYPT_USER_PASSWORD
Encrypt attribute RFC 2865 style.
Definition radius.h:147
@ RADIUS_FLAG_ENCRYPT_ASCEND_SECRET
Encrypt attribute ascend style.
Definition radius.h:149
@ RADIUS_FLAG_ENCRYPT_TUNNEL_PASSWORD
Encrypt attribute RFC 2868 style.
Definition radius.h:148
#define fr_radius_flag_abinary(_da)
Definition radius.h:193
bool tunnel_password_zeros
check for trailing zeros on decode
Definition radius.h:134
TALLOC_CTX * tmp_ctx
for temporary things cleaned up during decoding
Definition radius.h:129
fr_pair_list_t * tag_root
Where to insert tag attributes.
Definition radius.h:140
static fr_dict_attr_t const * attr_vendor_specific
Definition radsnmp.c:113
fr_pair_t * vp
ssize_t fr_struct_from_network(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, uint8_t const *data, size_t data_len, void *decode_ctx, fr_pair_decode_value_t decode_value, fr_pair_decode_value_t decode_tlv)
Convert a STRUCT to one or more VPs.
Definition struct.c:33
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
fr_dict_attr_t const *_CONST da
Dictionary attribute defines the attribute number, vendor and type of the pair.
Definition pair.h:69
fr_test_point_ctx_alloc_t test_ctx
Allocate a test ctx for the encoder.
Definition test_point.h:85
fr_test_point_ctx_alloc_t test_ctx
Allocate a test ctx for the encoder.
Definition test_point.h:67
Entry point for pair decoders.
Definition test_point.h:84
Entry point for protocol decoders.
Definition test_point.h:66
static fr_slen_t head
Definition xlat.h:422
static int fr_pair_find_or_append_by_da(TALLOC_CTX *ctx, fr_pair_t **out, fr_pair_list_t *list, fr_dict_attr_t const *da)
Definition pair.h:523
void fr_pair_list_free(fr_pair_list_t *list)
Free memory used by a valuepair list.
void fr_pair_list_append(fr_pair_list_t *dst, fr_pair_list_t *src)
Appends a list of fr_pair_t from a temporary list to a destination list.
size_t fr_pair_list_num_elements(fr_pair_list_t const *list)
Get the length of a list of fr_pair_t.
static fr_slen_t parent
Definition pair.h:851
#define FR_PROTO_HEX_DUMP(_data, _data_len, _fmt,...)
Definition proto.h:41
#define FR_PROTO_TRACE(_fmt,...)
Definition proto.h:40
char const * fr_strerror(void)
Get the last library error.
Definition strerror.c:554
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition strerror.h:64
#define fr_strerror_printf_push(_fmt,...)
Add a message to an existing stack of messages at the tail.
Definition strerror.h:84
#define fr_strerror_const(_msg)
Definition strerror.h:223
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
Definition types.h:433
#define FR_TYPE_LEAF
Definition types.h:297
ssize_t fr_value_box_from_network(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t type, fr_dict_attr_t const *enumv, fr_dbuff_t *dbuff, size_t len, bool tainted)
Decode a fr_value_box_t from serialized binary data.
Definition value.c:1754
static fr_slen_t data
Definition value.h:1265
int nonnull(2, 5))
static size_t char ** out
Definition value.h:997