diff options
author | Sumit Bose <sbose@redhat.com> | 2009-09-28 15:50:22 +0200 |
---|---|---|
committer | Stephen Gallagher <sgallagh@redhat.com> | 2009-10-05 10:32:09 -0400 |
commit | b8dede30141cf87fb62aca918d04e411fac82946 (patch) | |
tree | 8a3eccfc11d96162d11e3fac165751fbcdc6f0b9 /server/util/check_and_open.c | |
parent | e3a794633b02411c3d3adc4443e98541f045f41a (diff) | |
download | sssd-b8dede30141cf87fb62aca918d04e411fac82946.tar.gz sssd-b8dede30141cf87fb62aca918d04e411fac82946.tar.bz2 sssd-b8dede30141cf87fb62aca918d04e411fac82946.zip |
add utility call check_and_open_readonly
Use this new utility call to ensure that the config file is safe
to read from.
Diffstat (limited to 'server/util/check_and_open.c')
-rw-r--r-- | server/util/check_and_open.c | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/server/util/check_and_open.c b/server/util/check_and_open.c new file mode 100644 index 00000000..5d5b5799 --- /dev/null +++ b/server/util/check_and_open.c @@ -0,0 +1,89 @@ +/* + SSSD + + Check file permissions and open file + + Authors: + Sumit Bose <sbose@redhat.com> + + 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 <http://www.gnu.org/licenses/>. +*/ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> + +#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; +} + |