Line data Source code
1 : /*
2 : SSSD
3 :
4 : Kerberos 5 Backend Module -- Utilities tests
5 :
6 : Authors:
7 : Sumit Bose <sbose@redhat.com>
8 :
9 : Copyright (C) 2009 Red Hat
10 :
11 : This program is free software; you can redistribute it and/or modify
12 : it under the terms of the GNU General Public License as published by
13 : the Free Software Foundation; either version 3 of the License, or
14 : (at your option) any later version.
15 :
16 : This program is distributed in the hope that it will be useful,
17 : but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : GNU General Public License for more details.
20 :
21 : You should have received a copy of the GNU General Public License
22 : along with this program. If not, see <http://www.gnu.org/licenses/>.
23 : */
24 :
25 : #include <stdlib.h>
26 : #include <popt.h>
27 : #include <check.h>
28 :
29 : #include "providers/krb5/krb5_utils.h"
30 : #include "providers/krb5/krb5_ccache.h"
31 : #include "providers/krb5/krb5_auth.h"
32 : #include "util/sss_utf8.h"
33 : #include "tests/common.h"
34 :
35 : #define TESTS_PATH "tp_" BASE_FILE_STEM
36 :
37 : #define BASE "/abc/def"
38 : #define FILENAME "ghi"
39 :
40 : #define USERNAME "testuser"
41 : #define UID "12345"
42 : #define PRINCIPAL_NAME "testuser@EXAMPLE.COM"
43 : #define REALM "REALM.ORG"
44 : #define HOME_DIRECTORY "/home/testuser"
45 : #define CCACHE_DIR "/var/tmp"
46 : #define PID "4321"
47 :
48 : extern struct dp_option default_krb5_opts[];
49 :
50 : TALLOC_CTX *tmp_ctx = NULL;
51 : struct krb5child_req *kr;
52 :
53 : #define RMDIR(__dir__) do { \
54 : ret = rmdir(__dir__); \
55 : fail_unless(ret == EOK, "rmdir [%s] failed, [%d][%s].", __dir__, \
56 : errno, strerror(errno)); \
57 : } while(0)
58 :
59 2 : void setup_create_dir(void)
60 : {
61 2 : fail_unless(tmp_ctx == NULL, "Talloc context already initialized.");
62 2 : tmp_ctx = talloc_new(NULL);
63 2 : fail_unless(tmp_ctx != NULL, "Cannot create talloc context.");
64 2 : }
65 :
66 2 : void teardown_create_dir(void)
67 : {
68 : int ret;
69 2 : fail_unless(tmp_ctx != NULL, "Talloc context already freed.");
70 2 : ret = talloc_free(tmp_ctx);
71 2 : tmp_ctx = NULL;
72 2 : fail_unless(ret == 0, "Cannot free talloc context.");
73 2 : }
74 :
75 0 : static void check_dir(const char *dirname, uid_t uid, gid_t gid, mode_t mode)
76 : {
77 : struct stat stat_buf;
78 : int ret;
79 :
80 0 : ret = stat(dirname, &stat_buf);
81 0 : fail_unless(ret == EOK, "stat failed [%d][%s].", errno, strerror(errno));
82 :
83 0 : fail_unless(S_ISDIR(stat_buf.st_mode), "[%s] is not a directory.", dirname);
84 0 : fail_unless(stat_buf.st_uid == uid, "uid does not match, "
85 : "expected [%d], got [%d].",
86 : uid, stat_buf.st_uid);
87 0 : fail_unless(stat_buf.st_gid == gid, "gid does not match, "
88 : "expected [%d], got [%d].",
89 : gid, stat_buf.st_gid);
90 0 : fail_unless((stat_buf.st_mode & ~S_IFMT) == mode,
91 : "mode of [%s] does not match, "
92 : "expected [%o], got [%o].", dirname,
93 : mode, (stat_buf.st_mode & ~S_IFMT));
94 0 : }
95 :
96 0 : START_TEST(test_private_ccache_dir_in_user_dir)
97 : {
98 : int ret;
99 : char *cwd;
100 : char *user_dir;
101 : char *dn1;
102 : char *dn2;
103 : char *dn3;
104 : char *filename;
105 0 : uid_t uid = getuid();
106 0 : gid_t gid = getgid();
107 :
108 0 : if (uid == 0) {
109 0 : uid = 12345;
110 0 : gid = 12345;
111 : }
112 :
113 0 : cwd = getcwd(NULL, 0);
114 0 : fail_unless(cwd != NULL, "getcwd failed.");
115 :
116 0 : user_dir = talloc_asprintf(tmp_ctx, "%s/%s/user", cwd, TESTS_PATH);
117 0 : free(cwd);
118 0 : fail_unless(user_dir != NULL, "talloc_asprintf failed.");
119 0 : ret = mkdir(user_dir, 0700);
120 0 : fail_unless(ret == EOK, "mkdir failed.");
121 0 : ret = chown(user_dir, uid, gid);
122 0 : fail_unless(ret == EOK, "chown failed.");
123 :
124 0 : dn1 = talloc_asprintf(tmp_ctx, "%s/a", user_dir);
125 0 : fail_unless(dn1 != NULL, "talloc_asprintf failed.");
126 0 : dn2 = talloc_asprintf(tmp_ctx, "%s/b", dn1);
127 0 : fail_unless(dn2 != NULL, "talloc_asprintf failed.");
128 0 : dn3 = talloc_asprintf(tmp_ctx, "%s/c", dn2);
129 0 : fail_unless(dn3 != NULL, "talloc_asprintf failed.");
130 0 : filename = talloc_asprintf(tmp_ctx, "%s/ccfile", dn3);
131 0 : fail_unless(filename != NULL, "talloc_asprintf failed.");
132 :
133 0 : ret = chmod(user_dir, 0600);
134 0 : fail_unless(ret == EOK, "chmod failed.");
135 0 : ret = sss_krb5_precreate_ccache(filename, uid, gid);
136 0 : fail_unless(ret == EINVAL, "sss_krb5_precreate_ccache does not return EINVAL "
137 : "while x-bit is missing.");
138 :
139 0 : ret = chmod(user_dir, 0700);
140 0 : fail_unless(ret == EOK, "chmod failed.");
141 0 : ret = sss_krb5_precreate_ccache(filename, uid, gid);
142 0 : fail_unless(ret == EOK, "sss_krb5_precreate_ccache failed.");
143 :
144 0 : check_dir(dn3, uid, gid, 0700);
145 0 : RMDIR(dn3);
146 0 : check_dir(dn2, uid, gid, 0700);
147 0 : RMDIR(dn2);
148 0 : check_dir(dn1, uid, gid, 0700);
149 0 : RMDIR(dn1);
150 0 : RMDIR(user_dir);
151 : }
152 0 : END_TEST
153 :
154 0 : START_TEST(test_private_ccache_dir_in_wrong_user_dir)
155 : {
156 : int ret;
157 : char *cwd;
158 : char *dirname;
159 : char *subdirname;
160 : char *filename;
161 :
162 0 : fail_unless(getuid() == 0, "This test must be run as root.");
163 :
164 0 : cwd = getcwd(NULL, 0);
165 0 : fail_unless(cwd != NULL, "getcwd failed.");
166 :
167 0 : dirname = talloc_asprintf(tmp_ctx, "%s/%s/priv_ccdir", cwd, TESTS_PATH);
168 0 : free(cwd);
169 0 : fail_unless(dirname != NULL, "talloc_asprintf failed.");
170 0 : ret = mkdir(dirname, 0700);
171 0 : fail_unless(ret == EOK, "mkdir failed.\n");
172 0 : ret = chown(dirname, 12346, 12346);
173 0 : fail_unless(ret == EOK, "chown failed.\n");
174 0 : subdirname = talloc_asprintf(tmp_ctx, "%s/subdir", dirname);
175 0 : fail_unless(subdirname != NULL, "talloc_asprintf failed.");
176 0 : filename = talloc_asprintf(tmp_ctx, "%s/ccfile", subdirname);
177 0 : fail_unless(filename != NULL, "talloc_asprintf failed.");
178 :
179 0 : ret = sss_krb5_precreate_ccache(filename, 12345, 12345);
180 0 : fail_unless(ret == EINVAL, "Creating private ccache dir in wrong user "
181 : "dir does not failed with EINVAL.");
182 :
183 0 : RMDIR(dirname);
184 : }
185 0 : END_TEST
186 :
187 1 : START_TEST(test_illegal_patterns)
188 : {
189 : char *cwd;
190 : char *dirname;
191 : char *filename;
192 : pcre *illegal_re;
193 : const char *errstr;
194 : int errval;
195 : int errpos;
196 1 : char *result = NULL;
197 :
198 1 : illegal_re = pcre_compile2(ILLEGAL_PATH_PATTERN, 0,
199 : &errval, &errstr, &errpos, NULL);
200 1 : fail_unless(illegal_re != NULL, "Invalid Regular Expression pattern at "
201 : " position %d. (Error: %d [%s])\n",
202 : errpos, errval, errstr);
203 :
204 1 : cwd = getcwd(NULL, 0);
205 1 : fail_unless(cwd != NULL, "getcwd failed.");
206 :
207 1 : dirname = talloc_asprintf(tmp_ctx, "%s/%s/priv_ccdir", cwd, TESTS_PATH);
208 1 : free(cwd);
209 1 : fail_unless(dirname != NULL, "talloc_asprintf failed.");
210 :
211 1 : result = expand_ccname_template(tmp_ctx, kr, "abc/./ccfile", illegal_re, true, true);
212 1 : fail_unless(result == NULL, "expand_ccname_template allowed relative path\n");
213 :
214 1 : filename = talloc_asprintf(tmp_ctx, "%s/abc/./ccfile", dirname);
215 1 : fail_unless(filename != NULL, "talloc_asprintf failed.");
216 1 : result = expand_ccname_template(tmp_ctx, kr, filename, illegal_re, true, true);
217 1 : fail_unless(result == NULL, "expand_ccname_template allowed "
218 : "illegal pattern '/./'\n");
219 :
220 1 : filename = talloc_asprintf(tmp_ctx, "%s/abc/../ccfile", dirname);
221 1 : fail_unless(filename != NULL, "talloc_asprintf failed.");
222 1 : result = expand_ccname_template(tmp_ctx, kr, filename, illegal_re, true, true);
223 1 : fail_unless(result == NULL, "expand_ccname_template allowed "
224 : "illegal pattern '/../' in filename [%s].",
225 : filename);
226 :
227 1 : filename = talloc_asprintf(tmp_ctx, "%s/abc//ccfile", dirname);
228 1 : fail_unless(filename != NULL, "talloc_asprintf failed.");
229 1 : result = expand_ccname_template(tmp_ctx, kr, filename, illegal_re, true, true);
230 1 : fail_unless(result == NULL, "expand_ccname_template allowed "
231 : "illegal pattern '//' in filename [%s].",
232 : filename);
233 :
234 1 : pcre_free(illegal_re);
235 : }
236 1 : END_TEST
237 :
238 1 : START_TEST(test_cc_dir_create)
239 : {
240 : char *residual;
241 : char *dirname;
242 : char *cwd;
243 1 : uid_t uid = getuid();
244 1 : gid_t gid = getgid();
245 : errno_t ret;
246 :
247 1 : cwd = getcwd(NULL, 0);
248 1 : fail_unless(cwd != NULL, "getcwd failed.");
249 :
250 1 : dirname = talloc_asprintf(tmp_ctx, "%s/%s/user_dir",
251 : cwd, TESTS_PATH);
252 1 : fail_unless(dirname != NULL, "talloc_asprintf failed.");
253 1 : residual = talloc_asprintf(tmp_ctx, "DIR:%s/%s", dirname, "ccdir");
254 1 : fail_unless(residual != NULL, "talloc_asprintf failed.");
255 :
256 1 : ret = sss_krb5_precreate_ccache(residual, uid, gid);
257 1 : fail_unless(ret == EOK, "sss_krb5_precreate_ccache failed\n");
258 1 : ret = rmdir(dirname);
259 1 : if (ret < 0) ret = errno;
260 1 : fail_unless(ret == 0, "Cannot remove %s: %s\n", dirname, strerror(ret));
261 1 : talloc_free(residual);
262 :
263 1 : dirname = talloc_asprintf(tmp_ctx, "%s/%s/user_dir2",
264 : cwd, TESTS_PATH);
265 1 : fail_unless(dirname != NULL, "talloc_asprintf failed.");
266 1 : residual = talloc_asprintf(tmp_ctx, "DIR:%s/%s", dirname, "ccdir/");
267 1 : fail_unless(residual != NULL, "talloc_asprintf failed.");
268 :
269 1 : ret = sss_krb5_precreate_ccache(residual, uid, gid);
270 1 : fail_unless(ret == EOK, "sss_krb5_precreate_ccache failed\n");
271 1 : ret = rmdir(dirname);
272 1 : if (ret < 0) ret = errno;
273 1 : fail_unless(ret == 0, "Cannot remove %s: %s\n", dirname, strerror(ret));
274 1 : talloc_free(residual);
275 1 : free(cwd);
276 : }
277 1 : END_TEST
278 :
279 :
280 14 : void setup_talloc_context(void)
281 : {
282 : int ret;
283 : int i;
284 :
285 : struct pam_data *pd;
286 : struct krb5_ctx *krb5_ctx;
287 14 : fail_unless(tmp_ctx == NULL, "Talloc context already initialized.");
288 14 : tmp_ctx = talloc_new(NULL);
289 14 : fail_unless(tmp_ctx != NULL, "Cannot create talloc context.");
290 :
291 14 : kr = talloc_zero(tmp_ctx, struct krb5child_req);
292 14 : fail_unless(kr != NULL, "Cannot create krb5child_req structure.");
293 :
294 14 : pd = create_pam_data(tmp_ctx);
295 14 : fail_unless(pd != NULL, "Cannot create pam_data structure.");
296 :
297 14 : krb5_ctx = talloc_zero(tmp_ctx, struct krb5_ctx);
298 14 : fail_unless(pd != NULL, "Cannot create krb5_ctx structure.");
299 :
300 14 : pd->user = discard_const(USERNAME);
301 14 : kr->uid = atoi(UID);
302 14 : kr->upn = discard_const(PRINCIPAL_NAME);
303 14 : pd->cli_pid = atoi(PID);
304 :
305 14 : krb5_ctx->opts = talloc_zero_array(tmp_ctx, struct dp_option, KRB5_OPTS);
306 14 : fail_unless(krb5_ctx->opts != NULL, "Cannot created options.");
307 294 : for (i = 0; i < KRB5_OPTS; i++) {
308 280 : krb5_ctx->opts[i].opt_name = default_krb5_opts[i].opt_name;
309 280 : krb5_ctx->opts[i].type = default_krb5_opts[i].type;
310 280 : krb5_ctx->opts[i].def_val = default_krb5_opts[i].def_val;
311 : }
312 14 : ret = dp_opt_set_string(krb5_ctx->opts, KRB5_REALM, REALM);
313 14 : fail_unless(ret == EOK, "Failed to set Realm");
314 14 : ret = dp_opt_set_string(krb5_ctx->opts, KRB5_CCACHEDIR, CCACHE_DIR);
315 14 : fail_unless(ret == EOK, "Failed to set Ccache dir");
316 :
317 14 : kr->homedir = HOME_DIRECTORY;
318 :
319 14 : kr->pd = pd;
320 14 : kr->krb5_ctx = krb5_ctx;
321 :
322 14 : }
323 :
324 14 : void free_talloc_context(void)
325 : {
326 : int ret;
327 14 : fail_unless(tmp_ctx != NULL, "Talloc context already freed.");
328 14 : ret = talloc_free(tmp_ctx);
329 14 : tmp_ctx = NULL;
330 14 : fail_unless(ret == 0, "Cannot free talloc context.");
331 14 : }
332 :
333 16 : static void do_test(const char *file_template, const char *dir_template,
334 : const char *expected)
335 : {
336 : char *result;
337 : int ret;
338 :
339 16 : ret = dp_opt_set_string(kr->krb5_ctx->opts, KRB5_CCACHEDIR, dir_template);
340 16 : fail_unless(ret == EOK, "Failed to set Ccache dir");
341 :
342 16 : result = expand_ccname_template(tmp_ctx, kr, file_template, NULL, true, true);
343 :
344 16 : fail_unless(result != NULL, "Cannot expand template [%s].", file_template);
345 16 : fail_unless(strcmp(result, expected) == 0,
346 : "Expansion failed, result [%s], expected [%s].",
347 : result, expected);
348 16 : }
349 :
350 1 : START_TEST(test_multiple_substitutions)
351 : {
352 1 : do_test(BASE"_%u_%U_%u", CCACHE_DIR, BASE"_"USERNAME"_"UID"_"USERNAME);
353 1 : do_test("%d/"FILENAME, BASE"_%u_%U_%u",
354 : BASE"_"USERNAME"_"UID"_"USERNAME"/"FILENAME);
355 : }
356 1 : END_TEST
357 :
358 1 : START_TEST(test_username)
359 : {
360 1 : do_test(BASE"_%u", CCACHE_DIR, BASE"_"USERNAME);
361 1 : do_test("%d/"FILENAME, BASE"_%u", BASE"_"USERNAME"/"FILENAME);
362 : }
363 1 : END_TEST
364 :
365 1 : START_TEST(test_case_sensitive)
366 : {
367 : char *result;
368 : int ret;
369 1 : const char *file_template = BASE"_%u";
370 1 : const char *expected_cs = BASE"_TestUser";
371 1 : const char *expected_ci = BASE"_testuser";
372 :
373 1 : kr->pd->user = discard_const("TestUser");
374 1 : ret = dp_opt_set_string(kr->krb5_ctx->opts, KRB5_CCACHEDIR, CCACHE_DIR);
375 1 : fail_unless(ret == EOK, "Failed to set Ccache dir");
376 :
377 1 : result = expand_ccname_template(tmp_ctx, kr, file_template, NULL, true, true);
378 :
379 1 : fail_unless(result != NULL, "Cannot expand template [%s].", file_template);
380 1 : fail_unless(strcmp(result, expected_cs) == 0,
381 : "Expansion failed, result [%s], expected [%s].",
382 : result, expected_cs);
383 :
384 1 : result = expand_ccname_template(tmp_ctx, kr, file_template, NULL, true, false);
385 :
386 1 : fail_unless(result != NULL, "Cannot expand template [%s].", file_template);
387 1 : fail_unless(strcmp(result, expected_ci) == 0,
388 : "Expansion failed, result [%s], expected [%s].",
389 : result, expected_ci);
390 : }
391 1 : END_TEST
392 :
393 1 : START_TEST(test_uid)
394 : {
395 1 : do_test(BASE"_%U", CCACHE_DIR, BASE"_"UID);
396 1 : do_test("%d/"FILENAME, BASE"_%U", BASE"_"UID"/"FILENAME);
397 : }
398 1 : END_TEST
399 :
400 1 : START_TEST(test_upn)
401 : {
402 1 : do_test(BASE"_%p", CCACHE_DIR, BASE"_"PRINCIPAL_NAME);
403 1 : do_test("%d/"FILENAME, BASE"_%p", BASE"_"PRINCIPAL_NAME"/"FILENAME);
404 : }
405 1 : END_TEST
406 :
407 1 : START_TEST(test_realm)
408 : {
409 1 : do_test(BASE"_%r", CCACHE_DIR, BASE"_"REALM);
410 1 : do_test("%d/"FILENAME, BASE"_%r", BASE"_"REALM"/"FILENAME);
411 : }
412 1 : END_TEST
413 :
414 1 : START_TEST(test_home)
415 : {
416 1 : do_test(BASE"_%h", CCACHE_DIR, BASE"_"HOME_DIRECTORY);
417 1 : do_test("%d/"FILENAME, BASE"_%h", BASE"_"HOME_DIRECTORY"/"FILENAME);
418 : }
419 1 : END_TEST
420 :
421 1 : START_TEST(test_ccache_dir)
422 : {
423 : char *result;
424 : int ret;
425 :
426 1 : do_test(BASE"_%d", CCACHE_DIR, BASE"_"CCACHE_DIR);
427 :
428 1 : ret = dp_opt_set_string(kr->krb5_ctx->opts, KRB5_CCACHEDIR, BASE"_%d");
429 1 : fail_unless(ret == EOK, "Failed to set Ccache dir");
430 :
431 1 : result = expand_ccname_template(tmp_ctx, kr, "%d/"FILENAME, NULL, true, true);
432 :
433 1 : fail_unless(result == NULL, "Using %%d in ccache dir should fail.");
434 : }
435 1 : END_TEST
436 :
437 1 : START_TEST(test_pid)
438 : {
439 : char *result;
440 : int ret;
441 :
442 1 : do_test(BASE"_%P", CCACHE_DIR, BASE"_"PID);
443 :
444 1 : ret = dp_opt_set_string(kr->krb5_ctx->opts, KRB5_CCACHEDIR, BASE"_%P");
445 1 : fail_unless(ret == EOK, "Failed to set Ccache dir");
446 :
447 1 : result = expand_ccname_template(tmp_ctx, kr, "%d/"FILENAME, NULL, true, true);
448 :
449 1 : fail_unless(result == NULL, "Using %%P in ccache dir should fail.");
450 : }
451 1 : END_TEST
452 :
453 1 : START_TEST(test_percent)
454 : {
455 1 : do_test(BASE"_%%", CCACHE_DIR, BASE"_%");
456 1 : do_test("%d/"FILENAME, BASE"_%%", BASE"_%/"FILENAME);
457 : }
458 1 : END_TEST
459 :
460 1 : START_TEST(test_unknown_template)
461 : {
462 1 : const char *test_template = BASE"_%X";
463 : char *result;
464 : int ret;
465 :
466 1 : result = expand_ccname_template(tmp_ctx, kr, test_template, NULL, true, true);
467 :
468 1 : fail_unless(result == NULL, "Unknown template [%s] should fail.",
469 : test_template);
470 :
471 1 : ret = dp_opt_set_string(kr->krb5_ctx->opts, KRB5_CCACHEDIR, BASE"_%X");
472 1 : fail_unless(ret == EOK, "Failed to set Ccache dir");
473 1 : test_template = "%d/"FILENAME;
474 1 : result = expand_ccname_template(tmp_ctx, kr, test_template, NULL, true, true);
475 :
476 1 : fail_unless(result == NULL, "Unknown template [%s] should fail.",
477 : test_template);
478 : }
479 1 : END_TEST
480 :
481 1 : START_TEST(test_NULL)
482 : {
483 1 : char *test_template = NULL;
484 : char *result;
485 :
486 1 : result = expand_ccname_template(tmp_ctx, kr, test_template, NULL, true, true);
487 :
488 1 : fail_unless(result == NULL, "Expected NULL as a result for an empty input.",
489 : test_template);
490 : }
491 1 : END_TEST
492 :
493 1 : START_TEST(test_no_substitution)
494 : {
495 1 : const char *test_template = BASE;
496 : char *result;
497 :
498 1 : result = expand_ccname_template(tmp_ctx, kr, test_template, NULL, true, true);
499 :
500 1 : fail_unless(result != NULL, "Cannot expand template [%s].", test_template);
501 1 : fail_unless(strcmp(result, test_template) == 0,
502 : "Expansion failed, result [%s], expected [%s].",
503 : result, test_template);
504 : }
505 1 : END_TEST
506 :
507 1 : START_TEST(test_krb5_style_expansion)
508 : {
509 : char *result;
510 : const char *file_template;
511 : const char *expected;
512 :
513 1 : file_template = BASE"/%{uid}/%{USERID}/%{euid}/%{username}";
514 1 : expected = BASE"/"UID"/"UID"/"UID"/"USERNAME;
515 1 : result = expand_ccname_template(tmp_ctx, kr, file_template, NULL, true, true);
516 :
517 1 : fail_unless(result != NULL, "Cannot expand template [%s].", file_template);
518 1 : fail_unless(strcmp(result, expected) == 0,
519 : "Expansion failed, result [%s], expected [%s].",
520 : result, expected);
521 :
522 1 : file_template = BASE"/%{unknown}";
523 1 : expected = BASE"/%{unknown}";
524 1 : result = expand_ccname_template(tmp_ctx, kr, file_template, NULL, true, true);
525 :
526 1 : fail_unless(result != NULL, "Cannot expand template [%s].", file_template);
527 1 : fail_unless(strcmp(result, expected) == 0,
528 : "Expansion failed, result [%s], expected [%s].",
529 : result, expected);
530 : }
531 1 : END_TEST
532 :
533 1 : START_TEST(test_compare_principal_realm)
534 : {
535 : int ret;
536 : bool different_realm;
537 :
538 1 : ret = compare_principal_realm(NULL, "a", &different_realm);
539 1 : fail_unless(ret == EINVAL, "NULL upn does not cause EINVAL.");
540 :
541 1 : ret = compare_principal_realm("a", NULL, &different_realm);
542 1 : fail_unless(ret == EINVAL, "NULL realm does not cause EINVAL.");
543 :
544 1 : ret = compare_principal_realm("a", "b", NULL);
545 1 : fail_unless(ret == EINVAL, "NULL different_realmbool " \
546 : "does not cause EINVAL.");
547 :
548 1 : ret = compare_principal_realm("", "a", &different_realm);
549 1 : fail_unless(ret == EINVAL, "Empty upn does not cause EINVAL.");
550 :
551 1 : ret = compare_principal_realm("a", "", &different_realm);
552 1 : fail_unless(ret == EINVAL, "Empty realm does not cause EINVAL.");
553 :
554 1 : ret = compare_principal_realm("ABC", "ABC", &different_realm);
555 1 : fail_unless(ret == EINVAL, "Short UPN does not cause EINVAL.");
556 :
557 1 : ret = compare_principal_realm("userABC", "ABC", &different_realm);
558 1 : fail_unless(ret == EINVAL, "Missing '@' does not cause EINVAL.");
559 :
560 1 : ret = compare_principal_realm("user@ABC", "ABC", &different_realm);
561 1 : fail_unless(ret == EOK, "Failure with same realm");
562 1 : fail_unless(different_realm == false, "Same realm but " \
563 : "different_realm is not false.");
564 :
565 1 : ret = compare_principal_realm("user@ABC", "DEF", &different_realm);
566 1 : fail_unless(ret == EOK, "Failure with different realm");
567 1 : fail_unless(different_realm == true, "Different realm but " \
568 : "different_realm is not true.");
569 :
570 1 : ret = compare_principal_realm("user@ABC", "REALMNAMELONGERTHANUPN",
571 : &different_realm);
572 1 : fail_unless(ret == EOK, "Failure with long realm name.");
573 1 : fail_unless(different_realm == true, "Realm name longer than UPN but "
574 : "different_realm is not true.");
575 : }
576 1 : END_TEST
577 :
578 : static void
579 2 : compare_map_id_name_to_krb_primary(struct map_id_name_to_krb_primary *a,
580 : const char **str,
581 : size_t len)
582 : {
583 2 : int i = 0;
584 : errno_t ret;
585 :
586 10 : while (a[i].id_name != NULL && a[i].krb_primary != NULL) {
587 6 : fail_unless(i < len);
588 6 : ret = sss_utf8_case_eq((const uint8_t*)a[i].id_name,
589 6 : (const uint8_t*)str[i*2]);
590 6 : fail_unless(ret == EOK,
591 : "%s does not match %s", a[i].id_name, str[i*2]);
592 :
593 6 : ret = sss_utf8_case_eq((const uint8_t*)a[i].krb_primary,
594 6 : (const uint8_t*)str[i*2+1]);
595 6 : fail_unless(ret == EOK, "%s does not match %s",
596 : a[i].krb_primary, str[i*2+1]);
597 6 : i++;
598 : }
599 2 : fail_unless(len == i, "%u != %u", len, i);
600 2 : }
601 :
602 1 : START_TEST(test_parse_krb5_map_user)
603 : {
604 : errno_t ret;
605 : TALLOC_CTX *mem_ctx;
606 : struct map_id_name_to_krb_primary *name_to_primary;
607 :
608 1 : mem_ctx = talloc_new(NULL);
609 :
610 : /* empty input */
611 : {
612 1 : check_leaks_push(mem_ctx);
613 1 : ret = parse_krb5_map_user(mem_ctx, NULL, &name_to_primary);
614 1 : fail_unless(ret == EOK);
615 1 : fail_unless(name_to_primary[0].id_name == NULL &&
616 : name_to_primary[0].krb_primary == NULL);
617 1 : talloc_free(name_to_primary);
618 :
619 1 : ret = parse_krb5_map_user(mem_ctx, "", &name_to_primary);
620 2 : fail_unless(ret == EOK);
621 1 : fail_unless(name_to_primary[0].id_name == NULL &&
622 : name_to_primary[0].krb_primary == NULL);
623 1 : talloc_free(name_to_primary);
624 :
625 1 : ret = parse_krb5_map_user(mem_ctx, ",", &name_to_primary);
626 2 : fail_unless(ret == EOK);
627 1 : fail_unless(name_to_primary[0].id_name == NULL &&
628 : name_to_primary[0].krb_primary == NULL);
629 1 : talloc_free(name_to_primary);
630 :
631 1 : ret = parse_krb5_map_user(mem_ctx, ",,", &name_to_primary);
632 2 : fail_unless(ret == EOK);
633 1 : fail_unless(name_to_primary[0].id_name == NULL &&
634 : name_to_primary[0].krb_primary == NULL);
635 1 : talloc_free(name_to_primary);
636 :
637 1 : check_leaks_pop(mem_ctx);
638 : }
639 : /* valid input */
640 : {
641 1 : check_leaks_push(mem_ctx);
642 1 : const char *p = "pája:preichl,joe:juser,jdoe:ßlack";
643 1 : const char *p2 = " pája : preichl , joe:\njuser,jdoe\t: ßlack ";
644 1 : const char *expected[] = {"pája", "preichl", "joe", "juser", "jdoe", "ßlack"};
645 1 : ret = parse_krb5_map_user(mem_ctx, p, &name_to_primary);
646 2 : fail_unless(ret == EOK);
647 1 : compare_map_id_name_to_krb_primary(name_to_primary, expected,
648 : sizeof(expected)/sizeof(const char*)/2);
649 1 : talloc_free(name_to_primary);
650 :
651 1 : ret = parse_krb5_map_user(mem_ctx, p2, &name_to_primary);
652 1 : fail_unless(ret == EOK);
653 1 : compare_map_id_name_to_krb_primary(name_to_primary, expected,
654 : sizeof(expected)/sizeof(const char*)/2);
655 1 : talloc_free(name_to_primary);
656 1 : check_leaks_pop(mem_ctx);
657 : }
658 : /* invalid input */
659 : {
660 1 : check_leaks_push(mem_ctx);
661 :
662 1 : ret = parse_krb5_map_user(mem_ctx, ":", &name_to_primary);
663 1 : fail_unless(ret == EINVAL);
664 :
665 1 : ret = parse_krb5_map_user(mem_ctx, "joe:", &name_to_primary);
666 1 : fail_unless(ret == EINVAL);
667 :
668 1 : ret = parse_krb5_map_user(mem_ctx, ":joe", &name_to_primary);
669 1 : fail_unless(ret == EINVAL);
670 :
671 1 : ret = parse_krb5_map_user(mem_ctx, "joe:,", &name_to_primary);
672 1 : fail_unless(ret == EINVAL);
673 :
674 1 : ret = parse_krb5_map_user(mem_ctx, ",joe", &name_to_primary);
675 1 : fail_unless(ret == EINVAL);
676 :
677 1 : ret = parse_krb5_map_user(mem_ctx, "joe:j:user", &name_to_primary);
678 1 : fail_unless(ret == EINVAL);
679 :
680 1 : check_leaks_pop(mem_ctx);
681 : }
682 :
683 1 : talloc_free(mem_ctx);
684 : }
685 1 : END_TEST
686 :
687 1 : START_TEST(test_sss_krb5_realm_has_proxy)
688 : {
689 1 : fail_unless(sss_krb5_realm_has_proxy(NULL) == false);
690 :
691 1 : setenv("KRB5_CONFIG", "/dev/null", 1);
692 1 : fail_unless(sss_krb5_realm_has_proxy("REALM") == false);
693 :
694 1 : setenv("KRB5_CONFIG", ABS_SRC_DIR"/src/tests/krb5_proxy_check_test_data.conf", 1);
695 1 : fail_unless(sss_krb5_realm_has_proxy("REALM") == false);
696 1 : fail_unless(sss_krb5_realm_has_proxy("REALM_PROXY") == true);
697 : }
698 1 : END_TEST
699 :
700 1 : Suite *krb5_utils_suite (void)
701 : {
702 1 : Suite *s = suite_create ("krb5_utils");
703 :
704 1 : TCase *tc_ccname_template = tcase_create ("ccname_template");
705 1 : tcase_add_checked_fixture (tc_ccname_template, setup_talloc_context,
706 : free_talloc_context);
707 1 : tcase_add_test (tc_ccname_template, test_no_substitution);
708 1 : tcase_add_test (tc_ccname_template, test_NULL);
709 1 : tcase_add_test (tc_ccname_template, test_unknown_template);
710 1 : tcase_add_test (tc_ccname_template, test_username);
711 1 : tcase_add_test (tc_ccname_template, test_case_sensitive);
712 1 : tcase_add_test (tc_ccname_template, test_uid);
713 1 : tcase_add_test (tc_ccname_template, test_upn);
714 1 : tcase_add_test (tc_ccname_template, test_realm);
715 1 : tcase_add_test (tc_ccname_template, test_home);
716 1 : tcase_add_test (tc_ccname_template, test_ccache_dir);
717 1 : tcase_add_test (tc_ccname_template, test_pid);
718 1 : tcase_add_test (tc_ccname_template, test_percent);
719 1 : tcase_add_test (tc_ccname_template, test_multiple_substitutions);
720 1 : tcase_add_test (tc_ccname_template, test_krb5_style_expansion);
721 1 : suite_add_tcase (s, tc_ccname_template);
722 :
723 1 : TCase *tc_create_dir = tcase_create("create_dir");
724 1 : tcase_add_checked_fixture (tc_create_dir, setup_create_dir,
725 : teardown_create_dir);
726 1 : tcase_add_test (tc_create_dir, test_illegal_patterns);
727 1 : tcase_add_test (tc_create_dir, test_cc_dir_create);
728 1 : if (getuid() == 0) {
729 0 : tcase_add_test (tc_create_dir, test_private_ccache_dir_in_user_dir);
730 0 : tcase_add_test (tc_create_dir, test_private_ccache_dir_in_wrong_user_dir);
731 : } else {
732 1 : printf("Run as root to enable more tests.\n");
733 : }
734 1 : suite_add_tcase (s, tc_create_dir);
735 :
736 1 : TCase *tc_krb5_helpers = tcase_create("Helper functions");
737 1 : tcase_add_test(tc_krb5_helpers, test_compare_principal_realm);
738 1 : tcase_add_test(tc_krb5_helpers, test_parse_krb5_map_user);
739 1 : tcase_add_test(tc_krb5_helpers, test_sss_krb5_realm_has_proxy);
740 1 : suite_add_tcase(s, tc_krb5_helpers);
741 :
742 1 : return s;
743 : }
744 :
745 1 : int main(int argc, const char *argv[])
746 : {
747 : int ret;
748 : int opt;
749 : poptContext pc;
750 : int number_failed;
751 :
752 1 : tests_set_cwd();
753 :
754 6 : struct poptOption long_options[] = {
755 : POPT_AUTOHELP
756 5 : SSSD_MAIN_OPTS
757 : POPT_TABLEEND
758 : };
759 :
760 : /* Set debug level to invalid value so we can deside if -d 0 was used. */
761 1 : debug_level = SSSDBG_INVALID;
762 :
763 1 : pc = poptGetContext(argv[0], argc, argv, long_options, 0);
764 1 : while((opt = poptGetNextOpt(pc)) != -1) {
765 : switch(opt) {
766 : default:
767 0 : fprintf(stderr, "\nInvalid option %s: %s\n\n",
768 : poptBadOption(pc, 0), poptStrerror(opt));
769 0 : poptPrintUsage(pc, stderr, 0);
770 0 : return 1;
771 : }
772 : }
773 1 : poptFreeContext(pc);
774 :
775 1 : DEBUG_CLI_INIT(debug_level);
776 :
777 1 : ret = mkdir(TESTS_PATH, 0775);
778 1 : if (ret != EOK) {
779 0 : fprintf(stderr, "Could not create empty directory [%s]. ", TESTS_PATH);
780 0 : if (errno == EEXIST) {
781 0 : fprintf(stderr, "Please remove [%s].\n", TESTS_PATH);
782 : } else {
783 0 : fprintf(stderr, "[%d][%s].\n", errno, strerror(errno));
784 : }
785 :
786 0 : return 1;
787 : }
788 :
789 1 : Suite *s = krb5_utils_suite ();
790 1 : SRunner *sr = srunner_create (s);
791 : /* If CK_VERBOSITY is set, use that, otherwise it defaults to CK_NORMAL */
792 1 : srunner_run_all(sr, CK_ENV);
793 1 : number_failed = srunner_ntests_failed (sr);
794 1 : srunner_free (sr);
795 1 : if (number_failed == 0) {
796 1 : ret = rmdir(TESTS_PATH);
797 1 : if (ret != EOK) {
798 0 : fprintf(stderr, "Cannot remove [%s]: [%d][%s].\n", TESTS_PATH,
799 0 : errno, strerror(errno));
800 0 : return EXIT_FAILURE;
801 : }
802 :
803 1 : return EXIT_SUCCESS;
804 : }
805 :
806 0 : return EXIT_FAILURE;
807 : }
808 :
|