Line data Source code
1 : /*
2 : * gnome-keyring
3 : *
4 : * Copyright (C) 2008 Stefan Walter
5 : *
6 : * This program is free software; you can redistribute it and/or modify
7 : * it under the terms of the GNU Lesser General Public License as
8 : * published by the Free Software Foundation; either version 2.1 of
9 : * the License, or (at your option) any later version.
10 : *
11 : * This program is distributed in the hope that it will be useful, but
12 : * WITHOUT ANY WARRANTY; without even the implied warranty of
13 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : * Lesser General Public License for more details.
15 : *
16 : * You should have received a copy of the GNU Lesser General Public
17 : * License along with this program; if not, see
18 : * <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include "config.h"
22 :
23 : #include "gkm-attributes.h"
24 : #include "gkm-manager.h"
25 : #include "gkm-marshal.h"
26 : #include "gkm-module.h"
27 : #include "gkm-session.h"
28 : #include "gkm-util.h"
29 :
30 : #include <glib.h>
31 : #include <glib/gi18n.h>
32 :
33 : #include <stdarg.h>
34 :
35 : enum {
36 : PROP_0,
37 : PROP_FOR_TOKEN
38 : };
39 :
40 : enum {
41 : OBJECT_ADDED,
42 : OBJECT_REMOVED,
43 : ATTRIBUTE_CHANGED,
44 : LAST_SIGNAL
45 : };
46 :
47 : static guint signals[LAST_SIGNAL] = { 0 };
48 :
49 : struct _GkmManagerPrivate {
50 : gboolean for_token;
51 : GList *objects;
52 : GHashTable *index_by_attribute;
53 : GHashTable *index_by_property;
54 : };
55 :
56 : typedef struct _Index {
57 : gboolean unique;
58 : CK_ATTRIBUTE_TYPE attribute_type;
59 : gchar *property_name;
60 : GHashTable *values;
61 : GHashTable *objects;
62 : } Index;
63 :
64 : typedef struct _Finder {
65 : GkmManager *manager;
66 : void (*accumulator) (struct _Finder *ctx, GkmObject *found);
67 : gpointer results;
68 : CK_ATTRIBUTE_PTR attrs;
69 : CK_ULONG n_attrs;
70 : GkmSession *session;
71 : } Finder;
72 :
73 42354 : G_DEFINE_TYPE_WITH_PRIVATE (GkmManager, gkm_manager, G_TYPE_OBJECT);
74 :
75 : /* Friend functions for GkmObject */
76 : void _gkm_manager_register_object (GkmManager *self, GkmObject *object);
77 : void _gkm_manager_unregister_object (GkmManager *self, GkmObject *object);
78 :
79 : /* -----------------------------------------------------------------------------
80 : * HELPERS
81 : */
82 :
83 : static void
84 7710 : attribute_free (gpointer data)
85 : {
86 7710 : CK_ATTRIBUTE_PTR attr = data;
87 7710 : if (attr) {
88 7710 : g_free (attr->pValue);
89 7710 : g_slice_free (CK_ATTRIBUTE, attr);
90 : }
91 7710 : }
92 :
93 : static Index*
94 1485 : index_new (gboolean unique)
95 : {
96 1485 : Index *index = g_slice_new0 (Index);
97 1485 : index->unique = unique;
98 :
99 1485 : if (unique)
100 495 : index->values = g_hash_table_new_full (gkm_attribute_hash, gkm_attribute_equal, attribute_free, NULL);
101 : else
102 990 : index->values = g_hash_table_new_full (gkm_attribute_hash, gkm_attribute_equal, attribute_free,
103 : (GDestroyNotify)g_hash_table_destroy);
104 :
105 1485 : index->objects = g_hash_table_new (g_direct_hash, g_direct_equal);
106 :
107 1485 : return index;
108 : }
109 :
110 : static void
111 1485 : index_free (gpointer data)
112 : {
113 1485 : Index *index = data;
114 1485 : if (index) {
115 1485 : g_hash_table_destroy (index->values);
116 1485 : g_hash_table_destroy (index->objects);
117 1485 : g_free (index->property_name);
118 1485 : g_slice_free (Index, index);
119 : }
120 1485 : }
121 :
122 : static gboolean
123 5340 : read_attribute(GkmObject *object, CK_ATTRIBUTE_TYPE type, CK_ATTRIBUTE_PTR *result)
124 : {
125 : CK_ATTRIBUTE attr;
126 : CK_RV rv;
127 :
128 5340 : g_assert (GKM_IS_OBJECT (object));
129 5340 : g_assert (result);
130 :
131 5340 : *result = NULL;
132 :
133 5340 : attr.type = type;
134 5340 : attr.pValue = NULL;
135 5340 : attr.ulValueLen = 0;
136 :
137 : /* Figure out memory length */
138 5340 : rv = gkm_object_get_attribute (object, NULL, &attr);
139 :
140 : /* Not an error, just not present */
141 5340 : if (rv == CKR_ATTRIBUTE_TYPE_INVALID) {
142 300 : *result = NULL;
143 300 : return TRUE;
144 : }
145 :
146 5040 : if (rv != CKR_OK) {
147 0 : g_warning ("accessing indexed attribute failed");
148 0 : return FALSE;
149 : }
150 :
151 : /* Allocate memory length */
152 5040 : if (attr.ulValueLen) {
153 5022 : attr.pValue = g_malloc0 (attr.ulValueLen);
154 5022 : rv = gkm_object_get_attribute (object, NULL, &attr);
155 5022 : if (rv != CKR_OK) {
156 0 : g_warning ("accessing indexed attribute failed");
157 0 : g_free (attr.pValue);
158 0 : return FALSE;
159 : }
160 : }
161 :
162 5040 : *result = g_slice_new (CK_ATTRIBUTE);
163 5040 : memcpy (*result, &attr, sizeof (CK_ATTRIBUTE));
164 5040 : return TRUE;
165 : }
166 :
167 : static gboolean
168 2670 : read_value (GkmObject *object, const gchar *property, CK_ATTRIBUTE_PTR *result)
169 : {
170 : CK_ATTRIBUTE attr;
171 : GParamSpec *spec;
172 2670 : GValue value = { 0, };
173 : CK_ULONG number;
174 : CK_BBOOL boolean;
175 :
176 2670 : g_assert (GKM_IS_OBJECT (object));
177 2670 : g_assert (property);
178 2670 : g_assert (result);
179 :
180 2670 : spec = g_object_class_find_property (G_OBJECT_GET_CLASS (object),
181 : property);
182 :
183 : /* Not an error, just no such property on object */
184 2670 : if (spec == NULL) {
185 0 : *result = NULL;
186 0 : return TRUE;
187 : }
188 :
189 2670 : g_value_init(&value, spec->value_type);
190 2670 : g_object_get_property (G_OBJECT (object), property, &value);
191 :
192 2670 : attr.type = (CK_ATTRIBUTE_TYPE)-1;
193 2670 : attr.pValue = NULL;
194 2670 : attr.ulValueLen = 0;
195 :
196 : /* We only support specific types of values */
197 2670 : switch (spec->value_type)
198 : {
199 0 : case G_TYPE_STRING:
200 0 : attr.pValue = g_value_dup_string (&value);
201 0 : attr.ulValueLen = attr.pValue ? strlen (attr.pValue) : 0;
202 0 : break;
203 0 : case G_TYPE_INT:
204 0 : number = g_value_get_int (&value);
205 0 : attr.ulValueLen = sizeof (number);
206 0 : attr.pValue = g_memdup (&number, attr.ulValueLen);
207 0 : break;
208 0 : case G_TYPE_UINT:
209 0 : number = g_value_get_uint (&value);
210 0 : attr.ulValueLen = sizeof (number);
211 0 : attr.pValue = g_memdup (&number, attr.ulValueLen);
212 0 : break;
213 0 : case G_TYPE_LONG:
214 0 : number = g_value_get_long (&value);
215 0 : attr.ulValueLen = sizeof (number);
216 0 : attr.pValue = g_memdup (&number, attr.ulValueLen);
217 0 : break;
218 2670 : case G_TYPE_ULONG:
219 2670 : number = g_value_get_ulong (&value);
220 2670 : attr.ulValueLen = sizeof (number);
221 2670 : attr.pValue = g_memdup (&number, attr.ulValueLen);
222 2670 : break;
223 0 : case G_TYPE_BOOLEAN:
224 0 : boolean = g_value_get_boolean (&value) ? CK_TRUE : CK_FALSE;
225 0 : attr.ulValueLen = sizeof (boolean);
226 0 : attr.pValue = g_memdup (&boolean, attr.ulValueLen);
227 0 : break;
228 0 : default:
229 0 : g_warning ("couldn't convert value from type %s into attribute",
230 : g_type_name (spec->value_type));
231 0 : g_value_unset (&value);
232 0 : return FALSE;
233 : };
234 :
235 2670 : if (attr.pValue) {
236 2670 : *result = g_slice_new (CK_ATTRIBUTE);
237 2670 : memcpy (*result, &attr, sizeof (CK_ATTRIBUTE));
238 : } else {
239 0 : *result = NULL;
240 : }
241 :
242 2670 : g_value_unset (&value);
243 2670 : return TRUE;
244 : }
245 :
246 : static void
247 7710 : index_remove_attr (Index *index, gpointer object, CK_ATTRIBUTE_PTR attr)
248 : {
249 : GHashTable *objects;
250 :
251 7710 : g_assert (index);
252 7710 : g_assert (object);
253 7710 : g_assert (attr);
254 :
255 7710 : if (index->unique) {
256 2670 : if (!g_hash_table_remove (index->values, attr))
257 0 : g_assert_not_reached ();
258 : } else {
259 5040 : objects = g_hash_table_lookup (index->values, attr);
260 5040 : g_assert (objects);
261 5040 : if (!g_hash_table_remove (objects, object))
262 0 : g_assert_not_reached ();
263 5040 : if (g_hash_table_size (objects) == 0)
264 2787 : if (!g_hash_table_remove (index->values, attr))
265 0 : g_assert_not_reached ();
266 : }
267 7710 : }
268 :
269 : static void
270 8010 : index_remove (Index *index, gpointer object)
271 : {
272 : CK_ATTRIBUTE_PTR attr;
273 :
274 : /*
275 : * We don't actually access the object. We want to be able to
276 : * handle objects that have been destroyed as well.
277 : */
278 :
279 8010 : g_assert (object);
280 8010 : g_assert (index);
281 :
282 8010 : attr = g_hash_table_lookup (index->objects, object);
283 :
284 : /* Object not in this index */
285 8010 : if (attr == NULL)
286 300 : return;
287 :
288 : /* Remove the actual value */
289 7710 : index_remove_attr (index, object, attr);
290 :
291 7710 : if (!g_hash_table_remove (index->objects, object))
292 0 : g_assert_not_reached ();
293 : }
294 :
295 : static void
296 8010 : index_update (Index *index, GkmObject *object)
297 : {
298 8010 : CK_ATTRIBUTE_PTR attr = NULL;
299 : CK_ATTRIBUTE_PTR prev;
300 : GHashTable *objects;
301 : gboolean ret;
302 :
303 8010 : g_assert (GKM_IS_OBJECT (object));
304 8010 : g_assert (index);
305 :
306 : /* Get the value for this index */
307 8010 : if (index->property_name)
308 2670 : ret = read_value (object, index->property_name, &attr);
309 : else
310 5340 : ret = read_attribute (object, index->attribute_type, &attr);
311 8310 : g_return_if_fail (ret);
312 :
313 : /* No such attribute/property on object */
314 8010 : if (attr == NULL)
315 300 : return;
316 :
317 7710 : prev = g_hash_table_lookup (index->objects, object);
318 7710 : if (prev != NULL) {
319 :
320 : /* The previous one is same, ignore */
321 0 : if (gkm_attribute_equal (prev, attr)) {
322 0 : attribute_free (attr);
323 0 : return;
324 : }
325 :
326 : /* Remove the previous one */
327 0 : index_remove_attr (index, object, prev);
328 : }
329 :
330 : /* In this case values is a direct pointer to the object */
331 7710 : if (index->unique) {
332 2670 : g_return_if_fail (g_hash_table_lookup (index->values, attr) == NULL);
333 2670 : g_hash_table_replace (index->values, attr, object);
334 2670 : g_hash_table_replace (index->objects, object, attr);
335 :
336 : /* In this case values is a pointer to a hash set of objects */
337 : } else {
338 : gpointer key, value;
339 5040 : if (g_hash_table_lookup_extended (index->values, attr, &key, &value)) {
340 2253 : attribute_free (attr);
341 2253 : objects = value;
342 2253 : attr = key;
343 : } else {
344 2787 : objects = g_hash_table_new (g_direct_hash, g_direct_equal);
345 2787 : g_hash_table_insert (index->values, attr, objects);
346 : }
347 :
348 5040 : g_hash_table_insert (objects, object, object);
349 5040 : g_hash_table_replace (index->objects, object, attr);
350 : }
351 : }
352 :
353 : static gboolean
354 112 : index_contains (Index *index, GkmObject *object, CK_ATTRIBUTE_PTR attr)
355 : {
356 : GHashTable *objects;
357 :
358 112 : g_assert (index);
359 112 : g_assert (GKM_IS_OBJECT (object));
360 112 : g_assert (attr);
361 :
362 112 : if (index->unique) {
363 0 : return (g_hash_table_lookup (index->values, attr) == object);
364 : } else {
365 112 : objects = g_hash_table_lookup (index->values, attr);
366 112 : return (objects && g_hash_table_lookup (objects, object) == object);
367 : }
368 : }
369 :
370 : static void
371 8010 : index_object_each (gpointer key, gpointer value, gpointer user_data)
372 : {
373 8010 : index_update (value, user_data);
374 8010 : }
375 :
376 : static void
377 8010 : index_remove_each (gpointer key, gpointer value, gpointer user_data)
378 : {
379 8010 : index_remove (value, user_data);
380 8010 : }
381 :
382 : static void
383 2080 : notify_attribute (GkmObject *object, CK_ATTRIBUTE_TYPE attr_type, GkmManager *self)
384 : {
385 : Index *index;
386 :
387 2080 : g_return_if_fail (GKM_IS_OBJECT (object));
388 2080 : g_return_if_fail (GKM_IS_MANAGER (self));
389 2080 : g_return_if_fail (gkm_object_get_manager (object) == self);
390 :
391 2080 : index = g_hash_table_lookup (self->pv->index_by_attribute, &attr_type);
392 2080 : if (index != NULL)
393 0 : index_update (index, object);
394 :
395 : /* Tell everyone that this attribute changed on this object */
396 2080 : g_signal_emit (self, signals[ATTRIBUTE_CHANGED], 0, object, attr_type);
397 : }
398 :
399 : static void
400 4237 : notify_property (GkmObject *object, GParamSpec *spec, GkmManager *self)
401 : {
402 : Index *index;
403 :
404 4237 : g_return_if_fail (GKM_IS_OBJECT (object));
405 4237 : g_return_if_fail (GKM_IS_MANAGER (self));
406 4237 : g_return_if_fail (gkm_object_get_manager (object) == self);
407 :
408 4237 : index = g_hash_table_lookup (self->pv->index_by_property, spec->name);
409 4237 : if (index != NULL)
410 0 : index_update (index, object);
411 : }
412 :
413 : static void
414 2670 : add_object (GkmManager *self, GkmObject *object)
415 : {
416 : CK_OBJECT_HANDLE handle;
417 :
418 2670 : g_assert (GKM_IS_MANAGER (self));
419 2670 : g_assert (GKM_IS_OBJECT (object));
420 2670 : g_assert (gkm_object_get_manager (object) == self);
421 :
422 2670 : handle = gkm_object_get_handle (object);
423 2670 : if (!handle) {
424 : /* Make a new handle */
425 2669 : handle = gkm_util_next_handle ();
426 2669 : gkm_object_set_handle (object, handle);
427 : }
428 :
429 : /*
430 : * We don't ref the objects or anything. They're expected to
431 : * unregister upon dispose.
432 : */
433 :
434 : /* Note objects is being managed */
435 2670 : self->pv->objects = g_list_prepend (self->pv->objects, object);
436 :
437 : /* Now index the object properly */
438 2670 : g_hash_table_foreach (self->pv->index_by_attribute, index_object_each, object);
439 2670 : g_hash_table_foreach (self->pv->index_by_property, index_object_each, object);
440 2670 : g_signal_connect (object, "notify-attribute", G_CALLBACK (notify_attribute), self);
441 2670 : g_signal_connect (object, "notify", G_CALLBACK (notify_property), self);
442 :
443 : /* Tell everyone we added this object */
444 2670 : g_signal_emit (self, signals[OBJECT_ADDED], 0, object);
445 2670 : }
446 :
447 : static void
448 2670 : remove_object (GkmManager *self, GkmObject *object)
449 : {
450 : CK_OBJECT_HANDLE handle;
451 :
452 2670 : g_assert (GKM_IS_MANAGER (self));
453 2670 : g_assert (GKM_IS_OBJECT (object));
454 2670 : g_assert (gkm_object_get_manager (object) == self);
455 :
456 2670 : handle = gkm_object_get_handle (object);
457 2670 : g_assert (handle);
458 :
459 : /* Remove from all indexes */
460 2670 : g_signal_handlers_disconnect_by_func (object, G_CALLBACK (notify_attribute), self);
461 2670 : g_signal_handlers_disconnect_by_func (object, G_CALLBACK (notify_property), self);
462 2670 : g_hash_table_foreach (self->pv->index_by_attribute, index_remove_each, object);
463 2670 : g_hash_table_foreach (self->pv->index_by_property, index_remove_each, object);
464 :
465 : /* Release object management */
466 2670 : self->pv->objects = g_list_remove (self->pv->objects, object);
467 :
468 : /* Tell everyone this object is gone */
469 2670 : g_signal_emit (self, signals[OBJECT_REMOVED], 0, object);
470 2670 : }
471 :
472 : static void
473 2710 : find_each_object (gpointer unused, gpointer object, gpointer user_data)
474 : {
475 2710 : Finder *finder = user_data;
476 : CK_ATTRIBUTE_PTR attr;
477 : Index *index;
478 : CK_ULONG i;
479 :
480 2710 : g_assert (finder);
481 2710 : g_assert (GKM_IS_MANAGER (finder->manager));
482 :
483 : /* Match the object against all the other attributes */
484 3053 : for (i = 0; i < finder->n_attrs; ++i) {
485 628 : attr = &(finder->attrs[i]);
486 628 : index = g_hash_table_lookup (finder->manager->pv->index_by_attribute, &attr->type);
487 628 : if (index) {
488 112 : if (!index_contains (index, object, attr))
489 58 : return;
490 : } else {
491 516 : if (!gkm_object_match (object, finder->session, attr))
492 227 : return;
493 : }
494 : }
495 :
496 2425 : (finder->accumulator) (finder, object);
497 : }
498 :
499 : static void
500 803 : find_for_attributes (Finder *finder)
501 : {
502 : GHashTable *objects;
503 : CK_ATTRIBUTE_PTR first;
504 : GkmObject *object;
505 : Index *index;
506 : GList *l;
507 :
508 803 : g_assert (finder);
509 803 : g_assert (GKM_IS_MANAGER (finder->manager));
510 803 : g_assert (!finder->n_attrs || finder->attrs);
511 :
512 : /* All the objects */
513 803 : if (!finder->n_attrs) {
514 26 : for (l = finder->manager->pv->objects; l; l = g_list_next (l))
515 14 : (finder->accumulator) (finder, l->data);
516 12 : return;
517 : }
518 :
519 791 : first = finder->attrs;
520 791 : finder->attrs = finder->attrs + 1;
521 791 : finder->n_attrs = finder->n_attrs - 1;
522 :
523 791 : index = g_hash_table_lookup (finder->manager->pv->index_by_attribute,
524 791 : &first->type);
525 :
526 :
527 : /* No indexes, have to manually match */
528 791 : if (!index) {
529 :
530 69 : for (l = finder->manager->pv->objects; l; l = g_list_next (l)) {
531 43 : if (gkm_object_match (l->data, NULL, first))
532 8 : find_each_object (NULL, l->data, finder);
533 : }
534 :
535 26 : return;
536 : }
537 :
538 : /* Yay, an index */
539 765 : if (index->unique) {
540 0 : object = g_hash_table_lookup (index->values, first);
541 0 : if (object)
542 0 : find_each_object (NULL, object, finder);
543 : } else {
544 765 : objects = g_hash_table_lookup (index->values, first);
545 765 : if (objects)
546 437 : g_hash_table_foreach (objects, find_each_object, finder);
547 : }
548 : }
549 :
550 : static void
551 2240 : accumulate_list (Finder *finder, GkmObject *object)
552 : {
553 2240 : finder->results = g_list_prepend (finder->results, object);
554 2240 : }
555 :
556 : static void
557 4 : accumulate_one (Finder *finder, GkmObject *object)
558 : {
559 4 : if (!finder->results)
560 4 : finder->results = object;
561 4 : }
562 :
563 : static void
564 195 : accumulate_handles (Finder *finder, GkmObject *object)
565 : {
566 195 : CK_OBJECT_HANDLE handle = gkm_object_get_handle (object);
567 195 : g_return_if_fail (handle);
568 195 : g_array_append_val (finder->results, handle);
569 : }
570 :
571 : static void
572 0 : accumulate_public_handles (Finder *finder, GkmObject *object)
573 : {
574 : gboolean is_private;
575 0 : if (gkm_object_get_attribute_boolean (object, NULL, CKA_PRIVATE, &is_private) && is_private)
576 0 : return;
577 0 : accumulate_handles (finder, object);
578 : }
579 :
580 : static void
581 0 : values_to_list (gpointer key, gpointer value, gpointer user_data)
582 : {
583 0 : GList** list = (GList**)user_data;
584 0 : *list = g_list_prepend (*list, value);
585 0 : }
586 :
587 : static GList*
588 0 : find_all_for_property (GkmManager *self, const gchar *property, CK_ATTRIBUTE_PTR attr)
589 : {
590 : GkmObject *object;
591 : GHashTable *objects;
592 0 : GList *results = NULL;
593 : Index *index;
594 :
595 0 : g_assert (GKM_IS_MANAGER (self));
596 0 : g_assert (property);
597 0 : g_assert (attr);
598 :
599 0 : index = g_hash_table_lookup (self->pv->index_by_property, property);
600 0 : g_return_val_if_fail (index, NULL);
601 :
602 0 : if (index->unique) {
603 0 : object = g_hash_table_lookup (index->values, attr);
604 0 : return object ? g_list_prepend (NULL, object) : NULL;
605 : } else {
606 0 : objects = g_hash_table_lookup (index->values, attr);
607 0 : if (!objects)
608 0 : return NULL;
609 0 : g_hash_table_foreach (objects, values_to_list, &results);
610 0 : return results;
611 : }
612 : }
613 :
614 : static GkmObject*
615 4772 : find_one_for_property (GkmManager *self, const gchar *property, CK_ATTRIBUTE_PTR attr)
616 : {
617 : GkmObject *object;
618 : GHashTable *objects;
619 4772 : GList *results = NULL;
620 : Index *index;
621 :
622 4772 : g_assert (GKM_IS_MANAGER (self));
623 4772 : g_assert (property);
624 4772 : g_assert (attr);
625 :
626 4772 : index = g_hash_table_lookup (self->pv->index_by_property, property);
627 4772 : g_return_val_if_fail (index, NULL);
628 :
629 4772 : if (index->unique) {
630 4772 : return g_hash_table_lookup (index->values, attr);
631 : } else {
632 0 : objects = g_hash_table_lookup (index->values, attr);
633 0 : if (!objects)
634 0 : return NULL;
635 0 : g_hash_table_foreach (objects, values_to_list, &results);
636 0 : object = results ? results->data : NULL;
637 0 : g_list_free (results);
638 0 : return object;
639 : }
640 : }
641 :
642 : /* -----------------------------------------------------------------------------
643 : * OBJECT
644 : */
645 :
646 : static void
647 495 : gkm_manager_init (GkmManager *self)
648 : {
649 495 : self->pv = gkm_manager_get_instance_private (self);
650 495 : self->pv->index_by_attribute = g_hash_table_new_full (gkm_util_ulong_hash, gkm_util_ulong_equal,
651 : gkm_util_ulong_free, index_free);
652 495 : self->pv->index_by_property = g_hash_table_new_full (g_str_hash, g_str_equal,
653 : g_free, index_free);
654 495 : gkm_manager_add_property_index (self, "handle", TRUE);
655 495 : gkm_manager_add_attribute_index (self, CKA_ID, FALSE);
656 495 : gkm_manager_add_attribute_index (self, CKA_CLASS, FALSE);
657 495 : }
658 :
659 : static void
660 495 : gkm_manager_set_property (GObject *obj, guint prop_id, const GValue *value,
661 : GParamSpec *pspec)
662 : {
663 495 : GkmManager *self = GKM_MANAGER (obj);
664 :
665 495 : switch (prop_id) {
666 495 : case PROP_FOR_TOKEN:
667 495 : self->pv->for_token = g_value_get_boolean (value);
668 495 : break;
669 0 : default:
670 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
671 0 : break;
672 : }
673 495 : }
674 :
675 : static void
676 0 : gkm_manager_get_property (GObject *obj, guint prop_id, GValue *value,
677 : GParamSpec *pspec)
678 : {
679 0 : GkmManager *self = GKM_MANAGER (obj);
680 :
681 0 : switch (prop_id) {
682 0 : case PROP_FOR_TOKEN:
683 0 : g_value_set_boolean (value, gkm_manager_get_for_token (self));
684 0 : break;
685 0 : default:
686 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
687 0 : break;
688 : }
689 0 : }
690 :
691 :
692 : static void
693 495 : gkm_manager_dispose (GObject *obj)
694 : {
695 495 : GkmManager *self = GKM_MANAGER (obj);
696 : GList *objects, *l;
697 :
698 : /* Unregister all objects */
699 495 : objects = g_list_copy (self->pv->objects);
700 495 : for (l = objects; l; l = g_list_next (l))
701 0 : remove_object (self, GKM_OBJECT (l->data));
702 495 : g_list_free (objects);
703 :
704 495 : g_return_if_fail (self->pv->objects == NULL);
705 :
706 495 : G_OBJECT_CLASS (gkm_manager_parent_class)->dispose (obj);
707 : }
708 :
709 : static void
710 495 : gkm_manager_finalize (GObject *obj)
711 : {
712 495 : GkmManager *self = GKM_MANAGER (obj);
713 :
714 495 : g_assert (!self->pv->objects);
715 495 : g_hash_table_destroy (self->pv->index_by_attribute);
716 495 : g_hash_table_destroy (self->pv->index_by_property);
717 :
718 495 : G_OBJECT_CLASS (gkm_manager_parent_class)->finalize (obj);
719 495 : }
720 :
721 : static void
722 47 : gkm_manager_class_init (GkmManagerClass *klass)
723 : {
724 : GObjectClass *gobject_class;
725 47 : gobject_class = (GObjectClass*)klass;
726 :
727 47 : gobject_class->dispose = gkm_manager_dispose;
728 47 : gobject_class->get_property = gkm_manager_get_property;
729 47 : gobject_class->set_property = gkm_manager_set_property;
730 47 : gobject_class->finalize = gkm_manager_finalize;
731 :
732 47 : g_object_class_install_property (gobject_class, PROP_FOR_TOKEN,
733 : g_param_spec_boolean ("for-token", "For Token", "Whether this manager is for token objects or not",
734 : FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
735 :
736 47 : signals[OBJECT_ADDED] = g_signal_new ("object-added", GKM_TYPE_MANAGER,
737 : G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GkmManagerClass, object_added),
738 : NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
739 : G_TYPE_NONE, 1, GKM_TYPE_OBJECT);
740 :
741 47 : signals[OBJECT_REMOVED] = g_signal_new ("object-removed", GKM_TYPE_MANAGER,
742 : G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GkmManagerClass, object_removed),
743 : NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
744 : G_TYPE_NONE, 1, GKM_TYPE_OBJECT);
745 :
746 47 : signals[ATTRIBUTE_CHANGED] = g_signal_new ("attribute-changed", GKM_TYPE_MANAGER,
747 : G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GkmManagerClass, attribute_changed),
748 : NULL, NULL, gkm_marshal_VOID__OBJECT_ULONG,
749 : G_TYPE_NONE, 2, GKM_TYPE_OBJECT, G_TYPE_ULONG);
750 47 : }
751 :
752 : /* ------------------------------------------------------------------------
753 : * PUBLIC METHODS
754 : */
755 :
756 : gboolean
757 613 : gkm_manager_get_for_token (GkmManager *self)
758 : {
759 613 : g_return_val_if_fail (GKM_IS_MANAGER (self), FALSE);
760 613 : return self->pv->for_token;
761 : }
762 :
763 : void
764 990 : gkm_manager_add_attribute_index (GkmManager *self, CK_ATTRIBUTE_TYPE attr, gboolean unique)
765 : {
766 : Index *index;
767 : GList *l;
768 :
769 990 : g_return_if_fail (GKM_IS_MANAGER (self));
770 990 : g_return_if_fail (!g_hash_table_lookup (self->pv->index_by_attribute, &attr));
771 :
772 990 : index = index_new (unique);
773 990 : index->attribute_type = attr;
774 990 : g_hash_table_replace (self->pv->index_by_attribute, gkm_util_ulong_alloc (attr), index);
775 :
776 990 : for (l = self->pv->objects; l; l = g_list_next (l))
777 0 : index_update (index, l->data);
778 : }
779 :
780 : void
781 495 : gkm_manager_add_property_index (GkmManager *self, const gchar *property, gboolean unique)
782 : {
783 : Index *index;
784 : GList *l;
785 :
786 495 : g_return_if_fail (GKM_IS_MANAGER (self));
787 495 : g_return_if_fail (property);
788 495 : g_return_if_fail (!g_hash_table_lookup (self->pv->index_by_property, property));
789 :
790 495 : index = index_new (unique);
791 495 : index->property_name = g_strdup (property);
792 495 : g_hash_table_replace (self->pv->index_by_property, g_strdup (property), index);
793 :
794 495 : for (l = self->pv->objects; l; l = g_list_next (l))
795 0 : index_update (index, l->data);
796 : }
797 :
798 : void
799 2670 : _gkm_manager_register_object (GkmManager *self, GkmObject *object)
800 : {
801 2670 : g_return_if_fail (GKM_IS_MANAGER (self));
802 2670 : g_return_if_fail (GKM_IS_OBJECT (object));
803 2670 : g_return_if_fail (gkm_object_get_manager (object) == self);
804 :
805 2670 : add_object (self, object);
806 : }
807 :
808 : void
809 2670 : _gkm_manager_unregister_object (GkmManager *self, GkmObject *object)
810 : {
811 2670 : g_return_if_fail (GKM_IS_MANAGER (self));
812 2670 : g_return_if_fail (GKM_IS_OBJECT (object));
813 2670 : g_return_if_fail (gkm_object_get_manager (object) == self);
814 :
815 2670 : remove_object (self, object);
816 : }
817 :
818 : GkmObject*
819 4772 : gkm_manager_find_by_handle (GkmManager *self, CK_OBJECT_HANDLE handle)
820 : {
821 4772 : g_return_val_if_fail (GKM_IS_MANAGER (self), NULL);
822 4772 : g_return_val_if_fail (handle != 0, NULL);
823 :
824 4772 : return gkm_manager_find_one_by_number_property (self, "handle", handle);
825 : }
826 :
827 : GList*
828 0 : gkm_manager_find_by_number_property (GkmManager *self, const gchar *property, gulong value)
829 : {
830 : CK_ATTRIBUTE attr;
831 0 : CK_ULONG number = value;
832 :
833 0 : attr.type = (CK_ATTRIBUTE_TYPE)-1;
834 0 : attr.pValue = &number;
835 0 : attr.ulValueLen = sizeof (number);
836 :
837 0 : return find_all_for_property (self, property, &attr);
838 : }
839 :
840 : GkmObject*
841 4772 : gkm_manager_find_one_by_number_property (GkmManager *self, const gchar *property, gulong value)
842 : {
843 : CK_ATTRIBUTE attr;
844 4772 : CK_ULONG number = value;
845 :
846 4772 : attr.type = (CK_ATTRIBUTE_TYPE)-1;
847 4772 : attr.pValue = &number;
848 4772 : attr.ulValueLen = sizeof (number);
849 :
850 4772 : return find_one_for_property (self, property, &attr);
851 : }
852 :
853 : GList*
854 0 : gkm_manager_find_by_string_property (GkmManager *self, const gchar *property, const gchar *value)
855 : {
856 : CK_ATTRIBUTE attr;
857 :
858 0 : attr.type = (CK_ATTRIBUTE_TYPE)-1;
859 0 : attr.pValue = (void*)value;
860 0 : attr.ulValueLen = value ? strlen (value) : 0;
861 :
862 0 : return find_all_for_property (self, property, &attr);
863 : }
864 :
865 : GkmObject*
866 0 : gkm_manager_find_one_by_string_property (GkmManager *self, const gchar *property, const gchar *value)
867 : {
868 : CK_ATTRIBUTE attr;
869 :
870 0 : attr.type = (CK_ATTRIBUTE_TYPE)-1;
871 0 : attr.pValue = (void*)value;
872 0 : attr.ulValueLen = value ? strlen (value) : 0;
873 :
874 0 : return find_one_for_property (self, property, &attr);
875 : }
876 :
877 : GkmObject*
878 4 : gkm_manager_find_one_by_attributes (GkmManager *self, GkmSession *session,
879 : CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs)
880 : {
881 4 : Finder finder = { 0, };
882 :
883 4 : g_return_val_if_fail (GKM_IS_MANAGER (self), NULL);
884 4 : g_return_val_if_fail (attrs || !n_attrs, NULL);
885 :
886 4 : finder.accumulator = accumulate_one;
887 4 : finder.results = NULL;
888 4 : finder.manager = self;
889 4 : finder.attrs = attrs;
890 4 : finder.n_attrs = n_attrs;
891 4 : finder.session = session;
892 :
893 4 : find_for_attributes (&finder);
894 :
895 4 : return finder.results;
896 : }
897 :
898 : GList*
899 433 : gkm_manager_find_by_attributes (GkmManager *self, GkmSession *session,
900 : CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs)
901 : {
902 433 : Finder finder = { 0, };
903 :
904 433 : g_return_val_if_fail (GKM_IS_MANAGER (self), NULL);
905 433 : g_return_val_if_fail (attrs || !n_attrs, NULL);
906 :
907 433 : finder.accumulator = accumulate_list;
908 433 : finder.results = NULL;
909 433 : finder.manager = self;
910 433 : finder.attrs = attrs;
911 433 : finder.n_attrs = n_attrs;
912 433 : finder.session = session;
913 :
914 433 : find_for_attributes (&finder);
915 :
916 433 : return finder.results;
917 : }
918 :
919 : GList*
920 40 : gkm_manager_find_by_class (GkmManager *self, GkmSession *session, CK_OBJECT_CLASS klass)
921 : {
922 : CK_ATTRIBUTE attr;
923 :
924 40 : g_return_val_if_fail (GKM_IS_MANAGER (self), NULL);
925 :
926 40 : attr.type = CKA_CLASS;
927 40 : attr.ulValueLen = sizeof (klass);
928 40 : attr.pValue = &klass;
929 :
930 40 : return gkm_manager_find_by_attributes (self, session, &attr, 1);
931 : }
932 :
933 : GkmObject*
934 0 : gkm_manager_find_related (GkmManager *self, GkmSession *session,
935 : CK_OBJECT_CLASS klass, GkmObject *related_to)
936 : {
937 : CK_ATTRIBUTE attrs[2];
938 : GkmObject *object;
939 : guchar *id;
940 : gsize n_id;
941 :
942 0 : g_return_val_if_fail (GKM_IS_MANAGER (self), NULL);
943 0 : g_return_val_if_fail (GKM_IS_OBJECT (related_to), NULL);
944 :
945 0 : id = gkm_object_get_attribute_data (related_to, NULL, CKA_ID, &n_id);
946 0 : if (id == NULL)
947 0 : return NULL;
948 :
949 0 : attrs[0].type = CKA_ID;
950 0 : attrs[0].pValue = id;
951 0 : attrs[0].ulValueLen = n_id;
952 :
953 0 : attrs[1].type = CKA_CLASS;
954 0 : attrs[1].pValue = &klass;
955 0 : attrs[1].ulValueLen = sizeof (klass);
956 :
957 0 : object = gkm_manager_find_one_by_attributes (self, session, attrs, 2);
958 0 : g_free (id);
959 :
960 0 : return object;
961 : }
962 :
963 : CK_RV
964 366 : gkm_manager_find_handles (GkmManager *self, GkmSession *session,
965 : gboolean also_private, CK_ATTRIBUTE_PTR attrs,
966 : CK_ULONG n_attrs, GArray *found)
967 : {
968 366 : Finder finder = { 0, };
969 :
970 366 : g_return_val_if_fail (GKM_IS_MANAGER (self), CKR_GENERAL_ERROR);
971 366 : g_return_val_if_fail (attrs || !n_attrs, CKR_GENERAL_ERROR);
972 :
973 366 : finder.accumulator = also_private ? accumulate_handles : accumulate_public_handles;
974 366 : finder.results = found;
975 366 : finder.manager = self;
976 366 : finder.attrs = attrs;
977 366 : finder.n_attrs = n_attrs;
978 366 : finder.session = session;
979 :
980 366 : find_for_attributes (&finder);
981 :
982 366 : return CKR_OK;
983 : }
984 :
985 : /* Odd place for this function */
986 :
987 : GkmManager*
988 150 : gkm_manager_for_template (CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs, GkmSession *session)
989 : {
990 : gboolean is_token;
991 150 : if (!gkm_attributes_find_boolean (attrs, n_attrs, CKA_TOKEN, &is_token) || !is_token)
992 112 : return gkm_session_get_manager (session);
993 : else
994 38 : return gkm_module_get_manager (gkm_session_get_module (session));
995 : }
|