The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
main_config.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: 251f10bcbd4705e7d4c615361fecae39b87b4967 $
19 *
20 * @brief Handle the the main server's (radiusd) configuration.
21 * @file src/lib/server/main_config.c
22 *
23 * @copyright 2002,2006-2007 The FreeRADIUS server project
24 * @copyright 2002 Alan DeKok (aland@freeradius.org)
25 */
26
27RCSID("$Id: 251f10bcbd4705e7d4c615361fecae39b87b4967 $")
28
29#include <freeradius-devel/server/cf_file.h>
30#include <freeradius-devel/server/cf_util.h>
31#include <freeradius-devel/server/client.h>
32#include <freeradius-devel/server/dependency.h>
33#include <freeradius-devel/server/main_config.h>
34#include <freeradius-devel/server/map_proc.h>
35#include <freeradius-devel/server/modpriv.h>
36#include <freeradius-devel/server/module.h>
37#include <freeradius-devel/server/util.h>
38#include <freeradius-devel/server/virtual_servers.h>
39
40#include <freeradius-devel/unlang/xlat.h>
41
42#include <freeradius-devel/util/conf.h>
43#include <freeradius-devel/util/debug.h>
44#include <freeradius-devel/util/dict.h>
45#include <freeradius-devel/util/file.h>
46#include <freeradius-devel/util/hw.h>
47#include <freeradius-devel/util/perm.h>
48#include <freeradius-devel/util/sem.h>
49#include <freeradius-devel/util/token.h>
50#include <freeradius-devel/util/pair_legacy.h>
51
52#include <freeradius-devel/unlang/xlat_func.h>
53
54#include <sys/stat.h>
55#include <pwd.h>
56#include <grp.h>
57
58#include <unistd.h>
59#include <sys/types.h>
60
61#ifdef HAVE_SYSLOG_H
62# include <syslog.h>
63#endif
64
65#ifdef HAVE_FCNTL_H
66# include <fcntl.h>
67#endif
68
69main_config_t const *main_config; //!< Main server configuration.
70
71extern fr_log_t debug_log;
72
73fr_log_t debug_log = { .fd = -1, .dst = L_DST_NULL };
74
75/**********************************************************************
76 *
77 * We need to figure out where the logs go, before doing anything
78 * else. This is so that the log messages go to the correct
79 * place.
80 *
81 * BUT, we want the settings from the command line to over-ride
82 * the ones in the configuration file. So, these items are
83 * parsed ONLY if there is no "-l foo" on the command line.
84 *
85 **********************************************************************/
86
87static int reverse_lookups_parse(TALLOC_CTX *ctx, void *out, void *parent,CONF_ITEM *ci, conf_parser_t const *rule);
88static int hostname_lookups_parse(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule);
89
90static int num_networks_parse(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule);
91static int num_workers_parse(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule);
92static int num_workers_dflt(CONF_PAIR **out, void *parent, CONF_SECTION *cs, fr_token_t quote, conf_parser_t const *rule);
93
94static int lib_dir_on_read(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule);
95
96static int talloc_pool_size_parse(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule);
97
98static int max_request_time_parse(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule);
99
100static int name_parse(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule);
101
102/*
103 * Log destinations
104 */
106 { FR_CONF_OFFSET("destination", main_config_t, log_dest), .dflt = "file" },
107 { FR_CONF_OFFSET("syslog_facility", main_config_t, syslog_facility), .dflt = "daemon",
109 .uctx = &(cf_table_parse_ctx_t){
110 .table = syslog_facility_table,
112 }
113 },
114 { FR_CONF_OFFSET("local_state_dir", main_config_t, local_state_dir), .dflt = "${prefix}/var"},
115 { FR_CONF_OFFSET("logdir", main_config_t, log_dir), .dflt = "${local_state_dir}/log"},
116 { FR_CONF_OFFSET("file", main_config_t, log_file), .dflt = "${logdir}/radius.log" },
117 { FR_CONF_OFFSET("suppress_secrets", main_config_t, suppress_secrets), .dflt = "no" },
119};
120
121/*
122 * Basic configuration for the server.
123 */
125 { FR_CONF_POINTER("log", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) initial_log_config },
126
128};
129
130/*
131 * Basic configuration for the server.
132 */
134 { FR_CONF_OFFSET("prefix", main_config_t, prefix), .dflt = "/usr/local" },
135
138
139 { FR_CONF_OFFSET("libdir", main_config_t, lib_dir), .dflt = "${prefix}/lib",
141
143};
144
145/**********************************************************************
146 *
147 * Now that we've parsed the log destination, AND the security
148 * items, we can parse the rest of the configuration items.
149 *
150 **********************************************************************/
151static const conf_parser_t log_config[] = {
152 { FR_CONF_OFFSET("colourise", main_config_t, do_colourise) },
153 { FR_CONF_OFFSET("line_number", main_config_t, log_line_number) },
154 { FR_CONF_OFFSET("timestamp", main_config_t, log_timestamp) },
157};
158
159
160static const conf_parser_t resources[] = {
161 /*
162 * Don't set a default here. It's set in the code, below. This means that
163 * the config item will *not* get printed out in debug mode, so that no one knows
164 * it exists.
165 */
166 { FR_CONF_OFFSET_TYPE_FLAGS("talloc_pool_size", FR_TYPE_SIZE, CONF_FLAG_HIDDEN, main_config_t, talloc_pool_size), .func = talloc_pool_size_parse }, /* DO NOT SET DEFAULT */
167 { FR_CONF_OFFSET_FLAGS("talloc_memory_report", CONF_FLAG_HIDDEN, main_config_t, talloc_memory_report) }, /* DO NOT SET DEFAULT */
169};
170
171static const conf_parser_t thread_config[] = {
172 { FR_CONF_OFFSET("num_networks", main_config_t, max_networks), .dflt = STRINGIFY(1),
174 { FR_CONF_OFFSET("num_workers", main_config_t, max_workers), .dflt = STRINGIFY(0),
175 .func = num_workers_parse, .dflt_func = num_workers_dflt },
176
177 { FR_CONF_OFFSET_TYPE_FLAGS("stats_interval", FR_TYPE_TIME_DELTA, CONF_FLAG_HIDDEN, main_config_t, stats_interval) },
178
179#ifdef WITH_TLS
180 { FR_CONF_OFFSET_TYPE_FLAGS("openssl_async_pool_init", FR_TYPE_SIZE, 0, main_config_t, openssl_async_pool_init), .dflt = "64" },
181 { FR_CONF_OFFSET_TYPE_FLAGS("openssl_async_pool_max", FR_TYPE_SIZE, 0, main_config_t, openssl_async_pool_max), .dflt = "1024" },
182#endif
183
185};
186
187/*
188 * Migration configuration.
189 */
190extern bool tmpl_require_enum_prefix;
191
193 { FR_CONF_OFFSET_FLAGS("rewrite_update", CONF_FLAG_HIDDEN, main_config_t, rewrite_update) },
194 { FR_CONF_OFFSET_FLAGS("forbid_update", CONF_FLAG_HIDDEN, main_config_t, forbid_update) },
195
196 /*
197 * Do not add tmpl_require_enum_prefix here, as it is
198 * parsed too late to affect anything. It must be passed
199 * as a command-line option via
200 *
201 * -S v3_enum_names=yes
202 */
203
205};
206
207#ifndef NDEBUG
208/*
209 * Migration configuration.
210 */
212 { FR_CONF_OFFSET_FLAGS("countup_instructions", CONF_FLAG_HIDDEN, main_config_t, ins_countup) },
213 { FR_CONF_OFFSET_FLAGS("max_instructions", CONF_FLAG_HIDDEN, main_config_t, ins_max) },
215};
216#endif
217
218static const conf_parser_t server_config[] = {
219 /*
220 * FIXME: 'prefix' is the ONLY one which should be
221 * configured at compile time. Hard-coding it here is
222 * bad. It will be cleaned up once we clean up the
223 * hard-coded defines for the locations of the various
224 * files.
225 */
226 { FR_CONF_OFFSET("prefix", main_config_t, prefix), .dflt = "/usr/local" },
227 { FR_CONF_OFFSET("local_state_dir", main_config_t, local_state_dir), .dflt = "${prefix}/var"},
228 { FR_CONF_OFFSET("sbin_dir", main_config_t, sbin_dir), .dflt = "${prefix}/sbin"},
229 { FR_CONF_OFFSET("logdir", main_config_t, log_dir), .dflt = "${local_state_dir}/log"},
230 { FR_CONF_OFFSET("run_dir", main_config_t, run_dir), .dflt = "${local_state_dir}/run/${name}"},
231 { FR_CONF_OFFSET("radacctdir", main_config_t, radacct_dir), .dflt = "${logdir}/radacct" },
232 { FR_CONF_OFFSET("panic_action", main_config_t, panic_action) },
233 { FR_CONF_OFFSET("reverse_lookups", main_config_t, reverse_lookups), .dflt = "no", .func = reverse_lookups_parse },
234 { FR_CONF_OFFSET("hostname_lookups", main_config_t, hostname_lookups), .dflt = "yes", .func = hostname_lookups_parse },
235 { FR_CONF_OFFSET("max_request_time", main_config_t, max_request_time), .dflt = STRINGIFY(MAX_REQUEST_TIME), .func = max_request_time_parse },
236 { FR_CONF_OFFSET("pidfile", main_config_t, pid_file), .dflt = "${run_dir}/radiusd.pid"},
237
238 { FR_CONF_OFFSET_FLAGS("debug_level", CONF_FLAG_HIDDEN, main_config_t, debug_level), .dflt = "0" },
239 { FR_CONF_OFFSET("max_requests", main_config_t, max_requests), .dflt = "0" },
240
241 { FR_CONF_POINTER("log", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) log_config },
242
243 { FR_CONF_POINTER("resources", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) resources },
244
245 { FR_CONF_POINTER("thread", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) thread_config, .name2 = CF_IDENT_ANY },
246
247 { FR_CONF_POINTER("migrate", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) migrate_config, .name2 = CF_IDENT_ANY },
248
249#ifndef NDEBUG
250 { FR_CONF_POINTER("interpret", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) interpret_config, .name2 = CF_IDENT_ANY },
251#endif
252
254};
255
256
257/**********************************************************************
258 *
259 * The next few items are here to allow for switching of users
260 * while still opening the various output files with the correct
261 * permission.
262 *
263 * It's rare (or impossible) to have parse errors for these
264 * configuration items, so we don't worry too much about that.
265 * In contrast, when we parse the rest of the configuration, we
266 * CAN get parse errors. We want THOSE parse errors to go to the
267 * log file, and we want the log file to have the correct
268 * permissions.
269 *
270 **********************************************************************/
272#ifdef HAVE_SETUID
274 { FR_CONF_OFFSET_IS_SET("group", FR_TYPE_VOID, 0, main_config_t, gid), .func = cf_parse_gid },
275#endif
276 { FR_CONF_OFFSET("chroot", main_config_t, chroot_dir) },
277 { FR_CONF_OFFSET("allow_core_dumps", main_config_t, allow_core_dumps), .dflt = "no" },
278
279#ifdef ENABLE_OPENSSL_VERSION_CHECK
280 { FR_CONF_OFFSET("allow_vulnerable_openssl", main_config_t, allow_vulnerable_openssl), .dflt = "no" },
281#endif
282
283#ifdef WITH_TLS
284 { FR_CONF_OFFSET_IS_SET("openssl_fips_mode", FR_TYPE_BOOL, 0, main_config_t, openssl_fips_mode), .dflt = "no" },
285#endif
286
288};
289
291 { FR_CONF_POINTER("security", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) security_config },
292
293 { FR_CONF_OFFSET("name", main_config_t, name), .func = name_parse }, /* DO NOT SET DEFAULT */
294
295 { FR_CONF_OFFSET("prefix", main_config_t, prefix), .dflt = "/usr/local" },
296 { FR_CONF_OFFSET("local_state_dir", main_config_t, local_state_dir), .dflt = "${prefix}/var"},
297
298 { FR_CONF_OFFSET("run_dir", main_config_t, run_dir), .dflt = "${local_state_dir}/run/${name}"},
299
300 /*
301 * For backwards compatibility.
302 */
303#ifdef HAVE_SETUID
304 { FR_CONF_DEPRECATED("user", main_config_t, uid) },
305 { FR_CONF_DEPRECATED("group", main_config_t, gid) },
306#endif
307 { FR_CONF_DEPRECATED("chroot", main_config_t, NULL) },
308 { FR_CONF_DEPRECATED("allow_core_dumps", main_config_t, NULL) },
310};
311
312static int reverse_lookups_parse(TALLOC_CTX *ctx, void *out, void *parent,
313 CONF_ITEM *ci, conf_parser_t const *rule)
314{
315 int ret;
316
317 if ((ret = cf_pair_parse_value(ctx, out, parent, ci, rule)) < 0) return ret;
318
319 memcpy(&fr_reverse_lookups, out, sizeof(fr_reverse_lookups));
320
321 return 0;
322}
323
324static int hostname_lookups_parse(TALLOC_CTX *ctx, void *out, void *parent,
325 CONF_ITEM *ci, conf_parser_t const *rule)
326{
327 int ret;
328
329 if ((ret = cf_pair_parse_value(ctx, out, parent, ci, rule)) < 0) return ret;
330
332
333 return 0;
334}
335
336static int talloc_pool_size_parse(TALLOC_CTX *ctx, void *out, void *parent,
337 CONF_ITEM *ci, conf_parser_t const *rule)
338{
339 int ret;
340 size_t value;
341
342 if ((ret = cf_pair_parse_value(ctx, out, parent, ci, rule)) < 0) return ret;
343
344 memcpy(&value, out, sizeof(value));
345
346 FR_SIZE_BOUND_CHECK("resources.talloc_pool_size", value, >=, (size_t)(2 * 1024));
347 FR_SIZE_BOUND_CHECK("resources.talloc_pool_size", value, <=, (size_t)(1024 * 1024));
348
349 memcpy(out, &value, sizeof(value));
350
351 return 0;
352}
353
354static int max_request_time_parse(TALLOC_CTX *ctx, void *out, void *parent,
355 CONF_ITEM *ci, conf_parser_t const *rule)
356{
357 int ret;
359
360 if ((ret = cf_pair_parse_value(ctx, out, parent, ci, rule)) < 0) return ret;
361
362 memcpy(&value, out, sizeof(value));
363
364 FR_TIME_DELTA_BOUND_CHECK("max_request_time", value, >=, fr_time_delta_from_sec(5));
365 FR_TIME_DELTA_BOUND_CHECK("max_request_time", value, <=, fr_time_delta_from_sec(120));
366
367 memcpy(out, &value, sizeof(value));
368
369 return 0;
370}
371
372static int lib_dir_on_read(UNUSED TALLOC_CTX *ctx, UNUSED void *out, UNUSED void *parent,
373 CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
374{
375 CONF_PAIR *cp = cf_item_to_pair(ci);
376 char const *value;
377
378 fr_assert(main_config != NULL);
379 value = cf_pair_value(cp);
380 if (value) {
382
383 memcpy(&config, &main_config, sizeof(config)); /* const issues */
384
385 config->lib_dir = value;
386 }
387
388 /*
389 * Initialize the DL infrastructure, which is used by the
390 * config file parser. And also add in the search path.
391 */
393 cf_log_perr(ci, "Failed initializing 'lib_dir'");
394 return -1;
395 }
396
397 return 0;
398}
399
400/** Configured server name takes precedence over default values
401 *
402 */
403static int name_parse(TALLOC_CTX *ctx, void *out, void *parent,
404 CONF_ITEM *ci, conf_parser_t const *rule)
405{
407
408 if (*((char **)out)) {
409 if (config->overwrite_config_name) return 0; /* Don't change */
410
411 talloc_free(*((char **)out)); /* Free existing buffer */
412 }
413
414 return cf_pair_parse_value(ctx, out, parent, ci, rule); /* Set new value */
415}
416
417static int num_networks_parse(TALLOC_CTX *ctx, void *out, void *parent,
418 CONF_ITEM *ci, conf_parser_t const *rule)
419{
420 int ret;
422
423 if ((ret = cf_pair_parse_value(ctx, out, parent, ci, rule)) < 0) return ret;
424
425 memcpy(&value, out, sizeof(value));
426
427 FR_INTEGER_BOUND_CHECK("thread.num_networks", value, ==, 1);
428
429 memcpy(out, &value, sizeof(value));
430
431 return 0;
432}
433
434static inline CC_HINT(always_inline)
436{
438
440 if (value == 0) {
441 cf_log_pwarn(parent, "Failed retrieving core count, defaulting to 1 worker");
442 value = 1;
443 }
444
445 /*
446 * If we've got more than four times
447 * the number of cores as we have
448 * networks, then set the number of
449 * workers to the number of cores
450 * minus networks.
451 *
452 * This ensures at a least a 4:1
453 * ratio of workers to networks,
454 * which seems like a sensible ratio.
455 */
456 else if (value > (conf->max_networks * 4)) {
457 value -= conf->max_networks;
458 }
459
460 return value;
461}
462
463static int num_workers_parse(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
464{
465 int ret;
468
469 if ((ret = cf_pair_parse_value(ctx, out, parent, ci, rule)) < 0) return ret;
470
471 memcpy(&value, out, sizeof(value));
472
473 if (value == 0) value = num_workers_auto(conf, ci);
474
475 /*
476 * If no value is specified, try and
477 * discover it automatically.
478 */
479 FR_INTEGER_BOUND_CHECK("thread.num_workers", value, >=, 1);
480 FR_INTEGER_BOUND_CHECK("thread.num_workers", value, <=, 128);
481
482 memcpy(out, &value, sizeof(value));
483
484 return 0;
485}
486
487static int num_workers_dflt(CONF_PAIR **out, void *parent, CONF_SECTION *cs, fr_token_t quote, conf_parser_t const *rule)
488{
489 char *strvalue;
492
494 strvalue = talloc_asprintf(NULL, "%u", value);
495 *out = cf_pair_alloc(cs, rule->name1, strvalue, T_OP_EQ, T_BARE_WORD, quote);
496 talloc_free(strvalue);
497
498 /*
499 * Otherwise just create as many
500 * workers as we have cores.
501 */
502 cf_log_info(cs, "Dynamically determined thread.workers = %u", value);
503
504 return 0;
505}
506
507static int xlat_config_escape(UNUSED request_t *request, fr_value_box_t *vb, UNUSED void *uctx)
508{
509 static char const disallowed[] = "%{}\\'\"`";
510 size_t outmax = vb->vb_length * 3;
511 size_t outlen = 0;
512 char escaped[outmax + 1];
513 char const *in, *end;
514 char *out = escaped;
515
516 fr_assert(vb->type == FR_TYPE_STRING);
517 in = vb->vb_strvalue;
518 end = in + vb->vb_length;
519
520 do {
521 /*
522 * Non-printable characters get replaced with their
523 * mime-encoded equivalents.
524 */
525 if ((in[0] < 32)) {
526 snprintf(out, outlen, "=%02X", (unsigned char) in[0]);
527 out += 3;
528 outlen += 3;
529 continue;
530 }
531 if (strchr(disallowed, *in) != NULL) {
532 out[0] = '\\';
533 out[1] = *in;
534 out += 2;
535 outlen += 2;
536 continue;
537 }
538 /*
539 * Allowed character.
540 */
541 *out = *in;
542 out++;
543 outlen++;
544 } while (++in < end);
545 *out = '\0';
546
547 /*
548 * If the output length is greater than the input length
549 * something has been escaped - replace the original string
550 */
551 if (outlen > vb->vb_length) {
552 char *outbuff;
553 if (fr_value_box_bstr_realloc(vb, &outbuff, vb, outlen) < 0) return -1;
554 memcpy(outbuff, escaped, outlen);
555 }
556
557 return 0;
558
559}
560
562 { .required = true, .concat = true, .type = FR_TYPE_STRING, .always_escape = true, .func = xlat_config_escape },
564};
565
566/** xlat to get config values
567 *
568@verbatim
569%config(section.subsection.attribute)
570@endverbatim
571 *
572 * @ingroup xlat_functions
573 */
574static xlat_action_t xlat_config(TALLOC_CTX *ctx, fr_dcursor_t *out,
575 UNUSED xlat_ctx_t const *xctx,
576 request_t *request, fr_value_box_list_t *in)
577{
578 char const *value;
579 CONF_PAIR *cp;
580 CONF_ITEM *ci;
581 fr_value_box_t *in_head = fr_value_box_list_head(in);
582 fr_value_box_t *vb;
583
584 ci = cf_reference_item(main_config->root_cs, main_config->root_cs, in_head->vb_strvalue);
585 if (!ci || !cf_item_is_pair(ci)) {
586 REDEBUG("Config item \"%pV\" does not exist", in_head);
587 return XLAT_ACTION_FAIL;
588 }
589
590 cp = cf_item_to_pair(ci);
591
592 value = cf_pair_value(cp);
593 if (!value) return XLAT_ACTION_DONE;
594
595 MEM(vb = fr_value_box_alloc_null(ctx));
596 fr_value_box_bstrndup(vb, vb, NULL, value, strlen(value), false);
598
599 return XLAT_ACTION_DONE;
600}
601
602#ifdef HAVE_SETUID
603static int mkdir_chown(int fd, char const *path, void *uctx)
604{
605 main_config_t *config = uctx;
606 int ret = 0;
607
608 if ((config->server_uid != (uid_t)-1) || (config->server_gid != (gid_t)-1)) {
609 rad_suid_up();
610 ret = fchown(fd, config->server_uid, config->server_gid);
611 if (ret < 0) fr_strerror_printf("Failed changing ownership on directory \"%s\": %s",
612 path, fr_syserror(errno));
614 }
615
616 return ret;
617}
618/*
619 * Do chroot, if requested.
620 *
621 * Switch UID and GID to what is specified in the config file
622 */
623static int switch_users(main_config_t *config, CONF_SECTION *cs)
624{
625 bool do_suid = false;
626 bool do_sgid = false;
627
628 /*
629 * Get the current maximum for core files. Do this
630 * before anything else so as to ensure it's properly
631 * initialized.
632 */
633 if (fr_set_dumpable_init() < 0) {
634 fr_perror("%s", config->name);
635 return -1;
636 }
637
639 fprintf(stderr, "%s: Error: Failed pushing parse rules for user/group information.\n",
640 config->name);
641 return -1;
642 }
643
644 DEBUG("Parsing security rules to bootstrap UID / GID / chroot / etc.");
645 if (cf_section_parse(config, config, cs) < 0) {
646 fprintf(stderr, "%s: Error: Failed to parse user/group information.\n",
647 config->name);
648 return -1;
649 }
650
651 /*
652 * Don't do chroot/setuid/setgid if we're in debugging
653 * as non-root.
654 */
655 if (DEBUG_ENABLED && (getuid() != 0)) {
656 WARN("Ignoring configured UID / GID / chroot as we're running in debug mode");
657 return 0;
658 }
659#ifdef HAVE_GRP_H
660 /*
661 * Get the correct GID for the server.
662 */
663 config->server_gid = getgid();
664 if (config->gid_is_set && (config->server_gid != config->gid)) {
665 config->server_gid = config->gid;
666 do_sgid = true;
667 }
668#endif
669
670 /*
671 * Get the correct UID for the server.
672 */
673 config->server_uid = getuid();
674 if (config->uid_is_set && (config->server_uid != config->uid)) {
675 /*
676 * We're not the correct user. Go set that.
677 */
678 config->server_uid = config->uid;
679 do_suid = true;
680
681#ifdef HAVE_INITGROUPS
682 {
683 struct passwd *user;
684
685 if (fr_perm_getpwuid(config, &user, config->uid) < 0) {
686 fprintf(stderr, "%s: Failed resolving UID %i: %s\n",
687 config->name, (int)config->uid, fr_syserror(errno));
688 return -1;
689 }
690
691 if (initgroups(user->pw_name, config->server_gid) < 0) {
692 fprintf(stderr, "%s: Cannot initialize supplementary group list "
693 "for user %s: %s\n",
694 config->name, user->pw_name, fr_syserror(errno));
695 talloc_free(user);
696 return -1;
697 }
698
699 talloc_free(user);
700 }
701#endif
702 }
703
704 /*
705 * Set the user/group we're going to use
706 * to check read permissions on configuration files.
707 */
708 cf_file_check_user(config->server_uid ? config->server_uid : (uid_t)-1,
709 config->server_gid ? config->server_gid : (gid_t)-1);
710
711 /*
712 * Do chroot BEFORE changing UIDs.
713 */
714 if (config->chroot_dir) {
715 if (chroot(config->chroot_dir) < 0) {
716 fprintf(stderr, "%s: Failed to perform chroot %s: %s",
717 config->name, config->chroot_dir, fr_syserror(errno));
718 return -1;
719 }
720
721 /*
722 * Note that we leave chdir alone. It may be
723 * OUTSIDE of the root. This allows us to read
724 * the configuration from "-d ./etc/raddb", with
725 * the chroot as "./chroot/" for example. After
726 * the server has been loaded, it does a "cd
727 * ${logdir}" below, so that core files (if any)
728 * go to a logging directory.
729 *
730 * This also allows the configuration of the
731 * server to be outside of the chroot. If the
732 * server is statically linked, then the only
733 * things needed inside of the chroot are the
734 * logging directories.
735 */
736 }
737
738#ifdef HAVE_GRP_H
739 /*
740 * Set the GID. Don't bother checking it.
741 */
742 if (do_sgid) {
743 if (setgid(config->server_gid) < 0) {
744 struct group *group;
745
746 if (fr_perm_getgrgid(config, &group, config->gid) < 0) {
747 fprintf(stderr, "%s: Failed resolving GID %i: %s\n",
748 config->name, (int)config->gid, fr_syserror(errno));
749 return -1;
750 }
751
752 fprintf(stderr, "%s: Failed setting group to %s: %s",
753 config->name, group->gr_name, fr_syserror(errno));
754 return -1;
755 }
756 }
757#endif
758
759 /*
760 * The directories for PID files and logs must exist. We
761 * need to create them if we're told to write files to
762 * those directories.
763 *
764 * Because this creation is new in 3.0.9, it's a soft
765 * fail.
766 *
767 */
768 if (config->write_pid) {
769 /*
770 * Control sockets may be accessible by users
771 * other than the freeradius user, so we need
772 * to allow 'other' to traverse the run
773 * directory.
774 *
775 * The freeradius user should be the only one
776 * allowed to write to this directory however.
777 */
778 if (fr_mkdir(NULL, config->run_dir, -1, 0755, mkdir_chown, config) < 0) {
779 WARN("Failed creating run_dir %s: %s", config->run_dir, fr_syserror(errno));
780 }
781 }
782
783 if ((default_log.dst == L_DST_FILES) && config->log_dir) {
784 /*
785 * Every other Linux daemon allows 'other'
786 * to traverse the log directory. That doesn't
787 * mean the actual files should be world
788 * readable.
789 */
790 if (fr_mkdir(NULL, config->log_dir, -1, 0755, mkdir_chown, config) < 0) {
791 WARN("Failed creating log_dir %s: %s", config->log_dir, fr_syserror(errno));
792 }
793 }
794
795 /*
796 * If we don't already have a log file open, open one
797 * now. We may not have been logging anything yet. The
798 * server normally starts up fairly quietly.
799 */
800 if ((default_log.dst == L_DST_FILES) &&
801 (default_log.fd < 0)) {
802 default_log.fd = open(config->log_file,
803 O_WRONLY | O_APPEND | O_CREAT, 0640);
804 if (default_log.fd < 0) {
805 fprintf(stderr, "%s: Failed to open log file %s: %s\n",
806 config->name, config->log_file, fr_syserror(errno));
807 return -1;
808 }
809 }
810
811 /*
812 * If we need to change UID, ensure that the log files
813 * have the correct owner && group.
814 *
815 * We have to do this because some log files MAY already
816 * have been written as root. We need to change them to
817 * have the correct ownership before proceeding.
818 */
819 if ((do_suid || do_sgid) &&
821 if (fchown(default_log.fd, config->server_uid, config->server_gid) < 0) {
822 fprintf(stderr, "%s: Cannot change ownership of log file %s: %s\n",
823 config->name, config->log_file, fr_syserror(errno));
824 return -1;
825 }
826 }
827
828 /*
829 * Once we're done with all of the privileged work,
830 * permanently change the UID.
831 */
832 if (do_suid) {
833 rad_suid_set_down_uid(config->server_uid);
835 }
836
837 return 0;
838}
839#endif /* HAVE_SETUID */
840
841
842/** Set the server name
843 *
844 * @note Will only add pair if one does not already exist
845 *
846 * @param[in] config to alter.
847 * @param[in] name to set e.g. "radiusd".
848 * @param[in] overwrite_config replace any CONF_PAIRs with this value.
849 */
850void main_config_name_set_default(main_config_t *config, char const *name, bool overwrite_config)
851{
852 if (config->name) {
853 char *p;
854
855 memcpy(&p, &config->name, sizeof(p));
856 talloc_free(p);
857 config->name = NULL;
858 }
860
861 config->overwrite_config_name = overwrite_config;
862}
863
864/** Set the global radius config directory.
865 *
866 * @param[in] config to alter.
867 * @param[in] name to set as dir root e.g. /usr/local/etc/raddb.
868 */
870{
871 if (config->raddb_dir) {
872 talloc_const_free(config->raddb_dir);
873 config->raddb_dir = NULL;
874 }
875 if (name) config->raddb_dir = talloc_typed_strdup(config, name);
876}
877
878/** Clean up the semaphore when the main config is freed
879 *
880 * This helps with permissions issues if the user is switching between
881 * running the process under something like systemd and running it under
882 * debug mode.
883 */
885#ifndef HAVE_SEMAPHORES
886 UNUSED
887#endif
888 main_config_t const *config)
889{
890#ifdef HAVE_SEMAPHORES
891 if (config->multi_proc_sem_id >= 0) fr_sem_close(config->multi_proc_sem_id, NULL);
892#endif
893}
894
895/** Increment the semaphore in the child process so that it's not released when the parent exits
896 *
897 * @param[in] config specifying the path to the main config file.
898 * @return
899 * - 0 on success.
900 * - -1 on failure.
901 */
903#ifndef HAVE_SEMAPHORES
904 UNUSED
905#endif
906 main_config_t const *config)
907{
908#ifdef HAVE_SEMAPHORES
909 return fr_sem_take(config->multi_proc_sem_id, config->multi_proc_sem_path, true);
910#else
911 return 0;
912#endif
913}
914
915/** Check to see if we're the only process using this configuration file (or PID file if specified)
916 *
917 * @param[in] config specifying the path to the main config file.
918 * @return
919 * - 1 if another process is running with this config file
920 * - 0 if no other process is running with this config file.
921 * - -1 on error.
922 */
924{
925 char *path;
926
927#ifdef HAVE_SEMAPHORES
928 int sem_id;
929#endif
930
931 int ret = 0;
932 FILE *fp = NULL;
933 static bool sem_initd;
934
935 if (unlikely(sem_initd)) return 0;
936
937 if (config->write_pid) {
938 fr_assert(config->pid_file);
939 fp = fopen(config->pid_file, "w");
940 if (!fp) {
941 fr_strerror_printf("Refusing to start - Failed creating PID file at \"%s\" - %s",
942 config->pid_file, fr_syserror(errno));
943 return -1;
944 }
945 MEM(path = talloc_typed_strdup(config, config->pid_file));
946 } else {
947 MEM(path = talloc_asprintf(config, "%s/%s.conf", config->raddb_dir, config->name));
948 }
949
950#ifdef HAVE_SEMAPHORES
951 sem_id = fr_sem_get(path, 0,
952 main_config->uid_is_set ? main_config->uid : geteuid(),
953 main_config->gid_is_set ? main_config->gid : getegid(),
954 true, false);
955 if (sem_id < 0) {
956 talloc_free(path);
957 ret = -1;
958 goto done;
959 }
960
961 config->multi_proc_sem_id = -1;
962
963 ret = fr_sem_wait(sem_id, path, true, true);
964 switch (ret) {
965 case 0: /* we have the semaphore */
966 talloc_free(config->multi_proc_sem_path); /* Allow this to be called multiple times */
967 config->multi_proc_sem_id = sem_id;
968 config->multi_proc_sem_path = path;
969 sem_initd = true;
970 break;
971
972 case 1: /* another process has the semaphore */
973 {
974 pid_t pid;
975
976 fr_sem_pid(&pid, sem_id);
977 fr_strerror_printf("Refusing to start - PID %u already running with \"%s\"", pid, path);
978 talloc_free(path);
979 }
980 break;
981
982 default:
983 talloc_free(path);
984 break;
985 }
986done:
987#endif
988 if (fp != NULL) fclose(fp);
989
990 return ret;
991}
992
993/** Set the global dictionary directory.
994 *
995 * @param[in] config to alter.
996 * @param[in] name to set as dict dir root e.g. /usr/local/share/freeradius.
997 */
999{
1000 if (config->dict_dir) {
1001 talloc_const_free(config->dict_dir);
1002 config->dict_dir = NULL;
1003 }
1004 if (name) config->dict_dir = talloc_typed_strdup(config, name);
1005}
1006
1007/** Allocate a main_config_t struct, setting defaults
1008 *
1009 */
1011{
1013
1014 config = talloc_zero(ctx, main_config_t);
1015 if (!config) {
1016 fr_strerror_const("Failed allocating main config");
1017 return NULL;
1018 }
1019
1020 /*
1021 * Set the defaults from compile time arguments
1022 * these can be overridden later on the command line.
1023 */
1026
1028
1029 return config;
1030}
1031
1032static int _dlhandle_free(void **dl_handle)
1033{
1034 dlclose(*dl_handle);
1035 return 0;
1036}
1037
1038/*
1039 * Read config files.
1040 *
1041 * This function can ONLY be called from the main server process.
1042 */
1044{
1045 char const *p = NULL;
1046 CONF_SECTION *cs = NULL, *subcs;
1047 struct stat statbuf;
1048 bool can_colourise = false;
1049 char buffer[1024];
1050 xlat_t *xlat;
1051
1052 /*
1053 * Initialize the xlats before we load the configuration files,
1054 * so that we can later call xlat_func_register().
1055 */
1057
1058 if (stat(config->raddb_dir, &statbuf) < 0) {
1059 ERROR("Error checking raddb_dir \"%s\": %s", config->raddb_dir, fr_syserror(errno));
1060 return -1;
1061 }
1062
1063#ifdef S_IWOTH
1064 if ((statbuf.st_mode & S_IWOTH) != 0) {
1065 ERROR("Configuration directory %s is globally writable. "
1066 "Refusing to start due to insecure configuration", config->raddb_dir);
1067 return -1;
1068 }
1069#endif
1070
1071#if 0 && defined(S_IROTH)
1072 if (statbuf.st_mode & S_IROTH != 0) {
1073 ERROR("Configuration directory %s is globally readable. "
1074 "Refusing to start due to insecure configuration", config->raddb_dir);
1075 return -1;
1076 }
1077#endif
1078 INFO("Starting - reading configuration files ...");
1079
1080 /*
1081 * About sizeof(request_t) + sizeof(fr_packet_t) * 2 + sizeof(fr_pair_t) * 400
1082 *
1083 * Which should be enough for many configurations.
1084 */
1085 config->talloc_pool_size = 8 * 1024; /* default */
1086
1087 cs = cf_section_alloc(NULL, NULL, "main", NULL);
1088 if (!cs) return -1;
1089
1090 /*
1091 * Add a 'feature' subsection off the main config
1092 * We check if it's defined first, as the user may
1093 * have defined their own feature flags, or want
1094 * to manually override the ones set by modules
1095 * or the server.
1096 */
1097 subcs = cf_section_find(cs, "feature", NULL);
1098 if (!subcs) {
1099 subcs = cf_section_alloc(cs, cs, "feature", NULL);
1100 if (!subcs) {
1101 failure:
1102 fr_dict_free(&config->dict, __FILE__);
1103 talloc_free(cs);
1104 return -1;
1105 }
1106 }
1108
1110 PERROR("Failed reading internal dictionaries");
1111 goto failure;
1112 }
1113
1114 /*
1115 * Special-case things. If the output is a TTY, AND
1116 * we're debugging, colourise things. This flag also
1117 * removes the "Debug : " prefix from the log messages.
1118 */
1119 p = getenv("TERM");
1120 if (p && isatty(default_log.fd) && strstr(p, "xterm") && fr_debug_lvl) {
1121 can_colourise = default_log.colourise = true;
1122 } else {
1123 can_colourise = default_log.colourise = false;
1124 }
1125 default_log.line_number = config->log_line_number;
1126
1127 /*
1128 * Add a 'version' subsection off the main config
1129 * We check if it's defined first, this is for
1130 * backwards compatibility.
1131 */
1132 subcs = cf_section_find(cs, "version", NULL);
1133 if (!subcs) {
1134 subcs = cf_section_alloc(cs, cs, "version", NULL);
1135 if (!subcs) goto failure;
1136 }
1138
1139 /*
1140 * @todo - not quite done yet... these dictionaries have
1141 * to be loaded from raddb_dir. But the
1142 * fr_dict_autoload_t has a base_dir pointer
1143 * there... it's probably best to pass raddb_dir into
1144 * fr_dict_autoload() and have it use that instead.
1145 *
1146 * Once that's done, the proto_foo dictionaries SHOULD be
1147 * autoloaded, AND loaded before the configuration files
1148 * are read.
1149 *
1150 * And then all of the modules have to be updated to use
1151 * their local dict pointer, instead of NULL.
1152 */
1153 if (cf_section_rules_push(cs, lib_dir_on_read_config) < 0) goto failure;
1154 if (cf_section_rules_push(cs, virtual_servers_on_read_config) < 0) goto failure;
1155
1156 /*
1157 * Track the status of the configuration.
1158 */
1160
1161 /* Read the configuration file */
1162 snprintf(buffer, sizeof(buffer), "%.200s/%.50s.conf", config->raddb_dir, config->name);
1163 if (cf_file_read(cs, buffer) < 0) {
1164 ERROR("Error reading or parsing %s", buffer);
1165 goto failure;
1166 }
1167
1168 /*
1169 * Do any fixups here that might be used in references
1170 */
1171 if (config->name) {
1172 CONF_PAIR *cp;
1173
1174 cp = cf_pair_find(cs, "name");
1175 if (cp){
1176 if (config->overwrite_config_name && (cf_pair_replace(cs, cp, config->name) < 0)) {
1177 ERROR("Failed adding/replacing \"name\" config item");
1178 goto failure;
1179 }
1180 } else {
1182 }
1183 }
1184
1185 if (cf_section_pass2(cs) < 0) goto failure;
1186
1187 /*
1188 * Parse environment variables first.
1189 */
1190 subcs = cf_section_find(cs, "ENV", NULL);
1191 if (subcs) {
1192 char const *attr, *value;
1193 CONF_PAIR *cp;
1194 CONF_ITEM *ci;
1195
1196 for (ci = cf_item_next(subcs, NULL);
1197 ci != NULL;
1198 ci = cf_item_next(subcs, ci)) {
1199 if (cf_item_is_data(ci)) continue;
1200
1201 if (!cf_item_is_pair(ci)) {
1202 cf_log_err(ci, "Unexpected item in ENV section");
1203 goto failure;
1204 }
1205
1206 cp = cf_item_to_pair(ci);
1207 if (cf_pair_operator(cp) != T_OP_EQ) {
1208 cf_log_err(ci, "Invalid operator for item in ENV section");
1209 goto failure;
1210 }
1211
1212 attr = cf_pair_attr(cp);
1213 value = cf_pair_value(cp);
1214 if (!value) {
1215 if (unsetenv(attr) < 0) {
1216 cf_log_err(ci, "Failed deleting environment variable %s: %s",
1217 attr, fr_syserror(errno));
1218 goto failure;
1219 }
1220 } else {
1221 void *handle;
1222 void **handle_p;
1223
1224 if (setenv(attr, value, 1) < 0) {
1225 cf_log_err(ci, "Failed setting environment variable %s: %s",
1226 attr, fr_syserror(errno));
1227 goto failure;
1228 }
1229
1230 /*
1231 * Hacks for LD_PRELOAD.
1232 */
1233 if (strcmp(attr, "LD_PRELOAD") != 0) continue;
1234
1235 handle = dlopen(value, RTLD_NOW | RTLD_GLOBAL);
1236 if (!handle) {
1237 cf_log_err(ci, "Failed loading library %s: %s", value, dlerror());
1238 goto failure;
1239 }
1240
1241 /*
1242 * Wrap the pointer, so we can set a destructor.
1243 */
1244 MEM(handle_p = talloc(NULL, void *));
1245 *handle_p = handle;
1246 talloc_set_destructor(handle_p, _dlhandle_free);
1247 (void) cf_data_add(subcs, handle_p, value, true);
1248 }
1249 } /* loop over pairs in ENV */
1250 } /* there's an ENV subsection */
1251
1252 /*
1253 * Parse log section of main config.
1254 */
1256 fprintf(stderr, "%s: Error: Failed pushing rules for log {} section.\n",
1257 config->name);
1258 goto failure;
1259 }
1260
1261 DEBUG("Parsing initial logging configuration.");
1262 if (cf_section_parse(config, config, cs) < 0) {
1263 fprintf(stderr, "%s: Error: Failed to parse log{} section.\n",
1264 config->name);
1265 goto failure;
1266 }
1267
1268 /*
1269 * If there was no log destination set on the command line,
1270 * set it now.
1271 */
1272 if (default_log.dst == L_DST_NULL) {
1273 if (!config->log_dest) {
1274 fprintf(stderr, "%s: Error: No log destination specified.\n",
1275 config->name);
1276 goto failure;
1277 }
1278
1280
1281 switch (default_log.dst) {
1282 case L_DST_NUM_DEST:
1283 fprintf(stderr, "%s: Error: Unknown log_destination %s\n",
1284 config->name, config->log_dest);
1285 goto failure;
1286
1287#ifdef HAVE_SYSLOG_H
1288 case L_DST_SYSLOG:
1289 /*
1290 * Call openlog only once, when the
1291 * program starts.
1292 */
1293 openlog(config->name, LOG_PID, config->syslog_facility);
1294 break;
1295#endif
1296
1297 case L_DST_FILES:
1298 if (!config->log_file) {
1299 fprintf(stderr, "%s: Error: Specified \"files\" as a log destination, but no log filename was given!\n",
1300 config->name);
1301 goto failure;
1302 }
1303 default_log.file = config->log_file;
1304 break;
1305
1306 default:
1307 break;
1308 }
1309 }
1310
1311 /*
1312 * Only set timestamp logging from the config file if no value was
1313 * specified on the command line.
1314 */
1315 if (config->log_timestamp_is_set && (default_log.timestamp == L_TIMESTAMP_AUTO)) {
1317 }
1318
1319#ifdef HAVE_SETUID
1320 /*
1321 * Switch users as early as possible.
1322 */
1323 if (switch_users(config, cs) < 0) goto failure;
1324#endif
1325
1326 /*
1327 * This also clears the dumpable flag if core dumps
1328 * aren't allowed.
1329 */
1330 if (fr_set_dumpable(config->allow_core_dumps) < 0) PERROR("Failed enabling core dumps");
1331 if (config->allow_core_dumps) INFO("Core dumps are enabled");
1332
1333 /*
1334 * This allows us to figure out where, relative to
1335 * radiusd.conf, the other configuration files exist.
1336 */
1337 if (cf_section_rules_push(cs, server_config) < 0) goto failure;
1338 if (cf_section_rules_push(cs, virtual_servers_config) < 0) goto failure;
1339
1340 DEBUG("Parsing main configuration");
1341 if (cf_section_parse(config, config, cs) < 0) goto failure;
1342
1343 /*
1344 * Reset the colourisation state. The configuration
1345 * files can disable colourisation if the terminal
1346 * supports it. The configuration files *cannot* enable
1347 * colourisation if the terminal window doesn't support
1348 * it.
1349 */
1350 if (can_colourise && !config->do_colourise) {
1351 default_log.colourise = false;
1352 }
1353
1354 /*
1355 * Starting the server, WITHOUT "-x" on the
1356 * command-line: use whatever is in the config
1357 * file.
1358 */
1359 if (fr_debug_lvl == 0) fr_debug_lvl = config->debug_level;
1360
1361 INFO("Switching to configured log settings");
1362
1363 /*
1364 * Free the old configuration items, and replace them
1365 * with the new ones.
1366 *
1367 * Note that where possible, we do atomic switch-overs,
1368 * to ensure that the pointers are always valid.
1369 */
1370 fr_assert(config->root_cs == NULL);
1371
1372 /*
1373 * Redirect stderr/stdout as appropriate.
1374 */
1375 if (log_global_init(&default_log, config->daemonize) < 0) {
1376 cf_log_err(cs, "Failed initializing logging");
1377 goto failure;
1378 }
1379
1380 /*
1381 * Load different logging destinations.
1382 */
1383 for (subcs = cf_section_find_next(cs, NULL, "log", CF_IDENT_ANY);
1384 subcs != NULL;
1385 subcs = cf_section_find_next(cs, subcs, "log", CF_IDENT_ANY)) {
1386 if (!cf_section_name2(subcs)) continue;
1387
1388 if (log_parse_section(subcs) < 0) {
1389 cf_log_err(subcs, "Failed parsing log section: %s", fr_strerror());
1390 goto failure;
1391 }
1392 }
1393
1394 DEBUG2("%s: #### Loading Clients ####", config->name);
1395 if (!client_list_parse_section(cs, 0, false)) goto failure;
1396
1397 /*
1398 * Register the %config(section.subsection) xlat function.
1399 */
1400 if (unlikely((xlat = xlat_func_register(NULL, "config", xlat_config, FR_TYPE_STRING)) == NULL)) goto failure;
1403
1404 /*
1405 * Ensure cwd is inside the chroot.
1406 */
1407 if (config->chroot_dir) {
1408 if (chdir(config->log_dir) < 0) {
1409 ERROR("Failed to 'chdir %s' after chroot: %s", config->log_dir, fr_syserror(errno));
1410 goto failure;
1411 }
1412 }
1413
1414 config->root_cs = cs; /* Do this last to avoid dangling pointers on error */
1415
1416 /* Clear any unprocessed configuration errors */
1418
1419 return 0;
1420}
1421
1422/*
1423 * Free the configuration. Called only when the server is exiting.
1424 */
1426{
1427 /*
1428 * Frees request specific logging resources which is OK
1429 * because all the requests will have been stopped.
1430 */
1432
1433 /*
1434 * Clean up the configuration data
1435 * structures.
1436 */
1438
1439 /*
1440 * Frees current config and any previous configs.
1441 */
1442 TALLOC_FREE((*config)->root_cs);
1443 fr_dict_free(&(*config)->dict, __FILE__);
1444 TALLOC_FREE(*config);
1445
1446 return 0;
1447}
1448
1450{
1451 int fd, old_fd;
1452
1453 if (default_log.dst != L_DST_FILES) return;
1454
1455 fd = open(config->log_file, O_WRONLY | O_APPEND | O_CREAT, 0640);
1456 if (fd >= 0) {
1457 /*
1458 * Atomic swap. We'd like to keep the old
1459 * FD around so that callers don't
1460 * suddenly find the FD closed, and the
1461 * writes go nowhere. But that's hard to
1462 * do. So... we have the case where a
1463 * log message *might* be lost on HUP.
1464 */
1465 old_fd = default_log.fd;
1466 default_log.fd = fd;
1467 close(old_fd);
1468 }
1469}
1470
1472{
1473 fr_time_t when;
1474
1475 static fr_time_t last_hup = fr_time_wrap(0);
1476
1477 /*
1478 * Re-open the log file. If we can't, then keep logging
1479 * to the old log file.
1480 *
1481 * The "open log file" code is here rather than in log.c,
1482 * because it makes that function MUCH simpler.
1483 */
1485
1486 /*
1487 * Only check the config files every few seconds.
1488 */
1489 when = fr_time();
1490 if (fr_time_gteq(fr_time_add(last_hup, fr_time_delta_from_sec(2)), when)) {
1491 INFO("HUP - Last HUP was too recent. Ignoring");
1492 return;
1493 }
1494 last_hup = when;
1495
1496 INFO("HUP - NYI in version 4"); /* Not yet implemented in v4 */
1497}
1498
1500 { L("rewrite_update"), offsetof(main_config_t, rewrite_update) },
1501 { L("forbid_update"), offsetof(main_config_t, forbid_update) },
1502 { L("require_enum_prefix"), offsetof(main_config_t, require_enum_prefix) },
1503 { L("v3_enum_names"), offsetof(main_config_t, require_enum_prefix) },
1504};
1506
1507/*
1508 * Migration function that allows for command-line over-ride of
1509 * data structures which need to be initialized before the
1510 * configuration files are loaded.
1511 *
1512 * This should really only be temporary, until we get rid of flat vs nested.
1513 */
1515{
1516 fr_value_box_t box;
1517 size_t offset;
1518 char const *p;
1519 bool *out;
1520
1521 p = strchr(value, '=');
1522 if (!p) return -1;
1523
1525 if (offset) {
1526 out = (bool *) (((uintptr_t) main_config) + offset);
1527
1528 } else {
1529 return -1;
1530 }
1531
1532 p += 1;
1533
1534 fr_value_box_init(&box, FR_TYPE_BOOL, NULL, false);
1535 if (fr_value_box_from_str(NULL, &box, FR_TYPE_BOOL, NULL,
1536 p, strlen(p), NULL, false) < 0) {
1537 fr_perror("Invalid boolean \"%s\"", p);
1538 fr_exit(1);
1539 }
1540
1542
1543 *out = box.vb_bool;
1544
1545 return 0;
1546}
1547
1548/*
1549 * Allow other pieces of the code to examine the migration options.
1550 */
1552{
1553 size_t offset;
1554
1555 if (!main_config) return false;
1556
1557 if (strcmp(name, "use_new_conditions") == 0) return true; /* ignore this for migration */
1558
1559 offset = fr_table_value_by_substr(config_arg_table, name, strlen(name), 0);
1560 if (!offset) return false;
1561
1562 return *(bool *) (((uintptr_t) main_config) + offset);
1563}
static int const char char buffer[256]
Definition acutest.h:576
#define RCSID(id)
Definition build.h:483
#define L(_str)
Helper for initialising arrays of string literals.
Definition build.h:209
#define STRINGIFY(x)
Definition build.h:197
#define unlikely(_x)
Definition build.h:381
#define UNUSED
Definition build.h:315
#define NUM_ELEMENTS(_t)
Definition build.h:337
void cf_md5_init(void)
Definition cf_file.c:3080
int cf_file_read(CONF_SECTION *cs, char const *filename)
Definition cf_file.c:3423
int cf_section_pass2(CONF_SECTION *cs)
Definition cf_file.c:755
CONF_ITEM * cf_reference_item(CONF_SECTION const *parent_cs, CONF_SECTION const *outer_cs, char const *ptr)
Definition cf_file.c:3619
void cf_file_check_user(uid_t uid, gid_t gid)
Set the euid/egid used when performing file checks.
Definition cf_file.c:3497
int cf_section_parse(TALLOC_CTX *ctx, void *base, CONF_SECTION *cs)
Parse a configuration section into user-supplied variables.
Definition cf_parse.c:1151
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:1577
int cf_pair_parse_value(TALLOC_CTX *ctx, void *out, UNUSED void *base, CONF_ITEM *ci, conf_parser_t const *rule)
Parses a CONF_PAIR into a C data type.
Definition cf_parse.c:171
int cf_parse_gid(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
Generic function for resolving GID strings to uid_t values.
Definition cf_parse.c:1644
int cf_parse_uid(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
Generic function for resolving UID strings to uid_t values.
Definition cf_parse.c:1629
#define CONF_PARSER_TERMINATOR
Definition cf_parse.h:658
cf_parse_t func
Override default parsing behaviour for the specified type with a custom parsing function.
Definition cf_parse.h:612
#define FR_CONF_DEPRECATED(_name, _struct, _field)
conf_parser_t entry which raises an error if a matching CONF_PAIR is found
Definition cf_parse.h:414
#define FR_INTEGER_BOUND_CHECK(_name, _var, _op, _bound)
Definition cf_parse.h:518
#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:284
#define FR_SIZE_BOUND_CHECK(_name, _var, _op, _bound)
Definition cf_parse.h:508
#define cf_section_rules_push(_cs, _rule)
Definition cf_parse.h:690
#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:339
char const * name1
Name of the CONF_ITEM to parse.
Definition cf_parse.h:596
#define FR_CONF_OFFSET_IS_SET(_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:298
#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:272
cf_parse_t on_read
Function to call as the item is being read, just after it has been allocated and initialized.
Definition cf_parse.h:615
#define FR_TIME_DELTA_BOUND_CHECK(_name, _var, _op, _bound)
Definition cf_parse.h:529
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
Definition cf_parse.h:428
@ CONF_FLAG_HIDDEN
Used by scripts to omit items from the generated documentation.
Definition cf_parse.h:457
#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:595
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
bool cf_item_is_pair(CONF_ITEM const *ci)
Determine if CONF_ITEM is a CONF_PAIR.
Definition cf_util.c:632
char const * cf_section_name2(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
Definition cf_util.c:1185
CONF_ITEM * cf_section_to_item(CONF_SECTION const *cs)
Cast a CONF_SECTION to a CONF_ITEM.
Definition cf_util.c:738
CONF_PAIR * cf_pair_alloc(CONF_SECTION *parent, char const *attr, char const *value, fr_token_t op, fr_token_t lhs_quote, fr_token_t rhs_quote)
Allocate a CONF_PAIR.
Definition cf_util.c:1279
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
Definition cf_util.c:1028
CONF_PAIR * cf_pair_find(CONF_SECTION const *cs, char const *attr)
Search for a CONF_PAIR with a specific name.
Definition cf_util.c:1439
bool cf_item_is_data(CONF_ITEM const *ci)
Determine if CONF_ITEM is CONF_DATA.
Definition cf_util.c:646
fr_token_t cf_pair_operator(CONF_PAIR const *pair)
Return the operator of a pair.
Definition cf_util.c:1608
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
Definition cf_util.c:664
CONF_SECTION * cf_section_find_next(CONF_SECTION const *cs, CONF_SECTION const *prev, char const *name1, char const *name2)
Return the next matching section.
Definition cf_util.c:1049
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
Definition cf_util.c:1594
int cf_pair_replace(CONF_SECTION *cs, CONF_PAIR *cp, char const *value)
Replace pair in a given section with a new pair, of the given value.
Definition cf_util.c:1350
char const * cf_pair_attr(CONF_PAIR const *pair)
Return the attr of a CONF_PAIR.
Definition cf_util.c:1578
#define cf_log_err(_cf, _fmt,...)
Definition cf_util.h:289
#define cf_data_add(_cf, _data, _name, _free)
Definition cf_util.h:255
#define cf_log_info(_cf, _fmt,...)
Definition cf_util.h:291
#define cf_log_perr(_cf, _fmt,...)
Definition cf_util.h:296
#define cf_log_pwarn(_cf, _fmt,...)
Definition cf_util.h:297
#define cf_section_alloc(_ctx, _parent, _name1, _name2)
Definition cf_util.h:140
#define cf_item_next(_ci, _curr)
Definition cf_util.h:92
#define CF_IDENT_ANY
Definition cf_util.h:78
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
static char panic_action[512]
The command to execute when panicking.
Definition debug.c:96
int fr_set_dumpable(bool allow_core_dumps)
Enable or disable core dumps.
Definition debug.c:822
int fr_set_dumpable_init(void)
Get the current maximum for core files.
Definition debug.c:807
#define fr_exit(_x)
Exit, producing a log message in debug builds.
Definition debug.h:228
#define MEM(x)
Definition debug.h:36
void dependency_features_init(CONF_SECTION *cs)
Initialise core feature flags.
Definition dependency.c:184
void dependency_version_numbers_init(CONF_SECTION *cs)
Initialise core version flags.
Definition dependency.c:342
#define ERROR(fmt,...)
Definition dhcpclient.c:41
#define DEBUG(fmt,...)
Definition dhcpclient.c:39
int fr_dict_internal_afrom_file(fr_dict_t **out, char const *internal_name, char const *dependent)
(Re-)Initialize the special internal dictionary
int fr_dict_free(fr_dict_t **dict, char const *dependent)
Decrement the reference count on a previously loaded dictionary.
Definition dict_util.c:4028
static fr_slen_t in
Definition dict.h:823
Test enumeration values.
Definition dict_test.h:92
#define RTLD_NOW
Definition dl.c:44
dl_module_loader_t * dl_module_loader_init(char const *lib_dir)
Initialise structures needed by the dynamic linker.
Definition dl_module.c:532
ssize_t fr_mkdir(int *fd_out, char const *path, ssize_t len, mode_t mode, fr_mkdir_func_t func, void *uctx)
Create directories that are missing in the specified path.
Definition file.c:219
uint32_t fr_hw_num_cores_active(void)
Definition hw.c:122
bool fr_hostname_lookups
hostname -> IP lookups?
Definition inet.c:52
bool fr_reverse_lookups
IP -> hostname lookups?
Definition inet.c:51
static bool log_timestamp
Definition log.c:1094
fr_table_num_sorted_t const log_destination_table[]
Definition log.c:186
int log_global_init(fr_log_t *log, bool daemonize)
Initialises the server logging functionality, and the underlying libfreeradius log.
Definition log.c:1267
int log_parse_section(CONF_SECTION *cs)
Parse a named logging section.
Definition log.c:1132
size_t syslog_facility_table_len
Definition log.c:143
fr_table_num_sorted_t const syslog_facility_table[]
Syslog facility table.
Definition log.c:66
void log_global_free(void)
Definition log.c:1303
#define PERROR(_fmt,...)
Definition log.h:228
#define DEBUG_ENABLED
True if global debug level 1 messages are enabled.
Definition log.h:257
void rad_suid_up(void)
Definition util.c:896
void rad_suid_down(void)
Definition util.c:900
void rad_suid_set_down_uid(uid_t uid)
Definition util.c:892
talloc_free(reap)
int fr_debug_lvl
Definition log.c:43
fr_log_t default_log
Definition log.c:291
bool log_dates_utc
Definition log.c:289
@ L_DST_NULL
Discard log messages.
Definition log.h:83
@ L_DST_FILES
Log to a file on disk.
Definition log.h:79
@ L_DST_NUM_DEST
Definition log.h:84
@ L_DST_SYSLOG
Log to syslog.
Definition log.h:80
@ L_TIMESTAMP_ON
Always log timestamps.
Definition log.h:90
@ L_TIMESTAMP_OFF
Never log timestamps.
Definition log.h:91
@ L_TIMESTAMP_AUTO
Timestamp logging preference not specified.
Definition log.h:88
static const conf_parser_t log_config[]
static const conf_parser_t resources[]
int main_config_parse_option(char const *value)
fr_log_t debug_log
Definition main_config.c:73
static size_t config_arg_table_len
int main_config_free(main_config_t **config)
main_config_t * main_config_alloc(TALLOC_CTX *ctx)
Allocate a main_config_t struct, setting defaults.
static int xlat_config_escape(UNUSED request_t *request, fr_value_box_t *vb, UNUSED void *uctx)
void main_config_raddb_dir_set(main_config_t *config, char const *name)
Set the global radius config directory.
void main_config_exclusive_proc_done(UNUSED main_config_t const *config)
Clean up the semaphore when the main config is freed.
void main_config_hup(main_config_t *config)
bool tmpl_require_enum_prefix
static const conf_parser_t thread_config[]
int main_config_exclusive_proc(main_config_t *config)
Check to see if we're the only process using this configuration file (or PID file if specified)
static int lib_dir_on_read(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
static int num_workers_dflt(CONF_PAIR **out, void *parent, CONF_SECTION *cs, fr_token_t quote, conf_parser_t const *rule)
void main_config_name_set_default(main_config_t *config, char const *name, bool overwrite_config)
Set the server name.
static int reverse_lookups_parse(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
static const conf_parser_t switch_users_config[]
static const conf_parser_t server_config[]
static int _dlhandle_free(void **dl_handle)
void hup_logfile(main_config_t *config)
static xlat_arg_parser_t const xlat_config_args[]
static const conf_parser_t security_config[]
static uint32_t num_workers_auto(main_config_t *conf, CONF_ITEM *parent)
static const conf_parser_t initial_log_config[]
static fr_table_num_ordered_t config_arg_table[]
static int max_request_time_parse(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
static int num_networks_parse(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
static const conf_parser_t migrate_config[]
int main_config_init(main_config_t *config)
static const conf_parser_t initial_server_config[]
static int hostname_lookups_parse(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
static int name_parse(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
Configured server name takes precedence over default values.
main_config_t const * main_config
Main server configuration.
Definition main_config.c:69
static const conf_parser_t lib_dir_on_read_config[]
int main_config_exclusive_proc_child(UNUSED main_config_t const *config)
Increment the semaphore in the child process so that it's not released when the parent exits.
static const conf_parser_t interpret_config[]
static int talloc_pool_size_parse(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
static int num_workers_parse(TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
bool main_config_migrate_option_get(char const *name)
void main_config_dict_dir_set(main_config_t *config, char const *name)
Set the global dictionary directory.
#define MAX_REQUEST_TIME
Default maximum request time.
Definition main_config.h:35
char const * lib_dir
Definition main_config.h:75
bool require_enum_prefix
require "::" for enum parsing. They're always printed with this
CONF_SECTION * root_cs
Root of the server config.
Definition main_config.h:55
Main server configuration.
Definition main_config.h:51
@ FR_TYPE_TIME_DELTA
A period of time measured in nanoseconds.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_VOID
User data.
@ FR_TYPE_BOOL
A truth value.
@ FR_TYPE_SIZE
Unsigned integer capable of representing any memory address on the local system.
unsigned int uint32_t
int fr_perm_getgrgid(TALLOC_CTX *ctx, struct group **out, gid_t gid)
Resolve a gid to a group database entry.
Definition perm.c:329
int fr_perm_getpwuid(TALLOC_CTX *ctx, struct passwd **out, uid_t uid)
Resolve a uid to a passwd entry.
Definition perm.c:203
static const conf_parser_t config[]
Definition base.c:183
#define fr_assert(_expr)
Definition rad_assert.h:38
static bool done
Definition radclient.c:80
#define REDEBUG(fmt,...)
Definition radclient.h:52
#define DEBUG2(fmt,...)
Definition radclient.h:43
#define WARN(fmt,...)
Definition radclient.h:47
#define INFO(fmt,...)
Definition radict.c:54
static rs_t * conf
Definition radsniff.c:53
static char const * name
static const conf_parser_t xlat_config[]
Definition rlm_rest.c:154
int fr_sem_wait(int sem_id, char const *file, bool undo_on_exit, bool nonblock)
Wait for a semaphore to reach 0, then increment it by 1.
Definition sem.c:252
int fr_sem_close(int sem_id, char const *file)
Remove the semaphore, this helps with permissions issues.
Definition sem.c:329
int fr_sem_pid(pid_t *pid, int sem_id)
Return the PID of the process that last operated on the semaphore.
Definition sem.c:53
int fr_sem_get(char const *file, int proj_id, uid_t uid, gid_t gid, bool check_perm, bool must_exist)
Returns a semid for the semaphore associated with the file.
Definition sem.c:421
int fr_sem_take(int sem_id, char const *file, bool undo_on_exit)
Increment the semaphore by 1.
Definition sem.c:221
#define HAVE_SEMAPHORES
Definition sem.h:32
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
Definition snprintf.c:689
void client_list_free(void)
Definition client.c:89
fr_client_list_t * client_list_parse_section(CONF_SECTION *section, int proto, TLS_UNUSED bool tls_required)
Definition client.c:478
#define fr_time()
Allow us to arbitrarily manipulate time.
Definition state_test.c:8
Definition log.h:96
bool colourise
Prefix log messages with VT100 escape codes to change text colour.
Definition log.h:101
fr_log_dst_t dst
Log destination.
Definition log.h:97
bool line_number
Log src file and line number.
Definition log.h:99
int fd
File descriptor to write messages to.
Definition log.h:112
fr_log_timestamp_t timestamp
Prefix log messages with timestamps.
Definition log.h:110
char const * file
Path to log file.
Definition log.h:113
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
Definition syserror.c:243
#define fr_table_value_by_str(_table, _name, _def)
Convert a string to a value using a sorted or ordered table.
Definition table.h:653
#define fr_table_value_by_substr(_table, _name, _name_len, _def)
Convert a partial string to a value using an ordered or sorted table.
Definition table.h:693
An element in an arbitrarily ordered array of name to num mappings.
Definition table.h:57
char * talloc_typed_strdup(TALLOC_CTX *ctx, char const *p)
Call talloc_strdup, setting the type on the new chunk correctly.
Definition talloc.c:445
static int talloc_const_free(void const *ptr)
Free const'd memory.
Definition talloc.h:224
#define fr_time_gteq(_a, _b)
Definition time.h:238
static fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
Definition time.h:590
#define fr_time_wrap(_time)
Definition time.h:145
#define fr_time_add(_a, _b)
Add a time/time delta together.
Definition time.h:196
A time delta, a difference in time measured in nanoseconds.
Definition time.h:80
"server local" time.
Definition time.h:69
enum fr_token fr_token_t
@ T_BARE_WORD
Definition token.h:120
@ T_OP_EQ
Definition token.h:83
@ T_DOUBLE_QUOTED_STRING
Definition token.h:121
close(uq->fd)
bool required
Argument must be present, and non-empty.
Definition xlat.h:148
#define XLAT_ARG_PARSER_TERMINATOR
Definition xlat.h:168
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
Definition for a single argument consumend by an xlat function.
Definition xlat.h:147
#define FR_DICTIONARY_INTERNAL_DIR
Definition conf.h:8
static fr_slen_t parent
Definition pair.h:851
char const * fr_strerror(void)
Get the last library error.
Definition strerror.c:554
void fr_perror(char const *fmt,...)
Print the current error to stderr with a prefix.
Definition strerror.c:733
void fr_strerror_clear(void)
Clears all pending messages from the talloc pools.
Definition strerror.c:577
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition strerror.h:64
#define fr_strerror_const(_msg)
Definition strerror.h:223
ssize_t fr_value_box_from_str(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, char const *in, size_t inlen, fr_sbuff_unescape_rules_t const *erules, bool tainted)
Definition value.c:5361
int fr_value_box_bstr_realloc(TALLOC_CTX *ctx, char **out, fr_value_box_t *dst, size_t len)
Change the length of a buffer already allocated to a value box.
Definition value.c:4104
int fr_value_box_bstrndup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, size_t len, bool tainted)
Copy a string to to a fr_value_box_t.
Definition value.c:4148
#define fr_value_box_alloc_null(_ctx)
Allocate a value box for later use with a value assignment function.
Definition value.h:632
#define fr_value_box_init(_vb, _type, _enumv, _tainted)
Initialise a fr_value_box_t.
Definition value.h:587
static size_t char ** out
Definition value.h:997
const conf_parser_t virtual_servers_on_read_config[]
const conf_parser_t virtual_servers_config[]
An xlat calling ctx.
Definition xlat_ctx.h:49
void xlat_func_flags_set(xlat_t *x, xlat_func_flags_t flags)
Specify flags that alter the xlat's behaviour.
Definition xlat_func.c:402
int xlat_func_args_set(xlat_t *x, xlat_arg_parser_t const args[])
Register the arguments of an xlat.
Definition xlat_func.c:365
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
int xlat_func_init(void)
Definition xlat_func.c:550
@ XLAT_FUNC_FLAG_PURE
Definition xlat_func.h:38