Coverage Report

Created: 2026-09-28 06:27

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/freeradius-server/src/lib/util/cbor.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
/** CBPR encoding and decoding
18
 *
19
 * @file src/lib/util/cbor.c
20
 *
21
 * @copyright 2024 Network RADIUS SAS (legal@networkradius.com)
22
 */
23
RCSID("$Id: 8f2fd049283373f80677caa5f759cdca30f0ec4c $")
24
25
#include <freeradius-devel/util/cbor.h>
26
27
713k
#define CBOR_INTEGER  (0)
28
7.05k
#define CBOR_NEGATIVE (1)
29
36.3k
#define CBOR_OCTETS (2)
30
4.66k
#define CBOR_STRING (3)
31
10.4k
#define CBOR_ARRAY  (4)
32
610k
#define CBOR_MAP  (5)
33
17.1k
#define CBOR_TAG  (6)
34
1.04M
#define CBOR_FLOAT  (7)
35
36
86.5k
#define CBOR_1_BYTE ((uint8_t) 24)
37
77.0k
#define CBOR_2_BYTE ((uint8_t) 25)
38
4.51k
#define CBOR_4_BYTE ((uint8_t) 26)
39
3.13k
#define CBOR_8_BYTE ((uint8_t) 27)
40
41
static const char *cbor_type_to_str[8] = {
42
  "integer", "negative", "octets", "string",
43
  "array", "map", "tag", "float"
44
};
45
46
/*
47
 *  Some of our data types need tags.
48
 *
49
 *  We don't have a tag to data type array.  When decoding, we should usually have the enclosing pair
50
 *  number, which includes our data type.  If the tag type doesn't match the value here, then something is
51
 *  wrong.
52
 */
53
static const uint64_t cbor_type_to_tag[FR_TYPE_MAX + 1] = {
54
  [FR_TYPE_DATE] = 1,
55
  [FR_TYPE_ETHERNET] = 48,
56
  [FR_TYPE_IPV4_ADDR] = 52,
57
  [FR_TYPE_IPV4_PREFIX] = 52,
58
  [FR_TYPE_IPV6_ADDR] = 54,
59
  [FR_TYPE_IPV6_PREFIX] = 54,
60
  [FR_TYPE_TIME_DELTA] = 1002,
61
};
62
63
static fr_type_t cbor_guess_type(fr_dbuff_t *dbuff, bool pair);
64
65
static ssize_t cbor_encode_integer(fr_dbuff_t *dbuff, uint8_t type, uint64_t data)
66
0
{
67
0
  fr_dbuff_t  work_dbuff = FR_DBUFF(dbuff);
68
0
  uint8_t   value[8];
69
70
0
  fr_assert(type < 8);
71
0
  type <<= 5;
72
73
0
  if (data < 24) {
74
0
    data |= type;
75
76
0
    FR_DBUFF_IN_BYTES_RETURN(&work_dbuff, (uint8_t) (data & 0xff));
77
0
    goto done;
78
0
  }
79
80
0
  if (data < (((uint64_t) 1) << 8)) {
81
0
    value[0] = data;
82
83
0
    FR_DBUFF_IN_BYTES_RETURN(&work_dbuff, (uint8_t) (type | CBOR_1_BYTE));
84
0
    FR_DBUFF_IN_RETURN(&work_dbuff, value[0]);
85
0
    goto done;
86
0
  }
87
88
0
  if (data < (((uint64_t) 1) << 16)) {
89
0
    fr_nbo_from_uint16(value, data);
90
91
0
    FR_DBUFF_IN_BYTES_RETURN(&work_dbuff, (uint8_t) (type | CBOR_2_BYTE));
92
0
    FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff, value, 2);
93
0
    goto done;
94
0
  }
95
96
0
  if (data < (((uint64_t) 1) << 32)) {
97
0
    fr_nbo_from_uint32(value, data);
98
99
0
    FR_DBUFF_IN_BYTES_RETURN(&work_dbuff, (uint8_t) (type | CBOR_4_BYTE));
100
0
    FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff, value, 4);
101
0
    goto done;
102
0
  }
103
104
0
  fr_nbo_from_uint64(value, data);
105
106
  /*
107
   *  Has to be 8 bytes.
108
   */
109
0
  FR_DBUFF_IN_BYTES_RETURN(&work_dbuff, type | CBOR_8_BYTE);
110
0
  FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff, value, 8);
111
112
0
done:
113
0
  return fr_dbuff_set(dbuff, &work_dbuff);
114
0
}
115
116
0
#define cbor_encode_array(_dbuff, _size) cbor_encode_integer(_dbuff, CBOR_ARRAY, _size)
117
118
0
#define cbor_encode_tag(_dbuff, _tag) cbor_encode_integer(_dbuff, CBOR_TAG, _tag)
119
120
/*
121
 *  Make many things easier
122
 */
123
5.10k
#define return_slen return FR_DBUFF_ERROR_OFFSET(slen, fr_dbuff_used(&work_dbuff))
124
125
/*
126
 *  Octets is length + data
127
 */
128
static ssize_t cbor_encode_octets(fr_dbuff_t *dbuff, uint8_t const *data, size_t data_len)
129
0
{
130
0
  fr_dbuff_t  work_dbuff = FR_DBUFF(dbuff);
131
0
  ssize_t slen;
132
133
0
  slen = cbor_encode_integer(&work_dbuff, CBOR_OCTETS, data_len);
134
0
  if (slen <= 0) return_slen;
135
136
0
  if (data_len > 0) FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff, data, data_len);
137
138
0
  return fr_dbuff_set(dbuff, &work_dbuff);
139
0
}
140
141
static ssize_t cbor_encode_int64(fr_dbuff_t *dbuff, int64_t neg)
142
0
{
143
0
  fr_dbuff_t  work_dbuff = FR_DBUFF(dbuff);
144
0
  ssize_t slen;
145
146
0
  if (neg >= 0) {
147
0
    slen = cbor_encode_integer(&work_dbuff, CBOR_INTEGER, neg);
148
0
  } else {
149
0
    uint64_t data;
150
151
0
    neg++;
152
0
    data = -neg;
153
0
    slen = cbor_encode_integer(&work_dbuff, CBOR_NEGATIVE, data);
154
0
  }
155
0
  if (slen <= 0) return_slen;
156
157
0
  return fr_dbuff_set(dbuff, &work_dbuff);
158
0
}
159
160
0
#define cbor_encode_key cbor_encode_int64
161
162
/** Encode CBOR
163
 *
164
 *  Values 0..23 can be encoded in place.  Other values can be encoded using the closest smallest integer
165
 */
