1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /*
3 Copyright (C) 2009 Stefan Walter
4
5 The Gnome Keyring Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
9
10 The Gnome Keyring Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with the Gnome Library; see the file COPYING.LIB. If not,
17 <http://www.gnu.org/licenses/>.
18
19 Author: Stef Walter <stef@memberwebs.com>
20 */
21
22 #include "config.h"
23
24 #include "mock-secret-module.h"
25
26 #include "secret-store/gkm-secret-collection.h"
27 #include "secret-store/gkm-secret-fields.h"
28 #include "secret-store/gkm-secret-item.h"
29 #include "secret-store/gkm-secret-search.h"
30
31 #include "gkm/gkm-session.h"
32 #include "gkm/gkm-transaction.h"
33 #include "gkm/gkm-test.h"
34
35 #include "pkcs11/pkcs11i.h"
36
37 #include <glib.h>
38
39 #include <stdlib.h>
40 #include <stdio.h>
41 #include <string.h>
42
43 typedef struct {
44 GkmModule *module;
45 GkmSession *session;
46 GkmFactory *factory;
47 GkmSecretCollection *collection;
48 GkmSecretItem *item;
49 } Test;
50
51 static void
setup(Test * test,gconstpointer unused)52 setup (Test *test, gconstpointer unused)
53 {
54 GHashTable *fields;
55
56 test->module = test_secret_module_initialize_and_enter ();
57 test->session = test_secret_module_open_session (TRUE);
58 test->factory = GKM_FACTORY_SECRET_SEARCH;
59 g_assert (test->factory);
60
61 test->collection = g_object_new (GKM_TYPE_SECRET_COLLECTION,
62 "module", test->module,
63 "manager", gkm_session_get_manager (test->session),
64 "identifier", "test-collection",
65 NULL);
66
67 /* Create an test->item */
68 test->item = gkm_secret_collection_new_item (test->collection, "test-item");
69 fields = gkm_secret_fields_new ();
70 gkm_secret_fields_add (fields, "name1", "value1");
71 gkm_secret_fields_add (fields, "name2", "value2");
72 gkm_secret_item_set_fields (test->item, fields);
73 g_hash_table_unref (fields);
74
75 gkm_object_expose (GKM_OBJECT (test->collection), TRUE);
76 }
77
78 static void
teardown(Test * test,gconstpointer unused)79 teardown (Test *test, gconstpointer unused)
80 {
81 g_object_unref (test->collection);
82 test_secret_module_leave_and_finalize ();
83 }
84
85 static void
test_incomplete(Test * test,gconstpointer unused)86 test_incomplete (Test *test, gconstpointer unused)
87 {
88 CK_ATTRIBUTE attrs[1];
89 GkmObject *object = NULL;
90 GkmTransaction *transaction = gkm_transaction_new ();
91
92 object = gkm_session_create_object_for_factory (test->session, test->factory, transaction, attrs, 0);
93 g_assert (gkm_transaction_complete_and_unref (transaction) == CKR_TEMPLATE_INCOMPLETE);
94 g_assert (object == NULL);
95 }
96
97 static void
test_bad_fields(Test * test,gconstpointer unused)98 test_bad_fields (Test *test, gconstpointer unused)
99 {
100 CK_ATTRIBUTE attrs[] = {
101 { CKA_G_FIELDS, "bad-value", 9 },
102 };
103
104 GkmObject *object = NULL;
105 GkmTransaction *transaction = gkm_transaction_new ();
106
107 object = gkm_session_create_object_for_factory (test->session, test->factory, transaction, attrs, 1);
108 g_assert (gkm_transaction_complete_and_unref (transaction) == CKR_ATTRIBUTE_VALUE_INVALID);
109 g_assert (object == NULL);
110 }
111
112 static void
test_new(Test * test,gconstpointer unused)113 test_new (Test *test, gconstpointer unused)
114 {
115 CK_ATTRIBUTE attrs[] = {
116 { CKA_G_FIELDS, "test\0value\0two\0value2", 22 },
117 };
118
119 const gchar *identifier;
120 GkmObject *object = NULL;
121 GHashTable *fields;
122 gpointer vdata;
123 gulong vulong;
124 gboolean vbool;
125 gsize vsize;
126
127 object = gkm_session_create_object_for_factory (test->session, test->factory, NULL, attrs, 1);
128 g_assert (object != NULL);
129 g_assert (GKM_IS_SECRET_SEARCH (object));
130
131 if (!gkm_object_get_attribute_ulong (object, test->session, CKA_CLASS, &vulong))
132 g_assert_not_reached ();
133 g_assert (vulong == CKO_G_SEARCH);
134
135 if (!gkm_object_get_attribute_boolean (object, test->session, CKA_MODIFIABLE, &vbool))
136 g_assert_not_reached ();
137 g_assert (vbool == CK_TRUE);
138
139 vdata = gkm_object_get_attribute_data (object, test->session, CKA_G_FIELDS, &vsize);
140 g_assert (vdata);
141 g_assert (vsize == attrs[0].ulValueLen);
142 g_free (vdata);
143
144 vdata = gkm_object_get_attribute_data (object, test->session, CKA_G_COLLECTION, &vsize);
145 g_assert (vdata);
146 g_assert (vsize == 0);
147 g_free (vdata);
148
149 /* No objects matched */
150 vdata = gkm_object_get_attribute_data (object, test->session, CKA_G_MATCHED, &vsize);
151 g_assert (vdata);
152 g_assert (vsize == 0);
153 g_free (vdata);
154
155 /* Get the fields object and check */
156 fields = gkm_secret_search_get_fields (GKM_SECRET_SEARCH (object));
157 g_assert (fields);
158 g_assert_cmpstr (gkm_secret_fields_get (fields, "test"), ==, "value");
159
160 /* No test->collection */
161 identifier = gkm_secret_search_get_collection_id (GKM_SECRET_SEARCH (object));
162 g_assert (identifier == NULL);
163
164 g_object_unref (object);
165 }
166
167 static void
test_and_match(Test * test,gconstpointer unused)168 test_and_match (Test *test, gconstpointer unused)
169 {
170 CK_ATTRIBUTE attrs[] = {
171 { CKA_G_FIELDS, "name1\0value1\0name2\0value2", 26 },
172 };
173
174 GkmObject *object = NULL;
175 gpointer vdata;
176 gsize vsize;
177
178 object = gkm_session_create_object_for_factory (test->session, test->factory, NULL, attrs, 1);
179 g_assert (object != NULL);
180 g_assert (GKM_IS_SECRET_SEARCH (object));
181
182 /* One object matched */
183 vdata = gkm_object_get_attribute_data (object, test->session, CKA_G_MATCHED, &vsize);
184 g_assert (vdata);
185 g_assert (vsize == sizeof (CK_OBJECT_HANDLE));
186 g_assert (*((CK_OBJECT_HANDLE_PTR)vdata) == gkm_object_get_handle (GKM_OBJECT (test->item)));
187 g_free (vdata);
188
189 g_object_unref (object);
190 }
191
192 static void
test_and_change_to_match(Test * test,gconstpointer unused)193 test_and_change_to_match (Test *test, gconstpointer unused)
194 {
195 CK_ATTRIBUTE attrs[] = {
196 { CKA_G_FIELDS, "name1\0value1", 13 },
197 };
198
199 GkmObject *object = NULL;
200 GHashTable *fields;
201 gpointer vdata;
202 gsize vsize;
203
204 /* Make it not match */
205 fields = gkm_secret_fields_new ();
206 gkm_secret_item_set_fields (test->item, fields);
207 g_hash_table_unref (fields);
208
209 object = gkm_session_create_object_for_factory (test->session, test->factory, NULL, attrs, 1);
210 g_assert (object != NULL);
211 g_assert (GKM_IS_SECRET_SEARCH (object));
212
213 /* Nothing matched */
214 vdata = gkm_object_get_attribute_data (object, test->session, CKA_G_MATCHED, &vsize);
215 g_assert (vsize == 0);
216 g_free (vdata);
217
218 /* Make it match */
219 fields = gkm_secret_fields_new ();
220 gkm_secret_fields_add (fields, "name1", "value1");
221 gkm_secret_fields_add (fields, "name2", "value2");
222 gkm_secret_item_set_fields (test->item, fields);
223 g_hash_table_unref (fields);
224
225 /* One object matched */
226 vdata = gkm_object_get_attribute_data (object, test->session, CKA_G_MATCHED, &vsize);
227 g_assert (vdata);
228 g_assert (vsize == sizeof (CK_OBJECT_HANDLE));
229 g_assert (*((CK_OBJECT_HANDLE_PTR)vdata) == gkm_object_get_handle (GKM_OBJECT (test->item)));
230 g_free (vdata);
231
232 g_object_unref (object);
233 }
234
235 static void
test_and_change_to_not_match(Test * test,gconstpointer unused)236 test_and_change_to_not_match (Test *test, gconstpointer unused)
237 {
238 CK_ATTRIBUTE attrs[] = {
239 { CKA_G_FIELDS, "name1\0value1", 13 },
240 };
241
242 GkmObject *object = NULL;
243 GHashTable *fields;
244 gpointer vdata;
245 gsize vsize;
246
247 object = gkm_session_create_object_for_factory (test->session, test->factory, NULL, attrs, 1);
248 g_assert (object != NULL);
249 g_assert (GKM_IS_SECRET_SEARCH (object));
250
251 /* One object matched */
252 vdata = gkm_object_get_attribute_data (object, test->session, CKA_G_MATCHED, &vsize);
253 g_assert (vdata);
254 g_assert (vsize == sizeof (CK_OBJECT_HANDLE));
255 g_assert (*((CK_OBJECT_HANDLE_PTR)vdata) == gkm_object_get_handle (GKM_OBJECT (test->item)));
256 g_free (vdata);
257
258 /* Make it not match */
259 fields = gkm_secret_fields_new ();
260 gkm_secret_item_set_fields (test->item, fields);
261 g_hash_table_unref (fields);
262
263 /* Nothing matched */
264 vdata = gkm_object_get_attribute_data (object, test->session, CKA_G_MATCHED, &vsize);
265 g_assert (vsize == 0);
266 g_free (vdata);
267
268 g_object_unref (object);
269 }
270
271 static void
test_for_bad_collection(Test * test,gconstpointer unused)272 test_for_bad_collection (Test *test, gconstpointer unused)
273 {
274 CK_ATTRIBUTE attrs[] = {
275 { CKA_G_FIELDS, "name1\0value1", 13 },
276 { CKA_G_COLLECTION, "bad-test->collection", 14 },
277 };
278
279 GkmObject *object = NULL;
280 GkmTransaction *transaction = gkm_transaction_new ();
281
282 object = gkm_session_create_object_for_factory (test->session, test->factory, transaction, attrs, 2);
283 g_assert (gkm_transaction_complete_and_unref (transaction) == CKR_OK);
284
285 g_object_unref (object);
286 }
287
288 static void
test_for_collection(Test * test,gconstpointer unused)289 test_for_collection (Test *test, gconstpointer unused)
290 {
291 CK_ATTRIBUTE attrs[] = {
292 { CKA_G_FIELDS, "name1\0value1", 13 },
293 { CKA_G_COLLECTION, "test-collection", 15 },
294 };
295
296 GkmObject *object = NULL;
297 gpointer vdata;
298 gsize vsize;
299
300 object = gkm_session_create_object_for_factory (test->session, test->factory, NULL, attrs, 2);
301 g_assert (object != NULL);
302 g_assert (GKM_IS_SECRET_SEARCH (object));
303
304 /* Should have the test->collection set properly */
305 vdata = gkm_object_get_attribute_data (object, test->session, CKA_G_COLLECTION , &vsize);
306 g_assert (vdata);
307 g_assert (vsize == 15);
308 g_assert (memcmp (vdata, "test-collection", 15) == 0);
309 g_free (vdata);
310
311 /* One object matched */
312 vdata = gkm_object_get_attribute_data (object, test->session, CKA_G_MATCHED, &vsize);
313 g_assert (vdata);
314 g_assert (vsize == sizeof (CK_OBJECT_HANDLE));
315 g_assert (*((CK_OBJECT_HANDLE_PTR)vdata) == gkm_object_get_handle (GKM_OBJECT (test->item)));
316 g_free (vdata);
317
318 g_object_unref (object);
319 }
320
321 static void
test_for_collection_no_match(Test * test,gconstpointer unused)322 test_for_collection_no_match (Test *test, gconstpointer unused)
323 {
324 CK_ATTRIBUTE attrs[] = {
325 { CKA_G_FIELDS, "test\0value", 11 },
326 { CKA_G_COLLECTION, "test-collection", 15 },
327 };
328
329 GkmObject *object = NULL;
330 GkmSecretCollection *ocoll;
331 GkmSecretItem *oitem;
332 GHashTable *fields;
333 gpointer vdata;
334 gsize vsize;
335
336 ocoll = g_object_new (GKM_TYPE_SECRET_COLLECTION,
337 "module", test->module,
338 "manager", gkm_session_get_manager (test->session),
339 "identifier", "other-collection",
340 NULL);
341 oitem = gkm_secret_collection_new_item (ocoll, "other-item");
342 gkm_object_expose (GKM_OBJECT (ocoll), TRUE);
343
344 /* Make it match, but remember, wrong collection*/
345 fields = gkm_secret_fields_new ();
346 gkm_secret_fields_add (fields, "test", "value");
347 gkm_secret_item_set_fields (oitem, fields);
348 g_hash_table_unref (fields);
349
350 object = gkm_session_create_object_for_factory (test->session, test->factory, NULL, attrs, 2);
351 g_assert (object != NULL);
352 g_assert (GKM_IS_SECRET_SEARCH (object));
353
354 /* No objects matched */
355 vdata = gkm_object_get_attribute_data (object, test->session, CKA_G_MATCHED, &vsize);
356 g_assert (vsize == 0);
357 g_free (vdata);
358
359 g_object_unref (object);
360 g_object_unref (ocoll);
361 }
362
363 static void
test_order(Test * test,gconstpointer unused)364 test_order (Test *test,
365 gconstpointer unused)
366 {
367 CK_ATTRIBUTE attrs[] = {
368 { CKA_G_FIELDS, "test\0value", 11 },
369 { CKA_G_COLLECTION, "other-collection", 16 },
370 };
371
372 GkmObject *object = NULL;
373 GkmSecretCollection *collection;
374 GkmSecretItem *item;
375 GHashTable *fields;
376 gulong *matched;
377 gsize vsize;
378 gchar *identifier;
379 glong modified;
380 glong last;
381 gint i;
382 CK_RV rv;
383
384 collection = g_object_new (GKM_TYPE_SECRET_COLLECTION,
385 "module", test->module,
386 "manager", gkm_session_get_manager (test->session),
387 "identifier", "other-collection",
388 NULL);
389
390 gkm_object_expose (GKM_OBJECT (collection), TRUE);
391
392 /* Add a bunch of items */
393 for (i = 0; i < 2000; i++) {
394 identifier = g_strdup_printf ("item-%d", i);
395 item = gkm_secret_collection_new_item (collection, identifier);
396 g_free (identifier);
397
398 /* Make it match, but remember, wrong collection*/
399 fields = gkm_secret_fields_new ();
400 gkm_secret_fields_add (fields, "test", "value");
401 gkm_secret_item_set_fields (item, fields);
402 g_hash_table_unref (fields);
403
404 gkm_secret_object_set_modified (GKM_SECRET_OBJECT (item),
405 (glong)g_random_int ());
406 gkm_object_expose (GKM_OBJECT (item), TRUE);
407 }
408
409 object = gkm_session_create_object_for_factory (test->session, test->factory, NULL, attrs, 2);
410 g_assert (object != NULL);
411 g_assert (GKM_IS_SECRET_SEARCH (object));
412
413 /* No objects matched */
414 matched = gkm_object_get_attribute_data (object, test->session, CKA_G_MATCHED, &vsize);
415 g_assert (matched != NULL);
416 gkm_assert_cmpulong (vsize, ==, sizeof (gulong) * 2000);
417
418 last = G_MAXLONG;
419 for (i = 0; i < vsize / sizeof (gulong); i++) {
420 rv = gkm_session_lookup_readable_object (test->session, matched[i], (GkmObject **)&item);
421 gkm_assert_cmprv (rv, ==, CKR_OK);
422
423 modified = gkm_secret_object_get_modified (GKM_SECRET_OBJECT (item));
424 g_assert (last > modified);
425 last = modified;
426 }
427
428 g_free (matched);
429
430 g_object_unref (object);
431 g_object_unref (collection);
432 }
433
434 int
main(int argc,char ** argv)435 main (int argc, char **argv)
436 {
437 #if !GLIB_CHECK_VERSION(2,35,0)
438 g_type_init ();
439 #endif
440 g_test_init (&argc, &argv, NULL);
441
442 g_test_add ("/secret-store/search/new", Test, NULL, setup, test_new, teardown);
443 g_test_add ("/secret-store/search/incomplete", Test, NULL, setup, test_incomplete, teardown);
444 g_test_add ("/secret-store/search/bad_fields", Test, NULL, setup, test_bad_fields, teardown);
445 g_test_add ("/secret-store/search/and_match", Test, NULL, setup, test_and_match, teardown);
446 g_test_add ("/secret-store/search/and_change_to_match", Test, NULL, setup, test_and_change_to_match, teardown);
447 g_test_add ("/secret-store/search/and_change_to_not_match", Test, NULL, setup, test_and_change_to_not_match, teardown);
448 g_test_add ("/secret-store/search/for_bad_collection", Test, NULL, setup, test_for_bad_collection, teardown);
449 g_test_add ("/secret-store/search/for_collection", Test, NULL, setup, test_for_collection, teardown);
450 g_test_add ("/secret-store/search/for_collection_no_match", Test, NULL, setup, test_for_collection_no_match, teardown);
451 g_test_add ("/secret-store/search/order", Test, NULL, setup, test_order, teardown);
452
453 return g_test_run ();
454 }
455