Line data Source code
1 : /*
2 : Authors:
3 : Jakub Hrozek <jhrozek@redhat.com>
4 :
5 : Copyright (C) 2013 Red Hat
6 :
7 : SSSD tests: AD access control filter 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_common.c"
34 :
35 : #include "tests/cmocka/common_mock.h"
36 : #include "tests/cmocka/common_mock_krb5.h"
37 :
38 : #define DOMNAME "domname"
39 : #define SUBDOMNAME "sub."DOMNAME
40 : #define REALMNAME DOMNAME
41 : #define HOST_NAME "ad."REALMNAME
42 :
43 : #define TESTS_PATH "tp_" BASE_FILE_STEM
44 : #define TEST_AUTHID "host/"HOST_NAME
45 : #define KEYTAB_TEST_PRINC TEST_AUTHID"@"REALMNAME
46 : #define KEYTAB_PATH TESTS_PATH"/keytab_test.keytab"
47 :
48 : #define ONEWAY_DOMNAME "ONEWAY"
49 : #define ONEWAY_HOST_NAME "ad."ONEWAY_DOMNAME
50 :
51 : #define ONEWAY_KEYTAB_PATH TESTS_PATH"/oneway_test.keytab"
52 : #define ONEWAY_AUTHID "host/"ONEWAY_HOST_NAME
53 : #define ONEWAY_TEST_PRINC ONEWAY_AUTHID"@"ONEWAY_DOMNAME
54 :
55 : static bool call_real_sasl_options;
56 :
57 5 : krb5_error_code __wrap_krb5_kt_default(krb5_context context, krb5_keytab *id)
58 : {
59 5 : return krb5_kt_resolve(context, KEYTAB_PATH, id);
60 : }
61 :
62 : struct ad_common_test_ctx {
63 : struct ad_id_ctx *ad_ctx;
64 : struct ad_id_ctx *subdom_ad_ctx;
65 :
66 : struct sss_domain_info *dom;
67 : struct sss_domain_info *subdom;
68 : };
69 :
70 1 : static void test_ad_create_default_options(void **state)
71 : {
72 : struct ad_options *ad_options;
73 : const char *s;
74 :
75 1 : ad_options = ad_create_default_options(global_talloc_context);
76 :
77 1 : assert_non_null(ad_options->basic);
78 :
79 : /* Not too much to test here except some defaults */
80 1 : s = dp_opt_get_string(ad_options->basic, AD_DOMAIN);
81 1 : assert_null(s);
82 :
83 1 : assert_non_null(ad_options->id);
84 1 : }
85 :
86 6 : static int test_ad_common_setup(void **state)
87 : {
88 : struct ad_common_test_ctx *test_ctx;
89 :
90 6 : test_dom_suite_setup(TESTS_PATH);
91 :
92 6 : assert_true(leak_check_setup());
93 6 : check_leaks_push(global_talloc_context);
94 :
95 6 : test_ctx = talloc_zero(global_talloc_context, struct ad_common_test_ctx);
96 6 : assert_non_null(test_ctx);
97 :
98 6 : test_ctx->dom = talloc_zero(test_ctx, struct sss_domain_info);
99 6 : assert_non_null(test_ctx->dom);
100 6 : test_ctx->dom->name = discard_const(DOMNAME);
101 :
102 6 : test_ctx->subdom = talloc_zero(test_ctx, struct sss_domain_info);
103 6 : assert_non_null(test_ctx->subdom);
104 6 : test_ctx->subdom->name = discard_const(SUBDOMNAME);
105 6 : test_ctx->subdom->parent = test_ctx->dom;
106 :
107 6 : test_ctx->ad_ctx = talloc_zero(test_ctx, struct ad_id_ctx);
108 6 : assert_non_null(test_ctx->ad_ctx);
109 :
110 6 : check_leaks_push(test_ctx);
111 6 : *state = test_ctx;
112 6 : return 0;
113 : }
114 :
115 6 : static int test_ad_common_teardown(void **state)
116 : {
117 : int ret;
118 6 : struct ad_common_test_ctx *test_ctx = talloc_get_type(*state,
119 : struct ad_common_test_ctx);
120 6 : assert_non_null(test_ctx);
121 :
122 6 : assert_true(check_leaks_pop(test_ctx) == true);
123 6 : talloc_free(test_ctx);
124 6 : assert_true(check_leaks_pop(global_talloc_context) == true);
125 6 : assert_true(leak_check_teardown());
126 :
127 6 : ret = rmdir(TESTS_PATH);
128 6 : assert_return_code(ret, errno);
129 :
130 6 : return 0;
131 : }
132 :
133 1 : static void test_ad_create_1way_trust_options(void **state)
134 : {
135 1 : struct ad_common_test_ctx *test_ctx = talloc_get_type(*state,
136 : struct ad_common_test_ctx);
137 : const char *s;
138 :
139 1 : call_real_sasl_options = true;
140 : /* Make sure this is not the keytab that __wrap_krb5_kt_default uses */
141 1 : mock_keytab_with_contents(test_ctx, ONEWAY_KEYTAB_PATH, ONEWAY_TEST_PRINC);
142 :
143 2 : test_ctx->ad_ctx->ad_options = ad_create_1way_trust_options(
144 1 : test_ctx->ad_ctx,
145 : ONEWAY_DOMNAME,
146 : ONEWAY_HOST_NAME,
147 : ONEWAY_KEYTAB_PATH,
148 : ONEWAY_AUTHID);
149 1 : assert_non_null(test_ctx->ad_ctx->ad_options);
150 :
151 1 : assert_int_equal(test_ctx->ad_ctx->ad_options->id->schema_type,
152 : SDAP_SCHEMA_AD);
153 :
154 1 : s = dp_opt_get_string(test_ctx->ad_ctx->ad_options->basic,
155 : AD_KRB5_REALM);
156 1 : assert_non_null(s);
157 1 : assert_string_equal(s, ONEWAY_DOMNAME);
158 :
159 1 : s = dp_opt_get_string(test_ctx->ad_ctx->ad_options->basic,
160 : AD_DOMAIN);
161 1 : assert_non_null(s);
162 1 : assert_string_equal(s, ONEWAY_DOMNAME);
163 :
164 1 : s = dp_opt_get_string(test_ctx->ad_ctx->ad_options->basic,
165 : AD_HOSTNAME);
166 1 : assert_non_null(s);
167 1 : assert_string_equal(s, ONEWAY_HOST_NAME);
168 :
169 1 : s = dp_opt_get_string(test_ctx->ad_ctx->ad_options->basic,
170 : AD_KEYTAB);
171 1 : assert_non_null(s);
172 1 : assert_string_equal(s, ONEWAY_KEYTAB_PATH);
173 :
174 1 : s = dp_opt_get_string(test_ctx->ad_ctx->ad_options->id->basic,
175 : SDAP_KRB5_KEYTAB);
176 1 : assert_non_null(s);
177 :
178 1 : s = dp_opt_get_string(test_ctx->ad_ctx->ad_options->id->basic,
179 : SDAP_SASL_REALM);
180 1 : assert_non_null(s);
181 1 : assert_string_equal(s, ONEWAY_DOMNAME);
182 :
183 1 : s = dp_opt_get_string(test_ctx->ad_ctx->ad_options->id->basic,
184 : SDAP_KRB5_REALM);
185 1 : assert_non_null(s);
186 1 : assert_string_equal(s, ONEWAY_DOMNAME);
187 :
188 1 : s = dp_opt_get_string(test_ctx->ad_ctx->ad_options->id->basic,
189 : SDAP_SASL_AUTHID);
190 1 : assert_non_null(s);
191 1 : assert_string_equal(s, ONEWAY_AUTHID);
192 :
193 1 : talloc_free(test_ctx->ad_ctx->ad_options);
194 :
195 1 : unlink(ONEWAY_KEYTAB_PATH);
196 1 : }
197 1 : static void test_ad_create_2way_trust_options(void **state)
198 : {
199 1 : struct ad_common_test_ctx *test_ctx = talloc_get_type(*state,
200 : struct ad_common_test_ctx);
201 : const char *s;
202 :
203 1 : call_real_sasl_options = true;
204 1 : mock_keytab_with_contents(test_ctx, KEYTAB_PATH, KEYTAB_TEST_PRINC);
205 :
206 2 : test_ctx->ad_ctx->ad_options = ad_create_2way_trust_options(
207 1 : test_ctx->ad_ctx,
208 : REALMNAME,
209 : DOMNAME,
210 : HOST_NAME);
211 1 : assert_non_null(test_ctx->ad_ctx->ad_options);
212 :
213 1 : assert_int_equal(test_ctx->ad_ctx->ad_options->id->schema_type,
214 : SDAP_SCHEMA_AD);
215 :
216 1 : s = dp_opt_get_string(test_ctx->ad_ctx->ad_options->basic,
217 : AD_KRB5_REALM);
218 1 : assert_non_null(s);
219 1 : assert_string_equal(s, REALMNAME);
220 :
221 1 : s = dp_opt_get_string(test_ctx->ad_ctx->ad_options->basic,
222 : AD_DOMAIN);
223 1 : assert_non_null(s);
224 1 : assert_string_equal(s, DOMNAME);
225 :
226 1 : s = dp_opt_get_string(test_ctx->ad_ctx->ad_options->basic,
227 : AD_HOSTNAME);
228 1 : assert_non_null(s);
229 1 : assert_string_equal(s, HOST_NAME);
230 :
231 1 : s = dp_opt_get_string(test_ctx->ad_ctx->ad_options->id->basic,
232 : SDAP_KRB5_KEYTAB);
233 1 : assert_null(s); /* This is the system keytab */
234 :
235 1 : s = dp_opt_get_string(test_ctx->ad_ctx->ad_options->id->basic,
236 : SDAP_SASL_REALM);
237 1 : assert_non_null(s);
238 1 : assert_string_equal(s, REALMNAME);
239 :
240 1 : s = dp_opt_get_string(test_ctx->ad_ctx->ad_options->id->basic,
241 : SDAP_KRB5_REALM);
242 1 : assert_non_null(s);
243 1 : assert_string_equal(s, REALMNAME);
244 :
245 1 : s = dp_opt_get_string(test_ctx->ad_ctx->ad_options->id->basic,
246 : SDAP_SASL_AUTHID);
247 1 : assert_non_null(s);
248 1 : assert_string_equal(s, TEST_AUTHID);
249 :
250 1 : talloc_free(test_ctx->ad_ctx->ad_options);
251 :
252 1 : unlink(KEYTAB_PATH);
253 1 : }
254 :
255 : static int
256 4 : test_ldap_conn_setup(void **state)
257 : {
258 : struct ad_common_test_ctx *test_ctx;
259 : errno_t ret;
260 : struct sdap_domain *sdom;
261 : struct ad_id_ctx *ad_ctx;
262 : struct ad_id_ctx *subdom_ad_ctx;
263 : struct sdap_id_conn_ctx *subdom_ldap_ctx;
264 :
265 4 : ret = test_ad_common_setup((void **) &test_ctx);
266 4 : assert_int_equal(ret, EOK);
267 :
268 4 : mock_keytab_with_contents(test_ctx, KEYTAB_PATH, KEYTAB_TEST_PRINC);
269 :
270 4 : ad_ctx = test_ctx->ad_ctx;
271 :
272 4 : ad_ctx->ad_options = ad_create_2way_trust_options(ad_ctx,
273 : REALMNAME,
274 : DOMNAME,
275 : HOST_NAME);
276 4 : assert_non_null(ad_ctx->ad_options);
277 :
278 4 : ad_ctx->gc_ctx = talloc_zero(ad_ctx, struct sdap_id_conn_ctx);
279 4 : assert_non_null(ad_ctx->gc_ctx);
280 :
281 4 : ad_ctx->ldap_ctx = talloc_zero(ad_ctx, struct sdap_id_conn_ctx);
282 4 : assert_non_null(ad_ctx->ldap_ctx);
283 :
284 4 : ad_ctx->sdap_id_ctx = talloc_zero(ad_ctx, struct sdap_id_ctx);
285 4 : assert_non_null(ad_ctx->sdap_id_ctx);
286 :
287 4 : ad_ctx->sdap_id_ctx->opts = talloc_zero(ad_ctx->sdap_id_ctx,
288 : struct sdap_options);
289 4 : assert_non_null(ad_ctx->sdap_id_ctx->opts);
290 :
291 4 : ret = sdap_domain_add(ad_ctx->sdap_id_ctx->opts, test_ctx->dom, &sdom);
292 4 : assert_int_equal(ret, EOK);
293 4 : sdom->pvt = ad_ctx;
294 :
295 4 : subdom_ad_ctx = talloc_zero(test_ctx, struct ad_id_ctx);
296 4 : assert_non_null(subdom_ad_ctx);
297 :
298 4 : subdom_ldap_ctx = talloc_zero(subdom_ad_ctx, struct sdap_id_conn_ctx);
299 4 : assert_non_null(subdom_ldap_ctx);
300 4 : subdom_ad_ctx->ldap_ctx = subdom_ldap_ctx;
301 :
302 4 : ret = sdap_domain_add(ad_ctx->sdap_id_ctx->opts, test_ctx->subdom, &sdom);
303 4 : assert_int_equal(ret, EOK);
304 4 : sdom->pvt = subdom_ad_ctx;
305 :
306 4 : test_ctx->subdom_ad_ctx = subdom_ad_ctx;
307 :
308 4 : *state = test_ctx;
309 4 : return 0;
310 : }
311 :
312 : static int
313 4 : test_ldap_conn_teardown(void **state)
314 : {
315 4 : struct ad_common_test_ctx *test_ctx = talloc_get_type(*state,
316 : struct ad_common_test_ctx);
317 4 : assert_non_null(test_ctx);
318 :
319 4 : unlink(KEYTAB_PATH);
320 :
321 4 : talloc_free(test_ctx->subdom_ad_ctx);
322 4 : talloc_free(test_ctx->ad_ctx->ad_options);
323 4 : talloc_free(test_ctx->ad_ctx->gc_ctx);
324 4 : talloc_free(test_ctx->ad_ctx->ldap_ctx);
325 4 : talloc_free(test_ctx->ad_ctx->sdap_id_ctx);
326 :
327 4 : test_ad_common_teardown((void **) &test_ctx);
328 4 : return 0;
329 : }
330 :
331 : errno_t
332 : __real_sdap_set_sasl_options(struct sdap_options *id_opts,
333 : char *default_primary,
334 : char *default_realm,
335 : const char *keytab_path);
336 : errno_t
337 6 : __wrap_sdap_set_sasl_options(struct sdap_options *id_opts,
338 : char *default_primary,
339 : char *default_realm,
340 : const char *keytab_path)
341 : {
342 : /* Pretend SASL is fine */
343 6 : if (call_real_sasl_options == true) {
344 6 : return __real_sdap_set_sasl_options(id_opts,
345 : default_primary,
346 : default_realm,
347 : keytab_path);
348 : }
349 :
350 0 : return EOK;
351 : }
352 :
353 1 : void test_ad_get_dom_ldap_conn(void **state)
354 : {
355 : struct sdap_id_conn_ctx *conn;
356 :
357 1 : struct ad_common_test_ctx *test_ctx = talloc_get_type(*state,
358 : struct ad_common_test_ctx);
359 1 : assert_non_null(test_ctx);
360 :
361 1 : conn = ad_get_dom_ldap_conn(test_ctx->ad_ctx, test_ctx->dom);
362 1 : assert_true(conn == test_ctx->ad_ctx->ldap_ctx);
363 :
364 1 : conn = ad_get_dom_ldap_conn(test_ctx->ad_ctx, test_ctx->subdom);
365 1 : assert_true(conn == test_ctx->subdom_ad_ctx->ldap_ctx);
366 1 : }
367 :
368 1 : void test_gc_conn_list(void **state)
369 : {
370 : struct sdap_id_conn_ctx **conn_list;
371 :
372 1 : struct ad_common_test_ctx *test_ctx = talloc_get_type(*state,
373 : struct ad_common_test_ctx);
374 1 : assert_non_null(test_ctx);
375 :
376 1 : assert_true(dp_opt_get_bool(test_ctx->ad_ctx->ad_options->basic,
377 : AD_ENABLE_GC));
378 1 : conn_list = ad_gc_conn_list(test_ctx, test_ctx->ad_ctx, test_ctx->dom);
379 1 : assert_non_null(conn_list);
380 :
381 1 : assert_true(conn_list[0] == test_ctx->ad_ctx->gc_ctx);
382 : /* If there is a fallback, we should ignore the offline mode */
383 1 : assert_true(conn_list[0]->ignore_mark_offline);
384 1 : assert_true(conn_list[1] == test_ctx->ad_ctx->ldap_ctx);
385 1 : assert_false(conn_list[1]->ignore_mark_offline);
386 1 : assert_null(conn_list[2]);
387 1 : talloc_free(conn_list);
388 :
389 1 : conn_list = ad_gc_conn_list(test_ctx, test_ctx->ad_ctx, test_ctx->subdom);
390 1 : assert_non_null(conn_list);
391 :
392 1 : assert_true(conn_list[0] == test_ctx->ad_ctx->gc_ctx);
393 1 : assert_true(conn_list[0]->ignore_mark_offline);
394 1 : assert_true(conn_list[1] == test_ctx->subdom_ad_ctx->ldap_ctx);
395 : /* Subdomain error should not set the backend offline! */
396 1 : assert_true(conn_list[1]->ignore_mark_offline);
397 1 : talloc_free(conn_list);
398 :
399 1 : dp_opt_set_bool(test_ctx->ad_ctx->ad_options->basic, AD_ENABLE_GC, false);
400 1 : assert_false(dp_opt_get_bool(test_ctx->ad_ctx->ad_options->basic,
401 : AD_ENABLE_GC));
402 :
403 1 : conn_list = ad_gc_conn_list(test_ctx, test_ctx->ad_ctx, test_ctx->dom);
404 1 : assert_non_null(conn_list);
405 :
406 1 : assert_true(conn_list[0] == test_ctx->ad_ctx->ldap_ctx);
407 1 : assert_false(conn_list[0]->ignore_mark_offline);
408 1 : assert_null(conn_list[1]);
409 1 : talloc_free(conn_list);
410 :
411 1 : conn_list = ad_gc_conn_list(test_ctx, test_ctx->ad_ctx, test_ctx->subdom);
412 1 : assert_non_null(conn_list);
413 :
414 1 : assert_true(conn_list[0] == test_ctx->subdom_ad_ctx->ldap_ctx);
415 1 : assert_true(conn_list[0]->ignore_mark_offline);
416 1 : assert_null(conn_list[1]);
417 1 : talloc_free(conn_list);
418 1 : }
419 :
420 1 : void test_ldap_conn_list(void **state)
421 : {
422 : struct sdap_id_conn_ctx **conn_list;
423 :
424 1 : struct ad_common_test_ctx *test_ctx = talloc_get_type(*state,
425 : struct ad_common_test_ctx);
426 1 : assert_non_null(test_ctx);
427 :
428 1 : conn_list = ad_ldap_conn_list(test_ctx,
429 : test_ctx->ad_ctx,
430 : test_ctx->dom);
431 1 : assert_non_null(conn_list);
432 :
433 1 : assert_true(conn_list[0] == test_ctx->ad_ctx->ldap_ctx);
434 1 : assert_false(conn_list[0]->ignore_mark_offline);
435 1 : assert_null(conn_list[1]);
436 1 : talloc_free(conn_list);
437 :
438 1 : conn_list = ad_ldap_conn_list(test_ctx,
439 : test_ctx->ad_ctx,
440 : test_ctx->subdom);
441 1 : assert_non_null(conn_list);
442 :
443 1 : assert_true(conn_list[0] == test_ctx->subdom_ad_ctx->ldap_ctx);
444 1 : assert_true(conn_list[0]->ignore_mark_offline);
445 1 : assert_null(conn_list[1]);
446 1 : talloc_free(conn_list);
447 1 : }
448 :
449 1 : void test_user_conn_list(void **state)
450 : {
451 : struct sdap_id_conn_ctx **conn_list;
452 :
453 1 : struct ad_common_test_ctx *test_ctx = talloc_get_type(*state,
454 : struct ad_common_test_ctx);
455 1 : assert_non_null(test_ctx);
456 :
457 1 : conn_list = ad_user_conn_list(test_ctx,
458 : test_ctx->ad_ctx,
459 : test_ctx->dom);
460 1 : assert_non_null(conn_list);
461 :
462 1 : assert_true(conn_list[0] == test_ctx->ad_ctx->ldap_ctx);
463 1 : assert_false(conn_list[0]->ignore_mark_offline);
464 1 : assert_null(conn_list[1]);
465 1 : talloc_free(conn_list);
466 :
467 1 : conn_list = ad_user_conn_list(test_ctx,
468 : test_ctx->ad_ctx,
469 : test_ctx->subdom);
470 1 : assert_non_null(conn_list);
471 :
472 1 : assert_true(conn_list[0] == test_ctx->ad_ctx->gc_ctx);
473 1 : assert_true(conn_list[0]->ignore_mark_offline);
474 1 : assert_true(conn_list[1] == test_ctx->subdom_ad_ctx->ldap_ctx);
475 : /* Subdomain error should not set the backend offline! */
476 1 : assert_true(conn_list[1]->ignore_mark_offline);
477 1 : talloc_free(conn_list);
478 1 : }
479 :
480 1 : int main(int argc, const char *argv[])
481 : {
482 : poptContext pc;
483 : int opt;
484 6 : struct poptOption long_options[] = {
485 : POPT_AUTOHELP
486 5 : SSSD_DEBUG_OPTS
487 : POPT_TABLEEND
488 : };
489 :
490 1 : const struct CMUnitTest tests[] = {
491 : cmocka_unit_test(test_ad_create_default_options),
492 : cmocka_unit_test_setup_teardown(test_ad_create_1way_trust_options,
493 : test_ad_common_setup,
494 : test_ad_common_teardown),
495 : cmocka_unit_test_setup_teardown(test_ad_create_2way_trust_options,
496 : test_ad_common_setup,
497 : test_ad_common_teardown),
498 : cmocka_unit_test_setup_teardown(test_ad_get_dom_ldap_conn,
499 : test_ldap_conn_setup,
500 : test_ldap_conn_teardown),
501 : cmocka_unit_test_setup_teardown(test_gc_conn_list,
502 : test_ldap_conn_setup,
503 : test_ldap_conn_teardown),
504 : cmocka_unit_test_setup_teardown(test_ldap_conn_list,
505 : test_ldap_conn_setup,
506 : test_ldap_conn_teardown),
507 : cmocka_unit_test_setup_teardown(test_user_conn_list,
508 : test_ldap_conn_setup,
509 : test_ldap_conn_teardown),
510 : };
511 :
512 : /* Set debug level to invalid value so we can deside if -d 0 was used. */
513 1 : debug_level = SSSDBG_INVALID;
514 :
515 1 : pc = poptGetContext(argv[0], argc, argv, long_options, 0);
516 1 : while((opt = poptGetNextOpt(pc)) != -1) {
517 : switch(opt) {
518 : default:
519 0 : fprintf(stderr, "\nInvalid option %s: %s\n\n",
520 : poptBadOption(pc, 0), poptStrerror(opt));
521 0 : poptPrintUsage(pc, stderr, 0);
522 0 : return 1;
523 : }
524 : }
525 1 : poptFreeContext(pc);
526 :
527 1 : DEBUG_CLI_INIT(debug_level);
528 :
529 1 : tests_set_cwd();
530 :
531 1 : return cmocka_run_group_tests(tests, NULL, NULL);
532 : }
|