Line data Source code
1 : /* Copyright (c) 2014-2021, The Tor Project, Inc. */
2 : /* See LICENSE for licensing information */
3 :
4 : #include "orconfig.h"
5 : #include "core/or/or.h"
6 :
7 : #ifdef _WIN32
8 : #include <direct.h>
9 : #else
10 : #include <dirent.h>
11 : #endif
12 :
13 : #include "app/config/config.h"
14 : #include "test/test.h"
15 :
16 : #ifdef HAVE_SYS_STAT_H
17 : #include <sys/stat.h>
18 : #endif
19 :
20 : #ifdef _WIN32
21 : #define mkdir(a,b) mkdir(a)
22 : #define tt_int_op_nowin(a,op,b) do { (void)(a); (void)(b); } while (0)
23 : #define umask(mask) ((void)0)
24 : #else
25 : #define tt_int_op_nowin(a,op,b) tt_int_op((a),op,(b))
26 : #endif /* defined(_WIN32) */
27 :
28 : /** Run unit tests for private dir permission enforcement logic. */
29 : static void
30 1 : test_checkdir_perms(void *testdata)
31 : {
32 1 : (void)testdata;
33 1 : or_options_t *options = get_options_mutable();
34 1 : const char *subdir = "test_checkdir";
35 1 : char *testdir = NULL;
36 1 : cpd_check_t cpd_chkopts;
37 1 : cpd_check_t unix_create_opts;
38 1 : cpd_check_t unix_verify_optsmask;
39 1 : struct stat st;
40 :
41 1 : umask(022);
42 :
43 : /* setup data directory before tests. */
44 1 : tor_free(options->DataDirectory);
45 1 : options->DataDirectory = tor_strdup(get_fname(subdir));
46 1 : tt_int_op(mkdir(options->DataDirectory, 0750), OP_EQ, 0);
47 :
48 : /* test: create new dir, no flags. */
49 1 : testdir = get_datadir_fname("checkdir_new_none");
50 1 : cpd_chkopts = CPD_CREATE;
51 1 : unix_verify_optsmask = 0077;
52 1 : tt_int_op(0, OP_EQ, check_private_dir(testdir, cpd_chkopts, NULL));
53 1 : tt_int_op(0, OP_EQ, stat(testdir, &st));
54 1 : tt_int_op_nowin(0, OP_EQ, (st.st_mode & unix_verify_optsmask));
55 1 : tor_free(testdir);
56 :
57 : /* test: create new dir, CPD_GROUP_OK option set. */
58 1 : testdir = get_datadir_fname("checkdir_new_groupok");
59 1 : cpd_chkopts = CPD_CREATE|CPD_GROUP_OK;
60 1 : unix_verify_optsmask = 0077;
61 1 : tt_int_op(0, OP_EQ, check_private_dir(testdir, cpd_chkopts, NULL));
62 1 : tt_int_op(0, OP_EQ, stat(testdir, &st));
63 1 : tt_int_op_nowin(0, OP_EQ, (st.st_mode & unix_verify_optsmask));
64 1 : tor_free(testdir);
65 :
66 : /* test: should get an error on existing dir with
67 : wrong perms */
68 1 : testdir = get_datadir_fname("checkdir_new_groupok_err");
69 1 : tt_int_op(0, OP_EQ, mkdir(testdir, 027));
70 1 : cpd_chkopts = CPD_CHECK_MODE_ONLY|CPD_CREATE|CPD_GROUP_OK;
71 1 : tt_int_op_nowin(-1, OP_EQ, check_private_dir(testdir, cpd_chkopts, NULL));
72 1 : tor_free(testdir);
73 :
74 : /* test: create new dir, CPD_GROUP_READ option set. */
75 1 : testdir = get_datadir_fname("checkdir_new_groupread");
76 1 : cpd_chkopts = CPD_CREATE|CPD_GROUP_READ;
77 1 : unix_verify_optsmask = 0027;
78 1 : tt_int_op(0, OP_EQ, check_private_dir(testdir, cpd_chkopts, NULL));
79 1 : tt_int_op(0, OP_EQ, stat(testdir, &st));
80 1 : tt_int_op_nowin(0, OP_EQ, (st.st_mode & unix_verify_optsmask));
81 1 : tor_free(testdir);
82 :
83 : /* test: check existing dir created with defaults,
84 : and verify with CPD_CREATE only. */
85 1 : testdir = get_datadir_fname("checkdir_exists_none");
86 1 : cpd_chkopts = CPD_CREATE;
87 1 : unix_create_opts = 0700;
88 1 : (void)unix_create_opts;
89 1 : unix_verify_optsmask = 0077;
90 1 : tt_int_op(0, OP_EQ, mkdir(testdir, unix_create_opts));
91 1 : tt_int_op(0, OP_EQ, check_private_dir(testdir, cpd_chkopts, NULL));
92 1 : tt_int_op(0, OP_EQ, stat(testdir, &st));
93 1 : tt_int_op_nowin(0, OP_EQ, (st.st_mode & unix_verify_optsmask));
94 1 : tor_free(testdir);
95 :
96 : /* test: check existing dir created with defaults,
97 : and verify with CPD_GROUP_OK option set. */
98 1 : testdir = get_datadir_fname("checkdir_exists_groupok");
99 1 : cpd_chkopts = CPD_CREATE;
100 1 : unix_verify_optsmask = 0077;
101 1 : tt_int_op(0, OP_EQ, check_private_dir(testdir, cpd_chkopts, NULL));
102 1 : cpd_chkopts = CPD_GROUP_OK;
103 1 : tt_int_op(0, OP_EQ, check_private_dir(testdir, cpd_chkopts, NULL));
104 1 : tt_int_op(0, OP_EQ, stat(testdir, &st));
105 1 : tt_int_op_nowin(0, OP_EQ, (st.st_mode & unix_verify_optsmask));
106 1 : tor_free(testdir);
107 :
108 : /* test: check existing dir created with defaults,
109 : and verify with CPD_GROUP_READ option set. */
110 1 : testdir = get_datadir_fname("checkdir_exists_groupread");
111 1 : cpd_chkopts = CPD_CREATE;
112 1 : unix_verify_optsmask = 0027;
113 1 : tt_int_op(0, OP_EQ, check_private_dir(testdir, cpd_chkopts, NULL));
114 1 : cpd_chkopts = CPD_GROUP_READ;
115 1 : tt_int_op(0, OP_EQ, check_private_dir(testdir, cpd_chkopts, NULL));
116 1 : tt_int_op(0, OP_EQ, stat(testdir, &st));
117 1 : tt_int_op_nowin(0, OP_EQ, (st.st_mode & unix_verify_optsmask));
118 1 : tor_free(testdir);
119 :
120 : /* test: check existing dir created with CPD_GROUP_READ,
121 : and verify with CPD_GROUP_OK option set. */
122 1 : testdir = get_datadir_fname("checkdir_existsread_groupok");
123 1 : cpd_chkopts = CPD_CREATE|CPD_GROUP_READ;
124 1 : unix_verify_optsmask = 0027;
125 1 : tt_int_op(0, OP_EQ, check_private_dir(testdir, cpd_chkopts, NULL));
126 1 : cpd_chkopts = CPD_GROUP_OK;
127 1 : tt_int_op(0, OP_EQ, check_private_dir(testdir, cpd_chkopts, NULL));
128 1 : tt_int_op(0, OP_EQ, stat(testdir, &st));
129 1 : tt_int_op_nowin(0, OP_EQ, (st.st_mode & unix_verify_optsmask));
130 1 : tor_free(testdir);
131 :
132 : /* test: check existing dir created with CPD_GROUP_READ,
133 : and verify with CPD_GROUP_READ option set. */
134 1 : testdir = get_datadir_fname("checkdir_existsread_groupread");
135 1 : cpd_chkopts = CPD_CREATE|CPD_GROUP_READ;
136 1 : unix_verify_optsmask = 0027;
137 1 : tt_int_op(0, OP_EQ, check_private_dir(testdir, cpd_chkopts, NULL));
138 1 : tt_int_op(0, OP_EQ, stat(testdir, &st));
139 1 : tt_int_op_nowin(0, OP_EQ, (st.st_mode & unix_verify_optsmask));
140 :
141 1 : done:
142 1 : tor_free(testdir);
143 1 : }
144 :
145 : #define CHECKDIR(name,flags) \
146 : { #name, test_checkdir_##name, (flags), NULL, NULL }
147 :
148 : struct testcase_t checkdir_tests[] = {
149 : CHECKDIR(perms, TT_FORK),
150 : END_OF_TESTCASES
151 : };
|