Coverage Report

Created: 2026-05-11 06:44

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