Line data Source code
1 : /*
2 : * gnome-keyring
3 : *
4 : * Copyright (C) 2008 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-attributes.h"
24 : #define DEBUG_FLAG GKM_DEBUG_OBJECT
25 : #include "gkm-debug.h"
26 : #include "gkm-object.h"
27 : #include "gkm-store.h"
28 : #include "gkm-transaction.h"
29 : #include "gkm-util.h"
30 :
31 : typedef struct _Schema {
32 : CK_ATTRIBUTE_TYPE type;
33 : gpointer default_value;
34 : gsize default_length;
35 : GkmStoreValidator validator;
36 : guint flags;
37 : } Schema;
38 :
39 : struct _GkmStorePrivate {
40 : GHashTable *schemas;
41 : };
42 :
43 3867 : G_DEFINE_TYPE_WITH_PRIVATE (GkmStore, gkm_store, G_TYPE_OBJECT);
44 :
45 : /* -----------------------------------------------------------------------------
46 : * INTERNAL
47 : */
48 :
49 : static void
50 591 : schema_free (gpointer data)
51 : {
52 : Schema *schema;
53 :
54 591 : if (data == NULL)
55 0 : return;
56 :
57 591 : schema = data;
58 591 : g_free (schema->default_value);
59 591 : g_slice_free (Schema, schema);
60 : }
61 :
62 : /* -----------------------------------------------------------------------------
63 : * OBJECT
64 : */
65 :
66 : static GObject*
67 557 : gkm_store_constructor (GType type, guint n_props, GObjectConstructParam *props)
68 : {
69 557 : GkmStore *self = GKM_STORE (G_OBJECT_CLASS (gkm_store_parent_class)->constructor(type, n_props, props));
70 557 : g_return_val_if_fail (self, NULL);
71 :
72 557 : return G_OBJECT (self);
73 : }
74 :
75 : static void
76 557 : gkm_store_init (GkmStore *self)
77 : {
78 557 : self->pv = gkm_store_get_instance_private (self);
79 557 : self->pv->schemas = g_hash_table_new_full (gkm_util_ulong_hash, gkm_util_ulong_equal,
80 : NULL, schema_free);
81 557 : }
82 :
83 : static void
84 557 : gkm_store_dispose (GObject *obj)
85 : {
86 557 : GkmStore *self = GKM_STORE (obj);
87 :
88 557 : g_hash_table_remove_all (self->pv->schemas);
89 :
90 557 : G_OBJECT_CLASS (gkm_store_parent_class)->dispose (obj);
91 557 : }
92 :
93 : static void
94 557 : gkm_store_finalize (GObject *obj)
95 : {
96 557 : GkmStore *self = GKM_STORE (obj);
97 :
98 557 : g_hash_table_destroy (self->pv->schemas);
99 :
100 557 : G_OBJECT_CLASS (gkm_store_parent_class)->finalize (obj);
101 557 : }
102 :
103 : static void
104 0 : gkm_store_set_property (GObject *obj, guint prop_id, const GValue *value,
105 : GParamSpec *pspec)
106 : {
107 : switch (prop_id) {
108 : default:
109 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
110 0 : break;
111 : }
112 0 : }
113 :
114 : static void
115 0 : gkm_store_get_property (GObject *obj, guint prop_id, GValue *value,
116 : GParamSpec *pspec)
117 : {
118 : switch (prop_id) {
119 : default:
120 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
121 0 : break;
122 : }
123 0 : }
124 :
125 : static void
126 47 : gkm_store_class_init (GkmStoreClass *klass)
127 : {
128 47 : GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
129 :
130 47 : gobject_class->constructor = gkm_store_constructor;
131 47 : gobject_class->dispose = gkm_store_dispose;
132 47 : gobject_class->finalize = gkm_store_finalize;
133 47 : gobject_class->set_property = gkm_store_set_property;
134 47 : gobject_class->get_property = gkm_store_get_property;
135 47 : }
136 :
137 : /* -----------------------------------------------------------------------------
138 : * PUBLIC
139 : */
140 :
141 : gconstpointer
142 14 : gkm_store_read_value (GkmStore *self, GkmObject *object,
143 : CK_ATTRIBUTE_TYPE type, gsize *n_value)
144 : {
145 : CK_ATTRIBUTE at;
146 : Schema *schema;
147 : CK_RV rv;
148 :
149 14 : g_return_val_if_fail (GKM_IS_STORE (self), NULL);
150 14 : g_return_val_if_fail (GKM_IS_OBJECT (object), NULL);
151 14 : g_return_val_if_fail (n_value, NULL);
152 :
153 14 : g_assert (GKM_STORE_GET_CLASS (self)->read_value);
154 :
155 14 : schema = g_hash_table_lookup (self->pv->schemas, &type);
156 14 : if (schema == NULL)
157 0 : return NULL;
158 :
159 14 : at.type = type;
160 14 : at.pValue = NULL;
161 14 : at.ulValueLen = 0;
162 :
163 14 : rv = GKM_STORE_GET_CLASS (self)->read_value (self, object, &at);
164 14 : if (rv == CKR_ATTRIBUTE_TYPE_INVALID || rv == CKR_USER_NOT_LOGGED_IN) {
165 4 : at.pValue = schema->default_value;
166 4 : at.ulValueLen = schema->default_length;
167 10 : } else if (rv != CKR_OK) {
168 0 : g_return_val_if_reached (NULL);
169 : }
170 :
171 14 : *n_value = at.ulValueLen;
172 14 : return at.pValue;
173 : }
174 :
175 : gchar*
176 3 : gkm_store_read_string (GkmStore *self, GkmObject *object, CK_ATTRIBUTE_TYPE type)
177 : {
178 : gconstpointer value;
179 : gsize n_value;
180 :
181 3 : g_return_val_if_fail (GKM_IS_STORE (self), NULL);
182 3 : g_return_val_if_fail (GKM_IS_OBJECT (object), NULL);
183 :
184 3 : value = gkm_store_read_value (self, object, type, &n_value);
185 3 : if (!value)
186 0 : return NULL;
187 :
188 3 : return g_strndup (value, n_value);
189 : }
190 :
191 : CK_RV
192 139 : gkm_store_get_attribute (GkmStore *self, GkmObject *object, CK_ATTRIBUTE_PTR attr)
193 : {
194 : CK_ATTRIBUTE at;
195 : Schema *schema;
196 : CK_RV rv;
197 :
198 139 : g_return_val_if_fail (GKM_IS_STORE (self), CKR_GENERAL_ERROR);
199 139 : g_return_val_if_fail (GKM_IS_OBJECT (object), CKR_GENERAL_ERROR);
200 139 : g_return_val_if_fail (attr, CKR_GENERAL_ERROR);
201 :
202 139 : g_assert (GKM_STORE_GET_CLASS (self)->read_value);
203 :
204 139 : schema = g_hash_table_lookup (self->pv->schemas, &(attr->type));
205 139 : if (schema == NULL) {
206 133 : gkm_debug ("CKR_ATTRIBUTE_TYPE_INVALID: %s not in schema",
207 : gkm_log_attr_type (attr->type));
208 133 : return CKR_ATTRIBUTE_TYPE_INVALID;
209 : }
210 :
211 6 : if (schema->flags & GKM_STORE_IS_INTERNAL) {
212 1 : gkm_debug ("CKR_ATTRIBUTE_TYPE_INVALID: %s is an internal attribute",
213 : gkm_log_attr_type (attr->type));
214 1 : return CKR_ATTRIBUTE_TYPE_INVALID;
215 : }
216 :
217 5 : if (schema->flags & GKM_STORE_IS_SENSITIVE)
218 1 : return CKR_ATTRIBUTE_SENSITIVE;
219 :
220 4 : at.type = attr->type;
221 4 : at.pValue = NULL;
222 4 : at.ulValueLen = 0;
223 :
224 4 : rv = GKM_STORE_GET_CLASS (self)->read_value (self, object, &at);
225 4 : if (rv == CKR_ATTRIBUTE_TYPE_INVALID) {
226 3 : at.pValue = schema->default_value;
227 3 : at.ulValueLen = schema->default_length;
228 1 : } else if (rv != CKR_OK) {
229 0 : return rv;
230 : }
231 :
232 : /*
233 : * If we get an assert here, then the derived class is probably
234 : * trying to fill the buffer in the attribute passed. It should
235 : * actually just be setting the pValue to its own buffers.
236 : */
237 4 : g_assert (at.pValue || !at.ulValueLen);
238 :
239 4 : return gkm_attribute_set_data (attr, at.pValue, at.ulValueLen);
240 : }
241 :
242 : void
243 3 : gkm_store_write_value (GkmStore *self, GkmTransaction *transaction,
244 : GkmObject *object, CK_ATTRIBUTE_PTR attr)
245 : {
246 : Schema *schema;
247 :
248 3 : g_return_if_fail (GKM_IS_STORE (self));
249 3 : g_return_if_fail (GKM_IS_TRANSACTION (transaction));
250 3 : g_return_if_fail (GKM_IS_OBJECT (object));
251 3 : g_return_if_fail (attr);
252 :
253 3 : g_return_if_fail (!gkm_transaction_get_failed (transaction));
254 3 : g_assert (GKM_STORE_GET_CLASS (self)->write_value);
255 :
256 3 : schema = g_hash_table_lookup (self->pv->schemas, &(attr->type));
257 3 : if (schema == NULL) {
258 0 : gkm_debug ("CKR_ATTRIBUTE_TYPE_INVALID: %s not in schema",
259 : gkm_log_attr_type (attr->type));
260 0 : gkm_transaction_fail (transaction, CKR_ATTRIBUTE_TYPE_INVALID);
261 0 : return;
262 : }
263 :
264 3 : GKM_STORE_GET_CLASS (self)->write_value (self, transaction, object, attr);
265 : }
266 :
267 : void
268 13 : gkm_store_set_attribute (GkmStore *self, GkmTransaction *transaction,
269 : GkmObject *object, CK_ATTRIBUTE_PTR attr)
270 : {
271 : Schema *schema;
272 13 : CK_RV rv = CKR_OK;
273 :
274 13 : g_return_if_fail (GKM_IS_STORE (self));
275 13 : g_return_if_fail (GKM_IS_TRANSACTION (transaction));
276 13 : g_return_if_fail (GKM_IS_OBJECT (object));
277 13 : g_return_if_fail (attr);
278 :
279 13 : g_return_if_fail (!gkm_transaction_get_failed (transaction));
280 13 : g_assert (GKM_STORE_GET_CLASS (self)->write_value);
281 :
282 13 : schema = g_hash_table_lookup (self->pv->schemas, &(attr->type));
283 13 : if (schema == NULL) {
284 2 : gkm_debug ("CKR_ATTRIBUTE_TYPE_INVALID: %s not in schema",
285 : gkm_log_attr_type (attr->type));
286 2 : rv = CKR_ATTRIBUTE_TYPE_INVALID;
287 11 : } else if (schema->flags & GKM_STORE_IS_INTERNAL) {
288 1 : gkm_debug ("CKR_ATTRIBUTE_TYPE_INVALID: %s is internal",
289 : gkm_log_attr_type (attr->type));
290 1 : rv = CKR_ATTRIBUTE_TYPE_INVALID;
291 10 : } else if (schema->validator) {
292 8 : rv = (schema->validator) (object, attr);
293 : }
294 :
295 13 : if (rv != CKR_OK) {
296 4 : gkm_transaction_fail (transaction, rv);
297 4 : return;
298 : }
299 :
300 9 : GKM_STORE_GET_CLASS (self)->write_value (self, transaction, object, attr);
301 : }
302 :
303 : void
304 591 : gkm_store_register_schema (GkmStore *self, CK_ATTRIBUTE_PTR attr,
305 : GkmStoreValidator validator, guint flags)
306 : {
307 : Schema *schema;
308 :
309 591 : g_return_if_fail (GKM_IS_STORE (self));
310 591 : g_return_if_fail (g_hash_table_lookup (self->pv->schemas, &(attr->type)) == NULL);
311 591 : g_return_if_fail (!attr->ulValueLen || attr->pValue);
312 591 : g_return_if_fail (attr->ulValueLen != (CK_ULONG)-1);
313 :
314 591 : schema = g_slice_new0 (Schema);
315 591 : schema->type = attr->type;
316 591 : schema->flags = flags;
317 591 : schema->validator = validator;
318 591 : schema->default_value = attr->pValue;
319 591 : schema->default_length = attr->ulValueLen;
320 591 : if (schema->default_value)
321 571 : schema->default_value = g_memdup (schema->default_value,
322 571 : schema->default_length);
323 :
324 591 : g_hash_table_insert (self->pv->schemas, &(schema->type), schema);
325 : }
326 :
327 : gboolean
328 18 : gkm_store_lookup_schema (GkmStore *self, CK_ATTRIBUTE_TYPE type, guint *flags)
329 : {
330 : Schema *schema;
331 :
332 18 : g_return_val_if_fail (GKM_IS_STORE (self), FALSE);
333 :
334 18 : schema = g_hash_table_lookup (self->pv->schemas, &type);
335 18 : if (!schema)
336 1 : return FALSE;
337 17 : if (flags)
338 1 : *flags = schema->flags;
339 17 : return TRUE;
340 : }
|