Coverage Report

Created: 2025-12-31 06:18

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: 94a6519e1dbbe65c5e24cd14bc2fbd6156877859 $
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
#define RADIUS_HEADER_LENGTH      20
35
4.71k
#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
0
#define RADIUS_MAX_PASS_LENGTH      256
40
#define RADIUS_MAX_ATTRIBUTES     255
41
#define RADIUS_MAX_PACKET_SIZE      4096
42
43
#define RADIUS_VENDORPEC_USR      429
44
#define RADIUS_VENDORPEC_LUCENT     4846
45
#define RADIUS_VENDORPEC_STARENT    8164
46
47
/*
48
 *  protocols/radius/base.c
49
 */
50
51
52
#define FR_RADIUS_PACKET_CODE_VALID(_x) ((_x > 0) && (_x < FR_RADIUS_CODE_MAX))
53
54
0
#define AUTH_PASS_LEN (RADIUS_AUTH_VECTOR_LENGTH)
55
56
#define FR_TUNNEL_FR_ENC_LENGTH(_x) (2 + 1 + _x + PAD(_x + 1, 16))
57
58
/** Control whether Message-Authenticator is required in Access-Requests
59
 *
60
 * @note Don't change the enum values.  They allow efficient bistmasking.
61
 */
62
typedef enum {
63
  FR_RADIUS_REQUIRE_MA_NO     = 0x00,   //!< Do not require Message-Authenticator
64
  FR_RADIUS_REQUIRE_MA_YES    = 0x01,   //!< Require Message-Authenticator
65
  FR_RADIUS_REQUIRE_MA_AUTO   = 0x02,   //!< Only require Message-Authenticator if we've previously
66
                ///< received a packet from this client with Message-Authenticator.
67
                ///< @note This isn't used by the radius protocol code, but may be used
68
                ///< to drive logic in modules.
69
70
} fr_radius_require_ma_t;
71
72
/** Control whether Proxy-State is allowed in Access-Requests
73
 *
74
 * @note Don't change the enum values.  They allow efficient bistmasking.
75
 */
76
typedef enum {
77
  FR_RADIUS_LIMIT_PROXY_STATE_NO    = 0x00,   //!< Do not limit Proxy-State.  Allow proxy-state to be sent in
78
                ///< all packets.
79
  FR_RADIUS_LIMIT_PROXY_STATE_YES   = 0x01,   //!< Limit Proxy-State.  Do not allow Proxy-State to be sent in
80
                ///< packets which do not have a Message-Authenticator attribute.
81
82
  FR_RADIUS_LIMIT_PROXY_STATE_AUTO  = 0x02,   //!< Do not allow Proxy-State unless:
83
                ///< - All packets received from a client have containted proxy state.
84
                ///< - The client has sent a packet with a Message-Authenticator.
85
                ///< @note This isn't used by the radius protocol code, but may be used
86
                ///< to drive logic in modules.
87
} fr_radius_limit_proxy_state_t;
88
89
typedef struct {
90
  fr_pair_t *parent;
91
  fr_dcursor_t  cursor;
92
} fr_radius_tag_ctx_t;
93
94
typedef struct {
95
  char const    *secret;
96
  size_t      secret_length;
97
98
  bool      secure_transport; //!< for TLS
99
100
  uint64_t    proxy_state;
101
} fr_radius_ctx_t;
102
103
typedef struct {
104
  fr_radius_ctx_t const *common;
105
106
  uint8_t const   *request_authenticator;
107
108
  fr_fast_rand_t    rand_ctx;   //!< for tunnel passwords
109
  int     salt_offset;    //!< for tunnel passwords
110
111
112
  uint8_t     tag;      //!< current tag for encoding
113
114
  uint8_t     request_code;
115
116
  uint8_t     code;
117
  uint8_t     id;
118
119
  bool      add_proxy_state;        //!< do we add a Proxy-State?
120
  bool      disallow_tunnel_passwords; //!< not all packets can have tunnel passwords
121
  bool      seen_message_authenticator;
122
} fr_radius_encode_ctx_t;
123
124
typedef struct {
125
  fr_radius_ctx_t const   *common;
126
127
  uint8_t const   *request_authenticator;
128
129
  TALLOC_CTX    *tmp_ctx;   //!< for temporary things cleaned up during decoding
130
  uint8_t const     *end;     //!< end of the packet
131
132
  uint8_t     request_code;   //!< original code for the request.
133
134
  bool      tunnel_password_zeros;  //!< check for trailing zeros on decode
135
  bool      verify;     //!< can skip verify for dynamic clients
136
  bool      require_message_authenticator;
137
  bool      limit_proxy_state;  //!< Don't allow Proxy-State in requests
138
139
  fr_radius_tag_ctx_t     **tags;     //!< for decoding tagged attributes
140
  fr_pair_list_t    *tag_root;    //!< Where to insert tag attributes.
141
  TALLOC_CTX    *tag_root_ctx;    //!< Where to allocate new tag attributes.
142
} fr_radius_decode_ctx_t;
143
144
typedef enum {
145
  RADIUS_FLAG_ENCRYPT_INVALID = -1,     //!< Invalid encryption flag.
146
  RADIUS_FLAG_ENCRYPT_NONE = 0,       //!< No encryption.
147
  RADIUS_FLAG_ENCRYPT_USER_PASSWORD = 1,      //!< Encrypt attribute RFC 2865 style.
148
  RADIUS_FLAG_ENCRYPT_TUNNEL_PASSWORD = 2,    //!< Encrypt attribute RFC 2868 style.
149
  RADIUS_FLAG_ENCRYPT_ASCEND_SECRET = 3,      //!< Encrypt attribute ascend style.
150
} fr_radius_attr_flags_encrypt_t;
151
152
typedef struct {
153
  unsigned int      long_extended : 1;  //!< Attribute is a long extended attribute
154
  unsigned int      extended : 1;   //!< Attribute is an extended attribute
155
  unsigned int      concat : 1;   //!< Attribute is concatenated
156
  unsigned int      has_tag : 1;    //!< Attribute has a tag
157
  unsigned int      abinary : 1;    //!< Attribute is in "abinary" format
158
  fr_radius_attr_flags_encrypt_t  encrypt;    //!< Attribute is encrypted
159
} fr_radius_attr_flags_t;
160
161
/** Failure reasons */
162
typedef enum {
163
  DECODE_FAIL_NONE = 0,
164
  DECODE_FAIL_MIN_LENGTH_PACKET,
165
  DECODE_FAIL_MAX_LENGTH_PACKET,
166
  DECODE_FAIL_MIN_LENGTH_FIELD,
167
  DECODE_FAIL_MIN_LENGTH_MISMATCH,
168
  DECODE_FAIL_HEADER_OVERFLOW,
169
  DECODE_FAIL_UNKNOWN_PACKET_CODE,
170
  DECODE_FAIL_INVALID_ATTRIBUTE,
171
  DECODE_FAIL_ATTRIBUTE_TOO_SHORT,
172
  DECODE_FAIL_ATTRIBUTE_OVERFLOW,
173
  DECODE_FAIL_MA_INVALID_LENGTH,
174
  DECODE_FAIL_ATTRIBUTE_UNDERFLOW,
175
  DECODE_FAIL_TOO_MANY_ATTRIBUTES,
176
  DECODE_FAIL_MA_MISSING,
177
  DECODE_FAIL_MA_INVALID,
178
  DECODE_FAIL_VERIFY,
179
  DECODE_FAIL_UNKNOWN,
180
  DECODE_FAIL_MAX
181
} fr_radius_decode_fail_t;
182
183
184
DIAG_OFF(unused-function)
185
/** Return RADIUS-specific flags for a given attribute
186
 */
