Coverage Report

Created: 2026-09-28 06:27

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/freeradius-server/src/protocols/radius/radius.h
Line
Count
Source
1
#pragma once
2
/*
3
 *  This program is free software; you can redistribute it and/or modify
4
 *  it under the terms of the GNU General Public License as published by
5
 *  the Free Software Foundation; either version 2 of the License, or
6
 *  (at your option) any later version.
7
 *
8
 *  This program is distributed in the hope that it will be useful,
9
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
 *  GNU General Public License for more details.
12
 *
13
 *  You should have received a copy of the GNU General Public License
14
 *  along with this program; if not, write to the Free Software
15
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
16
 */
17
18
/*
19
 * $Id: 1626f0d95d45327f72272ea4fc85a25a0cc74a3a $
20
 *
21
 * @file protocols/radius/radius.h
22
 * @brief Structures and prototypes for base RADIUS functionality.
23
 *
24
 * @copyright 1999-2017 The FreeRADIUS server project
25
 */
26
#include <freeradius-devel/radius/defs.h>
27
#include <freeradius-devel/util/packet.h>
28
#include <freeradius-devel/util/rand.h>
29
#include <freeradius-devel/util/log.h>
30
#include <freeradius-devel/util/dbuff.h>
31
#include <freeradius-devel/io/test_point.h>
32
33
#define RADIUS_AUTH_VECTOR_OFFSET         4
34
0
#define RADIUS_HEADER_LENGTH      20
35
9.24k
#define RADIUS_MAX_STRING_LENGTH    253
36
#define RADIUS_MAX_TUNNEL_PASSWORD_LENGTH 249
37
0
#define RADIUS_AUTH_VECTOR_LENGTH   16
38
#define RADIUS_MESSAGE_AUTHENTICATOR_LENGTH 16
39
#define RADIUS_MAX_ATTRIBUTES     255
40
0
#define RADIUS_MAX_PACKET_SIZE      4096
41
42
#define RADIUS_VENDORPEC_USR      429
43
#define RADIUS_VENDORPEC_LUCENT     4846
44
#define RADIUS_VENDORPEC_STARENT    8164
45
46
/*
47
 *  protocols/radius/base.c
48
 */
49
50
51
0
#define FR_RADIUS_PACKET_CODE_VALID(_x) ((_x > 0) && (_x < FR_RADIUS_CODE_MAX))
52
53
0
#define AUTH_PASS_LEN (RADIUS_AUTH_VECTOR_LENGTH)
54
55
#define FR_TUNNEL_FR_ENC_LENGTH(_x) (2 + 1 + _x + PAD(_x + 1, 16))
56
57
/** Control whether Message-Authenticator is required in Access-Requests
58
 *
59
 * @note Don't change the enum values.  They allow efficient bistmasking.
60
 */
61
typedef enum {
62
  FR_RADIUS_REQUIRE_MA_NO     = 0x00,   //!< Do not require Message-Authenticator
63
  FR_RADIUS_REQUIRE_MA_YES    = 0x01,   //!< Require Message-Authenticator
64
  FR_RADIUS_REQUIRE_MA_AUTO   = 0x02,   //!< Only require Message-Authenticator if we've previously
65
                ///< received a packet from this client with Message-Authenticator.
66
                ///< @note This isn't used by the radius protocol code, but may be used
67
                ///< to drive logic in modules.
68
69
} fr_radius_require_ma_t;
70
71
/** Control whether Proxy-State is allowed in Access-Requests
72
 *
73
 * @note Don't change the enum values.  They allow efficient bistmasking.
74
 */
