~ubuntu-branches/ubuntu/natty/gnome-keyring/natty

« back to all changes in this revision

Viewing changes to pkcs11/gck/gck-credential.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2010-02-16 19:00:06 UTC
  • mfrom: (1.1.58 upstream)
  • Revision ID: james.westby@ubuntu.com-20100216190006-cqpnic4zxlkmmi0o
Tags: 2.29.90git20100218-0ubuntu1
Updated to a git snapshot version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * gnome-keyring
 
3
 *
 
4
 * Copyright (C) 2009 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  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  License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU Lesser General
 
17
 * License along with this program; if not, write to the Free Software
 
18
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 
19
 * 02111-1307, USA.
 
20
 */
 
21
 
 
22
#include "config.h"
 
23
 
 
24
#include "gck-attributes.h"
 
25
#include "gck-credential.h"
 
26
#include "gck-secret.h"
 
27
#include "gck-session.h"
 
28
#include "gck-transaction.h"
 
29
 
 
30
#include "pkcs11/pkcs11.h"
 
31
#include "pkcs11/pkcs11i.h"
 
32
 
 
33
enum {
 
34
        PROP_0,
 
35
        PROP_OBJECT,
 
36
        PROP_SECRET
 
37
};
 
38
 
 
39
struct _GckCredentialPrivate {
 
40
 
 
41
        /* The object we authenticated */
 
42
        GckObject *object;
 
43
 
 
44
        /* Secret which created this credential */
 
45
        GckSecret *secret;
 
46
 
 
47
        /* Stored data */
 
48
        GType user_type;
 
49
        gpointer user_data;
 
50
};
 
51
 
 
52
G_DEFINE_TYPE (GckCredential, gck_credential, GCK_TYPE_OBJECT);
 
53
 
 
54
/* -----------------------------------------------------------------------------
 
55
 * INTERNAL
 
56
 */
 
57
 
 
58
static GckObject*
 
59
factory_create_credential (GckSession *session, GckTransaction *transaction,
 
60
                              CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs)
 
61
{
 
62
        CK_OBJECT_HANDLE handle;
 
63
        GckCredential *cred;
 
64
        CK_ATTRIBUTE *attr;
 
65
        GckManager *manager;
 
66
        GckModule *module;
 
67
        GckObject *object = NULL;
 
68
        CK_RV rv;
 
69
 
 
70
        g_return_val_if_fail (GCK_IS_TRANSACTION (transaction), NULL);
 
71
        g_return_val_if_fail (attrs || !n_attrs, NULL);
 
72
 
 
73
        /* The handle is optional */
 
74
        if (gck_attributes_find_ulong (attrs, n_attrs, CKA_G_OBJECT, &handle)) {
 
75
                rv = gck_session_lookup_readable_object (session, handle, &object);
 
76
                if (rv != CKR_OK) {
 
77
                        gck_transaction_fail (transaction, rv);
 
78
                        return NULL;
 
79
                }
 
80
        } else {
 
81
                object = NULL;
 
82
        }
 
83
 
 
84
        /* The value is optional */
 
85
        attr = gck_attributes_find (attrs, n_attrs, CKA_VALUE);
 
86
 
 
87
        gck_attributes_consume (attrs, n_attrs, CKA_VALUE, CKA_G_OBJECT, G_MAXULONG);
 
88
 
 
89
        module = gck_session_get_module (session);
 
90
        manager = gck_manager_for_template (attrs, n_attrs, session);
 
91
        rv = gck_credential_create (module, manager, object,
 
92
                                    attr ? attr->pValue : NULL,
 
93
                                    attr ? attr->ulValueLen : 0, &cred);
 
94
 
 
95
        if (rv == CKR_OK) {
 
96
                gck_session_complete_object_creation (session, transaction, GCK_OBJECT (cred),
 
97
                                                      TRUE, attrs, n_attrs);
 
98
                return GCK_OBJECT (cred);
 
99
        } else {
 
100
                gck_transaction_fail (transaction, rv);
 
101
                return NULL;
 
102
        }
 
103
}
 
104
 
 
105
static void
 
106
self_destruct (GckCredential *self)
 
