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