diff --git a/conf.c b/conf.c index 9ebb268..c1b62cd 100644 --- a/conf.c +++ b/conf.c @@ -1261,8 +1261,26 @@ parse_include(char *line) void CNF_CreateDirs(uid_t uid, gid_t gid) { + char *dir; + UTI_CreateDirAndParents(logdir, 0755, uid, gid); UTI_CreateDirAndParents(dumpdir, 0755, uid, gid); + + /* Create a directory for the Unix domain command socket */ + if (bind_cmd_path[0]) { + dir = UTI_PathToDir(bind_cmd_path); + UTI_CreateDirAndParents(dir, 0770, uid, gid); + + /* Check the permissions and owner/group in case the directory already + existed. It MUST NOT be accessible by others as permissions on Unix + domain sockets are ignored on some systems (e.g. Solaris). */ + if (!UTI_CheckDirPermissions(dir, 0770, uid, gid)) { + LOG(LOGS_WARN, LOGF_Configure, "Disabled command socket %s", bind_cmd_path); + bind_cmd_path[0] = '\0'; + } + + Free(dir); + } } /* ================================================== */ diff --git a/util.c b/util.c index 08d3110..f03ebaf 100644 --- a/util.c +++ b/util.c @@ -897,6 +897,27 @@ UTI_SetQuitSignalsHandler(void (*handler)(int)) /* ================================================== */ +char * +UTI_PathToDir(const char *path) +{ + char *dir, *slash; + + slash = strrchr(path, '/'); + + if (!slash) + return Strdup("."); + + if (slash == path) + return Strdup("/"); + + dir = Malloc(slash - path + 1); + snprintf(dir, slash - path + 1, "%s", path); + + return dir; +} + +/* ================================================== */ + static int create_dir(char *p, mode_t mode, uid_t uid, gid_t gid) { @@ -986,3 +1007,33 @@ UTI_CreateDirAndParents(const char *path, mode_t mode, uid_t uid, gid_t gid) Free(p); return 1; } + +/* ================================================== */ + +int +UTI_CheckDirPermissions(const char *path, mode_t perm, uid_t uid, gid_t gid) +{ + struct stat buf; + + if (stat(path, &buf)) { + LOG(LOGS_ERR, LOGF_Util, "Could not access %s : %s", path, strerror(errno)); + return 0; + } + + if (!S_ISDIR(buf.st_mode)) { + LOG(LOGS_ERR, LOGF_Util, "%s is not directory", path); + return 0; + } + + if ((buf.st_mode & 0777) & ~perm) { + LOG(LOGS_ERR, LOGF_Util, "Wrong permissions on %s", path); + return 0; + } + + if (buf.st_uid != uid || buf.st_gid != gid) { + LOG(LOGS_ERR, LOGF_Util, "Wrong owner/group of %s", path); + return 0; + } + + return 1; +} diff --git a/util.h b/util.h index 4b4efe4..360fced 100644 --- a/util.h +++ b/util.h @@ -130,10 +130,17 @@ extern int UTI_DecodePasswordFromText(char *key); extern int UTI_SetQuitSignalsHandler(void (*handler)(int)); +/* Get directory (as an allocated string) for a path */ +extern char *UTI_PathToDir(const char *path); + /* Create a directory with a specified mode (umasked) and set its uid/gid (if not 0). Create also any parent directories that don't exist with mode 755 and default uid/gid. Returns 1 if created or already exists (even with different mode/uid/gid), 0 otherwise. */ extern int UTI_CreateDirAndParents(const char *path, mode_t mode, uid_t uid, gid_t gid); +/* Check if a directory is secure. It must not have other than the specified + permissions and its uid/gid must match the specified values. */ +extern int UTI_CheckDirPermissions(const char *path, mode_t perm, uid_t uid, gid_t gid); + #endif /* GOT_UTIL_H */