187
static inline fr_radius_attr_flags_t const * fr_radius_attr_flags(fr_dict_attr_t const *da)
188
0
{
189
0
  return fr_dict_attr_ext(da, FR_DICT_ATTR_EXT_PROTOCOL_SPECIFIC);
190
0
}
Unexecuted instantiation: encode.c:fr_radius_attr_flags
Unexecuted instantiation: list.c:fr_radius_attr_flags
Unexecuted instantiation: abinary.c:fr_radius_attr_flags
191
192
0
#define fr_radius_flag_has_tag(_da)   fr_radius_attr_flags(_da)->has_tag
193
0
#define fr_radius_flag_concat(_da)    fr_radius_attr_flags(_da)->concat
194
0
#define fr_radius_flag_abinary(_da)   fr_radius_attr_flags(_da)->abinary
195
0
#define fr_radius_flag_encrypted(_da)   fr_radius_attr_flags(_da)->encrypt
196
197
static bool fr_radius_flag_extended(fr_dict_attr_t const *da)
198
0
{
199
0
  fr_radius_attr_flags_t const *flags = fr_radius_attr_flags(da);
200
201
0
  return flags->extended || flags->long_extended;
202
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
203
204
0
#define fr_radius_flag_long_extended(_da) fr_radius_attr_flags(_da)->long_extended
205
DIAG_ON(unused-function)
206
207
extern fr_table_num_sorted_t const fr_radius_require_ma_table[];
208
extern size_t fr_radius_require_ma_table_len;
209
210
extern fr_table_num_sorted_t const fr_radius_limit_proxy_state_table[];
211
extern size_t fr_radius_limit_proxy_state_table_len;
212
213
extern fr_table_num_sorted_t const fr_radius_request_name_table[];
214
extern size_t fr_radius_request_name_table_len;
215
216
extern char const *fr_radius_packet_name[FR_RADIUS_CODE_MAX];
217
218
/*
219
 *  protocols/radius/base.c
220
 */
221
int   fr_radius_allow_reply(int code, bool allowed[static FR_RADIUS_CODE_MAX]);
222
223
int   fr_radius_sign(uint8_t *packet, uint8_t const *vector,
224
             uint8_t const *secret, size_t secret_len) CC_HINT(nonnull (1,3));
225
226
int   fr_radius_verify(uint8_t *packet, uint8_t const *vector,
227
         uint8_t const *secret, size_t secret_len,
228
         bool require_message_authenticator, bool limit_proxy_state) CC_HINT(nonnull (1,3));
229
230
bool    fr_radius_ok(uint8_t const *packet, size_t *packet_len_p,
231
           uint32_t max_attributes, bool require_message_authenticator, fr_radius_decode_fail_t *reason) CC_HINT(nonnull (1,2));
232
233
ssize_t   fr_radius_ascend_secret(fr_dbuff_t *dbuff, uint8_t const *in, size_t inlen,
234
          char const *secret, uint8_t const *vector);
235
236
ssize_t   fr_radius_recv_header(int sockfd, fr_ipaddr_t *src_ipaddr, uint16_t *src_port, unsigned int *code);
237
238
ssize_t   fr_radius_encode(fr_dbuff_t *dbuff, fr_pair_list_t *vps, fr_radius_encode_ctx_t *packet_ctx) CC_HINT(nonnull);
239
240
ssize_t   fr_radius_decode(TALLOC_CTX *ctx, fr_pair_list_t *out,
241
         uint8_t *packet, size_t packet_len,
242
         fr_radius_decode_ctx_t *decode_ctx) CC_HINT(nonnull);
243
244
ssize_t   fr_radius_decode_simple(TALLOC_CTX *ctx, fr_pair_list_t *out,
245
          uint8_t *packet, size_t packet_len,
246
          uint8_t const *vector, char const *secret) CC_HINT(nonnull(1,2,3,6));
247
248
int   fr_radius_global_init(void);
249
250
void    fr_radius_global_free(void);
251
252
/*
253
 *  protocols/radius/packet.c
254
 */
255
ssize_t   fr_packet_encode(fr_packet_t *packet, fr_pair_list_t *list,
256
          fr_packet_t const *original,
257
          char const *secret) CC_HINT(nonnull (1,2,4));
258
259
bool    fr_packet_ok(fr_packet_t *packet, uint32_t max_attributes, bool require_message_authenticator,
260
            fr_radius_decode_fail_t *reason) CC_HINT(nonnull (1));
261
262
int   fr_packet_verify(fr_packet_t *packet, fr_packet_t *original,
263
          char const *secret) CC_HINT(nonnull (1,3));
264
int   fr_packet_sign(fr_packet_t *packet, fr_packet_t const *original,
265
              char const *secret) CC_HINT(nonnull (1,3));
266
267
fr_packet_t *fr_packet_recv(TALLOC_CTX *ctx, int fd, int flags, uint32_t max_attributes, bool require_message_authenticator);
268
int   fr_packet_send(fr_packet_t *packet, fr_pair_list_t *list,
269
              fr_packet_t const *original, char const *secret) CC_HINT(nonnull (1,2,4));
270
271
#define fr_packet_log_hex(_log, _packet) _fr_packet_log_hex(_log, _packet, __FILE__, __LINE__)
272
void    _fr_packet_log_hex(fr_log_t const *log, fr_packet_t const *packet, char const *file, int line) CC_HINT(nonnull);
273
274
/*
275
 *  protocols/radius/abinary.c
276
 */
277
ssize_t   fr_radius_encode_abinary(fr_pair_t const *vp, fr_dbuff_t *dbuff);
278
279
ssize_t   fr_radius_decode_abinary(fr_pair_t *vp, uint8_t const *data, size_t data_len);
280
281
/*
282
 *  protocols/radius/encode.c
283
 */
284
ssize_t   fr_radius_encode_pair(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, void *encode_ctx);
285
286
ssize_t   fr_radius_encode_foreign(fr_dbuff_t *dbuff, fr_pair_list_t const *list) CC_HINT(nonnull);
287
288
/*
289
 *  protocols/radius/decode.c
290
 */
291
int   fr_radius_decode_tlv_ok(uint8_t const *data, size_t length, size_t dv_type, size_t dv_length);
292
293
ssize_t   fr_radius_decode_pair_value(TALLOC_CTX *ctx, fr_pair_list_t *list,
294
              fr_dict_attr_t const *parent,
295
              uint8_t const *data, size_t const attr_len,
296
              void *packet_ctx) CC_HINT(nonnull);
297
298
ssize_t   fr_radius_decode_tlv(TALLOC_CTX *ctx, fr_pair_list_t *list,
299
             fr_dict_attr_t const *parent,
300
             uint8_t const *data, size_t data_len,
301
             fr_radius_decode_ctx_t *packet_ctx) CC_HINT(nonnull);
302
303
ssize_t   fr_radius_decode_pair(TALLOC_CTX *ctx, fr_pair_list_t *list,
304
              uint8_t const *data, size_t data_len, fr_radius_decode_ctx_t *packet_ctx) CC_HINT(nonnull);
305
306
ssize_t   fr_radius_decode_foreign(TALLOC_CTX *ctx, fr_pair_list_t *out,
307
           uint8_t const *data, size_t data_len) CC_HINT(nonnull);
308
309
void    fr_radius_packet_header_log(fr_log_t const *log, fr_packet_t *packet, bool received);
310
311
void    fr_radius_packet_log(fr_log_t const *log, fr_packet_t *packet, fr_pair_list_t *list, bool received);