[glib-networking/tls-database] pkcs11: Load PKCS#11 trust lookup options from config
- From: Stefan Walter <stefw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib-networking/tls-database] pkcs11: Load PKCS#11 trust lookup options from config
- Date: Fri, 7 Jan 2011 01:32:53 +0000 (UTC)
commit a0281f4c78c899b5067d8229dc9c3bcbdd9d1f05
Author: Stef Walter <stefw collabora co uk>
Date: Thu Jan 6 17:31:27 2011 -0800
pkcs11: Load PKCS#11 trust lookup options from config
Use the /etc/pkcs11/pkcs11-options.conf and /etc/pkcs11-options.defaults
files to enumerate the slots that we should use for lookup of trust
assertions.
tls/gnutls/gtlspkcs11database-gnutls.c | 196 +++++++++++++++++++++++++-------
tls/pkcs11/gpkcs11slot.c | 35 ++++++
tls/pkcs11/gpkcs11slot.h | 6 +-
tls/pkcs11/gpkcs11uri.c | 110 +++++++++++++-----
tls/pkcs11/gpkcs11uri.h | 15 ++-
5 files changed, 286 insertions(+), 76 deletions(-)
---
diff --git a/tls/gnutls/gtlspkcs11database-gnutls.c b/tls/gnutls/gtlspkcs11database-gnutls.c
index 3c8061b..9181a02 100644
--- a/tls/gnutls/gtlspkcs11database-gnutls.c
+++ b/tls/gnutls/gtlspkcs11database-gnutls.c
@@ -46,6 +46,7 @@ struct _GTlsPkcs11DatabaseGnutlsPrivate
GList *pkcs11_slots;
GList *modules;
GList *initialized;
+ GList *trust_lookups;
};
static CK_RV
@@ -157,7 +158,8 @@ load_and_initialize_module (GTlsPkcs11DatabaseGnutls *self,
if (!module)
{
g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
- "Error loading PKCS#11 module: %s", g_module_error ());
+ _("Couldn't load PKCS#11 module: %s: %s"),
+ path, g_module_error ());
return NULL;
}
@@ -165,7 +167,8 @@ load_and_initialize_module (GTlsPkcs11DatabaseGnutls *self,
if (!g_module_symbol (module, "C_GetFunctionList", (void**)&get_function_list))
{
g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
- "Invalid PKCS#11 module: %s", g_module_error ());
+ _("Couldn't load PKCS#11 module: %s: %s"),
+ path, g_module_error ());
g_module_close (module);
return NULL;
}
@@ -175,8 +178,8 @@ load_and_initialize_module (GTlsPkcs11DatabaseGnutls *self,
if (rv != CKR_OK)
{
g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
- "Couldn't get PKCS#11 function list: %s",
- g_pkcs11_rv_to_message (rv));
+ _("Couldn't load PKCS#11 module: %s: %s"),
+ path, _("No function list"));
g_module_close (module);
return NULL;
}
@@ -204,8 +207,8 @@ load_and_initialize_module (GTlsPkcs11DatabaseGnutls *self,
else
{
g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
- "Couldn't initialize PKCS#11 module: %s",
- g_pkcs11_rv_to_message (rv));
+ _("Couldn't initialize PKCS#11 module: %s, %s"),
+ path, g_pkcs11_rv_to_message (rv));
g_module_close (module);
return NULL;
}
@@ -257,6 +260,117 @@ enumerate_and_setup_slots (GTlsPkcs11DatabaseGnutls *self,
}
static gboolean
+load_and_setup_all_modules (GTlsPkcs11DatabaseGnutls *self,
+ GCancellable *cancellable,
+ GError **error)
+{
+ CK_FUNCTION_LIST_PTR funcs;
+ gchar **paths, **path;
+ GError *err = NULL;
+ gboolean any_success = FALSE;
+ gboolean any_failure = FALSE;
+
+ paths = list_registered_pkcs11_module_paths (PKCS11_REGISTRY_DIR, &err);
+ if (!paths)
+ {
+ if (err)
+ {
+ g_propagate_error (error, err);
+ return FALSE;
+ }
+ return TRUE;
+ }
+
+ for (path = paths; *path; ++path)
+ {
+ funcs = load_and_initialize_module (self, *path, &err);
+ if (funcs && enumerate_and_setup_slots (self, funcs, &err))
+ {
+ /* Any module initialized */
+ any_success = TRUE;
+ g_clear_error (error);
+ continue;
+ }
+
+ /* All modules have failed */
+ if (!any_success && !any_failure)
+ g_propagate_error (error, err);
+ any_failure = TRUE;
+ }
+
+ g_strfreev (paths);
+ return any_failure && !any_success;
+}
+
+static void
+load_pkcs11_options (GTlsPkcs11DatabaseGnutls *self)
+{
+ GKeyFile *key_file;
+ GError *error = NULL;
+ const gchar *path;
+ gchar *value;
+ gchar **uris, **u;
+ GPkcs11UriInfo *uri_info;
+
+ key_file = g_key_file_new ();
+
+ /* Load the defaults */
+ path = "/etc/pkcs11/pkcs11-options.defaults";
+ if (!g_key_file_load_from_file (key_file, path, G_KEY_FILE_NONE, &error))
+ {
+ g_warning ("couldn't parse %s file: %s", path, error->message);
+ g_clear_error (&error);
+ }
+
+ /* Load any overrides */
+ path = "/etc/pkcs11/pkcs11-options.conf";
+ if (g_file_test (path, G_FILE_TEST_EXISTS) &&
+ !g_key_file_load_from_file (key_file, path, G_KEY_FILE_NONE, &error))
+ {
+ g_warning ("couldn't parse %s file: %s", path, error->message);
+ g_clear_error (&error);
+ }
+
+ value = g_key_file_get_string (key_file, "trust-assertions", "lookups", NULL);
+ uris = g_strsplit_set (value ? value : "", " \t", -1);
+ g_free (value);
+
+ g_key_file_free (key_file);
+
+ for (u = uris; u && *u; ++u)
+ {
+ uri_info = g_pkcs11_uri_parse (*u, &error);
+ if (error)
+ {
+ g_warning ("invalid PKCS#11 URI in options: %s: %s",
+ *u, error->message);
+ g_clear_error (&error);
+ }
+ else
+ {
+ self->priv->trust_lookups = g_list_prepend (self->priv->trust_lookups, uri_info);
+ }
+ }
+
+ g_strfreev (uris);
+}
+
+static gboolean
+slot_is_for_trust_lookup (GTlsPkcs11DatabaseGnutls *self,
+ GPkcs11Slot *slot)
+{
+ GList *l;
+
+ for (l = self->priv->trust_lookups; l; l = g_list_next (l))
+ {
+ if (g_pkcs11_slot_matches_uri (slot, l->data))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
find_objects_on_all_slots (GTlsPkcs11DatabaseGnutls *self,
GPkcs11Array *match,
CK_ATTRIBUTE_TYPE *attr_types,
@@ -265,8 +379,8 @@ find_objects_on_all_slots (GTlsPkcs11DatabaseGnutls *self,
gpointer user_data,
GError **error)
{
+ GPkcs11SlotFindStatus status = G_PKCS11_SLOT_FIND_COMPLETED;
GList *l;
- GPkcs11SlotFindStatus status;
for (l = self->priv->pkcs11_slots; l; l = g_list_next (l))
{
@@ -281,6 +395,31 @@ find_objects_on_all_slots (GTlsPkcs11DatabaseGnutls *self,
}
static gboolean
+find_objects_on_trust_slots (GTlsPkcs11DatabaseGnutls *self,
+ GPkcs11Array *match,
+ CK_ATTRIBUTE_TYPE *attr_types,
+ guint attr_types_length,
+ GPkcs11SlotFindFunc callback,
+ gpointer user_data,
+ GError **error)
+{
+ GPkcs11SlotFindStatus status = G_PKCS11_SLOT_FIND_COMPLETED;
+ GList *l;
+
+ for (l = self->priv->pkcs11_slots; l; l = g_list_next (l))
+ {
+ if (slot_is_for_trust_lookup (self, l->data))
+ status = g_pkcs11_slot_find_objects (l->data, match, attr_types,
+ attr_types_length, callback,
+ user_data, error);
+ if (status != G_PKCS11_SLOT_FIND_COMPLETED)
+ break;
+ }
+
+ return status != G_PKCS11_SLOT_FIND_FAILED;
+}
+
+static gboolean
find_if_any_exist (GPkcs11Slot *slot,
CK_OBJECT_HANDLE object,
GPkcs11Array *attributes,
@@ -338,6 +477,11 @@ g_tls_pkcs11_database_gnutls_finalize (GObject *object)
g_list_free (self->priv->pkcs11_slots);
self->priv->pkcs11_slots = NULL;
+ for (l = self->priv->trust_lookups; l; l = g_list_next (l))
+ g_pkcs11_uri_info_free (l->data);
+ g_list_free (self->priv->trust_lookups);
+ self->priv->trust_lookups = NULL;
+
G_OBJECT_CLASS (g_tls_pkcs11_database_gnutls_parent_class)->finalize (object);
}
@@ -396,8 +540,8 @@ g_tls_pkcs11_database_gnutls_lookup_assertion (GTlsDatabaseGnutls *data
}
if (ready)
- find_objects_on_all_slots (self, match, NULL, 0, find_if_any_exist,
- &found, error);
+ find_objects_on_trust_slots (self, match, NULL, 0, find_if_any_exist,
+ &found, error);
g_pkcs11_array_unref (match);
return found;
@@ -460,38 +604,12 @@ g_tls_pkcs11_database_gnutls_initable_init (GInitable *initable,
GError **error)
{
GTlsPkcs11DatabaseGnutls *self = G_TLS_PKCS11_DATABASE_GNUTLS (initable);
- CK_FUNCTION_LIST_PTR funcs;
- gchar **paths, **path;
- GError *err = NULL;
- gboolean ret = FALSE;
- g_return_val_if_fail (!error || !*error, FALSE);
+ if (!load_and_setup_all_modules (self, cancellable, error))
+ return FALSE;
- paths = list_registered_pkcs11_module_paths (PKCS11_REGISTRY_DIR, &err);
- if (!paths)
- {
- if (err)
- {
- g_propagate_error (error, err);
- return FALSE;
- }
- return TRUE;
- }
-
- /* TODO: Partial success or failure? */
-
- for (path = paths; *path; ++path)
- {
- funcs = load_and_initialize_module (self, *path, error);
- if (funcs != NULL)
- {
- if (enumerate_and_setup_slots (self, funcs, error))
- ret = TRUE;
- }
- }
-
- g_strfreev (paths);
- return ret;
+ load_pkcs11_options (self);
+ return TRUE;
}
static void
diff --git a/tls/pkcs11/gpkcs11slot.c b/tls/pkcs11/gpkcs11slot.c
index 02bf344..bd6cf69 100644
--- a/tls/pkcs11/gpkcs11slot.c
+++ b/tls/pkcs11/gpkcs11slot.c
@@ -400,3 +400,38 @@ g_pkcs11_slot_find_objects (GPkcs11Slot *self,
return status;
}
+
+gboolean
+g_pkcs11_slot_matches_uri (GPkcs11Slot *self,
+ GPkcs11UriInfo *uri_info)
+{
+ CK_INFO library;
+ CK_TOKEN_INFO token;
+ CK_RV rv;
+
+ g_return_val_if_fail (G_IS_PKCS11_SLOT (self), FALSE);
+ g_return_val_if_fail (uri_info, FALSE);
+
+ memset (&library, 0, sizeof (library));
+ rv = (self->priv->module->C_GetInfo) (&library);
+ if (rv != CKR_OK)
+ {
+ g_warning ("call to C_GetInfo on PKCS#11 module failed: %s",
+ g_pkcs11_rv_to_message (rv));
+ return FALSE;
+ }
+
+ memset (&token, 0, sizeof (token));
+ rv = (self->priv->module->C_GetTokenInfo) (self->priv->slot_id, &token);
+ if (rv == CKR_TOKEN_NOT_PRESENT)
+ return FALSE;
+
+ if (rv != CKR_OK)
+ {
+ g_warning ("call to C_GetTokenInfo on PKCS#11 module failed: %s",
+ g_pkcs11_rv_to_message (rv));
+ return FALSE;
+ }
+
+ return g_pkcs11_uri_info_match (uri_info, &library, &token);
+}
diff --git a/tls/pkcs11/gpkcs11slot.h b/tls/pkcs11/gpkcs11slot.h
index fcc017b..3aee754 100644
--- a/tls/pkcs11/gpkcs11slot.h
+++ b/tls/pkcs11/gpkcs11slot.h
@@ -18,6 +18,7 @@
#include <gio/gio.h>
#include "gpkcs11array.h"
+#include "gpkcs11uri.h"
#include "pkcs11.h"
@@ -71,6 +72,9 @@ GPkcs11SlotFindStatus g_pkcs11_slot_find_objects (GPkcs11Slot
gpointer user_data,
GError **error);
+gboolean g_pkcs11_slot_matches_uri (GPkcs11Slot *self,
+ GPkcs11UriInfo *uri_info);
+
G_END_DECLS
-#endif /* __G_TLS_CERTIFICATE_GNUTLS_H___ */
+#endif /* __G_PKCS11_SLOT_H___ */
diff --git a/tls/pkcs11/gpkcs11uri.c b/tls/pkcs11/gpkcs11uri.c
index 2ad8ff5..2d159c5 100644
--- a/tls/pkcs11/gpkcs11uri.c
+++ b/tls/pkcs11/gpkcs11uri.c
@@ -42,8 +42,7 @@ static gint
parse_string_field (const gchar *name,
const gchar *start,
const gchar *end,
- CK_INFO *info,
- CK_TOKEN_INFO *token,
+ GPkcs11UriInfo *info,
GError **error)
{
unsigned char *value;
@@ -54,38 +53,37 @@ parse_string_field (const gchar *name,
g_assert (name);
g_assert (start);
g_assert (end);
- g_assert (token);
g_assert (info);
if (g_str_equal (name, "model"))
{
- value = token->model;
- value_length = sizeof (token->model);
+ value = info->token.model;
+ value_length = sizeof (info->token.model);
}
else if (g_str_equal (name, "manufacturer"))
{
- value = token->manufacturerID;
- value_length = sizeof (token->manufacturerID);
+ value = info->token.manufacturerID;
+ value_length = sizeof (info->token.manufacturerID);
}
else if (g_str_equal (name, "serial"))
{
- value = token->serialNumber;
- value_length = sizeof (token->serialNumber);
+ value = info->token.serialNumber;
+ value_length = sizeof (info->token.serialNumber);
}
else if (g_str_equal (name, "token"))
{
- value = token->label;
- value_length = sizeof (token->label);
+ value = info->token.label;
+ value_length = sizeof (info->token.label);
}
else if (g_str_equal (name, "library-description"))
{
- value = info->libraryDescription;
- value_length = sizeof (info->libraryDescription);
+ value = info->library.libraryDescription;
+ value_length = sizeof (info->library.libraryDescription);
}
else if (g_str_equal (name, "library-manufacturer"))
{
- value = info->manufacturerID;
- value_length = sizeof (info->manufacturerID);
+ value = info->library.manufacturerID;
+ value_length = sizeof (info->library.manufacturerID);
}
else
{
@@ -116,34 +114,28 @@ parse_string_field (const gchar *name,
return SUCCESS;
}
-gboolean
+GPkcs11UriInfo*
g_pkcs11_uri_parse (const gchar *uri,
- CK_INFO *library,
- CK_TOKEN_INFO *token,
GError **error)
{
const gchar *spos, *epos;
+ GPkcs11UriInfo *result;
gchar *key = NULL;
- gboolean ret;
gint res;
- g_return_val_if_fail (uri, FALSE);
- g_return_val_if_fail (library, FALSE);
- g_return_val_if_fail (token, FALSE);
- g_return_val_if_fail (!error || !*error, FALSE);
+ g_return_val_if_fail (uri, NULL);
+ g_return_val_if_fail (!error || !*error, NULL);
if (!g_str_has_prefix (uri, URI_PREFIX))
{
g_set_error_literal (error, G_PKCS11_ERROR, G_PKCS11_ERROR_BAD_URI,
_("The URI has does not have the 'pkcs11' scheme."));
- return FALSE;
+ return NULL;
}
/* All fields set to zero, including string fields */
- memset (token, 0, sizeof (CK_TOKEN_INFO));
- memset (library, 0, sizeof (CK_INFO));
+ result = g_slice_new0 (GPkcs11UriInfo);
- ret = TRUE;
for (;;)
{
spos = strchr (uri, ';');
@@ -160,7 +152,8 @@ g_pkcs11_uri_parse (const gchar *uri,
{
g_set_error_literal (error, G_PKCS11_ERROR, G_PKCS11_ERROR_BAD_URI,
_("The URI has invalid syntax. It must consist of key=value pairs."));
- ret = FALSE;
+ g_pkcs11_uri_info_free (result);
+ result = NULL;
break;
}
@@ -168,14 +161,15 @@ g_pkcs11_uri_parse (const gchar *uri,
key = g_strndup (uri, epos - uri);
epos++;
- res = parse_string_field (key, epos, spos, library, token, error);
+ res = parse_string_field (key, epos, spos, result, error);
if (res == NO_MATCH)
{
g_message ("Ignoring unsupported field '%s'", key);
}
else if (res != SUCCESS)
{
- ret = FALSE;
+ g_pkcs11_uri_info_free (result);
+ result = NULL;
break;
}
@@ -185,5 +179,59 @@ g_pkcs11_uri_parse (const gchar *uri,
}
g_free (key);
- return ret;
+ return result;
+}
+
+#define match_member(x, y, m) \
+ ((x) && (y) && memcmp (&x->m, &y->m, sizeof (&x->m)) == 0)
+
+gboolean
+g_pkcs11_uri_info_match (GPkcs11UriInfo *match,
+ CK_INFO *library,
+ CK_TOKEN_INFO *token)
+{
+ CK_INFO *match_library;
+ CK_TOKEN_INFO *match_token;
+
+ g_return_val_if_fail (match, FALSE);
+
+ match_library = &match->library;
+ match_token = &match->token;
+
+ if (match_library->libraryVersion.major || match_library->libraryVersion.minor)
+ if (!match_member (match_library, library, cryptokiVersion))
+ return FALSE;
+
+ if (match->library.libraryDescription[0])
+ if (!match_member (match_library, library, libraryDescription))
+ return FALSE;
+
+ if (match->library.manufacturerID[0])
+ if (!match_member (match_library, library, manufacturerID))
+ return FALSE;
+
+ if (match->token.model[0])
+ if (!match_member (match_token, token, model))
+ return FALSE;
+
+ if (match->token.manufacturerID[0])
+ if (!match_member (match_token, token, manufacturerID))
+ return FALSE;
+
+ if (match->token.serialNumber[0])
+ if (!match_member (match_token, token, serialNumber))
+ return FALSE;
+
+ if (match->token.label[0])
+ if (!match_member (match_token, token, label))
+ return FALSE;
+
+ return TRUE;
+}
+
+void
+g_pkcs11_uri_info_free (GPkcs11UriInfo *info)
+{
+ if (info)
+ g_slice_free (GPkcs11UriInfo, info);
}
diff --git a/tls/pkcs11/gpkcs11uri.h b/tls/pkcs11/gpkcs11uri.h
index 95f96d0..313dd9c 100644
--- a/tls/pkcs11/gpkcs11uri.h
+++ b/tls/pkcs11/gpkcs11uri.h
@@ -21,16 +21,21 @@
G_BEGIN_DECLS
-gboolean g_pkcs11_uri_parse (const gchar *uri,
- CK_INFO *library,
- CK_TOKEN_INFO *token,
+typedef struct _GPkcs11UriInfo
+{
+ CK_INFO library;
+ CK_TOKEN_INFO token;
+} GPkcs11UriInfo;
+
+GPkcs11UriInfo * g_pkcs11_uri_parse (const gchar *uri,
GError **error);
-gboolean g_pkcs11_uri_info_match (CK_INFO *match_library,
+gboolean g_pkcs11_uri_info_match (GPkcs11UriInfo *match,
CK_INFO *library,
- CK_TOKEN_INFO *match_token,
CK_TOKEN_INFO *token);
+void g_pkcs11_uri_info_free (GPkcs11UriInfo *info);
+
G_END_DECLS
#endif /* __G_PKCS11_URI_H___ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]