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 "gkm/gkm-assertion.h"
27 : #include "gkm/gkm-attributes.h"
28 : #include "gkm/gkm-object.h"
29 : #include "gkm/gkm-session.h"
30 : #include "gkm/gkm-transaction.h"
31 : #include "gkm/gkm-trust.h"
32 : #include "gkm/gkm-util.h"
33 :
34 : #include "pkcs11/pkcs11i.h"
35 : #include "pkcs11/pkcs11n.h"
36 : #include "pkcs11/pkcs11x.h"
37 :
38 : #include <glib/gi18n.h>
39 :
40 61 : G_DEFINE_TYPE (GkmXdgAssertion, gkm_xdg_assertion, GKM_TYPE_ASSERTION);
41 :
42 : /* -----------------------------------------------------------------------------
43 : * QUARKS
44 : */
45 :
46 : /* -----------------------------------------------------------------------------
47 : * INTERNAL
48 : */
49 :
50 : static GkmXdgTrust*
51 39 : lookup_or_create_trust_object (GkmSession *session, GkmManager *manager,
52 : GkmTransaction *transaction, CK_X_ASSERTION_TYPE type,
53 : CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs, gboolean *created)
54 : {
55 : CK_ATTRIBUTE_PTR serial, issuer, value;
56 : CK_ATTRIBUTE lookups[3];
57 : CK_OBJECT_CLASS klass;
58 : CK_ULONG n_lookups;
59 : GList *objects;
60 : GkmXdgTrust *trust;
61 : GkmModule *module;
62 :
63 39 : klass = CKO_NETSCAPE_TRUST;
64 39 : lookups[0].type = CKA_CLASS;
65 39 : lookups[0].pValue = &klass;
66 39 : lookups[0].ulValueLen = sizeof (klass);
67 :
68 39 : switch (type) {
69 25 : case CKT_X_ANCHORED_CERTIFICATE:
70 : case CKT_X_PINNED_CERTIFICATE:
71 25 : value = gkm_attributes_find (attrs, n_attrs, CKA_X_CERTIFICATE_VALUE);
72 25 : if (!value) {
73 1 : gkm_transaction_fail (transaction, CKR_TEMPLATE_INCOMPLETE);
74 1 : return NULL;
75 : }
76 :
77 : /* Attributes used for looking up trust object */
78 24 : memcpy (&lookups[1], value, sizeof (CK_ATTRIBUTE));
79 24 : n_lookups = 2;
80 24 : break;
81 :
82 13 : case CKT_X_DISTRUSTED_CERTIFICATE:
83 13 : serial = gkm_attributes_find (attrs, n_attrs, CKA_SERIAL_NUMBER);
84 13 : issuer = gkm_attributes_find (attrs, n_attrs, CKA_ISSUER);
85 13 : if (!serial || !issuer) {
86 1 : gkm_transaction_fail (transaction, CKR_TEMPLATE_INCOMPLETE);
87 1 : return NULL;
88 : }
89 :
90 : /* Attributes used for looking up trust object */
91 12 : memcpy (&lookups[1], issuer, sizeof (CK_ATTRIBUTE));
92 12 : memcpy (&lookups[2], serial, sizeof (CK_ATTRIBUTE));
93 12 : n_lookups = 3;
94 12 : break;
95 :
96 1 : default:
97 1 : gkm_transaction_fail (transaction, CKR_TEMPLATE_INCONSISTENT);
98 1 : return NULL;
99 : };
100 :
101 36 : objects = gkm_manager_find_by_attributes (manager, session, lookups, n_lookups);
102 36 : module = gkm_session_get_module (session);
103 :
104 : /* Found a matching trust object for this assertion */
105 36 : if (objects) {
106 10 : g_return_val_if_fail (GKM_XDG_IS_TRUST (objects->data), NULL);
107 10 : trust = g_object_ref (objects->data);
108 10 : g_list_free (objects);
109 :
110 : /* Create a trust object for this assertion */
111 : } else {
112 26 : trust = gkm_xdg_trust_create_for_assertion (module, manager, transaction,
113 : lookups, n_lookups);
114 :
115 26 : gkm_attributes_consume (attrs, n_attrs, CKA_X_CERTIFICATE_VALUE,
116 : CKA_ISSUER, CKA_SERIAL_NUMBER, G_MAXULONG);
117 26 : gkm_attributes_consume (lookups, n_lookups, CKA_X_CERTIFICATE_VALUE,
118 : CKA_ISSUER, CKA_SERIAL_NUMBER, G_MAXULONG);
119 :
120 26 : if (!gkm_transaction_get_failed (transaction))
121 24 : gkm_session_complete_object_creation (session, transaction, GKM_OBJECT (trust),
122 : TRUE, lookups, n_lookups);
123 : }
124 :
125 36 : return trust;
126 : }
127 :
128 : static GkmObject*
129 41 : factory_create_assertion (GkmSession *session, GkmTransaction *transaction,
130 : CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs)
131 : {
132 : GkmAssertion *assertion;
133 : CK_X_ASSERTION_TYPE type;
134 : GkmManager *manager;
135 41 : gboolean created = FALSE;
136 : GkmXdgTrust *trust;
137 : gchar *purpose;
138 : gchar *peer;
139 :
140 41 : g_return_val_if_fail (attrs || !n_attrs, NULL);
141 :
142 41 : if (!gkm_attributes_find_ulong (attrs, n_attrs, CKA_X_ASSERTION_TYPE, &type)) {
143 1 : gkm_transaction_fail (transaction, CKR_TEMPLATE_INCOMPLETE);
144 1 : return NULL;
145 : }
146 :
147 40 : if (!gkm_attributes_find_string (attrs, n_attrs, CKA_X_PURPOSE, &purpose)) {
148 1 : gkm_transaction_fail (transaction, CKR_TEMPLATE_INCOMPLETE);
149 1 : return NULL;
150 : }
151 :
152 39 : if (!gkm_attributes_find_string (attrs, n_attrs, CKA_X_PEER, &peer))
153 39 : peer = NULL;
154 :
155 : /* Try to find or create an appropriate trust object for this assertion */
156 39 : manager = gkm_manager_for_template (attrs, n_attrs, session);
157 39 : trust = lookup_or_create_trust_object (session, manager, transaction,
158 : type, attrs, n_attrs, &created);
159 :
160 : /* Creating the trust object failed */
161 39 : if (trust == NULL) {
162 5 : g_return_val_if_fail (gkm_transaction_get_failed (transaction), NULL);
163 5 : g_free (purpose);
164 5 : g_free (peer);
165 5 : return NULL;
166 : }
167 :
168 34 : assertion = g_object_new (GKM_XDG_TYPE_ASSERTION,
169 : "module", gkm_session_get_module (session),
170 : "manager", manager,
171 : "trust", trust,
172 : "type", type,
173 : "purpose", purpose,
174 : "peer", peer,
175 : NULL);
176 34 : g_free (purpose);
177 34 : g_free (peer);
178 :
179 : /* Add the assertion to the trust object */
180 34 : if (!gkm_transaction_get_failed (transaction)) {
181 34 : gkm_xdg_trust_replace_assertion (trust, GKM_ASSERTION (assertion), transaction);
182 34 : if (gkm_transaction_get_failed (transaction)) {
183 0 : gkm_transaction_fail (transaction, CKR_GENERAL_ERROR);
184 :
185 : /* A new trust assertion */
186 : } else {
187 34 : gkm_attributes_consume (attrs, n_attrs, CKA_X_ASSERTION_TYPE, CKA_X_PURPOSE, G_MAXULONG);
188 34 : gkm_session_complete_object_creation (session, transaction, GKM_OBJECT (assertion),
189 : TRUE, attrs, n_attrs);
190 : }
191 : }
192 :
193 34 : g_object_unref (trust);
194 34 : return GKM_OBJECT (assertion);
195 : }
196 :
197 : /* -----------------------------------------------------------------------------
198 : * OBJECT
199 : */
200 :
201 : static void
202 47 : gkm_xdg_assertion_init (GkmXdgAssertion *self)
203 : {
204 47 : self->pv = NULL;
205 47 : }
206 :
207 : static void
208 2 : gkm_xdg_assertion_class_init (GkmXdgAssertionClass *klass)
209 : {
210 :
211 2 : }
212 :
213 : /* -----------------------------------------------------------------------------
214 : * PUBLIC
215 : */
216 :
217 :
218 : GkmFactory*
219 59 : gkm_xdg_assertion_get_factory (void)
220 : {
221 : static CK_OBJECT_CLASS klass = CKO_X_TRUST_ASSERTION;
222 :
223 : static CK_ATTRIBUTE attributes[] = {
224 : { CKA_CLASS, &klass, sizeof (klass) },
225 : };
226 :
227 : static GkmFactory factory = {
228 : attributes,
229 : G_N_ELEMENTS (attributes),
230 : factory_create_assertion
231 : };
232 :
233 59 : return &factory;
234 : }
|