struct _Callback *next;
} Callback;
-#define MAX_OBJECTS 64
-
/**
* P11KitIter:
*
CK_ULONG saw_slots;
/* The results of C_FindObjects */
- CK_OBJECT_HANDLE objects[MAX_OBJECTS];
+ CK_OBJECT_HANDLE *objects;
+ CK_ULONG max_objects;
CK_ULONG num_objects;
CK_ULONG saw_objects;
int iterating : 1;
int match_nothing : 1;
int keep_session : 1;
+ int preload_results : 1;
};
/**
* p11_kit_iter_new:
* @uri: (allow-none): a PKCS\#11 URI to filter on, or %NULL
+ * @behavior: various behavior flags for iterator
*
* Create a new PKCS\#11 iterator for iterating over objects. Only
* objects that match the @uri will be returned by the iterator.
* with p11_kit_iter_free()
*/
P11KitIter *
-p11_kit_iter_new (P11KitUri *uri)
+p11_kit_iter_new (P11KitUri *uri,
+ P11KitIterBehavior behavior)
{
P11KitIter *iter;
CK_ATTRIBUTE *attrs;
}
iter->session_flags = CKF_SERIAL_SESSION;
+ iter->preload_results = !(behavior & P11_KIT_ITER_BUSY_SESSIONS);
return iter;
}
CK_RV
p11_kit_iter_next (P11KitIter *iter)
{
+ CK_ULONG batch;
CK_ULONG count;
CK_BBOOL matches;
CK_RV rv;
iter->num_objects = 0;
iter->saw_objects = 0;
- rv = (iter->module->C_FindObjects) (iter->session, iter->objects,
- MAX_OBJECTS, &iter->num_objects);
- if (rv != CKR_OK)
- return finish_iterating (iter, rv);
-
- /*
- * Done searching on this session, although there are still
- * objects outstanding, which will be returned on next
- * iterations.
- */
- if (iter->num_objects != MAX_OBJECTS) {
- iter->searching = 0;
- iter->searched = 1;
- (iter->module->C_FindObjectsFinal) (iter->session);
+ for (;;) {
+ if (iter->max_objects - iter->num_objects == 0) {
+ iter->max_objects = iter->max_objects ? iter->max_objects * 2 : 64;
+ iter->objects = realloc (iter->objects, iter->max_objects * sizeof (CK_ULONG));
+ return_val_if_fail (iter->objects != NULL, CKR_HOST_MEMORY);
+ }
+
+ batch = iter->max_objects - iter->num_objects;
+ rv = (iter->module->C_FindObjects) (iter->session,
+ iter->objects + iter->num_objects,
+ batch, &count);
+ if (rv != CKR_OK)
+ return finish_iterating (iter, rv);
+
+ iter->num_objects += count;
+
+ /*
+ * Done searching on this session, although there are still
+ * objects outstanding, which will be returned on next
+ * iterations.
+ */
+ if (batch != count) {
+ iter->searching = 0;
+ iter->searched = 1;
+ (iter->module->C_FindObjectsFinal) (iter->session);
+ break;
+ }
+
+ if (!iter->preload_results)
+ break;
}
}
* The session may be closed after the next p11_kit_iter_next() call
* unless p11_kit_iter_keep_session() is called.
*
- * Returns: the slot of the current matching object
+ * Returns: the session used to find the current matching object
*/
CK_SESSION_HANDLE
p11_kit_iter_get_session (P11KitIter *iter)
finish_iterating (iter, CKR_OK);
p11_array_free (iter->modules);
p11_attrs_free (iter->match_attrs);
+ free (iter->objects);
free (iter->slots);
for (cb = iter->callbacks; cb != NULL; cb = next) {
#define P11_KIT_FUTURE_UNSTABLE_API 1
#include "attrs.h"
+#include "dict.h"
#include "iter.h"
#include "library.h"
#include "message.h"
modules = initialize_and_get_modules ();
- iter = p11_kit_iter_new (NULL);
+ iter = p11_kit_iter_new (NULL, P11_KIT_ITER_BUSY_SESSIONS);
p11_kit_iter_begin (iter, modules);
at = 0;
modules = initialize_and_get_modules ();
- iter = p11_kit_iter_new (NULL);
+ iter = p11_kit_iter_new (NULL, 0);
p11_kit_iter_add_callback (iter, on_iter_callback, "callback", NULL);
p11_kit_iter_begin (iter, modules);
modules = initialize_and_get_modules ();
- iter = p11_kit_iter_new (NULL);
+ iter = p11_kit_iter_new (NULL, 0);
p11_kit_iter_add_callback (iter, on_callback_fail, "callback", NULL);
p11_kit_iter_begin (iter, modules);
P11KitIter *iter;
int value = 1;
- iter = p11_kit_iter_new (NULL);
+ iter = p11_kit_iter_new (NULL, 0);
p11_kit_iter_add_callback (iter, on_callback_fail, &value, on_destroy_increment);
p11_kit_iter_free (iter);
rv = mock_C_OpenSession (MOCK_SLOT_ONE_ID, CKF_SERIAL_SESSION, NULL, NULL, &session);
assert (rv == CKR_OK);
- iter = p11_kit_iter_new (NULL);
+ iter = p11_kit_iter_new (NULL, 0);
p11_kit_iter_begin_with (iter, &mock_module, 0, session);
at= 0;
rv = mock_module.C_Initialize (NULL);
assert (rv == CKR_OK);
- iter = p11_kit_iter_new (NULL);
+ iter = p11_kit_iter_new (NULL, 0);
p11_kit_iter_begin_with (iter, &mock_module, MOCK_SLOT_ONE_ID, 0);
at= 0;
rv = mock_module.C_Initialize (NULL);
assert (rv == CKR_OK);
- iter = p11_kit_iter_new (NULL);
+ iter = p11_kit_iter_new (NULL, 0);
p11_kit_iter_begin_with (iter, &mock_module, 0, 0);
at= 0;
rv = mock_module.C_Initialize (NULL);
assert (rv == CKR_OK);
- iter = p11_kit_iter_new (NULL);
+ iter = p11_kit_iter_new (NULL, 0);
p11_kit_iter_begin_with (iter, &mock_module, 0, 0);
rv = p11_kit_iter_next (iter);
uri = p11_kit_uri_new ();
p11_kit_uri_set_unrecognized (uri, 1);
- iter = p11_kit_iter_new (uri);
+ iter = p11_kit_iter_new (uri, 0);
p11_kit_uri_free (uri);
p11_kit_iter_begin (iter, modules);
ret = p11_kit_uri_parse ("pkcs11:object-type=public", P11_KIT_URI_FOR_OBJECT, uri);
assert_num_eq (ret, P11_KIT_URI_OK);
- iter = p11_kit_iter_new (uri);
+ iter = p11_kit_iter_new (uri, 0);
p11_kit_uri_free (uri);
p11_kit_iter_begin (iter, modules);
modules = initialize_and_get_modules ();
- iter = p11_kit_iter_new (NULL);
+ iter = p11_kit_iter_new (NULL, 0);
p11_kit_iter_add_filter (iter, attrs, 2);
p11_kit_iter_begin (iter, modules);
modules = initialize_and_get_modules ();
- iter = p11_kit_iter_new (NULL);
+ iter = p11_kit_iter_new (NULL, 0);
p11_kit_iter_set_session_flags (iter, CKF_RW_SESSION);
p11_kit_iter_begin (iter, modules);
ret = p11_kit_uri_parse ("pkcs11:library-description=MOCK%20LIBRARY", P11_KIT_URI_FOR_MODULE, uri);
assert_num_eq (P11_KIT_URI_OK, ret);
- iter = p11_kit_iter_new (uri);
+ iter = p11_kit_iter_new (uri, 0);
p11_kit_uri_free (uri);
p11_kit_iter_begin (iter, modules);
ret = p11_kit_uri_parse ("pkcs11:library-description=blah", P11_KIT_URI_FOR_MODULE, uri);
assert_num_eq (P11_KIT_URI_OK, ret);
- iter = p11_kit_iter_new (uri);
+ iter = p11_kit_iter_new (uri, 0);
p11_kit_uri_free (uri);
p11_kit_iter_begin (iter, modules);
ret = p11_kit_uri_parse ("pkcs11:manufacturer=TEST%20MANUFACTURER", P11_KIT_URI_FOR_TOKEN, uri);
assert_num_eq (P11_KIT_URI_OK, ret);
- iter = p11_kit_iter_new (uri);
+ iter = p11_kit_iter_new (uri, 0);
p11_kit_uri_free (uri);
p11_kit_iter_begin (iter, modules);
ret = p11_kit_uri_parse ("pkcs11:manufacturer=blah", P11_KIT_URI_FOR_TOKEN, uri);
assert_num_eq (P11_KIT_URI_OK, ret);
- iter = p11_kit_iter_new (uri);
+ iter = p11_kit_iter_new (uri, 0);
p11_kit_uri_free (uri);
p11_kit_iter_begin (iter, modules);
memcpy (&module, &mock_module, sizeof (CK_FUNCTION_LIST));
module.C_GetSlotList = mock_C_GetSlotList__fail_first;
- iter = p11_kit_iter_new (NULL);
+ iter = p11_kit_iter_new (NULL, 0);
p11_kit_iter_begin_with (iter, &module, 0, 0);
at= 0;
memcpy (&module, &mock_module, sizeof (CK_FUNCTION_LIST));
module.C_GetSlotList = mock_C_GetSlotList__fail_late;
- iter = p11_kit_iter_new (NULL);
+ iter = p11_kit_iter_new (NULL, 0);
p11_kit_iter_begin_with (iter, &module, 0, 0);
at= 0;
memcpy (&module, &mock_module, sizeof (CK_FUNCTION_LIST));
module.C_OpenSession = mock_C_OpenSession__fails;
- iter = p11_kit_iter_new (NULL);
+ iter = p11_kit_iter_new (NULL, 0);
p11_kit_iter_begin_with (iter, &module, 0, 0);
at= 0;
memcpy (&module, &mock_module, sizeof (CK_FUNCTION_LIST));
module.C_FindObjectsInit = mock_C_FindObjectsInit__fails;
- iter = p11_kit_iter_new (NULL);
+ iter = p11_kit_iter_new (NULL, 0);
p11_kit_iter_begin_with (iter, &module, 0, 0);
at= 0;
memcpy (&module, &mock_module, sizeof (CK_FUNCTION_LIST));
module.C_FindObjects = mock_C_FindObjects__fails;
- iter = p11_kit_iter_new (NULL);
+ iter = p11_kit_iter_new (NULL, 0);
p11_kit_iter_begin_with (iter, &module, 0, 0);
at= 0;
modules = initialize_and_get_modules ();
- iter = p11_kit_iter_new (NULL);
+ iter = p11_kit_iter_new (NULL, 0);
p11_kit_iter_begin (iter, modules);
attrs = p11_attrs_buildn (NULL, types, 2);
memcpy (&module, &mock_module, sizeof (CK_FUNCTION_LIST));
- iter = p11_kit_iter_new (NULL);
+ iter = p11_kit_iter_new (NULL, 0);
p11_kit_iter_begin_with (iter, &module, 0, 0);
while ((rv = p11_kit_iter_next (iter)) == CKR_OK) {
memcpy (&module, &mock_module, sizeof (CK_FUNCTION_LIST));
module.C_GetAttributeValue = mock_C_GetAttributeValue__fail_first;
- iter = p11_kit_iter_new (NULL);
+ iter = p11_kit_iter_new (NULL, 0);
p11_kit_iter_begin_with (iter, &module, 0, 0);
while ((rv = p11_kit_iter_next (iter)) == CKR_OK) {
memcpy (&module, &mock_module, sizeof (CK_FUNCTION_LIST));
module.C_GetAttributeValue = mock_C_GetAttributeValue__fail_late;
- iter = p11_kit_iter_new (NULL);
+ iter = p11_kit_iter_new (NULL, 0);
p11_kit_iter_begin_with (iter, &module, 0, 0);
while ((rv = p11_kit_iter_next (iter)) == CKR_OK) {
assert (rv == CKR_OK);
}
+static void
+test_many (void *flags)
+{
+ P11KitIterBehavior behavior;
+ CK_SESSION_HANDLE session;
+ CK_OBJECT_HANDLE handle;
+ p11_dict *seen;
+ P11KitIter *iter;
+ CK_RV rv;
+ int count;
+ int i;
+
+ static CK_OBJECT_CLASS data = CKO_DATA;
+ static CK_ATTRIBUTE object[] = {
+ { CKA_VALUE, "blah", 4 },
+ { CKA_CLASS, &data, sizeof (data) },
+ { CKA_ID, "ID1", 3 },
+ { CKA_INVALID },
+ };
+
+ behavior = 0;
+ if (strstr (flags, "busy-sessions"))
+ behavior |= P11_KIT_ITER_BUSY_SESSIONS;
+
+ mock_module_reset ();
+ rv = mock_module.C_Initialize (NULL);
+ assert_num_eq (rv, CKR_OK);
+
+ rv = mock_C_OpenSession (MOCK_SLOT_ONE_ID, CKF_SERIAL_SESSION, NULL, NULL, &session);
+ assert_num_eq (rv, CKR_OK);
+
+ for (i = 0; i < 10000; i++)
+ mock_module_add_object (MOCK_SLOT_ONE_ID, object);
+
+ seen = p11_dict_new (p11_dict_ulongptr_hash, p11_dict_ulongptr_equal, free, NULL);
+ iter = p11_kit_iter_new (NULL, behavior);
+ p11_kit_iter_add_filter (iter, object, 3);
+ p11_kit_iter_begin_with (iter, &mock_module, 0, session);
+
+ count = 0;
+ while ((rv = p11_kit_iter_next (iter)) == CKR_OK) {
+ handle = p11_kit_iter_get_object (iter);
+ assert (p11_dict_get (seen, &handle) == NULL);
+ if (!p11_dict_set (seen, memdup (&handle, sizeof (handle)), "x"))
+ assert_not_reached ();
+ count++;
+ }
+
+ assert_num_eq (rv, CKR_CANCEL);
+ assert_num_eq (count, 10000);
+
+ p11_kit_iter_free (iter);
+ p11_dict_free (seen);
+
+ rv = mock_module.C_Finalize (NULL);
+ assert (rv == CKR_OK);
+}
+
int
main (int argc,
char *argv[])
p11_test (test_load_attributes_none, "/iter/test_load_attributes_none");
p11_test (test_load_attributes_fail_first, "/iter/test_load_attributes_fail_first");
p11_test (test_load_attributes_fail_late, "/iter/test_load_attributes_fail_late");
+ p11_testx (test_many, "", "/iter/test-many");
+ p11_testx (test_many, "busy-sessions", "/iter/test-many-busy");
return p11_test_run (argc, argv);
}