/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); |