166
ssize_t fr_cbor_encode_value_box(fr_dbuff_t *dbuff, fr_value_box_t *vb)
167
0
{
168
0
  fr_dbuff_t  work_dbuff = FR_DBUFF(dbuff);
169
0
  uint8_t   type = CBOR_INTEGER;
170
0
  uint64_t  data;
171
0
  int64_t   neg;
172
0
  ssize_t   slen;
173
0
  uint8_t   const *p, *end;
174
175
0
  switch (vb->type) {
176
0
  case FR_TYPE_BOOL:
177
    /*
178
     *  One byte of FLOAT (i.e. special value), and the boolean as a "simple value".
179
     */
180
0
    FR_DBUFF_IN_BYTES_RETURN(&work_dbuff, (uint8_t) ((CBOR_FLOAT << 5) | (20 + vb->vb_bool)));
181
0
    break;
182
183
0
  case FR_TYPE_UINT8:
184
0
    data = vb->vb_uint8;
185
0
    goto encode_int;
186
187
0
  case FR_TYPE_UINT16:
188
0
    data = vb->vb_uint16;
189
0
    goto encode_int;
190
191
0
  case FR_TYPE_UINT32:
192
0
    data = vb->vb_uint32;
193
0
    goto encode_int;
194
195
0
  case FR_TYPE_UINT64:
196
0
    data = vb->vb_uint64;
197
0
    goto encode_int;
198
199
  /*
200
   *  Negative numbers.
201
   */
202
0
  case FR_TYPE_INT8:
203
0
    neg = vb->vb_int8;
204
0
    goto encode_neg;
205
206
0
  case FR_TYPE_INT16:
207
0
    neg = vb->vb_int16;
208
0
    goto encode_neg;
209
210
0
  case FR_TYPE_INT32:
211
0
    neg = vb->vb_int32;
212
0
    goto encode_neg;
213
214
0
  case FR_TYPE_INT64:
215
0
    neg = vb->vb_int64;
216
0
  encode_neg:
217
0
    if (neg >= 0) {
218
0
      type = CBOR_INTEGER;
219
0
      data = neg;
220
0
      goto encode_int;
221
0
    }
222
223
    /*
224
     *  convert -1..-2^63 to 0..-(2^63-1)
225
     *  and then it fits into a positive integer.
226
     */
227
0
    neg++;
228
0
    data = -neg;
229
230
0
  encode_int:
231
0
    return cbor_encode_integer(dbuff, type, data);
232
233
0
  case FR_TYPE_OCTETS:
234
0
    return cbor_encode_octets(dbuff, vb->vb_octets, vb->vb_length);
235
236
0
  case FR_TYPE_STRING:
237
0
    slen = cbor_encode_integer(&work_dbuff, CBOR_STRING, vb->vb_length);
238
0
    if (slen <= 0) return_slen;
239
240
0
    if (vb->vb_length) FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff, vb->vb_strvalue, vb->vb_length);
241
0
    break;
242
243
    /*
244
     *  More complex data types are represented by type "tag", followed by a tag number.  The
245
     *  actual data is then encoded as the next item after the tag.
246
     */
247
0
  case FR_TYPE_ETHERNET:
248
0
    slen = cbor_encode_tag(&work_dbuff, cbor_type_to_tag[vb->type]);
249
0
    if (slen <= 0) return_slen;
250
251
0
    slen = cbor_encode_octets(&work_dbuff, vb->vb_ether, sizeof(vb->vb_ether));
252
0
    if (slen <= 0) return_slen;
253
0
    break;
254
255
    /*
256
     *  Tag 1, with integer seconds since epoch.
257
     *
258
     *  @todo - if the input has time resolution, then save it in that format.
259
     *
260
     *  RFC 9581 Section 3.
261
     *
262
     *  A tag with key 1001, and then: a map with required key 1 (integer epoch seconds) and
263
     *  optional key -3 (milliseconds), -6 (microseconds), or -9 (integer nanoseconds).
264
     *
265
     *  For the encoder, there are a ton of different formats for dates, and we shouldn't
266
     *  bother to parse them all. :(
267
     */
268
0
  case FR_TYPE_DATE:
269
0
    slen = cbor_encode_tag(&work_dbuff, cbor_type_to_tag[vb->type]);
270
0
    if (slen <= 0) return_slen;
271
272
0
    neg = fr_unix_time_to_sec(vb->vb_date);
273
0
    slen = cbor_encode_int64(&work_dbuff, neg);
274
0
    if (slen <= 0) return_slen;
275
0
    break;
276
277
    /*
278
     *  RFC 9581 Section 4.
279
     *
280
     *  A tag with key 1002, and then: a map with required key 1 (integer seconds) and
281
     *  optional key -3 (milliseconds), -6 (microseconds), or -9 (integer nanoseconds).
282
     */
283
0
  case FR_TYPE_TIME_DELTA:
284
0
    slen = cbor_encode_tag(&work_dbuff, cbor_type_to_tag[vb->type]);
285
0
    if (slen <= 0) return_slen;
286
287
0
    neg = fr_time_delta_unwrap(vb->vb_time_delta) % NSEC;
288
289
0
    slen = cbor_encode_integer(&work_dbuff, CBOR_MAP, 1 + (neg != 0));
290
0
    if (slen <= 0) return_slen;
291
292
    /*
293
     *  1: seconds
294
     */
295
0
    slen = cbor_encode_key(&work_dbuff, 1);
296
0
    if (slen <= 0) return_slen;
297
298
0
    slen = cbor_encode_int64(&work_dbuff, fr_time_delta_to_sec(vb->vb_time_delta));
299
0
    if (slen <= 0) return_slen;
300
301
    /*
302
     *  -9: nanoseconds
303
     */
304
0
    if (neg) {
305
0
      slen = cbor_encode_key(&work_dbuff, -9);
306
0
      if (slen <= 0) return_slen;
307
308
0
      slen = cbor_encode_int64(&work_dbuff, neg);
309
0
      if (slen <= 0) return_slen;
310
0
    }
311
0
    break;
312
313
    /*
314
     *  RFC 9164, Section 3.3
315
     *
316
     *
317
     *  tag=IPv4 + address + optional (prefix + scope)
318
     */
319
0
  case FR_TYPE_IPV4_ADDR:
320
0
    slen = cbor_encode_tag(&work_dbuff, cbor_type_to_tag[vb->type]);
321
0
    if (slen <= 0) return_slen;
322
323
0
    if (vb->vb_ip.scope_id != 0) {
324
0
      FR_DBUFF_IN_BYTES_RETURN(&work_dbuff, (uint8_t) ((CBOR_ARRAY << 5) | 3));
325
326
0
    }
327
328
0
    slen = cbor_encode_octets(&work_dbuff, (uint8_t const *) &vb->vb_ipv4addr, 4);
329
0
    if (slen <= 0) return_slen;
330
331
0
    if (vb->vb_ip.scope_id == 0) break;
332
333
0
    slen = cbor_encode_integer(&work_dbuff, CBOR_INTEGER, (uint8_t) 32);
334
0
    if (slen <= 0) return_slen;
335
336
0
    slen = cbor_encode_integer(&work_dbuff, CBOR_INTEGER, vb->vb_ip.scope_id);
337
0
    if (slen <= 0) return_slen;
338
0
    break;
339
340
    /*
341
     *  RFC 9164, Section 3.2
342
     *
343
     *  tag=IPv6 + address + optional (prefix + scope)
344
     */
345
0
  case FR_TYPE_IPV6_ADDR:
346
0
    slen = cbor_encode_tag(&work_dbuff, cbor_type_to_tag[vb->type]);
347
0
    if (slen <= 0) return_slen;
348
349
0
    if (vb->vb_ip.scope_id != 0) {
350
0
      FR_DBUFF_IN_BYTES_RETURN(&work_dbuff, (uint8_t) ((CBOR_ARRAY << 5) | 3));
351
0
    }
352
353
0
    slen = cbor_encode_octets(&work_dbuff, (uint8_t const *) &vb->vb_ipv6addr, 16);
354
0
    if (slen <= 0) return_slen;
355
356
0
    if (vb->vb_ip.scope_id == 0) break;
357
358
0
    slen = cbor_encode_integer(&work_dbuff, CBOR_INTEGER, (uint8_t) 128);
359
0
    if (slen <= 0) return_slen;
360
361
0
    slen = cbor_encode_integer(&work_dbuff, CBOR_INTEGER, vb->vb_ip.scope_id);
362
0
    if (slen <= 0) return_slen;
363
0
    break;
364
365
    /*
366
     *  RFC 9164, Section 3.3
367
     *
368
     *  tag=IPv4 + array(prefix-length, address)
369
     */
370
0
  case FR_TYPE_IPV4_PREFIX:
371
0
    slen = cbor_encode_tag(&work_dbuff, cbor_type_to_tag[vb->type]);
372
0
    if (slen <= 0) return_slen;
373
374
0
    slen = cbor_encode_array(&work_dbuff, 2);
375
0
    if (slen <= 0) return_slen;
376
377
0
    slen = cbor_encode_integer(&work_dbuff, CBOR_INTEGER, vb->vb_ip.prefix);
378
0
    if (slen <= 0) return_slen;
379
380
0
    p = (uint8_t const *) &vb->vb_ipv4addr;
381
0
    end = p + 3;
382
383
    /*
384
     *  RFC 9164 Section 4.2 - Drop lower octets which are all zero.
385
     *
386
     *  If this results in a zero-length string, so be it.
387
     *
388
     *  Note also that "There is no relationship between the number of bytes omitted and the
389
     *  prefix length."
390
     */
391
0
    do {
392
0
      if (*end != 0) break;
393
394
0
      end--;
395
0
    } while (end != p);
396
397
0
    slen = cbor_encode_octets(&work_dbuff, p, (end - p) + (*end != 0));
398
0
    if (slen <= 0) return_slen;
399
0
    break;
400
401
    /*
402
     *  RFC 9164, Section 3.2
403
     *
404
     *  tag=IPv6 + array(prefix-length, address)
405
     */
406
0
  case FR_TYPE_IPV6_PREFIX:
407
0
    slen = cbor_encode_tag(&work_dbuff, cbor_type_to_tag[vb->type]);
408
0
    if (slen <= 0) return_slen;
409
410
0
    slen = cbor_encode_array(&work_dbuff, 2);
411
0
    if (slen <= 0) return_slen;
412
413
0
    slen = cbor_encode_integer(&work_dbuff, CBOR_INTEGER, vb->vb_ip.prefix);
414
0
    if (slen <= 0) return_slen;
415
416
0
    p = (uint8_t const *) &vb->vb_ipv6addr;
417
0
    end = p + 15;
418
419
    /*
420
     *  RFC 9164 Section 4.2 - Drop lower octets which are all zero.
421
     *
422
     *  If this results in a zero-length string, so be it.
423
     *
424
     *  Note also that "There is no relationship between the number of bytes omitted and the
425
     *  prefix length."
426
     */
427
0
    do {
428
0
      if (*end != 0) break;
429
430
0
      end--;
431
0
    } while (end != p);
432
433
0
    slen = cbor_encode_octets(&work_dbuff, p, (end - p) + (*end != 0));
434
0
    if (slen <= 0) return_slen;
435
436
0
    break;
437
438
0
  case FR_TYPE_FLOAT32:
439
0
    FR_DBUFF_IN_BYTES_RETURN(&work_dbuff, (uint8_t) ((CBOR_FLOAT << 5) | CBOR_4_BYTE));
440
0
    FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff, (uint8_t const *) &vb->vb_float32, sizeof(vb->vb_float32));
441
0
    break;
442
443
0
  case FR_TYPE_FLOAT64:
444
0
    FR_DBUFF_IN_BYTES_RETURN(&work_dbuff, (uint8_t) ((CBOR_FLOAT << 5) | CBOR_8_BYTE));
445
0
    FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff, (uint8_t const *) &vb->vb_float64, sizeof(vb->vb_float64));
446
0
    break;
447
448
0
  case FR_TYPE_GROUP:
449
    /*
450
     *  Zero-length array.
451
     */
452
0
    if (fr_value_box_list_num_elements(&vb->vb_group) == 0) {
453
0
      FR_DBUFF_IN_BYTES_RETURN(&work_dbuff, (uint8_t) ((CBOR_ARRAY << 5) | 0));
454
0
      break;
455
0
    }
