~noskcaj/ubuntu/vivid/gnome-keyring/3.15.90

« back to all changes in this revision

Viewing changes to gcr/gcr-trust.c

  • Committer: Package Import Robot
  • Author(s): Jordi Mallach
  • Date: 2012-05-14 22:13:02 UTC
  • mfrom: (1.3.1)
  • mto: (80.2.8 experimental) (1.1.77)
  • mto: This revision was merged to the branch mainline in revision 148.
  • Revision ID: package-import@ubuntu.com-20120514221302-0l3gjmqpe6xopond
ImportĀ upstreamĀ versionĀ 3.4.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * gnome-keyring
3
 
 *
4
 
 * Copyright (C) 2010 Collabora Ltd
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, write to the Free Software
18
 
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19
 
 * 02111-1307, USA.
20
 
 *
21
 
 * Author: Stef Walter <stefw@collabora.co.uk>
22
 
 */
23
 
 
24
 
#include "config.h"
25
 
 
26
 
#include "gcr.h"
27
 
#include "gcr-types.h"
28
 
#include "gcr-internal.h"
29
 
#include "gcr-library.h"
30
 
#include "gcr-trust.h"
31
 
 
32
 
#include <gck/gck.h>
33
 
 
34
 
#include "pkcs11/pkcs11n.h"
35
 
#include "pkcs11/pkcs11i.h"
36
 
#include "pkcs11/pkcs11x.h"
37
 
 
38
 
#include <glib/gi18n-lib.h>
39
 
 
40
 
/**
41
 
 * SECTION:gcr-trust
42
 
 * @title: Trust Storage and Lookups
43
 
 * @short_description: Store and lookup bits of information used for
44
 
 * verifying certificates.
45
 
 *
46
 
 * These functions provide access to stored information about which
47
 
 * certificates the system and user trusts as certificate authority trust
48
 
 * anchors, or overrides to the normal verification of certificates.
49
 
 *
50
 
 * Trust anchors are used to verify the certificate authority in a certificate
51
 
 * chain. Trust anchors are always valid for a given purpose. The most common
52
 
 * purpose is the #GCR_PURPOSE_SERVER_AUTH and is used for a client application
53
 
 * to verify that the certificate at the server side of a TLS connection is
54
 
 * authorized to act as such. To check if a certificate is a trust anchor use
55
 
 * gcr_trust_is_certificate_anchored().
56
 
 *
57
 
 * Pinned certificates are used when a user overrides the default trust
58
 
 * decision for a given certificate. They're often used with self-signed
59
 
 * certificates. Pinned certificates are always only valid for a single peer
60
 
 * such as the remote host with which TLS is being performed. To lookup
61
 
 * pinned certificates use gcr_trust_is_certificate_pinned().
62
 
 *
63
 
 * After the user has requested to override the trust decision
64
 
 * about a given certificate then a pinned certificates can be added by using
65
 
 * the gcr_trust_add_pinned_certificate() function.
66
 
 *
67
 
 * These functions do not constitute a viable method for verifying certificates
68
 
 * used in TLS or other locations. Instead they support such verification
69
 
 * by providing some of the needed data for a trust decision.
70
 
 *
71
 
 * The storage is provided by pluggable PKCS\#11 modules.
72
 
 */
73
 
 
74
 
/**
75
 
 * GCR_PURPOSE_SERVER_AUTH:
76
 
 *
77
 
 * The purpose used to verify the server certificate in a TLS connection. This
78
 
 * is the most common purpose in use.
79
 
 */
80
 
 
81
 
/**
82
 
 * GCR_PURPOSE_CLIENT_AUTH:
83
 
 *
84
 
 * The purpose used to verify the client certificate in a TLS connection.
85
 
 */
86
 
 
87
 
/**
88
 
 * GCR_PURPOSE_CODE_SIGNING:
89
 
 *
90
 
 * The purpose used to verify certificate used for the signature on signed code.
91
 
 */
92
 
 
93
 
/**
94
 
 * GCR_PURPOSE_CODE_SIGNING:
95
 
 *
96
 
 * The purpose used to verify certificates that are used in email communication
97
 
 * such as S/MIME.
98
 
 */
99
 
 
100
 
/* ----------------------------------------------------------------------------------
101
 
 * HELPERS
102
 
 */
103
 
 
104
 
typedef struct _GcrTrustOperation {
105
 
        GckEnumerator *en;
106
 
        GckAttributes *attrs;
107
 
        gboolean found;
108
 
} GcrTrustOperation;
109
 
 
110
 
static void
111
 
trust_operation_free (gpointer data)
112
 
{
113
 
        GcrTrustOperation *op = data;
114
 
        g_assert (data);
115
 
 
116
 
        /* No reference held */
117
 
        g_assert (GCK_IS_ENUMERATOR (op->en));
118
 
        op->en = NULL;
119
 
 
120
 
        g_assert (op->attrs);
121
 
        gck_attributes_unref (op->attrs);
122
 
        op->attrs = NULL;
123
 
 
124
 
        g_slice_free (GcrTrustOperation, op);
125
 
}
126
 
 
127
 
