diff options
author | Martin Willi <martin@revosec.ch> | 2010-07-15 16:25:30 +0200 |
---|---|---|
committer | Martin Willi <martin@revosec.ch> | 2010-08-04 09:26:20 +0200 |
commit | d007ce320626ea504be547afef79851142b24c41 (patch) | |
tree | 7d0747fb32d34808582e72310f0e6bbf2a5bb76b | |
parent | ddbac66028254bda0bd2aaedac44e16728ca564d (diff) | |
download | strongswan-d007ce320626ea504be547afef79851142b24c41.tar.bz2 strongswan-d007ce320626ea504be547afef79851142b24c41.tar.xz |
Extended the PKCS#11 object enumerator by attribute retrieval
-rw-r--r-- | src/libstrongswan/plugins/pkcs11/pkcs11_creds.c | 90 | ||||
-rw-r--r-- | src/libstrongswan/plugins/pkcs11/pkcs11_library.c | 79 | ||||
-rw-r--r-- | src/libstrongswan/plugins/pkcs11/pkcs11_library.h | 11 |
3 files changed, 111 insertions, 69 deletions
diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_creds.c b/src/libstrongswan/plugins/pkcs11/pkcs11_creds.c index 2984c70d3..f46161488 100644 --- a/src/libstrongswan/plugins/pkcs11/pkcs11_creds.c +++ b/src/libstrongswan/plugins/pkcs11/pkcs11_creds.c @@ -52,68 +52,6 @@ struct private_pkcs11_creds_t { }; /** - * 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 */ static void find_certificates(private_pkcs11_creds_t *this, @@ -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); } diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_library.c b/src/libstrongswan/plugins/pkcs11/pkcs11_library.c index 286b807ed..d3335dd21 100644 --- a/src/libstrongswan/plugins/pkcs11/pkcs11_library.c +++ b/src/libstrongswan/plugins/pkcs11/pkcs11_library.c @@ -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; } diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_library.h b/src/libstrongswan/plugins/pkcs11/pkcs11_library.h index c1f7de0e6..3cca06678 100644 --- a/src/libstrongswan/plugins/pkcs11/pkcs11_library.h +++ b/src/libstrongswan/plugins/pkcs11/pkcs11_library.h @@ -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. |