75
typedef enum {
76
  FR_RADIUS_LIMIT_PROXY_STATE_NO    = 0x00,   //!< Do not limit Proxy-State.  Allow proxy-state to be sent in
77
                ///< all packets.
78
  FR_RADIUS_LIMIT_PROXY_STATE_YES   = 0x01,   //!< Limit Proxy-State.  Do not allow Proxy-State to be sent in
79
                ///< packets which do not have a Message-Authenticator attribute.
80
81
  FR_RADIUS_LIMIT_PROXY_STATE_AUTO  = 0x02,   //!< Do not allow Proxy-State unless:
82
                ///< - All packets received from a client have containted proxy state.
83
                ///< - The client has sent a packet with a Message-Authenticator.
84
                ///< @note This isn't used by the radius protocol code, but may be used
85
                ///< to drive logic in modules.
86
} fr_radius_limit_proxy_state_t;
87
88
/** Failure reasons */
89
typedef enum {
90
  FR_RADIUS_FAIL_NONE = 0,
91
  FR_RADIUS_FAIL_MIN_LENGTH_PACKET,
92
  FR_RADIUS_FAIL_MAX_LENGTH_PACKET,
93
  FR_RADIUS_FAIL_MIN_LENGTH_FIELD,
94
  FR_RADIUS_FAIL_MIN_LENGTH_MISMATCH,
95
  FR_RADIUS_FAIL_UNKNOWN_PACKET_CODE,
96
  FR_RADIUS_FAIL_UNEXPECTED_REQUEST_CODE,
97
  FR_RADIUS_FAIL_UNEXPECTED_RESPONSE_CODE,
98
  FR_RADIUS_FAIL_TOO_MANY_ATTRIBUTES,
99
100
  FR_RADIUS_FAIL_INVALID_ATTRIBUTE,
101
102
  FR_RADIUS_FAIL_HEADER_OVERFLOW,
103
  FR_RADIUS_FAIL_ATTRIBUTE_TOO_SHORT,
104
  FR_RADIUS_FAIL_ATTRIBUTE_OVERFLOW,
105
  FR_RADIUS_FAIL_ATTRIBUTE_DECODE,
106
107
  FR_RADIUS_FAIL_MA_INVALID_LENGTH,
108
  FR_RADIUS_FAIL_MA_MISSING,
109
  FR_RADIUS_FAIL_MA_INVALID,
110
  FR_RADIUS_FAIL_MA_TOO_MANY,
111
  FR_RADIUS_FAIL_PROXY_STATE_MISSING_MA,
112
113
  FR_RADIUS_FAIL_VERIFY,
114
  FR_RADIUS_FAIL_NO_MATCHING_REQUEST,
115
  FR_RADIUS_FAIL_IO_ERROR,
116
  FR_RADIUS_FAIL_MAX
117
} fr_radius_decode_fail_t;
118
119
extern char const *fr_radius_decode_fail_reason[FR_RADIUS_FAIL_MAX + 1];
120
121
typedef struct {
122
  fr_pair_t *parent;
123
  fr_dcursor_t  cursor;
124
} fr_radius_tag_ctx_t;
125
126
typedef struct {
127
  char const    *secret;
128
  size_t      secret_length;
129
130
  bool      secure_transport; //!< for TLS
131
132
  uint64_t    proxy_state;
133
} fr_radius_ctx_t;
134
135
typedef struct {
136
  fr_radius_ctx_t const *common;
137
138
  uint8_t const   *request_authenticator;
139
140
  fr_fast_rand_t    rand_ctx;   //!< for tunnel passwords
141
142
  uint8_t     tag;      //!< current tag for encoding
143
144
  uint8_t     request_code;
145
146
  uint8_t     code;
147
  uint8_t     id;
148
149
  bool      add_proxy_state;        //!< do we add a Proxy-State?
150
  bool      seen_message_authenticator;
151
  bool      foreign;    //!< are we in a foreign protocol?
152
#ifdef NAS_VIOLATES_RFC
153
  bool      allow_vulnerable_clients; //!< for vendors who violate the RFCs.
154
#endif
155
156
} fr_radius_encode_ctx_t;
157
158
typedef struct {
159
  fr_radius_ctx_t const   *common;
160
161
  uint8_t const   *request_authenticator;
162
163
  TALLOC_CTX    *tmp_ctx;   //!< for temporary things cleaned up during decoding
164
  uint8_t const     *end;     //!< end of the packet
165
166
  fr_radius_decode_fail_t reason;     //!< reason for decode failure
167
168
  uint8_t     request_code;   //!< original code for the request.
169
170
  bool      tunnel_password_zeros;  //!< check for trailing zeros on decode
171
  bool      verify;     //!< can skip verify for dynamic clients
172
  bool      require_message_authenticator;
173
  bool      limit_proxy_state;  //!< Don't allow Proxy-State in requests
174
175
  fr_radius_tag_ctx_t     **tags;     //!< for decoding tagged attributes
176
  fr_pair_list_t    *tag_root;    //!< Where to insert tag attributes.
177
  TALLOC_CTX    *tag_root_ctx;    //!< Where to allocate new tag attributes.
178
} fr_radius_decode_ctx_t;
179
180
typedef enum {
181
  RADIUS_FLAG_ENCRYPT_INVALID = -1,     //!< Invalid encryption flag.
182
  RADIUS_FLAG_ENCRYPT_NONE = 0,       //!< No encryption.
183
  RADIUS_FLAG_ENCRYPT_USER_PASSWORD = 1,      //!< Encrypt attribute RFC 2865 style.
184
  RADIUS_FLAG_ENCRYPT_TUNNEL_PASSWORD = 2,    //!< Encrypt attribute RFC 2868 style.
185
  RADIUS_FLAG_ENCRYPT_ASCEND_SECRET = 3,      //!< Encrypt attribute ascend style.
186
} fr_radius_attr_flags_encrypt_t;
187
188
typedef struct {
189
  unsigned int      long_extended : 1;  //!< Attribute is a long extended attribute
190
  unsigned int      extended : 1;   //!< Attribute is an extended attribute
191
  unsigned int      concat : 1;   //!< Attribute is concatenated
192
  unsigned int      has_tag : 1;    //!< Attribute has a tag
193
  unsigned int      abinary : 1;    //!< Attribute is in "abinary" format
194
  fr_radius_attr_flags_encrypt_t  encrypt;    //!< Attribute is encrypted
195
} fr_radius_attr_flags_t;
196
197
DIAG_OFF(unused-function)
198
extern fr_dict_protocol_t libfreeradius_radius_dict_protocol;
199
200
/** Return RADIUS-specific flags for a given attribute
201
 *
202
 * Assert in debug builds when the attribute belongs to another dictionary, as
203
 * the flags of one protocol say nothing about an attribute of another.
204
 *
205
 * If the attribute does not carry the protocol-specific extension, then assert.
206
 * Other builds log the error and return zeroed flags instead of NULL.
207
 */