static void
128
 
trust_operation_init (GckEnumerator *en, GckAttributes *attrs)
129
 
{
130
 
        GcrTrustOperation *op;
131
 
 
132
 
        g_assert (GCK_IS_ENUMERATOR (en));
133
 
        g_assert (!g_object_get_data (G_OBJECT (en), "trust-operation"));
134
 
        g_assert (attrs);
135
 
 
136
 
        op = g_slice_new0 (GcrTrustOperation);
137
 
        op->attrs = gck_attributes_ref (attrs);
138
 
 
139
 
        /* No reference held, GckEnumerator owns */
140
 
        op->en = en;
141
 
        g_object_set_data_full (G_OBJECT (en), "trust-operation", op, trust_operation_free);
142
 
}
143
 
 
144
 
static GcrTrustOperation*
145
 
trust_operation_get (GckEnumerator *en)
146
 
{
147
 
        GcrTrustOperation *op = g_object_get_data (G_OBJECT (en), "trust-operation");
148
 
        g_assert (op);
149
 
        g_assert (op->en == en);
150
 
        return op;
151
 
}
152
 
 
153
 
static GckAttributes*
154
 
prepare_trust_attrs (GcrCertificate *certificate, CK_X_ASSERTION_TYPE type)
155
 
{
156
 
        GckAttributes *attrs;
157
 
        gconstpointer data;
158
 
        gsize n_data;
159
 
 
160
 
        attrs = gck_attributes_new ();
161
 
        gck_attributes_add_ulong (attrs, CKA_CLASS, CKO_X_TRUST_ASSERTION);
162
 
        gck_attributes_add_ulong (attrs, CKA_X_ASSERTION_TYPE, type);
163
 
 
164
 
        data = gcr_certificate_get_der_data (certificate, &n_data);
165
 
        g_return_val_if_fail (data, NULL);
166
 
        gck_attributes_add_data (attrs, CKA_X_CERTIFICATE_VALUE, data, n_data);
167
 
 
168
 
        return attrs;
169
 
}
170
 
 
171
 
/* ----------------------------------------------------------------------------------
172
 
 * GET PINNED CERTIFICATE
173
 
 */
174
 
 
175
 
static GckEnumerator*
176
 
prepare_is_certificate_pinned (GcrCertificate *certificate, const gchar *purpose, const gchar *peer)
177
 
{
178
 
        GckAttributes *attrs;
179
 
        GckEnumerator *en;
180
 
        GList *slots;
181
 
 
182
 
        attrs = prepare_trust_attrs (certificate, CKT_X_PINNED_CERTIFICATE);
183
 
        g_return_val_if_fail (attrs, NULL);
184
 
 
185
 
        gck_attributes_add_string (attrs, CKA_X_PURPOSE, purpose);
186
 
        gck_attributes_add_string (attrs, CKA_X_PEER, peer);
187
 
 
188
 
        slots = gcr_pkcs11_get_trust_lookup_slots ();
189
 
        en = gck_slots_enumerate_objects (slots, attrs, 0);
190
 
        trust_operation_init (en, attrs);
191
 
        gck_attributes_unref (attrs);
192
 
        gck_list_unref_free (slots);
193
 
 
194
 
        return en;
195
 
}
196
 
 
197
 
static gboolean
198
 
perform_is_certificate_pinned (GckEnumerator *en, GCancellable *cancellable, GError **error)
199
 
{
200
 
        GcrTrustOperation *op;
201
 
        GckObject *object;
202
 
 
203
 
        op = trust_operation_get (en);
204
 
 
205
 
        g_assert (op != NULL);
206
 
        g_assert (op->found == FALSE);
207
 
 
208
 
        object = gck_enumerator_next (en, cancellable, error);
209
 
        op->found = (object != NULL);
210
 
 
211
 
        if (object)
212
 
                g_object_unref (object);
213
 
 
214
 
        return op->found;
215
 
}
216
 
 
217
 
/**
218
 
 * gcr_trust_is_certificate_pinned:
219
 
 * @certificate: a #GcrCertificate to check
220
 
 * @purpose: the purpose string
221
 
 * @peer: the peer for this pinned
222
 
 * @cancellable: a #GCancellable
223
 
 * @error: a #GError, or NULL
224
 
 *
225
 
 * Check if @certificate is pinned for @purpose to communicate with @peer.
226
 
 * A pinned certificate overrides all other certificate verification.
227
 
 *
228
 
 * This call may block, see gcr_trust_is_certificate_pinned_async() for the
229
 
 * non-blocking version.
230
 
 *
231
 
 * In the case of an error, %FALSE is also returned. Check @error to detect
232
 
 * if an error occurred.
233
 
 *
234
 
 * Returns: %TRUE if the certificate is pinned for the host and purpose
235
 
 */
236
 
gboolean
237
 
gcr_trust_is_certificate_pinned (GcrCertificate *certificate, const gchar *purpose,
238
 
                                 const gchar *peer, GCancellable *cancellable, GError **error)
