1 /*
2 * Copyright (c) 2014 Yubico AB
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials provided
15 * with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #include <stdio.h>
31 #include <assert.h>
32 #include <string.h>
33 #include <stdlib.h>
34
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <fcntl.h>
38 #include <unistd.h>
39
40 #include <pwd.h>
41
42 #include "util.h"
43
test_get_user_cfgfile_path(void)44 static void test_get_user_cfgfile_path(void) {
45 char *file;
46 struct passwd user;
47 int ret;
48 user.pw_name = "root";
49 user.pw_dir = "/root";
50 ret = get_user_cfgfile_path("/foo/bar", "test", &user, &file);
51 assert(ret == 1);
52 assert(strcmp(file, "/foo/bar/test") == 0);
53 free(file);
54 ret = get_user_cfgfile_path(NULL, "test", &user, &file);
55 assert(ret == 1);
56 assert(strcmp(file, "/root/.yubico/test") == 0);
57 free(file);
58 }
59
test_check_user_token(void)60 static void test_check_user_token(void) {
61 char file[] = "/tmp/pamtest.XXXXXX";
62 int fd = mkstemp(file);
63 FILE *handle;
64 int ret;
65
66 assert(fd != -1);
67 handle = fdopen(fd, "w");
68 fprintf(handle, "# This is a comment containing foobar:foobar\n");
69 fprintf(handle, "foobar:hhhvhvhdhbid:hnhbhnhbhnhb:\n");
70 fprintf(handle, "# This is a comment in the middle\n");
71 fprintf(handle, "kaka:hdhrhbhjhvhu:hihbhdhrhbhj\n");
72 fprintf(handle, "# foo2 is a user showing up twice in the file\n");
73 fprintf(handle, "foo2:vvvvvvvvvvvv\n");
74 fprintf(handle, "bar:hnhbhnhbhnhb\n");
75 fprintf(handle, "foo2:cccccccccccc\n");
76 fclose(handle);
77
78 ret = check_user_token(file, "foobar", "hhhvhvhdhbid", 1, stdout);
79 assert(ret == AUTH_FOUND);
80 ret = check_user_token(file, "foobar", "hnhbhnhbhnhb", 1, stdout);
81 assert(ret == AUTH_FOUND);
82 ret = check_user_token(file, "foobar", "hnhbhnhbhnhc", 1, stdout);
83 assert(ret == AUTH_NOT_FOUND);
84 ret = check_user_token(file, "kaka", "hihbhdhrhbhj", 1, stdout);
85 assert(ret == AUTH_FOUND);
86 ret = check_user_token(file, "bar", "hnhbhnhbhnhb", 1, stdout);
87 assert(ret == AUTH_FOUND);
88 ret = check_user_token(file, "foo", "hdhrhbhjhvhu", 1, stdout);
89 assert(ret == AUTH_NO_TOKENS);
90 ret = check_user_token(file, "foo2", "cccccccccccc", 1, stdout);
91 assert(ret == AUTH_FOUND);
92 ret = check_user_token(file, "foo2", "vvvvvvvvvvvv", 1, stdout);
93 assert(ret == AUTH_FOUND);
94 ret = check_user_token(file, "foo2", "vvvvvvvvvvcc", 1, stdout);
95 assert(ret == AUTH_NOT_FOUND);
96 ret = check_user_token(file, "foo2", "", 1, stdout);
97 assert(ret == AUTH_NOT_FOUND);
98 ret = check_user_token(file, "foo", "", 1, stdout);
99 assert(ret == AUTH_NO_TOKENS);
100 remove(file);
101 }
102
103 #if HAVE_CR
104
105 #define CHALLENGE1 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
106 #define RESPONSE1 "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
107 #define SALT1 "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
108 #define CHALLENGE2 "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
109 #define RESPONSE2 "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
110
test_load_chalresp_state(void)111 static void test_load_chalresp_state(void) {
112 int ret;
113 FILE *file = tmpfile();
114 CR_STATE state;
115
116 memset(&state, 0, sizeof(state));
117 fprintf(file, "v2:%s:%s:%s:%d:%d\n", CHALLENGE1, RESPONSE1, SALT1, 1000, 2);
118 rewind(file);
119 ret = load_chalresp_state(file, &state, true, stdout);
120 assert(ret == 1);
121 assert(state.iterations == 1000);
122 assert(state.slot == 2);
123 assert(state.challenge_len == CR_CHALLENGE_SIZE);
124 assert(state.response_len == CR_RESPONSE_SIZE);
125 assert(state.salt_len == CR_SALT_SIZE);
126 rewind(file);
127
128 memset(&state, 0, sizeof(state));
129 fprintf(file, "v1:%s:%s:%d\n", CHALLENGE2, RESPONSE2, 1);
130 rewind(file);
131 ret = load_chalresp_state(file, &state, true, stdout);
132 assert(ret == 1);
133 assert(state.iterations == CR_DEFAULT_ITERATIONS);
134 assert(state.slot == 1);
135 assert(state.challenge_len == CR_CHALLENGE_SIZE);
136 assert(state.response_len == CR_RESPONSE_SIZE);
137 assert(state.salt_len == 0);
138 rewind(file);
139
140 /* slot 3 should fail.. */
141 fprintf(file, "v2:%s:%s:%s:%d:%d\n", CHALLENGE1, RESPONSE1, SALT1, 1000, 3);
142 rewind(file);
143 ret = load_chalresp_state(file, &state, true, stdout);
144 assert(ret == 0);
145 fclose(file);
146 }
147
test_check_user_challenge_file(void)148 static void test_check_user_challenge_file(void) {
149 int ret;
150 char * tmpdir_path;
151 char * buf;
152 FILE * file;
153 struct passwd user;
154
155 buf = malloc(256);
156
157 #define create_tmpdir_dir(path) \
158 strcpy(buf, tmpdir_path); \
159 strcat(buf, "/"); \
160 strcat(buf, path); \
161 mkdir(buf, 0755);
162
163 #define remove_tmpdir_dir(path) \
164 strcpy(buf, tmpdir_path); \
165 strcat(buf, "/"); \
166 strcat(buf, path); \
167 rmdir(buf);
168
169 #define create_tmpdir_file(path) \
170 strcpy(buf, tmpdir_path); \
171 strcat(buf, "/"); \
172 strcat(buf, path); \
173 file = fopen(buf, "w"); \
174 fclose(file);
175
176 #define remove_tmpdir_file(path) \
177 strcpy(buf, tmpdir_path); \
178 strcat(buf, "/"); \
179 strcat(buf, path); \
180 unlink(buf);
181
182 /* create temporary directory */
183 char template[] = "/tmp/pamtest.XXXXXX";
184 tmpdir_path = mkdtemp(template);
185 assert(tmpdir_path != NULL);
186
187 /* set user data */
188 user.pw_name = "tester";
189 user.pw_dir = tmpdir_path;
190
191 /* execute tests */
192 /* no asserts here as we have directory to remove */
193
194 int case_001_empty_chalresp_dir;
195 case_001_empty_chalresp_dir = check_user_challenge_file(tmpdir_path, &user, stdout);
196
197 int case_002_one_challenge_file;
198 create_tmpdir_file("tester");
199 case_002_one_challenge_file = check_user_challenge_file(tmpdir_path, &user, stdout);
200 remove_tmpdir_file("tester");
201
202 int case_003_multiple_challenge_files;
203 create_tmpdir_file("tester-001");
204 create_tmpdir_file("tester-002");
205 case_003_multiple_challenge_files = check_user_challenge_file(tmpdir_path, &user, stdout);
206 remove_tmpdir_file("tester-002");
207 remove_tmpdir_file("tester-001");
208
209 int case_004_other_users_files;
210 create_tmpdir_file("tester1");
211 create_tmpdir_file("tester1-001");
212 case_004_other_users_files = check_user_challenge_file(tmpdir_path, &user, stdout);
213 remove_tmpdir_file("tester1-001");
214 remove_tmpdir_file("tester1");
215
216 int case_005_no_chalresp_no_yubico;
217 case_005_no_chalresp_no_yubico = check_user_challenge_file(NULL, &user, stdout);
218
219 int case_006_no_chalresp_empty_yubico;
220 create_tmpdir_dir(".yubico");
221 case_006_no_chalresp_empty_yubico = check_user_challenge_file(NULL, &user, stdout);
222 remove_tmpdir_dir(".yubico");
223
224 int case_007_no_chalresp_one_challenge_file;
225 create_tmpdir_dir(".yubico");
226 create_tmpdir_file(".yubico/challenge");
227 case_007_no_chalresp_one_challenge_file = check_user_challenge_file(NULL, &user, stdout);
228 remove_tmpdir_file(".yubico/challenge");
229 remove_tmpdir_dir(".yubico");
230
231 int case_008_no_chalresp_multiple_challenge_files;
232 create_tmpdir_dir(".yubico");
233 create_tmpdir_file(".yubico/challenge-001");
234 create_tmpdir_file(".yubico/challenge-002");
235 case_008_no_chalresp_multiple_challenge_files = check_user_challenge_file(NULL, &user, stdout);
236 remove_tmpdir_file(".yubico/challenge-002");
237 remove_tmpdir_file(".yubico/challenge-001");
238 remove_tmpdir_dir(".yubico");
239
240 /* remove temporary directory */
241 ret = rmdir(tmpdir_path);
242 assert(ret == 0);
243 free(buf);
244
245 /* check test results */
246 assert(case_001_empty_chalresp_dir == AUTH_NOT_FOUND);
247 assert(case_002_one_challenge_file == AUTH_FOUND);
248 assert(case_003_multiple_challenge_files == AUTH_FOUND);
249 assert(case_004_other_users_files == AUTH_NOT_FOUND);
250 assert(case_005_no_chalresp_no_yubico == AUTH_NOT_FOUND);
251 assert(case_006_no_chalresp_empty_yubico == AUTH_NOT_FOUND);
252 assert(case_007_no_chalresp_one_challenge_file == AUTH_FOUND);
253 assert(case_008_no_chalresp_multiple_challenge_files == AUTH_FOUND);
254
255 #undef create_tmpdir_dir
256 #undef remove_tmpdir_dir
257 #undef create_tmpdir_file
258 #undef remove_tmpdir_file
259 }
260
261 #endif /* HAVE_CR */
262
test_filter_printf(void)263 static void test_filter_printf(void) {
264 assert(filter_result_len("meno %u", "doof", NULL) == 10);
265 assert(filter_result_len("meno %u %u", "doof", NULL) == 15);
266 assert(filter_result_len("%u meno %u", "doof", NULL) == 15);
267 assert(filter_result_len("%u me %u no %u", "doof", NULL) == 21);
268 assert(filter_result_len("meno %w %%u", "doof", NULL) == 14);
269 assert(filter_result_len("meno %w %%u meno", "doof", NULL) == 19);
270 assert(filter_result_len("meno ", "doof", NULL) == 6);
271
272 assert(!strcmp(filter_printf("meno %u", "doof"), "meno doof"));
273 assert(!strcmp(filter_printf("meno %u %u", "doof"), "meno doof doof"));
274 assert(!strcmp(filter_printf("%u meno %u", "doof"), "doof meno doof"));
275 assert(!strcmp(filter_printf("%u me %u no %u", "doof"), "doof me doof no doof"));
276 assert(!strcmp(filter_printf("meno %w %%u", "doof"), "meno %w %doof"));
277 assert(!strcmp(filter_printf("meno %w %%u meno", "doof"), "meno %w %doof meno"));
278 assert(!strcmp(filter_printf("meno ", "doof"), "meno "));
279 printf("test_filter_printf OK\n");
280 }
281
main(void)282 int main (void) {
283 test_filter_printf();
284 test_get_user_cfgfile_path();
285 test_check_user_token();
286 #if HAVE_CR
287 test_load_chalresp_state();
288 test_check_user_challenge_file();
289 #endif /* HAVE_CR */
290 return 0;
291 }
292