]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
Extended the PKCS#11 object enumerator by attribute retrieval
authorMartin Willi <martin@revosec.ch>
Thu, 15 Jul 2010 14:25:30 +0000 (16:25 +0200)
committerMartin Willi <martin@revosec.ch>
Wed, 4 Aug 2010 07:26:20 +0000 (09:26 +0200)
src/libstrongswan/plugins/pkcs11/pkcs11_creds.c
src/libstrongswan/plugins/pkcs11/pkcs11_library.c
src/libstrongswan/plugins/pkcs11/pkcs11_library.h

index 2984c70d309bf76e2f2decbf9c5ee3ce48b8ef6d..f461614889c3e7628d9655261e737af08d98383c 100644 (file)
@@ -51,68 +51,6 @@ struct private_pkcs11_creds_t {
        linked_list_t *untrusted;
 };
 
-/**
- * Handle a certificate object, optionally trusted
- */
-static void handle_certificate(private_pkcs11_creds_t *this,
-                                                       CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object,
-                                                       CK_BBOOL trusted)
-{
-       CK_ATTRIBUTE attrs[] = {
-               {CKA_VALUE, NULL, 0},
-               {CKA_LABEL, NULL, 0},
-       };
-       CK_RV rv;
-       certificate_t *cert;
-
-       rv = this->lib->f->C_GetAttributeValue(session, object,
-                                                                                  attrs, countof(attrs));
-       if (rv != CKR_OK)
-       {
-               DBG1(DBG_CFG, "C_GetAttributeValue(NULL) error: %N", ck_rv_names, rv);
-               return;
-       }
-       if (attrs[0].ulValueLen)
-       {
-               attrs[0].pValue = malloc(attrs[0].ulValueLen);
-       }
-       if (attrs[1].ulValueLen)
-       {
-               attrs[1].pValue = malloc(attrs[1].ulValueLen);
-       }
-       rv = this->lib->f->C_GetAttributeValue(session, object,
-                                                                                  attrs, countof(attrs));
-       if (rv == CKR_OK)
-       {
-               cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
-                               BUILD_BLOB_ASN1_DER,
-                               chunk_create(attrs[0].pValue, attrs[0].ulValueLen),
-                               BUILD_END);
-               if (cert)
-               {
-                       DBG1(DBG_CFG, "    loaded %strusted cert '%.*s'",
-                                trusted ? "" : "un", attrs[1].ulValueLen, attrs[1].pValue);
-                       /* trusted certificates are also returned as untrusted */
-                       this->untrusted->insert_last(this->untrusted, cert);
-                       if (trusted)
-                       {
-                               this->trusted->insert_last(this->trusted, cert->get_ref(cert));
-                       }
-               }
-               else
-               {
-                       DBG1(DBG_CFG, "    loading cert '%.*s' failed",
-                                attrs[1].ulValueLen, attrs[1].pValue);
-               }
-       }
-       else
-       {
-               DBG1(DBG_CFG, "C_GetAttributeValue() error: %N", ck_rv_names, rv);
-       }
-       free(attrs[0].pValue);
-       free(attrs[1].pValue);
-}
-
 /**
  * Find certificates, optionally trusted
  */
@@ -121,19 +59,41 @@ static void find_certificates(private_pkcs11_creds_t *this,
 {
        CK_OBJECT_CLASS class = CKO_CERTIFICATE;
        CK_CERTIFICATE_TYPE type = CKC_X_509;
-       CK_ATTRIBUTE template[] = {
+       CK_ATTRIBUTE tmpl[] = {
                {CKA_CLASS, &class, sizeof(class)},
                {CKA_CERTIFICATE_TYPE, &type, sizeof(type)},
                {CKA_TRUSTED, &trusted, sizeof(trusted)},
        };
        CK_OBJECT_HANDLE object;
+       CK_ATTRIBUTE attr[] = {
+               {CKA_VALUE, NULL, 0},
+               {CKA_LABEL, NULL, 0},
+       };
        enumerator_t *enumerator;
+       certificate_t *cert;
 
        enumerator = this->lib->create_object_enumerator(this->lib,
-                                                                               session, template, countof(template));
+                                                       session, tmpl, countof(tmpl), attr, countof(attr));
        while (enumerator->enumerate(enumerator, &object))
        {
-               handle_certificate(this, session, object, trusted);
+               cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
+                                                       BUILD_BLOB_ASN1_DER,
+                                                       chunk_create(attr[0].pValue, attr[0].ulValueLen),
+                                                       BUILD_END);
+               if (!cert)
+               {
+                       DBG1(DBG_CFG, "    loading cert '%.*s' failed",
+                                attr[1].ulValueLen, attr[1].pValue);
+                       continue;
+               }
+               DBG1(DBG_CFG, "    loaded %strusted cert '%.*s'",
+                        trusted ? "" : "un", attr[1].ulValueLen, attr[1].pValue);
+               /* trusted certificates are also returned as untrusted */
+               this->untrusted->insert_last(this->untrusted, cert);
+               if (trusted)
+               {
+                       this->trusted->insert_last(this->trusted, cert->get_ref(cert));
+               }
        }
        enumerator->destroy(enumerator);
 }
index 286b807eda2c24736c034fa8fc0f5839f6fb8de7..d3335dd210409ac32a63f91ed59247011d13da90 100644 (file)
@@ -20,6 +20,7 @@
 #include <library.h>
 #include <debug.h>
 #include <threading/mutex.h>