456
457
    /*
458
     *  The value is array(children)
459
     */
460
0
    slen = cbor_encode_integer(&work_dbuff, CBOR_ARRAY,
461
0
             fr_value_box_list_num_elements(&vb->vb_group));
462
0
    if (slen <= 0) return_slen;
463
464
465
0
    fr_value_box_list_foreach(&vb->vb_group, child) {
466
0
      slen = fr_cbor_encode_value_box(&work_dbuff, child);
467
0
      if (slen <= 0) return_slen;
468
0
    }
469
0
    break;
470
471
472
0
  default:
473
0
    fr_strerror_printf("Invalid data type %s for cbor encoding", fr_type_to_str(vb->type));
474
0
    return -1;
475
0
  }
476
477
0
  return fr_dbuff_set(dbuff, &work_dbuff);
478
0
}
479
480
481
static ssize_t cbor_decode_integer(uint64_t *out, uint8_t info, fr_dbuff_t *dbuff)
482
717k
{
483
717k
  fr_dbuff_t work_dbuff = FR_DBUFF(dbuff);
484
485
717k
  if (info < 24) {
486
631k
    *out = info;
487
631k
    return 0;
488
631k
  }
489
490
85.3k
  if (info == CBOR_1_BYTE) {
491
8.26k
    uint8_t value;
492
493
8.26k
    FR_DBUFF_OUT_RETURN(&value, &work_dbuff);
494
8.25k
    *out = value;
495
8.25k
    goto done;
496
8.26k
  }
497
498
77.0k
  if (info == CBOR_2_BYTE) {
499
73.3k
    uint16_t value;
500
501
73.3k
    FR_DBUFF_OUT_RETURN(&value, &work_dbuff);
502
73.3k
    *out = value;
503
73.3k
    goto done;
504
73.3k
  }
505
506
3.72k
  if (info == CBOR_4_BYTE) {
507
999
    uint32_t value;
508
509
999
    FR_DBUFF_OUT_RETURN(&value, &work_dbuff);
510
973
    *out = value;
511
973
    goto done;
512
999
  }
513
514
2.72k
  if (info == CBOR_8_BYTE) {
515
2.71k
    uint64_t value;
516
517
2.71k
    FR_DBUFF_OUT_RETURN(&value, &work_dbuff);
518
2.67k
    *out = value;
519
2.67k
    goto done;
520
2.71k
  }
521
522
  /*
523
   *  28 and greater are invalid according to the RFCs.
524
   */
525
9
  if (info > CBOR_8_BYTE) return -1;
526
527
85.2k
done:
528
85.2k
  return fr_dbuff_set(dbuff, &work_dbuff);
529
9
}
530
531
static ssize_t cbor_decode_count(uint64_t *out, int expected, fr_dbuff_t *dbuff)
532
9.17k
{
533
9.17k
  fr_dbuff_t work_dbuff = FR_DBUFF(dbuff);
534
9.17k
  uint8_t major, info;
535
9.17k
  ssize_t slen;
536
537
9.17k
  FR_DBUFF_OUT_RETURN(&major, &work_dbuff);
538
539
9.08k
  info = major & 0x1f;
540
9.08k
  major >>= 5;
541
542
9.08k
  if (major != expected) {
543
52
    fr_strerror_printf("Expected cbor type '%s', got unexpected type %d ",
544
52
           cbor_type_to_str[expected], major);
545
52
    return -1;
546
52
  }
547
548
9.03k
  slen = cbor_decode_integer(out, info, &work_dbuff);
549
9.03k
  if (slen < 0) return_slen;
550
551
9.00k
  return fr_dbuff_set(dbuff, &work_dbuff);
552
9.03k
}
553
554
typedef ssize_t (*cbor_decode_type_t)(TALLOC_CTX *ctx, fr_value_box_t *vb, fr_dbuff_t *dbuff);
555
556
static ssize_t cbor_decode_octets_memcpy(uint8_t *dst, size_t dst_min, size_t dst_max, fr_dbuff_t *dbuff)
557
3.43k
{
558
3.43k
  fr_dbuff_t work_dbuff = FR_DBUFF(dbuff);
559
3.43k
  ssize_t slen;
560
3.43k
  uint64_t value = 0;
561
562
3.43k
  slen = cbor_decode_count(&value, CBOR_OCTETS, &work_dbuff);
563
3.43k
  if (slen < 0) return_slen;
564
565
3.30k
  if (value < dst_min) {
566
3
    fr_strerror_printf("Invalid length for data - expected at least %zu got %" PRIu64, dst_min, value);
567
3
    return -1;
568
3
  }
569
570
3.30k
  if (value > dst_max) {
571
121
    fr_strerror_printf("Invalid length for data - expected no more than %zu got %" PRIu64, dst_max, value);
572
121
    return -1;
573
121
  }
574
575
3.18k
  FR_DBUFF_OUT_MEMCPY_RETURN(dst, &work_dbuff, value);
576
577
3.17k
  return fr_dbuff_set(dbuff, &work_dbuff);
578
3.18k
}
579
580
#if 0
581
static ssize_t *cbor_decode_octets_memdup(TALLOC_CTX *ctx, uint8_t **out, fr_dbuff_t *dbuff)
582
{
583
  fr_dbuff_t work_dbuff = FR_DBUFF(dbuff);
584
  ssize_t slen;
585
  uint64_t value;
586
  uint8_t *ptr;
587
588
  slen = cbor_decode_count(&value, CBOR_OCTETS, &work_dbuff);
589
  if (slen < 0) return_slen;
590
591
  if (value > (1 << 20)) {
592
    fr_strerror_printf("cbor data string is too long (%" PRIu64 ")", value);
593
    return -1;
594
  }
595
596
  ptr = talloc_array(ctx, uint8_t, value);
597
  if (!ptr) {
598
    fr_strerror_const("Out of memory");
599
    return -1;
600
  }
601
602
  FR_DBUFF_OUT_MEMCPY_RETURN(ptr, &work_dbuff, value);
603
  *out = ptr;
604
605
  return fr_dbuff_set(dbuff, &work_dbuff);
606
}
607
#endif
608
609
static ssize_t cbor_decode_ethernet(UNUSED TALLOC_CTX *ctx, fr_value_box_t *vb, fr_dbuff_t *dbuff)
610
237
{
611
237
  return cbor_decode_octets_memcpy(vb->vb_ether, sizeof(vb->vb_ether), sizeof(vb->vb_ether), dbuff);
612
237
}
613
614
static ssize_t cbor_decode_ipv4_addr(UNUSED TALLOC_CTX *ctx, fr_value_box_t *vb, fr_dbuff_t *dbuff)
615
1.02k
{
616
1.02k
  fr_dbuff_t work_dbuff = FR_DBUFF(dbuff);
617
1.02k
  ssize_t slen;
618
1.02k
  uint8_t header;
619
1.02k
  size_t count = 0;
620
1.02k
  uint64_t value = 0;
621
622
1.02k
  FR_DBUFF_EXTEND_LOWAT_OR_RETURN(&work_dbuff, 1);
623
624
1.02k
  header = *fr_dbuff_current(&work_dbuff);
625
1.02k
  if ((header >> 5) == CBOR_ARRAY) {
626
537
    count = header & 0x1f;
627
628
537
    if ((count != 2) && (count != 3)) {
629
6
      fr_strerror_printf("Invalid IPv4 interface - expected array of 2-3 elements, got %02x",
630
6
             header);
631
6
      return -1;
632
6
    }
633
634
531
    fr_dbuff_advance(&work_dbuff, 1);
635
531
  }
636
637
1.02k
  vb->vb_ip.prefix = 32;
638
639
  /*
640
   *  Get the IP address.
641
   */
642
1.02k
  slen = cbor_decode_octets_memcpy((uint8_t *) &vb->vb_ipv4addr,
643
1.02k
           sizeof(vb->vb_ipv4addr),
644
1.02k
           sizeof(vb->vb_ipv4addr), &work_dbuff);
645
1.02k
  if (slen <= 0) return_slen;
646
647
948
  if (!count) return fr_dbuff_set(dbuff, &work_dbuff);
648
649
517
  slen = cbor_decode_count(&value, CBOR_INTEGER, &work_dbuff);
650
517
  if (slen <= 0) return_slen;
651
652
514
  if (value != 32) {
653
2
    fr_strerror_printf("Invalid IPv4 address - expected prefix = 32 got %" PRIu64, value);
654
2
    return -fr_dbuff_used(&work_dbuff);
655
2
  }
656
657
512
  if (count == 2) return fr_dbuff_set(dbuff, &work_dbuff);
658
659
  /*
660
   *  Get the scope ID
661
   */
662
259
  slen = cbor_decode_count(&value, CBOR_INTEGER, &work_dbuff);
663
259
  if (slen <= 0) return_slen;
664
665
255
  vb->vb_ip.scope_id = value;
666
667
255
  return fr_dbuff_set(dbuff, &work_dbuff);
668
259
}
669
670
static ssize_t cbor_decode_ipv6_addr(UNUSED TALLOC_CTX *ctx, fr_value_box_t *vb, fr_dbuff_t *dbuff)
671
1.26k
{
672
1.26k
  fr_dbuff_t work_dbuff = FR_DBUFF(dbuff);
673
1.26k
  ssize_t slen;
674
1.26k
  uint8_t header;
675
1.26k
  size_t count = 0;
676
1.26k
  uint64_t value = 0;
677
678
1.26k
  FR_DBUFF_EXTEND_LOWAT_OR_RETURN(&work_dbuff, 1);
679
680
1.26k
  header = *fr_dbuff_current(&work_dbuff);
681
1.26k
  if ((header >> 5) == CBOR_ARRAY) {
682
629
    count = header & 0x1f;
683
684
629
    if ((count != 2) && (count != 3)) {
685
7
      fr_strerror_printf("Invalid IPv4 interface - expected array of 2-3 elements, got %02x",
686
7
             header);
687
7
      return -1;
688
7
    }
689
690
622
    fr_dbuff_advance(&work_dbuff, 1);
691
622
  }
692
693
1.26k
  vb->vb_ip.prefix = 128;
694
695
  /*
696
   *  Get the IP address.
697
   */
698
1.26k
  slen = cbor_decode_octets_memcpy((uint8_t *) &vb->vb_ipv6addr,
699
1.26k
           sizeof(vb->vb_ipv6addr),
700
1.26k
           sizeof(vb->vb_ipv6addr), &work_dbuff);
701
702
1.26k
  if (slen <= 0) return_slen;
703
704
1.15k
  if (!count) return fr_dbuff_set(dbuff, &work_dbuff);
705
706
608
  slen = cbor_decode_count(&value, CBOR_INTEGER, &work_dbuff);
707
608
  if (slen <= 0) return_slen;
708
709
602
  if (value != 128) {
710
95
    fr_strerror_printf("Invalid IPv6 address - expected prefix = 128 got %" PRIu64, value);
711
95
    return -fr_dbuff_used(&work_dbuff);
712
95
  }
713
714
507
  vb->vb_ip.prefix = value;
715
716
507
  if (count == 2) return fr_dbuff_set(dbuff, &work_dbuff);
717
718
  /*
719
   *  Get the scope ID
720
   */
721
254
  slen = cbor_decode_count(&value, CBOR_INTEGER, &work_dbuff);
722
254
  if (slen <= 0) return_slen;
723
724
253
  vb->vb_ip.scope_id = value;
725
726
253
  return fr_dbuff_set(dbuff, &work_dbuff);
727
254
}
728
729
static ssize_t cbor_decode_ipv4_prefix(UNUSED TALLOC_CTX *ctx, fr_value_box_t *vb, fr_dbuff_t *dbuff)
730
602
{
731
602
  fr_dbuff_t work_dbuff = FR_DBUFF(dbuff);
732
602
  ssize_t slen;
733
602
  uint8_t header;
734
602
  uint64_t value = 0;
735
602
  uint8_t buffer[sizeof(vb->vb_ipv4addr)];
736
737
602
  FR_DBUFF_OUT_RETURN(&header, &work_dbuff);
738
739
601
  if (header != ((CBOR_ARRAY << 5) | 2)) {
740
13
    fr_strerror_printf("Invalid IPv4 prefix - expected array of 2 elements, got %02x",
741
13
           header);
742
13
    return -1;
743
13
  }
744
745
588
  slen = cbor_decode_count(&value, CBOR_INTEGER, &work_dbuff);
746
588
  if (slen <= 0) return_slen;
747
748
578
  if (value > 32) {
749
91
    fr_strerror_printf("Invalid IPv4 prefix - expected prefix < 32, got %" PRIu64, value);
750
91
    return -1;
751
91
  }
752
753
  /*
754
   *  RFC 9164 Section 4.3 - Trailing bytes of zero are omitted, so we
755
   *  first copy the data to a fixed-sized buffer which was
756
   *  zeroed out, and then (@todo) also check that unused bits in
757
   *  the last byte are all zero.
758
   */
759
487
  memset(buffer, 0, sizeof(buffer));
760
761
487
  slen = cbor_decode_octets_memcpy(buffer, 0, sizeof(buffer), &work_dbuff);
762
487
  if (slen <= 0) return_slen;
763
764
473
  memcpy((uint8_t *) &vb->vb_ipv4addr, buffer, sizeof(vb->vb_ipv4addr));
765
473
  vb->vb_ip.prefix = value;
766
767
473
  return fr_dbuff_set(dbuff, &work_dbuff);
768
487
}
769
770
static ssize_t cbor_decode_ipv6_prefix(UNUSED TALLOC_CTX *ctx, fr_value_box_t *vb, fr_dbuff_t *dbuff)
771
536
{
772
536
  fr_dbuff_t work_dbuff = FR_DBUFF(dbuff);
773
536
  ssize_t slen;
774
536
  uint8_t header;
775
536
  uint64_t value = 0;
776
536
  uint8_t buffer[sizeof(vb->vb_ipv6addr)];
777
778
536
  FR_DBUFF_OUT_RETURN(&header, &work_dbuff);
779
780
535
  if (header != ((CBOR_ARRAY << 5) | 2)) {
781
11
    fr_strerror_printf("Invalid IPv6 prefix - expected array of 2 elements, got %02x",
782
11
           header);
783
11
    return -1;
784
11
  }
785
786
524
  slen = cbor_decode_count(&value, CBOR_INTEGER, &work_dbuff);
787
524
  if (slen <= 0) return_slen;
788
789
516
  if (value > 128) {
790
86
    fr_strerror_printf("Invalid IPv6 prefix - expected prefix < 128, got %" PRIu64, value);
791
86
    return -1;
792
86
  }
793
794
  /*
795
   *  RFC 9164 Section 4.3 - Trailing bytes of zero are omitted, so we
796
   *  first copy the data to a fixed-sized buffer which was
797
   *  zeroed out, and then (@todo) also check that unused bits in
798
   *  the last byte are all zero.
799
   */
800
430
  memset(buffer, 0, sizeof(buffer));
801
802
430
  slen = cbor_decode_octets_memcpy(buffer, 0, sizeof(buffer), &work_dbuff);
803
430
  if (slen <= 0) return_slen;
804
805
412
  memcpy((uint8_t *) &vb->vb_ipv6addr, buffer, sizeof(vb->vb_ipv6addr));
806
412
  vb->vb_ip.prefix = value;
807
808
412
  return fr_dbuff_set(dbuff, &work_dbuff);
809
430
}
810
811
static ssize_t cbor_decode_int64(int64_t *out, fr_dbuff_t *dbuff, fr_type_t type)
812
11.1k
{
813
11.1k
  fr_dbuff_t work_dbuff = FR_DBUFF(dbuff);
814
11.1k
  ssize_t slen;
815
11.1k
  uint8_t major, info;
816
11.1k
  uint64_t value = 0;
817
11.1k
  int64_t neg;
818
819
11.1k
  FR_DBUFF_OUT_RETURN(&major, &work_dbuff);
820
821
11.0k
  info = major & 0x1f;
822
11.0k
  major >>= 5;
823
824
11.0k
  switch (major) {
825
5.90k
  case CBOR_INTEGER:
826
5.90k
    slen = cbor_decode_integer(&value, info, &work_dbuff);
827
5.90k
    if (slen < 0) return_slen;
828
829
5.89k
    if (value >= ((uint64_t) 1) << 63) { /* equal! */
830
140
    invalid:
831
140
      fr_strerror_printf("cbor value is too large for output data type %s",
832
140
             fr_type_to_str(type));
833
140
      return -1;
834
71
    }
835
836
5.82k
    *out = value;
837
5.82k
    break;
838
839
5.16k
  case CBOR_NEGATIVE:
840
5.16k
    slen = cbor_decode_integer(&value, info, &work_dbuff);
841
5.16k
    if (slen < 0) return_slen;
842
843
5.15k
    if (value >= ((uint64_t) 1) << 63) goto invalid; /* greater than! */
844
845
    /*
846
     *  Convert 0..(2^63-1) into -0..-(2^63-1)
847
     *  then conver to -1..-(2^63)
848
     */
849
5.08k
    neg = -value;
850
5.08k
    neg--;
851
852
5.08k
    *out = neg;
853
5.08k
    break;
854
855
2
  default:
856
2
    fr_strerror_printf("cbor data contains invalid content %d for expected data type %s",
857
2
           major, fr_type_to_str(type));
858
2
    return -1;
859
11.0k
  }
860
861
10.9k
  return fr_dbuff_set(dbuff, &work_dbuff);
862
863
11.0k
}
864
865
static ssize_t cbor_decode_date(UNUSED TALLOC_CTX *ctx, fr_value_box_t *vb, fr_dbuff_t *dbuff)
866
2.38k
{
867
2.38k
  fr_dbuff_t work_dbuff = FR_DBUFF(dbuff);
868
2.38k
  ssize_t slen;
869
2.38k
  int64_t neg;
870
871
2.38k
  slen = cbor_decode_int64(&neg, &work_dbuff, FR_TYPE_DATE);
872
2.38k
  if (slen <= 0) return_slen;
873
874
2.21k
  vb->vb_date = fr_unix_time_from_sec(neg);
875
876
2.21k
  return fr_dbuff_set(dbuff, &work_dbuff);
877
2.38k
}
878
879
/*
880
 *  Tag 1002, followed by map of at least 2 elements
881
 *  key 1: seconds
882
 *  key -9: nanoseconds
883
 */
