}
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),
{ 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
};
/*
* 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 }},
/*
* 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 }},
/*
/*
* 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
*/
RCSID("$Id$")
+#include <sys/errno.h>
+
#include <freeradius-devel/server/cf_file.h>
#include <freeradius-devel/server/cf_priv.h>
+#include <freeradius-devel/server/cf_util.h>
#include <freeradius-devel/server/log.h>
#include <freeradius-devel/server/tmpl.h>
#include <freeradius-devel/server/util.h>
#include <freeradius-devel/util/file.h>
#include <freeradius-devel/util/misc.h>
#include <freeradius-devel/util/perm.h>
+#include <freeradius-devel/util/strerror.h>
#include <freeradius-devel/util/skip.h>
#include <freeradius-devel/util/md5.h>
-
#ifdef HAVE_DIRENT_H
# include <dirent.h>
#endif
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"));
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;
}
/*
* 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
*/
if (!fr_rb_insert(tree, file)) talloc_free(file);
- return true;
+ return CF_FILE_OK;
}
/*
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)
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
}
* @copyright 2000 Miquel van Smoorenburg (miquels@cistron.nl)
* @copyright 2000 Alan DeKok (aland@freeradius.org)
*/
+#include "lib/util/syserror.h"
+#include <sys/errno.h>
+#include <sys/fcntl.h>
RCSID("$Id$")
#include <string.h>
* 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);
* - ``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
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;
}
//!< (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)
#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)
#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)
* 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
.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,
{ 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) },
#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), },
{ 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" },
{ 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) },
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 },
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) } ,
} 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
* 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) },
};
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
};
* 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
};
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
};
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" },
};
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
};
* 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},
* 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
};
} 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 = ":" },
* 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 },
};
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) },
} 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
*/
} 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
};
* 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
};