239
 
{
240
 
        GckEnumerator *en;
241
 
        gboolean ret;
242
 
 
243
 
        g_return_val_if_fail (GCR_IS_CERTIFICATE (certificate), FALSE);
244
 
        g_return_val_if_fail (purpose, FALSE);
245
 
        g_return_val_if_fail (peer, FALSE);
246
 
 
247
 
        _gcr_initialize ();
248
 
 
249
 
        en = prepare_is_certificate_pinned (certificate, purpose, peer);
250
 
        g_return_val_if_fail (en, FALSE);
251
 
 
252
 
        ret = perform_is_certificate_pinned (en, cancellable, error);
253
 
 
254
 
        g_object_unref (en);
255
 
 
256
 
        return ret;
257
 
}
258
 
 
259
 
static void
260
 
thread_is_certificate_pinned (GSimpleAsyncResult *result, GObject *object, GCancellable *cancel)
261
 
{
262
 
        GError *error = NULL;
263
 
 
264
 
        perform_is_certificate_pinned (GCK_ENUMERATOR (object), cancel, &error);
265
 
 
266
 
        if (error != NULL) {
267
 
                g_simple_async_result_set_from_error (result, error);
268
 
                g_clear_error (&error);
269
 
        }
270
 
}
271
 
 
272
 
/**
273
 
 * gcr_trust_is_certificate_pinned_async:
274
 
 * @certificate: a #GcrCertificate to check
275
 
 * @purpose: the purpose string
276
 
 * @peer: the peer for this pinned
277
 
 * @cancellable: a #GCancellable
278
 
 * @callback: a #GAsyncReadyCallback to call when the operation completes
279
 
 * @user_data: the data to pass to callback function
280
 
 *
281
 
 * Check if @certificate is pinned for @purpose to communicate with @peer. A
282
 
 * pinned certificate overrides all other certificate verification.
283
 
 *
284
 
 * When the operation is finished, callback will be called. You can then call
285
 
 * gcr_trust_is_certificate_pinned_finish() to get the result of the
286
 
 * operation.
287
 
 */
288
 
void
289
 
gcr_trust_is_certificate_pinned_async (GcrCertificate *certificate, const gchar *purpose,
290
 
                                       const gchar *peer, GCancellable *cancellable,
291
 
                                       GAsyncReadyCallback callback, gpointer user_data)
292
 
{
293
 
        GSimpleAsyncResult *async;
294
 
        GckEnumerator *en;
295
 
 
296
 
        g_return_if_fail (GCR_CERTIFICATE (certificate));
297
 
        g_return_if_fail (purpose);
298
 
        g_return_if_fail (peer);
299
 
 
300
 
        _gcr_initialize ();
301
 
 
302
 
        en = prepare_is_certificate_pinned (certificate, purpose, peer);
303
 
        g_return_if_fail (en);
304
 
 
305
 
        async = g_simple_async_result_new (G_OBJECT (en), callback, user_data,
306
 
                                           gcr_trust_is_certificate_pinned_async);
307
 
 
308
 
        g_simple_async_result_run_in_thread (async, thread_is_certificate_pinned,
309
 
                                             G_PRIORITY_DEFAULT, cancellable);
310
 
 
311
 
        g_object_unref (async);
312
 
        g_object_unref (en);
313
 
}
314
 
 
315
 
/**
316
 
 * gcr_trust_is_certificate_pinned_finish:
317
 
 * @result: the #GAsyncResult passed to the callback
318
 
 * @error: a #GError, or NULL
319
 
 *
320
 
 * Finishes an asynchronous operation started by
321
 
 * gcr_trust_is_certificate_pinned_async().
322
 
 *
323
 
 * In the case of an error, %FALSE is also returned. Check @error to detect
324
 
 * if an error occurred.
325
 
 *
326
 
 * Returns: %TRUE if the certificate is pinned.
327
 
 */
328
 
gboolean
329
 
gcr_trust_is_certificate_pinned_finish (GAsyncResult *result, GError **error)
330
 
{
331
 
        GcrTrustOperation *op;
332
 
        GObject *object;
333
 
        gboolean found;
334
 
 
335
 
        g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), FALSE);
336
 
        g_return_val_if_fail (!error || !*error, FALSE);
337
 
 
338
 
        _gcr_initialize ();
339
 
 
340
 
        object = g_async_result_get_source_object (result);
341
 
        g_return_val_if_fail (g_simple_async_result_is_valid (result, object,
342
 
                              gcr_trust_is_certificate_pinned_async), FALSE);
343
 
 
344
 
        if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
345
 
                return FALSE;
346
 
 
347
 
        op = trust_operation_get (GCK_ENUMERATOR (object));
348
 
        found = op->found;
349
 
        g_object_unref (object);
350
 
        return found;
351
 
}
352
 
 
353
 
/* ----------------------------------------------------------------------------------
354
 
 * ADD PINNED CERTIFICATE
355
 
 */
356
 
 
357
 
static GckEnumerator*
358
 