884
static ssize_t cbor_decode_time_delta(UNUSED TALLOC_CTX *ctx, fr_value_box_t *vb, fr_dbuff_t *dbuff)
885
2.99k
{
886
2.99k
  fr_dbuff_t work_dbuff = FR_DBUFF(dbuff);
887
2.99k
  uint64_t count;
888
2.99k
  ssize_t slen;
889
2.99k
  int64_t key, seconds, fraction, scale;
890
891
2.99k
  slen = cbor_decode_count(&count, CBOR_MAP, &work_dbuff);
892
2.99k
  if (slen < 0) return_slen;
893
894
2.97k
  if (!count || (count > 2)) {
895
114
    fr_strerror_printf("Unexpected count %" PRIu64"  for time_delta, expected map of 1-2 elements", count);
896
114
    return -1;
897
114
  }
898
899
2.86k
  key = seconds = fraction = 0;
900
901
  /*
902
   *  Expect key 1:seconds
903
   */
904
2.86k
  slen = cbor_decode_int64(&key, &work_dbuff, FR_TYPE_TIME_DELTA);
905
2.86k
  if (slen < 0) return_slen;
906
907
2.85k
  if (key != 1) {
908
107
    fr_strerror_printf("Unexpected key %" PRIi64 " for time_delta, expected key 1", key);
909
107
    return -1;
910
107
  }
911
912
2.74k
  slen = cbor_decode_int64(&seconds, &work_dbuff, FR_TYPE_TIME_DELTA);
913
2.74k
  if (slen < 0) return_slen;
914
915
2.74k
  if (count > 1) {
916
1.62k
    slen = cbor_decode_int64(&key, &work_dbuff, FR_TYPE_TIME_DELTA);
917
1.62k
    if (slen < 0) return_slen;
918
919
1.61k
    switch (key) {
920
855
    case -3:
921
855
      scale = MSEC;
922
855
      break;
923
924
374
    case -6:
925
374
      scale = USEC;
926
374
      break;
927
928
271
    case -9:
929
271
      scale = NSEC;
930
271
      break;
931
932
117
    default:
933
117
      fr_strerror_printf("Unsupported time_delta key %" PRIi64, key);
934
117
      return -fr_dbuff_used(&work_dbuff); /* point to actual key? */
935
936
1.61k
    }
937
938
1.50k
    slen = cbor_decode_int64(&fraction, &work_dbuff, FR_TYPE_TIME_DELTA);
939
1.50k
    if (slen < 0) return_slen;
940
941
1.47k
    if ((fraction < 0) || (fraction > scale)) fraction = 0;
942
1.47k
  } else {
943
1.12k
    scale = NSEC;
944
1.12k
    fraction = 0;
945
1.12k
  }
946
947
2.59k
  if (seconds > (INT64_MAX / scale)) {
948
251
    vb->vb_time_delta = fr_time_delta_max();
949
950
2.34k
  } else if (seconds < (INT64_MIN / scale)) {
951
240
    vb->vb_time_delta = fr_time_delta_min();
952
953
2.10k
  } else {
954
2.10k
    seconds *= scale;
955
956
2.10k
    if (seconds < 0) {
957
970
      seconds -= fraction;
958
1.13k
    } else {
959
1.13k
      seconds += fraction;
960
1.13k
    }
961
962
2.10k
    vb->vb_time_delta = fr_time_delta_wrap(seconds);
963
2.10k
  }
964
965
2.59k
  return fr_dbuff_set(dbuff, &work_dbuff);
966
2.74k
}
967
968
969
static cbor_decode_type_t cbor_decode_type[FR_TYPE_MAX] = {
970
  [FR_TYPE_ETHERNET] = cbor_decode_ethernet,
971
972
  [FR_TYPE_DATE] = cbor_decode_date,
973
  [FR_TYPE_TIME_DELTA] = cbor_decode_time_delta,
974
975
  [FR_TYPE_IPV4_ADDR] = cbor_decode_ipv4_addr,
976
  [FR_TYPE_IPV6_ADDR] = cbor_decode_ipv6_addr,
977
978
  [FR_TYPE_IPV4_PREFIX] = cbor_decode_ipv4_prefix,
979
  [FR_TYPE_IPV6_PREFIX] = cbor_decode_ipv6_prefix,
980
};
981
982
/*
983
 *  @todo - fr_cbor_encode_pair_list().  And then if we have da->flags.array, we encode the _value_ as an
984
 *  array of indeterminate length.  This is a little bit of a special case, but not terrible.
985
 */
