/* * gnome-keyring * * Copyright (C) 2010 Stefan Walter * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see * . */ #include "config.h" #include "gkm-xdg-assertion.h" #include "gkm-xdg-trust.h" #include "gkm/gkm-assertion.h" #include "gkm/gkm-attributes.h" #include "gkm/gkm-object.h" #include "gkm/gkm-session.h" #include "gkm/gkm-transaction.h" #include "gkm/gkm-trust.h" #include "gkm/gkm-util.h" #include "pkcs11/pkcs11i.h" #include "pkcs11/pkcs11n.h" #include "pkcs11/pkcs11x.h" #include G_DEFINE_TYPE (GkmXdgAssertion, gkm_xdg_assertion, GKM_TYPE_ASSERTION); /* ----------------------------------------------------------------------------- * QUARKS */ /* ----------------------------------------------------------------------------- * INTERNAL */ static GkmXdgTrust* lookup_or_create_trust_object (GkmSession *session, GkmManager *manager, GkmTransaction *transaction, CK_X_ASSERTION_TYPE type, CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs, gboolean *created) { CK_ATTRIBUTE_PTR serial, issuer, value; CK_ATTRIBUTE lookups[3]; CK_OBJECT_CLASS klass; CK_ULONG n_lookups; GList *objects; GkmXdgTrust *trust; GkmModule *module; klass = CKO_NETSCAPE_TRUST; lookups[0].type = CKA_CLASS; lookups[0].pValue = &klass; lookups[0].ulValueLen = sizeof (klass); switch (type) { case CKT_X_ANCHORED_CERTIFICATE: case CKT_X_PINNED_CERTIFICATE: value = gkm_attributes_find (attrs, n_attrs, CKA_X_CERTIFICATE_VALUE); if (!value) { gkm_transaction_fail (transaction, CKR_TEMPLATE_INCOMPLETE); return NULL; } /* Attributes used for looking up trust object */ memcpy (&lookups[1], value, sizeof (CK_ATTRIBUTE)); n_lookups = 2; break; case CKT_X_DISTRUSTED_CERTIFICATE: serial = gkm_attributes_find (attrs, n_attrs, CKA_SERIAL_NUMBER); issuer = gkm_attributes_find (attrs, n_attrs, CKA_ISSUER); if (!serial || !issuer) { gkm_transaction_fail (transaction, CKR_TEMPLATE_INCOMPLETE); return NULL; } /* Attributes used for looking up trust object */ memcpy (&lookups[1], issuer, sizeof (CK_ATTRIBUTE)); memcpy (&lookups[2], serial, sizeof (CK_ATTRIBUTE)); n_lookups = 3; break; default: gkm_transaction_fail (transaction, CKR_TEMPLATE_INCONSISTENT); return NULL; }; objects = gkm_manager_find_by_attributes (manager, session, lookups, n_lookups); module = gkm_session_get_module (session); /* Found a matching trust object for this assertion */ if (objects) { g_return_val_if_fail (GKM_XDG_IS_TRUST (objects->data), NULL); trust = g_object_ref (objects->data); g_list_free (objects); /* Create a trust object for this assertion */ } else { trust = gkm_xdg_trust_create_for_assertion (module, manager, transaction, lookups, n_lookups); gkm_attributes_consume (attrs, n_attrs, CKA_X_CERTIFICATE_VALUE, CKA_ISSUER, CKA_SERIAL_NUMBER, G_MAXULONG); gkm_attributes_consume (lookups, n_lookups, CKA_X_CERTIFICATE_VALUE, CKA_ISSUER, CKA_SERIAL_NUMBER, G_MAXULONG); if (!gkm_transaction_get_failed (transaction)) gkm_session_complete_object_creation (session, transaction, GKM_OBJECT (trust), TRUE, lookups, n_lookups); } return trust; } static GkmObject* factory_create_assertion (GkmSession *session, GkmTransaction *transaction, CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs) { GkmAssertion *assertion; CK_X_ASSERTION_TYPE type; GkmManager *manager; gboolean created = FALSE; GkmXdgTrust *trust; gchar *purpose; gchar *peer; g_return_val_if_fail (attrs || !n_attrs, NULL); if (!gkm_attributes_find_ulong (attrs, n_attrs, CKA_X_ASSERTION_TYPE, &type)) { gkm_transaction_fail (transaction, CKR_TEMPLATE_INCOMPLETE); return NULL; } if (!gkm_attributes_find_string (attrs, n_attrs, CKA_X_PURPOSE, &purpose)) { gkm_transaction_fail (transaction, CKR_TEMPLATE_INCOMPLETE); return NULL; } if (!gkm_attributes_find_string (attrs, n_attrs, CKA_X_PEER, &peer)) peer = NULL; /* Try to find or create an appropriate trust object for this assertion */ manager = gkm_manager_for_template (attrs, n_attrs, session); trust = lookup_or_create_trust_object (session, manager, transaction, type, attrs, n_attrs, &created); /* Creating the trust object failed */ if (trust == NULL) { g_return_val_if_fail (gkm_transaction_get_failed (transaction), NULL); g_free (purpose); g_free (peer); return NULL; } assertion = g_object_new (GKM_XDG_TYPE_ASSERTION, "module", gkm_session_get_module (session), "manager", manager, "trust", trust, "type", type, "purpose", purpose, "peer", peer, NULL); g_free (purpose); g_free (peer); /* Add the assertion to the trust object */ if (!gkm_transaction_get_failed (transaction)) { gkm_xdg_trust_replace_assertion (trust, GKM_ASSERTION (assertion), transaction); if (gkm_transaction_get_failed (transaction)) { gkm_transaction_fail (transaction, CKR_GENERAL_ERROR); /* A new trust assertion */ } else { gkm_attributes_consume (attrs, n_attrs, CKA_X_ASSERTION_TYPE, CKA_X_PURPOSE, G_MAXULONG); gkm_session_complete_object_creation (session, transaction, GKM_OBJECT (assertion), TRUE, attrs, n_attrs); } } g_object_unref (trust); return GKM_OBJECT (assertion); } /* ----------------------------------------------------------------------------- * OBJECT */ static void gkm_xdg_assertion_init (GkmXdgAssertion *self) { self->pv = NULL; } static void gkm_xdg_assertion_class_init (GkmXdgAssertionClass *klass) { } /* ----------------------------------------------------------------------------- * PUBLIC */ GkmFactory* gkm_xdg_assertion_get_factory (void) { static CK_OBJECT_CLASS klass = CKO_X_TRUST_ASSERTION; static CK_ATTRIBUTE attributes[] = { { CKA_CLASS, &klass, sizeof (klass) }, }; static GkmFactory factory = { attributes, G_N_ELEMENTS (attributes), factory_create_assertion }; return &factory; }