208
static inline fr_radius_attr_flags_t const * fr_radius_attr_flags(fr_dict_attr_t const *da)
209
0
{
210
0
  static fr_radius_attr_flags_t const no_flags = {};
211
0
  fr_radius_attr_flags_t const    *flags;
212
0
213
0
  fr_assert_msg(fr_dict_protocol(da->dict) == &libfreeradius_radius_dict_protocol,
214
0
          "%s is not a RADIUS attribute, it is from the \"%s\" dictionary",
215
0
          da->name, fr_dict_root(da->dict)->name);
216
0
217
0
  flags = fr_dict_attr_ext(da, FR_DICT_ATTR_EXT_PROTOCOL_SPECIFIC);
218
0
  if (!fr_cond_assert_msg(flags, "%s is not a RADIUS attribute, it has no protocol extension",
219
0
        da->name)) return &no_flags;
220
0
221
0
  return flags;
222
0
}
Unexecuted instantiation: list.c:fr_radius_attr_flags
Unexecuted instantiation: abinary.c:fr_radius_attr_flags
223
224
static inline bool fr_radius_flag_has_tag(fr_dict_attr_t const *da)
225
0
{
226
0
  return fr_radius_attr_flags(da)->has_tag;
227
0
}
Unexecuted instantiation: encode.c:fr_radius_flag_has_tag
Unexecuted instantiation: list.c:fr_radius_flag_has_tag
Unexecuted instantiation: abinary.c:fr_radius_flag_has_tag
228
229
static inline bool fr_radius_flag_concat(fr_dict_attr_t const *da)
230
0
{
231
0
  return fr_radius_attr_flags(da)->concat;
232
0
}
Unexecuted instantiation: encode.c:fr_radius_flag_concat
Unexecuted instantiation: list.c:fr_radius_flag_concat
Unexecuted instantiation: abinary.c:fr_radius_flag_concat
233
234
static inline bool fr_radius_flag_abinary(fr_dict_attr_t const *da)
235
0
{
236
0
  return fr_radius_attr_flags(da)->abinary;
237
0
}
Unexecuted instantiation: encode.c:fr_radius_flag_abinary
Unexecuted instantiation: list.c:fr_radius_flag_abinary
Unexecuted instantiation: abinary.c:fr_radius_flag_abinary
238
239
static inline fr_radius_attr_flags_encrypt_t fr_radius_flag_encrypted(fr_dict_attr_t const *da)
240
0
{
241
0
  return fr_radius_attr_flags(da)->encrypt;
242
0
}
Unexecuted instantiation: encode.c:fr_radius_flag_encrypted
Unexecuted instantiation: list.c:fr_radius_flag_encrypted
Unexecuted instantiation: abinary.c:fr_radius_flag_encrypted
243
244
static inline bool fr_radius_flag_extended(fr_dict_attr_t const *da)
245
0
{
246
0
  fr_radius_attr_flags_t const *flags = fr_radius_attr_flags(da);
247
248
0
  return flags->extended || flags->long_extended;
249
0
}
Unexecuted instantiation: encode.c:fr_radius_flag_extended
Unexecuted instantiation: list.c:fr_radius_flag_extended
Unexecuted instantiation: abinary.c:fr_radius_flag_extended
250
251
static inline bool fr_radius_flag_long_extended(fr_dict_attr_t const *da)
252
0
{
253
0
  return fr_radius_attr_flags(da)->long_extended;
254
0
}
Unexecuted instantiation: encode.c:fr_radius_flag_long_extended
Unexecuted instantiation: list.c:fr_radius_flag_long_extended
Unexecuted instantiation: abinary.c:fr_radius_flag_long_extended
255
DIAG_ON(unused-function)
256
257
extern fr_table_num_sorted_t const fr_radius_require_ma_table[];
258
extern size_t fr_radius_require_ma_table_len;
259
260
extern fr_table_num_sorted_t const fr_radius_limit_proxy_state_table[];
261
extern size_t fr_radius_limit_proxy_state_table_len;
262
263
extern fr_table_num_sorted_t const fr_radius_request_name_table[];
264
extern size_t fr_radius_request_name_table_len;
265
266
extern char const *fr_radius_packet_name[FR_RADIUS_CODE_MAX];
267
268
/*
269
 *  protocols/radius/base.c
270
 */
