/src/p11-kit/p11-kit/iter.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright (C) 2013,2016 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@redhat.com> |
33 | | */ |
34 | | |
35 | | #include "config.h" |
36 | | |
37 | | #include "array.h" |
38 | | #include "attrs.h" |
39 | | #include "compat.h" |
40 | | #include "debug.h" |
41 | | #include "iter.h" |
42 | | #include "pin.h" |
43 | | #include "private.h" |
44 | | |
45 | | #include <assert.h> |
46 | | #include <stdio.h> |
47 | | #include <stdlib.h> |
48 | | #include <string.h> |
49 | | |
50 | | #ifdef ENABLE_NLS |
51 | | #include <libintl.h> |
52 | 0 | #define _(x) dgettext(PACKAGE_NAME, x) |
53 | | #else |
54 | | #define _(x) (x) |
55 | | #endif |
56 | | |
57 | | typedef struct _Callback { |
58 | | p11_kit_iter_callback func; |
59 | | void *callback_data; |
60 | | p11_kit_destroyer destroyer; |
61 | | struct _Callback *next; |
62 | | } Callback; |
63 | | |
64 | | /** |
65 | | * P11KitIter: |
66 | | * |
67 | | * Used to iterate over PKCS\#11 objects, tokens, slots, and modules. |
68 | | */ |
69 | | struct p11_kit_iter { |
70 | | |
71 | | /* Iterator matching data */ |
72 | | CK_INFO match_module; |
73 | | CK_SLOT_INFO match_slot; |
74 | | CK_TOKEN_INFO match_token; |
75 | | CK_ATTRIBUTE *match_attrs; |
76 | | CK_SLOT_ID match_slot_id; |
77 | | Callback *callbacks; |
78 | | char *pin_value; |
79 | | char *pin_source; |
80 | | |
81 | | /* The input modules */ |
82 | | p11_array *modules; |
83 | | |
84 | | /* The results of C_GetSlotList */ |
85 | | CK_SLOT_ID *slots; |
86 | | CK_ULONG num_slots; |
87 | | CK_ULONG saw_slots; |
88 | | |
89 | | /* The results of C_FindObjects */ |
90 | | CK_OBJECT_HANDLE *objects; |
91 | | CK_ULONG max_objects; |
92 | | CK_ULONG num_objects; |
93 | | CK_ULONG saw_objects; |
94 | | |
95 | | /* The current iteration */ |
96 | | P11KitIterKind kind; |
97 | | CK_FUNCTION_LIST_PTR module; |
98 | | CK_SLOT_ID slot; |
99 | | CK_SESSION_HANDLE session; |
100 | | CK_OBJECT_HANDLE object; |
101 | | CK_SLOT_INFO slot_info; |
102 | | CK_TOKEN_INFO token_info; |
103 | | int move_next_session_state; |
104 | | int iter_next_state; |
105 | | |
106 | | /* And various flags */ |
107 | | unsigned int searching : 1; |
108 | | unsigned int searched : 1; |
109 | | unsigned int iterating : 1; |
110 | | unsigned int match_nothing : 1; |
111 | | unsigned int keep_session : 1; |
112 | | unsigned int preload_results : 1; |
113 | | unsigned int want_writable : 1; |
114 | | unsigned int with_modules : 1; |
115 | | unsigned int with_slots : 1; |
116 | | unsigned int with_tokens : 1; |
117 | | unsigned int with_objects : 1; |
118 | | unsigned int with_login : 1; |
119 | | unsigned int with_sessions : 1; |
120 | | }; |
121 | | |
122 | | /** |
123 | | * P11KitIterKind: |
124 | | * @P11_KIT_ITER_KIND_MODULE: The iterator is pointing to a module. |
125 | | * @P11_KIT_ITER_KIND_SLOT: The iterator is pointing to a slot. |
126 | | * @P11_KIT_ITER_KIND_TOKEN: The iterator is pointing to a token. |
127 | | * @P11_KIT_ITER_KIND_SESSION: The iterator is pointing to a token with an |
128 | | * active session. |
129 | | * @P11_KIT_ITER_KIND_OBJECT: The iterator is pointing to an object. |
130 | | * @P11_KIT_ITER_KIND_UNKNOWN: The iterator doesn't point to anything. |
131 | | * |
132 | | * The kind of the current match. |
133 | | */ |
134 | | |
135 | | /** |
136 | | * P11KitIterBehavior: |
137 | | * @P11_KIT_ITER_BUSY_SESSIONS: Allow the iterator's sessions to be |
138 | | * in a busy state when the iterator returns an object. |
139 | | * @P11_KIT_ITER_WANT_WRITABLE: Try to open read-write sessions when |
140 | | * iterating over objects. |
141 | | * @P11_KIT_ITER_WITH_MODULES: Stop at each module while iterating. |
142 | | * @P11_KIT_ITER_WITH_SLOTS: Stop at each slot while iterating. |
143 | | * @P11_KIT_ITER_WITH_TOKENS: Stop at each token while iterating. |
144 | | * @P11_KIT_ITER_WITH_SESSIONS: Stop at each token while iterating (after |
145 | | * opening a session). |
146 | | * @P11_KIT_ITER_WITHOUT_OBJECTS: Ignore objects while iterating. |
147 | | * |
148 | | * Various flags controlling the behavior of the iterator. |
149 | | */ |
150 | | |
151 | | /** |
152 | | * p11_kit_iter_new: |
153 | | * @uri: (allow-none): a PKCS\#11 URI to filter on, or %NULL |
154 | | * @behavior: various behavior flags for iterator |
155 | | * |
156 | | * Create a new PKCS\#11 iterator for iterating over objects. Only |
157 | | * objects that match the @uri will be returned by the iterator. |
158 | | * Relevant information in @uri is copied, and you need not keep |
159 | | * @uri around. |
160 | | * |
161 | | * If no @uri is specified then the iterator will iterate over all |
162 | | * objects, unless otherwise filtered. |
163 | | * |
164 | | * Returns: (transfer full): a new iterator, which should be freed |
165 | | * with p11_kit_iter_free() |
166 | | */ |
167 | | P11KitIter * |
168 | | p11_kit_iter_new (P11KitUri *uri, |
169 | | P11KitIterBehavior behavior) |
170 | 0 | { |
171 | 0 | P11KitIter *iter; |
172 | |
|
173 | 0 | iter = calloc (1, sizeof (P11KitIter)); |
174 | 0 | return_val_if_fail (iter != NULL, NULL); |
175 | | |
176 | 0 | iter->modules = p11_array_new (NULL); |
177 | 0 | if (iter->modules == NULL) { |
178 | 0 | p11_kit_iter_free (iter); |
179 | 0 | return_val_if_reached (NULL); |
180 | 0 | } |
181 | | |
182 | 0 | iter->want_writable = !!(behavior & P11_KIT_ITER_WANT_WRITABLE); |
183 | 0 | iter->preload_results = !(behavior & P11_KIT_ITER_BUSY_SESSIONS); |
184 | 0 | iter->with_modules = !!(behavior & P11_KIT_ITER_WITH_MODULES); |
185 | 0 | iter->with_slots = !!(behavior & P11_KIT_ITER_WITH_SLOTS); |
186 | 0 | iter->with_tokens = !!(behavior & P11_KIT_ITER_WITH_TOKENS); |
187 | 0 | iter->with_sessions = !!(behavior & P11_KIT_ITER_WITH_SESSIONS); |
188 | 0 | iter->with_objects = !(behavior & P11_KIT_ITER_WITHOUT_OBJECTS); |
189 | 0 | iter->with_login = !!(behavior & P11_KIT_ITER_WITH_LOGIN); |
190 | |
|
191 | 0 | p11_kit_iter_set_uri (iter, uri); |
192 | 0 | return iter; |
193 | 0 | } |
194 | | |
195 | | /** |
196 | | * p11_kit_iter_set_uri: |
197 | | * @iter: the iterator |
198 | | * @uri: (allow-none): a PKCS\#11 URI to filter on, or %NULL |
199 | | * |
200 | | * Set the PKCS\#11 uri for iterator. Only |
201 | | * objects that match the @uri will be returned by the iterator. |
202 | | * Relevant information in @uri is copied, and you need not keep |
203 | | * @uri around. |
204 | | * |
205 | | * If no @uri is specified then the iterator will iterate over all |
206 | | * objects, unless otherwise filtered. |
207 | | * |
208 | | * This function should be called at most once, and should be |
209 | | * called before iterating begins. |
210 | | * |
211 | | */ |
212 | | void |
213 | | p11_kit_iter_set_uri (P11KitIter *iter, |
214 | | P11KitUri *uri) |
215 | 0 | { |
216 | 0 | CK_ATTRIBUTE *attrs; |
217 | 0 | CK_TOKEN_INFO *tinfo; |
218 | 0 | CK_SLOT_INFO *sinfo; |
219 | 0 | CK_INFO *minfo; |
220 | 0 | CK_ULONG count; |
221 | 0 | const char *pin_value; |
222 | |
|
223 | 0 | return_if_fail (iter != NULL); |
224 | | |
225 | 0 | if (uri != NULL) { |
226 | |
|
227 | 0 | if (p11_kit_uri_any_unrecognized (uri)) { |
228 | 0 | iter->match_nothing = 1; |
229 | |
|
230 | 0 | } else { |
231 | 0 | attrs = p11_kit_uri_get_attributes (uri, &count); |
232 | 0 | iter->match_attrs = p11_attrs_buildn (NULL, attrs, count); |
233 | |
|
234 | 0 | iter->match_slot_id = p11_kit_uri_get_slot_id (uri); |
235 | |
|
236 | 0 | minfo = p11_kit_uri_get_module_info (uri); |
237 | 0 | if (minfo != NULL) |
238 | 0 | memcpy (&iter->match_module, minfo, sizeof (CK_INFO)); |
239 | |
|
240 | 0 | sinfo = p11_kit_uri_get_slot_info (uri); |
241 | 0 | if (sinfo != NULL) |
242 | 0 | memcpy (&iter->match_slot, sinfo, sizeof (CK_SLOT_INFO)); |
243 | |
|
244 | 0 | tinfo = p11_kit_uri_get_token_info (uri); |
245 | 0 | if (tinfo != NULL) |
246 | 0 | memcpy (&iter->match_token, tinfo, sizeof (CK_TOKEN_INFO)); |
247 | |
|
248 | 0 | pin_value = p11_kit_uri_get_pin_value (uri); |
249 | 0 | if (pin_value != NULL) |
250 | 0 | iter->pin_value = strdup (pin_value); |
251 | 0 | else { |
252 | | /* If the PIN is not immediately available |
253 | | * through pin-value, keep pin-source for later |
254 | | * retrieval. |
255 | | */ |
256 | 0 | const char *pin_source; |
257 | |
|
258 | 0 | pin_source = p11_kit_uri_get_pin_source (uri); |
259 | 0 | if (pin_source != NULL) |
260 | 0 | iter->pin_source = strdup (pin_source); |
261 | 0 | } |
262 | 0 | } |
263 | 0 | } else { |
264 | | /* Match any module version number and slot ID */ |
265 | 0 | memset (&iter->match_module, 0, sizeof (iter->match_module)); |
266 | 0 | iter->match_module.libraryVersion.major = (CK_BYTE)-1; |
267 | 0 | iter->match_module.libraryVersion.minor = (CK_BYTE)-1; |
268 | 0 | iter->match_slot_id = (CK_SLOT_ID)-1; |
269 | 0 | } |
270 | 0 | } |
271 | | |
272 | | /** |
273 | | * p11_kit_destroyer: |
274 | | * @data: data to destroy |
275 | | * |
276 | | * A callback called to free a resource. |
277 | | */ |
278 | | |
279 | | /** |
280 | | * p11_kit_iter_callback: |
281 | | * @iter: the iterator |
282 | | * @matches: (out): whether to match the current object |
283 | | * @data: callback data |
284 | | * |
285 | | * A callback setup with p11_kit_iter_add_callback(). This callback is |
286 | | * called for each object iterated. |
287 | | * |
288 | | * If the callback sets @matches to CK_FALSE, then this object is |
289 | | * skipped and not matched by p11_kit_iter_next(). If you return |
290 | | * anything but CKR_OK, then the iteration is stopped, and |
291 | | * p11_kit_iter_next() returns the result code. |
292 | | * |
293 | | * Returns: CKR_OK to continue iterating, CKR_CANCEL to stop, or |
294 | | * anything else to fail |
295 | | */ |
296 | | |
297 | | /** |
298 | | * p11_kit_iter_add_callback: |
299 | | * @iter: the iterator |
300 | | * @callback: a function to call for each iteration |
301 | | * @callback_data: (allow-none): data to pass to the function |
302 | | * @callback_destroy: (allow-none): used to cleanup the data |
303 | | * |
304 | | * Adds a callback to the iterator which will be called each time |
305 | | * that an object is iterated. |
306 | | * |
307 | | * These callbacks can also perform filtering. If any callback |
308 | | * indicates through it's <literal>matches</literal> argument that |
309 | | * the object should not match, then that object will not be iterated |
310 | | * as far as p11_kit_iter_next() is concerned. |
311 | | * |
312 | | * The callbacks will be called with the <literal>matches</literal> |
313 | | * set to <literal>CK_TRUE</literal> and it's up to filters to change |
314 | | * it to <literal>CK_FALSE</literal> when necessary. |
315 | | */ |
316 | | void |
317 | | p11_kit_iter_add_callback (P11KitIter *iter, |
318 | | p11_kit_iter_callback callback, |
319 | | void *callback_data, |
320 | | p11_kit_destroyer callback_destroy) |
321 | 0 | { |
322 | 0 | Callback *cb; |
323 | |
|
324 | 0 | return_if_fail (iter != NULL); |
325 | 0 | return_if_fail (callback != NULL); |
326 | | |
327 | 0 | cb = calloc (1, sizeof (Callback)); |
328 | 0 | return_if_fail (cb != NULL); |
329 | | |
330 | 0 | cb->func = callback; |
331 | 0 | cb->destroyer = callback_destroy; |
332 | 0 | cb->callback_data = callback_data; |
333 | 0 | cb->next = iter->callbacks; |
334 | 0 | iter->callbacks = cb; |
335 | 0 | } |
336 | | |
337 | | /** |
338 | | * p11_kit_iter_add_filter: |
339 | | * @iter: the iterator |
340 | | * @matching: (array length=count): the attributes that the objects should match |
341 | | * @count: the number of attributes |
342 | | * |
343 | | * Add a filter to limit the objects that the iterator iterates over. |
344 | | * |
345 | | * Only objects matching the passed in attributes will be iterated. |
346 | | * This function can be called multiple times. |
347 | | * |
348 | | * The @matching attributes are copied. |
349 | | */ |
350 | | void |
351 | | p11_kit_iter_add_filter (P11KitIter *iter, |
352 | | CK_ATTRIBUTE *matching, |
353 | | CK_ULONG count) |
354 | 0 | { |
355 | 0 | return_if_fail (iter != NULL); |
356 | 0 | return_if_fail (!iter->iterating); |
357 | | |
358 | 0 | iter->match_attrs = p11_attrs_buildn (iter->match_attrs, matching, count); |
359 | 0 | return_if_fail (iter->match_attrs != NULL); |
360 | 0 | } |
361 | | |
362 | | static void |
363 | | finish_object (P11KitIter *iter) |
364 | 0 | { |
365 | 0 | iter->object = 0; |
366 | 0 | } |
367 | | |
368 | | static void |
369 | | finish_slot (P11KitIter *iter) |
370 | 0 | { |
371 | 0 | if (iter->session && !iter->keep_session) { |
372 | 0 | assert (iter->module != NULL); |
373 | 0 | (iter->module->C_CloseSession) (iter->session); |
374 | 0 | } |
375 | |
|
376 | 0 | iter->keep_session = 0; |
377 | 0 | iter->session = 0; |
378 | 0 | iter->searched = 0; |
379 | 0 | iter->searching = 0; |
380 | 0 | iter->slot = 0; |
381 | 0 | } |
382 | | |
383 | | static void |
384 | | finish_module (P11KitIter *iter) |
385 | 0 | { |
386 | 0 | iter->num_slots = 0; |
387 | 0 | iter->saw_slots = 0; |
388 | 0 | iter->module = NULL; |
389 | 0 | } |
390 | | |
391 | | static CK_RV |
392 | | finish_iterating (P11KitIter *iter, |
393 | | CK_RV rv) |
394 | 0 | { |
395 | 0 | finish_object (iter); |
396 | 0 | finish_slot (iter); |
397 | 0 | finish_module (iter); |
398 | 0 | p11_array_clear (iter->modules); |
399 | |
|
400 | 0 | iter->iterating = 0; |
401 | 0 | iter->move_next_session_state = 0; |
402 | 0 | iter->iter_next_state = 0; |
403 | 0 | iter->kind = P11_KIT_ITER_KIND_UNKNOWN; |
404 | 0 | return rv; |
405 | 0 | } |
406 | | |
407 | | /** |
408 | | * p11_kit_iter_begin: |
409 | | * @iter: the iterator |
410 | | * @modules: (array zero-terminated=1): null-terminated list of |
411 | | * modules to iterate over |
412 | | * |
413 | | * Begin iterating PKCS\#11 objects in the given @modules. |
414 | | * |
415 | | * The @modules arguments should be a null-terminated list of |
416 | | * pointers to the modules' PKCS\#11 function pointers. |
417 | | * |
418 | | * For each module, all initialized slots will be iterated over, |
419 | | * having sessions opened for each of them in turn, and searched |
420 | | * for objects matching the search criteria. |
421 | | */ |
422 | | void |
423 | | p11_kit_iter_begin (P11KitIter *iter, |
424 | | CK_FUNCTION_LIST_PTR *modules) |
425 | 0 | { |
426 | 0 | int i; |
427 | |
|
428 | 0 | return_if_fail (modules != NULL); |
429 | | |
430 | 0 | finish_iterating (iter, CKR_OK); |
431 | | |
432 | | /* Use this module */ |
433 | 0 | for (i = 0; modules[i] != NULL; i++) { |
434 | 0 | if (!p11_array_push (iter->modules, modules[i])) |
435 | 0 | return_if_reached (); |
436 | 0 | } |
437 | | |
438 | 0 | iter->iterating = 1; |
439 | 0 | iter->searched = 1; |
440 | 0 | } |
441 | | |
442 | | /** |
443 | | * p11_kit_iter_begin_with: |
444 | | * @iter: the iterator |
445 | | * @module: the module to iterate over |
446 | | * @slot: (allow-none): the slot to iterate objects in, or zero |
447 | | * @session: (allow-none): the session to search for objects on, or zero |
448 | | * |
449 | | * Begin iterating PKCS\#11 objects in the given @module. |
450 | | * |
451 | | * If @slot is non-zero then the iteration will be limited to that |
452 | | * slot. |
453 | | * |
454 | | * If @session is non-zero then the iteration will be limited to |
455 | | * objects visible through that session, which implies that they |
456 | | * are also limited to the slot which the session was opened for. |
457 | | */ |
458 | | void |
459 | | p11_kit_iter_begin_with (P11KitIter *iter, |
460 | | CK_FUNCTION_LIST_PTR module, |
461 | | CK_SLOT_ID slot, |
462 | | CK_SESSION_HANDLE session) |
463 | 0 | { |
464 | 0 | CK_SESSION_INFO info; |
465 | 0 | CK_RV rv; |
466 | |
|
467 | 0 | finish_iterating (iter, CKR_OK); |
468 | |
|
469 | 0 | return_if_fail (module != NULL); |
470 | | |
471 | 0 | if (session != 0) { |
472 | | /* |
473 | | * A currently active session. Initialize as if we're ready |
474 | | * to search using this session. |
475 | | */ |
476 | | |
477 | | /* If we have a session, but no slot, then look it up */ |
478 | 0 | if (slot == 0) { |
479 | 0 | assert (module != NULL); |
480 | 0 | rv = (module->C_GetSessionInfo) (session, &info); |
481 | 0 | if (rv == CKR_OK) |
482 | 0 | slot = info.slotID; |
483 | 0 | } |
484 | | |
485 | | /* So initialize as if we're ready to search */ |
486 | 0 | iter->session = session; |
487 | 0 | iter->slot = slot; |
488 | 0 | iter->module = module; |
489 | 0 | iter->keep_session = 1; |
490 | |
|
491 | 0 | } else if (slot != 0) { |
492 | 0 | CK_SLOT_ID *slots; |
493 | | |
494 | | /* |
495 | | * Limit to this slot. Initialize as if we're ready to use the |
496 | | * slot from the slots list. |
497 | | */ |
498 | |
|
499 | 0 | iter->module = module; |
500 | 0 | slots = realloc (iter->slots, sizeof (CK_SLOT_ID)); |
501 | 0 | return_if_fail (slots != NULL); |
502 | 0 | iter->slots = slots; |
503 | 0 | iter->slots[0] = slot; |
504 | 0 | iter->num_slots = 1; |
505 | 0 | iter->searched = 1; |
506 | |
|
507 | 0 | } else { |
508 | | |
509 | | /* |
510 | | * Limit to this module. Initialize as if we're ready to use |
511 | | * the module from the modules array. |
512 | | */ |
513 | |
|
514 | 0 | assert (module != NULL); |
515 | 0 | p11_array_push (iter->modules, module); |
516 | 0 | iter->session = 0; |
517 | 0 | iter->slot = 0; |
518 | 0 | iter->searched = 1; |
519 | 0 | } |
520 | | |
521 | 0 | iter->iterating = 1; |
522 | 0 | } |
523 | | |
524 | | static CK_RV |
525 | | call_all_filters (P11KitIter *iter, |
526 | | CK_BBOOL *matches) |
527 | 0 | { |
528 | 0 | Callback *cb; |
529 | 0 | CK_RV rv; |
530 | |
|
531 | 0 | *matches = CK_TRUE; |
532 | |
|
533 | 0 | for (cb = iter->callbacks; cb != NULL; cb = cb->next) { |
534 | 0 | rv = (cb->func) (iter, matches, cb->callback_data); |
535 | 0 | if (rv != CKR_OK || !*matches) |
536 | 0 | return rv; |
537 | 0 | } |
538 | | |
539 | 0 | return CKR_OK; |
540 | 0 | } |
541 | | |
542 | 0 | #define COROUTINE_BEGIN(name) switch (iter->name ## _state) { case 0: |
543 | 0 | #define COROUTINE_RETURN(name,i,x) do { iter->name ## _state = i; return x; case i:; } while (0) |
544 | 0 | #define COROUTINE_END(name) } |
545 | | |
546 | | static P11KitPin * |
547 | | request_pin (P11KitIter *iter) |
548 | 0 | { |
549 | 0 | P11KitPin *pin; |
550 | 0 | char *pin_description; |
551 | |
|
552 | 0 | if (iter->pin_value) { |
553 | 0 | return p11_kit_pin_new_for_string (iter->pin_value); |
554 | 0 | } |
555 | | |
556 | 0 | if (asprintf (&pin_description, |
557 | 0 | _("PIN for %.*s"), |
558 | 0 | (int) p11_kit_space_strlen (iter->token_info.label, |
559 | 0 | sizeof (iter->token_info.label)), |
560 | 0 | iter->token_info.label) < 0) { |
561 | 0 | return NULL; |
562 | 0 | } |
563 | | |
564 | 0 | pin = p11_kit_pin_request (iter->pin_source, |
565 | 0 | NULL, |
566 | 0 | pin_description, |
567 | 0 | P11_KIT_PIN_FLAGS_USER_LOGIN); |
568 | 0 | free (pin_description); |
569 | 0 | return pin; |
570 | 0 | } |
571 | | |
572 | | static CK_RV |
573 | | move_next_session (P11KitIter *iter) |
574 | 0 | { |
575 | 0 | CK_ULONG session_flags; |
576 | 0 | CK_ULONG num_slots; |
577 | 0 | CK_INFO minfo; |
578 | 0 | CK_RV rv; |
579 | |
|
580 | 0 | COROUTINE_BEGIN (move_next_session); |
581 | |
|
582 | 0 | finish_slot (iter); |
583 | | |
584 | | /* If we have no more slots, then move to next module */ |
585 | 0 | while (iter->saw_slots >= iter->num_slots) { |
586 | 0 | finish_module (iter); |
587 | | |
588 | | /* Iter is finished */ |
589 | 0 | if (iter->modules->num == 0) |
590 | 0 | return finish_iterating (iter, CKR_CANCEL); |
591 | | |
592 | 0 | iter->module = iter->modules->elem[0]; |
593 | 0 | p11_array_remove (iter->modules, 0); |
594 | | |
595 | | /* Skip module if it doesn't match uri */ |
596 | 0 | assert (iter->module != NULL); |
597 | 0 | rv = (iter->module->C_GetInfo) (&minfo); |
598 | 0 | if (rv != CKR_OK || !p11_match_uri_module_info (&iter->match_module, &minfo)) |
599 | 0 | continue; |
600 | | |
601 | 0 | if (iter->with_modules) { |
602 | 0 | iter->kind = P11_KIT_ITER_KIND_MODULE; |
603 | 0 | COROUTINE_RETURN (move_next_session, 1, CKR_OK); |
604 | 0 | } |
605 | | |
606 | 0 | if (iter->with_slots || iter->with_tokens || iter->with_sessions || iter->with_objects) { |
607 | 0 | CK_SLOT_ID *slots; |
608 | |
|
609 | 0 | rv = (iter->module->C_GetSlotList) (CK_TRUE, NULL, &num_slots); |
610 | 0 | if (rv != CKR_OK) |
611 | 0 | return finish_iterating (iter, rv); |
612 | | |
613 | 0 | slots = reallocarray (iter->slots, num_slots + 1, sizeof (CK_SLOT_ID)); |
614 | 0 | return_val_if_fail (slots != NULL, CKR_HOST_MEMORY); |
615 | 0 | iter->slots = slots; |
616 | |
|
617 | 0 | rv = (iter->module->C_GetSlotList) (CK_TRUE, iter->slots, &num_slots); |
618 | 0 | if (rv != CKR_OK) |
619 | 0 | return finish_iterating (iter, rv); |
620 | | |
621 | 0 | iter->num_slots = num_slots; |
622 | 0 | assert (iter->saw_slots == 0); |
623 | 0 | } |
624 | 0 | } |
625 | | |
626 | | /* Move to the next slot, and open a session on it */ |
627 | 0 | while ((iter->with_slots || iter->with_tokens || iter->with_sessions || |
628 | 0 | iter->with_objects) && |
629 | 0 | iter->saw_slots < iter->num_slots) { |
630 | 0 | iter->slot = iter->slots[iter->saw_slots++]; |
631 | |
|
632 | 0 | assert (iter->module != NULL); |
633 | 0 | if (iter->match_slot_id != (CK_SLOT_ID)-1 && iter->slot != iter->match_slot_id) |
634 | 0 | continue; |
635 | 0 | rv = (iter->module->C_GetSlotInfo) (iter->slot, &iter->slot_info); |
636 | 0 | if (rv != CKR_OK || !p11_match_uri_slot_info (&iter->match_slot, &iter->slot_info)) |
637 | 0 | continue; |
638 | 0 | if (iter->with_slots) { |
639 | 0 | iter->kind = P11_KIT_ITER_KIND_SLOT; |
640 | 0 | COROUTINE_RETURN (move_next_session, 2, CKR_OK); |
641 | 0 | } |
642 | 0 | rv = (iter->module->C_GetTokenInfo) (iter->slot, &iter->token_info); |
643 | 0 | if (rv != CKR_OK || !p11_match_uri_token_info (&iter->match_token, &iter->token_info)) |
644 | 0 | continue; |
645 | | |
646 | 0 | if (iter->with_tokens) { |
647 | 0 | iter->kind = P11_KIT_ITER_KIND_TOKEN; |
648 | 0 | COROUTINE_RETURN (move_next_session, 3, CKR_OK); |
649 | 0 | } |
650 | | |
651 | 0 | session_flags = CKF_SERIAL_SESSION; |
652 | | |
653 | | /* Skip if the read/write on a read-only token */ |
654 | 0 | if (iter->want_writable && (iter->token_info.flags & CKF_WRITE_PROTECTED) == 0) |
655 | 0 | session_flags |= CKF_RW_SESSION; |
656 | |
|
657 | 0 | rv = (iter->module->C_OpenSession) (iter->slot, session_flags, |
658 | 0 | NULL, NULL, &iter->session); |
659 | 0 | if (rv != CKR_OK) |
660 | 0 | return finish_iterating (iter, rv); |
661 | | |
662 | 0 | if (iter->session != 0) { |
663 | 0 | if (iter->with_login && |
664 | 0 | (iter->pin_value != NULL || iter->pin_source != NULL)) { |
665 | 0 | P11KitPin *pin; |
666 | |
|
667 | 0 | pin = request_pin (iter); |
668 | 0 | if (!pin) |
669 | 0 | continue; |
670 | | |
671 | 0 | rv = (iter->module->C_Login) (iter->session, CKU_USER, |
672 | 0 | (unsigned char *) p11_kit_pin_get_value (pin, NULL), |
673 | 0 | p11_kit_pin_get_length (pin)); |
674 | 0 | p11_kit_pin_unref (pin); |
675 | 0 | if (rv != CKR_OK) |
676 | 0 | return finish_iterating (iter, rv); |
677 | 0 | } |
678 | | |
679 | 0 | if (iter->with_sessions) { |
680 | 0 | iter->kind = P11_KIT_ITER_KIND_SESSION; |
681 | 0 | COROUTINE_RETURN (move_next_session, 4, CKR_OK); |
682 | 0 | } |
683 | 0 | } |
684 | | |
685 | 0 | iter->move_next_session_state = 0; |
686 | 0 | iter->kind = P11_KIT_ITER_KIND_UNKNOWN; |
687 | 0 | return CKR_OK; |
688 | 0 | } |
689 | |
|
690 | 0 | COROUTINE_END (move_next_session); |
691 | | |
692 | | /* Otherwise try again */ |
693 | 0 | iter->move_next_session_state = 0; |
694 | 0 | return move_next_session (iter); |
695 | 0 | } |
696 | | |
697 | | /** |
698 | | * p11_kit_iter_next: |
699 | | * @iter: the iterator |
700 | | * |
701 | | * Iterate to the next matching object. |
702 | | * |
703 | | * To access the object, session and so on, use the p11_kit_iter_get_object(), |
704 | | * p11_kit_iter_get_session(), and p11_kit_iter_get_module() functions. |
705 | | * |
706 | | * This call must only be called after either p11_kit_iter_begin() |
707 | | * or p11_kit_iter_begin_with() have been called. |
708 | | * |
709 | | * Objects which are skipped by callbacks will not be returned here |
710 | | * as matching objects. |
711 | | * |
712 | | * Returns: CKR_OK if an object matched, CKR_CANCEL if no more objects, or another error |
713 | | */ |
714 | | CK_RV |
715 | | p11_kit_iter_next (P11KitIter *iter) |
716 | 0 | { |
717 | 0 | CK_ULONG batch; |
718 | 0 | CK_ULONG count; |
719 | 0 | CK_BBOOL matches; |
720 | 0 | CK_RV rv; |
721 | |
|
722 | 0 | return_val_if_fail (iter->iterating, CKR_OPERATION_NOT_INITIALIZED); |
723 | | |
724 | 0 | COROUTINE_BEGIN (iter_next); |
725 | |
|
726 | 0 | iter->object = 0; |
727 | |
|
728 | 0 | if (iter->match_nothing) |
729 | 0 | return finish_iterating (iter, CKR_CANCEL); |
730 | | |
731 | 0 | if (!(iter->with_modules || iter->with_slots || iter->with_tokens || |
732 | 0 | iter->with_sessions || iter->with_objects)) |
733 | 0 | return finish_iterating (iter, CKR_CANCEL); |
734 | | |
735 | | /* |
736 | | * If we have outstanding objects, then iterate one through those |
737 | | * Note that we pass each object through the filters, and only |
738 | | * assume it's iterated if it matches |
739 | | */ |
740 | 0 | while (iter->with_objects && iter->saw_objects < iter->num_objects) { |
741 | 0 | iter->object = iter->objects[iter->saw_objects++]; |
742 | |
|
743 | 0 | rv = call_all_filters (iter, &matches); |
744 | 0 | if (rv != CKR_OK) |
745 | 0 | return finish_iterating (iter, rv); |
746 | | |
747 | 0 | if (matches && iter->with_objects) { |
748 | 0 | iter->kind = P11_KIT_ITER_KIND_OBJECT; |
749 | 0 | COROUTINE_RETURN (iter_next, 1, CKR_OK); |
750 | 0 | } |
751 | 0 | } |
752 | | |
753 | | /* Move to next session, if we have finished searching |
754 | | * objects, or we are looking for modules/slots/tokens */ |
755 | 0 | if ((iter->with_objects && iter->searched) || |
756 | 0 | (!iter->with_objects && |
757 | 0 | (iter->with_modules || iter->with_slots || iter->with_tokens || |
758 | 0 | iter->with_sessions))) { |
759 | | /* Use iter->kind as the sentinel to detect the case where |
760 | | * any match (except object) is successful in |
761 | | * move_next_session() */ |
762 | 0 | do { |
763 | 0 | iter->kind = P11_KIT_ITER_KIND_UNKNOWN; |
764 | 0 | rv = move_next_session (iter); |
765 | 0 | if (rv != CKR_OK) |
766 | 0 | return finish_iterating (iter, rv); |
767 | 0 | if (iter->kind != P11_KIT_ITER_KIND_UNKNOWN) |
768 | 0 | COROUTINE_RETURN (iter_next, 2, CKR_OK); |
769 | 0 | } while (iter->move_next_session_state > 0); |
770 | 0 | } |
771 | | |
772 | | /* Ready to start searching */ |
773 | 0 | if (iter->with_objects && !iter->searching && !iter->searched) { |
774 | 0 | count = p11_attrs_count (iter->match_attrs); |
775 | 0 | rv = (iter->module->C_FindObjectsInit) (iter->session, iter->match_attrs, count); |
776 | 0 | if (rv != CKR_OK) |
777 | 0 | return finish_iterating (iter, rv); |
778 | 0 | iter->searching = 1; |
779 | 0 | iter->searched = 0; |
780 | 0 | } |
781 | | |
782 | | /* If we have searched on this session then try to continue */ |
783 | 0 | if (iter->with_objects && iter->searching) { |
784 | 0 | assert (iter->module != NULL); |
785 | 0 | assert (iter->session != 0); |
786 | 0 | iter->num_objects = 0; |
787 | 0 | iter->saw_objects = 0; |
788 | |
|
789 | 0 | for (;;) { |
790 | 0 | if (iter->max_objects - iter->num_objects == 0) { |
791 | 0 | CK_OBJECT_HANDLE *objects; |
792 | |
|
793 | 0 | iter->max_objects = iter->max_objects ? iter->max_objects * 2 : 64; |
794 | 0 | objects = reallocarray (iter->objects, iter->max_objects, sizeof (CK_ULONG)); |
795 | 0 | return_val_if_fail (objects != NULL, CKR_HOST_MEMORY); |
796 | 0 | iter->objects = objects; |
797 | 0 | } |
798 | | |
799 | 0 | batch = iter->max_objects - iter->num_objects; |
800 | 0 | rv = (iter->module->C_FindObjects) (iter->session, |
801 | 0 | iter->objects + iter->num_objects, |
802 | 0 | batch, &count); |
803 | 0 | if (rv != CKR_OK) |
804 | 0 | return finish_iterating (iter, rv); |
805 | | |
806 | 0 | iter->num_objects += count; |
807 | | |
808 | | /* |
809 | | * Done searching on this session, although there are still |
810 | | * objects outstanding, which will be returned on next |
811 | | * iterations. |
812 | | */ |
813 | 0 | if (batch != count) { |
814 | 0 | iter->searching = 0; |
815 | 0 | iter->searched = 1; |
816 | 0 | (iter->module->C_FindObjectsFinal) (iter->session); |
817 | 0 | break; |
818 | 0 | } |
819 | | |
820 | 0 | if (!iter->preload_results) |
821 | 0 | break; |
822 | 0 | } |
823 | 0 | } |
824 | |
|
825 | 0 | COROUTINE_END (iter_next); |
826 | | |
827 | | /* Try again */ |
828 | 0 | iter->iter_next_state = 0; |
829 | 0 | iter->move_next_session_state = 0; |
830 | 0 | iter->kind = P11_KIT_ITER_KIND_UNKNOWN; |
831 | 0 | return p11_kit_iter_next (iter); |
832 | 0 | } |
833 | | |
834 | | /** |
835 | | * p11_kit_iter_get_kind: |
836 | | * @iter: the iterator |
837 | | * |
838 | | * Get the kind of the current match (a module, slot, token, or an |
839 | | * object). |
840 | | * |
841 | | * This can only be called after p11_kit_iter_next() succeeds. |
842 | | * |
843 | | * Returns: a #P11KitIterKind value |
844 | | */ |
845 | | P11KitIterKind |
846 | | p11_kit_iter_get_kind (P11KitIter *iter) |
847 | 0 | { |
848 | 0 | return_val_if_fail (iter != NULL, P11_KIT_ITER_KIND_UNKNOWN); |
849 | 0 | return_val_if_fail (iter->iterating, P11_KIT_ITER_KIND_UNKNOWN); |
850 | 0 | return iter->kind; |
851 | 0 | } |
852 | | |
853 | | /** |
854 | | * p11_kit_iter_get_module: |
855 | | * @iter: the iterator |
856 | | * |
857 | | * Get the module function pointers for the current matching object. |
858 | | * |
859 | | * This can only be called after p11_kit_iter_next() succeeds. |
860 | | * |
861 | | * Returns: the module which the current matching object is in |
862 | | */ |
863 | | CK_FUNCTION_LIST_PTR |
864 | | p11_kit_iter_get_module (P11KitIter *iter) |
865 | 0 | { |
866 | 0 | return_val_if_fail (iter != NULL, NULL); |
867 | 0 | return_val_if_fail (iter->iterating, 0); |
868 | 0 | return iter->module; |
869 | 0 | } |
870 | | |
871 | | /** |
872 | | * p11_kit_iter_get_slot: |
873 | | * @iter: the iterator |
874 | | * |
875 | | * Get the slot which the current matching object is on. |
876 | | * |
877 | | * This can only be called after p11_kit_iter_next() succeeds. |
878 | | * |
879 | | * Returns: the slot of the current matching object |
880 | | */ |
881 | | CK_SLOT_ID |
882 | | p11_kit_iter_get_slot (P11KitIter *iter) |
883 | 0 | { |
884 | 0 | return_val_if_fail (iter != NULL, 0); |
885 | 0 | return_val_if_fail (iter->iterating, 0); |
886 | 0 | return iter->slot; |
887 | 0 | } |
888 | | |
889 | | /** |
890 | | * p11_kit_iter_get_slot_info: |
891 | | * @iter: the iterator |
892 | | * |
893 | | * Get the slot info for the slot which the current matching object is on. |
894 | | * |
895 | | * This can only be called after p11_kit_iter_next() succeeds. |
896 | | * |
897 | | * Returns: the slot of the current matching object. |
898 | | */ |
899 | | CK_SLOT_INFO * |
900 | | p11_kit_iter_get_slot_info (P11KitIter *iter) |
901 | 0 | { |
902 | 0 | return_val_if_fail (iter != NULL, NULL); |
903 | 0 | return &iter->slot_info; |
904 | 0 | } |
905 | | |
906 | | /** |
907 | | * p11_kit_iter_get_token: |
908 | | * @iter: the iterator |
909 | | * |
910 | | * Get the token info for the token which the current matching object is on. |
911 | | * |
912 | | * This can only be called after p11_kit_iter_next() succeeds. |
913 | | * |
914 | | * Returns: the slot of the current matching object. |
915 | | */ |
916 | | CK_TOKEN_INFO * |
917 | | p11_kit_iter_get_token (P11KitIter *iter) |
918 | 0 | { |
919 | 0 | return_val_if_fail (iter != NULL, NULL); |
920 | 0 | return &iter->token_info; |
921 | 0 | } |
922 | | |
923 | | /** |
924 | | * p11_kit_iter_get_session: |
925 | | * @iter: the iterator |
926 | | * |
927 | | * Get the session which the current matching object is accessible |
928 | | * through. |
929 | | * |
930 | | * This can only be called after p11_kit_iter_next() succeeds. |
931 | | * |
932 | | * The session may be closed after the next p11_kit_iter_next() call |
933 | | * unless p11_kit_iter_keep_session() is called. |
934 | | * |
935 | | * Returns: the session used to find the current matching object |
936 | | */ |
937 | | CK_SESSION_HANDLE |
938 | | p11_kit_iter_get_session (P11KitIter *iter) |
939 | 0 | { |
940 | 0 | return_val_if_fail (iter != NULL, 0); |
941 | 0 | return_val_if_fail (iter->iterating, 0); |
942 | 0 | return iter->session; |
943 | 0 | } |
944 | | |
945 | | /** |
946 | | * p11_kit_iter_get_object: |
947 | | * @iter: the iterator |
948 | | * |
949 | | * Get the current matching object. |
950 | | * |
951 | | * This can only be called after p11_kit_iter_next() succeeds. |
952 | | * |
953 | | * Returns: the current matching object |
954 | | */ |
955 | | CK_OBJECT_HANDLE |
956 | | p11_kit_iter_get_object (P11KitIter *iter) |
957 | 0 | { |
958 | 0 | return_val_if_fail (iter != NULL, 0); |
959 | 0 | return iter->object; |
960 | 0 | } |
961 | | |
962 | | /** |
963 | | * p11_kit_iter_destroy_object: |
964 | | * @iter: the iterator |
965 | | * |
966 | | * Destroy the current matching object. |
967 | | * |
968 | | * This can only be called after p11_kit_iter_next() succeeds. |
969 | | * |
970 | | * Returns: CKR_OK or a failure code |
971 | | */ |
972 | | CK_RV |
973 | | p11_kit_iter_destroy_object (P11KitIter *iter) |
974 | 0 | { |
975 | 0 | return_val_if_fail (iter != NULL, CKR_GENERAL_ERROR); |
976 | 0 | return_val_if_fail (iter->iterating, CKR_GENERAL_ERROR); |
977 | 0 | return (iter->module->C_DestroyObject) (iter->session, iter->object); |
978 | 0 | } |
979 | | |
980 | | /** |
981 | | * p11_kit_iter_get_attributes: |
982 | | * @iter: the iterator |
983 | | * @templ: (array length=count) (inout): the attributes to get |
984 | | * @count: the number of attributes |
985 | | * |
986 | | * Get attributes for the current matching object. |
987 | | * |
988 | | * This calls <literal>C_GetAttributeValue</literal> for the object |
989 | | * currently iterated to. Return value and attribute memory behavior |
990 | | * is identical to the PKCS\#11 <literal>C_GetAttributeValue</literal> |
991 | | * function. |
992 | | * |
993 | | * You might choose to use p11_kit_iter_load_attributes() for a more |
994 | | * helpful variant. |
995 | | * |
996 | | * This can only be called after p11_kit_iter_next() succeeds. |
997 | | * |
998 | | * Returns: The result from <literal>C_GetAttributeValue</literal>. |
999 | | */ |
1000 | | CK_RV |
1001 | | p11_kit_iter_get_attributes (P11KitIter *iter, |
1002 | | CK_ATTRIBUTE *templ, |
1003 | | CK_ULONG count) |
1004 | 0 | { |
1005 | 0 | return_val_if_fail (iter != NULL, CKR_GENERAL_ERROR); |
1006 | 0 | return_val_if_fail (iter->iterating, CKR_GENERAL_ERROR); |
1007 | 0 | return_val_if_fail (iter->module != NULL, CKR_GENERAL_ERROR); |
1008 | 0 | return_val_if_fail (iter->session != 0, CKR_GENERAL_ERROR); |
1009 | 0 | return_val_if_fail (iter->object != 0, CKR_GENERAL_ERROR); |
1010 | | |
1011 | 0 | return (iter->module->C_GetAttributeValue) (iter->session, iter->object, |
1012 | 0 | templ, count); |
1013 | 0 | } |
1014 | | |
1015 | | static CK_RV |
1016 | | prepare_recursive_attribute (P11KitIter *iter, |
1017 | | CK_ATTRIBUTE *attr, |
1018 | | CK_ATTRIBUTE *templ, |
1019 | | CK_ULONG templ_len) |
1020 | 0 | { |
1021 | 0 | CK_RV rv; |
1022 | 0 | CK_ULONG i; |
1023 | |
|
1024 | 0 | return_val_if_fail (iter != NULL, CKR_GENERAL_ERROR); |
1025 | 0 | return_val_if_fail (attr != NULL, CKR_GENERAL_ERROR); |
1026 | 0 | return_val_if_fail (templ != NULL, CKR_GENERAL_ERROR); |
1027 | 0 | return_val_if_fail (templ_len != 0, CKR_GENERAL_ERROR); |
1028 | 0 | return_val_if_fail (IS_ATTRIBUTE_ARRAY (attr), CKR_GENERAL_ERROR); |
1029 | | |
1030 | 0 | memset (templ, 0, templ_len); |
1031 | 0 | rv = (iter->module->C_GetAttributeValue) (iter->session, iter->object, attr, 1); |
1032 | |
|
1033 | 0 | switch (rv) { |
1034 | 0 | case CKR_OK: |
1035 | 0 | case CKR_ATTRIBUTE_TYPE_INVALID: |
1036 | 0 | case CKR_ATTRIBUTE_SENSITIVE: |
1037 | 0 | break; |
1038 | 0 | default: |
1039 | 0 | return_val_if_fail (rv != CKR_BUFFER_TOO_SMALL, rv); |
1040 | 0 | return rv; |
1041 | 0 | } |
1042 | | |
1043 | 0 | for (i = 0; i < templ_len / sizeof (CK_ATTRIBUTE); ++i) { |
1044 | 0 | return_val_if_fail (templ[i].type != CKA_INVALID, CKR_GENERAL_ERROR); |
1045 | 0 | return_val_if_fail (templ[i].ulValueLen != 0, CKR_GENERAL_ERROR); |
1046 | 0 | return_val_if_fail (templ[i].ulValueLen != (CK_ULONG)-1, CKR_GENERAL_ERROR); |
1047 | | |
1048 | 0 | templ[i].pValue = malloc (templ[i].ulValueLen); |
1049 | 0 | return_val_if_fail (templ[i].pValue != NULL, CKR_HOST_MEMORY); |
1050 | | |
1051 | 0 | if (IS_ATTRIBUTE_ARRAY (templ + i)) { |
1052 | 0 | rv = prepare_recursive_attribute (iter, attr, templ[i].pValue, |
1053 | 0 | templ[i].ulValueLen); |
1054 | 0 | return_val_if_fail (rv == CKR_OK, rv); |
1055 | 0 | } |
1056 | 0 | } |
1057 | | |
1058 | 0 | return CKR_OK; |
1059 | 0 | } |
1060 | | |
1061 | | /** |
1062 | | * p11_kit_iter_load_attributes: |
1063 | | * @iter: the iterator |
1064 | | * @templ: (array length=count) (inout): the attributes to load |
1065 | | * @count: the number of attributes |
1066 | | * |
1067 | | * Retrieve attributes for the current matching object. |
1068 | | * |
1069 | | * Each attribute in the array will be filled in with the value |
1070 | | * of that attribute retrieved from the object. After use the |
1071 | | * attribute value memory pointed to by the <literal>pValue</literal> |
1072 | | * of each attribute should be freed with the <literal>free<!-- -->()</literal> |
1073 | | * function. |
1074 | | * |
1075 | | * If the <literal>pValue</literal> of an attribute is not %NULL passed |
1076 | | * to this function, then it will be passed to |
1077 | | * <literal>realloc<!-- -->()</literal> to allocate the correct amount |
1078 | | * of space for the attribute value. |
1079 | | * |
1080 | | * If any attribute is not present on the object, or is sensitive and |
1081 | | * cannot be retrieved, then the <literal>pValue</literal> will be NULL. |
1082 | | * If <literal>pValue</literal> was not %NULL when passed to this function |
1083 | | * then it will be freed with <literal>free<!-- -->()</literal>. In these |
1084 | | * cases <literal>CKR_OK</literal> is returned. |
1085 | | * |
1086 | | * This can only be called after p11_kit_iter_next() succeeds. |
1087 | | * |
1088 | | * Returns: CKR_OK or a failure code |
1089 | | */ |
1090 | | CK_RV |
1091 | | p11_kit_iter_load_attributes (P11KitIter *iter, |
1092 | | CK_ATTRIBUTE *templ, |
1093 | | CK_ULONG count) |
1094 | 0 | { |
1095 | 0 | CK_ATTRIBUTE *original = NULL; |
1096 | 0 | CK_ULONG i; |
1097 | 0 | CK_RV rv; |
1098 | |
|
1099 | 0 | return_val_if_fail (iter != NULL, CKR_GENERAL_ERROR); |
1100 | 0 | return_val_if_fail (iter->iterating, CKR_GENERAL_ERROR); |
1101 | 0 | return_val_if_fail (iter->module != NULL, CKR_GENERAL_ERROR); |
1102 | 0 | return_val_if_fail (iter->session != 0, CKR_GENERAL_ERROR); |
1103 | 0 | return_val_if_fail (iter->object != 0, CKR_GENERAL_ERROR); |
1104 | | |
1105 | 0 | if (count == 0) |
1106 | 0 | return CKR_OK; |
1107 | | |
1108 | 0 | original = memdup (templ, count * sizeof (CK_ATTRIBUTE)); |
1109 | 0 | return_val_if_fail (original != NULL, CKR_HOST_MEMORY); |
1110 | | |
1111 | 0 | for (i = 0; i < count; i++) |
1112 | 0 | templ[i].pValue = NULL; |
1113 | |
|
1114 | 0 | rv = (iter->module->C_GetAttributeValue) (iter->session, iter->object, templ, count); |
1115 | |
|
1116 | 0 | switch (rv) { |
1117 | 0 | case CKR_OK: |
1118 | 0 | case CKR_ATTRIBUTE_TYPE_INVALID: |
1119 | 0 | case CKR_ATTRIBUTE_SENSITIVE: |
1120 | 0 | case CKR_BUFFER_TOO_SMALL: |
1121 | 0 | break; |
1122 | 0 | default: |
1123 | 0 | free (original); |
1124 | 0 | return rv; |
1125 | 0 | } |
1126 | | |
1127 | 0 | for (i = 0; i < count; i++) { |
1128 | 0 | if (templ[i].ulValueLen == (CK_ULONG)-1 || |
1129 | 0 | templ[i].ulValueLen == 0) { |
1130 | 0 | p11_attr_clear (original + i); |
1131 | |
|
1132 | 0 | } else if (original[i].pValue != NULL && |
1133 | 0 | templ[i].ulValueLen == original[i].ulValueLen) { |
1134 | 0 | templ[i].pValue = original[i].pValue; |
1135 | |
|
1136 | 0 | } else { |
1137 | 0 | templ[i].pValue = realloc (original[i].pValue, templ[i].ulValueLen); |
1138 | 0 | return_val_if_fail (templ[i].pValue != NULL, CKR_HOST_MEMORY); |
1139 | | |
1140 | 0 | if (IS_ATTRIBUTE_ARRAY (templ + i)) { |
1141 | 0 | rv = prepare_recursive_attribute (iter, templ + i, |
1142 | 0 | templ[i].pValue, |
1143 | 0 | templ[i].ulValueLen); |
1144 | 0 | if (rv != CKR_OK) { |
1145 | 0 | free (original); |
1146 | 0 | return rv; |
1147 | 0 | } |
1148 | 0 | } |
1149 | 0 | } |
1150 | 0 | } |
1151 | | |
1152 | 0 | free (original); |
1153 | |
|
1154 | 0 | rv = (iter->module->C_GetAttributeValue) (iter->session, iter->object, templ, count); |
1155 | |
|
1156 | 0 | switch (rv) { |
1157 | 0 | case CKR_OK: |
1158 | 0 | case CKR_ATTRIBUTE_TYPE_INVALID: |
1159 | 0 | case CKR_ATTRIBUTE_SENSITIVE: |
1160 | 0 | rv = CKR_OK; |
1161 | 0 | break; |
1162 | 0 | default: |
1163 | 0 | return_val_if_fail (rv != CKR_BUFFER_TOO_SMALL, rv); |
1164 | 0 | return rv; |
1165 | 0 | } |
1166 | | |
1167 | 0 | for (i = 0; i < count; i++) { |
1168 | 0 | if (templ[i].ulValueLen == (CK_ULONG)-1 || |
1169 | 0 | templ[i].ulValueLen == 0) { |
1170 | 0 | free (templ[i].pValue); |
1171 | 0 | templ[i].pValue = NULL; |
1172 | 0 | } |
1173 | 0 | } |
1174 | |
|
1175 | 0 | return rv; |
1176 | 0 | } |
1177 | | |
1178 | | /** |
1179 | | * p11_kit_iter_keep_session: |
1180 | | * @iter: the iterator |
1181 | | * |
1182 | | * After calling this function the session open for iterating |
1183 | | * the current object will not be automatically closed by |
1184 | | * the iterator after later calls to p11_kit_iter_next() or |
1185 | | * p11_kit_iter_free(). |
1186 | | * |
1187 | | * It is the callers responsibility to close this session, |
1188 | | * after the iterator has been freed. The session may still be |
1189 | | * used by the iterator if further iterations are performed. |
1190 | | * |
1191 | | * This can only be called after p11_kit_iter_next() succeeds. |
1192 | | * |
1193 | | * Returns: the current session |
1194 | | */ |
1195 | | CK_SESSION_HANDLE |
1196 | | p11_kit_iter_keep_session (P11KitIter *iter) |
1197 | 0 | { |
1198 | 0 | return_val_if_fail (iter != NULL, 0); |
1199 | 0 | return_val_if_fail (iter->iterating, 0); |
1200 | 0 | return_val_if_fail (iter->session != 0, 0); |
1201 | | |
1202 | 0 | iter->keep_session = 1; |
1203 | 0 | return iter->session; |
1204 | 0 | } |
1205 | | |
1206 | | /** |
1207 | | * p11_kit_iter_free: |
1208 | | * @iter: the iterator |
1209 | | * |
1210 | | * Frees the iterator and all resources, such as sessions |
1211 | | * or callbacks held by the iterator. |
1212 | | */ |
1213 | | void |
1214 | | p11_kit_iter_free (P11KitIter *iter) |
1215 | 0 | { |
1216 | 0 | Callback *cb, *next; |
1217 | |
|
1218 | 0 | if (iter == NULL) |
1219 | 0 | return; |
1220 | | |
1221 | 0 | finish_iterating (iter, CKR_OK); |
1222 | 0 | p11_array_free (iter->modules); |
1223 | 0 | p11_attrs_free (iter->match_attrs); |
1224 | 0 | free (iter->objects); |
1225 | 0 | free (iter->slots); |
1226 | 0 | free (iter->pin_value); |
1227 | 0 | free (iter->pin_source); |
1228 | |
|
1229 | 0 | for (cb = iter->callbacks; cb != NULL; cb = next) { |
1230 | 0 | next = cb->next; |
1231 | 0 | if (cb->destroyer) |
1232 | 0 | (cb->destroyer) (cb->callback_data); |
1233 | 0 | free (cb); |
1234 | 0 | } |
1235 | |
|
1236 | 0 | free (iter); |
1237 | 0 | } |