aboutsummaryrefslogtreecommitdiff
path: root/src/test/test_checkdir.c
blob: 186a55cc8c93d131cb2be8340229371983e4fe54 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/* Copyright (c) 2014-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */

#include "orconfig.h"
#include "core/or/or.h"

#ifdef _WIN32
#include <direct.h>
#else
#include <dirent.h>
#endif

#include "app/config/config.h"
#include "test/test.h"

#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif

#ifdef _WIN32
#define mkdir(a,b) mkdir(a)
#define tt_int_op_nowin(a,op,b) do { (void)(a); (void)(b); } while (0)
#define umask(mask) ((void)0)
#else
#define tt_int_op_nowin(a,op,b) tt_int_op((a),op,(b))
#endif /* defined(_WIN32) */

/** Run unit tests for private dir permission enforcement logic. */
static void
test_checkdir_perms(void *testdata)
{
  (void)testdata;
  or_options_t *options = get_options_mutable();
  const char *subdir = "test_checkdir";
  char *testdir = NULL;
  cpd_check_t  cpd_chkopts;
  cpd_check_t  unix_create_opts;
  cpd_check_t  unix_verify_optsmask;
  struct stat st;

  umask(022);

  /* setup data directory before tests. */
  tor_free(options->DataDirectory);
  options->DataDirectory = tor_strdup(get_fname(subdir));
  tt_int_op(mkdir(options->DataDirectory, 0750), OP_EQ, 0);

  /* test: create new dir, no flags. */
  testdir = get_datadir_fname("checkdir_new_none");
  cpd_chkopts = CPD_CREATE;
  unix_verify_optsmask = 0077;
  tt_int_op(0, OP_EQ, check_private_dir(testdir, cpd_chkopts, NULL));
  tt_int_op(0, OP_EQ, stat(testdir, &st));
  tt_int_op_nowin(0, OP_EQ, (st.st_mode & unix_verify_optsmask));
  tor_free(testdir);

  /* test: create new dir, CPD_GROUP_OK option set. */
  testdir = get_datadir_fname("checkdir_new_groupok");
  cpd_chkopts = CPD_CREATE|CPD_GROUP_OK;
  unix_verify_optsmask = 0077;
  tt_int_op(0, OP_EQ, check_private_dir(testdir, cpd_chkopts, NULL));
  tt_int_op(0, OP_EQ, stat(testdir, &st));
  tt_int_op_nowin(0, OP_EQ, (st.st_mode & unix_verify_optsmask));
  tor_free(testdir);

  /* test: should get an error on existing dir with
           wrong perms */
  testdir = get_datadir_fname("checkdir_new_groupok_err");
  tt_int_op(0, OP_EQ, mkdir(testdir, 027));
  cpd_chkopts = CPD_CHECK_MODE_ONLY|CPD_CREATE|CPD_GROUP_OK;
  tt_int_op_nowin(-1, OP_EQ, check_private_dir(testdir, cpd_chkopts, NULL));
  tor_free(testdir);

  /* test: create new dir, CPD_GROUP_READ option set. */
  testdir = get_datadir_fname("checkdir_new_groupread");
  cpd_chkopts = CPD_CREATE|CPD_GROUP_READ;
  unix_verify_optsmask = 0027;
  tt_int_op(0, OP_EQ, check_private_dir(testdir, cpd_chkopts, NULL));
  tt_int_op(0, OP_EQ, stat(testdir, &st));
  tt_int_op_nowin(0, OP_EQ, (st.st_mode & unix_verify_optsmask));
  tor_free(testdir);

  /* test: check existing dir created with defaults,
            and verify with CPD_CREATE only. */
  testdir = get_datadir_fname("checkdir_exists_none");
  cpd_chkopts = CPD_CREATE;
  unix_create_opts = 0700;
  (void)unix_create_opts;
  unix_verify_optsmask = 0077;
  tt_int_op(0, OP_EQ, mkdir(testdir, unix_create_opts));
  tt_int_op(0, OP_EQ, check_private_dir(testdir, cpd_chkopts, NULL));
  tt_int_op(0, OP_EQ, stat(testdir, &st));
  tt_int_op_nowin(0, OP_EQ, (st.st_mode & unix_verify_optsmask));
  tor_free(testdir);

  /* test: check existing dir created with defaults,
            and verify with CPD_GROUP_OK option set. */
  testdir = get_datadir_fname("checkdir_exists_groupok");
  cpd_chkopts = CPD_CREATE;
  unix_verify_optsmask = 0077;
  tt_int_op(0, OP_EQ, check_private_dir(testdir, cpd_chkopts, NULL));
  cpd_chkopts = CPD_GROUP_OK;
  tt_int_op(0, OP_EQ, check_private_dir(testdir, cpd_chkopts, NULL));
  tt_int_op(0, OP_EQ, stat(testdir, &st));
  tt_int_op_nowin(0, OP_EQ, (st.st_mode & unix_verify_optsmask));
  tor_free(testdir);

  /* test: check existing dir created with defaults,
            and verify with CPD_GROUP_READ option set. */
  testdir = get_datadir_fname("checkdir_exists_groupread");
  cpd_chkopts = CPD_CREATE;
  unix_verify_optsmask = 0027;
  tt_int_op(0, OP_EQ, check_private_dir(testdir, cpd_chkopts, NULL));
  cpd_chkopts = CPD_GROUP_READ;
  tt_int_op(0, OP_EQ, check_private_dir(testdir, cpd_chkopts, NULL));
  tt_int_op(0, OP_EQ, stat(testdir, &st));
  tt_int_op_nowin(0, OP_EQ, (st.st_mode & unix_verify_optsmask));
  tor_free(testdir);

  /* test: check existing dir created with CPD_GROUP_READ,
            and verify with CPD_GROUP_OK option set. */
  testdir = get_datadir_fname("checkdir_existsread_groupok");
  cpd_chkopts = CPD_CREATE|CPD_GROUP_READ;
  unix_verify_optsmask = 0027;
  tt_int_op(0, OP_EQ, check_private_dir(testdir, cpd_chkopts, NULL));
  cpd_chkopts = CPD_GROUP_OK;
  tt_int_op(0, OP_EQ, check_private_dir(testdir, cpd_chkopts, NULL));
  tt_int_op(0, OP_EQ, stat(testdir, &st));
  tt_int_op_nowin(0, OP_EQ, (st.st_mode & unix_verify_optsmask));
  tor_free(testdir);

  /* test: check existing dir created with CPD_GROUP_READ,
            and verify with CPD_GROUP_READ option set. */
  testdir = get_datadir_fname("checkdir_existsread_groupread");
  cpd_chkopts = CPD_CREATE|CPD_GROUP_READ;
  unix_verify_optsmask = 0027;
  tt_int_op(0, OP_EQ, check_private_dir(testdir, cpd_chkopts, NULL));
  tt_int_op(0, OP_EQ, stat(testdir, &st));
  tt_int_op_nowin(0, OP_EQ, (st.st_mode & unix_verify_optsmask));

 done:
  tor_free(testdir);
}

#define CHECKDIR(name,flags)                              \
  { #name, test_checkdir_##name, (flags), NULL, NULL }

struct testcase_t checkdir_tests[] = {
  CHECKDIR(perms, TT_FORK),
  END_OF_TESTCASES
};