LCOV - code coverage report
Current view: top level - pkcs11/xdg-store - gkm-xdg-trust.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 87.3 % 409 357
Test Date: 2024-04-08 13:24:42 Functions: 100.0 % 41 41

            Line data    Source code
       1              : /*
       2              :  * gnome-keyring
       3              :  *
       4              :  * Copyright (C) 2010 Stefan Walter
       5              :  *
       6              :  * This program is free software; you can redistribute it and/or modify
       7              :  * it under the terms of the GNU Lesser General Public License as
       8              :  * published by the Free Software Foundation; either version 2.1 of
       9              :  * the License, or (at your option) any later version.
      10              :  *
      11              :  * This program is distributed in the hope that it will be useful, but
      12              :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      13              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14              :  * Lesser General Public License for more details.
      15              :  *
      16              :  * You should have received a copy of the GNU Lesser General Public
      17              :  * License along with this program; if not, see
      18              :  * <http://www.gnu.org/licenses/>.
      19              :  */
      20              : 
      21              : #include "config.h"
      22              : 
      23              : #include "gkm-xdg-assertion.h"
      24              : #include "gkm-xdg-trust.h"
      25              : 
      26              : #include "egg/egg-asn1x.h"
      27              : #include "egg/egg-asn1-defs.h"
      28              : 
      29              : #include "gkm/gkm-assertion.h"
      30              : #include "gkm/gkm-attributes.h"
      31              : #define DEBUG_FLAG GKM_DEBUG_OBJECT
      32              : #include "gkm/gkm-debug.h"
      33              : #include "gkm/gkm-object.h"
      34              : #include "gkm/gkm-oids.h"
      35              : #include "gkm/gkm-serializable.h"
      36              : #include "gkm/gkm-session.h"
      37              : #include "gkm/gkm-transaction.h"
      38              : #include "gkm/gkm-util.h"
      39              : 
      40              : #include "pkcs11/pkcs11i.h"
      41              : #include "pkcs11/pkcs11n.h"
      42              : #include "pkcs11/pkcs11x.h"
      43              : 
      44              : #include <glib/gi18n.h>
      45              : 
      46              : extern const struct _EggAsn1xDef xdg_asn1_tab[];
      47              : 
      48              : struct _GkmXdgTrustPrivate {
      49              :         GHashTable *assertions;
      50              :         GNode *asn;
      51              :         GBytes *bytes;
      52              : };
      53              : 
      54              : static void gkm_xdg_trust_serializable (GkmSerializableIface *iface);
      55              : 
      56          694 : G_DEFINE_TYPE_EXTENDED (GkmXdgTrust, gkm_xdg_trust, GKM_TYPE_TRUST, 0,
      57              :                         G_IMPLEMENT_INTERFACE (GKM_TYPE_SERIALIZABLE, gkm_xdg_trust_serializable)
      58              :                                                 G_ADD_PRIVATE (GkmXdgTrust));
      59              : 
      60              : static GQuark QDATA_ASSERTION_KEY = 0;
      61              : 
      62              : /* Forward declarations */
      63              : static void add_assertion_to_trust (GkmXdgTrust *self, GkmAssertion *assertion,
      64              :                                     GkmTransaction *transaction);
      65              : 
      66              : static void remove_assertion_from_trust (GkmXdgTrust *self, GkmAssertion *assertion,
      67              :                                          GkmTransaction *transaction);
      68              : 
      69              : /* -----------------------------------------------------------------------------
      70              :  * QUARKS
      71              :  */
      72              : 
      73              : static GQuark TRUST_UNKNOWN;
      74              : static GQuark TRUST_DISTRUSTED;
      75              : static GQuark TRUST_TRUSTED;
      76              : static GQuark TRUST_TRUSTED_ANCHOR;
      77              : 
      78              : static void
      79            2 : init_quarks (void)
      80              : {
      81              :         static gsize quarks_inited = 0;
      82              : 
      83            2 :         if (g_once_init_enter (&quarks_inited)) {
      84              : 
      85              :                 #define QUARK(name, value) \
      86              :                         name = g_quark_from_static_string(value)
      87              : 
      88            2 :                 QUARK (TRUST_UNKNOWN, "trustUnknown");
      89            2 :                 QUARK (TRUST_DISTRUSTED, "distrusted");
      90            2 :                 QUARK (TRUST_TRUSTED, "trusted");
      91            2 :                 QUARK (TRUST_TRUSTED_ANCHOR, "trustedAnchor");
      92              : 
      93              :                 #undef QUARK
      94              : 
      95            2 :                 g_once_init_leave (&quarks_inited, 1);
      96              :         }
      97            2 : }
      98              : 
      99              : /* -----------------------------------------------------------------------------
     100              :  * INTERNAL
     101              :  */
     102              : 
     103              : static CK_RV
     104           21 : trust_get_der (GkmXdgTrust *self, const gchar *part, CK_ATTRIBUTE_PTR attr)
     105              : {
     106              :         GNode *node;
     107              :         GBytes *element;
     108              :         CK_RV rv;
     109              : 
     110           21 :         g_assert (GKM_XDG_IS_TRUST (self));
     111              : 
     112           21 :         node = egg_asn1x_node (self->pv->asn, "reference", "certReference", part, NULL);
     113           21 :         g_return_val_if_fail (node, CKR_GENERAL_ERROR);
     114              : 
     115              :         /* If the assertion doesn't contain this info ... */
     116           21 :         if (!egg_asn1x_have (node)) {
     117           10 :                 gkm_debug ("CKR_ATTRIBUTE_TYPE_INVALID: %s wants %s which is not part of assertion",
     118              :                            gkm_log_attr_type (attr->type), part);
     119           10 :                 return CKR_ATTRIBUTE_TYPE_INVALID;
     120              :         }
     121              : 
     122           11 :         element = egg_asn1x_get_element_raw (node);
     123           11 :         rv = gkm_attribute_set_bytes (attr, element);
     124           11 :         g_bytes_unref (element);
     125              : 
     126           11 :         return rv;
     127              : }
     128              : 
     129              : static CK_RV
     130           20 : trust_get_integer (GkmXdgTrust *self, const gchar *part, CK_ATTRIBUTE_PTR attr)
     131              : {
     132              :         GNode *node;
     133              :         GBytes *integer;
     134              :         CK_RV rv;
     135              : 
     136           20 :         g_assert (GKM_XDG_IS_TRUST (self));
     137              : 
     138           20 :         node = egg_asn1x_node (self->pv->asn, "reference", "certReference", part, NULL);
     139           20 :         g_return_val_if_fail (node, CKR_GENERAL_ERROR);
     140              : 
     141              :         /* If the assertion doesn't contain this info ... */
     142           20 :         if (!egg_asn1x_have (node)) {
     143            9 :                 gkm_debug ("CKR_ATTRIBUTE_TYPE_INVALID: %s wants %s which is not part of assertion",
     144              :                            gkm_log_attr_type (attr->type), part);
     145            9 :                 return CKR_ATTRIBUTE_TYPE_INVALID;
     146              :         }
     147              : 
     148           11 :         integer = egg_asn1x_get_integer_as_raw (node);
     149           11 :         g_return_val_if_fail (integer, CKR_GENERAL_ERROR);
     150              : 
     151           11 :         rv = gkm_attribute_set_bytes (attr, integer);
     152           11 :         g_bytes_unref (integer);
     153              : 
     154           11 :         return rv;
     155              : }
     156              : 
     157              : static CK_RV
     158           20 : trust_get_hash (GkmXdgTrust *self, GChecksumType ctype, CK_ATTRIBUTE_PTR attr)
     159              : {
     160              :         GNode *cert;
     161              :         GBytes *element;
     162              :         CK_RV rv;
     163              : 
     164           20 :         cert = egg_asn1x_node (self->pv->asn, "reference", "certComplete", NULL);
     165           20 :         g_return_val_if_fail (cert, CKR_GENERAL_ERROR);
     166              : 
     167              :         /* If it's not stored, then this attribute is not present */
     168           20 :         if (!egg_asn1x_have (cert)) {
     169            2 :                 gkm_debug ("CKR_ATTRIBUTE_TYPE_INVALID: %s wants certComplete which is not part of assertion",
     170              :                            gkm_log_attr_type (attr->type));
     171            2 :                 return CKR_ATTRIBUTE_TYPE_INVALID;
     172              :         }
     173              : 
     174           18 :         element = egg_asn1x_get_element_raw (cert);
     175           18 :         g_return_val_if_fail (element != NULL, CKR_GENERAL_ERROR);
     176              : 
     177           18 :         rv = gkm_attribute_set_checksum (attr, ctype,
     178              :                                          g_bytes_get_data (element, NULL),
     179              :                                          g_bytes_get_size (element));
     180              : 
     181           18 :         g_bytes_unref (element);
     182           18 :         return rv;
     183              : }
     184              : 
     185              : static CK_RV
     186           29 : trust_get_complete (GkmXdgTrust *self, CK_ATTRIBUTE_PTR attr)
     187              : {
     188              :         GNode *cert;
     189              :         GBytes *element;
     190              :         CK_RV rv;
     191              : 
     192           29 :         cert = egg_asn1x_node (self->pv->asn, "reference", "certComplete", NULL);
     193           29 :         g_return_val_if_fail (cert, CKR_GENERAL_ERROR);
     194              : 
     195              :         /* If it's not stored, then this attribute is not present */
     196           29 :         if (!egg_asn1x_have (cert)) {
     197            7 :                 gkm_debug ("CKR_ATTRIBUTE_TYPE_INVALID: %s wants certComplete which is not part of assertion",
     198              :                            gkm_log_attr_type (attr->type));
     199            7 :                 return CKR_ATTRIBUTE_TYPE_INVALID;
     200              :         }
     201              : 
     202           22 :         element = egg_asn1x_get_element_raw (cert);
     203           22 :         g_return_val_if_fail (element != NULL, CKR_GENERAL_ERROR);
     204              : 
     205           22 :         rv = gkm_attribute_set_bytes (attr, element);
     206           22 :         g_bytes_unref (element);
     207              : 
     208           22 :         return rv;
     209              : }
     210              : 
     211              : 
     212              : static gboolean
     213           26 : validate_der (CK_ATTRIBUTE_PTR attr, const gchar *asn_type)
     214              : {
     215              :         GNode *asn;
     216           26 :         gboolean valid = TRUE;
     217              :         GBytes *data;
     218              : 
     219           26 :         if (!attr->pValue || attr->ulValueLen == (CK_ULONG)-1)
     220            1 :                 return FALSE;
     221              : 
     222           25 :         asn = egg_asn1x_create (pkix_asn1_tab, asn_type);
     223           25 :         g_return_val_if_fail (asn, FALSE);
     224              : 
     225           25 :         data = g_bytes_new_static (attr->pValue, attr->ulValueLen);
     226           25 :         valid = egg_asn1x_decode (asn, data);
     227           25 :         g_bytes_unref (data);
     228              : 
     229           25 :         if (!valid)
     230            1 :                 g_message ("failed to parse certificate passed to trust assertion: %s",
     231              :                            egg_asn1x_message (asn));
     232              : 
     233              :         /* Yes, this is an expensive check, but worthwhile */
     234           25 :         egg_asn1x_destroy (asn);
     235           25 :         return valid;
     236              : }
     237              : 
     238              : static gboolean
     239           11 : validate_integer (CK_ATTRIBUTE_PTR attr)
     240              : {
     241           22 :         return attr->pValue != NULL &&
     242           22 :                attr->ulValueLen > 0 &&
     243           11 :                attr->ulValueLen != (CK_ULONG)-1;
     244              : }
     245              : 
     246              : static GQuark
     247            2 : assertion_type_to_level_enum (CK_X_ASSERTION_TYPE type)
     248              : {
     249            2 :         switch (type) {
     250            0 :         case CKT_X_DISTRUSTED_CERTIFICATE:
     251            0 :                 return TRUST_DISTRUSTED;
     252            0 :         case CKT_X_ANCHORED_CERTIFICATE:
     253            0 :                 return TRUST_TRUSTED_ANCHOR;
     254            2 :         case CKT_X_PINNED_CERTIFICATE:
     255            2 :                 return TRUST_TRUSTED;
     256            0 :         default:
     257            0 :                 return 0;
     258              :         };
     259              : }
     260              : 
     261              : static gboolean
     262           13 : level_enum_to_assertion_type (GQuark level, CK_X_ASSERTION_TYPE *type)
     263              : {
     264           13 :         if (level == TRUST_DISTRUSTED)
     265            0 :                 *type = CKT_X_DISTRUSTED_CERTIFICATE;
     266           13 :         else if (level == TRUST_TRUSTED_ANCHOR)
     267            0 :                 *type = CKT_X_ANCHORED_CERTIFICATE;
     268           13 :         else if (level == TRUST_TRUSTED)
     269           13 :                 *type = CKT_X_PINNED_CERTIFICATE;
     270            0 :         else if (level == TRUST_UNKNOWN)
     271            0 :                 *type = 0;
     272              :         else
     273            0 :                 return FALSE;
     274           13 :         return TRUE;
     275              : }
     276              : 
     277              : static void
     278           36 : check_and_unref_assertion (gpointer data)
     279              : {
     280           36 :         g_assert (GKM_IS_ASSERTION (data));
     281           36 :         g_assert (g_object_get_qdata (data, QDATA_ASSERTION_KEY) != NULL);
     282           36 :         g_object_run_dispose (data);
     283           36 :         g_object_unref (data);
     284           36 : }
     285              : 
     286              : static GHashTable*
     287           61 : create_assertions (void)
     288              : {
     289           61 :         return g_hash_table_new_full (g_bytes_hash, g_bytes_equal,
     290              :                                       (GDestroyNotify)g_bytes_unref,
     291              :                                       check_and_unref_assertion);
     292              : }
     293              : 
     294              : static GkmAssertion*
     295           13 : create_assertion (GkmXdgTrust *self, GNode *asn)
     296              : {
     297           13 :         CK_X_ASSERTION_TYPE type = 0;
     298              :         GkmAssertion *assertion;
     299              :         GQuark level;
     300              :         gchar *purpose;
     301              :         gchar *peer;
     302              :         GNode *node;
     303              : 
     304              :         /* Get the trust level */
     305           13 :         level = egg_asn1x_get_enumerated (egg_asn1x_node (asn, "level", NULL));
     306           13 :         g_return_val_if_fail (level != 0, NULL);
     307           13 :         if (!level_enum_to_assertion_type (level, &type))
     308            0 :                 g_message ("unsupported trust level %s in trust object", g_quark_to_string (level));
     309           13 :         else if (type == 0)
     310            0 :                 return NULL;
     311              : 
     312              :         /* A purpose */
     313           13 :         purpose = egg_asn1x_get_string_as_utf8 (egg_asn1x_node (asn, "purpose", NULL), NULL);
     314           13 :         g_return_val_if_fail (purpose, NULL);
     315              : 
     316              :         /* A peer name */
     317           13 :         node = egg_asn1x_node (asn, "peer", NULL);
     318           13 :         if (egg_asn1x_have (node))
     319            0 :                 peer = egg_asn1x_get_string_as_utf8 (node, NULL);
     320              :         else
     321           13 :                 peer = NULL;
     322              : 
     323           26 :         assertion = g_object_new (GKM_XDG_TYPE_ASSERTION,
     324           13 :                                   "module", gkm_object_get_module (GKM_OBJECT (self)),
     325           13 :                                   "manager", gkm_object_get_manager (GKM_OBJECT (self)),
     326              :                                   "trust", self,
     327              :                                   "type", type,
     328              :                                   "purpose", purpose,
     329              :                                   "peer", peer,
     330              :                                   NULL);
     331              : 
     332           13 :         g_free (purpose);
     333           13 :         g_free (peer);
     334              : 
     335           13 :         return assertion;
     336              : }
     337              : 
     338              : static GBytes *
     339           71 : create_assertion_key (const gchar *purpose,
     340              :                       const gchar *peer)
     341              : {
     342              :         GString *string;
     343              :         gsize len;
     344              : 
     345           71 :         g_return_val_if_fail (purpose, NULL);
     346              : 
     347           71 :         string = g_string_sized_new (32);
     348              :         g_string_append (string, purpose);
     349              : 
     350           71 :         if (peer != NULL) {
     351              :                 g_string_append_len (string, "\0", 1);
     352              :                 g_string_append (string, peer);
     353              :         }
     354              : 
     355           71 :         len = string->len;
     356           71 :         return g_bytes_new_take (g_string_free (string, FALSE), len);
     357              : }
     358              : 
     359              : static GBytes *
     360           93 : lookup_assertion_key (GkmAssertion *assertion)
     361              : {
     362           93 :         return g_object_get_qdata (G_OBJECT (assertion), QDATA_ASSERTION_KEY);
     363              : }
     364              : 
     365              : static GBytes *
     366           81 : lookup_or_create_assertion_key (GkmAssertion *assertion)
     367              : {
     368              :         GBytes *key;
     369              : 
     370           81 :         key = lookup_assertion_key (assertion);
     371           81 :         if (key == NULL) {
     372           47 :                 key = create_assertion_key (gkm_assertion_get_purpose (assertion),
     373              :                                             gkm_assertion_get_peer (assertion));
     374           47 :                 g_object_set_qdata_full (G_OBJECT (assertion), QDATA_ASSERTION_KEY,
     375              :                                          key, (GDestroyNotify)g_bytes_unref);
     376              :         }
     377              : 
     378           81 :         return key;
     379              : }
     380              : 
     381              : static gboolean
     382           34 : complete_add_assertion (GkmTransaction *transaction, GObject *object, gpointer user_data)
     383              : {
     384           34 :         GkmAssertion *assertion = GKM_ASSERTION (user_data);
     385           34 :         GkmXdgTrust *self = GKM_XDG_TRUST (object);
     386              : 
     387           34 :         if (gkm_transaction_get_failed (transaction))
     388            0 :                 remove_assertion_from_trust (self, assertion, NULL);
     389              : 
     390           34 :         g_object_unref (assertion);
     391           34 :         return TRUE;
     392              : }
     393              : 
     394              : static void
     395           47 : add_assertion_to_trust (GkmXdgTrust *self, GkmAssertion *assertion,
     396              :                         GkmTransaction *transaction)
     397              : {
     398              :         GBytes *key;
     399              : 
     400           47 :         key = lookup_or_create_assertion_key (assertion);
     401           47 :         g_assert (key != NULL);
     402              : 
     403           47 :         g_hash_table_insert (self->pv->assertions, g_bytes_ref (key), g_object_ref (assertion));
     404           47 :         gkm_object_expose (GKM_OBJECT (assertion), gkm_object_is_exposed (GKM_OBJECT (self)));
     405              : 
     406           47 :         if (transaction != NULL)
     407           34 :                 gkm_transaction_add (transaction, self, complete_add_assertion, g_object_ref (assertion));
     408           47 : }
     409              : 
     410              : static gboolean
     411           11 : complete_remove_assertion (GkmTransaction *transaction, GObject *object, gpointer user_data)
     412              : {
     413           11 :         GkmXdgTrust *self = GKM_XDG_TRUST (object);
     414           11 :         GkmAssertion *assertion = GKM_ASSERTION (user_data);
     415              : 
     416           11 :         if (gkm_transaction_get_failed (transaction))
     417            0 :                 add_assertion_to_trust (self, assertion, NULL);
     418              :         else
     419           11 :                 g_object_run_dispose (G_OBJECT (assertion));
     420              : 
     421           11 :         g_object_unref (assertion);
     422           11 :         return TRUE;
     423              : }
     424              : 
     425              : static void
     426           11 : remove_assertion_from_trust (GkmXdgTrust *self, GkmAssertion *assertion,
     427              :                              GkmTransaction *transaction)
     428              : {
     429              :         GBytes *key;
     430              : 
     431           11 :         key = lookup_assertion_key (assertion);
     432           11 :         g_assert (key != NULL);
     433              : 
     434           11 :         gkm_object_expose (GKM_OBJECT (assertion), FALSE);
     435              : 
     436           11 :         if (transaction == NULL) {
     437            0 :                 if (!g_hash_table_remove (self->pv->assertions, key))
     438            0 :                         g_return_if_reached ();
     439              :         } else {
     440           11 :                 if (!g_hash_table_steal (self->pv->assertions, key))
     441            0 :                         g_return_if_reached ();
     442           11 :                 gkm_transaction_add (transaction, self, complete_remove_assertion, assertion);
     443           11 :                 g_bytes_unref (key);
     444              :         }
     445              : }
     446              : 
     447              : static gboolean
     448           13 : load_assertions (GkmXdgTrust *self, GNode *asn)
     449              : {
     450              :         GHashTable *assertions;
     451              :         GkmAssertion *assertion;
     452              :         GBytes *key;
     453              :         GNode *node;
     454              :         guint count, i;
     455              : 
     456           13 :         g_assert (self);
     457           13 :         g_assert (asn);
     458              : 
     459           13 :         assertions = self->pv->assertions;
     460           13 :         self->pv->assertions = create_assertions ();
     461              : 
     462           13 :         count = egg_asn1x_count (egg_asn1x_node (asn, "assertions", NULL));
     463              : 
     464           26 :         for (i = 0; i < count; ++i) {
     465           13 :                 node = egg_asn1x_node (asn, "assertions", i + 1, NULL);
     466           13 :                 g_return_val_if_fail (node != NULL, FALSE);
     467              : 
     468              :                 /* We use the raw DER encoding as an assertion */
     469           13 :                 key = egg_asn1x_get_element_raw (node);
     470           13 :                 g_return_val_if_fail (key != NULL, FALSE);
     471              : 
     472              :                 /* Already have this assertion? */
     473           13 :                 assertion = g_hash_table_lookup (assertions, key);
     474           13 :                 if (assertion) {
     475            0 :                         if (!g_hash_table_steal (assertions, key))
     476            0 :                                 g_assert_not_reached ();
     477              : 
     478              :                 /* Create a new assertion */
     479              :                 } else {
     480           13 :                         assertion = create_assertion (self, node);
     481              :                 }
     482              : 
     483           13 :                 add_assertion_to_trust (self, assertion, NULL);
     484           13 :                 g_bytes_unref (key);
     485           13 :                 g_object_unref (assertion);
     486              :         }
     487              : 
     488              :         /* Override the stored assertions and netscape trust */
     489           13 :         g_hash_table_remove_all (assertions);
     490           13 :         g_hash_table_unref (assertions);
     491              : 
     492           13 :         return TRUE;
     493              : }
     494              : 
     495              : static gboolean
     496            2 : save_assertion (GNode *asn, GkmAssertion *assertion)
     497              : {
     498              :         const gchar *purpose;
     499              :         const gchar *peer;
     500              :         GQuark level;
     501              : 
     502            2 :         level = assertion_type_to_level_enum (gkm_assertion_get_trust_type (assertion));
     503            2 :         purpose = gkm_assertion_get_purpose (assertion);
     504            2 :         peer = gkm_assertion_get_peer (assertion);
     505              : 
     506            2 :         if (!egg_asn1x_set_string_as_utf8 (egg_asn1x_node (asn, "purpose", NULL),
     507            2 :                                            g_strdup (purpose), g_free))
     508            0 :                 g_return_val_if_reached (FALSE);
     509            2 :         egg_asn1x_set_enumerated (egg_asn1x_node (asn, "level", NULL), level);
     510              : 
     511            2 :         if (peer && !egg_asn1x_set_string_as_utf8 (egg_asn1x_node (asn, "peer", NULL),
     512            0 :                                                    g_strdup (peer), g_free))
     513            0 :                 g_return_val_if_reached (FALSE);
     514              : 
     515            2 :         return TRUE;
     516              : }
     517              : 
     518              : static gboolean
     519            3 : save_assertions (GkmXdgTrust *self, GNode *asn)
     520              : {
     521              :         GHashTableIter iter;
     522              :         GNode *pair, *node;
     523              :         gpointer value;
     524              : 
     525            3 :         g_assert (GKM_XDG_IS_TRUST (self));
     526            3 :         g_assert (asn);
     527              : 
     528            3 :         node = egg_asn1x_node (asn, "assertions", NULL);
     529            3 :         egg_asn1x_clear (node);
     530              : 
     531            3 :         g_hash_table_iter_init (&iter, self->pv->assertions);
     532            5 :         while (g_hash_table_iter_next (&iter, NULL, &value)) {
     533            2 :                 pair = egg_asn1x_append (node);
     534            2 :                 g_return_val_if_fail (pair, FALSE);
     535            2 :                 save_assertion (pair, GKM_ASSERTION (value));
     536              :         }
     537              : 
     538            3 :         return TRUE;
     539              : }
     540              : 
     541              : static GkmXdgTrust*
     542           11 : create_trust_for_reference (GkmModule *module, GkmManager *manager,
     543              :                             CK_ATTRIBUTE_PTR serial, CK_ATTRIBUTE_PTR issuer)
     544              : {
     545              :         GkmXdgTrust *trust;
     546              :         GNode *asn, *ref, *node;
     547              :         GBytes *bytes;
     548              : 
     549           11 :         asn = egg_asn1x_create (xdg_asn1_tab, "trust-1");
     550           11 :         g_return_val_if_fail (asn, NULL);
     551              : 
     552           11 :         ref = egg_asn1x_node (asn, "reference", NULL);
     553           11 :         node = egg_asn1x_node (ref, "certReference", NULL);
     554              : 
     555           11 :         egg_asn1x_set_choice (ref, node);
     556           11 :         bytes = g_bytes_new (serial->pValue, serial->ulValueLen);
     557           11 :         egg_asn1x_set_integer_as_raw (egg_asn1x_node (node, "serialNumber", NULL), bytes);
     558           11 :         g_bytes_unref (bytes);
     559              : 
     560           11 :         bytes = g_bytes_new (issuer->pValue, issuer->ulValueLen);
     561           11 :         egg_asn1x_set_any_raw (egg_asn1x_node (node, "issuer", NULL), bytes);
     562           11 :         g_bytes_unref (bytes);
     563              : 
     564           11 :         trust = g_object_new (GKM_XDG_TYPE_TRUST, "module", module, "manager", manager, NULL);
     565           11 :         trust->pv->asn = asn;
     566              : 
     567              :         /* Encode it, so we have read access to all the data */
     568           11 :         trust->pv->bytes = egg_asn1x_encode (asn, NULL);
     569           11 :         if (!trust->pv->bytes) {
     570            0 :                 g_warning ("created invalid trust object: %s", egg_asn1x_message (asn));
     571            0 :                 return NULL;
     572              :         }
     573              : 
     574           11 :         return trust;
     575              : }
     576              : 
     577              : static GkmXdgTrust*
     578           13 : create_trust_for_complete (GkmModule *module, GkmManager *manager,
     579              :                               CK_ATTRIBUTE_PTR cert)
     580              : {
     581              :         GkmXdgTrust *trust;
     582              :         GNode *asn, *ref, *node;
     583              :         GBytes *bytes;
     584              : 
     585           13 :         asn = egg_asn1x_create (xdg_asn1_tab, "trust-1");
     586           13 :         g_return_val_if_fail (asn, NULL);
     587              : 
     588           13 :         ref = egg_asn1x_node (asn, "reference", NULL);
     589           13 :         node = egg_asn1x_node (ref, "certComplete", NULL);
     590              : 
     591           13 :         egg_asn1x_set_choice (ref, node);
     592           13 :         bytes = g_bytes_new (cert->pValue, cert->ulValueLen);
     593           13 :         egg_asn1x_set_any_raw (node, bytes);
     594           13 :         g_bytes_unref (bytes);
     595              : 
     596           13 :         trust = g_object_new (GKM_XDG_TYPE_TRUST, "module", module, "manager", manager, NULL);
     597           13 :         trust->pv->asn = asn;
     598              : 
     599              :         /* Encode it, which validates, and so we have read access to all the data */
     600           13 :         trust->pv->bytes = egg_asn1x_encode (asn, NULL);
     601           13 :         if (!trust->pv->bytes) {
     602            0 :                 g_warning ("created invalid trust object: %s", egg_asn1x_message (asn));
     603            0 :                 return NULL;
     604              :         }
     605              : 
     606           13 :         return trust;
     607              : }
     608              : 
     609              : /* -----------------------------------------------------------------------------
     610              :  * OBJECT
     611              :  */
     612              : 
     613              : static CK_RV
     614          282 : gkm_xdg_trust_get_attribute (GkmObject *base, GkmSession *session, CK_ATTRIBUTE_PTR attr)
     615              : {
     616          282 :         GkmXdgTrust *self = GKM_XDG_TRUST (base);
     617              : 
     618          282 :         switch (attr->type)
     619              :         {
     620            0 :         case CKA_PRIVATE:
     621            0 :                 return gkm_attribute_set_bool (attr, CK_FALSE);
     622            0 :         case CKA_TRUST_STEP_UP_APPROVED:
     623            0 :                 return gkm_attribute_set_bool (attr, CK_FALSE);
     624           96 :         case CKA_CLASS:
     625           96 :                 return gkm_attribute_set_ulong (attr, CKO_NETSCAPE_TRUST);
     626            0 :         case CKA_MODIFIABLE:
     627            0 :                 return gkm_attribute_set_bool (attr, CK_FALSE);
     628              : 
     629              :         /* Certificate reference values */
     630            1 :         case CKA_SUBJECT:
     631            1 :                 return trust_get_der (self, "subject", attr);
     632           20 :         case CKA_SERIAL_NUMBER:
     633           20 :                 return trust_get_integer (self, "serialNumber", attr);
     634           20 :         case CKA_ISSUER:
     635           20 :                 return trust_get_der (self, "issuer", attr);
     636           29 :         case CKA_X_CERTIFICATE_VALUE:
     637           29 :                 return trust_get_complete (self, attr);
     638              : 
     639              :         /* Certificate hash values */
     640            2 :         case CKA_CERT_MD5_HASH:
     641            2 :                 return trust_get_hash (self, G_CHECKSUM_MD5, attr);
     642           18 :         case CKA_CERT_SHA1_HASH:
     643           18 :                 return trust_get_hash (self, G_CHECKSUM_SHA1, attr);
     644              : 
     645           96 :         default:
     646           96 :                 break;
     647              :         };
     648              : 
     649           96 :         return GKM_OBJECT_CLASS (gkm_xdg_trust_parent_class)->get_attribute (base, session, attr);
     650              : }
     651              : 
     652              : static void
     653           72 : gkm_xdg_trust_expose_object (GkmObject *base, gboolean expose)
     654              : {
     655              :         GHashTableIter iter;
     656              :         gpointer value;
     657              : 
     658           72 :         GKM_OBJECT_CLASS (gkm_xdg_trust_parent_class)->expose_object (base, expose);
     659              : 
     660           72 :         g_hash_table_iter_init (&iter, GKM_XDG_TRUST (base)->pv->assertions);
     661          119 :         while (g_hash_table_iter_next (&iter, NULL, &value))
     662           47 :                 gkm_object_expose (value, expose);
     663           72 : }
     664              : 
     665              : static GkmTrustLevel
     666           24 : gkm_xdg_trust_get_level (GkmTrust *base, const gchar *purpose)
     667              : {
     668           24 :         GkmXdgTrust *self = GKM_XDG_TRUST (base);
     669              :         GkmAssertion *assertion;
     670              :         GBytes *key;
     671              :         gulong type;
     672              : 
     673           24 :         key = create_assertion_key (purpose, NULL);
     674           24 :         assertion = g_hash_table_lookup (self->pv->assertions, key);
     675           24 :         g_bytes_unref (key);
     676              : 
     677           24 :         if (!assertion)
     678            0 :                 return GKM_TRUST_UNKNOWN;
     679              : 
     680           24 :         type = gkm_assertion_get_trust_type (assertion);
     681           24 :         if (type == CKT_X_ANCHORED_CERTIFICATE)
     682            8 :                 return GKM_TRUST_ANCHOR;
     683           16 :         else if (type == CKT_X_PINNED_CERTIFICATE)
     684            8 :                 return GKM_TRUST_TRUSTED;
     685            8 :         else if (type == CKT_X_DISTRUSTED_CERTIFICATE)
     686            8 :                 return GKM_TRUST_DISTRUSTED;
     687              :         else
     688            0 :                 g_return_val_if_reached (GKM_TRUST_UNKNOWN);
     689              : }
     690              : 
     691              : static void
     692           48 : gkm_xdg_trust_init (GkmXdgTrust *self)
     693              : {
     694           48 :         self->pv = gkm_xdg_trust_get_instance_private (self);
     695           48 :         self->pv->assertions = create_assertions ();
     696           48 : }
     697              : 
     698              : static void
     699           48 : gkm_xdg_trust_finalize (GObject *obj)
     700              : {
     701           48 :         GkmXdgTrust *self = GKM_XDG_TRUST (obj);
     702              : 
     703           48 :         if (self->pv->asn)
     704           36 :                 egg_asn1x_destroy (self->pv->asn);
     705           48 :         self->pv->asn = NULL;
     706              : 
     707           48 :         if (self->pv->assertions)
     708           48 :                 g_hash_table_destroy (self->pv->assertions);
     709           48 :         self->pv->assertions = NULL;
     710              : 
     711           48 :         if (self->pv->bytes)
     712           36 :                 g_bytes_unref (self->pv->bytes);
     713           48 :         self->pv->bytes = NULL;
     714              : 
     715           48 :         G_OBJECT_CLASS (gkm_xdg_trust_parent_class)->finalize (obj);
     716           48 : }
     717              : 
     718              : static void
     719            2 : gkm_xdg_trust_class_init (GkmXdgTrustClass *klass)
     720              : {
     721            2 :         GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
     722            2 :         GkmObjectClass *gkm_class = GKM_OBJECT_CLASS (klass);
     723            2 :         GkmTrustClass *trust_class = GKM_TRUST_CLASS (klass);
     724              : 
     725            2 :         gobject_class->finalize = gkm_xdg_trust_finalize;
     726            2 :         gkm_class->get_attribute = gkm_xdg_trust_get_attribute;
     727            2 :         gkm_class->expose_object = gkm_xdg_trust_expose_object;
     728            2 :         trust_class->get_trust_level = gkm_xdg_trust_get_level;
     729              : 
     730            2 :         QDATA_ASSERTION_KEY = g_quark_from_static_string ("gkm-xdg-trust-assertion-key");
     731              : 
     732            2 :         init_quarks ();
     733            2 : }
     734              : 
     735              : static gboolean
     736           26 : gkm_xdg_trust_real_load (GkmSerializable *base,
     737              :                          GkmSecret *login,
     738              :                          GBytes *data)
     739              : {
     740           26 :         GkmXdgTrust *self = GKM_XDG_TRUST (base);
     741           26 :         GNode *asn = NULL;
     742              : 
     743           26 :         if (g_bytes_get_size (data) == 0)
     744           13 :                 return FALSE;
     745              : 
     746           13 :         asn = egg_asn1x_create (xdg_asn1_tab, "trust-1");
     747           13 :         g_return_val_if_fail (asn, FALSE);
     748              : 
     749           13 :         if (!egg_asn1x_decode (asn, data)) {
     750            0 :                 g_warning ("couldn't parse trust data: %s", egg_asn1x_message (asn));
     751            0 :                 egg_asn1x_destroy (asn);
     752            0 :                 return FALSE;
     753              :         }
     754              : 
     755              :         /* Next parse out all the pairs */
     756           13 :         if (!load_assertions (self, asn)) {
     757            0 :                 egg_asn1x_destroy (asn);
     758            0 :                 return FALSE;
     759              :         }
     760              : 
     761              :         /* Take ownership of this new data */
     762           13 :         if (self->pv->bytes)
     763            1 :                 g_bytes_unref (self->pv->bytes);
     764           13 :         self->pv->bytes = g_bytes_ref (data);
     765           13 :         egg_asn1x_destroy (self->pv->asn);
     766           13 :         self->pv->asn = asn;
     767              : 
     768           13 :         return TRUE;
     769              : }
     770              : 
     771              : static GBytes *
     772            3 : gkm_xdg_trust_real_save (GkmSerializable *base, GkmSecret *login)
     773              : {
     774            3 :         GkmXdgTrust *self = GKM_XDG_TRUST (base);
     775              :         GBytes *bytes;
     776              : 
     777            3 :         g_return_val_if_fail (GKM_XDG_IS_TRUST (self), FALSE);
     778            3 :         g_return_val_if_fail (self->pv->asn, FALSE);
     779              : 
     780            3 :         if (!save_assertions (self, self->pv->asn))
     781            0 :                 return FALSE;
     782              : 
     783            3 :         bytes = egg_asn1x_encode (self->pv->asn, NULL);
     784            3 :         if (bytes == NULL) {
     785            0 :                 g_warning ("encoding trust failed: %s", egg_asn1x_message (self->pv->asn));
     786            0 :                 return FALSE;
     787              :         }
     788              : 
     789            3 :         if (self->pv->bytes)
     790            3 :                 g_bytes_unref (self->pv->bytes);
     791            3 :         self->pv->bytes = bytes;
     792              : 
     793            3 :         return g_bytes_ref (bytes);
     794              : }
     795              : 
     796              : static void
     797            2 : gkm_xdg_trust_serializable (GkmSerializableIface *iface)
     798              : {
     799            2 :         iface->extension = ".trust";
     800            2 :         iface->load = gkm_xdg_trust_real_load;
     801            2 :         iface->save = gkm_xdg_trust_real_save;
     802            2 : }
     803              : 
     804              : /* -----------------------------------------------------------------------------
     805              :  * PUBLIC
     806              :  */
     807              : 
     808              : GkmXdgTrust*
     809           26 : gkm_xdg_trust_create_for_assertion (GkmModule *module, GkmManager *manager,
     810              :                                     GkmTransaction *transaction,
     811              :                                     CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs)
     812              : {
     813              : 
     814              :         CK_ATTRIBUTE_PTR serial, issuer, cert;
     815              :         GkmXdgTrust *trust;
     816              : 
     817           26 :         g_return_val_if_fail (GKM_IS_MODULE (module), NULL);
     818           26 :         g_return_val_if_fail (GKM_IS_MANAGER (manager), NULL);
     819           26 :         g_return_val_if_fail (attrs || !n_attrs, NULL);
     820              : 
     821           26 :         serial = gkm_attributes_find (attrs, n_attrs, CKA_SERIAL_NUMBER);
     822           26 :         issuer = gkm_attributes_find (attrs, n_attrs, CKA_ISSUER);
     823           26 :         cert = gkm_attributes_find (attrs, n_attrs, CKA_X_CERTIFICATE_VALUE);
     824              : 
     825              :         /* A trust object with just serial + issuer */
     826           26 :         if (serial != NULL && issuer != NULL) {
     827           11 :                 if (cert != NULL) {
     828            0 :                         gkm_transaction_fail (transaction, CKR_TEMPLATE_INCONSISTENT);
     829            0 :                         return NULL;
     830              :                 }
     831           11 :                 if (!validate_der (issuer, "Name") || !validate_integer (serial)) {
     832            0 :                         gkm_transaction_fail (transaction, CKR_ATTRIBUTE_VALUE_INVALID);
     833            0 :                         return NULL;
     834              :                 }
     835              : 
     836           11 :                 trust = create_trust_for_reference (module, manager, serial, issuer);
     837              : 
     838              :         /* A trust object with a full certificate */
     839           15 :         } else if (cert != NULL) {
     840           15 :                 if (serial != NULL || issuer != NULL) {
     841            0 :                         gkm_transaction_fail (transaction, CKR_TEMPLATE_INCONSISTENT);
     842            0 :                         return NULL;
     843              :                 }
     844           15 :                 if (!validate_der (cert, "Certificate")) {
     845            2 :                         gkm_transaction_fail (transaction, CKR_ATTRIBUTE_VALUE_INVALID);
     846            2 :                         return NULL;
     847              :                 }
     848              : 
     849           13 :                 trust = create_trust_for_complete (module, manager, cert);
     850              : 
     851              :         /* Not sure what this is */
     852              :         } else {
     853            0 :                 gkm_transaction_fail (transaction, CKR_TEMPLATE_INCOMPLETE);
     854            0 :                 return NULL;
     855              :         }
     856              : 
     857           24 :         gkm_attributes_consume (attrs, n_attrs, CKA_X_CERTIFICATE_VALUE, CKA_ISSUER,
     858              :                                 CKA_SERIAL_NUMBER, G_MAXULONG);
     859              : 
     860           24 :         return trust;
     861              : }
     862              : 
     863              : void
     864           34 : gkm_xdg_trust_replace_assertion (GkmXdgTrust *self, GkmAssertion *assertion,
     865              :                              GkmTransaction *transaction)
     866              : {
     867              :         GkmAssertion *previous;
     868              :         GBytes *key;
     869              : 
     870           34 :         g_return_if_fail (GKM_XDG_IS_TRUST (self));
     871           34 :         g_return_if_fail (GKM_IS_ASSERTION (assertion));
     872           34 :         g_return_if_fail (!transaction || GKM_IS_TRANSACTION (transaction));
     873              : 
     874              :         /* Build up a key if we don't have one */
     875           34 :         key = lookup_or_create_assertion_key (assertion);
     876              : 
     877              :         /* Remove any previous assertion with this key */
     878           34 :         previous = g_hash_table_lookup (self->pv->assertions, key);
     879           34 :         if (previous != NULL)
     880           10 :                 remove_assertion_from_trust (self, previous, transaction);
     881           34 :         add_assertion_to_trust (self, assertion, transaction);
     882              : 
     883              : }
     884              : 
     885              : void
     886            1 : gkm_xdg_trust_remove_assertion (GkmXdgTrust *self, GkmAssertion *assertion,
     887              :                                 GkmTransaction *transaction)
     888              : {
     889              :         GBytes *key;
     890              : 
     891            1 :         g_return_if_fail (GKM_XDG_IS_TRUST (self));
     892            1 :         g_return_if_fail (GKM_IS_ASSERTION (assertion));
     893            1 :         g_return_if_fail (!transaction || GKM_IS_TRANSACTION (transaction));
     894              : 
     895            1 :         key = lookup_assertion_key (assertion);
     896            1 :         g_return_if_fail (key);
     897              : 
     898              :         /* Assertion needs to be from this trust object */
     899            1 :         g_return_if_fail (g_hash_table_lookup (self->pv->assertions, key) == assertion);
     900            1 :         remove_assertion_from_trust (self, assertion, transaction);
     901              : }
     902              : 
     903              : gboolean
     904            1 : gkm_xdg_trust_have_assertion (GkmXdgTrust *self)
     905              : {
     906            1 :         g_return_val_if_fail (GKM_XDG_IS_TRUST (self), FALSE);
     907            1 :         return g_hash_table_size (self->pv->assertions);
     908              : }
        

Generated by: LCOV version 2.0-1