Branch data 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 : : const int uid, const int gid,
34 : : const int mode, enum check_file_type type);
35 : :
36 : 2 : errno_t check_file(const char *filename, const int uid, const int gid,
37 : : const int mode, enum check_file_type type,
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 : : stat_buf = &local_stat_buf;
46 : : } else {
47 : 0 : stat_buf = caller_stat_buf;
48 : : }
49 : :
50 [ + + ]: 2 : ret = follow_symlink ? stat(filename, stat_buf) : \
51 : : lstat(filename, stat_buf);
52 [ - + ]: 2 : if (ret == -1) {
53 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_TRACE_FUNC, ("lstat for [%s] failed: [%d][%s].\n", filename, errno,
[ # # ][ # # ]
[ # # ]
54 : : strerror(errno)));
55 : 0 : return errno;
56 : : }
57 : :
58 : 2 : return perform_checks(stat_buf, uid, gid, mode, type);
59 : : }
60 : :
61 : 7 : errno_t check_fd(int fd, const int uid, const int gid,
62 : : const int mode, enum check_file_type type,
63 : : struct stat *caller_stat_buf)
64 : : {
65 : : int ret;
66 : : struct stat local_stat_buf;
67 : : struct stat *stat_buf;
68 : :
69 [ + - ]: 7 : if (caller_stat_buf == NULL) {
70 : : stat_buf = &local_stat_buf;
71 : : } else {
72 : 7 : stat_buf = caller_stat_buf;
73 : : }
74 : :
75 : 7 : ret = fstat(fd, stat_buf);
76 [ - + ]: 7 : if (ret == -1) {
77 [ # # ][ # # ]: 0 : DEBUG(1, ("fstat for [%d] failed: [%d][%s].\n", fd, errno,
[ # # ][ # # ]
[ # # ]
78 : : strerror(errno)));
79 : 0 : return errno;
80 : : }
81 : :
82 : 7 : return perform_checks(stat_buf, uid, gid, mode, type);
83 : : }
84 : :
85 : 9 : static errno_t perform_checks(struct stat *stat_buf,
86 : : const int uid, const int gid,
87 : : const int mode, enum check_file_type type)
88 : : {
89 : : bool type_check;
90 : :
91 [ + - - - : 9 : switch (type) {
- - - -
- ]
92 : : case CHECK_DONT_CHECK_FILE_TYPE:
93 : : type_check = true;
94 : : break;
95 : : case CHECK_REG:
96 : 9 : type_check = S_ISREG(stat_buf->st_mode);
97 : 9 : break;
98 : : case CHECK_DIR:
99 : 0 : type_check = S_ISDIR(stat_buf->st_mode);
100 : 0 : break;
101 : : case CHECK_CHR:
102 : 0 : type_check = S_ISCHR(stat_buf->st_mode);
103 : 0 : break;
104 : : case CHECK_BLK:
105 : 0 : type_check = S_ISBLK(stat_buf->st_mode);
106 : 0 : break;
107 : : case CHECK_FIFO:
108 : 0 : type_check = S_ISFIFO(stat_buf->st_mode);
109 : 0 : break;
110 : : case CHECK_LNK:
111 : 0 : type_check = S_ISLNK(stat_buf->st_mode);
112 : 0 : break;
113 : : case CHECK_SOCK:
114 : 0 : type_check = S_ISSOCK(stat_buf->st_mode);
115 : 0 : break;
116 : : default:
117 [ # # ][ # # ]: 0 : DEBUG(1, ("Unsupported file type.\n"));
[ # # ][ # # ]
[ # # ]
118 : : return EINVAL;
119 : : }
120 : :
121 [ + + ]: 9 : if (!type_check) {
122 [ + - ][ + - ]: 2 : DEBUG(1, ("File is not the right type.\n"));
[ + - ][ + - ]
[ + - ]
123 : : return EINVAL;
124 : : }
125 : :
126 [ + - ][ + + ]: 7 : if (mode >= 0 && (stat_buf->st_mode & ~S_IFMT) != mode) {
127 [ + - ][ + - ]: 1 : DEBUG(1, ("File has the wrong mode [%.7o], expected [%.7o].\n",
[ + - ][ + - ]
[ + - ]
128 : : (stat_buf->st_mode & ~S_IFMT), mode));
129 : : return EINVAL;
130 : : }
131 : :
132 [ + - ][ + + ]: 6 : if (uid >= 0 && stat_buf->st_uid != uid) {
133 [ + - ][ + - ]: 1 : DEBUG(1, ("File must be owned by uid [%d].\n", uid));
[ + - ][ + - ]
[ + - ]
134 : : return EINVAL;
135 : : }
136 : :
137 [ + - ][ + + ]: 5 : if (gid >= 0 && stat_buf->st_gid != gid) {
138 [ + - ][ + - ]: 9 : DEBUG(1, ("File must be owned by gid [%d].\n", gid));
[ + - ][ + - ]
[ + - ]
139 : : return EINVAL;
140 : : }
141 : :
142 : : return EOK;
143 : : }
144 : :
145 : 8 : errno_t check_and_open_readonly(const char *filename, int *fd, const uid_t uid,
146 : : const gid_t gid, const mode_t mode,
147 : : enum check_file_type type)
148 : : {
149 : : int ret;
150 : : struct stat stat_buf;
151 : :
152 : 8 : *fd = open(filename, O_RDONLY);
153 [ + + ]: 8 : if (*fd == -1) {
154 [ + - ][ + - ]: 1 : DEBUG(1, ("open [%s] failed: [%d][%s].\n", filename, errno,
[ + - ][ + - ]
[ + - ]
155 : : strerror(errno)));
156 : 1 : return errno;
157 : : }
158 : :
159 : 7 : ret = check_fd(*fd, uid, gid, mode, type, &stat_buf);
160 [ + + ]: 7 : if (ret != EOK) {
161 : 4 : close(*fd);
162 : 4 : *fd = -1;
163 [ + - ][ + - ]: 8 : DEBUG(1, ("check_fd failed.\n"));
[ + - ][ + - ]
[ + - ]
164 : : return ret;
165 : : }
166 : :
167 : : return EOK;
168 : : }
169 : :
|