Extended the PKCS#11 object enumerator by attribute retrieval
This commit is contained in:
@@ -51,68 +51,6 @@ struct private_pkcs11_creds_t {
|
|||||||
linked_list_t *untrusted;
|
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
|
* Find certificates, optionally trusted
|
||||||
*/
|
*/
|
||||||
@@ -121,19 +59,41 @@ static void find_certificates(private_pkcs11_creds_t *this,
|
|||||||
{
|
{
|
||||||
CK_OBJECT_CLASS class = CKO_CERTIFICATE;
|
CK_OBJECT_CLASS class = CKO_CERTIFICATE;
|
||||||
CK_CERTIFICATE_TYPE type = CKC_X_509;
|
CK_CERTIFICATE_TYPE type = CKC_X_509;
|
||||||
CK_ATTRIBUTE template[] = {
|
CK_ATTRIBUTE tmpl[] = {
|
||||||
{CKA_CLASS, &class, sizeof(class)},
|
{CKA_CLASS, &class, sizeof(class)},
|
||||||
{CKA_CERTIFICATE_TYPE, &type, sizeof(type)},
|
{CKA_CERTIFICATE_TYPE, &type, sizeof(type)},
|
||||||
{CKA_TRUSTED, &trusted, sizeof(trusted)},
|
{CKA_TRUSTED, &trusted, sizeof(trusted)},
|
||||||
};
|
};
|
||||||
CK_OBJECT_HANDLE object;
|
CK_OBJECT_HANDLE object;
|
||||||
|
CK_ATTRIBUTE attr[] = {
|
||||||
|
{CKA_VALUE, NULL, 0},
|
||||||
|
{CKA_LABEL, NULL, 0},
|
||||||
|
};
|
||||||
enumerator_t *enumerator;
|
enumerator_t *enumerator;
|
||||||
|
certificate_t *cert;
|
||||||
|
|
||||||
enumerator = this->lib->create_object_enumerator(this->lib,
|
enumerator = this->lib->create_object_enumerator(this->lib,
|
||||||
session, template, countof(template));
|
session, tmpl, countof(tmpl), attr, countof(attr));
|
||||||
while (enumerator->enumerate(enumerator, &object))
|
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);
|
enumerator->destroy(enumerator);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
#include <library.h>
|
#include <library.h>
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
#include <threading/mutex.h>
|
#include <threading/mutex.h>
|
||||||
|
#include <utils/linked_list.h>
|
||||||
|
|
||||||
typedef struct private_pkcs11_library_t private_pkcs11_library_t;
|
typedef struct private_pkcs11_library_t private_pkcs11_library_t;
|
||||||
|
|
||||||
@@ -483,8 +484,69 @@ typedef struct {
|
|||||||
CK_SESSION_HANDLE session;
|
CK_SESSION_HANDLE session;
|
||||||
/* pkcs11 library */
|
/* pkcs11 library */
|
||||||
pkcs11_library_t *lib;
|
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;
|
} 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,
|
METHOD(enumerator_t, object_enumerate, bool,
|
||||||
object_enumerator_t *this, CK_OBJECT_HANDLE *out)
|
object_enumerator_t *this, CK_OBJECT_HANDLE *out)
|
||||||
{
|
{
|
||||||
@@ -500,6 +562,13 @@ METHOD(enumerator_t, object_enumerate, bool,
|
|||||||
}
|
}
|
||||||
if (found)
|
if (found)
|
||||||
{
|
{
|
||||||
|
if (this->attr)
|
||||||
|
{
|
||||||
|
if (!get_attributes(this, object))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
*out = object;
|
*out = object;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@@ -510,17 +579,20 @@ METHOD(enumerator_t, object_destroy, void,
|
|||||||
object_enumerator_t *this)
|
object_enumerator_t *this)
|
||||||
{
|
{
|
||||||
this->lib->f->C_FindObjectsFinal(this->session);
|
this->lib->f->C_FindObjectsFinal(this->session);
|
||||||
|
free_attrs(this);
|
||||||
|
this->freelist->destroy(this->freelist);
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(pkcs11_library_t, create_object_enumerator, enumerator_t*,
|
METHOD(pkcs11_library_t, create_object_enumerator, enumerator_t*,
|
||||||
private_pkcs11_library_t *this, CK_SESSION_HANDLE session,
|
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;
|
object_enumerator_t *enumerator;
|
||||||
CK_RV rv;
|
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)
|
if (rv != CKR_OK)
|
||||||
{
|
{
|
||||||
DBG1(DBG_CFG, "C_FindObjectsInit() failed: %N", ck_rv_names, rv);
|
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,
|
.session = session,
|
||||||
.lib = &this->public,
|
.lib = &this->public,
|
||||||
|
.attr = attr,
|
||||||
|
.count = acount,
|
||||||
|
.freelist = linked_list_create(),
|
||||||
);
|
);
|
||||||
return &enumerator->public;
|
return &enumerator->public;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,12 +48,19 @@ struct pkcs11_library_t {
|
|||||||
/**
|
/**
|
||||||
* Create an enumerator over CK_OBJECT_HANDLE using a search template.
|
* 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 session session to use
|
||||||
* @param tmpl search template
|
* @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,
|
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.
|
* Destroy a pkcs11_library_t.
|
||||||
|
|||||||
Reference in New Issue
Block a user