prepare_add_pinned_certificate (GcrCertificate *certificate, const gchar *purpose, const gchar *peer)
359
 
{
360
 
        GckAttributes *attrs;
361
 
        GckEnumerator *en;
362
 
        GList *slots;
363
 
 
364
 
        attrs = prepare_trust_attrs (certificate, CKT_X_PINNED_CERTIFICATE);
365
 
        g_return_val_if_fail (attrs, NULL);
366
 
 
367
 
        gck_attributes_add_string (attrs, CKA_X_PURPOSE, purpose);
368
 
        gck_attributes_add_string (attrs, CKA_X_PEER, peer);
369
 
        gck_attributes_add_boolean (attrs, CKA_TOKEN, TRUE);
370
 
 
371
 
        slots = gcr_pkcs11_get_trust_lookup_slots ();
372
 
        en = gck_slots_enumerate_objects (slots, attrs, CKF_RW_SESSION);
373
 
        trust_operation_init (en, attrs);
374
 
        gck_attributes_unref (attrs);
375
 
        gck_list_unref_free (slots);
376
 
 
377
 
        return en;
378
 
}
379
 
 
380
 
static gboolean
381
 
perform_add_pinned_certificate (GckEnumerator *en, GCancellable *cancellable, GError **error)
382
 
{
383
 
        GcrTrustOperation *op;
384
 
        GckAttributes *attrs;
385
 
        gboolean ret = FALSE;
386
 
        GError *lerr = NULL;
387
 
        GckObject *object;
388
 
        GckSession *session;
389
 
        GckSlot *slot;
390
 
 
391
 
        op = trust_operation_get (en);
392
 
        g_assert (op != NULL);
393
 
 
394
 
        /* We need an error below */
395
 
        if (error && !*error)
396
 
                *error = lerr;
397
 
 
398
 
        object = gck_enumerator_next (en, cancellable, error);
399
 
        if (*error)
400
 
                return FALSE;
401
 
 
402
 
        /* It already exists */
403
 
        if (object) {
404
 
                g_object_unref (object);
405
 
                return TRUE;
406
 
        }
407
 
 
408
 
        attrs = gck_attributes_new ();
409
 
        gck_attributes_add_all (attrs, op->attrs);
410
 
 
411
 
        /* TODO: Add relevant label */
412
 
 
413
 
        /* Find an appropriate token */
414
 
        slot = gcr_pkcs11_get_trust_store_slot ();
415
 
        if (slot == NULL) {
416
 
                g_set_error (error, GCK_ERROR, CKR_FUNCTION_FAILED,
417
 
                             /* Translators: A pinned certificate is an exception which
418
 
                                trusts a given certificate explicitly for a purpose and
419
 
                                communication with a certain peer. */
420
 
                             _("Couldn't find a place to store the pinned certificate"));
421
 
                ret = FALSE;
422
 
        } else {
423
 
                session = gck_slot_open_session (slot, CKF_RW_SESSION, NULL, error);
424
 
                if (session != NULL) {
425
 
                        object = gck_session_create_object (session, attrs, cancellable, error);
426
 
                        if (object != NULL) {
427
 
                                g_object_unref (object);
428
 
                                ret = TRUE;
429
 
                        }
430
 
 
431
 
                        g_object_unref (session);
432
 
                }
433
 
 
434
 
                g_object_unref (slot);
435
 
        }
436
 
 
437
 
        gck_attributes_unref (attrs);
438
 
 
439
 
        /* Our own local error pointer */
440
 
        g_clear_error (&lerr);
441
 
 
442
 
        return ret;
443
 
}
444
 
 
445
 
/**
446
 
 * gcr_trust_add_pinned_certificate:
447
 
 * @certificate: a #GcrCertificate
448
 
 * @purpose: the purpose string
449
 
 * @peer: the peer for this pinned certificate
450
 
 * @cancellable: a #GCancellable
451
 
 * @error: a #GError, or NULL
452
 
 *
453
 
 * Add a pinned @certificate for connections to @peer for @purpose. A pinned
454
 
 * certificate overrides all other certificate verification and should be
455
 
 * used with care.
456
 
 *
457
 
 * If the same pinned certificate already exists, then this operation
458
 
 * does not add another, and succeeds without error.
459
 
 *
460
 
 * This call may block, see gcr_trust_add_pinned_certificate_async() for the
461
 
 * non-blocking version.
462
 
 *
463
 
 * Returns: %TRUE if the pinned certificate is recorded successfully
464
 
 */
465
 
gboolean
466
 
gcr_trust_add_pinned_certificate (GcrCertificate *certificate, const gchar *purpose, const gchar *peer,
467
 
                                  GCancellable *cancellable, GError **error)
468
 