986
ssize_t fr_cbor_decode_value_box(TALLOC_CTX *ctx, fr_value_box_t *vb, fr_dbuff_t *dbuff,
987
         fr_type_t type, fr_dict_attr_t const *enumv, bool tainted)
988
602k
{
989
602k
  fr_dbuff_t work_dbuff = FR_DBUFF(dbuff);
990
602k
  bool indefinite;
991
602k
  uint8_t major, info;
992
602k
  ssize_t slen;
993
602k
  int64_t neg;
994
602k
  uint64_t value;
995
602k
  uint8_t *ptr;
996
997
602k
  FR_DBUFF_OUT_RETURN(&major, &work_dbuff);
998
999
602k
  if (type == FR_TYPE_NULL) {
1000
0
    type = cbor_guess_type(&work_dbuff, false);
1001
0
    if (type == FR_TYPE_NULL) {
1002
0
      fr_strerror_const("Unable to determine data type from cbor");
1003
0
      return -1;
1004
0
    }
1005
0
  }
1006
1007
602k
  fr_value_box_init(vb, type, enumv, tainted);
1008
1009
602k
  info = major & 0x1f;
1010
602k
  major >>= 5;
1011
1012
  /*
1013
   *  Invalid combinations.
1014
   */
1015
602k
  if (((info >= 28) && (info <= 30)) ||
1016
602k
      ((info == 31) && ((major == 0) || (major == 1) || (major == 6)))) {
1017
6
    fr_strerror_const("Invalid cbor data - input is not 'well formed'");
1018
6
    return -1;
1019
6
  }
1020
1021
602k
  switch (major) {
1022
2.33k
  case CBOR_STRING:
1023
2.33k
    if (type != FR_TYPE_STRING) {
1024
6
    mismatch:
1025
6
      fr_strerror_printf("cbor data contains invalid content %d for expected data type %s",
1026
6
             major, fr_type_to_str(type));
1027
6
      return -1;
1028
1
    }
1029
1030
2.33k
    if (info == 31) {
1031
2
    no_chunks:
1032
2
      fr_strerror_const("Chunked strings are not supported");
1033
2
      return -1;
1034
1
    }
1035
1036
1037
    /*
1038
     *  @todo - undefinite length strings.  Which are really "chunked" strings.
1039
     */
1040
2.33k
    slen = cbor_decode_integer(&value, info, &work_dbuff);
1041
2.33k
    if (slen < 0) return_slen;
1042
1043
    /*
1044
     *  A little bit of sanity check.
1045
     */
1046
2.33k
    if (value > (1 << 20)) {
1047
62
      fr_strerror_printf("cbor data string is too long (%" PRIu64 ")", value);
1048
62
      return -1;
1049
62
    }
1050
1051
2.26k
    ptr = talloc_array(ctx, uint8_t, value + 1);
1052
2.26k
    if (!ptr) {
1053
0
      fr_strerror_const("Out of memory");
1054
0
      return -1;
1055
0
    }
1056
2.26k
    talloc_set_type(ptr, char);
1057
2.26k
    if (value) FR_DBUFF_OUT_MEMCPY_RETURN(ptr, &work_dbuff, value);
1058
2.19k
    ptr[value] = '\0';
1059
1060
2.19k
    fr_value_box_strdup_shallow(vb, NULL, (char const *) ptr, tainted);
1061
1062
2.19k
    break;
1063
1064
16.4k
  case CBOR_OCTETS:
1065
16.4k
    if (type != FR_TYPE_OCTETS) goto mismatch;
1066
1067
16.4k
    if (info == 31) goto no_chunks;
1068
1069
    /*
1070
     *  @todo - indefinite length octet strings.  Which are really "chunked" octet strings.
1071
     */
1072
16.4k
    slen = cbor_decode_integer(&value, info, &work_dbuff);
1073
16.4k
    if (slen < 0) return_slen;
1074
1075
    /*
1076
     *  A little bit of sanity check.
1077
     */
1078
16.4k
    if (value > (1 << 20)) {
1079
62
      fr_strerror_printf("cbor data string is too long (%" PRIu64 ")", value);
1080
62
      return -1;
1081
62
    }
1082
1083
16.3k
    ptr = talloc_array(ctx, uint8_t, value);
1084
16.3k
    if (!ptr) {
1085
0
      fr_strerror_const("Out of memory");
1086
0
      return -1;
1087
0
    }
1088
1089
16.3k
    fr_value_box_memdup_shallow(vb, NULL, (uint8_t const *) ptr, value, false); /* tainted? */
1090
1091
16.3k
    if (value) FR_DBUFF_OUT_MEMCPY_RETURN(ptr, &work_dbuff, value);
1092
16.2k
    break;
1093
1094
50.1k
  case CBOR_INTEGER:
1095
50.1k
    slen = cbor_decode_integer(&value, info, &work_dbuff);
1096
50.1k
    if (slen < 0) return_slen;
1097
1098
50.1k
    switch (type) {
1099
368
    case FR_TYPE_BOOL:
1100
368
      if (value > 1) goto invalid_bool;
1101
284
      vb->vb_bool = value;
1102
284
      break;
1103
1104
291
    case FR_TYPE_UINT8:
1105
291
      if (value > UINT8_MAX) {
1106
680
      invalid:
1107
680
        fr_strerror_printf("cbor value is too large for output data type %s",
1108
680
               fr_type_to_str(type));
1109
680
        return -1;
1110
86
      }
1111
205
      vb->vb_uint8 = value;
1112
205
      break;
1113
1114
491
    case FR_TYPE_UINT16:
1115
491
      if (value > UINT16_MAX) goto invalid;
1116
417
      vb->vb_uint16 = value;
1117
417
      break;
1118
1119
338
    case FR_TYPE_UINT32:
1120
338
      if (value > UINT32_MAX) goto invalid;
1121
296
      vb->vb_uint32 = value;
1122
296
      break;
1123
1124
47.4k
    case FR_TYPE_UINT64:
1125
47.4k
      vb->vb_uint64 = value;
1126
47.4k
      break;
1127
1128
291
    case FR_TYPE_INT8:
1129
291
      if (value > INT8_MAX) goto invalid;
1130
200
      vb->vb_int8 = value;
1131
200
      break;
1132
1133
285
    case FR_TYPE_INT16:
1134
285
      if (value > INT16_MAX) goto invalid;
1135
216
      vb->vb_int16 = value;
1136
216
      break;
1137
1138
296
    case FR_TYPE_INT32:
1139
296
      if (value > INT32_MAX) goto invalid;
1140
250
      vb->vb_int32 = value;
1141
250
      break;
1142
1143
296
    case FR_TYPE_INT64:
1144
296
      if (value > INT64_MAX) goto invalid;
1145
227
      vb->vb_int64 = value;
1146
227
      break;
1147
1148
3
    default:
1149
6
    integer_type_mismatch:
1150
6
      fr_strerror_printf("Unexpected cbor type 'integer' when decoding data type %s",
1151
6
             fr_type_to_str(type));
1152
6
      return -1;
1153
50.1k
    }
1154
49.5k
    break;
1155
1156
49.5k
  case CBOR_NEGATIVE:
1157
1.34k
    slen = cbor_decode_integer(&value, info, &work_dbuff);
1158
1.34k
    if (slen < 0) return_slen;
1159
1160
    /*
1161
     *  Signed numbers only go down to -2^63
1162
     *  so value must be less than 2^63
1163
     */
1164
1.34k
    if (value >= ((uint64_t) 1) << 63) goto invalid;
1165
1166
    /*
1167
     *  Convert 0..(2^63-1) into -0..-(2^63-1)
1168
     *  then conver to -1..-(2^63)
1169
     */
1170
1.28k
    neg = -value;
1171
1.28k
    neg--;
1172
1173
1.28k
    switch (type) {
1174
261
    case FR_TYPE_INT8:
1175
261
      if (neg < INT8_MIN) goto invalid;
1176
205
      vb->vb_int8 = neg;
1177
205
      break;
1178
1179
267
    case FR_TYPE_INT16:
1180
267
      if (neg < INT16_MIN) goto invalid;
1181
218
      vb->vb_int16 = neg;
1182
218
      break;
1183
1184
278
    case FR_TYPE_INT32:
1185
278
      if (neg < INT32_MIN) goto invalid;
1186
245
      vb->vb_int32 = neg;
1187
245
      break;
1188
1189
471
    case FR_TYPE_INT64:
1190
471
      vb->vb_int64 = neg;
1191
471
      break;
1192
1193
3
    default:
1194
3
      goto integer_type_mismatch;
1195
1.28k
    }
1196
1.13k
    break;
1197
1198
522k
  case CBOR_FLOAT:
1199
    /*
1200
     *  Simple values.  See RFC 8489 Section 3.3.
1201
     *
1202
     *  20 - false
1203
     *  21 - true
1204
     *  22 - NULL
1205
     */
1206
522k
    if (info < 24) {
1207
521k
      switch (type) {
1208
520k
      case FR_TYPE_BOOL:
1209
520k
        if (info == 20) {
1210
519k
          vb->vb_bool = false;
1211
519k
          break;
1212
519k
        }
1213
1214
695
        if (info == 21) {
1215
687
          vb->vb_bool = true;
1216
687
          break;
1217
687
        }
1218
1219
92
      invalid_bool:
1220
92
        fr_strerror_printf("Invalid cbor - boolean is not encoded as 'true' or 'false'");
1221
92
        return -fr_dbuff_used(&work_dbuff);
1222
1223
554
      case FR_TYPE_OCTETS:
1224
1.31k
      case FR_TYPE_STRING:
1225
1.31k
      case FR_TYPE_TLV:
1226
1.31k
      case FR_TYPE_VENDOR:
1227
1.31k
      case FR_TYPE_GROUP:
1228
1.31k
      case FR_TYPE_STRUCT:
1229
        /*
1230
         *  Be a little forgiving.  22 is NULL, so we treat that as "nothing".
1231
         *
1232
         *  i.e. empty string, empty set, etc.
1233
         */
1234
1.31k
        if (info == 22) break;
1235
1236
9
        FALL_THROUGH;
1237
1238
12
      default:
1239
12
        fr_strerror_printf("Invalid cbor - unexpected 'simple value' %u", info);
1240
12
        return -fr_dbuff_used(&work_dbuff);
1241
521k
      }
1242
521k
      break;
1243
521k
    }
1244
1245
    /*
1246
     *  Or as one-byte integers.
1247
     */
1248
1.25k
    if (info == CBOR_1_BYTE) {
1249
456
      uint8_t data;
1250
1251
456
      FR_DBUFF_OUT_RETURN(&data, &work_dbuff);
1252
1253
448
      switch (type) {
1254
194
      case FR_TYPE_FLOAT32:
1255
194
        vb->vb_float32 = data;
1256
194
        break;
1257
1258
253
      case FR_TYPE_FLOAT64:
1259
253
        vb->vb_float64 = data;
1260
253
        break;
1261
1262
1
      default:
1263
9
      float_type_mismatch:
1264
9
        fr_strerror_printf("Unexpected cbor type 'float' when decoding data type %s",
1265
9
               fr_type_to_str(type));
1266
9
        return -1;
1267
448
      }
1268
1269
447
      break;
1270
448
    }
1271
1272
    /*
1273
     *  We don't support float16
1274
     */
1275
1276
798
    if (info == CBOR_4_BYTE) {
1277
397
      float data;
1278
1279
397
      FR_DBUFF_OUT_RETURN(&data, &work_dbuff);
1280
1281
394
      switch (type) {
1282
199
      case FR_TYPE_FLOAT32:
1283
199
        vb->vb_float32 = data;
1284
199
        break;
1285
1286
194
      case FR_TYPE_FLOAT64:
1287
194
        vb->vb_float64 = (double) data;
1288
194
        break;
1289
1290
1
      default:
1291
1
        goto float_type_mismatch;
1292
394
      }
1293
1294
393
      break;
1295
394
    }
1296
1297
401
    if (info == CBOR_8_BYTE) {
1298
395
      double data;
1299
1300
395
      FR_DBUFF_OUT_RETURN(&data, &work_dbuff);
1301
1302
389
      switch (type) {
1303
194
      case FR_TYPE_FLOAT32:
1304
194
        vb->vb_float32 = data; /* maybe loses precision? */
1305
194
        break;
1306
1307
194
      case FR_TYPE_FLOAT64:
1308
194
        vb->vb_float64 = data;
1309
194
        break;
1310
1311
1
      default:
1312
1
        goto float_type_mismatch;
1313
389
      }
1314
1315
388
      break;
1316
389
    }
1317
1318
    /*
1319
     *  24 is FLOAT16, which we don't support.
1320
     *  31 is BREAK, which the caller should have checked for.
1321
     */
1322
6
    goto float_type_mismatch;
1323
1324
9.15k
  case CBOR_TAG:
1325
    /*
1326
     *  We only support a limited number of tags.
1327
     */
1328
9.15k
    slen = cbor_decode_integer(&value, info, &work_dbuff);
1329
9.15k
    if (slen < 0) return_slen;
1330
1331
    /*
1332
     *  No tag defined for this data type, that's on us.
1333
     */
1334
9.15k
    if (!cbor_type_to_tag[type]) {
1335
2
      fr_strerror_printf("Unknown cbor tag %" PRIu64 " for expected data type %s",
1336
2
             value, fr_type_to_str(type));
1337
2
      return -fr_dbuff_used(&work_dbuff);
1338
2
    }
1339
1340
    /*
1341
     *  Wrong tag for this data type, that's on them.
1342
     */
1343
9.15k
    if (cbor_type_to_tag[type] != value) {
1344
101
      fr_strerror_printf("Invalid cbor tag %" PRIu64 " for expected data type %s",
1345
101
             value, fr_type_to_str(type));
1346
101
      return -fr_dbuff_used(&work_dbuff);
1347
101
    }
1348
1349
9.04k
    fr_value_box_init(vb, type, enumv, tainted);
1350
1351
9.04k
    slen = cbor_decode_type[type](ctx, vb, &work_dbuff);
1352
9.04k
    if (slen < 0) return_slen;
1353
7.86k
    break;
1354
1355
7.86k
  case CBOR_ARRAY:
1356
11
    if (type != FR_TYPE_GROUP) goto invalid_type;
1357
1358
    /*
1359
     *  Loop until done.
1360
     */
1361
0
    if (info == 31) {
1362
0
      value = ~0;
1363
0
      indefinite = true;
1364
1365
0
    } else {
1366
0
      slen = cbor_decode_integer(&value, info, &work_dbuff);
1367
0
      if (slen < 0) return_slen;
1368
1369
0
      indefinite = false;
1370
0
    }
1371
1372
#ifdef STATIC_ANALYZER
1373
    if (value > fr_dbuff_remaining(&work_dbuff)) return -1;
1374
#endif
1375
1376
    /*
1377
     *  Loop until we decode everything.  For simplicity, we handle indefinite and definite
1378
     *  length arrays in the same loop.
1379
     */
1380
0
    for (/* nothing */; value > 0; value--) {
1381
0
      uint8_t header;
1382
0
      fr_value_box_t *child;
1383
1384
      /*
1385
       *  Require at least one byte in the buffer.
1386
       */
1387
0
      FR_DBUFF_EXTEND_LOWAT_OR_RETURN(&work_dbuff, 1);
1388
1389
      /*
1390
       *  Peek ahead for a break.
1391
       */
1392
0
      header = *fr_dbuff_current(&work_dbuff);
1393
0
      if (header == 0xff) {
1394
0
        if (!indefinite) {
1395
0
          fr_strerror_const("Unexpected 'break' found in cbor data");
1396
0
          return -fr_dbuff_used(&work_dbuff);
1397
0
        }
1398
1399
        /*
1400
         *  Done!
1401
         */
1402
0
        fr_dbuff_advance(&work_dbuff, 1);
1403
0
        break;
1404
0
      }
1405
1406
0
      child = fr_value_box_alloc(ctx, FR_TYPE_NULL, NULL);
1407
0
      if (!child) {
1408
0
        fr_strerror_const("Out of memory");
1409
0
        return -fr_dbuff_used(&work_dbuff);
1410
0
      }
1411
1412
      /*
1413
       *  We have to decode at least one value.
1414
       */
1415
0
      slen = fr_cbor_decode_value_box(child, child, &work_dbuff, FR_TYPE_NULL, NULL, tainted);
1416
0
      if (slen <= 0) {
1417
0
        talloc_free(child);
1418
0
        return_slen;
1419
0
      }
1420
1421
0
      fr_value_box_list_insert_tail(&vb->vb_group, child);
1422
0
    }
1423
0
    break;
1424
1425
    /*
1426
     *  These are not value-box types.
1427
     */
1428
1
  case CBOR_MAP:
1429
12
  invalid_type:
1430
12
    fr_strerror_printf("Invalid data type %s for cbor to value-box", fr_type_to_str(type));
1431
12
    return -1;
1432
602k
  }
1433
1434
599k
  return fr_dbuff_set(dbuff, &work_dbuff);
1435
602k
}
1436
1437
/** Encode a pair
1438
 *
1439
 */
