Coverage Report

Created: 2026-01-17 07:10

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