{
469
 
        GckEnumerator *en;
470
 
        gboolean ret;
471
 
 
472
 
        g_return_val_if_fail (GCR_IS_CERTIFICATE (certificate), FALSE);
473
 
        g_return_val_if_fail (purpose, FALSE);
474
 
        g_return_val_if_fail (peer, FALSE);
475
 
 
476
 
        _gcr_initialize ();
477
 
 
478
 
        en = prepare_add_pinned_certificate (certificate, purpose, peer);
479
 
        g_return_val_if_fail (en, FALSE);
480
 
 
481
 
        ret = perform_add_pinned_certificate (en, cancellable, error);
482
 
 
483
 
        g_object_unref (en);
484
 
 
485
 
        return ret;
486
 
}
487
 
 
488
 
static void
489
 
thread_add_pinned_certificate (GSimpleAsyncResult *result, GObject *object, GCancellable *cancel)
490
 
{
491
 
        GError *error = NULL;
492
 
 
493
 
        perform_add_pinned_certificate (GCK_ENUMERATOR (object), cancel, &error);
494
 
 
495
 
        if (error != NULL) {
496
 
                g_simple_async_result_set_from_error (result, error);
497
 
                g_clear_error (&error);
498
 
        }
499
 
}
500
 
 
501
 
/**
502
 
 * gcr_trust_add_pinned_certificate_async:
503
 
 * @certificate: a #GcrCertificate
504
 
 * @purpose: the purpose string
505
 
 * @peer: the peer for this pinned certificate
506
 
 * @cancellable: a #GCancellable
507
 
 * @callback: a #GAsyncReadyCallback to call when the operation completes
508
 
 * @user_data: the data to pass to callback function
509
 
 *
510
 
 * Add a pinned certificate for communication with @peer for @purpose. A pinned
511
 
 * certificate overrides all other certificate verification and should be used
512
 
 * with care.
513
 
 *
514
 
 * If the same pinned certificate already exists, then this operation
515
 
 * does not add another, and succeeds without error.
516
 
 *
517
 
 * When the operation is finished, callback will be called. You can then call
518
 
 * gcr_trust_add_pinned_certificate_finish() to get the result of the
519
 
 * operation.
520
 
 */
521
 
void
522
 
gcr_trust_add_pinned_certificate_async (GcrCertificate *certificate, const gchar *purpose,
523
 
                                        const gchar *peer, GCancellable *cancellable,
524
 
                                        GAsyncReadyCallback callback, gpointer user_data)
525
 
{
526
 
        GSimpleAsyncResult *async;
527
 
        GckEnumerator *en;
528
 
 
529
 
        g_return_if_fail (GCR_IS_CERTIFICATE (certificate));
530
 
        g_return_if_fail (purpose);
531
 
        g_return_if_fail (peer);
532
 
 
533
 
        _gcr_initialize ();
534
 
 
535
 
        en = prepare_add_pinned_certificate (certificate, purpose, peer);
536
 
        g_return_if_fail (en);
537
 
 
538
 
        async = g_simple_async_result_new (G_OBJECT (en), callback, user_data,
539
 
                                           gcr_trust_add_pinned_certificate_async);
540
 
 
541
 
        g_simple_async_result_run_in_thread (async, thread_add_pinned_certificate,
542
 
                                             G_PRIORITY_DEFAULT, cancellable);
543
 
 
544
 
        g_object_unref (async);
545
 
        g_object_unref (en);
546
 
}
547
 
 
548
 
/**
549
 
 * gcr_trust_add_pinned_certificate_finish:
550
 
 * @result: the #GAsyncResult passed to the callback
551
 
 * @error: a #GError, or NULL
552
 
 *
553
 
 * Finishes an asynchronous operation started by
554
 
 * gcr_trust_add_pinned_certificate_async().
555
 
 *
556
 
 * Returns: %TRUE if the pinned certificate is recorded successfully
557
 
 */
558
 
gboolean
559
 
gcr_trust_add_pinned_certificate_finish (GAsyncResult *result, GError **error)
560
 
{
561
 
        GObject *object;
562
 
 
563
 
        g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), FALSE);
564
 
        g_return_val_if_fail (!error || !*error, FALSE);
565
 
 
566
 
        _gcr_initialize ();
567
 
 
568
 
        object = g_async_result_get_source_object (result);
569
 
        g_return_val_if_fail (g_simple_async_result_is_valid (result, object,
570
 
                              gcr_trust_add_pinned_certificate_async), FALSE);
571
 
        g_object_unref (object);
572
 
 
573
 
        if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
574
 
                return FALSE;
575
 
 
576
 
        return TRUE;
577
 
}
578
 
 
579
 
/* -----------------------------------------------------------------------
580
 
 * REMOVE PINNED CERTIFICATE
581
 
 */
582
 
 
583
 
static GckEnumerator*
584
 
prepare_remove_pinned_certificate (GcrCertificate *certificate, const gchar *purpose,
585
 
                                   const gchar *peer)
586
 