1440
ssize_t fr_cbor_encode_pair(fr_dbuff_t *dbuff, fr_pair_t *vp)
1441
0
{
1442
0
  fr_dbuff_t  work_dbuff = FR_DBUFF(dbuff);
1443
0
  ssize_t   slen;
1444
0
  fr_dict_attr_t const *parent;
1445
0
  size_t    count;
1446
1447
0
  FR_DBUFF_IN_BYTES_RETURN(&work_dbuff, (uint8_t) ((CBOR_MAP << 5) | 1)); /* map of 1 item */
1448
1449
  /*
1450
   *  Key is the attribute number.
1451
   */
1452
0
  slen = cbor_encode_integer(&work_dbuff, CBOR_INTEGER, vp->da->attr);
1453
0
  if (slen <= 0) return_slen;
1454
1455
  /*
1456
   *  Value is the actual value of the leaf, or the array of children.
1457
   */
1458
0
  switch (vp->vp_type) {
1459
0
  case FR_TYPE_LEAF:
1460
0
    slen = fr_cbor_encode_value_box(&work_dbuff, &vp->data);
1461
0
    if (slen <= 0) return_slen;
1462
0
    break;
1463
1464
    /*
1465
     *  Groups reparent to the ref.
1466
     */
1467
0
  case FR_TYPE_GROUP:
1468
0
    parent = fr_dict_attr_ref(vp->da);
1469
0
    fr_assert(parent != NULL);
1470
0
    goto encode_children;
1471
1472
    /*
1473
     *  The only difference between TLV and VSA is that the children of VSA are all VENDORs.
1474
     */
1475
0
  case FR_TYPE_VENDOR:
1476
0
  case FR_TYPE_VSA:
1477
0
  case FR_TYPE_TLV:
1478
0
    parent = vp->da;
1479
1480
    /*
1481
     *  The value is array(children)
1482
     */
1483
0
encode_children:
1484
0
    if (fr_pair_list_num_elements(&vp->vp_group) == 0) {
1485
0
      FR_DBUFF_IN_BYTES_RETURN(&work_dbuff, (uint8_t) ((CBOR_FLOAT << 5) | 22)); /* NULL */
1486
0
      break;
1487
0
    }
1488
1489
    /*
1490
     *  The groups, etc. may contain internal attributes.  We don't yet deal with those.
1491
     */
1492
0
    count = 0;
1493
0
    fr_pair_list_foreach(&vp->vp_group, child) {
1494
0
      if (child->da->parent != parent) continue;
1495
0
      count++;
1496
0
    }
1497
1498
0
    slen = cbor_encode_integer(&work_dbuff, CBOR_ARRAY, count);
1499
0
    if (slen <= 0) return_slen;
1500
1501
0
    fr_pair_list_foreach(&vp->vp_group, child) {
1502
      /*
1503
       *  We don't allow changing dictionaries here.
1504
       */
1505
0
      if (child->da->parent != parent) continue;
1506
1507
0
      slen = fr_cbor_encode_pair(&work_dbuff, child);
1508
0
      if (slen <= 0) return_slen;
1509
0
    }
1510
0
    break;
1511
1512
  /*
1513
   *  @todo - struct, except if we hit the end of the struct, check if the next child is the child
1514
   *  of the key?  That makes it all more annoying :(
1515
   */
1516
1517
0
  default:
1518
0
    fr_strerror_printf("Invalid data type %s for cbor encoding", fr_type_to_str(vp->vp_type));
1519
0
    return -1;
1520
0
  }
1521
1522
0
  return fr_dbuff_set(dbuff, &work_dbuff);
1523
0
}
1524
1525
/** Guess the data type of the CBOR data.
1526
 *
1527
 *  We've parsed the attribute number, and found that we don't have a dictionary entry for it.  But rather
1528
 *  than create an attribute of type octets, we try to guess the data type.
1529
 */
