27 RCSID(
"$Id: 6521203ba7d8d5e9f4676e9d6aa41f769d670704 $")
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>
40 #include <freeradius-devel/unlang/xlat.h>
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>
52 #include <freeradius-devel/unlang/xlat_func.h>
59 #include <sys/types.h>
272 #ifdef ENABLE_OPENSSL_VERSION_CHECK
401 if (*((
char **)
out)) {
402 if (
config->overwrite_config_name)
return 0;
427 static inline CC_HINT(always_inline)
449 else if (
value > (
conf->max_networks * 4)) {
487 strvalue = talloc_asprintf(NULL,
"%u",
value);
502 static char const disallowed[] =
"%{}\\'\"`";
503 size_t outmax = vb->vb_length * 3;
505 char escaped[outmax + 1];
506 char const *
in, *end;
510 in = vb->vb_strvalue;
511 end =
in + vb->vb_length;
524 if (strchr(disallowed, *
in) != NULL) {
537 }
while (++
in < end);
544 if (outlen > vb->vb_length) {
547 memcpy(outbuff, escaped, outlen);
579 REDEBUG(
"Config item \"%pV\" does not exist", in_head);
596 static int mkdir_chown(
int fd,
char const *path,
void *
uctx)
601 if ((
config->server_uid != (uid_t)-1) || (
config->server_gid != (gid_t)-1)) {
603 ret = fchown(fd,
config->server_uid,
config->server_gid);
618 bool do_suid =
false;
619 bool do_sgid =
false;
632 fprintf(stderr,
"%s: Error: Failed pushing parse rules for user/group information.\n",
637 DEBUG(
"Parsing security rules to bootstrap UID / GID / chroot / etc.");
639 fprintf(stderr,
"%s: Error: Failed to parse user/group information.\n",
649 WARN(
"Ignoring configured UID / GID / chroot as we're running in debug mode");
656 config->server_gid = getgid();
666 config->server_uid = getuid();
674 #ifdef HAVE_INITGROUPS
679 fprintf(stderr,
"%s: Failed resolving UID %i: %s\n",
684 if (initgroups(user->pw_name,
config->server_gid) < 0) {
685 fprintf(stderr,
"%s: Cannot initialize supplementary group list "
708 if (chroot(
config->chroot_dir) < 0) {
709 fprintf(stderr,
"%s: Failed to perform chroot %s: %s",
736 if (setgid(
config->server_gid) < 0) {
740 fprintf(stderr,
"%s: Failed resolving GID %i: %s\n",
745 fprintf(stderr,
"%s: Failed setting group to %s: %s",
796 O_WRONLY | O_APPEND | O_CREAT, 0640);
798 fprintf(stderr,
"%s: Failed to open log file %s: %s\n",
812 if ((do_suid || do_sgid) &&
815 fprintf(stderr,
"%s: Cannot change ownership of log file %s: %s\n",
848 memcpy(&p, &
config->name,
sizeof(p));
854 config->overwrite_config_name = overwrite_config;
883 #ifdef HAVE_SEMAPHORES
901 #ifdef HAVE_SEMAPHORES
920 #ifdef HAVE_SEMAPHORES
926 static bool sem_initd;
932 fp = fopen(
config->pid_file,
"w");
943 #ifdef HAVE_SEMAPHORES
954 config->multi_proc_sem_id = -1;
960 config->multi_proc_sem_id = sem_id;
961 config->multi_proc_sem_path = path;
970 fr_strerror_printf(
"Refusing to start - PID %u already running with \"%s\"", pid, path);
981 if (fp != NULL) fclose(fp);
1027 dlclose(*dl_handle);
1038 char const *p = NULL;
1040 struct stat statbuf;
1041 bool can_colourise =
false;
1051 if (stat(
config->raddb_dir, &statbuf) < 0) {
1057 if ((statbuf.st_mode & S_IWOTH) != 0) {
1058 ERROR(
"Configuration directory %s is globally writable. "
1059 "Refusing to start due to insecure configuration",
config->raddb_dir);
1064 #if 0 && defined(S_IROTH)
1065 if (statbuf.st_mode & S_IROTH != 0) {
1066 ERROR(
"Configuration directory %s is globally readable. "
1067 "Refusing to start due to insecure configuration",
config->raddb_dir);
1071 INFO(
"Starting - reading configuration files ...");
1078 config->talloc_pool_size = 8 * 1024;
1108 PERROR(
"Failed reading internal dictionaries");
1133 if (!subcs)
goto failure;
1175 ERROR(
"Failed adding/replacing \"name\" config item");
1190 char const *attr, *
value;
1200 cf_log_err(ci,
"Unexpected item in ENV section");
1206 cf_log_err(ci,
"Invalid operator for item in ENV section");
1213 if (unsetenv(attr) < 0) {
1214 cf_log_err(ci,
"Failed deleting environment variable %s: %s",
1222 if (setenv(attr,
value, 1) < 0) {
1223 cf_log_err(ci,
"Failed setting environment variable %s: %s",
1231 if (strcmp(attr,
"LD_PRELOAD") != 0)
continue;
1242 MEM(handle_p = talloc(NULL,
void *));
1254 fprintf(stderr,
"%s: Error: Failed pushing rules for log {} section.\n",
1259 DEBUG(
"Parsing initial logging configuration.");
1261 fprintf(stderr,
"%s: Error: Failed to parse log{} section.\n",
1272 fprintf(stderr,
"%s: Error: No log destination specified.\n",
1281 fprintf(stderr,
"%s: Error: Unknown log_destination %s\n",
1285 #ifdef HAVE_SYSLOG_H
1291 openlog(
config->name, LOG_PID,
config->syslog_facility);
1297 fprintf(stderr,
"%s: Error: Specified \"files\" as a log destination, but no log filename was given!\n",
1321 if (switch_users(
config, cs) < 0)
goto failure;
1329 if (
config->allow_core_dumps)
INFO(
"Core dumps are enabled");
1338 DEBUG(
"Parsing main configuration");
1348 if (can_colourise && !
config->do_colourise) {
1359 INFO(
"Switching to configured log settings");
1374 cf_log_err(cs,
"Failed initializing logging");
1405 if (
config->chroot_dir) {
1406 if (chdir(
config->log_dir) < 0) {
1440 TALLOC_FREE((*config)->root_cs);
1453 fd = open(
config->log_file, O_WRONLY | O_APPEND | O_CREAT, 0640);
1489 INFO(
"HUP - Last HUP was too recent. Ignoring");
1494 INFO(
"HUP - NYI in version 4");
1498 {
L(
"rewrite_update"), offsetof(
main_config_t, rewrite_update) },
1500 {
L(
"require_enum_prefix"), offsetof(
main_config_t, require_enum_prefix) },
1518 p = strchr(
value,
'=');
1533 p, strlen(p), NULL,
false) < 0) {
1552 if (strcmp(
name,
"use_new_conditions") == 0)
return true;
1555 if (!offset)
return false;
1557 return *(
bool *) (((uintptr_t)
main_config) + offset);
static int const char char buffer[256]
#define L(_str)
Helper for initialising arrays of string literals.
int cf_file_read(CONF_SECTION *cs, char const *filename)
int cf_section_pass2(CONF_SECTION *cs)
void cf_file_check_user(uid_t uid, gid_t gid)
Set the euid/egid used when performing file checks.
CONF_ITEM * cf_reference_item(CONF_SECTION const *parent_cs, CONF_SECTION const *outer_cs, char const *ptr)
int cf_section_parse(TALLOC_CTX *ctx, void *base, CONF_SECTION *cs)
Parse a configuration section into user-supplied variables.
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.
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.
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.
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.
#define CONF_PARSER_TERMINATOR
#define FR_CONF_DEPRECATED(_name, _struct, _field)
conf_parser_t entry which raises an error if a matching CONF_PAIR is found
#define FR_INTEGER_BOUND_CHECK(_name, _var, _op, _bound)
#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
#define FR_SIZE_BOUND_CHECK(_name, _var, _op, _bound)
#define cf_section_rules_push(_cs, _rule)
#define FR_CONF_POINTER(_name, _type, _flags, _res_p)
conf_parser_t which parses a single CONF_PAIR producing a single global result
char const * name1
Name of the CONF_ITEM to parse.
#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,...
#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
#define FR_TIME_DELTA_BOUND_CHECK(_name, _var, _op, _bound)
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
@ CONF_FLAG_HIDDEN
Used by scripts to omit items from the generated documentation.
#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
Defines a CONF_PAIR to C data type mapping.
Common header for all CONF_* types.
Configuration AVP similar to a fr_pair_t.
A section grouping multiple CONF_PAIR.
bool cf_item_is_pair(CONF_ITEM const *ci)
Determine if CONF_ITEM is a CONF_PAIR.
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
CONF_ITEM * cf_section_to_item(CONF_SECTION const *cs)
Cast a CONF_SECTION to a CONF_ITEM.
char const * cf_pair_attr(CONF_PAIR const *pair)
Return the attr of a CONF_PAIR.
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
CONF_PAIR * cf_pair_find(CONF_SECTION const *cs, char const *attr)
Search for a CONF_PAIR with a specific name.
char const * cf_section_name2(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
bool cf_item_is_data(CONF_ITEM const *ci)
Determine if CONF_ITEM is CONF_DATA.
fr_token_t cf_pair_operator(CONF_PAIR const *pair)
Return the operator of a pair.
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.
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.
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.
#define cf_log_err(_cf, _fmt,...)
#define cf_data_add(_cf, _data, _name, _free)
#define cf_log_info(_cf, _fmt,...)
#define cf_log_perr(_cf, _fmt,...)
#define cf_log_pwarn(_cf, _fmt,...)
#define cf_section_alloc(_ctx, _parent, _name1, _name2)
#define cf_item_next(_ci, _curr)
static int fr_dcursor_append(fr_dcursor_t *cursor, void *v)
Insert a single item at the end of the list.
fr_dcursor_eval_t void const * uctx
static char panic_action[512]
The command to execute when panicking.
int fr_set_dumpable(bool allow_core_dumps)
Enable or disable core dumps.
int fr_set_dumpable_init(void)
Get the current maximum for core files.
#define fr_exit(_x)
Exit, producing a log message in debug builds.
void dependency_features_init(CONF_SECTION *cs)
Initialise core feature flags.
void dependency_version_numbers_init(CONF_SECTION *cs)
Initialise core version flags.
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.
dl_module_loader_t * dl_module_loader_init(char const *lib_dir)
Initialise structures needed by the dynamic linker.
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.
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
uint32_t fr_hw_num_cores_active(void)
bool fr_hostname_lookups
hostname -> IP lookups?
bool fr_reverse_lookups
IP -> hostname lookups?
static bool log_timestamp
fr_table_num_sorted_t const log_destination_table[]
int log_global_init(fr_log_t *log, bool daemonize)
Initialises the server logging functionality, and the underlying libfreeradius log.
int log_parse_section(CONF_SECTION *cs)
Parse a named logging section.
size_t syslog_facility_table_len
fr_table_num_sorted_t const syslog_facility_table[]
Syslog facility table.
void log_global_free(void)
#define DEBUG_ENABLED
True if global debug level 1 messages are enabled.
void rad_suid_set_down_uid(uid_t uid)
@ L_DST_NULL
Discard log messages.
@ L_DST_FILES
Log to a file on disk.
@ L_DST_SYSLOG
Log to syslog.
@ L_TIMESTAMP_ON
Always log timestamps.
@ L_TIMESTAMP_OFF
Never log timestamps.
@ L_TIMESTAMP_AUTO
Timestamp logging preference not specified.
static const conf_parser_t log_config[]
static const conf_parser_t resources[]
int main_config_parse_option(char const *value)
static size_t config_arg_table_len
int main_config_free(main_config_t **config)
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.
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)
main_config_t * main_config_alloc(TALLOC_CTX *ctx)
Allocate a main_config_t struct, setting defaults.
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.
CONF_SECTION * root_cs
Root of the server config.
Main server configuration.
@ FR_TYPE_TIME_DELTA
A period of time measured in nanoseconds.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_BOOL
A truth value.
@ FR_TYPE_SIZE
Unsigned integer capable of representing any memory address on the local system.
int fr_perm_getgrgid(TALLOC_CTX *ctx, struct group **out, gid_t gid)
Resolve a gid to a group database entry.
int fr_perm_getpwuid(TALLOC_CTX *ctx, struct passwd **out, uid_t uid)
Resolve a uid to a passwd entry.
static const conf_parser_t config[]
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.
int fr_sem_close(int sem_id, char const *file)
Remove the semaphore, this helps with permissions issues.
int fr_sem_pid(pid_t *pid, int sem_id)
Return the PID of the process that last operated on the semaphore.
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.
int fr_sem_take(int sem_id, char const *file, bool undo_on_exit)
Increment the semaphore by 1.
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
fr_client_list_t * client_list_parse_section(CONF_SECTION *section, int proto, TLS_UNUSED bool tls_required)
void client_list_free(void)
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
#define fr_time()
Allow us to arbitrarily manipulate time.
bool colourise
Prefix log messages with VT100 escape codes to change text colour.
fr_log_dst_t dst
Log destination.
bool line_number
Log src file and line number.
int fd
File descriptor to write messages to.
fr_log_timestamp_t timestamp
Prefix log messages with timestamps.
char const * file
Path to log file.
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
#define fr_table_value_by_str(_table, _name, _def)
Convert a string to a value using a sorted or ordered table.
#define fr_table_value_by_substr(_table, _name, _name_len, _def)
Convert a partial string to a value using an ordered or sorted table.
An element in an arbitrarily ordered array of name to num mappings.
char * talloc_typed_strdup(TALLOC_CTX *ctx, char const *p)
Call talloc_strdup, setting the type on the new chunk correctly.
static int talloc_const_free(void const *ptr)
Free const'd memory.
#define fr_time_gteq(_a, _b)
static fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
#define fr_time_wrap(_time)
#define fr_time_add(_a, _b)
Add a time/time delta together.
A time delta, a difference in time measured in nanoseconds.
bool required
Argument must be present, and non-empty.
#define XLAT_ARG_PARSER_TERMINATOR
@ XLAT_ACTION_FAIL
An xlat function failed.
@ XLAT_ACTION_DONE
We're done evaluating this level of nesting.
Definition for a single argument consumend by an xlat function.
#define FR_DICTIONARY_INTERNAL_DIR
void fr_perror(char const *fmt,...)
Print the current error to stderr with a prefix.
void fr_strerror_clear(void)
Clears all pending messages from the talloc pools.
char const * fr_strerror(void)
Get the last library error.
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
#define fr_strerror_const(_msg)
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)
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.
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.
#define fr_value_box_alloc_null(_ctx)
Allocate a value box for later use with a value assignment function.
#define fr_value_box_init(_vb, _type, _enumv, _tainted)
Initialise a fr_value_box_t.
static size_t char ** out
const conf_parser_t virtual_servers_on_read_config[]
const conf_parser_t virtual_servers_config[]
void xlat_func_flags_set(xlat_t *x, xlat_func_flags_t flags)
Specify flags that alter the xlat's behaviour.
int xlat_func_args_set(xlat_t *x, xlat_arg_parser_t const args[])
Register the arguments of an xlat.
xlat_t * xlat_func_register(TALLOC_CTX *ctx, char const *name, xlat_func_t func, fr_type_t return_type)
Register an xlat function.