{
587
 
        GckAttributes *attrs;
588
 
        GckEnumerator *en;
589
 
        GList *slots;
590
 
 
591
 
        attrs = prepare_trust_attrs (certificate, CKT_X_PINNED_CERTIFICATE);
592
 
        g_return_val_if_fail (attrs, NULL);
593
 
 
594
 
        gck_attributes_add_string (attrs, CKA_X_PURPOSE, purpose);
595
 
        gck_attributes_add_string (attrs, CKA_X_PEER, peer);
596
 
 
597
 
        slots = gcr_pkcs11_get_trust_lookup_slots ();
598
 
        en = gck_slots_enumerate_objects (slots, attrs, CKF_RW_SESSION);
599
 
        trust_operation_init (en, attrs);
600
 
        gck_attributes_unref (attrs);
601
 
        gck_list_unref_free (slots);
602
 
 
603
 
        return en;
604
 
}
605
 
 
606
 
static gboolean
607
 
perform_remove_pinned_certificate (GckEnumerator *en, GCancellable *cancellable, GError **error)
608
 
{
609
 
        GcrTrustOperation *op;
610
 
        GList *objects, *l;
611
 
        GError *lerr = NULL;
612
 
 
613
 
        op = trust_operation_get (en);
614
 
        g_assert (op != NULL);
615
 
 
616
 
        /* We need an error below */
617
 
        if (error && !*error)
618
 
                *error = lerr;
619
 
 
620
 
        objects = gck_enumerator_next_n (en, -1, cancellable, error);
621
 
        if (*error)
622
 
                return FALSE;
623
 
 
624
 
        for (l = objects; l; l = g_list_next (l)) {
625
 
                if (!gck_object_destroy (l->data, cancellable, error)) {
626
 
 
627
 
                        /* In case there's a race condition */
628
 
                        if (g_error_matches (*error, GCK_ERROR, CKR_OBJECT_HANDLE_INVALID)) {
629
 
                                g_clear_error (error);
630
 
                                continue;
631
 
                        }
632
 
 
633
 
                        gck_list_unref_free (objects);
634
 
                        return FALSE;
635
 
                }
636
 
        }
637
 
 
638
 
        gck_list_unref_free (objects);
639
 
        return TRUE;
640
 
}
641
 
 
642
 
/**
643
 
 * gcr_trust_remove_pinned_certificate:
644
 
 * @certificate: a #GcrCertificate
645
 
 * @purpose: the purpose string
646
 
 * @peer: the peer for this pinned certificate
647
 
 * @cancellable: a #GCancellable
648
 
 * @error: a #GError, or NULL
649
 
 *
650
 
 * Remove a pinned certificate for communication with @peer for @purpose.
651
 
 *
652
 
 * If the same pinned certificate does not exist, or was already removed,
653
 
 * then this operation succeeds without error.
654
 
 *
655
 
 * This call may block, see gcr_trust_remove_pinned_certificate_async() for the
656
 
 * non-blocking version.
657
 
 *
658
 
 * Returns: %TRUE if the pinned certificate no longer exists
659
 
 */
660
 
gboolean
661
 
gcr_trust_remove_pinned_certificate (GcrCertificate *certificate, const gchar *purpose, const gchar *peer,
662
 
                                     GCancellable *cancellable, GError **error)
663
 
{
664
 
        GckEnumerator *en;
665
 
        gboolean ret;
666
 
 
667
 
        g_return_val_if_fail (GCR_IS_CERTIFICATE (certificate), FALSE);
668
 
        g_return_val_if_fail (purpose, FALSE);
669
 
        g_return_val_if_fail (peer, FALSE);
670
 
 
671
 
        _gcr_initialize ();
672
 
 
673
 
        en = prepare_remove_pinned_certificate (certificate, purpose, peer);
674
 
        g_return_val_if_fail (en, FALSE);
675
 
 
676
 
        ret = perform_remove_pinned_certificate (en, cancellable, error);
677
 
 
678
 
        g_object_unref (en);
679
 
 
680
 
        return ret;
681
 
}
682
 
 
683
 
static void
684
 
thread_remove_pinned_certificate (GSimpleAsyncResult *result, GObject *object, GCancellable *cancel)
685
 
{
686
 
        GError *error = NULL;
687
 
 
688
 
        perform_remove_pinned_certificate (GCK_ENUMERATOR (object), cancel, &error);
689
 
 
690
 
        if (error != NULL) {
691
 
                g_simple_async_result_set_from_error (result, error);
692
 
                g_clear_error (&error);
693
 
        }
694
 
}
695
 
 
696
 
/**
697
 
 * gcr_trust_remove_pinned_certificate_async:
698
 
 * @certificate: a #GcrCertificate
699
 
 * @purpose: the purpose string
700
 
 * @peer: the peer for this pinned certificate
701
 
 * @cancellable: a #GCancellable
702
 
 * @callback: a #GAsyncReadyCallback to call when the operation completes
703
 
 * @user_data: the data to pass to callback function
704
 
 *
705
 
 * Remove a pinned certificate for communication with @peer for @purpose.
706
 
 *
707
 
 * If the same pinned certificate does not exist, or was already removed,
708
 
 * then this operation succeeds without error.
709
 
 *
710
 
 * When the operation is finished, callback will be called. You can then call
711
 
 * gcr_trust_remove_pinned_certificate_finish() to get the result of the
712
 
 * operation.
713
 
 */