1530
static fr_type_t cbor_guess_type(fr_dbuff_t *dbuff, bool pair)
1531
595k
{
1532
595k
  fr_dbuff_t work_dbuff = FR_DBUFF(dbuff);
1533
595k
  ssize_t slen;
1534
595k
  uint8_t major, info;
1535
595k
  uint64_t value;
1536
1537
  /*
1538
   *  get the next byte, which is a CBOR header.
1539
   */
1540
595k
  slen = fr_dbuff_out(&major, &work_dbuff);
1541
595k
  if (slen <= 0) {
1542
60
  no_data:
1543
60
    fr_strerror_const("Invalid cbor - insufficient data");
1544
60
    return FR_TYPE_NULL;
1545
58
  }
1546
1547
595k
  info = major & 0x1f;
1548
595k
  major >>= 5;
1549
1550
595k
  switch (major) {
1551
47.5k
  case CBOR_INTEGER:
1552
47.5k
    return FR_TYPE_UINT64;
1553
1554
539
  case CBOR_NEGATIVE:
1555
539
    return FR_TYPE_INT64;
1556
1557
2.33k
  case CBOR_STRING:
1558
2.33k
    return FR_TYPE_STRING;
1559
1560
16.4k
  case CBOR_OCTETS:
1561
16.4k
    return FR_TYPE_OCTETS;
1562
1563
1
  case CBOR_ARRAY:
1564
1
    if (!pair) return FR_TYPE_GROUP;
1565
1
    break;
1566
1567
26
  case CBOR_MAP:
1568
26
    return FR_TYPE_TLV;
1569
1570
    /*
1571
     *  Look at the tag to determine what it is
1572
     */
1573
8.01k
  case CBOR_TAG:
1574
8.01k
    slen = cbor_decode_integer(&value, info, &work_dbuff);
1575
8.01k
    if (slen < 0) break;
1576
1577
8.00k
    switch (value) {
1578
2.38k
    case 1:
1579
2.38k
    case 1001:
1580
2.38k
      return FR_TYPE_DATE;
1581
1582
2.99k
    case 1002:
1583
2.99k
      return FR_TYPE_TIME_DELTA;
1584
1585
237
    case 48:
1586
237
      return FR_TYPE_ETHERNET;
1587
1588
1.08k
    case 52:
1589
1.08k
      slen = fr_dbuff_out(&major, &work_dbuff);
1590
1.08k
      if (slen <= 0) goto no_data;
1591
1592
1.08k
      major >>= 5;
1593
1594
1.08k
      if (major == CBOR_ARRAY) {
1595
594
        return FR_TYPE_IPV4_PREFIX;
1596
594
      }
1597
489
      return FR_TYPE_IPV4_ADDR;
1598
1599
1.16k
    case 54:
1600
1.16k
      slen = fr_dbuff_out(&major, &work_dbuff);
1601
1.16k
      if (slen <= 0) goto no_data;
1602
1603
1.16k
      major >>= 5;
1604
1605
1.16k
      if (major == CBOR_ARRAY) {
1606
529
        return FR_TYPE_IPV6_PREFIX;
1607
529
      }
1608
638
      return FR_TYPE_IPV6_ADDR;
1609
1610
139
    default:
1611
139
      break;
1612
8.00k
    }
1613
1614
139
    break;
1615
1616
520k
  case CBOR_FLOAT:
1617
    /*
1618
     *  In-place values are special. false / true / NULL
1619
     */
1620
520k
    if (info < 24) {
1621
520k
      if ((info == 20) || (info == 21)) return FR_TYPE_BOOL;
1622
1623
10
      return FR_TYPE_NULL;
1624
520k
    }
1625
1626
670
    return FR_TYPE_FLOAT64;
1627
595k
  }
1628
1629
1630
  /*
1631
   *  No idea.  :(
1632
   *
1633
   *  @todo - also check the cbor data, and return the length of cbor data which needs to be
1634
   *  converted to data type 'octets'.  This work involves mostly parsing the cbor data, which isn't
1635
   *  trivial.
1636
   */
1637
145
  fr_strerror_const("Invalid cbor - unable to determine data type");
1638
145
  return FR_TYPE_NULL;
1639
595k
}
1640
1641
static ssize_t cbor_decode_pair(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dbuff_t *dbuff,
1642
        fr_dict_attr_t const *parent, bool tainted, int depth)
