From: Arran Cudbard-Bell Date: Thu, 17 Jul 2025 02:19:55 +0000 (-0600) Subject: Add additional file check flags X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=69b265dadcf99103ccd7b5616ab3dbbfb331a69f;p=thirdparty%2Ffreeradius-server.git Add additional file check flags Add specific flag for unix sockets --- diff --git a/src/lib/curl/base.c b/src/lib/curl/base.c index 16bee41395..6230cd5d44 100644 --- a/src/lib/curl/base.c +++ b/src/lib/curl/base.c @@ -66,11 +66,11 @@ static int tls_config_dflt_capath(CONF_PAIR **out, UNUSED void *parent, CONF_SEC } conf_parser_t fr_curl_tls_config[] = { - { FR_CONF_OFFSET_FLAGS("ca_file", CONF_FLAG_FILE_INPUT, fr_curl_tls_t, ca_file) }, - { FR_CONF_OFFSET_FLAGS("ca_issuer_file", CONF_FLAG_FILE_INPUT, fr_curl_tls_t, ca_issuer_file) }, - { FR_CONF_OFFSET_FLAGS("ca_path", CONF_FLAG_FILE_INPUT, fr_curl_tls_t, ca_path), .dflt_func = tls_config_dflt_capath }, - { FR_CONF_OFFSET_FLAGS("certificate_file", CONF_FLAG_FILE_INPUT, fr_curl_tls_t, certificate_file) }, - { FR_CONF_OFFSET_FLAGS("private_key_file", CONF_FLAG_FILE_INPUT, fr_curl_tls_t, private_key_file) }, + { FR_CONF_OFFSET_FLAGS("ca_file", CONF_FLAG_FILE_READABLE, fr_curl_tls_t, ca_file) }, + { FR_CONF_OFFSET_FLAGS("ca_issuer_file", CONF_FLAG_FILE_READABLE, fr_curl_tls_t, ca_issuer_file) }, + { FR_CONF_OFFSET_FLAGS("ca_path", CONF_FLAG_FILE_READABLE, fr_curl_tls_t, ca_path), .dflt_func = tls_config_dflt_capath }, + { FR_CONF_OFFSET_FLAGS("certificate_file", CONF_FLAG_FILE_READABLE, fr_curl_tls_t, certificate_file) }, + { FR_CONF_OFFSET_FLAGS("private_key_file", CONF_FLAG_FILE_READABLE, fr_curl_tls_t, private_key_file) }, { FR_CONF_OFFSET_FLAGS("private_key_password", CONF_FLAG_SECRET, fr_curl_tls_t, private_key_password) }, { FR_CONF_OFFSET("random_file", fr_curl_tls_t, random_file) }, { FR_CONF_OFFSET_TYPE_FLAGS("require_cert", FR_TYPE_VOID, 0, fr_curl_tls_t, require_cert), @@ -84,7 +84,7 @@ conf_parser_t fr_curl_tls_config[] = { { FR_CONF_OFFSET("check_cert_cn", fr_curl_tls_t, check_cert_cn), .dflt = "yes" }, { FR_CONF_OFFSET("extract_cert_attrs", fr_curl_tls_t, extract_cert_attrs), .dflt = "no" }, #ifdef WITH_TLS - { FR_CONF_OFFSET_FLAGS("keylog_file", CONF_FLAG_FILE_OUTPUT, fr_curl_tls_t, keylog_file) }, + { FR_CONF_OFFSET_FLAGS("keylog_file", CONF_FLAG_FILE_WRITABLE, fr_curl_tls_t, keylog_file) }, #endif CONF_PARSER_TERMINATOR }; diff --git a/src/lib/kafka/base.c b/src/lib/kafka/base.c index 1c5b31927d..493b74b287 100644 --- a/src/lib/kafka/base.c +++ b/src/lib/kafka/base.c @@ -576,7 +576,7 @@ static conf_parser_t const kafka_sasl_kerberos_config[] = { /* * keytab */ - { FR_CONF_FUNC("keytab", FR_TYPE_STRING, CONF_FLAG_FILE_INPUT, kafka_config_parse, kafka_config_dflt), + { FR_CONF_FUNC("keytab", FR_TYPE_STRING, CONF_FLAG_FILE_READABLE, kafka_config_parse, kafka_config_dflt), .uctx = &(fr_kafka_conf_ctx_t){ .property = "sasl.kerberos.kinit.keytab", .empty_default = true }}, /* @@ -645,27 +645,27 @@ static conf_parser_t const kafka_tls_config[] = { * Sets the full path to a CA certificate (used to validate * the certificate the server presents). */ - { FR_CONF_FUNC("ca_file", FR_TYPE_STRING, CONF_FLAG_FILE_INPUT, kafka_config_parse, kafka_config_dflt), + { FR_CONF_FUNC("ca_file", FR_TYPE_STRING, CONF_FLAG_FILE_READABLE, kafka_config_parse, kafka_config_dflt), .uctx = &(fr_kafka_conf_ctx_t){ .property = "ssl.ca.location", .empty_default = true }}, /* * Location of the CRL file. */ - { FR_CONF_FUNC("crl_file", FR_TYPE_STRING, CONF_FLAG_FILE_INPUT, kafka_config_parse, kafka_config_dflt), + { FR_CONF_FUNC("crl_file", FR_TYPE_STRING, CONF_FLAG_FILE_READABLE, kafka_config_parse, kafka_config_dflt), .uctx = &(fr_kafka_conf_ctx_t){ .property = "ssl.crl.location", .empty_default = true }}, /* * Sets the path to the public certificate file we present * to the servers. */ - { FR_CONF_FUNC("certificate_file", FR_TYPE_STRING, CONF_FLAG_FILE_INPUT, kafka_config_parse, kafka_config_dflt), + { FR_CONF_FUNC("certificate_file", FR_TYPE_STRING, CONF_FLAG_FILE_READABLE, kafka_config_parse, kafka_config_dflt), .uctx = &(fr_kafka_conf_ctx_t){ .property = "ssl.certificate.location", .empty_default = true }}, /* * Sets the path to the private key for our public * certificate. */ - { FR_CONF_FUNC("private_key_file", FR_TYPE_STRING, CONF_FLAG_FILE_INPUT, kafka_config_parse, kafka_config_dflt), + { FR_CONF_FUNC("private_key_file", FR_TYPE_STRING, CONF_FLAG_FILE_READABLE, kafka_config_parse, kafka_config_dflt), .uctx = &(fr_kafka_conf_ctx_t){ .property = "ssl.key.location", .empty_default = true }}, /* diff --git a/src/lib/ldap/conf.c b/src/lib/ldap/conf.c index 51c617111b..9dea5a2117 100644 --- a/src/lib/ldap/conf.c +++ b/src/lib/ldap/conf.c @@ -41,13 +41,13 @@ conf_parser_t const fr_ldap_tls_config[] = { /* * Deprecated attributes */ - { FR_CONF_OFFSET_FLAGS("ca_file", CONF_FLAG_FILE_INPUT, fr_ldap_config_t, tls_ca_file) }, + { FR_CONF_OFFSET_FLAGS("ca_file", CONF_FLAG_FILE_READABLE, fr_ldap_config_t, tls_ca_file) }, - { FR_CONF_OFFSET_FLAGS("ca_path", CONF_FLAG_FILE_INPUT, fr_ldap_config_t, tls_ca_path) }, + { FR_CONF_OFFSET_FLAGS("ca_path", CONF_FLAG_FILE_READABLE, fr_ldap_config_t, tls_ca_path) }, - { FR_CONF_OFFSET_FLAGS("certificate_file", CONF_FLAG_FILE_INPUT, fr_ldap_config_t, tls_certificate_file) }, + { FR_CONF_OFFSET_FLAGS("certificate_file", CONF_FLAG_FILE_READABLE, fr_ldap_config_t, tls_certificate_file) }, - { FR_CONF_OFFSET_FLAGS("private_key_file", CONF_FLAG_FILE_INPUT, fr_ldap_config_t, tls_private_key_file) }, + { FR_CONF_OFFSET_FLAGS("private_key_file", CONF_FLAG_FILE_READABLE, fr_ldap_config_t, tls_private_key_file) }, /* * LDAP Specific TLS attributes diff --git a/src/lib/server/cf_file.c b/src/lib/server/cf_file.c index 36edb1e991..ddfe121a4b 100644 --- a/src/lib/server/cf_file.c +++ b/src/lib/server/cf_file.c @@ -30,8 +30,11 @@ */ RCSID("$Id$") +#include + #include #include +#include #include #include #include @@ -40,10 +43,10 @@ RCSID("$Id$") #include #include #include +#include #include #include - #ifdef HAVE_DIRENT_H # include #endif @@ -655,24 +658,259 @@ static int cf_file_open(CONF_SECTION *cs, char const *filename, bool from_dir, F return 0; } +/** Set the euid/egid used when performing file checks + * + * Sets the euid, and egid used when cf_file_check is called to check + * permissions on conf items of type #CONF_FLAG_FILE_READABLE + * + * @note This is probably only useful for the freeradius daemon itself. + * + * @param uid to set, (uid_t)-1 to use current euid. + * @param gid to set, (gid_t)-1 to use current egid. + */ +void cf_file_check_set_uid_gid(uid_t uid, gid_t gid) +{ + if (uid != 0) conf_check_uid = uid; + if (gid != 0) conf_check_gid = gid; +} + +/** Perform an operation with the effect/group set to conf_check_gid and conf_check_uid + * + * @param filename CONF_PAIR for the file being checked + * @param cb callback function to perform the check + * @param uctx user context for the callback + * @return + * - CF_FILE_OTHER_ERROR if there was a problem modifying permissions + * - The return value from the callback + */ +cf_file_check_err_t cf_file_check_effective(char const *filename, + cf_file_check_err_t (*cb)(char const *filename, void *uctx), void *uctx) +{ + int ret; + + uid_t euid = (uid_t)-1; + gid_t egid = (gid_t)-1; + + if ((conf_check_gid != (gid_t)-1) && ((egid = getegid()) != conf_check_gid)) { + if (setegid(conf_check_gid) < 0) { + fr_strerror_printf("Failed setting effective group ID (%d) for file check: %s", + (int) conf_check_gid, fr_syserror(errno)); + return CF_FILE_OTHER_ERROR; + } + } + if ((conf_check_uid != (uid_t)-1) && ((euid = geteuid()) != conf_check_uid)) { + if (seteuid(conf_check_uid) < 0) { + fr_strerror_printf("Failed setting effective user ID (%d) for file check: %s", + (int) conf_check_uid, fr_syserror(errno)); + return CF_FILE_OTHER_ERROR; + } + } + ret = cb(filename, uctx); + if (conf_check_uid != euid) { + if (seteuid(euid) < 0) { + fr_strerror_printf("Failed restoring effective user ID (%d) after file check: %s", + (int) euid, fr_syserror(errno)); + return CF_FILE_OTHER_ERROR; + } + } + if (conf_check_gid != egid) { + if (setegid(egid) < 0) { + fr_strerror_printf("Failed restoring effective group ID (%d) after file check: %s", + (int) egid, fr_syserror(errno)); + return CF_FILE_OTHER_ERROR; + } + } + + return ret; +} + +/** Check if we can connect to a unix socket + * + * @param[in] filename CONF_PAIR for the unix socket path + * @param[in] uctx user context, not used + * @return + * - CF_FILE_OK if the socket exists and is accessible. + * - -1 if we couldn't create a new file descriptor. + * - -2 if the file doesn't exist. + * - -3 if the file exists but is not accessible. + * - -4 any other error. + */ +cf_file_check_err_t cf_file_check_unix_connect(char const *filename, UNUSED void *uctx) +{ + int fd; + cf_file_check_err_t ret = CF_FILE_OK; + + struct sockaddr_un addr = { .sun_family = AF_UNIX }; + + fr_strerror_clear(); + + if (talloc_strlen(filename) >= sizeof(addr.sun_path)) { + fr_strerror_printf("Socket path \"%s\" to long", filename); + return CF_FILE_OTHER_ERROR; + } + + strncpy(addr.sun_path, filename, sizeof(addr.sun_path) - 1); + + fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd < 0) { + fr_strerror_printf("Failed checking permissions for \"%s\": %s", + filename, fr_syserror(errno)); + return CF_FILE_OTHER_ERROR; + } + if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) { + fr_strerror_printf("Failed setting non-blocking mode for socket %s: %s", + filename, fr_syserror(errno)); + close(fd); + return CF_FILE_OTHER_ERROR; + } + + if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + switch (errno) { + case EINPROGRESS: /* This is fine */ + break; + + case ENOENT: + fr_strerror_printf("Socket path \"%s\" does not exist", filename); + ret = CF_FILE_NO_EXIST; + break; + + case EACCES: + fr_perm_file_error(errno); + fr_strerror_printf_push("Socket path \"%s\" exists but is not accessible", filename); + ret = CF_FILE_NO_PERMISSION; + break; + + case ENOTSOCK: + fr_strerror_printf("File \"%s\" is not a socket", filename); + ret = CF_FILE_NO_UNIX_SOCKET; + break; + + default: + fr_strerror_printf("Failed connecting to socket %s: %s", filename, fr_syserror(errno)); + ret = CF_FILE_OTHER_ERROR; + break; + } + } + + close(fd); + + return ret; +} + +/** Check if file exists, and is a socket + * + * @param[in] filename CONF_PAIR for the unix socket path + * @param[in] uctx user context, not used + * @return + * - CF_FILE_OK if the socket exists and is a socket. + * - CF_FILE_NO_EXIST if the file doesn't exist. + * - CF_FILE_NO_PERMISSION if the file exists but is not accessible. + * - CF_FILE_NO_UNIX_SOCKET if the file exists but is not a socket. + * - CF_FILE_OTHER_ERROR any other error. + */ +cf_file_check_err_t cf_file_check_unix_perm(char const *filename, UNUSED void *uctx) +{ + struct stat buf; + + fr_strerror_clear(); + + if (stat(filename, &buf) < 0) { + switch (errno) { + case ENOENT: + fr_strerror_printf("Socket path \"%s\" does not exist", filename); + return CF_FILE_NO_EXIST; + + case EPERM: + case EACCES: + fr_perm_file_error(errno); + fr_strerror_printf_push("Socket path \"%s\" exists but is not accessible: %s", + filename, fr_syserror(errno)); + return CF_FILE_NO_PERMISSION; + + default: + fr_strerror_printf("Unable to state socket \"%s\": %s", filename, fr_syserror(errno)); + return CF_FILE_OTHER_ERROR; + } + } + + if (!S_ISSOCK(buf.st_mode)) { + fr_strerror_printf("File \"%s\" is not a socket", filename); + return CF_FILE_NO_UNIX_SOCKET; + } + + return CF_FILE_OK; +} + +/** Callback for cf_file_check to open a file and check permissions. + * + * This is used to check if a file exists, and is readable by the + * unprivileged user/group. + * + * @param filename currently being processed. + * @param uctx user context, which is a pointer to cf_file_t + * @return + * - CF_FILE_OK if the file exists and is readable. + * - CF_FILE_NO_EXIST if the file does not exist. + * - CF_FILE_NO_PERMISSION if the file exists but is not accessible. + * - CF_FILE_OTHER_ERROR if there was any other error. + */ +cf_file_check_err_t cf_file_check_open_read(char const *filename, void *uctx) +{ + int fd; + cf_file_t *file = uctx; + + fr_strerror_clear(); + + fd = open(filename, O_RDONLY); + if (fd < 0) { + error: + if (fd >= 0) close(fd); + + switch (errno) { + case ENOENT: + fr_strerror_printf("File \"%s\" does not exist", filename); + return CF_FILE_NO_EXIST; + + case EPERM: + case EACCES: + fr_perm_file_error(errno); + fr_strerror_printf_push("File \"%s\" exists but is not accessible: %s", + filename, fr_syserror(errno)); + return CF_FILE_NO_PERMISSION; + + default: + fr_strerror_printf("Unable to open file \"%s\": %s", filename, fr_syserror(errno)); + return CF_FILE_OTHER_ERROR; + + } + } + + if (file && fstat(fd, &file->buf) < 0) goto error; + + close(fd); + return CF_FILE_OK; +} + /** Do some checks on the file as an "input" file. i.e. one read by a module. * * @note Must be called with super user privileges. * * @param cp currently being processed. - * @param check_perms If true - will return false if file is world readable, + * @param check_perms If true - will return error if file is world readable, * or not readable by the unprivileged user/group. * @return - * - true if permissions are OK, or the file exists. - * - false if the file does not exist or the permissions are incorrect. + * - CF_FILE_OK if the socket exists and is a socket. + * - CF_FILE_NO_EXIST if the file doesn't exist. + * - CF_FILE_NO_PERMISSION if the file exists but is not accessible. + * - CF_FILE_OTHER_ERROR any other error. */ -bool cf_file_check(CONF_PAIR *cp, bool check_perms) +cf_file_check_err_t cf_file_check(CONF_PAIR *cp, bool check_perms) { - cf_file_t *file; - CONF_SECTION *top; - fr_rb_tree_t *tree; - char const *filename = cf_pair_value(cp); - int fd = -1; + cf_file_t *file; + CONF_SECTION *top; + fr_rb_tree_t *tree; + char const *filename = cf_pair_value(cp); + cf_file_check_err_t ret; top = cf_root(cp); tree = cf_data_value(cf_data_find(top, fr_rb_tree_t, "filename")); @@ -686,16 +924,14 @@ bool cf_file_check(CONF_PAIR *cp, bool check_perms) if (!check_perms) { if (stat(filename, &file->buf) < 0) { - perm_error: fr_perm_file_error(errno); /* Write error and euid/egid to error buff */ cf_log_perr(cp, "Unable to open file \"%s\"", filename); error: - if (fd >= 0) close(fd); talloc_free(file); - return false; + return CF_FILE_OTHER_ERROR; } talloc_free(file); - return true; + return CF_FILE_OK; } /* @@ -703,52 +939,17 @@ bool cf_file_check(CONF_PAIR *cp, bool check_perms) * to check that the file can be read with the * euid/egid. */ - { - uid_t euid = (uid_t)-1; - gid_t egid = (gid_t)-1; - - if ((conf_check_gid != (gid_t)-1) && ((egid = getegid()) != conf_check_gid)) { - if (setegid(conf_check_gid) < 0) { - cf_log_perr(cp, "Failed setting effective group ID (%d) for file check: %s", - (int) conf_check_gid, fr_syserror(errno)); - goto error; - } - } - if ((conf_check_uid != (uid_t)-1) && ((euid = geteuid()) != conf_check_uid)) { - if (seteuid(conf_check_uid) < 0) { - cf_log_perr(cp, "Failed setting effective user ID (%d) for file check: %s", - (int) conf_check_uid, fr_syserror(errno)); - goto error; - } - } - fd = open(filename, O_RDONLY); - if (conf_check_uid != euid) { - if (seteuid(euid) < 0) { - cf_log_perr(cp, "Failed restoring effective user ID (%d) after file check: %s", - (int) euid, fr_syserror(errno)); - goto error; - } - } - if (conf_check_gid != egid) { - if (setegid(egid) < 0) { - cf_log_perr(cp, "Failed restoring effective group ID (%d) after file check: %s", - (int) egid, fr_syserror(errno)); - goto error; - } - } + ret = cf_file_check_effective(filename, cf_file_check_open_read, file); + if (ret < 0) { + cf_log_perr(cp, "Permissions check failed"); + goto error; } - - if (fd < 0) goto perm_error; - if (fstat(fd, &file->buf) < 0) goto perm_error; - - close(fd); - #ifdef S_IWOTH if ((file->buf.st_mode & S_IWOTH) != 0) { cf_log_perr(cp, "Configuration file %s is globally writable. " "Refusing to start due to insecure configuration.", filename); talloc_free(file); - return false; + return CF_FILE_OTHER_ERROR; } #endif @@ -757,7 +958,7 @@ bool cf_file_check(CONF_PAIR *cp, bool check_perms) */ if (!fr_rb_insert(tree, file)) talloc_free(file); - return true; + return CF_FILE_OK; } /* @@ -3423,22 +3624,6 @@ void cf_file_free(CONF_SECTION *cs) talloc_free(cs); } -/** Set the euid/egid used when performing file checks - * - * Sets the euid, and egid used when cf_file_check is called to check - * permissions on conf items of type #CONF_FLAG_FILE_INPUT - * - * @note This is probably only useful for the freeradius daemon itself. - * - * @param uid to set, (uid_t)-1 to use current euid. - * @param gid to set, (gid_t)-1 to use current egid. - */ -void cf_file_check_user(uid_t uid, gid_t gid) -{ - if (uid != 0) conf_check_uid = uid; - if (gid != 0) conf_check_gid = gid; -} - static char const parse_tabs[] = " "; static ssize_t cf_string_write(FILE *fp, char const *string, size_t len, fr_token_t t) diff --git a/src/lib/server/cf_file.h b/src/lib/server/cf_file.h index 3fd9fce548..6253120b2d 100644 --- a/src/lib/server/cf_file.h +++ b/src/lib/server/cf_file.h @@ -39,33 +39,52 @@ RCSIDH(cf_file_h, "$Id$") extern "C" { #endif +/** Results of file checks + * + */ +typedef enum { + CF_FILE_OK = 0, //!< File checks passed. + CF_FILE_NO_PERMISSION = -1, //!< Requested permissions not set + CF_FILE_NO_EXIST = -2, //!< File does not exist + CF_FILE_NO_UNIX_SOCKET = -3, //!< File is not a unix socket + CF_FILE_OTHER_ERROR = -4 //!< Other error occurred checking permissions +} cf_file_check_err_t; + /* * Config file parsing */ -int cf_file_read(CONF_SECTION *cs, char const *file); -int cf_section_pass2(CONF_SECTION *cs); -void cf_file_free(CONF_SECTION *cs); +int cf_file_read(CONF_SECTION *cs, char const *file); +int cf_section_pass2(CONF_SECTION *cs); +void cf_file_free(CONF_SECTION *cs); + +void cf_file_check_set_uid_gid(uid_t uid, gid_t gid); +cf_file_check_err_t cf_file_check_effective(char const *filename, + cf_file_check_err_t (*cb)(char const *filename, void *uctx), void *uctx); + +cf_file_check_err_t cf_file_check_unix_connect(char const *filename, UNUSED void *uctx); +cf_file_check_err_t cf_file_check_unix_perm(char const *filename, UNUSED void *uctx); +cf_file_check_err_t cf_file_check_open_read(char const *filename, void *uctx); + +cf_file_check_err_t cf_file_check(CONF_PAIR *cp, bool check_perms); -bool cf_file_check(CONF_PAIR *cp, bool check_perms); -void cf_file_check_user(uid_t uid, gid_t gid); -void cf_md5_init(void); -void cf_md5_final(uint8_t *digest); +void cf_md5_init(void); +void cf_md5_final(uint8_t *digest); /* * Config file writing */ -int cf_section_write(FILE *fp, CONF_SECTION *cs, int depth); +int cf_section_write(FILE *fp, CONF_SECTION *cs, int depth); /* * Misc */ -CONF_ITEM *cf_reference_item(CONF_SECTION const *parentcs, CONF_SECTION const *outercs, char const *ptr); -char const *cf_expand_variables(char const *filename, int lineno, - CONF_SECTION *outer_cs, - char *output, size_t outsize, - char const *input, ssize_t inlen, bool *soft_fail); -void cf_section_set_unlang(CONF_SECTION *cs); +CONF_ITEM *cf_reference_item(CONF_SECTION const *parentcs, CONF_SECTION const *outercs, char const *ptr); +char const *cf_expand_variables(char const *filename, int lineno, + CONF_SECTION *outer_cs, + char *output, size_t outsize, + char const *input, ssize_t inlen, bool *soft_fail); +void cf_section_set_unlang(CONF_SECTION *cs); #ifdef __cplusplus } diff --git a/src/lib/server/cf_parse.c b/src/lib/server/cf_parse.c index ca0a1dc750..a8e56e7907 100644 --- a/src/lib/server/cf_parse.c +++ b/src/lib/server/cf_parse.c @@ -24,6 +24,9 @@ * @copyright 2000 Miquel van Smoorenburg (miquels@cistron.nl) * @copyright 2000 Alan DeKok (aland@freeradius.org) */ +#include "lib/util/syserror.h" +#include +#include RCSID("$Id$") #include @@ -136,18 +139,56 @@ int cf_pair_to_value_box(TALLOC_CTX *ctx, fr_value_box_t *out, CONF_PAIR *cp, co * Strings can be file paths... */ if (fr_type_is_string(rule->type)) { + if (fr_rule_file_socket(rule)) { + /* + * Attempt to actually connect to the socket. + * There's no real standard behaviour across + * operating systems for this. + * + * This also implies fr_rule_file_exists. + */ + if (fr_rule_file_readable(rule) || fr_rule_file_writable(rule)) { + if (cf_file_check_effective(cf_pair_value(cp), cf_file_check_unix_connect, NULL) != 0) { + cf_log_perr(cp, "File check failed"); + return -1; + } + /* + * Otherwise just passively check if the socket + * exists. + */ + } else if (fr_rule_file_exists(rule)) { + if (cf_file_check_effective(cf_pair_value(cp), cf_file_check_unix_perm, NULL) != 0) { + cf_log_perr(cp, "File check failed"); + return -1; + } + /* + * ...and if there's no existence requirement + * just check that it's a unix socket. + */ + } else { + switch (cf_file_check_effective(cf_pair_value(cp), cf_file_check_unix_perm, NULL)) { + default: + /* ok */ + break; + + case CF_FILE_NO_UNIX_SOCKET: + cf_log_perr(cp, "File check failed"); + return -1; + } + } + } /* * If there's out AND it's an input file, check * that we can read it. This check allows errors * to be caught as early as possible, during * server startup. */ - if (fr_rule_file_input(rule) && !cf_file_check(cp, true)) { + else if (fr_rule_file_readable(rule) && (cf_file_check(cp, true) < 0)) { error: fr_value_box_clear(out); return -1; } - if (fr_rule_file_exists(rule) && !cf_file_check(cp, false)) goto error; + else if (fr_rule_file_exists(rule) && (cf_file_check(cp, false) < 0)) goto error; } fr_value_box_mark_safe_for(out, FR_VALUE_BOX_SAFE_FOR_ANY); @@ -713,8 +754,8 @@ static int CC_HINT(nonnull(4,5)) cf_pair_parse_internal(TALLOC_CTX *ctx, void *o * - ``flag`` #CONF_FLAG_REQUIRED - @copybrief CONF_FLAG_REQUIRED * - ``flag`` #CONF_FLAG_ATTRIBUTE - @copybrief CONF_FLAG_ATTRIBUTE * - ``flag`` #CONF_FLAG_SECRET - @copybrief CONF_FLAG_SECRET - * - ``flag`` #CONF_FLAG_FILE_INPUT - @copybrief CONF_FLAG_FILE_INPUT - * - ``flag`` #CONF_FLAG_FILE_OUTPUT - @copybrief CONF_FLAG_FILE_OUTPUT + * - ``flag`` #CONF_FLAG_FILE_READABLE - @copybrief CONF_FLAG_FILE_READABLE + * - ``flag`` #CONF_FLAG_FILE_WRITABLE - @copybrief CONF_FLAG_FILE_WRITABLE * - ``flag`` #CONF_FLAG_NOT_EMPTY - @copybrief CONF_FLAG_NOT_EMPTY * - ``flag`` #CONF_FLAG_MULTI - @copybrief CONF_FLAG_MULTI * - ``flag`` #CONF_FLAG_IS_SET - @copybrief CONF_FLAG_IS_SET @@ -851,8 +892,8 @@ static int cf_section_parse_init(CONF_SECTION *cs, void *base, conf_parser_t con if (cp && cp->parsed) return 0; if ((rule->type != FR_TYPE_STRING) && - (!(rule->flags & CONF_FLAG_FILE_INPUT)) && - (!(rule->flags & CONF_FLAG_FILE_OUTPUT))) { + (!(rule->flags & CONF_FLAG_FILE_READABLE)) && + (!(rule->flags & CONF_FLAG_FILE_WRITABLE))) { return 0; } diff --git a/src/lib/server/cf_parse.h b/src/lib/server/cf_parse.h index aada8f866e..2f501b3ddf 100644 --- a/src/lib/server/cf_parse.h +++ b/src/lib/server/cf_parse.h @@ -437,27 +437,30 @@ typedef enum CC_HINT(flag_enum) { //!< (deprecated, use #CONF_FLAG_TMPL). CONF_FLAG_SECRET = (1 << 13), //!< Only print value if debug level >= 3. - CONF_FLAG_FILE_INPUT = (1 << 14), //!< File matching value must exist, + CONF_FLAG_FILE_READABLE = (1 << 14), //!< File matching value must exist, //!< and must be readable. - CONF_FLAG_FILE_OUTPUT = (1 << 15), //!< File matching value must exist, + CONF_FLAG_FILE_WRITABLE = (1 << 15), //!< File matching value must exist, //!< and must be writable. + CONF_FLAG_FILE_SOCKET = (1 << 16), //!< File matching value must exist, + //!< and must be a unix socket. + CONF_FLAG_FILE_EXISTS = (1 << 17), //!< File matching value must exist - CONF_FLAG_XLAT = (1 << 16), //!< string will be dynamically expanded. - CONF_FLAG_TMPL = (1 << 17), //!< CONF_PAIR should be parsed as a template. + CONF_FLAG_XLAT = (1 << 18), //!< string will be dynamically expanded. + CONF_FLAG_TMPL = (1 << 19), //!< CONF_PAIR should be parsed as a template. - CONF_FLAG_MULTI = (1 << 18), //!< CONF_PAIR can have multiple copies. - CONF_FLAG_NOT_EMPTY = (1 << 19), //!< CONF_PAIR is required to have a non zero + CONF_FLAG_MULTI = (1 << 20), //!< CONF_PAIR can have multiple copies. + CONF_FLAG_NOT_EMPTY = (1 << 21), //!< CONF_PAIR is required to have a non zero //!< length value. - CONF_FLAG_FILE_EXISTS = (1 << 20), //!< File matching value must exist - CONF_FLAG_IS_SET = (1 << 21), //!< Write whether this config item was + + CONF_FLAG_IS_SET = (1 << 22), //!< Write whether this config item was //!< left as the default to is_set_offset //!< or is_set_ptr. - CONF_FLAG_OK_MISSING = (1 << 22), //!< OK if it's missing - CONF_FLAG_HIDDEN = (1 << 23), //!< Used by scripts to omit items from the + CONF_FLAG_OK_MISSING = (1 << 23), //!< OK if it's missing + CONF_FLAG_HIDDEN = (1 << 24), //!< Used by scripts to omit items from the ///< generated documentation. - CONF_FLAG_REF = (1 << 24), //!< reference another conf_parser_t inline in this one - CONF_FLAG_OPTIONAL = (1 << 25), //!< subsection is pushed only if a non-optional matching one is pushed + CONF_FLAG_REF = (1 << 25), //!< reference another conf_parser_t inline in this one + CONF_FLAG_OPTIONAL = (1 << 26), //!< subsection is pushed only if a non-optional matching one is pushed } conf_parser_flags_t; DIAG_ON(attributes) @@ -473,10 +476,13 @@ DIAG_ON(attributes) #define fr_rule_secret(_rule) ((_rule)->flags & CONF_FLAG_SECRET) -#define fr_rule_file_input(_rule) ((_rule)->flags & CONF_FLAG_FILE_INPUT) +#define fr_rule_file_readable(_rule) ((_rule)->flags & CONF_FLAG_FILE_READABLE) + +#define fr_rule_file_writable(_rule) ((_rule)->flags & CONF_FLAG_FILE_WRITABLE) -#define fr_rule_file_output(_rule) ((_rule)->flags & CONF_FLAG_FILE_OUTPUT) +#define fr_rule_file_socket(_rule) ((_rule)->flags & CONF_FLAG_FILE_SOCKET) +#define fr_rule_file_exists(_rule) ((_rule)->flags & CONF_FLAG_FILE_EXISTS) #define fr_rule_multi(_rule) ((_rule)->flags & CONF_FLAG_MULTI) @@ -486,8 +492,6 @@ DIAG_ON(attributes) #define fr_rule_ok_missing(_rule) ((_rule)->flags & CONF_FLAG_OK_MISSING) -#define fr_rule_file_exists(_rule) ((_rule)->flags & CONF_FLAG_FILE_EXISTS) - #define fr_rule_dflt(_rule) ((_rule)->dflt || (_rule)->dflt_func) #define fr_rule_is_attribute(_rule) ((_rule)->flags & CONF_FLAG_ATTRIBUTE) diff --git a/src/lib/server/main_config.c b/src/lib/server/main_config.c index 62becaa5f0..81aa1308ab 100644 --- a/src/lib/server/main_config.c +++ b/src/lib/server/main_config.c @@ -696,7 +696,7 @@ static int switch_users(main_config_t *config, CONF_SECTION *cs) * Set the user/group we're going to use * to check read permissions on configuration files. */ - cf_file_check_user(config->server_uid ? config->server_uid : (uid_t)-1, + cf_file_check_set_uid_gid(config->server_uid ? config->server_uid : (uid_t)-1, config->server_gid ? config->server_gid : (gid_t)-1); #ifdef HAVE_GRP_H diff --git a/src/lib/tls/conf.c b/src/lib/tls/conf.c index 7f76cb6286..c3e41ad0dd 100644 --- a/src/lib/tls/conf.c +++ b/src/lib/tls/conf.c @@ -116,11 +116,11 @@ static conf_parser_t tls_chain_config[] = { .len = &certificate_format_table_len }, .dflt = "pem" }, - { FR_CONF_OFFSET_FLAGS("certificate_file", CONF_FLAG_FILE_INPUT | CONF_FLAG_FILE_EXISTS | CONF_FLAG_REQUIRED, fr_tls_chain_conf_t, certificate_file) }, + { FR_CONF_OFFSET_FLAGS("certificate_file", CONF_FLAG_FILE_READABLE | CONF_FLAG_FILE_EXISTS | CONF_FLAG_REQUIRED, fr_tls_chain_conf_t, certificate_file) }, { FR_CONF_OFFSET_FLAGS("private_key_password", CONF_FLAG_SECRET, fr_tls_chain_conf_t, password) }, - { FR_CONF_OFFSET_FLAGS("private_key_file", CONF_FLAG_FILE_INPUT | CONF_FLAG_FILE_EXISTS | CONF_FLAG_REQUIRED, fr_tls_chain_conf_t, private_key_file) }, + { FR_CONF_OFFSET_FLAGS("private_key_file", CONF_FLAG_FILE_READABLE | CONF_FLAG_FILE_EXISTS | CONF_FLAG_REQUIRED, fr_tls_chain_conf_t, private_key_file) }, - { FR_CONF_OFFSET_FLAGS("ca_file", CONF_FLAG_FILE_INPUT | CONF_FLAG_MULTI, fr_tls_chain_conf_t, ca_files) }, + { FR_CONF_OFFSET_FLAGS("ca_file", CONF_FLAG_FILE_READABLE | CONF_FLAG_MULTI, fr_tls_chain_conf_t, ca_files) }, { FR_CONF_OFFSET("verify_mode", fr_tls_chain_conf_t, verify_mode), .func = cf_table_parse_int, @@ -166,8 +166,8 @@ conf_parser_t fr_tls_server_config[] = { { FR_CONF_DEPRECATED("private_key_file", fr_tls_conf_t, NULL) }, { FR_CONF_OFFSET("verify_depth", fr_tls_conf_t, verify_depth), .dflt = "0" }, - { FR_CONF_OFFSET_FLAGS("ca_path", CONF_FLAG_FILE_INPUT, fr_tls_conf_t, ca_path) }, - { FR_CONF_OFFSET_FLAGS("ca_file", CONF_FLAG_FILE_INPUT, fr_tls_conf_t, ca_file) }, + { FR_CONF_OFFSET_FLAGS("ca_path", CONF_FLAG_FILE_READABLE, fr_tls_conf_t, ca_path) }, + { FR_CONF_OFFSET_FLAGS("ca_file", CONF_FLAG_FILE_READABLE, fr_tls_conf_t, ca_file) }, #ifdef PSK_MAX_IDENTITY_LEN { FR_CONF_OFFSET("psk_identity", fr_tls_conf_t, psk_identity) }, @@ -176,7 +176,7 @@ conf_parser_t fr_tls_server_config[] = { #endif { FR_CONF_OFFSET("keylog_file", fr_tls_conf_t, keylog_file) }, - { FR_CONF_OFFSET_FLAGS("dh_file", CONF_FLAG_FILE_INPUT, fr_tls_conf_t, dh_file) }, + { FR_CONF_OFFSET_FLAGS("dh_file", CONF_FLAG_FILE_READABLE, fr_tls_conf_t, dh_file) }, { FR_CONF_OFFSET("fragment_size", fr_tls_conf_t, fragment_size), .dflt = "1024" }, { FR_CONF_OFFSET("padding", fr_tls_conf_t, padding_block_size), }, @@ -221,9 +221,9 @@ conf_parser_t fr_tls_client_config[] = { { FR_CONF_OFFSET("keylog_file", fr_tls_conf_t, keylog_file) }, { FR_CONF_OFFSET("verify_depth", fr_tls_conf_t, verify_depth), .dflt = "0" }, - { FR_CONF_OFFSET_FLAGS("ca_path", CONF_FLAG_FILE_INPUT, fr_tls_conf_t, ca_path) }, + { FR_CONF_OFFSET_FLAGS("ca_path", CONF_FLAG_FILE_READABLE, fr_tls_conf_t, ca_path) }, - { FR_CONF_OFFSET_FLAGS("ca_file", CONF_FLAG_FILE_INPUT, fr_tls_conf_t, ca_file) }, + { FR_CONF_OFFSET_FLAGS("ca_file", CONF_FLAG_FILE_READABLE, fr_tls_conf_t, ca_file) }, { FR_CONF_OFFSET("dh_file", fr_tls_conf_t, dh_file) }, { FR_CONF_OFFSET("random_file", fr_tls_conf_t, random_file) }, { FR_CONF_OFFSET("fragment_size", fr_tls_conf_t, fragment_size), .dflt = "1024" }, diff --git a/src/listen/cron/cron.c b/src/listen/cron/cron.c index 786073cf8c..baeaa8eb5d 100644 --- a/src/listen/cron/cron.c +++ b/src/listen/cron/cron.c @@ -51,7 +51,7 @@ static conf_parser_t const proto_cron_config[] = { { FR_CONF_OFFSET_FLAGS("when", CONF_FLAG_NOT_EMPTY | CONF_FLAG_REQUIRED, proto_cron_t, spec), .func = time_parse }, - { FR_CONF_OFFSET_FLAGS("filename", CONF_FLAG_FILE_INPUT | CONF_FLAG_REQUIRED | CONF_FLAG_NOT_EMPTY, proto_cron_t, filename ) }, + { FR_CONF_OFFSET_FLAGS("filename", CONF_FLAG_FILE_READABLE | CONF_FLAG_REQUIRED | CONF_FLAG_NOT_EMPTY, proto_cron_t, filename ) }, { FR_CONF_OFFSET("priority", proto_cron_t, priority) }, diff --git a/src/listen/cron/proto_cron_crontab.c b/src/listen/cron/proto_cron_crontab.c index 55878dc2c0..b2f1150804 100644 --- a/src/listen/cron/proto_cron_crontab.c +++ b/src/listen/cron/proto_cron_crontab.c @@ -86,7 +86,7 @@ struct proto_cron_tab_s { static int time_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule); static const conf_parser_t crontab_listen_config[] = { - { FR_CONF_OFFSET_FLAGS("filename", CONF_FLAG_FILE_INPUT | CONF_FLAG_REQUIRED | CONF_FLAG_NOT_EMPTY, proto_cron_crontab_t, filename) }, + { FR_CONF_OFFSET_FLAGS("filename", CONF_FLAG_FILE_READABLE | CONF_FLAG_REQUIRED | CONF_FLAG_NOT_EMPTY, proto_cron_crontab_t, filename) }, { FR_CONF_OFFSET_FLAGS("timespec", CONF_FLAG_NOT_EMPTY | CONF_FLAG_REQUIRED, proto_cron_crontab_t, spec), .func = time_parse }, diff --git a/src/listen/load/proto_load_step.c b/src/listen/load/proto_load_step.c index 9fa0aa78f9..2b8c436ef7 100644 --- a/src/listen/load/proto_load_step.c +++ b/src/listen/load/proto_load_step.c @@ -79,7 +79,7 @@ struct proto_load_step_s { static const conf_parser_t load_listen_config[] = { - { FR_CONF_OFFSET_FLAGS("filename", CONF_FLAG_FILE_INPUT | CONF_FLAG_REQUIRED | CONF_FLAG_NOT_EMPTY, proto_load_step_t, filename) }, + { FR_CONF_OFFSET_FLAGS("filename", CONF_FLAG_FILE_READABLE | CONF_FLAG_REQUIRED | CONF_FLAG_NOT_EMPTY, proto_load_step_t, filename) }, { FR_CONF_OFFSET("csv", proto_load_step_t, csv) }, { FR_CONF_OFFSET("max_attributes", proto_load_step_t, max_attributes), .dflt = STRINGIFY(RADIUS_MAX_ATTRIBUTES) } , diff --git a/src/modules/rlm_attr_filter/rlm_attr_filter.c b/src/modules/rlm_attr_filter/rlm_attr_filter.c index bfee1e4fcb..0e74b28cc4 100644 --- a/src/modules/rlm_attr_filter/rlm_attr_filter.c +++ b/src/modules/rlm_attr_filter/rlm_attr_filter.c @@ -48,7 +48,7 @@ typedef struct { } rlm_attr_filter_t; static const conf_parser_t module_config[] = { - { FR_CONF_OFFSET_FLAGS("filename", CONF_FLAG_FILE_INPUT | CONF_FLAG_REQUIRED, rlm_attr_filter_t, filename) }, + { FR_CONF_OFFSET_FLAGS("filename", CONF_FLAG_FILE_READABLE | CONF_FLAG_REQUIRED, rlm_attr_filter_t, filename) }, { FR_CONF_OFFSET_HINT_TYPE("key", FR_TYPE_STRING, rlm_attr_filter_t, key), .dflt = "Realm", .quote = T_BARE_WORD }, { FR_CONF_OFFSET("relaxed", rlm_attr_filter_t, relaxed), .dflt = "no" }, CONF_PARSER_TERMINATOR diff --git a/src/modules/rlm_csv/rlm_csv.c b/src/modules/rlm_csv/rlm_csv.c index cf58efb27d..1bc5ed86ba 100644 --- a/src/modules/rlm_csv/rlm_csv.c +++ b/src/modules/rlm_csv/rlm_csv.c @@ -79,7 +79,7 @@ struct rlm_csv_entry_s { * A mapping of configuration file names to internal variables. */ static const conf_parser_t module_config[] = { - { FR_CONF_OFFSET_FLAGS("filename", CONF_FLAG_FILE_INPUT | CONF_FLAG_REQUIRED | CONF_FLAG_NOT_EMPTY, rlm_csv_t, filename) }, + { FR_CONF_OFFSET_FLAGS("filename", CONF_FLAG_FILE_READABLE | CONF_FLAG_REQUIRED | CONF_FLAG_NOT_EMPTY, rlm_csv_t, filename) }, { FR_CONF_OFFSET_FLAGS("delimiter", CONF_FLAG_NOT_EMPTY, rlm_csv_t, delimiter), .dflt = "," }, { FR_CONF_OFFSET("fields", rlm_csv_t, fields) }, { FR_CONF_OFFSET("header", rlm_csv_t, header) }, diff --git a/src/modules/rlm_files/rlm_files.c b/src/modules/rlm_files/rlm_files.c index f8ffb90dc1..51459cee11 100644 --- a/src/modules/rlm_files/rlm_files.c +++ b/src/modules/rlm_files/rlm_files.c @@ -78,7 +78,7 @@ fr_dict_attr_autoload_t rlm_files_dict_attr[] = { }; static const conf_parser_t module_config[] = { - { FR_CONF_OFFSET_FLAGS("filename", CONF_FLAG_REQUIRED | CONF_FLAG_FILE_INPUT, rlm_files_t, filename) }, + { FR_CONF_OFFSET_FLAGS("filename", CONF_FLAG_REQUIRED | CONF_FLAG_FILE_READABLE, rlm_files_t, filename) }, { FR_CONF_OFFSET("v3_compat", rlm_files_t, v3_compat) }, CONF_PARSER_TERMINATOR }; diff --git a/src/modules/rlm_isc_dhcp/rlm_isc_dhcp.c b/src/modules/rlm_isc_dhcp/rlm_isc_dhcp.c index c66c4ddc2c..d66026bb34 100644 --- a/src/modules/rlm_isc_dhcp/rlm_isc_dhcp.c +++ b/src/modules/rlm_isc_dhcp/rlm_isc_dhcp.c @@ -96,7 +96,7 @@ typedef struct { * A mapping of configuration file names to internal variables. */ static const conf_parser_t module_config[] = { - { FR_CONF_OFFSET_FLAGS("filename", CONF_FLAG_FILE_INPUT | CONF_FLAG_REQUIRED | CONF_FLAG_NOT_EMPTY, rlm_isc_dhcp_t, filename) }, + { FR_CONF_OFFSET_FLAGS("filename", CONF_FLAG_FILE_READABLE | CONF_FLAG_REQUIRED | CONF_FLAG_NOT_EMPTY, rlm_isc_dhcp_t, filename) }, { FR_CONF_OFFSET("debug", rlm_isc_dhcp_t, debug) }, { FR_CONF_OFFSET("pedantic", rlm_isc_dhcp_t, pedantic) }, CONF_PARSER_TERMINATOR diff --git a/src/modules/rlm_linelog/rlm_linelog.c b/src/modules/rlm_linelog/rlm_linelog.c index ac08670292..d31665ef2c 100644 --- a/src/modules/rlm_linelog/rlm_linelog.c +++ b/src/modules/rlm_linelog/rlm_linelog.c @@ -155,7 +155,7 @@ static const conf_parser_t syslog_config[] = { }; static const conf_parser_t unix_config[] = { - { FR_CONF_OFFSET_FLAGS("filename", CONF_FLAG_FILE_INPUT, rlm_linelog_t, unix_sock.path) }, + { FR_CONF_OFFSET_FLAGS("filename", CONF_FLAG_FILE_SOCKET, rlm_linelog_t, unix_sock.path) }, CONF_PARSER_TERMINATOR }; diff --git a/src/modules/rlm_logtee/rlm_logtee.c b/src/modules/rlm_logtee/rlm_logtee.c index f89b7cbbd7..6d35e6b9b3 100644 --- a/src/modules/rlm_logtee/rlm_logtee.c +++ b/src/modules/rlm_logtee/rlm_logtee.c @@ -130,7 +130,7 @@ typedef struct { static const conf_parser_t file_config[] = { - { FR_CONF_OFFSET_FLAGS("filename", CONF_FLAG_FILE_OUTPUT | CONF_FLAG_XLAT, rlm_logtee_t, file.name) }, + { FR_CONF_OFFSET_FLAGS("filename", CONF_FLAG_FILE_WRITABLE | CONF_FLAG_XLAT, rlm_logtee_t, file.name) }, { FR_CONF_OFFSET("permissions", rlm_logtee_t, file.permissions), .dflt = "0600" }, { FR_CONF_OFFSET("group", rlm_logtee_t, file.group_str) }, { FR_CONF_OFFSET("escape_filenames", rlm_logtee_t, file.escape), .dflt = "no" }, @@ -138,7 +138,7 @@ static const conf_parser_t file_config[] = { }; static const conf_parser_t unix_config[] = { - { FR_CONF_OFFSET_FLAGS("filename", CONF_FLAG_FILE_INPUT, rlm_logtee_t, unix_sock.path) }, + { FR_CONF_OFFSET_FLAGS("filename", CONF_FLAG_FILE_READABLE, rlm_logtee_t, unix_sock.path) }, CONF_PARSER_TERMINATOR }; diff --git a/src/modules/rlm_lua/rlm_lua.c b/src/modules/rlm_lua/rlm_lua.c index 4d1e4c0963..3fc7643ef6 100644 --- a/src/modules/rlm_lua/rlm_lua.c +++ b/src/modules/rlm_lua/rlm_lua.c @@ -42,7 +42,7 @@ RCSID("$Id$") * buffer over-flows. */ static const conf_parser_t module_config[] = { - { FR_CONF_OFFSET_FLAGS("filename", CONF_FLAG_FILE_INPUT | CONF_FLAG_REQUIRED, rlm_lua_t, module), NULL}, + { FR_CONF_OFFSET_FLAGS("filename", CONF_FLAG_FILE_READABLE | CONF_FLAG_REQUIRED, rlm_lua_t, module), NULL}, { FR_CONF_OFFSET("func_instantiate", rlm_lua_t, func_instantiate), NULL}, { FR_CONF_OFFSET("func_detach", rlm_lua_t, func_detach), NULL}, { FR_CONF_OFFSET("func_xlat", rlm_lua_t, func_xlat), NULL}, diff --git a/src/modules/rlm_mruby/rlm_mruby.c b/src/modules/rlm_mruby/rlm_mruby.c index 54e1311102..ac645cd7de 100644 --- a/src/modules/rlm_mruby/rlm_mruby.c +++ b/src/modules/rlm_mruby/rlm_mruby.c @@ -45,7 +45,7 @@ typedef struct { * A mapping of configuration file names to internal variables. */ static const conf_parser_t module_config[] = { - { FR_CONF_OFFSET_FLAGS("filename", CONF_FLAG_FILE_INPUT | CONF_FLAG_REQUIRED, rlm_mruby_t, filename) }, + { FR_CONF_OFFSET_FLAGS("filename", CONF_FLAG_FILE_READABLE | CONF_FLAG_REQUIRED, rlm_mruby_t, filename) }, { FR_CONF_OFFSET("module", rlm_mruby_t, module_name), .dflt = "FreeRADIUS" }, CONF_PARSER_TERMINATOR }; diff --git a/src/modules/rlm_passwd/rlm_passwd.c b/src/modules/rlm_passwd/rlm_passwd.c index 8d2ee376a9..753b0ee33d 100644 --- a/src/modules/rlm_passwd/rlm_passwd.c +++ b/src/modules/rlm_passwd/rlm_passwd.c @@ -371,7 +371,7 @@ typedef struct { } rlm_passwd_t; static const conf_parser_t module_config[] = { - { FR_CONF_OFFSET_FLAGS("filename", CONF_FLAG_FILE_INPUT | CONF_FLAG_REQUIRED, rlm_passwd_t, filename) }, + { FR_CONF_OFFSET_FLAGS("filename", CONF_FLAG_FILE_READABLE | CONF_FLAG_REQUIRED, rlm_passwd_t, filename) }, { FR_CONF_OFFSET_FLAGS("format", CONF_FLAG_REQUIRED, rlm_passwd_t, format) }, { FR_CONF_OFFSET("delimiter", rlm_passwd_t, delimiter), .dflt = ":" }, diff --git a/src/modules/rlm_perl/rlm_perl.c b/src/modules/rlm_perl/rlm_perl.c index bdc32e5faa..d9248469ad 100644 --- a/src/modules/rlm_perl/rlm_perl.c +++ b/src/modules/rlm_perl/rlm_perl.c @@ -118,7 +118,7 @@ static void *perl_dlhandle; //!< To allow us to load perl's symbols into the gl * A mapping of configuration file names to internal variables. */ static const conf_parser_t module_config[] = { - { FR_CONF_OFFSET_FLAGS("filename", CONF_FLAG_FILE_INPUT | CONF_FLAG_REQUIRED, rlm_perl_t, module) }, + { FR_CONF_OFFSET_FLAGS("filename", CONF_FLAG_FILE_READABLE | CONF_FLAG_REQUIRED, rlm_perl_t, module) }, { FR_CONF_OFFSET("func_detach", rlm_perl_t, func_detach), .data = NULL, .dflt = "detach", .quote = T_INVALID }, diff --git a/src/modules/rlm_sql/drivers/rlm_sql_cassandra/rlm_sql_cassandra.c b/src/modules/rlm_sql/drivers/rlm_sql_cassandra/rlm_sql_cassandra.c index ed612f727c..e7caecf5f4 100644 --- a/src/modules/rlm_sql/drivers/rlm_sql_cassandra/rlm_sql_cassandra.c +++ b/src/modules/rlm_sql/drivers/rlm_sql_cassandra/rlm_sql_cassandra.c @@ -201,9 +201,9 @@ static conf_parser_t latency_aware_routing_config[] = { }; static conf_parser_t tls_config[] = { - { FR_CONF_OFFSET_FLAGS("ca_file", CONF_FLAG_FILE_INPUT, rlm_sql_cassandra_t, tls_ca_file) }, - { FR_CONF_OFFSET_FLAGS("certificate_file", CONF_FLAG_FILE_INPUT, rlm_sql_cassandra_t, tls_certificate_file) }, - { FR_CONF_OFFSET_FLAGS("private_key_file", CONF_FLAG_FILE_INPUT, rlm_sql_cassandra_t, tls_private_key_file) }, + { FR_CONF_OFFSET_FLAGS("ca_file", CONF_FLAG_FILE_READABLE, rlm_sql_cassandra_t, tls_ca_file) }, + { FR_CONF_OFFSET_FLAGS("certificate_file", CONF_FLAG_FILE_READABLE, rlm_sql_cassandra_t, tls_certificate_file) }, + { FR_CONF_OFFSET_FLAGS("private_key_file", CONF_FLAG_FILE_READABLE, rlm_sql_cassandra_t, tls_private_key_file) }, { FR_CONF_OFFSET_FLAGS("private_key_password", CONF_FLAG_SECRET, rlm_sql_cassandra_t, tls_private_key_password) }, { FR_CONF_OFFSET("verify_cert", rlm_sql_cassandra_t, tls_verify_cert_str) }, diff --git a/src/modules/rlm_sql/drivers/rlm_sql_mysql/rlm_sql_mysql.c b/src/modules/rlm_sql/drivers/rlm_sql_mysql/rlm_sql_mysql.c index 3b03fc36f2..963dea6d03 100644 --- a/src/modules/rlm_sql/drivers/rlm_sql_mysql/rlm_sql_mysql.c +++ b/src/modules/rlm_sql/drivers/rlm_sql_mysql/rlm_sql_mysql.c @@ -101,12 +101,12 @@ typedef struct { } rlm_sql_mysql_t; static conf_parser_t tls_config[] = { - { FR_CONF_OFFSET_FLAGS("ca_file", CONF_FLAG_FILE_INPUT, rlm_sql_mysql_t, tls_ca_file) }, - { FR_CONF_OFFSET_FLAGS("ca_path", CONF_FLAG_FILE_INPUT, rlm_sql_mysql_t, tls_ca_path) }, - { FR_CONF_OFFSET_FLAGS("certificate_file", CONF_FLAG_FILE_INPUT, rlm_sql_mysql_t, tls_certificate_file) }, - { FR_CONF_OFFSET_FLAGS("private_key_file", CONF_FLAG_FILE_INPUT, rlm_sql_mysql_t, tls_private_key_file) }, - { FR_CONF_OFFSET_FLAGS("crl_file", CONF_FLAG_FILE_INPUT, rlm_sql_mysql_t, tls_crl_file) }, - { FR_CONF_OFFSET_FLAGS("crl_path", CONF_FLAG_FILE_INPUT, rlm_sql_mysql_t, tls_crl_path) }, + { FR_CONF_OFFSET_FLAGS("ca_file", CONF_FLAG_FILE_READABLE, rlm_sql_mysql_t, tls_ca_file) }, + { FR_CONF_OFFSET_FLAGS("ca_path", CONF_FLAG_FILE_READABLE, rlm_sql_mysql_t, tls_ca_path) }, + { FR_CONF_OFFSET_FLAGS("certificate_file", CONF_FLAG_FILE_READABLE, rlm_sql_mysql_t, tls_certificate_file) }, + { FR_CONF_OFFSET_FLAGS("private_key_file", CONF_FLAG_FILE_READABLE, rlm_sql_mysql_t, tls_private_key_file) }, + { FR_CONF_OFFSET_FLAGS("crl_file", CONF_FLAG_FILE_READABLE, rlm_sql_mysql_t, tls_crl_file) }, + { FR_CONF_OFFSET_FLAGS("crl_path", CONF_FLAG_FILE_READABLE, rlm_sql_mysql_t, tls_crl_path) }, /* * MySQL Specific TLS attributes */ diff --git a/src/modules/rlm_sql/drivers/rlm_sql_sqlite/rlm_sql_sqlite.c b/src/modules/rlm_sql/drivers/rlm_sql_sqlite/rlm_sql_sqlite.c index e943f32704..d6ea7fa6f4 100644 --- a/src/modules/rlm_sql/drivers/rlm_sql_sqlite/rlm_sql_sqlite.c +++ b/src/modules/rlm_sql/drivers/rlm_sql_sqlite/rlm_sql_sqlite.c @@ -63,7 +63,7 @@ typedef struct { } rlm_sql_sqlite_t; static const conf_parser_t driver_config[] = { - { FR_CONF_OFFSET_FLAGS("filename", CONF_FLAG_FILE_OUTPUT | CONF_FLAG_REQUIRED, rlm_sql_sqlite_t, filename) }, + { FR_CONF_OFFSET_FLAGS("filename", CONF_FLAG_FILE_WRITABLE | CONF_FLAG_REQUIRED, rlm_sql_sqlite_t, filename) }, { FR_CONF_OFFSET("busy_timeout", rlm_sql_sqlite_t, busy_timeout) }, CONF_PARSER_TERMINATOR }; diff --git a/src/modules/rlm_unbound/rlm_unbound.c b/src/modules/rlm_unbound/rlm_unbound.c index 187d62e7c0..db70c49fe9 100644 --- a/src/modules/rlm_unbound/rlm_unbound.c +++ b/src/modules/rlm_unbound/rlm_unbound.c @@ -68,10 +68,10 @@ typedef struct { * A mapping of configuration file names to internal variables. */ static const conf_parser_t module_config[] = { - { FR_CONF_OFFSET_FLAGS("filename", CONF_FLAG_FILE_INPUT, rlm_unbound_t, filename), .dflt = "${modconfdir}/unbound/default.conf" }, + { FR_CONF_OFFSET_FLAGS("filename", CONF_FLAG_FILE_READABLE, rlm_unbound_t, filename), .dflt = "${modconfdir}/unbound/default.conf" }, { FR_CONF_OFFSET("timeout", rlm_unbound_t, timeout), .dflt = "3000" }, - { FR_CONF_OFFSET_FLAGS("resolvconf", CONF_FLAG_FILE_INPUT, rlm_unbound_t, resolvconf) }, - { FR_CONF_OFFSET_FLAGS("hosts", CONF_FLAG_FILE_INPUT, rlm_unbound_t, hosts) }, + { FR_CONF_OFFSET_FLAGS("resolvconf", CONF_FLAG_FILE_READABLE, rlm_unbound_t, resolvconf) }, + { FR_CONF_OFFSET_FLAGS("hosts", CONF_FLAG_FILE_READABLE, rlm_unbound_t, hosts) }, CONF_PARSER_TERMINATOR };