From b8dede30141cf87fb62aca918d04e411fac82946 Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Mon, 28 Sep 2009 15:50:22 +0200 Subject: add utility call check_and_open_readonly Use this new utility call to ensure that the config file is safe to read from. --- server/util/check_and_open.c | 89 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 server/util/check_and_open.c (limited to 'server/util/check_and_open.c') diff --git a/server/util/check_and_open.c b/server/util/check_and_open.c new file mode 100644 index 000000000..5d5b57993 --- /dev/null +++ b/server/util/check_and_open.c @@ -0,0 +1,89 @@ +/* + SSSD + + Check file permissions and open file + + Authors: + Sumit Bose + + Copyright (C) 2009 Red Hat + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include +#include +#include +#include + +#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) +{ + int ret; + struct stat stat_buf; + struct stat fd_stat_buf; + + *fd = -1; + + 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)); + return EINVAL; + } + + if ((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)); + 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)); + return EINVAL; + } + + *fd = open(filename, O_RDONLY); + if (*fd == -1) { + DEBUG(1, ("open [%s] failed: [%d][%s].\n", filename, errno, + strerror(errno))); + return errno; + } + + ret = fstat(*fd, &fd_stat_buf); + if (ret == -1) { + DEBUG(1, ("fstat for [%s] failed: [%d][%s].\n", filename, errno, + strerror(errno))); + return errno; + } + + if (stat_buf.st_dev != fd_stat_buf.st_dev || + stat_buf.st_ino != fd_stat_buf.st_ino) { + DEBUG(1, ("File [%s] was modified between lstat and open.\n", filename)); + close(*fd); + *fd = -1; + return EIO; + } + + return EOK; +} + -- cgit