]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Add additional file check flags
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Thu, 17 Jul 2025 02:19:55 +0000 (20:19 -0600)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Thu, 17 Jul 2025 02:20:11 +0000 (20:20 -0600)
Add specific flag for unix sockets

26 files changed:
src/lib/curl/base.c
src/lib/kafka/base.c
src/lib/ldap/conf.c
src/lib/server/cf_file.c
src/lib/server/cf_file.h
src/lib/server/cf_parse.c
src/lib/server/cf_parse.h
src/lib/server/main_config.c
src/lib/tls/conf.c
src/listen/cron/cron.c
src/listen/cron/proto_cron_crontab.c
src/listen/load/proto_load_step.c
src/modules/rlm_attr_filter/rlm_attr_filter.c
src/modules/rlm_csv/rlm_csv.c
src/modules/rlm_files/rlm_files.c
src/modules/rlm_isc_dhcp/rlm_isc_dhcp.c
src/modules/rlm_linelog/rlm_linelog.c
src/modules/rlm_logtee/rlm_logtee.c
src/modules/rlm_lua/rlm_lua.c
src/modules/rlm_mruby/rlm_mruby.c
src/modules/rlm_passwd/rlm_passwd.c
src/modules/rlm_perl/rlm_perl.c
src/modules/rlm_sql/drivers/rlm_sql_cassandra/rlm_sql_cassandra.c
src/modules/rlm_sql/drivers/rlm_sql_mysql/rlm_sql_mysql.c
src/modules/rlm_sql/drivers/rlm_sql_sqlite/rlm_sql_sqlite.c
src/modules/rlm_unbound/rlm_unbound.c

index 16bee413956a7252e2b5278b4e57ddc37a7d3ead..6230cd5d44a72eb344f4a346fde2bf2a35fc3531 100644 (file)
@@ -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
 };
index 1c5b31927d4e569cd934a3f2d567d2a70091105c..493b74b2873cb44018b917aa64b842c59380b18e 100644 (file)
@@ -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 }},
 
        /*
index 51c617111b779c31a41609a5fe9c7aa32ba7d039..9dea5a2117a7ea0a5bf0d7918612839f7feaf491 100644 (file)
@@ -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
index 36edb1e991e5d3ced0d1e0c11a6b0e01cf67d693..ddfe121a4b4842e00017ec2fdf65b6c974872f47 100644 (file)
  */
 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>
@@ -40,10 +43,10 @@ RCSID("$Id$")
 #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
@@ -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)
index 3fd9fce54853c2297bdd76009c3a82c067c41a7c..6253120b2d3966a1c3efa25fe3819986867d44e5 100644 (file)
@@ -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
 }
index ca0a1dc7502eac50d48b49c8c1c60e2c9611eba0..a8e56e79070ae16d0cdb91327cc0d5f881a48a38 100644 (file)
@@ -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 <sys/errno.h>
+#include <sys/fcntl.h>
 RCSID("$Id$")
 
 #include <string.h>
@@ -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;
        }
 
index aada8f866edabf5329af3a20783f7f5620805235..2f501b3ddf9e2f0584053e9ef411e91f8dc9d26b 100644 (file)
@@ -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)
index 62becaa5f0ec0cc740d3a21fd455609fe1068b93..81aa1308ab5746c03904a737c61c2b3a3d69f16e 100644 (file)
@@ -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
index 7f76cb6286d31d1c62acdb37c31a556a3586a580..c3e41ad0dd02894da37975b56d7ff1d94437eb73 100644 (file)
@@ -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" },
index 786073cf8c8fdc98667a68ed1c356acd9afaf890..baeaa8eb5d2f81b8a5c7b1bf6b98571bfd2da8d6 100644 (file)
@@ -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) },
 
index 55878dc2c0aecf8fcdc90d87b8dfb89a7689c0c4..b2f11508040cc5f1b4059be6bc47624c16a4314e 100644 (file)
@@ -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 },
index 9fa0aa78f90516a715e94fb74d1e02a93eec791b..2b8c436ef7a65c480c2af8f32722b4e62dddfb60 100644 (file)
@@ -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) } ,
index bfee1e4fcb4f2a2fc4b9621c00deecd4642aeceb..0e74b28cc4d25ac110bb6cd3d020aa6b04ffb89c 100644 (file)
@@ -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
index cf58efb27d846a0f7f4f25d83777f50223ecd0e2..1bc5ed86ba5bf4c1e8abdb9a4fc06cb2a59e7616 100644 (file)
@@ -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) },
index f8ffb90dc1c68e8f745b89355254c8b95e9dfbf2..51459cee114cb1c4f6524eca88268e2f8addbbb5 100644 (file)
@@ -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
 };
index c66c4ddc2cc40f765f0ee4b5ba2c726bd1b415fe..d66026bb34b10fd66f415238c8e05bb18d906b8a 100644 (file)
@@ -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
index ac086702923bd28db6773e7639668082dec06668..d31665ef2c1f107a92b03e8d560fb20915cdf167 100644 (file)
@@ -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
 };
 
index f89b7cbbd7b4b32fed78fe332d5119d28672ce1c..6d35e6b9b387b9da4ef6028a4c2353f60d0e53ab 100644 (file)
@@ -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
 };
 
index 4d1e4c096316291eff314ec0790e9c1bb8b3aae2..3fc7643ef6719ab10dc4b661ece44de726940eb1 100644 (file)
@@ -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},
index 54e131110274126e951f0ee0f11d7f7ded62a5a9..ac645cd7de6f08e5fa15ca10ed7551f60f7ded1e 100644 (file)
@@ -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
 };
index 8d2ee376a9c0a441db207d6f515f3c84d955e62a..753b0ee33dd0323f56aea3e3ba4843e889a9ab46 100644 (file)
@@ -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 = ":" },
 
index bdc32e5faae45a8bb3d58c3fabf64b1486629fef..d9248469ad551ce1d29be288a17464ed36bccce9 100644 (file)
@@ -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 },
 
index ed612f727c9eabcd9a25350fbb6df08c30cb254e..e7caecf5f48496206b06430949228b83dc9f974c 100644 (file)
@@ -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) },
index 3b03fc36f2697f5a06011494f27048cf359f05a9..963dea6d03a7712f3b6febcbe5bc33eb3fde35fb 100644 (file)
@@ -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
         */
index e943f32704976db45162355cd3ce1c5260efd3e5..d6ea7fa6f4cc7bf2085b468be3f9ee129367e3d9 100644 (file)
@@ -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
 };
index 187d62e7c00af55bd4587ff9231c9dce584b1b8f..db70c49fe939eee164bef30bce36017526f68370 100644 (file)
@@ -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
 };