714
 
void
715
 
gcr_trust_remove_pinned_certificate_async (GcrCertificate *certificate, const gchar *purpose,
716
 
                                           const gchar *peer, GCancellable *cancellable,
717
 
                                           GAsyncReadyCallback callback, gpointer user_data)
718
 
{
719
 
        GSimpleAsyncResult *async;
720
 
        GckEnumerator *en;
721
 
 
722
 
        g_return_if_fail (GCR_IS_CERTIFICATE (certificate));
723
 
        g_return_if_fail (purpose);
724
 
        g_return_if_fail (peer);
725
 
 
726
 
        _gcr_initialize ();
727
 
 
728
 
        en = prepare_remove_pinned_certificate (certificate, purpose, peer);
729
 
        g_return_if_fail (en);
730
 
 
731
 
        async = g_simple_async_result_new (G_OBJECT (en), callback, user_data,
732
 
                                           gcr_trust_remove_pinned_certificate_async);
733
 
 
734
 
        g_simple_async_result_run_in_thread (async, thread_remove_pinned_certificate,
735
 
                                             G_PRIORITY_DEFAULT, cancellable);
736
 
 
737
 
        g_object_unref (async);
738
 
        g_object_unref (en);
739
 
}
740
 
 
741
 
/**
742
 
 * gcr_trust_remove_pinned_certificate_finish:
743
 
 * @result: the #GAsyncResult passed to the callback
744
 
 * @error: a #GError, or NULL
745
 
 *
746
 
 * Finishes an asynchronous operation started by
747
 
 * gcr_trust_remove_pinned_certificate_async().
748
 
 *
749
 
 * Returns: %TRUE if the pinned certificate no longer exists
750
 
 */
751
 
gboolean
752
 
gcr_trust_remove_pinned_certificate_finish (GAsyncResult *result, GError **error)
753
 
{
754
 
        GObject *object;
755
 
 
756
 
        g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), FALSE);
757
 
        g_return_val_if_fail (!error || !*error, FALSE);
758
 
 
759
 
        _gcr_initialize ();
760
 
 
761
 
        object = g_async_result_get_source_object (result);
762
 
        g_return_val_if_fail (g_simple_async_result_is_valid (result, object,
763
 
                              gcr_trust_remove_pinned_certificate_async), FALSE);
764
 
        g_object_unref (object);
765
 
 
766
 
        if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
767
 
                return FALSE;
768
 
 
769
 
        return TRUE;
770
 
}
771
 
 
772
 
/* ----------------------------------------------------------------------------------
773
 
 * CERTIFICATE ROOT
774
 
 */
775
 
 
776
 
static GckEnumerator*
777
 
prepare_is_certificate_anchored (GcrCertificate *certificate, const gchar *purpose)
778
 
{
779
 
        GckAttributes *attrs;
780
 
        GckEnumerator *en;
781
 
        GList *slots;
782
 
 
783
 
        attrs = prepare_trust_attrs (certificate, CKT_X_ANCHORED_CERTIFICATE);
784
 
        g_return_val_if_fail (attrs, NULL);
785
 
 
786
 
        gck_attributes_add_string (attrs, CKA_X_PURPOSE, purpose);
787
 
 
788
 
        slots = gcr_pkcs11_get_trust_lookup_slots ();
789
 
        en = gck_slots_enumerate_objects (slots, attrs, 0);
790
 
        trust_operation_init (en, attrs);
791
 
        gck_attributes_unref (attrs);
792
 
        gck_list_unref_free (slots);
793
 
 
794
 
        return en;
795
 
}
796
 
 
797
 
static gboolean
798
 
perform_is_certificate_anchored (GckEnumerator *en, GCancellable *cancellable, GError **error)
799
 
{
800
 
        GcrTrustOperation *op;
801
 
        GckObject *object;
802
 
 
803
 
        op = trust_operation_get (en);
804
 
        g_assert (op != NULL);
805
 
 
806
 
        object = gck_enumerator_next (en, cancellable, error);
807
 
        if (object != NULL) {
808
 
                op->found = TRUE;
809
 
                g_object_unref (object);
810
 
        } else {
811
 
                op->found = FALSE;
812
 
        }
813
 
 
814
 
        return op->found;
815
 
}
816
 
 
817
 
/**
818
 
 * gcr_trust_is_certificate_anchored:
819
 
 * @certificate: a #GcrCertificate to check
820
 
 * @purpose: the purpose string
821
 
 * @cancellable: a #GCancellable
822
 
 * @error: a #GError, or NULL
823
 
 *
824
 
 * Check if the @certificate is a trust anchor for the given @purpose. A trust
825
 
 * anchor is used to verify the signatures on other certificates when verifying
826
 
 * a certificate chain. Also known as a trusted certificate authority.
827
 
 *
828
 
 * This call may block, see gcr_trust_is_certificate_anchored_async() for the
829
 
 * non-blocking version.
830
 
 *
831
 
 * In the case of an error, %FALSE is also returned. Check @error to detect
832
 
 * if an error occurred.
833
 
 *
834
 
 * Returns: %TRUE if the certificate is a trust anchor
835
 
 */