271
int   fr_radius_allow_reply(int code, bool allowed[static FR_RADIUS_CODE_MAX]);
272
273
int   fr_radius_sign(uint8_t *packet, uint8_t const *vector,
274
             uint8_t const *secret, size_t secret_len) CC_HINT(nonnull (1,3));
275
276
int   fr_radius_verify(uint8_t *packet, uint8_t const *vector,
277
         uint8_t const *secret, size_t secret_len,
278
         bool require_message_authenticator, bool limit_proxy_state) CC_HINT(nonnull (1,3));
279
280
bool    fr_radius_ok(uint8_t const *packet, size_t *packet_len_p,
281
           uint32_t max_attributes, bool require_message_authenticator, fr_radius_decode_fail_t *reason) CC_HINT(nonnull (1,2));
282
283
ssize_t   fr_radius_ascend_secret(fr_dbuff_t *dbuff, uint8_t const *in, size_t inlen,
284
          char const *secret, size_t secret_len, uint8_t const *vector);
285
286
ssize_t   fr_radius_recv_header(int sockfd, fr_ipaddr_t *src_ipaddr, uint16_t *src_port, unsigned int *code);
287
288
ssize_t   fr_radius_encode(fr_dbuff_t *dbuff, fr_pair_list_t *vps, fr_radius_encode_ctx_t *packet_ctx) CC_HINT(nonnull);
289
290
ssize_t   fr_radius_decode(TALLOC_CTX *ctx, fr_pair_list_t *out,
291
         uint8_t *packet, size_t packet_len,
292
         fr_radius_decode_ctx_t *decode_ctx) CC_HINT(nonnull);
