From 7b9727184150335ac5e3824a92e0109258a60f45 Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Tue, 16 Feb 2010 15:53:56 +0100 Subject: [PATCH 1/2] Check and set permissions on SBUS sockets --- src/confdb/confdb_setup.c | 3 +- src/sbus/sbus_client.c | 13 ++++++ src/sbus/sssd_dbus_server.c | 27 ++++++++++++ src/tests/check_and_open-tests.c | 17 ++++---- src/tests/files-tests.c | 2 +- src/util/check_and_open.c | 87 +++++++++++++++++++++++++++++++------ src/util/util.h | 17 +++++++- 7 files changed, 141 insertions(+), 25 deletions(-) diff --git a/src/confdb/confdb_setup.c b/src/confdb/confdb_setup.c index 3c10c06..77cd5f9 100644 --- a/src/confdb/confdb_setup.c +++ b/src/confdb/confdb_setup.c @@ -285,7 +285,8 @@ int confdb_init_db(const char *config_file, struct confdb_ctx *cdb) tmp_ctx = talloc_new(cdb); if (tmp_ctx == NULL) return ENOMEM; - ret = check_and_open_readonly(config_file, &fd, 0, 0, (S_IRUSR|S_IWUSR)); + ret = check_and_open_readonly(config_file, &fd, 0, 0, (S_IRUSR|S_IWUSR), + CHECK_REG); if (ret != EOK) { DEBUG(1, ("Permission check on config file failed.\n")); talloc_zfree(tmp_ctx); diff --git a/src/sbus/sbus_client.c b/src/sbus/sbus_client.c index df5c071..1c5c1b2 100644 --- a/src/sbus/sbus_client.c +++ b/src/sbus/sbus_client.c @@ -33,12 +33,25 @@ int sbus_client_init(TALLOC_CTX *mem_ctx, { struct sbus_connection *conn = NULL; int ret; + char *filename; /* Validate input */ if (server_address == NULL) { return EINVAL; } + filename = strchr(server_address, '/'); + if (filename == NULL) { + DEBUG(1, ("Unexpected dbus address [%s].\n", server_address)); + return EIO; + } + + ret = check_file(filename, 0, 0, 0600, CHECK_SOCK, NULL); + if (ret != EOK) { + DEBUG(1, ("check_file failed for [%s].\n", filename)); + return EIO; + } + ret = sbus_new_connection(mem_ctx, ev, server_address, intf, &conn); if (ret != EOK) { goto fail; diff --git a/src/sbus/sssd_dbus_server.c b/src/sbus/sssd_dbus_server.c index a859cba..98c308e 100644 --- a/src/sbus/sssd_dbus_server.c +++ b/src/sbus/sssd_dbus_server.c @@ -19,6 +19,9 @@ along with this program. If not, see . */ #include +#include +#include + #include "tevent.h" #include "util/util.h" #include "dbus/dbus.h" @@ -95,6 +98,9 @@ int sbus_new_server(TALLOC_CTX *mem_ctx, DBusError dbus_error; dbus_bool_t dbret; char *tmp; + int ret; + char *filename; + struct stat stat_buf; *_server = NULL; @@ -108,6 +114,27 @@ int sbus_new_server(TALLOC_CTX *mem_ctx, return EIO; } + filename = strchr(address, '/'); + if (filename == NULL) { + DEBUG(1, ("Unexpected dbus address [%s].\n", address)); + return EIO; + } + + ret = check_file(filename, 0, 0, -1, CHECK_SOCK, &stat_buf); + if (ret != EOK) { + DEBUG(1, ("check_file failed for [%s].\n", filename)); + return EIO; + } + + if ((stat_buf.st_mode & ~S_IFMT) != 0600) { + ret = chmod(filename, 0600); + if (ret != EOK) { + DEBUG(1, ("chmod failed for [%s]: [%d][%s].\n", filename, errno, + strerror(errno))); + return EIO; + } + } + tmp = dbus_server_get_address(dbus_server); DEBUG(3, ("D-BUS Server listening on %s\n", tmp)); free(tmp); diff --git a/src/tests/check_and_open-tests.c b/src/tests/check_and_open-tests.c index b0d638b..32cf09f 100644 --- a/src/tests/check_and_open-tests.c +++ b/src/tests/check_and_open-tests.c @@ -74,7 +74,7 @@ START_TEST(test_wrong_filename) { int ret; - ret = check_and_open_readonly("/bla/bla/bla", &fd, uid, gid, mode); + ret = check_and_open_readonly("/bla/bla/bla", &fd, uid, gid, mode, CHECK_REG); fail_unless(ret == ENOENT, "check_and_open_readonly succeeded on non-existing file"); fail_unless(fd == -1, "check_and_open_readonly file descriptor not -1"); @@ -99,7 +99,7 @@ START_TEST(test_symlink) ret = symlink(filename, newpath); fail_unless(ret == 0, "symlink failed [%d][%s]", ret, strerror(ret)); - ret = check_and_open_readonly(newpath, &fd, uid, gid, mode); + ret = check_and_open_readonly(newpath, &fd, uid, gid, mode, CHECK_REG); unlink(newpath); fail_unless(ret == EINVAL, "check_and_open_readonly succeeded on symlink"); @@ -111,7 +111,7 @@ START_TEST(test_not_regular_file) { int ret; - ret = check_and_open_readonly("/dev/null", &fd, uid, gid, mode); + ret = check_and_open_readonly("/dev/null", &fd, uid, gid, mode, CHECK_REG); fail_unless(ret == EINVAL, "check_and_open_readonly succeeded on non-regular file"); fail_unless(fd == -1, "check_and_open_readonly file descriptor not -1"); @@ -122,7 +122,7 @@ START_TEST(test_wrong_uid) { int ret; - ret = check_and_open_readonly(filename, &fd, uid+1, gid, mode); + ret = check_and_open_readonly(filename, &fd, uid+1, gid, mode, CHECK_REG); fail_unless(ret == EINVAL, "check_and_open_readonly succeeded with wrong uid"); fail_unless(fd == -1, "check_and_open_readonly file descriptor not -1"); @@ -133,7 +133,7 @@ START_TEST(test_wrong_gid) { int ret; - ret = check_and_open_readonly(filename, &fd, uid, gid+1, mode); + ret = check_and_open_readonly(filename, &fd, uid, gid+1, mode, CHECK_REG); fail_unless(ret == EINVAL, "check_and_open_readonly succeeded with wrong gid"); fail_unless(fd == -1, "check_and_open_readonly file descriptor not -1"); @@ -144,7 +144,8 @@ START_TEST(test_wrong_permission) { int ret; - ret = check_and_open_readonly(filename, &fd, uid, gid, (mode|S_IWOTH)); + ret = check_and_open_readonly(filename, &fd, uid, gid, (mode|S_IWOTH), + CHECK_REG); fail_unless(ret == EINVAL, "check_and_open_readonly succeeded with wrong mode"); fail_unless(fd == -1, "check_and_open_readonly file descriptor not -1"); @@ -155,7 +156,7 @@ START_TEST(test_ok) { int ret; - ret = check_and_open_readonly(filename, &fd, uid, gid, mode); + ret = check_and_open_readonly(filename, &fd, uid, gid, mode, CHECK_REG); fail_unless(ret == EOK, "check_and_open_readonly failed"); fail_unless(fd >= 0, @@ -169,7 +170,7 @@ START_TEST(test_write) ssize_t size; errno_t my_errno; - ret = check_and_open_readonly(filename, &fd, uid, gid, mode); + ret = check_and_open_readonly(filename, &fd, uid, gid, mode, CHECK_REG); fail_unless(ret == EOK, "check_and_open_readonly failed"); fail_unless(fd >= 0, diff --git a/src/tests/files-tests.c b/src/tests/files-tests.c index 90b9717..2ebe659 100644 --- a/src/tests/files-tests.c +++ b/src/tests/files-tests.c @@ -183,7 +183,7 @@ START_TEST(test_simple_copy) fail_unless(ret == 0, "destination directory not there\n"); tmp = talloc_asprintf(test_ctx, "%s/bar", dst_path); - ret = check_and_open_readonly(tmp, &fd, uid, gid, 0700); + ret = check_and_open_readonly(tmp, &fd, uid, gid, 0700, CHECK_REG); fail_unless(ret == EOK, "Cannot open %s\n"); close(fd); talloc_free(tmp); diff --git a/src/util/check_and_open.c b/src/util/check_and_open.c index 5d5b579..d010670 100644 --- a/src/util/check_and_open.c +++ b/src/util/check_and_open.c @@ -29,39 +29,98 @@ #include "util/util.h" -errno_t check_and_open_readonly(const char *filename, int *fd, const uid_t uid, - const gid_t gid, const mode_t mode) +errno_t check_file(const char *filename, const int uid, const int gid, + const int mode, enum check_file_type type, + struct stat *caller_stat_buf) { int ret; - struct stat stat_buf; - struct stat fd_stat_buf; - - *fd = -1; + struct stat local_stat_buf; + struct stat *stat_buf; + bool type_check; + + if (caller_stat_buf == NULL) { + stat_buf = &local_stat_buf; + } else { + stat_buf = caller_stat_buf; + } - ret = lstat(filename, &stat_buf); + ret = lstat(filename, stat_buf); if (ret == -1) { DEBUG(1, ("lstat for [%s] failed: [%d][%s].\n", filename, errno, strerror(errno))); return errno; } - if (!S_ISREG(stat_buf.st_mode)) { - DEBUG(1, ("File [%s] is not a regular file.\n", filename)); + switch (type) { + case CHECK_DONT_CHECK_FILE_TYPE: + type_check = true; + break; + case CHECK_REG: + type_check = S_ISREG(stat_buf->st_mode); + break; + case CHECK_DIR: + type_check = S_ISDIR(stat_buf->st_mode); + break; + case CHECK_CHR: + type_check = S_ISCHR(stat_buf->st_mode); + break; + case CHECK_BLK: + type_check = S_ISBLK(stat_buf->st_mode); + break; + case CHECK_FIFO: + type_check = S_ISFIFO(stat_buf->st_mode); + break; + case CHECK_LNK: + type_check = S_ISLNK(stat_buf->st_mode); + break; + case CHECK_SOCK: + type_check = S_ISSOCK(stat_buf->st_mode); + break; + default: + DEBUG(1, ("Unsupprted file type.\n")); + return EINVAL; + } + + if (!type_check) { + DEBUG(1, ("File [%s] is not the right type.\n", filename)); return EINVAL; } - if ((stat_buf.st_mode & ~S_IFMT) != mode) { + if (mode >= 0 && (stat_buf->st_mode & ~S_IFMT) != mode) { DEBUG(1, ("File [%s] has the wrong mode [%.7o], expected [%.7o].\n", - filename, (stat_buf.st_mode & ~S_IFMT), mode)); + filename, (stat_buf->st_mode & ~S_IFMT), mode)); + return EINVAL; + } + + if (uid >= 0 && stat_buf->st_uid != uid) { + DEBUG(1, ("File [%s] must be owned by uid [%d].\n", filename, uid)); return EINVAL; } - if (stat_buf.st_uid != uid || stat_buf.st_gid != gid) { - DEBUG(1, ("File [%s] must be owned by uid [%d] and gid [%d].\n", - filename, uid, gid)); + if (gid >= 0 && stat_buf->st_gid != gid) { + DEBUG(1, ("File [%s] must be owned by gid [%d].\n", filename, gid)); return EINVAL; } + return EOK; +} + +errno_t check_and_open_readonly(const char *filename, int *fd, const uid_t uid, + const gid_t gid, const mode_t mode, + enum check_file_type type) +{ + int ret; + struct stat stat_buf; + struct stat fd_stat_buf; + + *fd = -1; + + ret = check_file(filename, uid, gid, mode, type, &stat_buf); + if (ret != EOK) { + DEBUG(1, ("check_file failed.\n")); + return ret; + } + *fd = open(filename, O_RDONLY); if (*fd == -1) { DEBUG(1, ("open [%s] failed: [%d][%s].\n", filename, errno, diff --git a/src/util/util.h b/src/util/util.h index 945e20d..5d2dff2 100644 --- a/src/util/util.h +++ b/src/util/util.h @@ -33,6 +33,7 @@ #include #include #include +#include #include "config.h" @@ -247,8 +248,22 @@ int sss_parse_name(TALLOC_CTX *memctx, int backup_file(const char *src, int dbglvl); /* from check_and_open.c */ +enum check_file_type { + CHECK_DONT_CHECK_FILE_TYPE = -1, + CHECK_REG, + CHECK_DIR, + CHECK_CHR, + CHECK_BLK, + CHECK_FIFO, + CHECK_LNK, + CHECK_SOCK +}; +errno_t check_file(const char *filename, const int uid, const int gid, + const int mode, enum check_file_type type, + struct stat *caller_stat_buf); errno_t check_and_open_readonly(const char *filename, int *fd, const uid_t uid, - const gid_t gid, const mode_t mode); + const gid_t gid, const mode_t mode, + enum check_file_type type); /* from util.c */ int split_on_separator(TALLOC_CTX *mem_ctx, const char *str, -- 1.6.6