call rad_mkdir to make the path for the control socket, and modify the default config...
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Sun, 18 Jan 2015 15:32:34 +0000 (22:32 +0700)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Sun, 18 Jan 2015 15:33:21 +0000 (22:33 +0700)
If this works everywhere we should be able to manage control socket permissions using just the filesystem

raddb/sites-available/control-socket
src/include/radiusd.h
src/main/command.c
src/main/exfile.c
src/main/log.c
src/main/util.c
src/modules/rlm_linelog/rlm_linelog.c
src/modules/rlm_sql/drivers/rlm_sql_sqlite/rlm_sql_sqlite.c

index 8d06082..2331f30 100644 (file)
@@ -34,7 +34,7 @@ listen {
        #  no permissions for "other" users.  These permissions form
        #  minimal security, and should not be relied on.
        #
-       socket = ${run_dir}/${name}.sock
+       socket = ${run_dir}/control/${name}.sock
 
        #
        #  The following two parameters perform authentication and
index 1cacad9..58ed52b 100644 (file)
@@ -544,7 +544,7 @@ int         log_err (char *);
 /* util.c */
 #define MEM(x) if (!(x)) { ERROR("%s[%u] OUT OF MEMORY", __FILE__, __LINE__); _fr_exit_now(__FILE__, __LINE__, 1); }
 void (*reset_signal(int signo, void (*func)(int)))(int);
-int            rad_mkdir(char *directory, mode_t mode);
+int            rad_mkdir(char *directory, mode_t mode, uid_t uid, gid_t gid);
 size_t         rad_filename_escape(UNUSED REQUEST *request, char *out, size_t outlen,
                                    char const *in, UNUSED void *arg);
 ssize_t                rad_filename_unescape(char *out, size_t outlen, char const *in, size_t inlen);
index 4162984..ea09645 100644 (file)
@@ -2133,7 +2133,6 @@ static int command_socket_parse_unix(CONF_SECTION *cs, rad_listen_t *this)
        sock->copy = NULL;
        if (sock->path) sock->copy = talloc_typed_strdup(sock, sock->path);
 
-#if defined(HAVE_GETPEEREID) || defined (SO_PEERCRED)
        if (sock->uid_name) {
                struct passwd *pwd;
 
@@ -2156,50 +2155,66 @@ static int command_socket_parse_unix(CONF_SECTION *cs, rad_listen_t *this)
                sock->gid = -1;
        }
 
-#else  /* can't get uid or gid of connecting user */
-
-       if (sock->uid_name || sock->gid_name) {
-               ERROR("System does not support uid or gid authentication for sockets");
-               return -1;
-       }
-
-#endif
-
        if (!sock->mode_name) {
                sock->co.mode = FR_READ;
        } else {
                sock->co.mode = fr_str2int(mode_names, sock->mode_name, 0);
                if (!sock->co.mode) {
-                       ERROR("Invalid mode name \"%s\"",
-                              sock->mode_name);
+                       ERROR("Invalid mode name \"%s\"", sock->mode_name);
                        return -1;
                }
        }
 
        /*
+        *      Ensure the path to the control socket has been created.
+        */
+       {
+               char *dir, *buff;
+               int perm = 0;
+
+               buff = talloc_strdup(cs, sock->path);
+               if (!buff) return -1;
+               dir = dirname(buff);
+
+               if ((sock->uid == (uid_t) -1) && (sock->gid == (gid_t) -1)) {
+                       perm = 0770;    /* World readable/writable probably dangerous */
+               } else {
+                       if (sock->uid != (uid_t) -1) {
+                               perm |= 0700;
+                       }
+                       if (sock->gid != (gid_t) -1) {
+                               perm |= 0070;
+                       }
+               }
+
+               fr_suid_up();
+               rad_mkdir(dir, perm, sock->uid, sock->gid);
+               fr_suid_down();
+
+               talloc_free(buff);
+       }
+
+       /*
         *      FIXME: check for absolute pathnames?
         *      check for uid/gid on the other end...
         */
-
        this->fd = fr_server_domain_socket(sock->path);
        if (this->fd < 0) {
                return -1;
        }
 
-#if defined(HAVE_GETPEEREID) || defined (SO_PEERCRED)
        /*
         *      Don't chown it from (possibly) non-root to root.
         *      Do chown it from (possibly) root to non-root.
         */
-       if ((sock->uid != (uid_t) -1) || (sock->gid != (gid_t) -1)) {
+       if ((sock->uid == (uid_t) -1) && (sock->gid != (gid_t) -1)) {
                struct stat buf;
 
                /*
                 *      Don't do chown if it's already owned by us.
                 */
                if (fstat(this->fd, &buf) < 0) {
-                       ERROR("Failed reading %s: %s",
-                             sock->path, fr_syserror(errno));
+                       ERROR("Failed reading %s: %s", sock->path, fr_syserror(errno));
                        return -1;
                }
 
@@ -2211,7 +2226,6 @@ static int command_socket_parse_unix(CONF_SECTION *cs, rad_listen_t *this)
                 */
 #  ifdef __linux__
                if ((buf.st_uid != sock->uid) || (buf.st_gid != sock->gid)) {
-
                        fr_suid_up();
                        if (fchown(this->fd, sock->uid, sock->gid) < 0) {
                                ERROR("Failed setting ownership of \"%s\" to (%d, %d): %s",
@@ -2225,7 +2239,7 @@ static int command_socket_parse_unix(CONF_SECTION *cs, rad_listen_t *this)
                /*
                 *      We don't want to arbitrarily change directory
                 *      permissions, especially if we don't know we created
-                *      the directory, so just error out and get the admin
+                *      the directory, so just error out and get the user
                 *      to change the permissions.
                 */
                {
@@ -2271,7 +2285,6 @@ static int command_socket_parse_unix(CONF_SECTION *cs, rad_listen_t *this)
                }
 #  endif
        }
-#endif
 
        return 0;
 }
index 94c0362..d8a1acb 100644 (file)
@@ -230,7 +230,7 @@ int exfile_open(exfile_t *ef, char const *filename, mode_t permissions, bool app
                if ((dirperm & 0060) != 0) dirperm |= 0010;
                if ((dirperm & 0006) != 0) dirperm |= 0001;
 
-               if (rad_mkdir(dir, dirperm) < 0) {
+               if (rad_mkdir(dir, dirperm, -1, -1) < 0) {
                        fr_strerror_printf("Failed to create directory %s: %s",
                                           dir, strerror(errno));
                        talloc_free(dir);
index 4c11f0e..fd51171 100644 (file)
@@ -594,7 +594,7 @@ void vradlog_request(log_type_t type, log_lvl_t lvl, REQUEST *request, char cons
                p = strrchr(buffer, FR_DIR_SEP);
                if (p) {
                        *p = '\0';
-                       if (rad_mkdir(buffer, S_IRWXU) < 0) {
+                       if (rad_mkdir(buffer, S_IRWXU, -1, -1) < 0) {
                                ERROR("Failed creating %s: %s", buffer, fr_syserror(errno));
                                return;
                        }
index 68015e7..1328901 100644 (file)
@@ -197,7 +197,7 @@ void *request_data_reference(REQUEST *request, void *unique_ptr, int unique_int)
  *     This is so that IF an error is returned, the 'directory' ptr
  *     points to the name of the file which caused the error.
  */
-int rad_mkdir(char *directory, mode_t mode)
+int rad_mkdir(char *directory, mode_t mode, uid_t uid, gid_t gid)
 {
        int rcode;
        char *p;
@@ -228,7 +228,7 @@ int rad_mkdir(char *directory, mode_t mode)
                if (!p || (p == directory)) return -1;
 
                *p = '\0';
-               rcode = rad_mkdir(directory, mode);
+               rcode = rad_mkdir(directory, mode, uid, gid);
                if (rcode < 0) return rcode;
 
                /*
@@ -243,7 +243,10 @@ int rad_mkdir(char *directory, mode_t mode)
        /*
         *      Set the permissions on the created directory.
         */
-       return chmod(directory, mode);
+       rcode = chmod(directory, mode);
+       if (rcode < 0) return rcode;
+       if ((uid != (uid_t)-1) || (gid != (gid_t)-1)) rcode = chown(directory, uid, gid);
+       return rcode;
 }
 
 /** Escapes the raw string such that it should be safe to use as part of a file path
index c9e9bb2..e3640e0 100644 (file)
@@ -265,7 +265,7 @@ static rlm_rcode_t CC_HINT(nonnull) mod_do_linelog(void *instance, REQUEST *requ
                p = strrchr(path, '/');
                if (p) {
                        *p = '\0';
-                       if (rad_mkdir(path, 0700) < 0) {
+                       if (rad_mkdir(path, 0700, -1, -1) < 0) {
                                RERROR("rlm_linelog: Failed to create directory %s: %s", path, fr_syserror(errno));
                                return RLM_MODULE_FAIL;
                        }
index 4073724..ccdcad9 100644 (file)
@@ -278,7 +278,7 @@ static int mod_instantiate(CONF_SECTION *conf, rlm_sql_config_t *config)
                        MEM(buff = talloc_typed_strdup(conf, driver->filename));
                }
 
-               ret = rad_mkdir(buff, 0700);
+               ret = rad_mkdir(buff, 0700, -1, -1);
                talloc_free(buff);
                if (ret < 0) {
                        ERROR("rlm_sql_sqlite: Failed creating directory for SQLite database: %s", fr_syserror(errno));