The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
proto_radius.c
Go to the documentation of this file.
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: b54fc5c9e05ca564864d7bf74242996ac89beea3 $
19 * @file proto_radius.c
20 * @brief RADIUS master protocol handler.
21 *
22 * @copyright 2017 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
23 * @copyright 2016 Alan DeKok (aland@freeradius.org)
24 */
25#include <freeradius-devel/radius/radius.h>
26#include <freeradius-devel/io/listen.h>
27#include <freeradius-devel/unlang/xlat_func.h>
28#include <freeradius-devel/server/module_rlm.h>
29#include <stdbool.h>
30#include "proto_radius.h"
31
33
34static int type_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule);
35static int transport_parse(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule);
36
37static conf_parser_t const limit_config[] = {
38 { FR_CONF_OFFSET("cleanup_delay", proto_radius_t, io.cleanup_delay), .dflt = "5.0" } ,
39 { FR_CONF_OFFSET("idle_timeout", proto_radius_t, io.idle_timeout), .dflt = "30.0" } ,
40 { FR_CONF_OFFSET("nak_lifetime", proto_radius_t, io.nak_lifetime), .dflt = "30.0" } ,
41
42 { FR_CONF_OFFSET("max_connections", proto_radius_t, io.max_connections), .dflt = "1024" } ,
43 { FR_CONF_OFFSET("max_clients", proto_radius_t, io.max_clients), .dflt = "256" } ,
44 { FR_CONF_OFFSET("max_pending_packets", proto_radius_t, io.max_pending_packets), .dflt = "256" } ,
45
46 /*
47 * For performance tweaking. NOT for normal humans.
48 */
49 { FR_CONF_OFFSET("max_packet_size", proto_radius_t, max_packet_size) } ,
50 { FR_CONF_OFFSET("num_messages", proto_radius_t, num_messages) } ,
51
53};
54
56 { FR_CONF_OFFSET("Access-Request", proto_radius_t, priorities[FR_RADIUS_CODE_ACCESS_REQUEST]),
57 .func = cf_table_parse_int, .uctx = &(cf_table_parse_ctx_t){ .table = channel_packet_priority, .len = &channel_packet_priority_len }, .dflt = "high" },
58 { FR_CONF_OFFSET("Accounting-Request", proto_radius_t, priorities[FR_RADIUS_CODE_ACCOUNTING_REQUEST]),
59 .func = cf_table_parse_int, .uctx = &(cf_table_parse_ctx_t){ .table = channel_packet_priority, .len = &channel_packet_priority_len }, .dflt = "low" },
60 { FR_CONF_OFFSET("CoA-Request", proto_radius_t, priorities[FR_RADIUS_CODE_COA_REQUEST]),
61 .func = cf_table_parse_int, .uctx = &(cf_table_parse_ctx_t){ .table = channel_packet_priority, .len = &channel_packet_priority_len }, .dflt = "normal" },
62 { FR_CONF_OFFSET("Disconnect-Request", proto_radius_t, priorities[FR_RADIUS_CODE_DISCONNECT_REQUEST]),
63 .func = cf_table_parse_int, .uctx = &(cf_table_parse_ctx_t){ .table = channel_packet_priority, .len = &channel_packet_priority_len }, .dflt = "low" },
64 { FR_CONF_OFFSET("Status-Server", proto_radius_t, priorities[FR_RADIUS_CODE_STATUS_SERVER]),
65 .func = cf_table_parse_int, .uctx = &(cf_table_parse_ctx_t){ .table = channel_packet_priority, .len = &channel_packet_priority_len }, .dflt = "now" },
66
68};
69
70/** How to parse a RADIUS listen section
71 *
72 */
75 { FR_CONF_OFFSET_TYPE_FLAGS("transport", FR_TYPE_VOID, 0, proto_radius_t, io.submodule),
76 .func = transport_parse },
77
78 /*
79 * Check whether or not the *trailing* bits of a
80 * Tunnel-Password are zero, as they should be.
81 */
82 { FR_CONF_OFFSET("tunnel_password_zeros", proto_radius_t, tunnel_password_zeros) } ,
83
84 { FR_CONF_POINTER("limit", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) limit_config },
85 { FR_CONF_POINTER("priority", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) priority_config },
86
87 { FR_CONF_OFFSET("require_message_authenticator", proto_radius_t, require_message_authenticator),
90 .dflt = "no" },
91
92 { FR_CONF_OFFSET("limit_proxy_state", proto_radius_t, limit_proxy_state),
93 .func = cf_table_parse_int,
95 .dflt = "auto" },
96
98};
99
100static fr_dict_t const *dict_radius;
101
104 { .out = &dict_radius, .proto = "radius" },
105 { NULL }
106};
107
114
117 { .out = &attr_packet_type, .name = "Packet-Type", .type = FR_TYPE_UINT32, .dict = &dict_radius},
118 { .out = &attr_user_name, .name = "User-Name", .type = FR_TYPE_STRING, .dict = &dict_radius},
119 { .out = &attr_state, .name = "State", .type = FR_TYPE_OCTETS, .dict = &dict_radius},
120 { .out = &attr_proxy_state, .name = "Proxy-State", .type = FR_TYPE_OCTETS, .dict = &dict_radius},
121 { .out = &attr_message_authenticator, .name = "Message-Authenticator", .type = FR_TYPE_OCTETS, .dict = &dict_radius},
122 { .out = &attr_eap_message, .name = "EAP-Message", .type = FR_TYPE_OCTETS, .dict = &dict_radius},
123 { NULL }
124};
125
126/** Translates the packet-type into a submodule name
127 *
128 * If we found a Packet-Type = Access-Request CONF_PAIR for example, here's we'd load
129 * the proto_radius_auth module.
130 *
131 * @param[in] ctx to allocate data in (instance of proto_radius).
132 * @param[out] out Where to write a module_instance_t containing the module handle and instance.
133 * @param[in] parent Base structure address.
134 * @param[in] ci #CONF_PAIR specifying the name of the type module.
135 * @param[in] rule unused.
136 * @return
137 * - 0 on success.
138 * - -1 on failure.
139 */
140static int type_parse(UNUSED TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
141{
142 proto_radius_t *inst = talloc_get_type_abort(parent, proto_radius_t);
144 CONF_PAIR *cp;
145 char const *value;
146
147 cp = cf_item_to_pair(ci);
148 value = cf_pair_value(cp);
149
151 if (!dv || (dv->value->vb_uint32 >= FR_RADIUS_CODE_MAX)) {
152 cf_log_err(ci, "Unknown RADIUS packet type '%s'", value);
153 return -1;
154 }
155
156 inst->allowed[dv->value->vb_uint32] = true;
157 *((char const **) out) = value;
158
159 return 0;
160}
161
162static int transport_parse(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
163{
164 proto_radius_t *inst = talloc_get_type_abort(parent, proto_radius_t);
166
167 if (unlikely(virtual_server_listen_transport_parse(ctx, out, parent, ci, rule) < 0)) {
168 return -1;
169 }
170
171 mi = talloc_get_type_abort(*(void **)out, module_instance_t);
172 inst->io.app_io = (fr_app_io_t const *)mi->exported;
173 inst->io.app_io_instance = mi->data;
174 inst->io.app_io_conf = mi->conf;
175
176 return 0;
177}
178
179/** Decode the packet
180 *
181 */
182static int mod_decode(void const *instance, request_t *request, uint8_t *const data, size_t data_len)
183{
185 fr_io_track_t const *track = talloc_get_type_abort_const(request->async->packet_ctx, fr_io_track_t);
186 fr_io_address_t const *address = track->address;
187 fr_client_t *client = UNCONST(fr_client_t *, address->radclient);
188 fr_radius_ctx_t common_ctx;
189 fr_radius_decode_ctx_t decode_ctx;
190
191 fr_radius_require_ma_t require_message_authenticator = client->require_message_authenticator_is_set ?
193 inst->require_message_authenticator;
194 fr_radius_limit_proxy_state_t limit_proxy_state = client->limit_proxy_state_is_set ?
195 client->limit_proxy_state:
196 inst->limit_proxy_state;
197
199
200 /*
201 * Set the request dictionary so that we can do
202 * generic->protocol attribute conversions as
203 * the request runs through the server.
204 */
205 request->dict = dict_radius;
206
207 common_ctx = (fr_radius_ctx_t) {
208 .secret = client->secret,
209 .secret_length = talloc_array_length(client->secret) - 1,
210 };
211
212 request->packet->code = data[0];
213
214 decode_ctx = (fr_radius_decode_ctx_t) {
215 .common = &common_ctx,
216 .tmp_ctx = talloc(request, uint8_t),
217 /* decode figures out request_authenticator */
218 .end = data + data_len,
219 .verify = client->active,
220 };
221
222 if (request->packet->code == FR_RADIUS_CODE_ACCESS_REQUEST) {
223 /*
224 * bit1 is set if we've seen a packet, and the auto bit in require_message_authenticator is set/
225 * bit2 is set if we always require a message_authenticator.
226 * If either bit is high we require a message authenticator in the packet.
227 */
228 decode_ctx.require_message_authenticator = (
229 (client->received_message_authenticator & require_message_authenticator) |
230 (require_message_authenticator & FR_RADIUS_REQUIRE_MA_YES)
231 ) > 0;
232 decode_ctx.limit_proxy_state = (
233 (client->first_packet_no_proxy_state & limit_proxy_state) |
234 (limit_proxy_state & FR_RADIUS_LIMIT_PROXY_STATE_YES)
235 ) > 0;
236 }
237
238 /*
239 * The verify() routine over-writes the request packet vector.
240 *
241 * @todo - That needs to be changed.
242 */
243 request->packet->id = data[1];
244 request->reply->id = data[1];
245 memcpy(request->packet->vector, data + 4, sizeof(request->packet->vector));
246
247 request->packet->data = talloc_memdup(request->packet, data, data_len);
248 request->packet->data_len = data_len;
249
250 /*
251 * !client->active means a fake packet defining a dynamic client - so there will
252 * be no secret defined yet - so can't verify.
253 */
254 if (fr_radius_decode(request->request_ctx, &request->request_pairs,
255 data, data_len, &decode_ctx) < 0) {
256 talloc_free(decode_ctx.tmp_ctx);
257 RPEDEBUG("Failed reading packet");
258 return -1;
259 }
260 talloc_free(decode_ctx.tmp_ctx);
261
262 /*
263 * Set the rest of the fields.
264 */
265 request->client = client;
266
267 request->packet->socket = address->socket;
268 fr_socket_addr_swap(&request->reply->socket, &address->socket);
269
270 if (request->packet->code == FR_RADIUS_CODE_ACCESS_REQUEST) {
271 /*
272 * If require_message_authenticator is "auto" then
273 * we start requiring messages authenticator after
274 * the first Access-Request packet containing a
275 * verified one. This isn't vulnerable to the same
276 * attack as limit_proxy_state, as the attacker would
277 * need knowledge of the secret.
278 *
279 * Unfortunately there are too many cases where
280 * auto mode could break things (dealing with
281 * multiple clients behind a NAT for example).
282 */
283 if (!client->received_message_authenticator &&
284 fr_pair_find_by_da(&request->request_pairs, NULL, attr_message_authenticator)) {
285 /*
286 * Don't print debugging messages if all is OK.
287 */
288 if (require_message_authenticator == FR_RADIUS_REQUIRE_MA_YES) {
289 client->received_message_authenticator = true;
290
291 } else if (require_message_authenticator == FR_RADIUS_REQUIRE_MA_AUTO) {
292 if (!fr_pair_find_by_da(&request->request_pairs, NULL, attr_eap_message)) {
293 client->received_message_authenticator = true;
294
295 RINFO("Packet from client %pV (%pV) contained a valid Message-Authenticator. Setting \"require_message_authenticator = yes\"",
296 fr_box_ipaddr(client->ipaddr),
298 } else {
299 RINFO("Packet from client %pV (%pV) contained a valid Message-Authenticator but also EAP-Message",
300 fr_box_ipaddr(client->ipaddr),
302 RINFO("Not changing the value of 'require_message_authenticator = auto'");
303 }
304 }
305 }
306
307 /*
308 * It's important we only evaluate this on the
309 * first packet. Otherwise an attacker could send
310 * Access-Requests with no Proxy-State whilst
311 * spoofing a legitimate Proxy-Server, and causing an
312 * outage.
313 *
314 * The likelihood of an attacker sending a packet
315 * to coincide with the reboot of a RADIUS
316 * server is low. That said, 'auto' should likely
317 * not be enabled for internet facing servers.
318 */
319 if (!client->received_message_authenticator &&
320 (limit_proxy_state == FR_RADIUS_LIMIT_PROXY_STATE_AUTO) &&
321 client->active && !client->seen_first_packet) {
322 client->seen_first_packet = true;
323 client->first_packet_no_proxy_state = fr_pair_find_by_da(&request->request_pairs, NULL, attr_proxy_state) == NULL;
324
325 if (!fr_pair_find_by_da(&request->request_pairs, NULL, attr_message_authenticator)) {
326 RERROR("Packet from %pV (%pV) did not contain Message-Authenticator:",
327 fr_box_ipaddr(client->ipaddr),
329 RERROR("- Upgrade the client, as your network is vulnerable to the BlastRADIUS attack.");
330 RERROR("- Then set 'require_message_authenticator = yes' in the client definition");
331 } else {
332 RWARN("Packet from %pV (%pV) contains Message-Authenticator:",
333 fr_box_ipaddr(client->ipaddr),
335 RWARN("- Then set 'require_message_authenticator = yes' in the client definition");
336 }
337
338 RINFO("First packet from %pV (%pV) %s Proxy-State. Setting \"limit_proxy_state = %s\"",
339 fr_box_ipaddr(client->ipaddr),
341 client->first_packet_no_proxy_state ? "did not contain" : "contained",
342 client->first_packet_no_proxy_state ? "yes" : "no");
343
344 if (!client->first_packet_no_proxy_state) {
345 RERROR("Packet from %pV (%pV) contains Proxy-State, but no Message-Authenticator:",
346 fr_box_ipaddr(client->ipaddr),
348 RERROR("- Upgrade the client, as your network is vulnerable to the BlastRADIUS attack.");
349 RERROR("- Then set 'require_message_authenticator = yes' in the client definition");
350 }
351 }
352 }
353
354 REQUEST_VERIFY(request);
355
356 /*
357 * If we're defining a dynamic client, this packet is
358 * fake. We don't have a secret, so we mash all of the
359 * encrypted attributes to sane (i.e. non-hurtful)
360 * values.
361 */
362 if (!client->active) {
363 fr_pair_t *vp;
364
365 fr_assert(client->dynamic);
366
368
369 for (vp = fr_pair_list_head(&request->request_pairs);
370 vp != NULL;
371 vp = fr_pair_list_next(&request->request_pairs, vp)) {
373 switch (vp->vp_type) {
374 default:
375 break;
376
377 case FR_TYPE_UINT32:
378 vp->vp_uint32 = 0;
379 break;
380
382 vp->vp_ipv4addr = INADDR_ANY;
383 break;
384
385 case FR_TYPE_OCTETS:
386 fr_pair_value_memdup(vp, (uint8_t const *) "", 1, true);
387 break;
388
389 case FR_TYPE_STRING:
390 fr_pair_value_strdup(vp, "", true);
391 break;
392 }
393 }
394 }
395 }
396
397 /*
398 * Set the sequence to be at least one. This will
399 * prioritize replies to Access-Challenges over other
400 * packets. The sequence will be updated (if necessary)
401 * by the RADIUS state machine. If the request yields,
402 * it will get re-inserted with an updated sequence
403 * number.
404 */
405 if ((request->packet->code == FR_RADIUS_CODE_ACCESS_REQUEST) &&
406 fr_pair_find_by_da(&request->request_pairs, NULL, attr_state)) {
407 request->async->sequence = 1;
408 }
409
410 if (fr_packet_pairs_from_packet(request->request_ctx, &request->request_pairs, request->packet) < 0) {
411 RPEDEBUG("Failed decoding 'Net.*' packet");
412 return -1;
413 }
414
415 return 0;
416}
417
418static ssize_t mod_encode(UNUSED void const *instance, request_t *request, uint8_t *buffer, size_t buffer_len)
419{
420 fr_io_track_t *track = talloc_get_type_abort(request->async->packet_ctx, fr_io_track_t);
421 fr_io_address_t const *address = track->address;
422 ssize_t data_len;
423 fr_client_t const *client;
424 fr_radius_ctx_t common_ctx = {};
426
427 /*
428 * Process layer NAK, or "Do not respond".
429 */
430 if ((buffer_len == 1) ||
431 (request->reply->code == FR_RADIUS_CODE_DO_NOT_RESPOND) ||
432 (request->reply->code == 0) || (request->reply->code >= FR_RADIUS_CODE_MAX)) {
433 track->do_not_respond = true;
434 return 1;
435 }
436
437 client = address->radclient;
438 fr_assert(client);
439
440 /*
441 * Dynamic client stuff
442 */
443 if (client->dynamic && !client->active) {
444 fr_client_t *new_client;
445
446 fr_assert(buffer_len >= sizeof(client));
447
448 /*
449 * We don't accept the new client, so don't do
450 * anything.
451 */
452 if (request->reply->code != FR_RADIUS_CODE_ACCESS_ACCEPT) {
453 *buffer = true;
454 return 1;
455 }
456
457 /*
458 * Allocate the client. If that fails, send back a NAK.
459 *
460 * @todo - deal with NUMA zones? Or just deal with this
461 * client being in different memory.
462 *
463 * Maybe we should create a CONF_SECTION from the client,
464 * and pass *that* back to mod_write(), which can then
465 * parse it to create the actual client....
466 */
467 new_client = client_afrom_request(NULL, request);
468 if (!new_client) {
469 PERROR("Failed creating new client");
470 *buffer = true;
471 return 1;
472 }
473
474 memcpy(buffer, &new_client, sizeof(new_client));
475 return sizeof(new_client);
476 }
477
478 /*
479 * Overwrite the src ip address on the outbound packet
480 * with the one specified by the client. This is useful
481 * to work around broken DSR implementations and other
482 * routing issues.
483 */
484 if (client->src_ipaddr.af != AF_UNSPEC) {
485 request->reply->socket.inet.src_ipaddr = client->src_ipaddr;
486 }
487
488 common_ctx = (fr_radius_ctx_t) {
489 .secret = client->secret,
490 .secret_length = talloc_array_length(client->secret) - 1,
491 };
493 .common = &common_ctx,
494 .request_authenticator = request->packet->data + 4,
495 .rand_ctx = (fr_fast_rand_t) {
496 .a = fr_rand(),
497 .b = fr_rand(),
498 },
499 .request_code = request->packet->data[0],
500 .code = request->reply->code,
501 .id = request->reply->id,
502 };
503
504 data_len = fr_radius_encode(&FR_DBUFF_TMP(buffer, buffer_len), &request->reply_pairs, &encode_ctx);
505 if (data_len < 0) {
506 RPEDEBUG("Failed encoding RADIUS reply");
507 return -1;
508 }
509
510 if (fr_radius_sign(buffer, request->packet->data + 4,
511 (uint8_t const *) client->secret, talloc_array_length(client->secret) - 1) < 0) {
512 RPEDEBUG("Failed signing RADIUS reply");
513 return -1;
514 }
515
516 fr_packet_net_from_pairs(request->reply, &request->reply_pairs);
517
518 if (RDEBUG_ENABLED) {
519 RDEBUG("Sending %s ID %i from %pV:%i to %pV:%i length %zu via socket %s",
520 fr_radius_packet_name[request->reply->code],
521 request->reply->id,
522 fr_box_ipaddr(request->reply->socket.inet.src_ipaddr),
523 request->reply->socket.inet.src_port,
524 fr_box_ipaddr(request->reply->socket.inet.dst_ipaddr),
525 request->reply->socket.inet.dst_port,
526 data_len,
527 request->async->listen->name);
528
529 log_request_pair_list(L_DBG_LVL_1, request, NULL, &request->reply_pairs, NULL);
530 }
531
532 return data_len;
533}
534
535static int mod_priority_set(void const *instance, uint8_t const *buffer, UNUSED size_t buflen)
536{
538
539 fr_assert(buffer[0] > 0);
541
542 /*
543 * Disallowed packet
544 */
545 if (!inst->priorities[buffer[0]]) return 0;
546
547 if (!inst->allowed[buffer[0]]) return -1;
548
549 /*
550 * @todo - if we cared, we could also return -1 for "this
551 * is a bad packet". But that's really only for
552 * mod_inject, as we assume that app_io->read() always
553 * returns good packets.
554 */
555
556 /*
557 * Return the configured priority.
558 */
559 return inst->priorities[buffer[0]];
560}
561
562/** Open listen sockets/connect to external event source
563 *
564 * @param[in] instance Ctx data for this application.
565 * @param[in] sc to add our file descriptor to.
566 * @param[in] conf Listen section parsed to give us instance.
567 * @return
568 * - 0 on success.
569 * - -1 on failure.
570 */
571static int mod_open(void *instance, fr_schedule_t *sc, UNUSED CONF_SECTION *conf)
572{
573 proto_radius_t *inst = talloc_get_type_abort(instance, proto_radius_t);
574
575 /*
576 * io.app_io should already be set
577 */
578 return fr_master_io_listen(&inst->io, sc,
579 inst->max_packet_size, inst->num_messages);
580}
581
582/** Instantiate the application
583 *
584 * Instantiate I/O and type submodules.
585 *
586 * @return
587 * - 0 on success.
588 * - -1 on failure.
589 */
590static int mod_instantiate(module_inst_ctx_t const *mctx)
591{
592 proto_radius_t *inst = talloc_get_type_abort(mctx->mi->data, proto_radius_t);
593
594 /*
595 * No IO module, it's an empty listener.
596 */
597 if (!inst->io.submodule) return 0;
598
599 /*
600 * These timers are usually protocol specific.
601 */
602 FR_TIME_DELTA_BOUND_CHECK("idle_timeout", inst->io.idle_timeout, >=, fr_time_delta_from_sec(1));
603 FR_TIME_DELTA_BOUND_CHECK("idle_timeout", inst->io.idle_timeout, <=, fr_time_delta_from_sec(600));
604
605 FR_TIME_DELTA_BOUND_CHECK("nak_lifetime", inst->io.nak_lifetime, >=, fr_time_delta_from_sec(1));
606 FR_TIME_DELTA_BOUND_CHECK("nak_lifetime", inst->io.nak_lifetime, <=, fr_time_delta_from_sec(600));
607
608 FR_TIME_DELTA_BOUND_CHECK("cleanup_delay", inst->io.cleanup_delay, <=, fr_time_delta_from_sec(30));
609 FR_TIME_DELTA_BOUND_CHECK("cleanup_delay", inst->io.cleanup_delay, >, fr_time_delta_from_sec(0));
610
611#if 0
612 /*
613 * No Access-Request packets, then no cleanup delay.
614 */
615 if (!inst->allowed[FR_RADIUS_CODE_ACCESS_REQUEST]) {
616 inst->io.cleanup_delay = 0;
617 }
618#endif
619
620 /*
621 * Ensure that the server CONF_SECTION is always set.
622 */
623 inst->io.server_cs = cf_item_to_section(cf_parent(mctx->mi->conf));
624
625 /*
626 * These configuration items are not printed by default,
627 * because normal people shouldn't be touching them.
628 */
629 if (!inst->max_packet_size && inst->io.app_io) inst->max_packet_size = inst->io.app_io->default_message_size;
630
631 if (!inst->num_messages) inst->num_messages = 256;
632
633 FR_INTEGER_BOUND_CHECK("num_messages", inst->num_messages, >=, 32);
634 FR_INTEGER_BOUND_CHECK("num_messages", inst->num_messages, <=, 65535);
635
636 FR_INTEGER_BOUND_CHECK("max_packet_size", inst->max_packet_size, >=, 1024);
637 FR_INTEGER_BOUND_CHECK("max_packet_size", inst->max_packet_size, <=, 65535);
638
639 /*
640 * Tell the master handler about the main protocol instance.
641 */
642 inst->io.app = &proto_radius;
643 inst->io.app_instance = inst;
644
645 /*
646 * We will need this for dynamic clients and connected sockets.
647 */
648 inst->io.mi = mctx->mi;
649
650 /*
651 * Instantiate the transport module before calling the
652 * common instantiation function.
653 */
654 if (module_instantiate(inst->io.submodule) < 0) return -1;
655
656 /*
657 * Instantiate the master io submodule
658 */
660}
661
662/** Get the authentication vector.
663 *
664 * Note that we don't allow people to get the reply vector, because
665 * it doesn't exist until the reply is sent.
666 *
667 */
669 UNUSED xlat_ctx_t const *xctx, request_t *request,
670 UNUSED fr_value_box_list_t *in)
671{
672 fr_value_box_t *vb;
673
674 if (request->dict != dict_radius) return XLAT_ACTION_FAIL;
675
676 MEM(vb = fr_value_box_alloc(ctx, FR_TYPE_OCTETS, NULL));
677 if (fr_value_box_memdup(vb, vb, NULL, request->packet->vector, sizeof(request->packet->vector), true) < 0) {
678 talloc_free(vb);
679 return XLAT_ACTION_FAIL;
680 }
681
683
684 return XLAT_ACTION_DONE;
685}
686
687
688static int mod_load(void)
689{
690 if (fr_radius_global_init() < 0) {
691 PERROR("Failed initialising protocol library");
692 return -1;
693 }
694
695
696 if (!xlat_func_register(NULL, "radius.packet.vector", packet_vector_xlat, FR_TYPE_OCTETS)) return -1;
697
698 return 0;
699}
700
701static void mod_unload(void)
702{
703 xlat_func_unregister("radius.packet.vector");
704
706}
707
709 .common = {
710 .magic = MODULE_MAGIC_INIT,
711 .name = "radius",
713 .inst_size = sizeof(proto_radius_t),
714 .onload = mod_load,
715 .unload = mod_unload,
717 },
718 .dict = &dict_radius,
719 .open = mod_open,
720 .decode = mod_decode,
721 .encode = mod_encode,
722 .priority = mod_priority_set
723};
static int const char char buffer[256]
Definition acutest.h:576
module_t common
Common fields to all loadable modules.
Definition app_io.h:34
Public structure describing an I/O path for a protocol.
Definition app_io.h:33
module_t common
Common fields provided by all modules.
Definition application.h:72
Describes a new application (protocol)
Definition application.h:71
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
Definition build.h:167
#define unlikely(_x)
Definition build.h:381
#define UNUSED
Definition build.h:315
int cf_table_parse_int(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
Generic function for parsing conf pair values as int.
Definition cf_parse.c:1550
#define CONF_PARSER_TERMINATOR
Definition cf_parse.h:642
cf_parse_t func
Override default parsing behaviour for the specified type with a custom parsing function.
Definition cf_parse.h:596
#define FR_INTEGER_BOUND_CHECK(_name, _var, _op, _bound)
Definition cf_parse.h:502
#define FR_CONF_OFFSET(_name, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Definition cf_parse.h:268
#define FR_CONF_POINTER(_name, _type, _flags, _res_p)
conf_parser_t which parses a single CONF_PAIR producing a single global result
Definition cf_parse.h:323
#define FR_CONF_OFFSET_FLAGS(_name, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Definition cf_parse.h:256
#define FR_TIME_DELTA_BOUND_CHECK(_name, _var, _op, _bound)
Definition cf_parse.h:513
@ CONF_FLAG_NOT_EMPTY
CONF_PAIR is required to have a non zero length value.
Definition cf_parse.h:433
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
Definition cf_parse.h:412
#define FR_CONF_OFFSET_TYPE_FLAGS(_name, _type, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Definition cf_parse.h:241
Defines a CONF_PAIR to C data type mapping.
Definition cf_parse.h:579
Common header for all CONF_* types.
Definition cf_priv.h:49
Configuration AVP similar to a fr_pair_t.
Definition cf_priv.h:70
A section grouping multiple CONF_PAIR.
Definition cf_priv.h:101
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
Definition cf_util.c:684
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
Definition cf_util.c:664
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
Definition cf_util.c:1594
#define cf_log_err(_cf, _fmt,...)
Definition cf_util.h:289
#define cf_parent(_cf)
Definition cf_util.h:101
size_t channel_packet_priority_len
Definition channel.c:170
fr_table_num_sorted_t const channel_packet_priority[]
Definition channel.c:164
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
Definition dbuff.h:514
static int fr_dcursor_append(fr_dcursor_t *cursor, void *v)
Insert a single item at the end of the list.
Definition dcursor.h:406
#define MEM(x)
Definition debug.h:36
@ FR_RADIUS_CODE_ACCESS_REQUEST
RFC2865 - Access-Request.
Definition defs.h:33
@ FR_RADIUS_CODE_DISCONNECT_REQUEST
RFC3575/RFC5176 - Disconnect-Request.
Definition defs.h:46
@ FR_RADIUS_CODE_DO_NOT_RESPOND
Special rcode to indicate we will not respond.
Definition defs.h:54
@ FR_RADIUS_CODE_MAX
Maximum possible protocol code.
Definition defs.h:53
@ FR_RADIUS_CODE_STATUS_SERVER
RFC2865/RFC5997 - Status Server (request)
Definition defs.h:44
@ FR_RADIUS_CODE_COA_REQUEST
RFC3575/RFC5176 - CoA-Request.
Definition defs.h:49
@ FR_RADIUS_CODE_ACCESS_ACCEPT
RFC2865 - Access-Accept.
Definition defs.h:34
@ FR_RADIUS_CODE_ACCOUNTING_REQUEST
RFC2866 - Accounting-Request.
Definition defs.h:36
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
Definition dict.h:268
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition dict.h:281
fr_value_box_t const * value
Enum value (what name maps to).
Definition dict.h:231
fr_dict_enum_value_t * fr_dict_enum_by_name(fr_dict_attr_t const *da, char const *name, ssize_t len)
Definition dict_util.c:3395
static fr_slen_t in
Definition dict.h:824
Specifies an attribute which must be present for the module to function.
Definition dict.h:267
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition dict.h:280
Value of an enumerated attribute.
Definition dict.h:227
Test enumeration values.
Definition dict_test.h:92
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition dl_module.h:63
int af
Address family.
Definition inet.h:64
fr_socket_t socket
src/dst ip and port.
Definition base.h:336
fr_client_t const * radclient
old-style client definition
Definition base.h:338
fr_ipaddr_t ipaddr
IPv4/IPv6 address of the host.
Definition client.h:83
bool received_message_authenticator
Whether we've seen a message authenticator from this client in any previous packets.
Definition client.h:111
fr_radius_require_ma_t require_message_authenticator
Require RADIUS message authenticator for incoming packets.
Definition client.h:94
char const * secret
Secret PSK.
Definition client.h:90
bool active
for dynamic clients
Definition client.h:119
fr_ipaddr_t src_ipaddr
IPv4/IPv6 address to send responses from (family must match ipaddr).
Definition client.h:84
bool require_message_authenticator_is_set
Whether require_message_authenticator is set in the configuration.
Definition client.h:98
bool seen_first_packet
Whether we've seen a packet from this client.
Definition client.h:114
bool limit_proxy_state_is_set
Whether limit_proxy_state is set in the configuration.
Definition client.h:109
bool dynamic
Whether the client was dynamically defined.
Definition client.h:118
bool first_packet_no_proxy_state
Whether that first packet contained a Proxy-State attribute.
Definition client.h:115
char const * shortname
Client nickname.
Definition client.h:88
fr_radius_limit_proxy_state_t limit_proxy_state
Whether to allow Proxy-State in incoming packets that don't contain a message authenticator.
Definition client.h:105
Describes a host allowed to send packets to the server.
Definition client.h:80
void log_request_pair_list(fr_log_lvl_t lvl, request_t *request, fr_pair_t const *parent, fr_pair_list_t const *vps, char const *prefix)
Print a fr_pair_list_t.
Definition log.c:830
#define PERROR(_fmt,...)
Definition log.h:228
#define RWARN(fmt,...)
Definition log.h:297
#define RERROR(fmt,...)
Definition log.h:298
#define RINFO(fmt,...)
Definition log.h:296
#define RPEDEBUG(fmt,...)
Definition log.h:376
int fr_packet_pairs_from_packet(TALLOC_CTX *ctx, fr_pair_list_t *list, fr_packet_t const *packet)
Allocate a "Net." struct with src/dst host and port.
Definition packet.c:89
void fr_packet_net_from_pairs(fr_packet_t *packet, fr_pair_list_t const *list)
Convert pairs to information in a packet.
Definition packet.c:139
talloc_free(reap)
@ L_DBG_LVL_1
Highest priority debug messages (-x).
Definition log.h:70
fr_app_io_t fr_master_app_io
Definition master.c:3134
int fr_master_io_listen(fr_io_instance_t *inst, fr_schedule_t *sc, size_t default_message_size, size_t num_messages)
Definition master.c:2925
fr_io_address_t const * address
of this packet.. shared between multiple packets
Definition master.h:54
bool do_not_respond
don't respond
Definition master.h:50
@ FR_TYPE_IPV4_ADDR
32 Bit IPv4 Address.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_VOID
User data.
@ FR_TYPE_OCTETS
Raw octets.
long int ssize_t
unsigned char uint8_t
#define MODULE_INST_CTX(_mi)
Wrapper to create a module_inst_ctx_t as a compound literal.
Definition module_ctx.h:158
module_instance_t * mi
Instance of the module being instantiated.
Definition module_ctx.h:51
Temporary structure to hold arguments for instantiation calls.
Definition module_ctx.h:50
int fr_pair_value_memdup(fr_pair_t *vp, uint8_t const *src, size_t len, bool tainted)
Copy data into an "octets" data type.
Definition pair.c:2981
int fr_pair_value_strdup(fr_pair_t *vp, char const *src, bool tainted)
Copy data into an "string" data type.
Definition pair.c:2634
fr_pair_t * fr_pair_find_by_da(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find the first pair with a matching da.
Definition pair.c:693
static fr_internal_encode_ctx_t encode_ctx
static int mod_load(void)
static fr_dict_attr_t const * attr_packet_type
static ssize_t mod_encode(UNUSED void const *instance, request_t *request, uint8_t *buffer, size_t buffer_len)
static xlat_action_t packet_vector_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, UNUSED fr_value_box_list_t *in)
Get the authentication vector.
static fr_dict_attr_t const * attr_state
fr_dict_autoload_t proto_radius_dict[]
static conf_parser_t const limit_config[]
static fr_dict_attr_t const * attr_eap_message
static int type_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
fr_app_t proto_radius
static int mod_decode(void const *instance, request_t *request, uint8_t *const data, size_t data_len)
Decode the packet.
static fr_dict_t const * dict_radius
static void mod_unload(void)
static fr_dict_attr_t const * attr_proxy_state
static const conf_parser_t priority_config[]
static fr_dict_attr_t const * attr_user_name
static int transport_parse(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
static int mod_instantiate(module_inst_ctx_t const *mctx)
Instantiate the application.
static int mod_open(void *instance, fr_schedule_t *sc, UNUSED CONF_SECTION *conf)
Open listen sockets/connect to external event source.
static int mod_priority_set(void const *instance, uint8_t const *buffer, UNUSED size_t buflen)
fr_dict_attr_autoload_t proto_radius_dict_attr[]
static fr_dict_attr_t const * attr_message_authenticator
static conf_parser_t const proto_radius_config[]
How to parse a RADIUS listen section.
An instance of a proto_radius listen section.
ssize_t fr_radius_decode(TALLOC_CTX *ctx, fr_pair_list_t *out, uint8_t *packet, size_t packet_len, fr_radius_decode_ctx_t *decode_ctx)
Definition base.c:1088
size_t fr_radius_limit_proxy_state_table_len
Definition base.c:99
int fr_radius_sign(uint8_t *packet, uint8_t const *vector, uint8_t const *secret, size_t secret_len)
Sign a previously encoded packet.
Definition base.c:358
size_t fr_radius_require_ma_table_len
Definition base.c:90
int fr_radius_global_init(void)
Definition base.c:1218
void fr_radius_global_free(void)
Definition base.c:1241
fr_table_num_sorted_t const fr_radius_limit_proxy_state_table[]
Definition base.c:92
fr_table_num_sorted_t const fr_radius_require_ma_table[]
Definition base.c:83
ssize_t fr_radius_encode(fr_dbuff_t *dbuff, fr_pair_list_t *vps, fr_radius_encode_ctx_t *packet_ctx)
Definition base.c:953
char const * fr_radius_packet_name[FR_RADIUS_CODE_MAX]
Definition base.c:112
#define fr_assert(_expr)
Definition rad_assert.h:38
#define RDEBUG(fmt,...)
Definition radclient.h:53
#define RDEBUG_ENABLED()
Definition radclient.h:49
fr_radius_require_ma_t
Control whether Message-Authenticator is required in Access-Requests.
Definition radius.h:62
@ FR_RADIUS_REQUIRE_MA_YES
Require Message-Authenticator.
Definition radius.h:64
@ FR_RADIUS_REQUIRE_MA_AUTO
Only require Message-Authenticator if we've previously received a packet from this client with Messag...
Definition radius.h:65
char const * secret
Definition radius.h:95
bool limit_proxy_state
Don't allow Proxy-State in requests.
Definition radius.h:137
#define fr_radius_flag_encrypted(_da)
Definition radius.h:194
bool require_message_authenticator
Definition radius.h:136
fr_radius_ctx_t const * common
Definition radius.h:125
fr_radius_limit_proxy_state_t
Control whether Proxy-State is allowed in Access-Requests.
Definition radius.h:76
@ FR_RADIUS_LIMIT_PROXY_STATE_AUTO
Do not allow Proxy-State unless:
Definition radius.h:82
@ FR_RADIUS_LIMIT_PROXY_STATE_YES
Limit Proxy-State.
Definition radius.h:79
TALLOC_CTX * tmp_ctx
for temporary things cleaned up during decoding
Definition radius.h:129
static rs_t * conf
Definition radsniff.c:53
uint32_t fr_rand(void)
Return a 32-bit random number.
Definition rand.c:105
Smaller fast random number generator.
Definition rand.h:54
#define REQUEST_VERIFY(_x)
Definition request.h:276
#define request_set_dynamic_client(_x)
Definition request.h:163
static int instantiate(module_inst_ctx_t const *mctx)
Definition rlm_rest.c:1310
The scheduler.
Definition schedule.c:125
CONF_SECTION * conf
Module's instance configuration.
Definition module.h:329
void * data
Module's instance data.
Definition module.h:271
module_instantiate_t instantiate
Callback to allow the module to register any per-instance resources like sockets and file handles.
Definition module.h:218
conf_parser_t const * config
How to convert a CONF_SECTION to a module instance.
Definition module.h:198
module_t * exported
Public module structure.
Definition module.h:276
Module instance data.
Definition module.h:265
static const uchar sc[16]
Definition smbdes.c:115
fr_client_t * client_afrom_request(TALLOC_CTX *ctx, request_t *request)
Create a new client, consuming all attributes in the control list of the request.
Definition client.c:930
int module_instantiate(module_instance_t *instance)
Manually complete module setup by calling its instantiate function.
Definition module.c:1195
eap_aka_sim_process_conf_t * inst
fr_pair_t * vp
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
fr_dict_attr_t const *_CONST da
Dictionary attribute defines the attribute number, vendor and type of the pair.
Definition pair.h:69
#define talloc_get_type_abort_const
Definition talloc.h:282
static fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
Definition time.h:590
xlat_action_t
Definition xlat.h:37
@ XLAT_ACTION_FAIL
An xlat function failed.
Definition xlat.h:44
@ XLAT_ACTION_DONE
We're done evaluating this level of nesting.
Definition xlat.h:43
fr_pair_t * fr_pair_list_next(fr_pair_list_t const *list, fr_pair_t const *item))
Get the next item in a valuepair list after a specific entry.
Definition pair_inline.c:70
fr_pair_t * fr_pair_list_head(fr_pair_list_t const *list)
Get the head of a valuepair list.
Definition pair_inline.c:43
static fr_slen_t parent
Definition pair.h:851
static void fr_socket_addr_swap(fr_socket_t *dst, fr_socket_t const *src)
Swap src/dst information of a fr_socket_t.
Definition socket.h:121
int fr_value_box_memdup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, uint8_t const *src, size_t len, bool tainted)
Copy a buffer to a fr_value_box_t.
Definition value.c:4468
#define fr_value_box_alloc(_ctx, _type, _enumv)
Allocate a value box of a specific type.
Definition value.h:621
#define fr_box_ipaddr(_val)
Definition value.h:294
#define fr_box_strvalue_buffer(_val)
Definition value.h:289
static fr_slen_t data
Definition value.h:1265
static size_t char ** out
Definition value.h:997
int virtual_server_listen_transport_parse(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
Generic conf_parser_t func for loading drivers.
An xlat calling ctx.
Definition xlat_ctx.h:49
xlat_t * xlat_func_register(TALLOC_CTX *ctx, char const *name, xlat_func_t func, fr_type_t return_type)
Register an xlat function.
Definition xlat_func.c:218
void xlat_func_unregister(char const *name)
Unregister an xlat function.
Definition xlat_func.c:519