Line data Source code
1 : /*
2 : Authors:
3 : Yassir Elley <yelley@redhat.com>
4 :
5 : Copyright (C) 2014 Red Hat
6 :
7 : SSSD tests: GPO unit tests
8 :
9 : This program is free software; you can redistribute it and/or modify
10 : it under the terms of the GNU General Public License as published by
11 : the Free Software Foundation; either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program. If not, see <http://www.gnu.org/licenses/>.
21 : */
22 :
23 : #include <talloc.h>
24 : #include <tevent.h>
25 : #include <errno.h>
26 : #include <popt.h>
27 : #include <unistd.h>
28 : #include <sys/types.h>
29 : #include <ifaddrs.h>
30 : #include <arpa/inet.h>
31 :
32 : /* In order to access opaque types */
33 : #include "providers/ad/ad_gpo.c"
34 :
35 : #include "tests/cmocka/common_mock.h"
36 :
37 : struct ad_gpo_test_ctx {
38 : struct ldb_context *ldb_ctx;
39 : };
40 :
41 : static struct ad_gpo_test_ctx *test_ctx;
42 :
43 8 : static int ad_gpo_test_setup(void **state)
44 : {
45 8 : assert_true(leak_check_setup());
46 8 : test_ctx = talloc_zero(global_talloc_context,
47 : struct ad_gpo_test_ctx);
48 8 : assert_non_null(test_ctx);
49 :
50 8 : test_ctx->ldb_ctx = ldb_init(test_ctx, NULL);
51 8 : assert_non_null(test_ctx->ldb_ctx);
52 8 : return 0;
53 : }
54 :
55 8 : static int ad_gpo_test_teardown(void **state)
56 : {
57 8 : talloc_free(test_ctx);
58 8 : assert_true(leak_check_teardown());
59 8 : return 0;
60 : }
61 :
62 : struct som_list_result {
63 : const int result;
64 : const int num_soms;
65 : const char **som_dns;
66 : };
67 :
68 : /*
69 : * Test parsing target dn into som components
70 : */
71 2 : static void test_populate_som_list(const char *target_dn,
72 : struct som_list_result *expected)
73 : {
74 : errno_t ret;
75 : int i;
76 : int num_soms;
77 2 : struct gp_som **som_list = NULL;
78 : TALLOC_CTX *tmp_ctx;
79 :
80 2 : tmp_ctx = talloc_new(global_talloc_context);
81 2 : assert_non_null(tmp_ctx);
82 2 : check_leaks_push(tmp_ctx);
83 :
84 2 : ret = ad_gpo_populate_som_list(tmp_ctx,
85 2 : test_ctx->ldb_ctx,
86 : target_dn,
87 : &num_soms,
88 : &som_list);
89 :
90 2 : assert_int_equal(ret, expected->result);
91 2 : if (ret != EOK) {
92 1 : goto done;
93 : }
94 :
95 1 : assert_int_equal(num_soms, expected->num_soms);
96 :
97 4 : for (i=0; i<expected->num_soms; i++){
98 3 : bool equal = true;
99 6 : if (strncmp(som_list[i]->som_dn,
100 3 : expected->som_dns[i],
101 3 : strlen(expected->som_dns[i])) != 0) {
102 0 : equal = false;
103 : }
104 :
105 3 : assert_int_equal(equal, true);
106 : }
107 :
108 1 : if (som_list) {
109 1 : talloc_free(som_list);
110 : }
111 :
112 : done:
113 2 : assert_true(check_leaks_pop(tmp_ctx) == true);
114 2 : talloc_free(tmp_ctx);
115 2 : }
116 :
117 1 : void test_populate_som_list_plain(void **state)
118 : {
119 1 : const char *som_dns[] = {"OU=West OU,OU=Sales OU,DC=foo,DC=com",
120 : "OU=Sales OU,DC=foo,DC=com",
121 : "DC=foo,DC=com"};
122 :
123 1 : struct som_list_result expected = {
124 : .result = EOK,
125 : .num_soms = 3,
126 : .som_dns = som_dns
127 : };
128 :
129 1 : test_populate_som_list("CN=F21-Client,OU=West OU,OU=Sales OU,DC=foo,DC=com",
130 : &expected);
131 1 : }
132 :
133 1 : void test_populate_som_list_malformed(void **state)
134 : {
135 1 : struct som_list_result expected = {
136 : .result = EINVAL,
137 : };
138 :
139 1 : test_populate_som_list("malformed target dn", &expected);
140 1 : }
141 :
142 : struct gplink_list_result {
143 : const int result;
144 : const int num_gplinks;
145 : const char **gpo_dns;
146 : bool *enforced;
147 : };
148 :
149 : /*
150 : * Test parsing raw_gplink_value into gplink components
151 : */
152 6 : static void test_populate_gplink_list(const char *input_gplink_value,
153 : bool allow_enforced_only,
154 : struct gplink_list_result *expected)
155 : {
156 : errno_t ret;
157 : int i;
158 6 : struct gp_gplink **gplink_list = NULL;
159 : TALLOC_CTX *tmp_ctx;
160 :
161 6 : tmp_ctx = talloc_new(global_talloc_context);
162 6 : assert_non_null(tmp_ctx);
163 6 : check_leaks_push(tmp_ctx);
164 :
165 6 : char *raw_gplink_value = talloc_strdup(tmp_ctx, input_gplink_value);
166 :
167 6 : ret = ad_gpo_populate_gplink_list(tmp_ctx,
168 : NULL,
169 : raw_gplink_value,
170 : &gplink_list,
171 : allow_enforced_only);
172 :
173 6 : talloc_free(raw_gplink_value);
174 :
175 6 : assert_int_equal(ret, expected->result);
176 6 : if (ret != EOK) {
177 3 : goto done;
178 : }
179 :
180 7 : for (i=0; i<expected->num_gplinks; i++){
181 4 : bool equal = true;
182 8 : if (strncmp(gplink_list[i]->gpo_dn,
183 4 : expected->gpo_dns[i],
184 4 : strlen(expected->gpo_dns[i])) != 0) {
185 0 : equal = false;
186 : }
187 :
188 4 : if (gplink_list[i]->enforced != expected->enforced[i])
189 0 : equal = false;
190 :
191 4 : assert_int_equal(equal, true);
192 : }
193 :
194 3 : if (gplink_list) {
195 3 : talloc_free(gplink_list);
196 : }
197 :
198 : done:
199 6 : assert_true(check_leaks_pop(tmp_ctx) == true);
200 6 : talloc_free(tmp_ctx);
201 6 : }
202 :
203 1 : void test_populate_gplink_list_plain(void **state)
204 : {
205 1 : const char *gpo_dns[] = {"OU=Sales,DC=FOO,DC=COM", "DC=FOO,DC=COM"};
206 1 : bool enforced[] = {false, true};
207 :
208 1 : struct gplink_list_result expected = {
209 : .result = EOK,
210 : .num_gplinks = 2,
211 : .gpo_dns = gpo_dns,
212 : .enforced = enforced
213 : };
214 :
215 1 : test_populate_gplink_list("[OU=Sales,DC=FOO,DC=COM;0][DC=FOO,DC=COM;2]",
216 : false,
217 : &expected);
218 1 : }
219 :
220 1 : void test_populate_gplink_list_with_ignored(void **state)
221 : {
222 1 : const char *gpo_dns[] = {"OU=Sales,DC=FOO,DC=COM"};
223 1 : bool enforced[] = {false};
224 :
225 1 : struct gplink_list_result expected = {
226 : .result = EOK,
227 : .num_gplinks = 1,
228 : .gpo_dns = gpo_dns,
229 : .enforced = enforced
230 : };
231 :
232 1 : test_populate_gplink_list("[OU=Sales,DC=FOO,DC=COM;0][DC=ignored;1]",
233 : false,
234 : &expected);
235 1 : }
236 :
237 1 : void test_populate_gplink_list_with_allow_enforced(void **state)
238 : {
239 1 : const char *gpo_dns[] = {"DC=FOO,DC=COM"};
240 1 : bool enforced[] = {true};
241 :
242 1 : struct gplink_list_result expected = {
243 : .result = EOK,
244 : .num_gplinks = 1,
245 : .gpo_dns = gpo_dns,
246 : .enforced = enforced
247 : };
248 :
249 1 : test_populate_gplink_list("[OU=Sales,DC=FOO,DC=COM;0][DC=FOO,DC=COM;2]",
250 : true,
251 : &expected);
252 1 : }
253 :
254 1 : void test_populate_gplink_list_malformed(void **state)
255 : {
256 1 : struct gplink_list_result expected = {
257 : .result = EINVAL,
258 : };
259 :
260 1 : test_populate_gplink_list(NULL, false, &expected);
261 1 : test_populate_gplink_list("[malformed]", false, &expected);
262 : /* the GPLinkOptions value (after semicolon) must be between 0 and 3 */
263 1 : test_populate_gplink_list("[gpo_dn; 4]", false, &expected);
264 1 : }
265 :
266 : /*
267 : * Test sid-matching logic
268 : */
269 2 : static void test_ad_gpo_ace_includes_client_sid(const char *user_sid,
270 : const char **group_sids,
271 : int group_size,
272 : struct dom_sid ace_dom_sid,
273 : bool expected)
274 : {
275 : errno_t ret;
276 : enum idmap_error_code err;
277 : struct sss_idmap_ctx *idmap_ctx;
278 : bool includes_client_sid;
279 : TALLOC_CTX *tmp_ctx;
280 :
281 2 : tmp_ctx = talloc_new(global_talloc_context);
282 2 : assert_non_null(tmp_ctx);
283 2 : check_leaks_push(tmp_ctx);
284 :
285 2 : err = sss_idmap_init(sss_idmap_talloc, tmp_ctx, sss_idmap_talloc_free,
286 : &idmap_ctx);
287 2 : assert_int_equal(err, IDMAP_SUCCESS);
288 :
289 2 : ret = ad_gpo_ace_includes_client_sid(user_sid, group_sids, group_size,
290 : ace_dom_sid, idmap_ctx,
291 : &includes_client_sid);
292 2 : talloc_free(idmap_ctx);
293 :
294 2 : assert_int_equal(ret, EOK);
295 :
296 2 : assert_int_equal(includes_client_sid, expected);
297 :
298 2 : assert_true(check_leaks_pop(tmp_ctx) == true);
299 2 : talloc_free(tmp_ctx);
300 2 : }
301 :
302 1 : void test_ad_gpo_ace_includes_client_sid_true(void **state)
303 : {
304 : /* ace_dom_sid represents "S-1-5-21-2-3-4" */
305 1 : struct dom_sid ace_dom_sid = {1, 4, {0, 0, 0, 0, 0, 5}, {21, 2, 3, 4}};
306 :
307 1 : const char *user_sid = "S-1-5-21-1175337206-4250576914-2321192831-1103";
308 :
309 1 : int group_size = 2;
310 1 : const char *group_sids[] = {"S-1-5-21-2-3-4",
311 : "S-1-5-21-2-3-5"};
312 :
313 1 : test_ad_gpo_ace_includes_client_sid(user_sid, group_sids, group_size,
314 : ace_dom_sid, true);
315 1 : }
316 :
317 1 : void test_ad_gpo_ace_includes_client_sid_false(void **state)
318 : {
319 : /* ace_dom_sid represents "S-1-5-21-2-3-4" */
320 1 : struct dom_sid ace_dom_sid = {1, 4, {0, 0, 0, 0, 0, 5}, {21, 2, 3, 4}};
321 :
322 1 : const char *user_sid = "S-1-5-21-1175337206-4250576914-2321192831-1103";
323 :
324 1 : int group_size = 2;
325 1 : const char *group_sids[] = {"S-1-5-21-2-3-5",
326 : "S-1-5-21-2-3-6"};
327 :
328 1 : test_ad_gpo_ace_includes_client_sid(user_sid, group_sids, group_size,
329 : ace_dom_sid, false);
330 1 : }
331 :
332 1 : int main(int argc, const char *argv[])
333 : {
334 : poptContext pc;
335 : int opt;
336 6 : struct poptOption long_options[] = {
337 : POPT_AUTOHELP
338 5 : SSSD_DEBUG_OPTS
339 : POPT_TABLEEND
340 : };
341 :
342 1 : const struct CMUnitTest tests[] = {
343 : cmocka_unit_test_setup_teardown(test_populate_som_list_plain,
344 : ad_gpo_test_setup,
345 : ad_gpo_test_teardown),
346 : cmocka_unit_test_setup_teardown(test_populate_som_list_malformed,
347 : ad_gpo_test_setup,
348 : ad_gpo_test_teardown),
349 : cmocka_unit_test_setup_teardown(test_populate_gplink_list_plain,
350 : ad_gpo_test_setup,
351 : ad_gpo_test_teardown),
352 : cmocka_unit_test_setup_teardown(test_populate_gplink_list_with_ignored,
353 : ad_gpo_test_setup,
354 : ad_gpo_test_teardown),
355 : cmocka_unit_test_setup_teardown(test_populate_gplink_list_with_allow_enforced,
356 : ad_gpo_test_setup,
357 : ad_gpo_test_teardown),
358 : cmocka_unit_test_setup_teardown(test_populate_gplink_list_malformed,
359 : ad_gpo_test_setup,
360 : ad_gpo_test_teardown),
361 : cmocka_unit_test_setup_teardown(test_ad_gpo_ace_includes_client_sid_true,
362 : ad_gpo_test_setup,
363 : ad_gpo_test_teardown),
364 : cmocka_unit_test_setup_teardown(test_ad_gpo_ace_includes_client_sid_false,
365 : ad_gpo_test_setup,
366 : ad_gpo_test_teardown),
367 : };
368 :
369 : /* Set debug level to invalid value so we can deside if -d 0 was used. */
370 1 : debug_level = SSSDBG_INVALID;
371 :
372 1 : pc = poptGetContext(argv[0], argc, argv, long_options, 0);
373 1 : while((opt = poptGetNextOpt(pc)) != -1) {
374 : switch(opt) {
375 : default:
376 0 : fprintf(stderr, "\nInvalid option %s: %s\n\n",
377 : poptBadOption(pc, 0), poptStrerror(opt));
378 0 : poptPrintUsage(pc, stderr, 0);
379 0 : return 1;
380 : }
381 : }
382 1 : poptFreeContext(pc);
383 :
384 1 : DEBUG_CLI_INIT(debug_level);
385 :
386 1 : tests_set_cwd();
387 :
388 1 : return cmocka_run_group_tests(tests, NULL, NULL);
389 : }
|