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/unlang/xlat_pair.c
Line
Count
Source
1
/*
2
 *   This program is free software; you can redistribute it and/or modify
3
 *   it under the terms of the GNU General Public License as published by
4
 *   the Free Software Foundation; either version 2 of the License, or
5
 *   (at your option) any later version.
6
 *
7
 *   This program 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
10
 *   GNU General Public License for more details.
11
 *
12
 *   You should have received a copy of the GNU General Public License
13
 *   along with this program; 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: ac59457647299f86aedd3a2e3a677fefa62a5da4 $
19
 *
20
 * @brief Protocol agnostic encode/decoders
21
 * @file unlang/xlat_pair.c
22
 *
23
 * @copyright 2021 Network RADIUS SAS (legal@networkradius.com)
24
 */
25
RCSID("$Id: ac59457647299f86aedd3a2e3a677fefa62a5da4 $")
26
27
#include <freeradius-devel/unlang/xlat_priv.h>
28
29
/** Keep decoding pairs until all of the data has been used.
30
 *
31
 * @param[in] ctx   to allocate new pairs in.
32
 * @param[in] out   the cursor to update
33
 * @param[in] parent    to use as the root
34
 * @param[in] data    to decode.
35
 * @param[in] data_len    The length of the incoming data.
36
 * @param[in] decode_ctx  Any decode specific data such as secrets or configurable.
37
 * @param[in] decode    the function used to decode one specific pair.
38
 * @return
39
 *  - <= 0 on error.  May be the offset (as a negative value) where the error occurred.
40
 *  - > 0 on success.  How many bytes were decoded.
41
 */
42
static ssize_t fr_pair_decode_multi(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent,
43
            uint8_t const *data, size_t data_len, void *decode_ctx, fr_pair_decode_t decode)
44
0
{
45
0
  uint8_t const *p, *end;
46
0
  fr_pair_list_t tmp;
47
48
  /*
49
   *  Catch idiocies.
50
   */
51
0
  if (data_len == 0) return 0;
52
53
0
  fr_pair_list_init(&tmp);
54
55
0
  p = data;
56
0
  end = data + data_len;
57
58
0
  while (p < end) {
59
0
    ssize_t len;
60
61
0
    len = decode(ctx, &tmp, parent, p, end - p, decode_ctx);
62
0
    if (len <= 0) {
63
0
      fr_pair_list_free(&tmp);
64
0
      return len - (p - data);
65
0
    }
66
0
    p += len;
67
0
  }
68
69
  /*
70
   *  Add the pairs to the cursor
71
   */
72
0
  fr_pair_list_append(out, &tmp);
73
74
0
  return data_len;
75
0
}
76
77
78
/** Decode all of the value boxes into the output cursor
79
 *
80
 * @param[in] ctx   to allocate new pairs in.
81
 * @param[in] out   the cursor to update
82
 * @param[in] request   the request
83
 * @param[in] decode_ctx  Any decode specific data such as secrets or configurable.
84
 * @param[in] decode    the function used to decode one specific pair.
85
 * @param[in] in    the list of value boxes to decode
86
 * @return
87
 *  - <= 0 on error.  May be the offset (as a negative value) where the error occurred.
88
 *  - > 0 on success.  How many value boxes were decoded
89
 */
90
int xlat_decode_value_box_list(TALLOC_CTX *ctx, fr_pair_list_t *out,
91
             request_t *request, void *decode_ctx, fr_pair_decode_t decode,
92
             fr_value_box_list_t *in)
93
0
{
94
0
  int   decoded = 0;
95
0
  fr_pair_t *vp = NULL;
96
0
  fr_dict_attr_t const *parent = fr_dict_root(request->proto_dict);
97
0
  fr_pair_list_t  head;
98
99
0
  fr_pair_list_init(&head);
100
101
0
  fr_value_box_list_foreach(in, vb) {
102
0
    ssize_t   len;
103
104
0
    if (vb->type != FR_TYPE_OCTETS) {
105
0
      RWDEBUG("Skipping value \"%pR\", expected value of type %s, got type %s",
106
0
        vb,
107
0
        fr_type_to_str(FR_TYPE_OCTETS),
108
0
        fr_type_to_str(vb->type));
109
0
      continue;
110
0
    }
111
112
0
    len = fr_pair_decode_multi(ctx, &head, parent,
113
0
             vb->vb_octets, vb->vb_length, decode_ctx, decode);
114
0
    if (len <= 0) {
115
0
      fr_pair_list_free(&head);
116
0
      return -decoded;
117
0
    }
118
0
    decoded++;  /* one more VB, but there may be many pairs in the decoded vps. */
119
0
  }
120
121
0
  if (RDEBUG_ENABLED2) {
122
0
    char const *name = parent->name;
123
124
0
    while ((vp = fr_pair_list_next(&head, vp))) {
125
0
      RDEBUG2("decode %s: %pP", name, vp);
126
0
    }
127
0
  }
128
129
0
  decoded = fr_pair_list_num_elements(&head);
130
131
0
  fr_pair_list_append(out, &head);
132
133
0
  return decoded;
134
0
}