+#include <utils/linked_list.h>
 
 typedef struct private_pkcs11_library_t private_pkcs11_library_t;
 
@@ -483,8 +484,69 @@ typedef struct {
        CK_SESSION_HANDLE session;
        /* pkcs11 library */
        pkcs11_library_t *lib;
+       /* attributes to retreive */
+       CK_ATTRIBUTE_PTR attr;
+       /* number of attributes */
+       CK_ULONG count;
+       /* currently allocated attributes, to free */
+       linked_list_t *freelist;
 } object_enumerator_t;
 
+/**
+ * Free contents of attributes in a list
+ */
+static void free_attrs(object_enumerator_t *this)
+{
+       CK_ATTRIBUTE_PTR attr;
+
+       while (this->freelist->remove_last(this->freelist, (void**)&attr) == SUCCESS)
+       {
+               free(attr->pValue);
+               attr->pValue = NULL;
+               attr->ulValueLen = 0;
+       }
+}
+
+/**
+ * Get attributes for a given object during enumeration
+ */
+static bool get_attributes(object_enumerator_t *this, CK_OBJECT_HANDLE object)
+{
+       CK_RV rv;
+       int i;
+
+       free_attrs(this);
+
+       /* get length of objects first */
+       rv = this->lib->f->C_GetAttributeValue(this->session, object,
+                                                                                  this->attr, this->count);
+       if (rv != CKR_OK)
+       {
+               DBG1(DBG_CFG, "C_GetAttributeValue(NULL) error: %N", ck_rv_names, rv);
+               return FALSE;
+       }
+       /* allocate required chunks */
+       for (i = 0; i < this->count; i++)
+       {
+               if (this->attr[i].pValue == NULL &&
+                       this->attr[i].ulValueLen != 0 && this->attr[i].ulValueLen != -1)
+               {
+                       this->attr[i].pValue = malloc(this->attr[i].ulValueLen);
+                       this->freelist->insert_last(this->freelist, &this->attr[i]);
+               }
+       }
+       /* get the data */
+       rv = this->lib->f->C_GetAttributeValue(this->session, object,
+                                                                                  this->attr, this->count);
+       if (rv != CKR_OK)
+       {
+               free_attrs(this);
+               DBG1(DBG_CFG, "C_GetAttributeValue(NULL) error: %N", ck_rv_names, rv);
+               return FALSE;
+       }
+       return TRUE;
+}
+
 METHOD(enumerator_t, object_enumerate, bool,
        object_enumerator_t *this, CK_OBJECT_HANDLE *out)
 {
@@ -500,6 +562,13 @@ METHOD(enumerator_t, object_enumerate, bool,
        }
        if (found)
        {
+               if (this->attr)
+               {
+                       if (!get_attributes(this, object))
+                       {
+                               return FALSE;
+                       }
+               }
                *out = object;
                return TRUE;
        }
@@ -510,17 +579,20 @@ METHOD(enumerator_t, object_destroy, void,
        object_enumerator_t *this)
 {
        this->lib->f->C_FindObjectsFinal(this->session);
+       free_attrs(this);
+       this->freelist->destroy(this->freelist);
        free(this);
 }
 
 METHOD(pkcs11_library_t, create_object_enumerator, enumerator_t*,
        private_pkcs11_library_t *this, CK_SESSION_HANDLE session,
-       CK_ATTRIBUTE_PTR tmpl, CK_ULONG count)
+       CK_ATTRIBUTE_PTR tmpl, CK_ULONG tcount,
+       CK_ATTRIBUTE_PTR attr, CK_ULONG acount)
 {
        object_enumerator_t *enumerator;
        CK_RV rv;
 
-       rv = this->public.f->C_FindObjectsInit(session, tmpl, count);
+       rv = this->public.f->C_FindObjectsInit(session, tmpl, tcount);
        if (rv != CKR_OK)
        {
                DBG1(DBG_CFG, "C_FindObjectsInit() failed: %N", ck_rv_names, rv);
@@ -534,6 +606,9 @@ METHOD(pkcs11_library_t, create_object_enumerator, enumerator_t*,
                },
                .session = session,
                .lib = &this->public,
+               .attr = attr,
+               .count = acount,
+               .freelist = linked_list_create(),
        );
        return &enumerator->public;
 }
index c1f7de0e66eba30782082d049103bb6d35d96268..3cca066787825e4e553442c11047b3ceda41d462 100644 (file)
@@ -48,12 +48,19 @@ struct pkcs11_library_t {
        /**
         * Create an enumerator over CK_OBJECT_HANDLE using a search template.
         *
+        * An optional attribute array is automatically filled in with the
+        * objects associated attributes. If the value of an output attribute
+        * is NULL, the value gets allocated/freed during enumeration.
+        *
         * @param session       session to use
         * @param tmpl          search template
-        * @param count         number of attributes in the search template
+        * @param tcount        number of attributes in the search template
+        * @param attr          attributes to read from object
+        * @param acount        number of attributes to read
         */
        enumerator_t* (*create_object_enumerator)(pkcs11_library_t *this,
-                       CK_SESSION_HANDLE session, CK_ATTRIBUTE_PTR tmpl, CK_ULONG count);
+                       CK_SESSION_HANDLE session, CK_ATTRIBUTE_PTR tmpl, CK_ULONG tcount,
+                       CK_ATTRIBUTE_PTR attr, CK_ULONG acount);
 
        /**
         * Destroy a pkcs11_library_t.