836
 
gboolean
837
 
gcr_trust_is_certificate_anchored (GcrCertificate *certificate, const gchar *purpose,
838
 
                                   GCancellable *cancellable, GError **error)
839
 
{
840
 
        GckEnumerator *en;
841
 
        gboolean ret;
842
 
 
843
 
        g_return_val_if_fail (GCR_IS_CERTIFICATE (certificate), FALSE);
844
 
        g_return_val_if_fail (purpose, FALSE);
845
 
 
846
 
        _gcr_initialize ();
847
 
 
848
 
        en = prepare_is_certificate_anchored (certificate, purpose);
849
 
        g_return_val_if_fail (en, FALSE);
850
 
 
851
 
        ret = perform_is_certificate_anchored (en, cancellable, error);
852
 
 
853
 
        g_object_unref (en);
854
 
 
855
 
        return ret;
856
 
}
857
 
 
858
 
static void
859
 
thread_is_certificate_anchored (GSimpleAsyncResult *result, GObject *object, GCancellable *cancel)
860
 
{
861
 
        GError *error = NULL;
862
 
 
863
 
        perform_is_certificate_anchored (GCK_ENUMERATOR (object), cancel, &error);
864
 
 
865
 
        if (error != NULL) {
866
 
                g_simple_async_result_set_from_error (result, error);
867
 
                g_clear_error (&error);
868
 
        }
869
 
}
870
 
 
871
 
/**
872
 
 * gcr_trust_is_certificate_anchored_async:
873
 
 * @certificate: a #GcrCertificate to check
874
 
 * @purpose: the purpose string
875
 
 * @cancellable: a #GCancellable
876
 
 * @callback: a #GAsyncReadyCallback to call when the operation completes
877
 
 * @user_data: the data to pass to callback function
878
 
 *
879
 
 * Check if the @certificate is a trust anchor for the given @purpose. A trust
880
 
 * anchor is used to verify the signatures on other certificates when verifying
881
 
 * a certificate chain. Also known as a trusted certificate authority.
882
 
 *
883
 
 * When the operation is finished, callback will be called. You can then call
884
 
 * gcr_trust_is_certificate_anchored_finish() to get the result of the operation.
885
 
 */
886
 
void
887
 
gcr_trust_is_certificate_anchored_async (GcrCertificate *certificate, const gchar *purpose,
888
 
                                         GCancellable *cancellable, GAsyncReadyCallback callback,
889
 
                                         gpointer user_data)
890
 
{
891
 
        GSimpleAsyncResult *async;
892
 
        GckEnumerator *en;
893
 
 
894
 
        g_return_if_fail (GCR_IS_CERTIFICATE (certificate));
895
 
        g_return_if_fail (purpose);
896
 
 
897
 
        _gcr_initialize ();
898
 
 
899
 
        en = prepare_is_certificate_anchored (certificate, purpose);
900
 
        g_return_if_fail (en);
901
 
 
902
 
        async = g_simple_async_result_new (G_OBJECT (en), callback, user_data,
903
 
                                           gcr_trust_is_certificate_anchored_async);
904
 
 
905
 
        g_simple_async_result_run_in_thread (async, thread_is_certificate_anchored,
906
 
                                             G_PRIORITY_DEFAULT, cancellable);
907
 
 
908
 
        g_object_unref (async);
909
 
        g_object_unref (en);
910
 
}
911
 
 
912
 
/**
913
 
 * gcr_trust_is_certificate_anchored_finish:
914
 
 * @result: the #GAsyncResult passed to the callback
915
 
 * @error: a #GError, or NULL
916
 
 *
917
 
 * Finishes an asynchronous operation started by
918
 
 * gcr_trust_is_certificate_anchored_async().
919
 
 *
920
 
 * In the case of an error, %FALSE is also returned. Check @error to detect
921
 
 * if an error occurred.
922
 
 *
923
 
 * Returns: %TRUE if the certificate is a trust anchor
924
 
 */
925
 
gboolean
926
 
gcr_trust_is_certificate_anchored_finish (GAsyncResult *result, GError **error)
927
 
{
928
 
        GcrTrustOperation *op;
929
 
        GObject *object;
930
 
        gboolean found;
931
 
 
932
 
        g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
933
 
        g_return_val_if_fail (!error || !*error, FALSE);
934
 
 
935
 
        _gcr_initialize ();
936
 
 
937
 
        object = g_async_result_get_source_object (result);
938
 
        g_return_val_if_fail (g_simple_async_result_is_valid (result, object,
939
 
                              gcr_trust_is_certificate_anchored_async), FALSE);
940
 
 
941
 
        if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
942
 
                return FALSE;
943
 
 
944
 
        op = trust_operation_get (GCK_ENUMERATOR (object));
945
 
        found = op->found;
946
 
        g_object_unref (object);
947
 
        return found;
948
 
}