Coverage Report

Created: 2026-01-16 06:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}