From 2268bddadaf2d3aab09f18eea863895c9a01ce7a Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Sun, 18 Jan 2015 22:32:34 +0700 Subject: [PATCH] call rad_mkdir to make the path for the control socket, and modify the default config to place the control socket into a 'control' subdirectory If this works everywhere we should be able to manage control socket permissions using just the filesystem --- raddb/sites-available/control-socket | 2 +- src/include/radiusd.h | 2 +- src/main/command.c | 53 ++++++++++++++-------- src/main/exfile.c | 2 +- src/main/log.c | 2 +- src/main/util.c | 9 ++-- src/modules/rlm_linelog/rlm_linelog.c | 2 +- .../drivers/rlm_sql_sqlite/rlm_sql_sqlite.c | 2 +- 8 files changed, 45 insertions(+), 29 deletions(-) diff --git a/raddb/sites-available/control-socket b/raddb/sites-available/control-socket index 8d06082..2331f30 100644 --- a/raddb/sites-available/control-socket +++ b/raddb/sites-available/control-socket @@ -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 diff --git a/src/include/radiusd.h b/src/include/radiusd.h index 68123fa..40271f4 100644 --- a/src/include/radiusd.h +++ b/src/include/radiusd.h @@ -529,7 +529,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); diff --git a/src/main/command.c b/src/main/command.c index 4f41a9f..b1c08fa 100644 --- a/src/main/command.c +++ b/src/main/command.c @@ -2124,7 +2124,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; @@ -2147,50 +2146,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; } @@ -2202,7 +2217,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", @@ -2216,7 +2230,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. */ { @@ -2262,7 +2276,6 @@ static int command_socket_parse_unix(CONF_SECTION *cs, rad_listen_t *this) } # endif } -#endif return 0; } diff --git a/src/main/exfile.c b/src/main/exfile.c index 94c0362..d8a1acb 100644 --- a/src/main/exfile.c +++ b/src/main/exfile.c @@ -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); diff --git a/src/main/log.c b/src/main/log.c index 4c11f0e..fd51171 100644 --- a/src/main/log.c +++ b/src/main/log.c @@ -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; } diff --git a/src/main/util.c b/src/main/util.c index e9623f3..e154505 100644 --- a/src/main/util.c +++ b/src/main/util.c @@ -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 diff --git a/src/modules/rlm_linelog/rlm_linelog.c b/src/modules/rlm_linelog/rlm_linelog.c index c9e9bb2..e3640e0 100644 --- a/src/modules/rlm_linelog/rlm_linelog.c +++ b/src/modules/rlm_linelog/rlm_linelog.c @@ -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; } diff --git a/src/modules/rlm_sql/drivers/rlm_sql_sqlite/rlm_sql_sqlite.c b/src/modules/rlm_sql/drivers/rlm_sql_sqlite/rlm_sql_sqlite.c index ffd76b2..88ef187 100644 --- a/src/modules/rlm_sql/drivers/rlm_sql_sqlite/rlm_sql_sqlite.c +++ b/src/modules/rlm_sql/drivers/rlm_sql_sqlite/rlm_sql_sqlite.c @@ -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)); -- 2.1.4