1 | /* |
---|
2 | * Utility functions for tests that use Kerberos. |
---|
3 | * |
---|
4 | * Currently only provides kerberos_setup(), which assumes a particular set of |
---|
5 | * data files in either the SOURCE or BUILD directories and, using those, |
---|
6 | * obtains Kerberos credentials, sets up a ticket cache, and sets the |
---|
7 | * environment variable pointing to the Kerberos keytab to use for testing. |
---|
8 | * |
---|
9 | * Copyright 2006, 2007, 2009 |
---|
10 | * Board of Trustees, Leland Stanford Jr. University |
---|
11 | * |
---|
12 | * See LICENSE for licensing terms. |
---|
13 | */ |
---|
14 | |
---|
15 | #include <config.h> |
---|
16 | #include <portable/system.h> |
---|
17 | |
---|
18 | #include <krb5.h> |
---|
19 | |
---|
20 | #include <tests/tap/basic.h> |
---|
21 | #include <tests/tap/kerberos.h> |
---|
22 | #include <util/util.h> |
---|
23 | |
---|
24 | |
---|
25 | /* |
---|
26 | * Given the partial path to a file, look under BUILD and then SOURCE for the |
---|
27 | * file and return the full path to the file in newly-allocated memory. |
---|
28 | * Returns NULL if the file doesn't exist. |
---|
29 | */ |
---|
30 | static char * |
---|
31 | find_file(const char *file) |
---|
32 | { |
---|
33 | char *base; |
---|
34 | char *path = NULL; |
---|
35 | const char *envs[] = { "BUILD", "SOURCE", NULL }; |
---|
36 | int i; |
---|
37 | |
---|
38 | for (i = 0; envs[i] != NULL; i++) { |
---|
39 | base = getenv(envs[i]); |
---|
40 | if (base == NULL) |
---|
41 | continue; |
---|
42 | path = concatpath(base, file); |
---|
43 | if (access(path, R_OK) == 0) |
---|
44 | break; |
---|
45 | free(path); |
---|
46 | path = NULL; |
---|
47 | } |
---|
48 | return path; |
---|
49 | } |
---|
50 | |
---|
51 | |
---|
52 | /* |
---|
53 | * Obtain Kerberos tickets for the principal specified in test.principal using |
---|
54 | * the keytab specified in test.keytab, both of which are presumed to be in |
---|
55 | * tests/data in either the build or the source tree. |
---|
56 | * |
---|
57 | * Returns the contents of test.principal in newly allocated memory or NULL if |
---|
58 | * Kerberos tests are apparently not configured. If Kerberos tests are |
---|
59 | * configured but something else fails, calls bail(). |
---|
60 | */ |
---|
61 | char * |
---|
62 | kerberos_setup(void) |
---|
63 | { |
---|
64 | static const char format1[] |
---|
65 | = "kinit -k -t %s %s >/dev/null 2>&1 </dev/null"; |
---|
66 | static const char format2[] |
---|
67 | = "kinit -t %s %s >/dev/null 2>&1 </dev/null"; |
---|
68 | static const char format3[] |
---|
69 | = "kinit -k -K %s %s >/dev/null 2>&1 </dev/null"; |
---|
70 | FILE *file; |
---|
71 | char *path; |
---|
72 | const char *build; |
---|
73 | char principal[BUFSIZ], *command; |
---|
74 | size_t length; |
---|
75 | int status; |
---|
76 | |
---|
77 | /* Read the principal name and find the keytab file. */ |
---|
78 | path = find_file("data/test.principal"); |
---|
79 | if (path == NULL) |
---|
80 | return NULL; |
---|
81 | file = fopen(path, "r"); |
---|
82 | if (file == NULL) { |
---|
83 | free(path); |
---|
84 | return NULL; |
---|
85 | } |
---|
86 | if (fgets(principal, sizeof(principal), file) == NULL) { |
---|
87 | fclose(file); |
---|
88 | bail("cannot read %s", path); |
---|
89 | } |
---|
90 | fclose(file); |
---|
91 | if (principal[strlen(principal) - 1] != '\n') |
---|
92 | bail("no newline in %s", path); |
---|
93 | free(path); |
---|
94 | principal[strlen(principal) - 1] = '\0'; |
---|
95 | path = find_file("data/test.keytab"); |
---|
96 | if (path == NULL) |
---|
97 | return NULL; |
---|
98 | |
---|
99 | /* Set the KRB5CCNAME and KRB5_KTNAME environment variables. */ |
---|
100 | build = getenv("BUILD"); |
---|
101 | if (build == NULL) |
---|
102 | build = "."; |
---|
103 | putenv(concat("KRB5CCNAME=", build, "/data/test.cache", (char *) 0)); |
---|
104 | putenv(concat("KRB5_KTNAME=", path, (char *) 0)); |
---|
105 | |
---|
106 | /* Now do the Kerberos initialization. */ |
---|
107 | length = strlen(format1) + strlen(path) + strlen(principal); |
---|
108 | command = xmalloc(length); |
---|
109 | snprintf(command, length, format1, path, principal); |
---|
110 | status = system(command); |
---|
111 | free(command); |
---|
112 | if (status == -1 || WEXITSTATUS(status) != 0) { |
---|
113 | length = strlen(format2) + strlen(path) + strlen(principal); |
---|
114 | command = xmalloc(length); |
---|
115 | snprintf(command, length, format2, path, principal); |
---|
116 | status = system(command); |
---|
117 | free(command); |
---|
118 | } |
---|
119 | if (status == -1 || WEXITSTATUS(status) != 0) { |
---|
120 | length = strlen(format3) + strlen(path) + strlen(principal); |
---|
121 | command = xmalloc(length); |
---|
122 | snprintf(command, length, format3, path, principal); |
---|
123 | status = system(command); |
---|
124 | free(command); |
---|
125 | } |
---|
126 | if (status == -1 || WEXITSTATUS(status) != 0) |
---|
127 | return NULL; |
---|
128 | free(path); |
---|
129 | return xstrdup(principal); |
---|
130 | } |
---|
131 | |
---|
132 | |
---|
133 | /* |
---|
134 | * Clean up at the end of a test. Currently, all this does is remove the |
---|
135 | * ticket cache. |
---|
136 | */ |
---|
137 | void |
---|
138 | kerberos_cleanup(void) |
---|
139 | { |
---|
140 | char *path; |
---|
141 | |
---|
142 | path = concatpath(getenv("BUILD"), "data/test.cache"); |
---|
143 | unlink(path); |
---|
144 | free(path); |
---|
145 | } |
---|