b29714d23e33ad9f24f92df703fda0b7ea278b59
[autobuild.flakey.sn-devel-184/.git] / source3 / modules / test_nfs4_acls.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *
4  *  Unit test for NFS4 ACL handling
5  *
6  *  Copyright (C) Christof Schmitt 2019
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 3 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include "nfs4_acls.c"
23 #include "librpc/gen_ndr/idmap.h"
24 #include "idmap_cache.h"
25 #include <cmocka.h>
26
27 struct test_sids {
28         const char *sid_str;
29         struct unixid unix_id;
30 } test_sids[] = {
31         { "S-1-5-2-123-456-789-100",    { 1000, ID_TYPE_UID     }},
32         { "S-1-5-2-123-456-789-101",    { 1001, ID_TYPE_GID     }},
33         { "S-1-5-2-123-456-789-102",    { 1002, ID_TYPE_BOTH    }},
34         { SID_CREATOR_OWNER,            { 1003, ID_TYPE_UID     }},
35         { SID_CREATOR_GROUP,            { 1004, ID_TYPE_GID     }},
36         { "S-1-5-2-123-456-789-103",    { 1000, ID_TYPE_GID     }},
37         { "S-1-5-2-123-456-789-104",    { 1005, ID_TYPE_BOTH    }},
38         { "S-1-5-2-123-456-789-105",    { 1006, ID_TYPE_BOTH    }},
39         { "S-1-5-2-123-456-789-106",    { 1007, ID_TYPE_BOTH    }},
40 };
41
42 static int group_setup(void **state)
43 {
44         struct dom_sid *sids = NULL;
45         int i;
46
47         sids = talloc_array(NULL, struct dom_sid, ARRAY_SIZE(test_sids));
48         assert_non_null(sids);
49
50         for (i = 0; i < ARRAY_SIZE(test_sids); i++) {
51                 assert_true(dom_sid_parse(test_sids[i].sid_str, &sids[i]));
52                 idmap_cache_set_sid2unixid(&sids[i], &test_sids[i].unix_id);
53         }
54
55         *state = sids;
56
57         return 0;
58
59 }
60
61 static int group_teardown(void **state)
62 {
63         struct dom_sid *sids = *state;
64         int i;
65
66         for (i = 0; i < ARRAY_SIZE(test_sids); i++) {
67                 assert_true(idmap_cache_del_sid(&sids[i]));
68         }
69
70         TALLOC_FREE(sids);
71         *state = NULL;
72
73         return 0;
74 }
75
76 /*
77  * Run this as first test to verify that the id mappings used by other
78  * tests are available in the cache.
79  */
80 static void test_cached_id_mappings(void **state)
81 {
82         struct dom_sid *sids = *state;
83         int i;
84
85         for (i = 0; i < ARRAY_SIZE(test_sids); i++) {
86                 struct dom_sid *sid = &sids[i];
87                 struct unixid *unix_id = &test_sids[i].unix_id;
88                 uid_t uid;
89                 gid_t gid;
90
91                 switch(unix_id->type) {
92                 case ID_TYPE_UID:
93                         assert_true(sid_to_uid(sid, &uid));
94                         assert_int_equal(uid, unix_id->id);
95                         assert_false(sid_to_gid(sid, &gid));
96                         break;
97                 case ID_TYPE_GID:
98                         assert_false(sid_to_uid(sid, &uid));
99                         assert_true(sid_to_gid(sid, &gid));
100                         assert_int_equal(gid, unix_id->id);
101                         break;
102                 case ID_TYPE_BOTH:
103                         assert_true(sid_to_uid(sid, &uid));
104                         assert_int_equal(uid, unix_id->id);
105                         assert_true(sid_to_gid(sid, &gid));
106                         assert_int_equal(gid, unix_id->id);
107                         break;
108                 default:
109                         fail_msg("Unknown id type %d\n", unix_id->type);
110                         break;
111                 }
112         }
113 }
114
115 static void test_empty_nfs4_to_dacl(void **state)
116 {
117         struct dom_sid *sids = *state;
118         TALLOC_CTX *frame = talloc_stackframe();
119         struct SMB4ACL_T *nfs4_acl;
120         struct security_ace *dacl_aces;
121         int good_aces;
122         struct smbacl4_vfs_params params = {
123                 .mode = e_simple,
124                 .do_chown = true,
125                 .acedup = e_merge,
126                 .map_full_control = true,
127         };
128
129         nfs4_acl = smb_create_smb4acl(frame);
130         assert_non_null(nfs4_acl);
131
132         assert_true(smbacl4_nfs42win(frame, &params, nfs4_acl,
133                                      &sids[0], &sids[1], false,
134                                      &dacl_aces, &good_aces));
135
136         assert_int_equal(good_aces, 0);
137         assert_null(dacl_aces);
138
139         TALLOC_FREE(frame);
140 }
141
142 static void test_empty_dacl_to_nfs4(void **state)
143 {
144         TALLOC_CTX *frame = talloc_stackframe();
145         struct SMB4ACL_T *nfs4_acl;
146         struct security_acl *dacl;
147         struct smbacl4_vfs_params params = {
148                 .mode = e_simple,
149                 .do_chown = true,
150                 .acedup = e_merge,
151                 .map_full_control = true,
152         };
153
154         dacl = make_sec_acl(frame, SECURITY_ACL_REVISION_ADS, 0, NULL);
155         assert_non_null(dacl);
156
157         nfs4_acl = smbacl4_win2nfs4(frame, false, dacl, &params, 1001, 1002);
158
159         assert_non_null(nfs4_acl);
160         assert_int_equal(smbacl4_get_controlflags(nfs4_acl),
161                          SEC_DESC_SELF_RELATIVE);
162         assert_int_equal(smb_get_naces(nfs4_acl), 0);
163         assert_null(smb_first_ace4(nfs4_acl));
164 }
165
166 struct ace_dacl_type_mapping {
167         uint32_t nfs4_type;
168         enum security_ace_type dacl_type;
169 } ace_dacl_type_mapping[] = {
170         { SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE,     SEC_ACE_TYPE_ACCESS_ALLOWED   },
171         { SMB_ACE4_ACCESS_DENIED_ACE_TYPE,      SEC_ACE_TYPE_ACCESS_DENIED    },
172 };
173
174 static void test_acl_type_nfs4_to_dacl(void **state)
175 {
176         struct dom_sid *sids = *state;
177         TALLOC_CTX *frame = talloc_stackframe();
178         int i;
179
180         for (i = 0; i < ARRAY_SIZE(ace_dacl_type_mapping); i++) {
181                 struct SMB4ACL_T *nfs4_acl;
182                 SMB_ACE4PROP_T nfs4_ace;
183                 struct security_ace *dacl_aces;
184                 int good_aces;
185                 struct smbacl4_vfs_params params = {
186                         .mode = e_simple,
187                         .do_chown = true,
188                         .acedup = e_merge,
189                         .map_full_control = true,
190                 };
191
192                 nfs4_acl = smb_create_smb4acl(frame);
193                 assert_non_null(nfs4_acl);
194
195                 nfs4_ace = (SMB_ACE4PROP_T) {
196                         .flags          = 0,
197                         .who.uid        = 1000,
198                         .aceType        = ace_dacl_type_mapping[i].nfs4_type,
199                         .aceFlags       = 0,
200                         .aceMask        = SMB_ACE4_READ_DATA,
201                 };
202                 assert_non_null(smb_add_ace4(nfs4_acl, &nfs4_ace));
203
204                 assert_true(smbacl4_nfs42win(frame, &params, nfs4_acl,
205                                              &sids[2], &sids[3], false,
206                                              &dacl_aces, &good_aces));
207
208                 assert_int_equal(good_aces, 1);
209                 assert_non_null(dacl_aces);
210
211                 assert_int_equal(dacl_aces[0].type,
212                                  ace_dacl_type_mapping[i].dacl_type);
213                 assert_int_equal(dacl_aces[0].flags, 0);
214                 assert_int_equal(dacl_aces[0].access_mask, SEC_FILE_READ_DATA);
215                 assert_true(dom_sid_equal(&dacl_aces[0].trustee, &sids[0]));
216         }
217
218         TALLOC_FREE(frame);
219 }
220
221 static void test_acl_type_dacl_to_nfs4(void **state)
222 {
223         struct dom_sid *sids = *state;
224         TALLOC_CTX *frame = talloc_stackframe();
225         int i;
226
227         for (i = 0; i < ARRAY_SIZE(ace_dacl_type_mapping); i++) {
228                 struct SMB4ACL_T *nfs4_acl;
229                 struct SMB4ACE_T *nfs4_ace_container;
230                 SMB_ACE4PROP_T *nfs4_ace;
231                 struct security_ace dacl_aces[1];
232                 struct security_acl *dacl;
233                 struct smbacl4_vfs_params params = {
234                         .mode = e_simple,
235                         .do_chown = true,
236                         .acedup = e_merge,
237                         .map_full_control = true,
238                 };
239
240                 init_sec_ace(&dacl_aces[0], &sids[0],
241                              ace_dacl_type_mapping[i].dacl_type,
242                              SEC_FILE_READ_DATA, 0);
243                 dacl = make_sec_acl(frame, SECURITY_ACL_REVISION_ADS,
244                                     ARRAY_SIZE(dacl_aces), dacl_aces);
245                 assert_non_null(dacl);
246
247                 nfs4_acl = smbacl4_win2nfs4(frame, false, dacl, &params,
248                                             101, 102);
249
250                 assert_non_null(nfs4_acl);
251                 assert_int_equal(smbacl4_get_controlflags(nfs4_acl),
252                                  SEC_DESC_SELF_RELATIVE);
253                 assert_int_equal(smb_get_naces(nfs4_acl), 1);
254
255                 nfs4_ace_container = smb_first_ace4(nfs4_acl);
256                 assert_non_null(nfs4_ace_container);
257                 assert_null(smb_next_ace4(nfs4_ace_container));
258
259                 nfs4_ace = smb_get_ace4(nfs4_ace_container);
260                 assert_int_equal(nfs4_ace->flags, 0);
261                 assert_int_equal(nfs4_ace->who.uid, 1000);
262                 assert_int_equal(nfs4_ace->aceFlags, 0);
263                 assert_int_equal(nfs4_ace->aceType,
264                                  ace_dacl_type_mapping[i].nfs4_type);
265                 assert_int_equal(nfs4_ace->aceMask, SMB_ACE4_READ_DATA);
266         }
267
268         TALLOC_FREE(frame);
269 }
270
271 int main(int argc, char **argv)
272 {
273         const struct CMUnitTest tests[] = {
274                 cmocka_unit_test(test_cached_id_mappings),
275                 cmocka_unit_test(test_empty_nfs4_to_dacl),
276                 cmocka_unit_test(test_empty_dacl_to_nfs4),
277                 cmocka_unit_test(test_acl_type_nfs4_to_dacl),
278                 cmocka_unit_test(test_acl_type_dacl_to_nfs4),
279         };
280
281         cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
282
283         if (argc != 2) {
284                 print_error("Usage: %s smb.conf\n", argv[0]);
285                 exit(1);
286         }
287
288         /*
289          * Initialize enough of the Samba internals to have the
290          * mappings tests work.
291          */
292         talloc_stackframe();
293         lp_load_global(argv[1]);
294
295         return cmocka_run_group_tests(tests, group_setup, group_teardown);
296 }