107
{
 
108
        GckTransaction *transaction;
 
109
        CK_RV rv;
 
110
 
 
111
        g_assert (GCK_IS_CREDENTIAL (self));
 
112
 
 
113
        transaction = gck_transaction_new ();
 
114
 
 
115
        /* Destroy ourselves */
 
116
        gck_object_destroy (GCK_OBJECT (self), transaction);
 
117
 
 
118
        gck_transaction_complete (transaction);
 
119
        rv = gck_transaction_get_result (transaction);
 
120
        g_object_unref (transaction);
 
121
 
 
122
        if (rv != CKR_OK)
 
123
                g_warning ("Couldn't destroy credential object: (code %lu)", (gulong)rv);
 
124
}
 
125
 
 
126
static void
 
127
object_went_away (gpointer data, GObject *old_object)
 
128
{
 
129
        GckCredential *self = data;
 
130
        g_return_if_fail (GCK_IS_CREDENTIAL (self));
 
131
        self->pv->object = NULL;
 
132
        self_destruct (self);
 
133
}
 
134
 
 
135
static void
 
136
clear_data (GckCredential *self)
 
137
{
 
138
        if (!self->pv->user_data)
 
139
                return;
 
140
        if (G_TYPE_IS_BOXED (self->pv->user_type))
 
141
                g_boxed_free (self->pv->user_type, self->pv->user_data);
 
142
        else if (G_TYPE_IS_OBJECT (self->pv->user_type))
 
143
                g_object_unref (self->pv->user_data);
 
144
        else
 
145
                g_assert_not_reached ();
 
146
        self->pv->user_data = NULL;
 
147
        self->pv->user_type = 0;
 
148
}
 
149
 
 
150
/* -----------------------------------------------------------------------------
 
151
 * OBJECT
 
152
 */
 
153
 
 
154
static CK_RV
 
155
gck_credential_real_get_attribute (GckObject *base, GckSession *session, CK_ATTRIBUTE *attr)
 
156
{
 
157
        GckCredential *self = GCK_CREDENTIAL (base);
 
158
        CK_OBJECT_HANDLE handle;
 
159
 
 
160
        switch (attr->type) {
 
161
 
 
162
        case CKA_CLASS:
 
163
                return gck_attribute_set_ulong (attr, CKO_G_CREDENTIAL);
 
164
 
 
165
        case CKA_PRIVATE:
 
166
                return gck_attribute_set_bool (attr, TRUE);
 
167
 
 
168
        case CKA_G_OBJECT:
 
169
                handle = self->pv->object ? gck_object_get_handle (self->pv->object) : 0;
 
170
                return gck_attribute_set_ulong (attr, handle);
 
171
 
 
172
        case CKA_VALUE:
 
173
                return CKR_ATTRIBUTE_SENSITIVE;
 
174
        };
 
175
 
 
176
        return GCK_OBJECT_CLASS (gck_credential_parent_class)->get_attribute (base, session, attr);
 
177
}
 
178
 
 
179
static GObject*
 
180
gck_credential_constructor (GType type, guint n_props, GObjectConstructParam *props)
 
181
{
 
182
        GckCredential *self = GCK_CREDENTIAL (G_OBJECT_CLASS (gck_credential_parent_class)->constructor(type, n_props, props));
 
183
        g_return_val_if_fail (self, NULL);
 
184
 
 
185
        return G_OBJECT (self);
 
186
}
 
187
 
 
188
static void
 
189
gck_credential_init (GckCredential *self)
 
190
{
 
191
        self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, GCK_TYPE_CREDENTIAL, GckCredentialPrivate);
 
192
}
 
193
 
 
194
static void
 
195
gck_credential_dispose (GObject *obj)
 
196
{
 
197
        GckCredential *self = GCK_CREDENTIAL (obj);
 
198
 
 
199
        if (self->pv->object)
 
200
                g_object_weak_unref (G_OBJECT (self->pv->object), object_went_away, self);
 
201
        self->pv->object = NULL;
 
202
 
 
203
        clear_data (self);
 
204
 
 
205
        G_OBJECT_CLASS (gck_credential_parent_class)->dispose (obj);
 
206
}
 
207
 
 
208
static void
 
209
gck_credential_finalize (GObject *obj)
 
210
{
 
211
        GckCredential *self = GCK_CREDENTIAL (obj);
 
212
 
 
213
        g_assert (!self->pv->object);
 
214
        g_assert (!self->pv->user_type);
 
215
        g_assert (!self->pv->user_data);
 
216
 
 
217
        G_OBJECT_CLASS (gck_credential_parent_class)->finalize (obj);
 
218
}
 
