1 /*
2 * Copyright (c) 2012 Red Hat Inc.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * * Redistributions of source code must retain the above
9 * copyright notice, this list of conditions and the
10 * following disclaimer.
11 * * Redistributions in binary form must reproduce the
12 * above copyright notice, this list of conditions and
13 * the following disclaimer in the documentation and/or
14 * other materials provided with the distribution.
15 * * The names of contributors to this software may not be
16 * used to endorse or promote products derived from this
17 * software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
29 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
30 * DAMAGE.
31 *
32 * Author: Stef Walter <stefw@gnome.org>
33 */
34
35 #include "config.h"
36 #include "test.h"
37 #include "test-trust.h"
38
39 #include <stdlib.h>
40 #include <stdio.h>
41 #include <string.h>
42
43 #include <sys/stat.h>
44 #include <sys/types.h>
45 #include <fcntl.h>
46 #ifdef OS_UNIX
47 #include <unistd.h>
48 #endif
49
50 #include "attrs.h"
51 #include "debug.h"
52 #include "parser.h"
53 #include "path.h"
54 #include "pkcs11x.h"
55 #include "message.h"
56 #include "token.h"
57
58 static CK_OBJECT_CLASS certificate = CKO_CERTIFICATE;
59 static CK_OBJECT_CLASS data = CKO_DATA;
60 static CK_BBOOL falsev = CK_FALSE;
61 static CK_BBOOL truev = CK_TRUE;
62
63 struct {
64 p11_token *token;
65 p11_index *index;
66 p11_parser *parser;
67 char *directory;
68 char *unwritable;
69 } test;
70
71 static void
setup(void * path)72 setup (void *path)
73 {
74 test.token = p11_token_new (333, path, "Label", P11_TOKEN_FLAG_NONE);
75 assert_ptr_not_null (test.token);
76
77 test.index = p11_token_index (test.token);
78 assert_ptr_not_null (test.token);
79
80 test.parser = p11_token_parser (test.token);
81 assert_ptr_not_null (test.parser);
82 }
83
84 static void
setup_temp(void * unused)85 setup_temp (void *unused)
86 {
87 test.directory = p11_test_directory ("test-module");
88 setup (test.directory);
89 }
90
91 static void
setup_writable(void * unused)92 setup_writable (void *unused)
93 {
94 setup_temp (unused);
95
96 test.unwritable = p11_path_build (test.directory, "unwritable", NULL);
97 #ifdef OS_UNIX
98 if (mkdir (test.unwritable, S_IRWXU) < 0)
99 #else
100 if (mkdir (test.unwritable) < 0)
101 #endif
102 assert_fail ("mkdir() failed", test.unwritable);
103
104 chmod (test.unwritable, 0);
105 }
106
107 static void
teardown(void * path)108 teardown (void *path)
109 {
110 p11_token_free (test.token);
111 }
112
113 static void
teardown_temp(void * unused)114 teardown_temp (void *unused)
115 {
116 p11_test_directory_delete (test.directory);
117 teardown (test.directory);
118 free (test.directory);
119 memset (&test, 0, sizeof (test));
120 }
121
122 static void
teardown_writable(void * unused)123 teardown_writable (void *unused)
124 {
125 chmod (test.unwritable, 0644);
126 free (test.unwritable);
127
128 teardown_temp (unused);
129 }
130
131 static void
test_token_load(void * path)132 test_token_load (void *path)
133 {
134 p11_index *index;
135 int count;
136
137 count = p11_token_load (test.token);
138 assert_num_eq (8, count);
139
140 /* A certificate and trust object for each parsed object */
141 index = p11_token_index (test.token);
142 assert (((count - 1) * 2) + 1 <= p11_index_size (index));
143 }
144
145 static void
test_token_flags(void * path)146 test_token_flags (void *path)
147 {
148 /*
149 * blocklist comes from the input/distrust.pem file. It is not in the blocklist
150 * directory, but is an OpenSSL trusted certificate file, and is marked
151 * in the blocklist style for OpenSSL.
152 */
153
154 CK_ATTRIBUTE blocklist[] = {
155 { CKA_CLASS, &certificate, sizeof (certificate) },
156 { CKA_LABEL, "Red Hat Is the CA", 17 },
157 { CKA_SERIAL_NUMBER, "\x02\x01\x01", 3 },
158 { CKA_TRUSTED, &falsev, sizeof (falsev) },
159 { CKA_X_DISTRUSTED, &truev, sizeof (truev) },
160 { CKA_INVALID },
161 };
162
163 /*
164 * blocklist2 comes from the input/blocklist/self-server.der file. It is
165 * explicitly put on the blocklist, even though it contains no trust
166 * policy information.
167 */
168
169 const unsigned char self_server_subject[] = {
170 0x30, 0x4b, 0x31, 0x13, 0x30, 0x11, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64,
171 0x01, 0x19, 0x16, 0x03, 0x43, 0x4f, 0x4d, 0x31, 0x17, 0x30, 0x15, 0x06, 0x0a, 0x09, 0x92, 0x26,
172 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x07, 0x45, 0x58, 0x41, 0x4d, 0x50, 0x4c, 0x45,
173 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x12, 0x73, 0x65, 0x72, 0x76, 0x65,
174 0x72, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d,
175 };
176
177 CK_ATTRIBUTE blocklist2[] = {
178 { CKA_CLASS, &certificate, sizeof (certificate) },
179 { CKA_SUBJECT, (void *)self_server_subject, sizeof (self_server_subject) },
180 { CKA_TRUSTED, &falsev, sizeof (falsev) },
181 { CKA_X_DISTRUSTED, &truev, sizeof (truev) },
182 { CKA_INVALID },
183 };
184
185 /*
186 * anchor comes from the input/anchors/cacert3.der file. It is
187 * explicitly marked as an anchor, even though it contains no trust
188 * policy information.
189 */
190
191 CK_ATTRIBUTE anchor[] = {
192 { CKA_CLASS, &certificate, sizeof (certificate) },
193 { CKA_SUBJECT, (void *)test_cacert3_ca_subject, sizeof (test_cacert3_ca_subject) },
194 { CKA_TRUSTED, &truev, sizeof (truev) },
195 { CKA_X_DISTRUSTED, &falsev, sizeof (falsev) },
196 { CKA_INVALID },
197 };
198
199 const unsigned char cacert_root_subject[] = {
200 0x30, 0x79, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x07, 0x52, 0x6f, 0x6f,
201 0x74, 0x20, 0x43, 0x41, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x15, 0x68,
202 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x63, 0x61, 0x63, 0x65, 0x72, 0x74,
203 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x19, 0x43,
204 0x41, 0x20, 0x43, 0x65, 0x72, 0x74, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x41,
205 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86,
206 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74,
207 0x40, 0x63, 0x61, 0x63, 0x65, 0x72, 0x74, 0x2e, 0x6f, 0x72, 0x67,
208 };
209
210 /*
211 * notrust comes from the input/cacert-ca.der file. It contains no
212 * trust information, and is not explicitly marked as an anchor, so
213 * it's neither trusted or distrusted.
214 */
215
216 CK_ATTRIBUTE notrust[] = {
217 { CKA_CLASS, &certificate, sizeof (certificate) },
218 { CKA_SUBJECT, (void *)cacert_root_subject, sizeof (cacert_root_subject) },
219 { CKA_TRUSTED, &falsev, sizeof (falsev) },
220 { CKA_X_DISTRUSTED, &falsev, sizeof (falsev) },
221 { CKA_INVALID },
222 };
223
224 CK_ATTRIBUTE *expected[] = {
225 anchor,
226 blocklist,
227 blocklist2,
228 notrust,
229 NULL,
230 };
231
232 CK_OBJECT_HANDLE handle;
233 CK_ATTRIBUTE *object;
234 int i;
235
236 if (p11_token_load (test.token) < 0)
237 assert_not_reached ();
238
239 /* The other objects */
240 for (i = 0; expected[i]; i++) {
241 handle = p11_index_find (p11_token_index (test.token), expected[i], 2);
242 assert (handle != 0);
243
244 object = p11_index_lookup (p11_token_index (test.token), handle);
245 assert_ptr_not_null (object);
246
247 test_check_attrs (expected[i], object);
248 }
249 }
250
251 static void
test_token_path(void * path)252 test_token_path (void *path)
253 {
254 assert_str_eq (path, p11_token_get_path (test.token));
255 }
256
257 static void
test_token_label(void * path)258 test_token_label (void *path)
259 {
260 assert_str_eq ("Label", p11_token_get_label (test.token));
261 }
262
263 static void
test_token_slot(void * path)264 test_token_slot (void *path)
265 {
266 assert_num_eq (333, p11_token_get_slot (test.token));
267 }
268
269 static void
test_not_writable(void)270 test_not_writable (void)
271 {
272 p11_token *token;
273 char *path;
274 int fd;
275
276 path = p11_path_build (test.unwritable, "test", NULL);
277 fd = open (path, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
278 free (path);
279
280 if (fd >= 0) {
281 close (fd);
282 assert_skip ("cannot perform non-writable test", NULL);
283 }
284
285 token = p11_token_new (333, test.unwritable, "Label", P11_TOKEN_FLAG_NONE);
286 assert (!p11_token_is_writable (token));
287 p11_token_free (token);
288
289 token = p11_token_new (333, "", "Label", P11_TOKEN_FLAG_NONE);
290 assert (!p11_token_is_writable (token));
291 p11_token_free (token);
292
293 path = p11_path_build (test.unwritable, "non-existent", NULL);
294 token = p11_token_new (333, path, "Label", P11_TOKEN_FLAG_NONE);
295 free (path);
296 assert (!p11_token_is_writable (token));
297 p11_token_free (token);
298 }
299
300 static void
test_writable_exists(void)301 test_writable_exists (void)
302 {
303 /* A writable directory since we created it */
304 assert (p11_token_is_writable (test.token));
305 }
306
307 static void
test_writable_no_exist(void)308 test_writable_no_exist (void)
309 {
310 char *directory;
311 p11_token *token;
312 char *path;
313
314 directory = p11_test_directory ("test-module");
315
316 path = p11_path_build (directory, "subdir", NULL);
317 assert (path != NULL);
318
319 token = p11_token_new (333, path, "Label", P11_TOKEN_FLAG_NONE);
320 free (path);
321
322 /* A writable directory since parent is writable */
323 assert (p11_token_is_writable (token));
324
325 p11_token_free (token);
326
327 if (rmdir (directory) < 0)
328 assert_not_reached ();
329
330 free (directory);
331 }
332
333 static void
test_load_already(void)334 test_load_already (void)
335 {
336 CK_ATTRIBUTE cert[] = {
337 { CKA_CLASS, &certificate, sizeof (certificate) },
338 { CKA_SUBJECT, (void *)test_cacert3_ca_subject, sizeof (test_cacert3_ca_subject) },
339 { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) },
340 { CKA_INVALID },
341 };
342
343 CK_OBJECT_HANDLE handle;
344 int ret;
345
346 p11_test_file_write (test.directory, "test.cer", test_cacert3_ca_der,
347 sizeof (test_cacert3_ca_der));
348
349 ret = p11_token_load (test.token);
350 assert_num_eq (ret, 1);
351 handle = p11_index_find (test.index, cert, -1);
352 assert (handle != 0);
353
354 /* Have to wait to make sure changes are detected */
355 p11_sleep_ms (1100);
356
357 ret = p11_token_load (test.token);
358 assert_num_eq (ret, 0);
359 assert_num_eq (p11_index_find (test.index, cert, -1), handle);
360 }
361
362 static void
test_load_unreadable(void)363 test_load_unreadable (void)
364 {
365 CK_ATTRIBUTE cert[] = {
366 { CKA_CLASS, &certificate, sizeof (certificate) },
367 { CKA_SUBJECT, (void *)test_cacert3_ca_subject, sizeof (test_cacert3_ca_subject) },
368 { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) },
369 { CKA_INVALID },
370 };
371
372 int ret;
373
374 p11_test_file_write (test.directory, "test.cer", test_cacert3_ca_der,
375 sizeof (test_cacert3_ca_der));
376
377 ret = p11_token_load (test.token);
378 assert_num_eq (ret, 1);
379 assert (p11_index_find (test.index, cert, -1) != 0);
380
381 p11_test_file_write (test.directory, "test.cer", "", 0);
382
383 /* Have to wait to make sure changes are detected */
384 p11_sleep_ms (1100);
385
386 ret = p11_token_load (test.token);
387 assert_num_eq (ret, 0);
388 assert (p11_index_find (test.index, cert, -1) == 0);
389 }
390
391 static void
test_load_gone(void)392 test_load_gone (void)
393 {
394 CK_ATTRIBUTE cert[] = {
395 { CKA_CLASS, &certificate, sizeof (certificate) },
396 { CKA_SUBJECT, (void *)test_cacert3_ca_subject, sizeof (test_cacert3_ca_subject) },
397 { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) },
398 { CKA_INVALID },
399 };
400
401 int ret;
402
403 p11_test_file_write (test.directory, "test.cer", test_cacert3_ca_der,
404 sizeof (test_cacert3_ca_der));
405
406 ret = p11_token_load (test.token);
407 assert_num_eq (ret, 1);
408 assert (p11_index_find (test.index, cert, -1) != 0);
409
410 p11_test_file_delete (test.directory, "test.cer");
411
412 /* Have to wait to make sure changes are detected */
413 p11_sleep_ms (1100);
414
415 ret = p11_token_load (test.token);
416 assert_num_eq (ret, 0);
417 assert (p11_index_find (test.index, cert, -1) == 0);
418 }
419
420 static void
test_load_found(void)421 test_load_found (void)
422 {
423 CK_ATTRIBUTE cert[] = {
424 { CKA_CLASS, &certificate, sizeof (certificate) },
425 { CKA_SUBJECT, (void *)test_cacert3_ca_subject, sizeof (test_cacert3_ca_subject) },
426 { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) },
427 { CKA_INVALID },
428 };
429
430 int ret;
431
432 ret = p11_token_load (test.token);
433 assert_num_eq (ret, 0);
434 assert (p11_index_find (test.index, cert, -1) == 0);
435
436 /* Have to wait to make sure changes are detected */
437 p11_sleep_ms (1100);
438
439 p11_test_file_write (test.directory, "test.cer", test_cacert3_ca_der,
440 sizeof (test_cacert3_ca_der));
441
442 ret = p11_token_load (test.token);
443 assert_num_eq (ret, 1);
444 assert (p11_index_find (test.index, cert, -1) != 0);
445 }
446
447 static void
test_load_contrived(void)448 test_load_contrived (void)
449 {
450 int ret;
451 p11_index *index;
452
453 p11_test_file_write (test.directory, "contrived.der", test_contrived_der,
454 sizeof (test_contrived_der));
455
456 ret = p11_token_load (test.token);
457 assert_num_eq (ret, 1);
458
459 index = p11_token_index (test.token);
460 ret = p11_index_size (index);
461 assert_num_eq (ret, 3);
462 }
463
464 static void
test_reload_changed(void)465 test_reload_changed (void)
466 {
467 CK_ATTRIBUTE cacert3[] = {
468 { CKA_CLASS, &certificate, sizeof (certificate) },
469 { CKA_SUBJECT, (void *)test_cacert3_ca_subject, sizeof (test_cacert3_ca_subject) },
470 { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) },
471 { CKA_INVALID },
472 };
473
474 CK_ATTRIBUTE verisign[] = {
475 { CKA_CLASS, &certificate, sizeof (certificate) },
476 { CKA_VALUE, (void *)verisign_v1_ca, sizeof (verisign_v1_ca) },
477 { CKA_INVALID },
478 };
479
480 CK_ATTRIBUTE *attrs;
481 CK_OBJECT_HANDLE handle;
482 int ret;
483
484 /* Just one file */
485 p11_test_file_write (test.directory, "test.cer", test_cacert3_ca_der,
486 sizeof (test_cacert3_ca_der));
487
488 ret = p11_token_load (test.token);
489 assert_num_eq (ret, 1);
490 handle = p11_index_find (test.index, cacert3, -1);
491 assert (handle != 0);
492
493 /* Replace the file with verisign */
494 p11_test_file_write (test.directory, "test.cer", verisign_v1_ca,
495 sizeof (verisign_v1_ca));
496
497 /* Add another file with cacert3, but not reloaded */
498 p11_test_file_write (test.directory, "another.cer", test_cacert3_ca_der,
499 sizeof (test_cacert3_ca_der));
500
501 attrs = p11_index_lookup (test.index, handle);
502 assert_ptr_not_null (attrs);
503 if (!p11_token_reload (test.token, attrs))
504 assert_not_reached ();
505
506 assert (p11_index_find (test.index, cacert3, -1) == 0);
507 assert (p11_index_find (test.index, verisign, -1) != 0);
508 }
509
510 static void
test_reload_gone(void)511 test_reload_gone (void)
512 {
513 CK_ATTRIBUTE cacert3[] = {
514 { CKA_CLASS, &certificate, sizeof (certificate) },
515 { CKA_SUBJECT, (void *)test_cacert3_ca_subject, sizeof (test_cacert3_ca_subject) },
516 { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) },
517 { CKA_INVALID },
518 };
519
520 CK_ATTRIBUTE verisign[] = {
521 { CKA_CLASS, &certificate, sizeof (certificate) },
522 { CKA_VALUE, (void *)verisign_v1_ca, sizeof (verisign_v1_ca) },
523 { CKA_INVALID },
524 };
525
526 CK_ATTRIBUTE *attrs;
527 CK_OBJECT_HANDLE handle;
528 int ret;
529
530 /* Just one file */
531 p11_test_file_write (test.directory, "cacert3.cer", test_cacert3_ca_der,
532 sizeof (test_cacert3_ca_der));
533 p11_test_file_write (test.directory, "verisign.cer", verisign_v1_ca,
534 sizeof (verisign_v1_ca));
535
536 ret = p11_token_load (test.token);
537 assert_num_eq (ret, 2);
538 handle = p11_index_find (test.index, cacert3, -1);
539 assert (handle != 0);
540 assert (p11_index_find (test.index, verisign, -1) != 0);
541
542 p11_test_file_delete (test.directory, "cacert3.cer");
543 p11_test_file_delete (test.directory, "verisign.cer");
544
545 attrs = p11_index_lookup (test.index, handle);
546 assert_ptr_not_null (attrs);
547 if (p11_token_reload (test.token, attrs))
548 assert_not_reached ();
549
550 assert (p11_index_find (test.index, cacert3, -1) == 0);
551 assert (p11_index_find (test.index, verisign, -1) != 0);
552 }
553
554 static void
test_reload_no_origin(void)555 test_reload_no_origin (void)
556 {
557 CK_ATTRIBUTE cacert3[] = {
558 { CKA_CLASS, &certificate, sizeof (certificate) },
559 { CKA_SUBJECT, (void *)test_cacert3_ca_subject, sizeof (test_cacert3_ca_subject) },
560 { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) },
561 { CKA_INVALID },
562 };
563
564 if (p11_token_reload (test.token, cacert3))
565 assert_not_reached ();
566 }
567
568 static void
test_write_new(void)569 test_write_new (void)
570 {
571 CK_ATTRIBUTE original[] = {
572 { CKA_CLASS, &data, sizeof (data) },
573 { CKA_LABEL, "Yay!", 4 },
574 { CKA_VALUE, "eight", 5 },
575 { CKA_TOKEN, &truev, sizeof (truev) },
576 { CKA_INVALID }
577 };
578
579 CK_ATTRIBUTE expected[] = {
580 { CKA_CLASS, &data, sizeof (data) },
581 { CKA_LABEL, "Yay!", 4 },
582 { CKA_VALUE, "eight", 5 },
583 { CKA_APPLICATION, "", 0 },
584 { CKA_OBJECT_ID, "", 0 },
585 { CKA_INVALID }
586 };
587
588 CK_OBJECT_HANDLE handle;
589 p11_array *parsed;
590 char *path;
591 CK_RV rv;
592 int ret;
593
594 rv = p11_index_add (test.index, original, 4, &handle);
595 assert_num_eq (rv, CKR_OK);
596
597 /* The expected file name */
598 path = p11_path_build (test.directory, "Yay_.p11-kit", NULL);
599 ret = p11_parse_file (test.parser, path, NULL, 0);
600 assert_num_eq (ret, P11_PARSE_SUCCESS);
601 free (path);
602
603 parsed = p11_parser_parsed (test.parser);
604 assert_num_eq (parsed->num, 1);
605
606 test_check_attrs (expected, parsed->elem[0]);
607 }
608
609 static void
test_write_no_label(void)610 test_write_no_label (void)
611 {
612 CK_ATTRIBUTE original[] = {
613 { CKA_CLASS, &data, sizeof (data) },
614 { CKA_VALUE, "eight", 5 },
615 { CKA_TOKEN, &truev, sizeof (truev) },
616 { CKA_INVALID }
617 };
618
619 CK_ATTRIBUTE expected[] = {
620 { CKA_CLASS, &data, sizeof (data) },
621 { CKA_LABEL, "", 0 },
622 { CKA_VALUE, "eight", 5 },
623 { CKA_APPLICATION, "", 0 },
624 { CKA_OBJECT_ID, "", 0 },
625 { CKA_INVALID }
626 };
627
628 CK_OBJECT_HANDLE handle;
629 p11_array *parsed;
630 char *path;
631 CK_RV rv;
632 int ret;
633
634 rv = p11_index_add (test.index, original, 4, &handle);
635 assert_num_eq (rv, CKR_OK);
636
637 /* The expected file name */
638 path = p11_path_build (test.directory, "data.p11-kit", NULL);
639 ret = p11_parse_file (test.parser, path, NULL, 0);
640 assert_num_eq (ret, P11_PARSE_SUCCESS);
641 free (path);
642
643 parsed = p11_parser_parsed (test.parser);
644 assert_num_eq (parsed->num, 1);
645
646 test_check_attrs (expected, parsed->elem[0]);
647 }
648
649 static void
test_modify_multiple(void)650 test_modify_multiple (void)
651 {
652 const char *test_data =
653 "# This file has been auto-generated and written by p11-kit.\n"
654 "[p11-kit-object-v1]\n"
655 "class: data\n"
656 "label: \"first\"\n"
657 "value: \"1\"\n"
658 "\n"
659 "[p11-kit-object-v1]\n"
660 "class: data\n"
661 "label: \"second\"\n"
662 "value: \"2\"\n"
663 "\n"
664 "[p11-kit-object-v1]\n"
665 "class: data\n"
666 "label: \"third\"\n"
667 "value: \"3\"\n";
668
669 CK_ATTRIBUTE first[] = {
670 { CKA_CLASS, &data, sizeof (data) },
671 { CKA_LABEL, "first", 5 },
672 { CKA_VALUE, "1", 1 },
673 { CKA_INVALID },
674 };
675
676 CK_ATTRIBUTE second[] = {
677 { CKA_CLASS, &data, sizeof (data) },
678 { CKA_LABEL, "zwei", 4 },
679 { CKA_VALUE, "2", 2 },
680 { CKA_INVALID },
681 };
682
683 CK_ATTRIBUTE third[] = {
684 { CKA_CLASS, &data, sizeof (data) },
685 { CKA_LABEL, "third", 5 },
686 { CKA_VALUE, "3", 1 },
687 { CKA_INVALID },
688 };
689
690 CK_ATTRIBUTE match = { CKA_LABEL, "second", 6 };
691
692 CK_OBJECT_HANDLE handle;
693 p11_array *parsed;
694 char *path;
695 int ret;
696 CK_RV rv;
697
698 p11_test_file_write (test.directory, "Test.p11-kit", test_data, strlen (test_data));
699
700 /* Reload now that we have this new file */
701 p11_token_load (test.token);
702
703 handle = p11_index_find (test.index, &match, 1);
704
705 rv = p11_index_update (test.index, handle, p11_attrs_dup (second));
706 assert_num_eq (rv, CKR_OK);
707
708 /* Now read in the file and make sure it has all the objects */
709 path = p11_path_build (test.directory, "Test.p11-kit", NULL);
710 ret = p11_parse_file (test.parser, path, NULL, 0);
711 assert_num_eq (ret, P11_PARSE_SUCCESS);
712 free (path);
713
714 parsed = p11_parser_parsed (test.parser);
715 assert_num_eq (parsed->num, 3);
716
717 /* The modified one will be first */
718 test_check_attrs (second, parsed->elem[0]);
719 test_check_attrs (first, parsed->elem[1]);
720 test_check_attrs (third, parsed->elem[2]);
721 }
722
723 static void
test_remove_one(void)724 test_remove_one (void)
725 {
726 const char *test_data =
727 "[p11-kit-object-v1]\n"
728 "class: data\n"
729 "label: \"first\"\n"
730 "value: \"1\"\n"
731 "\n";
732
733 CK_ATTRIBUTE match = { CKA_LABEL, "first", 5 };
734
735 CK_OBJECT_HANDLE handle;
736 CK_RV rv;
737
738 p11_test_file_write (test.directory, "Test.p11-kit", test_data, strlen (test_data));
739 test_check_directory (test.directory, ("Test.p11-kit", NULL));
740
741 /* Reload now that we have this new file */
742 p11_token_load (test.token);
743
744 handle = p11_index_find (test.index, &match, 1);
745 assert_num_cmp (handle, !=, 0);
746
747 rv = p11_index_remove (test.index, handle);
748 assert_num_eq (rv, CKR_OK);
749
750 /* No other files in the test directory, all files gone */
751 test_check_directory (test.directory, (NULL, NULL));
752 }
753
754 static void
test_remove_multiple(void)755 test_remove_multiple (void)
756 {
757 const char *test_data =
758 "[p11-kit-object-v1]\n"
759 "class: data\n"
760 "label: \"first\"\n"
761 "value: \"1\"\n"
762 "\n"
763 "[p11-kit-object-v1]\n"
764 "class: data\n"
765 "label: \"second\"\n"
766 "value: \"2\"\n"
767 "\n"
768 "[p11-kit-object-v1]\n"
769 "class: data\n"
770 "label: \"third\"\n"
771 "value: \"3\"\n";
772
773 CK_ATTRIBUTE first[] = {
774 { CKA_CLASS, &data, sizeof (data) },
775 { CKA_LABEL, "first", 5 },
776 { CKA_VALUE, "1", 1 },
777 { CKA_INVALID },
778 };
779
780 CK_ATTRIBUTE third[] = {
781 { CKA_CLASS, &data, sizeof (data) },
782 { CKA_LABEL, "third", 5 },
783 { CKA_VALUE, "3", 1 },
784 { CKA_INVALID },
785 };
786
787 CK_ATTRIBUTE match = { CKA_LABEL, "second", 6 };
788
789 CK_OBJECT_HANDLE handle;
790 p11_array *parsed;
791 char *path;
792 int ret;
793 CK_RV rv;
794
795 p11_test_file_write (test.directory, "Test.p11-kit", test_data, strlen (test_data));
796
797 /* Reload now that we have this new file */
798 p11_token_load (test.token);
799
800 handle = p11_index_find (test.index, &match, 1);
801 assert_num_cmp (handle, !=, 0);
802
803 rv = p11_index_remove (test.index, handle);
804 assert_num_eq (rv, CKR_OK);
805
806 /* Now read in the file and make sure it has all the objects */
807 path = p11_path_build (test.directory, "Test.p11-kit", NULL);
808 ret = p11_parse_file (test.parser, path, NULL, 0);
809 assert_num_eq (ret, P11_PARSE_SUCCESS);
810 free (path);
811
812 parsed = p11_parser_parsed (test.parser);
813 assert_num_eq (parsed->num, 2);
814
815 /* The modified one will be first */
816 test_check_attrs (first, parsed->elem[0]);
817 test_check_attrs (third, parsed->elem[1]);
818 }
819
820 int
main(int argc,char * argv[])821 main (int argc,
822 char *argv[])
823 {
824 p11_fixture (setup, teardown);
825 p11_testx (test_token_load, SRCDIR "/trust/input", "/token/load");
826 p11_testx (test_token_flags, SRCDIR "/trust/input", "/token/flags");
827 p11_testx (test_token_path, "/wheee", "/token/path");
828 p11_testx (test_token_label, "/wheee", "/token/label");
829 p11_testx (test_token_slot, "/unneeded", "/token/slot");
830
831 p11_fixture (setup_writable, teardown_writable);
832 p11_test (test_not_writable, "/token/not-writable");
833 p11_test (test_writable_no_exist, "/token/writable-no-exist");
834
835 p11_fixture (setup_temp, teardown_temp);
836 p11_test (test_writable_exists, "/token/writable-exists");
837 p11_test (test_load_found, "/token/load-found");
838 p11_test (test_load_already, "/token/load-already");
839 p11_test (test_load_unreadable, "/token/load-unreadable");
840 p11_test (test_load_gone, "/token/load-gone");
841 p11_test (test_load_contrived, "/token/load-contrived");
842 p11_test (test_reload_changed, "/token/reload-changed");
843 p11_test (test_reload_gone, "/token/reload-gone");
844 p11_test (test_reload_no_origin, "/token/reload-no-origin");
845 p11_test (test_write_new, "/token/write-new");
846 p11_test (test_write_no_label, "/token/write-no-label");
847 p11_test (test_modify_multiple, "/token/modify-multiple");
848 p11_test (test_remove_one, "/token/remove-one");
849 p11_test (test_remove_multiple, "/token/remove-multiple");
850
851 return p11_test_run (argc, argv);
852 }
853