Branch data Line data Source code
1 : : /*
2 : : SSSD
3 : :
4 : : Utilities tests check_and_open
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 <stdlib.h>
26 : : #include <check.h>
27 : : #include <unistd.h>
28 : : #include <sys/types.h>
29 : : #include <sys/stat.h>
30 : :
31 : : #include "util/util.h"
32 : : #include "tests/common.h"
33 : :
34 : : #define SUFFIX ".symlink"
35 : :
36 : : #define FILENAME_TEMPLATE "check_and_open-tests-XXXXXX"
37 : : char *filename;
38 : : uid_t uid;
39 : : gid_t gid;
40 : : mode_t mode;
41 : : int fd;
42 : :
43 : 9 : void setup_check_and_open(void)
44 : : {
45 : : int ret;
46 : : mode_t old_umask;
47 : :
48 [ + - ]: 9 : filename = strdup(FILENAME_TEMPLATE);
49 : 9 : fail_unless(filename != NULL, "strdup failed");
50 : :
51 : 9 : old_umask = umask(077);
52 : 9 : ret = mkstemp(filename);
53 : 9 : umask(old_umask);
54 : 9 : fail_unless(ret != -1, "mkstemp failed [%d][%s]", errno, strerror(errno));
55 : 9 : close(ret);
56 : :
57 : 9 : uid = getuid();
58 : 9 : gid = getgid();
59 : 9 : mode = (S_IRUSR | S_IWUSR);
60 : 9 : fd = -1;
61 : 9 : }
62 : :
63 : 9 : void teardown_check_and_open(void)
64 : : {
65 : : int ret;
66 : :
67 [ + + ]: 9 : if (fd != -1) {
68 : 2 : ret = close(fd);
69 : 2 : fail_unless(ret == 0, "close failed [%d][%s]", errno, strerror(errno));
70 : : }
71 : :
72 : 9 : fail_unless(filename != NULL, "unknown filename");
73 : 9 : ret = unlink(filename);
74 : 9 : free(filename);
75 : 9 : fail_unless(ret == 0, "unlink failed [%d][%s]", errno, strerror(errno));
76 : 9 : }
77 : :
78 : 1 : START_TEST(test_wrong_filename)
79 : : {
80 : : int ret;
81 : :
82 : 1 : ret = check_and_open_readonly("/bla/bla/bla", &fd, uid, gid, mode, CHECK_REG);
83 : 1 : fail_unless(ret == ENOENT,
84 : : "check_and_open_readonly succeeded on non-existing file");
85 : 1 : fail_unless(fd == -1, "check_and_open_readonly file descriptor not -1");
86 : : }
87 : 1 : END_TEST
88 : :
89 : 1 : START_TEST(test_symlink)
90 : : {
91 : : int ret;
92 : : char *newpath;
93 : : size_t newpath_length;
94 : :
95 : 1 : newpath_length = strlen(filename) + strlen(SUFFIX) + 1;
96 : 1 : newpath = malloc((newpath_length) * sizeof(char));
97 : 1 : fail_unless(newpath != NULL, "malloc failed");
98 : :
99 : 1 : ret = snprintf(newpath, newpath_length, "%s%s", filename, SUFFIX);
100 : 1 : fail_unless(ret == newpath_length - 1,
101 : : "snprintf failed: expected [%d] got [%d]", newpath_length -1,
102 : : ret);
103 : :
104 : 1 : ret = symlink(filename, newpath);
105 : 1 : fail_unless(ret == 0, "symlink failed [%d][%s]", ret, strerror(errno));
106 : :
107 : 1 : ret = check_file(newpath, uid, gid, mode, CHECK_REG, NULL, false);
108 : 1 : unlink(newpath);
109 : :
110 : 1 : fail_unless(ret == EINVAL,
111 : : "check_and_open_readonly succeeded on symlink");
112 : : }
113 : 1 : END_TEST
114 : :
115 : 1 : START_TEST(test_follow_symlink)
116 : : {
117 : : int ret;
118 : : char *newpath;
119 : : size_t newpath_length;
120 : :
121 : 1 : newpath_length = strlen(filename) + strlen(SUFFIX) + 1;
122 : 1 : newpath = malloc((newpath_length) * sizeof(char));
123 : 1 : fail_unless(newpath != NULL, "malloc failed");
124 : :
125 : 1 : ret = snprintf(newpath, newpath_length, "%s%s", filename, SUFFIX);
126 : 1 : fail_unless(ret == newpath_length - 1,
127 : : "snprintf failed: expected [%d] got [%d]", newpath_length -1,
128 : : ret);
129 : :
130 : 1 : ret = symlink(filename, newpath);
131 : 1 : fail_unless(ret == 0, "symlink failed [%d][%s]", ret, strerror(errno));
132 : :
133 : 1 : ret = check_file(newpath, uid, gid, mode, CHECK_REG, NULL, true);
134 : 1 : unlink(newpath);
135 : :
136 : 1 : fail_unless(ret == EOK,
137 : : "check_and_open_readonly failed on symlink with follow=true");
138 : : }
139 : 1 : END_TEST
140 : :
141 : 1 : START_TEST(test_not_regular_file)
142 : : {
143 : : int ret;
144 : :
145 : 1 : ret = check_and_open_readonly("/dev/null", &fd, uid, gid, mode, CHECK_REG);
146 : 1 : fail_unless(ret == EINVAL,
147 : : "check_and_open_readonly succeeded on non-regular file");
148 : 1 : fail_unless(fd == -1, "check_and_open_readonly file descriptor not -1");
149 : : }
150 : 1 : END_TEST
151 : :
152 : 1 : START_TEST(test_wrong_uid)
153 : : {
154 : : int ret;
155 : :
156 : 1 : ret = check_and_open_readonly(filename, &fd, uid+1, gid, mode, CHECK_REG);
157 : 1 : fail_unless(ret == EINVAL,
158 : : "check_and_open_readonly succeeded with wrong uid");
159 : 1 : fail_unless(fd == -1, "check_and_open_readonly file descriptor not -1");
160 : : }
161 : 1 : END_TEST
162 : :
163 : 1 : START_TEST(test_wrong_gid)
164 : : {
165 : : int ret;
166 : :
167 : 1 : ret = check_and_open_readonly(filename, &fd, uid, gid+1, mode, CHECK_REG);
168 : 1 : fail_unless(ret == EINVAL,
169 : : "check_and_open_readonly succeeded with wrong gid");
170 : 1 : fail_unless(fd == -1, "check_and_open_readonly file descriptor not -1");
171 : : }
172 : 1 : END_TEST
173 : :
174 : 1 : START_TEST(test_wrong_permission)
175 : : {
176 : : int ret;
177 : :
178 : 1 : ret = check_and_open_readonly(filename, &fd, uid, gid, (mode|S_IWOTH),
179 : : CHECK_REG);
180 : 1 : fail_unless(ret == EINVAL,
181 : : "check_and_open_readonly succeeded with wrong mode");
182 : 1 : fail_unless(fd == -1, "check_and_open_readonly file descriptor not -1");
183 : : }
184 : 1 : END_TEST
185 : :
186 : 1 : START_TEST(test_ok)
187 : : {
188 : : int ret;
189 : :
190 : 1 : ret = check_and_open_readonly(filename, &fd, uid, gid, mode, CHECK_REG);
191 : 1 : fail_unless(ret == EOK,
192 : : "check_and_open_readonly failed");
193 : 1 : fail_unless(fd >= 0,
194 : : "check_and_open_readonly returned illegal file descriptor");
195 : : }
196 : 1 : END_TEST
197 : :
198 : 1 : START_TEST(test_write)
199 : : {
200 : : int ret;
201 : : ssize_t size;
202 : : errno_t my_errno;
203 : :
204 : 1 : ret = check_and_open_readonly(filename, &fd, uid, gid, mode, CHECK_REG);
205 : 1 : fail_unless(ret == EOK,
206 : : "check_and_open_readonly failed");
207 : 1 : fail_unless(fd >= 0,
208 : : "check_and_open_readonly returned illegal file descriptor");
209 : :
210 : 1 : size = write(fd, "abc", 3);
211 : 1 : my_errno = errno;
212 : 1 : fail_unless(size == -1, "check_and_open_readonly file is not readonly");
213 : 1 : fail_unless(my_errno == EBADF,
214 : : "write failed for other reason than readonly");
215 : : }
216 : 1 : END_TEST
217 : :
218 : 10 : Suite *check_and_open_suite (void)
219 : : {
220 : 10 : Suite *s = suite_create ("check_and_open");
221 : :
222 : 10 : TCase *tc_check_and_open_readonly = tcase_create ("check_and_open_readonly");
223 : 10 : tcase_add_checked_fixture (tc_check_and_open_readonly,
224 : : setup_check_and_open,
225 : : teardown_check_and_open);
226 : 10 : tcase_add_test (tc_check_and_open_readonly, test_wrong_filename);
227 : 10 : tcase_add_test (tc_check_and_open_readonly, test_not_regular_file);
228 : 10 : tcase_add_test (tc_check_and_open_readonly, test_symlink);
229 : 10 : tcase_add_test (tc_check_and_open_readonly, test_follow_symlink);
230 : 10 : tcase_add_test (tc_check_and_open_readonly, test_wrong_uid);
231 : 10 : tcase_add_test (tc_check_and_open_readonly, test_wrong_gid);
232 : 10 : tcase_add_test (tc_check_and_open_readonly, test_wrong_permission);
233 : 10 : tcase_add_test (tc_check_and_open_readonly, test_ok);
234 : 10 : tcase_add_test (tc_check_and_open_readonly, test_write);
235 : 10 : suite_add_tcase (s, tc_check_and_open_readonly);
236 : :
237 : 10 : return s;
238 : : }
239 : :
240 : 10 : int main(void)
241 : : {
242 : : int number_failed;
243 : :
244 : 10 : tests_set_cwd();
245 : :
246 : 10 : Suite *s = check_and_open_suite ();
247 : 10 : SRunner *sr = srunner_create (s);
248 : : /* If CK_VERBOSITY is set, use that, otherwise it defaults to CK_NORMAL */
249 : 10 : srunner_run_all(sr, CK_ENV);
250 : 1 : number_failed = srunner_ntests_failed (sr);
251 : 1 : srunner_free (sr);
252 : 1 : return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
253 : : }
254 : :
|