1643
607k
{
1644
607k
  fr_dbuff_t work_dbuff = FR_DBUFF(dbuff);
1645
607k
  uint8_t header, major, info;
1646
607k
  bool indefinite;
1647
607k
  ssize_t slen;
1648
607k
  fr_pair_t *vp;
1649
607k
  uint64_t value = 0;
1650
607k
  fr_dict_attr_t const *da;
1651
1652
607k
  FR_DBUFF_OUT_RETURN(&header, &work_dbuff);
1653
1654
  /*
1655
   *  We require a 2-element array(attribute number, value)
1656
   */
1657
607k
  if (header != (((CBOR_MAP) << 5) | 1)) {
1658
80
    fr_strerror_printf("Invalid cbor header - expected map of 1 elements, got %02x", header);
1659
80
    return -1;
1660
80
  }
1661
1662
  /*
1663
   *  This should be a CBOR_INTEGER.
1664
   */
1665
607k
  FR_DBUFF_OUT_RETURN(&major, &work_dbuff);
1666
1667
607k
  info = major & 0x1f;
1668
607k
  major >>= 5;
1669
1670
607k
  if (major != CBOR_INTEGER) {
1671
10
    fr_strerror_printf("Invalid cbor - expected 'integer', got major type %d",
1672
10
           major);
1673
10
    return -1;
1674
10
  }
1675
1676
607k
  slen = cbor_decode_integer(&value, info, &work_dbuff);
1677
607k
  if (slen < 0) {
1678
20
    return_slen;
1679
20
  }
1680
1681
  /*
1682
   *  If the nesting is too deep, decode as raw octets.  We have to do this manually in CBOR,
1683
   *  because the other protocols create a da_stack which limits the depth.
1684
   */
1685
607k
  if (depth >= FR_DICT_MAX_TLV_STACK) goto raw;
1686
1687
607k
  da = fr_dict_attr_child_by_num(parent, value);
1688
607k
  if (!da) {
1689
595k
    fr_type_t type;
1690
1691
595k
    type = cbor_guess_type(&work_dbuff, true);
1692
595k
    if (type == FR_TYPE_NULL) return -fr_dbuff_used(&work_dbuff);
1693
1694
595k
    if (depth >= FR_DICT_MAX_TLV_STACK) {
1695
196
    raw:
1696
196
      type = FR_TYPE_OCTETS;
1697
196
    }
1698
1699
    /*
1700
     *  @todo - the value here isn't a cbor octets type, but is instead cbor data.  Since cbor
1701
     *  is typed, we _could_ perhaps instead discover the type from the cbor data, and then
1702
     *  use that instead.  This would involve creating a function which maps cbor types to our
1703
     *  data types.
1704
     */
1705
595k
    da = fr_dict_attr_unknown_typed_afrom_num(ctx, parent, value, type);
1706
595k
    if (!da) return -fr_dbuff_used(&work_dbuff);
1707
595k
  }
1708
1709
606k
  vp = fr_pair_afrom_da(ctx, da);
1710
606k
  if (!vp) {
1711
0
    fr_strerror_const("Out of memory");
1712
0
    return -fr_dbuff_used(&work_dbuff);
1713
0
  }
1714
1715
  /*
1716
   *  Leaf values are easy.
1717
   */
1718
606k
  if (fr_type_is_leaf(da->type)) {
1719
602k
    slen = fr_cbor_decode_value_box(vp, &vp->data, &work_dbuff, da->type, da, tainted);
1720
602k
    if (slen < 0) {
1721
2.45k
      talloc_free(vp);
1722
2.45k
      return_slen;
1723
2.45k
    }
1724
1725
599k
    goto done;
1726
602k
  }
1727
1728
4.77k
  fr_assert(fr_type_is_structural(da->type));
1729
1730
4.77k
  switch (da->type) {
1731
    /*
1732
     *  All of these are essentially the same.
1733
     */
1734
0
  case FR_TYPE_VENDOR:
1735
297
  case FR_TYPE_VSA:
1736
1.07k
  case FR_TYPE_TLV:
1737
1.07k
    parent = vp->da;
1738
1.07k
    break;
1739
1740
    /*
1741
     *  Groups reparent to the ref.
1742
     */
1743
3.69k
  case FR_TYPE_GROUP:
1744
3.69k
    parent = fr_dict_attr_ref(vp->da);
1745
3.69k
    fr_assert(parent != NULL);
1746
3.69k
    break;
1747
1748
2
  default:
1749
2
    fr_strerror_printf("Invalid data type %s for child %s of %s",
1750
2
           fr_type_to_str(da->type), vp->da->name, parent->name);
1751
2
    talloc_free(vp);
1752
2
    return -1;
1753
4.77k
  }
1754
1755
  /*
1756
   *  This should be a CBOR_ARRAY.
1757
   */
1758
4.76k
  FR_DBUFF_OUT_RETURN(&major, &work_dbuff);
1759
1760
4.73k
  info = major & 0x1f;
1761
4.73k
  major >>= 5;
1762
1763
4.73k
  if (major != CBOR_ARRAY) {
1764
    /*
1765
     *  Allow NULL as a synonym for "no children".
1766
     */
1767
1.09k
    if ((major == CBOR_FLOAT) && (info == 22)) goto done;
1768
1769
1.09k
    talloc_free(vp);
1770
31
    fr_strerror_printf("Invalid cbor - expected 'array', got major type %d",
1771
31
           major);
1772
31
    return -1;
1773
1.09k
  }
1774
1775
3.64k
  if (info == 31) {
1776
1.32k
    value = ~0;
1777
1.32k
    indefinite = true;
1778
1779
2.31k
  } else {
1780
2.31k
    slen = cbor_decode_integer(&value, info, &work_dbuff);
1781
2.31k
    if (slen < 0) {
1782
5
      talloc_free(vp);
1783
5
      return_slen;
1784
5
    }
1785
1786
2.31k
    indefinite = false;
1787
2.31k
  }
1788
1789
#ifdef STATIC_ANALYZER
1790
  if (value > fr_dbuff_remaining(&work_dbuff)) return -1;
1791
#endif
1792
1793
  /*
1794
   *  Loop until we decode everything.  For simplicity, we handle indefinite and definite
1795
   *  length arrays in the same loop.
1796
   */
1797
8.19k
  for (/* nothing */; value > 0; value--) {
1798
    /*
1799
     *  Require at least one byte in the buffer.
1800
     */
1801
6.17k
    if (fr_dbuff_extend_lowat(NULL, &work_dbuff, 1) == 0) {
1802
159
      talloc_free(vp);
1803
159
      return -fr_dbuff_used(&work_dbuff);
1804
159
    }
1805
1806
    /*
1807
     *  Peek ahead for a break.
1808
     */
1809
6.01k
    header = *fr_dbuff_current(&work_dbuff);
1810
6.01k
    if (header == 0xff) {
1811
707
      if (!indefinite) {
1812
2
        talloc_free(vp);
1813
2
        fr_strerror_const("Unexpected 'break' found in cbor data");
1814
2
        return -fr_dbuff_used(&work_dbuff);
1815
2
      }
1816
1817
      /*
1818
       *  Done!
1819
       */
1820
705
      fr_dbuff_advance(&work_dbuff, 1);
1821
705
      break;
1822
707
    }
1823
1824
5.31k
    slen = cbor_decode_pair(vp, &vp->vp_group, &work_dbuff, parent, tainted, depth + 1);
1825
5.31k
    if (slen <= 0) {
1826
763
      talloc_free(vp);
1827
763
      return_slen;
1828
763
    }
1829
5.31k
  }
1830
1831
603k
done:
1832
603k
  FR_PAIR_APPEND(out, vp);
1833
603k
  return fr_dbuff_set(dbuff, &work_dbuff);
1834
3.64k
}
1835
1836
ssize_t fr_cbor_decode_pair(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dbuff_t *dbuff,
1837
          fr_dict_attr_t const *parent, bool tainted)
1838
602k
{
1839
602k
  return cbor_decode_pair(ctx, out, dbuff, parent, tainted, 0);
1840
602k
}
1841
1842
/*
1843
 *  @todo - cbor_print
1844
 *  [] for array
1845
 *  [_...] for indefinite array
1846
 *  {a:b} for map
1847
 *  digits for integer
1848
 *  'string' for string
1849
 *  h'HHHH' for octets
1850
 *
1851
 *  https://datatracker.ietf.org/doc/html/draft-ietf-cbor-edn-literals
1852
 */