219
 
 
220
static void
 
221
gck_credential_set_property (GObject *obj, guint prop_id, const GValue *value,
 
222
                                GParamSpec *pspec)
 
223
{
 
224
        GckCredential *self = GCK_CREDENTIAL (obj);
 
225
        GckObject *object;
 
226
 
 
227
        switch (prop_id) {
 
228
        case PROP_OBJECT:
 
229
                object = g_value_get_object (value);
 
230
                if (object)
 
231
                        gck_credential_connect (self, object);
 
232
                else
 
233
                        g_return_if_fail (!self->pv->object);
 
234
                break;
 
235
        case PROP_SECRET:
 
236
                gck_credential_set_secret (self, g_value_get_object (value));
 
237
                break;
 
238
        default:
 
239
                G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
 
240
                break;
 
241
        }
 
242
}
 
243
 
 
244
static void
 
245
gck_credential_get_property (GObject *obj, guint prop_id, GValue *value,
 
246
                              GParamSpec *pspec)
 
247
{
 
248
        GckCredential *self = GCK_CREDENTIAL (obj);
 
249
 
 
250
        switch (prop_id) {
 
251
        case PROP_OBJECT:
 
252
                g_value_set_object (value, gck_credential_get_object (self));
 
253
                break;
 
254
        case PROP_SECRET:
 
255
                g_value_set_object (value, gck_credential_get_secret (self));
 
256
                break;
 
257
        default:
 
258
                G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
 
259
                break;
 
260
        }
 
261
}
 
262
 
 
263
static void
 
264
gck_credential_class_init (GckCredentialClass *klass)
 
265
{
 
266
        GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
267
        GckObjectClass *gck_class = GCK_OBJECT_CLASS (klass);
 
268
 
 
269
        gck_credential_parent_class = g_type_class_peek_parent (klass);
 
270
        g_type_class_add_private (klass, sizeof (GckCredentialPrivate));
 
271
 
 
272
        gobject_class->constructor = gck_credential_constructor;
 
273
        gobject_class->dispose = gck_credential_dispose;
 
274
        gobject_class->finalize = gck_credential_finalize;
 
275
        gobject_class->set_property = gck_credential_set_property;
 
276
        gobject_class->get_property = gck_credential_get_property;
 
277
 
 
278
        gck_class->get_attribute = gck_credential_real_get_attribute;
 
279
 
 
280
        g_object_class_install_property (gobject_class, PROP_OBJECT,
 
281
                   g_param_spec_object ("object", "Object", "Object authenticated",
 
282
                                        GCK_TYPE_OBJECT, G_PARAM_READWRITE));
 
283
 
 
284
        g_object_class_install_property (gobject_class, PROP_SECRET,
 
285
                   g_param_spec_object ("secret", "Secret", "Optiontal secret",
 
286
                                        GCK_TYPE_SECRET, G_PARAM_READWRITE));
 
287
}
 
288
 
 
289
/* -----------------------------------------------------------------------------
 
290
 * PUBLIC
 
291
 */
 
292
 
 
293
GckFactory*
 
294
gck_credential_get_factory (void)
 
295
{
 
296
        static CK_OBJECT_CLASS klass = CKO_G_CREDENTIAL;
 
297
 
 
298
        static CK_ATTRIBUTE attributes[] = {
 
299
                { CKA_CLASS, &klass, sizeof (klass) },
 
300
        };
 
301
 
 
302
        static GckFactory factory = {
 
303
                attributes,
 
304
                G_N_ELEMENTS (attributes),
 
305
                factory_create_credential
 
306
        };
 
307
 
 
308
        return &factory;
 
309
}
 
310
 
 
311
CK_RV
 
312
gck_credential_create (GckModule *module, GckManager *manager, GckObject *object,
 
313
                       CK_UTF8CHAR_PTR pin, CK_ULONG n_pin, GckCredential **result)
 
