LCOV - code coverage report
Current view: top level - util - check_and_open.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 42 49 85.7 %
Date: 2016-06-29 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /*
       2             :     SSSD
       3             : 
       4             :     Check file permissions and open file
       5             : 
       6             :     Authors:
       7             :         Sumit Bose <sbose@redhat.com>
       8             : 
       9             :     Copyright (C) 2009 Red Hat
      10             : 
      11             :     This program is free software; you can redistribute it and/or modify
      12             :     it under the terms of the GNU General Public License as published by
      13             :     the Free Software Foundation; either version 3 of the License, or
      14             :     (at your option) any later version.
      15             : 
      16             :     This program is distributed in the hope that it will be useful,
      17             :     but WITHOUT ANY WARRANTY; without even the implied warranty of
      18             :     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19             :     GNU General Public License for more details.
      20             : 
      21             :     You should have received a copy of the GNU General Public License
      22             :     along with this program.  If not, see <http://www.gnu.org/licenses/>.
      23             : */
      24             : 
      25             : #include <sys/types.h>
      26             : #include <sys/stat.h>
      27             : #include <fcntl.h>
      28             : #include <unistd.h>
      29             : 
      30             : #include "util/util.h"
      31             : 
      32             : static errno_t perform_checks(struct stat *stat_buf,
      33             :                               uid_t uid, gid_t gid,
      34             :                               mode_t mode, mode_t mask);
      35             : 
      36           2 : errno_t check_file(const char *filename,
      37             :                    uid_t uid, uid_t gid, mode_t mode, mode_t mask,
      38             :                    struct stat *caller_stat_buf, bool follow_symlink)
      39             : {
      40             :     int ret;
      41             :     struct stat local_stat_buf;
      42             :     struct stat *stat_buf;
      43             : 
      44           2 :     if (caller_stat_buf == NULL) {
      45           2 :         stat_buf = &local_stat_buf;
      46             :     } else {
      47           0 :         stat_buf = caller_stat_buf;
      48             :     }
      49             : 
      50           2 :     if (follow_symlink) {
      51           1 :         ret = stat(filename, stat_buf);
      52             :     } else {
      53           1 :         ret = lstat(filename, stat_buf);
      54             :     }
      55           2 :     if (ret == -1) {
      56           0 :         DEBUG(SSSDBG_TRACE_FUNC, "lstat for [%s] failed: [%d][%s].\n",
      57             :                                  filename, errno, strerror(errno));
      58           0 :         return errno;
      59             :     }
      60             : 
      61           2 :     return perform_checks(stat_buf, uid, gid, mode, mask);
      62             : }
      63             : 
      64          12 : errno_t check_fd(int fd, uid_t uid, gid_t gid,
      65             :                  mode_t mode, mode_t mask,
      66             :                  struct stat *caller_stat_buf)
      67             : {
      68             :     int ret;
      69             :     struct stat local_stat_buf;
      70             :     struct stat *stat_buf;
      71             : 
      72          12 :     if (caller_stat_buf == NULL) {
      73           0 :         stat_buf = &local_stat_buf;
      74             :     } else {
      75          12 :         stat_buf = caller_stat_buf;
      76             :     }
      77             : 
      78          12 :     ret = fstat(fd, stat_buf);
      79          12 :     if (ret == -1) {
      80           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
      81             :               "fstat for [%d] failed: [%d][%s].\n", fd, errno,
      82             :                                                         strerror(errno));
      83           0 :         return errno;
      84             :     }
      85             : 
      86          12 :     return perform_checks(stat_buf, uid, gid, mode, mask);
      87             : }
      88             : 
      89          14 : static errno_t perform_checks(struct stat *stat_buf,
      90             :                               uid_t uid, gid_t gid,
      91             :                               mode_t mode, mode_t mask)
      92             : {
      93             :     mode_t st_mode;
      94             : 
      95          14 :     if (mask) {
      96           0 :         st_mode = stat_buf->st_mode & mask;
      97             :     } else {
      98          14 :         st_mode = stat_buf->st_mode & (S_IFMT|ALLPERMS);
      99             :     }
     100             : 
     101          14 :     if ((mode & S_IFMT) != (st_mode & S_IFMT)) {
     102           2 :         DEBUG(SSSDBG_TRACE_LIBS, "File is not the right type.\n");
     103           2 :         return EINVAL;
     104             :     }
     105             : 
     106          12 :     if ((st_mode & ALLPERMS) != (mode & ALLPERMS)) {
     107           1 :         DEBUG(SSSDBG_TRACE_LIBS,
     108             :               "File has the wrong (bit masked) mode [%.7o], "
     109             :               "expected [%.7o].\n",
     110             :               (st_mode & ALLPERMS), (mode & ALLPERMS));
     111           1 :         return EINVAL;
     112             :     }
     113             : 
     114          11 :     if (uid != (uid_t)(-1) && stat_buf->st_uid != uid) {
     115           1 :         DEBUG(SSSDBG_TRACE_LIBS, "File must be owned by uid [%d].\n", uid);
     116           1 :         return EINVAL;
     117             :     }
     118             : 
     119          10 :     if (gid != (gid_t)(-1) && stat_buf->st_gid != gid) {
     120           1 :         DEBUG(SSSDBG_TRACE_LIBS, "File must be owned by gid [%d].\n", gid);
     121           1 :         return EINVAL;
     122             :     }
     123             : 
     124           9 :     return EOK;
     125             : }
     126             : 
     127          13 : errno_t check_and_open_readonly(const char *filename, int *fd,
     128             :                                 uid_t uid, gid_t gid,
     129             :                                 mode_t mode, mode_t mask)
     130             : {
     131             :     int ret;
     132             :     struct stat stat_buf;
     133             : 
     134          13 :     *fd = open(filename, O_RDONLY);
     135          13 :     if (*fd == -1) {
     136           3 :         DEBUG(SSSDBG_CRIT_FAILURE,
     137             :               "open [%s] failed: [%d][%s].\n", filename, errno,
     138             :                   strerror(errno));
     139           3 :         return errno;
     140             :     }
     141             : 
     142          10 :     ret = check_fd(*fd, uid, gid, mode, mask, &stat_buf);
     143          10 :     if (ret != EOK) {
     144           4 :         close(*fd);
     145           4 :         *fd = -1;
     146           4 :         DEBUG(SSSDBG_CRIT_FAILURE, "check_fd failed.\n");
     147           4 :         return ret;
     148             :     }
     149             : 
     150           6 :     return EOK;
     151             : }
     152             : 

Generated by: LCOV version 1.10