ctdb-scripts: Support storing statd-callout state in cluster filesystem
[samba4-gss.git] / source4 / torture / smb2 / max_allowed.c
blob6d69b84fbe67f9ec201af9b724808db1c1976c33
1 /*
2 Unix SMB/CIFS implementation.
3 SMB torture tester - deny mode scanning functions
4 Copyright (C) Andrew Tridgell 2001
5 Copyright (C) David Mulder 2019
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "includes.h"
22 #include "system/filesys.h"
23 #include "libcli/smb2/smb2.h"
24 #include "libcli/smb2/smb2_calls.h"
25 #include "libcli/security/security.h"
26 #include "torture/util.h"
27 #include "torture/smb2/proto.h"
29 #define MAXIMUM_ALLOWED_FILE "torture_maximum_allowed"
30 static bool torture_smb2_maximum_allowed(struct torture_context *tctx,
31 struct smb2_tree *tree)
33 struct security_descriptor *sd = NULL, *sd_orig = NULL;
34 struct smb2_create io = {0};
35 TALLOC_CTX *mem_ctx = NULL;
36 struct smb2_handle fnum = {{0}}, fnum1 = {{0}};
37 int i;
38 bool ret = true;
39 NTSTATUS status;
40 union smb_fileinfo q;
41 union smb_setfileinfo set;
42 const char *owner_sid = NULL;
43 bool has_restore_privilege, has_backup_privilege, has_system_security_privilege;
45 mem_ctx = talloc_init("torture_maximum_allowed");
46 torture_assert_goto(tctx, mem_ctx != NULL, ret, done,
47 "talloc allocation failed\n");
49 if (!torture_setting_bool(tctx, "sacl_support", true))
50 torture_warning(tctx, "Skipping SACL related tests!\n");
52 sd = security_descriptor_dacl_create(mem_ctx,
53 0, NULL, NULL,
54 SID_NT_AUTHENTICATED_USERS,
55 SEC_ACE_TYPE_ACCESS_ALLOWED,
56 SEC_RIGHTS_FILE_READ,
57 0, NULL);
58 torture_assert_goto(tctx, sd != NULL, ret, done,
59 "security descriptor creation failed\n");
61 /* Blank slate */
62 smb2_util_unlink(tree, MAXIMUM_ALLOWED_FILE);
64 /* create initial file with restrictive SD */
65 io.in.desired_access = SEC_RIGHTS_FILE_ALL;
66 io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
67 io.in.create_disposition = NTCREATEX_DISP_CREATE;
68 io.in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS;
69 io.in.fname = MAXIMUM_ALLOWED_FILE;
70 io.in.sec_desc = sd;
72 status = smb2_create(tree, mem_ctx, &io);
73 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
74 talloc_asprintf(tctx, "Incorrect status %s - should be %s\n",
75 nt_errstr(status), nt_errstr(NT_STATUS_OK)));
76 fnum = io.out.file.handle;
78 /* the correct answers for this test depends on whether the
79 user has restore privileges. To find that out we first need
80 to know our SID - get it from the owner_sid of the file we
81 just created */
82 q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
83 q.query_secdesc.in.file.handle = fnum;
84 q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
85 status = smb2_getinfo_file(tree, tctx, &q);
86 torture_assert_ntstatus_ok_goto(tctx, status, ret, set_sd,
87 talloc_asprintf(tctx, "Incorrect status %s - should be %s\n",
88 nt_errstr(status), nt_errstr(NT_STATUS_OK)));
89 sd_orig = q.query_secdesc.out.sd;
91 owner_sid = dom_sid_string(tctx, sd_orig->owner_sid);
93 status = torture_smb2_check_privilege(tree,
94 owner_sid,
95 sec_privilege_name(SEC_PRIV_RESTORE));
96 has_restore_privilege = NT_STATUS_IS_OK(status);
97 torture_comment(tctx, "Checked SEC_PRIV_RESTORE for %s - %s\n",
98 owner_sid,
99 has_restore_privilege?"Yes":"No");
101 status = torture_smb2_check_privilege(tree,
102 owner_sid,
103 sec_privilege_name(SEC_PRIV_BACKUP));
104 has_backup_privilege = NT_STATUS_IS_OK(status);
105 torture_comment(tctx, "Checked SEC_PRIV_BACKUP for %s - %s\n",
106 owner_sid,
107 has_backup_privilege?"Yes":"No");
109 status = torture_smb2_check_privilege(tree,
110 owner_sid,
111 sec_privilege_name(SEC_PRIV_SECURITY));
112 has_system_security_privilege = NT_STATUS_IS_OK(status);
113 torture_comment(tctx, "Checked SEC_PRIV_SECURITY for %s - %s\n",
114 owner_sid,
115 has_system_security_privilege?"Yes":"No");
117 smb2_util_close(tree, fnum);
119 for (i = 0; i < 32; i++) {
120 uint32_t mask = SEC_FLAG_MAXIMUM_ALLOWED | (1u << i);
122 * SEC_GENERIC_EXECUTE is a complete subset of
123 * SEC_GENERIC_READ when mapped to specific bits,
124 * so we need to include it in the basic OK mask.
126 uint32_t ok_mask = SEC_RIGHTS_FILE_READ | SEC_GENERIC_READ | SEC_GENERIC_EXECUTE |
127 SEC_STD_DELETE | SEC_STD_WRITE_DAC;
130 * Now SEC_RIGHTS_PRIV_RESTORE and SEC_RIGHTS_PRIV_BACKUP
131 * don't include any generic bits (they're used directly
132 * in the fileserver where the generic bits have already
133 * been mapped into file specific bits) we need to add the
134 * generic bits to the ok_mask when we have these privileges.
136 if (has_restore_privilege) {
137 ok_mask |= SEC_RIGHTS_PRIV_RESTORE|SEC_GENERIC_WRITE;
139 if (has_backup_privilege) {
140 ok_mask |= SEC_RIGHTS_PRIV_BACKUP|SEC_GENERIC_READ;
142 if (has_system_security_privilege) {
143 ok_mask |= SEC_FLAG_SYSTEM_SECURITY;
146 /* Skip all SACL related tests. */
147 if ((!torture_setting_bool(tctx, "sacl_support", true)) &&
148 (mask & SEC_FLAG_SYSTEM_SECURITY))
149 continue;
151 io = (struct smb2_create){0};
152 io.in.desired_access = mask;
153 io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
154 io.in.create_disposition = NTCREATEX_DISP_OPEN;
155 io.in.impersonation_level =
156 NTCREATEX_IMPERSONATION_ANONYMOUS;
157 io.in.fname = MAXIMUM_ALLOWED_FILE;
159 status = smb2_create(tree, mem_ctx, &io);
160 if (mask & ok_mask ||
161 mask == SEC_FLAG_MAXIMUM_ALLOWED) {
162 torture_assert_ntstatus_ok_goto(tctx, status, ret,
163 set_sd, talloc_asprintf(tctx,
164 "Incorrect status %s - should be %s\n",
165 nt_errstr(status), nt_errstr(NT_STATUS_OK)));
166 } else {
167 if (mask & SEC_FLAG_SYSTEM_SECURITY) {
168 torture_assert_ntstatus_equal_goto(tctx,
169 status, NT_STATUS_PRIVILEGE_NOT_HELD,
170 ret, set_sd, talloc_asprintf(tctx,
171 "Incorrect status %s - should be %s\n",
172 nt_errstr(status),
173 nt_errstr(NT_STATUS_PRIVILEGE_NOT_HELD)));
174 } else {
175 torture_assert_ntstatus_equal_goto(tctx,
176 status, NT_STATUS_ACCESS_DENIED,
177 ret, set_sd, talloc_asprintf(tctx,
178 "Incorrect status %s - should be %s\n",
179 nt_errstr(status),
180 nt_errstr(NT_STATUS_ACCESS_DENIED)));
184 fnum = io.out.file.handle;
186 smb2_util_close(tree, fnum);
189 set_sd:
190 io.in.desired_access = SEC_STD_WRITE_DAC;
191 io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
192 io.in.create_disposition = NTCREATEX_DISP_OPEN;
193 io.in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS;
194 io.in.fname = MAXIMUM_ALLOWED_FILE;
196 status = smb2_create(tree, mem_ctx, &io);
197 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
198 talloc_asprintf(tctx, "Incorrect status %s - should be %s\n",
199 nt_errstr(status), nt_errstr(NT_STATUS_OK)));
200 fnum1 = io.out.file.handle;
202 sd = security_descriptor_dacl_create(tctx,
203 0, NULL, NULL,
204 SID_NT_AUTHENTICATED_USERS,
205 SEC_ACE_TYPE_ACCESS_ALLOWED,
206 SEC_STD_DELETE,
208 NULL);
209 set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
210 set.set_secdesc.in.file.handle = fnum1;
211 set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
212 set.set_secdesc.in.sd = sd;
214 status = smb2_setinfo_file(tree, &set);
215 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
216 talloc_asprintf(tctx, "Incorrect status %s - should be %s\n",
217 nt_errstr(status), nt_errstr(NT_STATUS_OK)));
219 done:
220 smb2_util_close(tree, fnum1);
221 smb2_util_unlink(tree, MAXIMUM_ALLOWED_FILE);
222 talloc_free(mem_ctx);
223 return ret;
226 static bool torture_smb2_read_only_file(struct torture_context *tctx,
227 struct smb2_tree *tree)
229 struct smb2_create c;
230 struct smb2_handle h = {{0}};
231 bool ret = true;
232 NTSTATUS status;
234 smb2_deltree(tree, MAXIMUM_ALLOWED_FILE);
236 c = (struct smb2_create) {
237 .in.desired_access = SEC_RIGHTS_FILE_ALL,
238 .in.file_attributes = FILE_ATTRIBUTE_READONLY,
239 .in.create_disposition = NTCREATEX_DISP_CREATE,
240 .in.fname = MAXIMUM_ALLOWED_FILE,
243 status = smb2_create(tree, tctx, &c);
244 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
245 "smb2_create failed\n");
246 h = c.out.file.handle;
247 smb2_util_close(tree, h);
248 ZERO_STRUCT(h);
250 c = (struct smb2_create) {
251 .in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED,
252 .in.file_attributes = FILE_ATTRIBUTE_READONLY,
253 .in.create_disposition = NTCREATEX_DISP_OPEN,
254 .in.fname = MAXIMUM_ALLOWED_FILE,
257 status = smb2_create(tree, tctx, &c);
258 torture_assert_ntstatus_ok_goto(
259 tctx, status, ret, done,
260 "Failed to open READ-ONLY file with SEC_FLAG_MAXIMUM_ALLOWED\n");
261 h = c.out.file.handle;
262 smb2_util_close(tree, h);
263 ZERO_STRUCT(h);
265 done:
266 if (!smb2_util_handle_empty(h)) {
267 smb2_util_close(tree, h);
269 smb2_deltree(tree, MAXIMUM_ALLOWED_FILE);
270 return ret;
273 struct torture_suite *torture_smb2_max_allowed(TALLOC_CTX *ctx)
275 struct torture_suite *suite = torture_suite_create(ctx, "maximum_allowed");
277 torture_suite_add_1smb2_test(suite, "maximum_allowed", torture_smb2_maximum_allowed);
278 torture_suite_add_1smb2_test(suite, "read_only", torture_smb2_read_only_file);
279 return suite;