314
{
 
315
        GckCredential *cred;
 
316
        GckSecret *secret = NULL;
 
317
        CK_RV rv;
 
318
 
 
319
        g_return_val_if_fail (GCK_IS_MODULE (module), CKR_GENERAL_ERROR);
 
320
        g_return_val_if_fail (!object || GCK_IS_OBJECT (object), CKR_GENERAL_ERROR);
 
321
        g_return_val_if_fail (!manager || GCK_IS_MANAGER (manager), CKR_GENERAL_ERROR);
 
322
        g_return_val_if_fail (result, CKR_GENERAL_ERROR);
 
323
 
 
324
        secret = gck_secret_new_from_login (pin, n_pin);
 
325
        cred = g_object_new (GCK_TYPE_CREDENTIAL,
 
326
                             "module", module,
 
327
                             "manager", manager,
 
328
                             "secret", secret,
 
329
                             "object", object,
 
330
                             NULL);
 
331
        g_object_unref (secret);
 
332
 
 
333
        /* If we have an object, the unlock must work */
 
334
        if (object) {
 
335
                rv = gck_object_unlock (object, cred);
 
336
                if (rv == CKR_OK)
 
337
                        *result = cred;
 
338
                else
 
339
                        g_object_unref (cred);
 
340
 
 
341
        /* Created credentials without object */
 
342
        } else {
 
343
                *result = cred;
 
344
                rv = CKR_OK;
 
345
        }
 
346
 
 
347
        return rv;
 
348
}
 
349
 
 
350
void
 
351
gck_credential_connect (GckCredential *self, GckObject *object)
 
352
{
 
353
        g_return_if_fail (GCK_IS_CREDENTIAL (self));
 
354
        g_return_if_fail (GCK_IS_OBJECT (object));
 
355
        g_return_if_fail (self->pv->object == NULL);
 
356
        g_return_if_fail (GCK_OBJECT (self) != object);
 
357
        self->pv->object = object;
 
358
        g_object_weak_ref (G_OBJECT (self->pv->object), object_went_away, self);
 
359
}
 
360
 
 
361
GckSecret*
 
362
gck_credential_get_secret (GckCredential *self)
 
363
{
 
364
        g_return_val_if_fail (GCK_IS_CREDENTIAL (self), NULL);
 
365
        return self->pv->secret;
 
366
}
 
367
 
 
368
void
 
369
gck_credential_set_secret (GckCredential *self, GckSecret *secret)
 
370
{
 
371
        g_return_if_fail (GCK_IS_CREDENTIAL (self));
 
372
 
 
373
        if (secret) {
 
374
                g_return_if_fail (GCK_IS_SECRET (secret));
 
375
                g_object_ref (secret);
 
376
        }
 
377
        if (self->pv->secret)
 
378
                g_object_unref (self->pv->secret);
 
379
        self->pv->secret = secret;
 
380
 
 
381
        g_object_notify (G_OBJECT (self), "secret");
 
382
}
 
383
 
 
384
const gchar*
 
385
gck_credential_get_password (GckCredential *self, gsize *n_password)
 
386
{
 
387
        g_return_val_if_fail (GCK_IS_CREDENTIAL (self), NULL);
 
388
        g_return_val_if_fail (n_password, NULL);
 
389
 
 
390
        if (!self->pv->secret) {
 
391
                *n_password = 0;
 
392
                return NULL;
 
393
        }
 
394
 
 
395
        return gck_secret_get_password (self->pv->secret, n_password);
 
396
}
 
397
 
 
398
GckObject*
 
399
gck_credential_get_object (GckCredential *self)
 
400
{
 
401
        g_return_val_if_fail (GCK_IS_CREDENTIAL (self), NULL);
 
402
        return self->pv->object;
 
403
}
 
404
 
 
405
gpointer
 
406
gck_credential_peek_data (GckCredential *self, GType type)
 
407
{
 
408
        g_return_val_if_fail (GCK_IS_CREDENTIAL (self), NULL);
 
409
        if (!self->pv->user_data)
 
410
                return NULL;
 
411
        g_return_val_if_fail (type == self->pv->user_type, NULL);
 
412
        return self->pv->user_data;
 
413
}
 
414
 
 
415
gpointer
 
416
gck_credential_pop_data (GckCredential *self, GType type)
 