293
294
ssize_t   fr_radius_decode_simple(TALLOC_CTX *ctx, fr_pair_list_t *out,
295
          uint8_t *packet, size_t packet_len,
296
          uint8_t const *vector, char const *secret) CC_HINT(nonnull(1,2,3,6));
297
298
int   fr_radius_global_init(void);
299
300
void    fr_radius_global_free(void);
301
302
/*
303
 *  protocols/radius/packet.c
304
 */
305
ssize_t   fr_radius_packet_encode(fr_packet_t *packet, fr_pair_list_t *list,
306
          fr_packet_t const *original,
307
          char const *secret) CC_HINT(nonnull (1,2,4));
308
309
bool    fr_packet_ok(fr_packet_t *packet, uint32_t max_attributes, bool require_message_authenticator,
310
            fr_radius_decode_fail_t *reason) CC_HINT(nonnull (1));
311
312
int   fr_radius_packet_verify(fr_packet_t *packet, fr_packet_t *original,
313
          char const *secret) CC_HINT(nonnull (1,3));
314
int   fr_radius_packet_sign(fr_packet_t *packet, fr_packet_t const *original,
315
              char const *secret) CC_HINT(nonnull (1,3));
316
317
fr_packet_t *fr_packet_recv(TALLOC_CTX *ctx, int fd, int flags, uint32_t max_attributes, bool require_message_authenticator);
318
int   fr_radius_packet_send(fr_packet_t *packet, fr_pair_list_t *list,
319
              fr_packet_t const *original, char const *secret) CC_HINT(nonnull (1,2,4));
320
321
#define fr_packet_log_hex(_log, _packet) _fr_packet_log_hex(_log, _packet, __FILE__, __LINE__)
322
void    _fr_packet_log_hex(fr_log_t const *log, fr_packet_t const *packet, char const *file, int line) CC_HINT(nonnull);
323
324
/*
325
 *  protocols/radius/abinary.c
326
 */
327
ssize_t   fr_radius_encode_abinary(fr_pair_t const *vp, fr_dbuff_t *dbuff);
328
329
ssize_t   fr_radius_decode_abinary(fr_pair_t *vp, uint8_t const *data, size_t data_len);
330
331
/*
332
 *  protocols/radius/encode.c
333
 */
334
ssize_t   fr_radius_encode_pair(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, void *encode_ctx);
335
336
ssize_t   fr_radius_encode_foreign(fr_dbuff_t *dbuff, fr_pair_list_t const *list) CC_HINT(nonnull);
337
338
/*
339
 *  protocols/radius/decode.c
340
 */
341
int   fr_radius_decode_tlv_ok(uint8_t const *data, size_t length, size_t dv_type, size_t dv_length);
342
343
ssize_t   fr_radius_decode_pair_value(TALLOC_CTX *ctx, fr_pair_list_t *list,
344
              fr_dict_attr_t const *parent,
345
              uint8_t const *data, size_t const attr_len,
346
              void *packet_ctx) CC_HINT(nonnull);
347
348
ssize_t   fr_radius_decode_tlv(TALLOC_CTX *ctx, fr_pair_list_t *list,
349
             fr_dict_attr_t const *parent,
350
             uint8_t const *data, size_t data_len,
351
             fr_radius_decode_ctx_t *packet_ctx) CC_HINT(nonnull);
352
353
ssize_t   fr_radius_decode_pair(TALLOC_CTX *ctx, fr_pair_list_t *list,
354
              uint8_t const *data, size_t data_len, fr_radius_decode_ctx_t *packet_ctx) CC_HINT(nonnull);
355
356
ssize_t   fr_radius_decode_foreign(TALLOC_CTX *ctx, fr_pair_list_t *out,
357
           uint8_t const *data, size_t data_len) CC_HINT(nonnull);
358
359
void    fr_radius_packet_header_log(fr_log_t const *log, fr_packet_t *packet, bool received);
360
361
void    fr_radius_packet_log(fr_log_t const *log, fr_packet_t *packet, fr_pair_list_t *list, bool received);