417
{
 
418
        gpointer data = NULL;
 
419
        g_return_val_if_fail (GCK_IS_CREDENTIAL (self), NULL);
 
420
 
 
421
        if (self->pv->user_data) {
 
422
                g_return_val_if_fail (type == self->pv->user_type, NULL);
 
423
                if (G_TYPE_IS_BOXED (self->pv->user_type))
 
424
                        data = g_boxed_copy (self->pv->user_type, self->pv->user_data);
 
425
                else if (G_TYPE_IS_OBJECT (self->pv->user_type))
 
426
                        data = g_object_ref (self->pv->user_data);
 
427
                else
 
428
                        g_assert_not_reached ();
 
429
        }
 
430
 
 
431
        gck_object_mark_used (GCK_OBJECT (self));
 
432
        return data;
 
433
}
 
434
 
 
435
void
 
436
gck_credential_set_data (GckCredential *self, GType type, gpointer data)
 
437
{
 
438
        g_return_if_fail (GCK_IS_CREDENTIAL (self));
 
439
 
 
440
        if (data) {
 
441
                g_return_if_fail (type);
 
442
                g_return_if_fail (G_TYPE_IS_BOXED (type) || G_TYPE_IS_OBJECT (type));
 
443
        }
 
444
 
 
445
        clear_data (self);
 
446
 
 
447
        if (data) {
 
448
                self->pv->user_type = type;
 
449
                if (G_TYPE_IS_BOXED (type))
 
450
                        self->pv->user_data = g_boxed_copy (type, data);
 
451
                else if (G_TYPE_IS_OBJECT (type))
 
452
                        self->pv->user_data = g_object_ref (data);
 
453
                else
 
454
                        g_assert_not_reached ();
 
455
        }
 
456
}
 
457
 
 
458
gboolean
 
459
gck_credential_for_each (GckSession *session, GckObject *object,
 
460
                         GckCredentialFunc func, gpointer user_data)
 
461
{
 
462
        CK_OBJECT_HANDLE handle;
 
463
        CK_OBJECT_CLASS klass;
 
464
        CK_ATTRIBUTE attrs[2];
 
465
        GList *results, *l;
 
466
        GckCredential *cred;
 
467
        gboolean ret;
 
468
 
 
469
        g_return_val_if_fail (GCK_IS_SESSION (session), FALSE);
 
470
        g_return_val_if_fail (GCK_IS_OBJECT (object), FALSE);
 
471
        g_return_val_if_fail (func, FALSE);
 
472
 
 
473
        /* Do we have one right on the session */
 
474
        cred = gck_session_get_credential (session);
 
475
        if (cred && gck_credential_get_object (cred) == object) {
 
476
                g_object_ref (cred);
 
477
                ret = (func) (cred, object, user_data);
 
478
                g_object_unref (cred);
 
479
                if (ret)
 
480
                        return TRUE;
 
481
        }
 
482
 
 
483
        klass = CKO_G_CREDENTIAL;
 
484
        attrs[0].type = CKA_CLASS;
 
485
        attrs[0].pValue = &klass;
 
486
        attrs[0].ulValueLen = sizeof (klass);
 
487
 
 
488
        handle = gck_object_get_handle (object);
 
489
        attrs[1].type = CKA_G_OBJECT;
 
490
        attrs[1].pValue = &handle;
 
491
        attrs[1].ulValueLen = sizeof (handle);
 
492
 
 
493
        /* Find any on the session */
 
494
        results = gck_manager_find_by_attributes (gck_session_get_manager (session),
 
495
                                                  attrs, G_N_ELEMENTS (attrs));
 
496
 
 
497
        for (l = results; l; l = g_list_next (l)) {
 
498
                g_object_ref (l->data);
 
499
                ret = (func) (l->data, object, user_data);
 
500
                g_object_unref (l->data);
 
501
                if (ret)
 
502
                        break;
 
503
        }
 
504
 
 
505
        g_list_free (results);
 
506
 
 
507
        if (l != NULL)
 
508
                return TRUE;
 
509
 
 
510
        /* Find any in the token */
 
511
        results = gck_manager_find_by_attributes (gck_module_get_manager (gck_session_get_module (session)),
 
512
                                                  attrs, G_N_ELEMENTS (attrs));
 
513
 
 
514
        for (l = results; l; l = g_list_next (l)) {
 
515
                g_object_ref (l->data);
 
516
                ret = (func) (l->data, object, user_data);
 
517
                g_object_unref (l->data);
 
518
                if (ret)
 
519
                        break;
 
520
        }
 
521
 
 
522
        g_list_free (results);
 
523
 
 
524
        return (l != NULL);
 
525
}