4
* Copyright (C) 2010 Collabora Ltd
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.
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.
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
21
* Author: Stef Walter <stefw@collabora.co.uk>
26
#include "gcr-certificate-chain.h"
28
#include "gcr-certificate.h"
29
#include "gcr-pkcs11-certificate.h"
30
#include "gcr-simple-certificate.h"
32
#include "gcr-trust.h"
35
* SECTION:gcr-certificate-chain
36
* @title: GcrCertificateChain
37
* @short_description: A certificate chain
39
* #GcrCertificateChain represents a chain of certificates, normally used to
40
* validate the trust in a certificate. An X.509 certificate chain has one
41
* endpoint certificate (the one for which trust is being verified) and then
42
* in turn the certificate that issued each previous certificate in the chain.
44
* This functionality is for building of certificate chains not for validating
45
* them. Use your favorite crypto library to validate trust in a certificate
46
* chain once its built.
48
* The order of certificates in the chain should be first the endpoint
49
* certificates and then the signing certificates.
51
* Create a new certificate chain with gcr_certificate_chain_new() and then
52
* add the certificates with gcr_certificate_chain_add().
54
* You can then use gcr_certificate_chain_build() to build the remainder of
55
* the chain. This will lookup missing certificates in PKCS\#11 modules and
56
* also check that each certificate in the chain is the signer of the previous
57
* one. If a trust anchor, pinned certificate, or self-signed certificate is
58
* found, then the chain is considered built. Any extra certificates are
59
* removed from the chain.
61
* Once the certificate chain has been built, you can access its status
62
* through gcr_certificate_chain_get_status(). The status signifies whether
63
* the chain is anchored on a trust root, self-signed, incomplete etc. See
64
* #GcrCertificateChainStatus for information on the various statuses.
66
* It's important to understand that the building of a certificate chain is
67
* merely the first step towards verifying trust in a certificate.
76
struct _GcrCertificateChainPrivate {
77
GPtrArray *certificates;
78
GcrCertificateChainStatus status;
80
/* Used in build operation */
86
static GQuark Q_ORIGINAL_CERT = 0;
87
static GQuark Q_OPERATION_DATA = 0;
89
G_DEFINE_TYPE (GcrCertificateChain, gcr_certificate_chain, G_TYPE_OBJECT);
91
/* -----------------------------------------------------------------------------
96
free_chain_private (gpointer data)
98
GcrCertificateChainPrivate *pv = data;
99
g_ptr_array_unref (pv->certificates);
100
g_free (pv->purpose);
102
g_slice_free (GcrCertificateChainPrivate, pv);
105
static GcrCertificateChainPrivate*
106
new_chain_private (void)
108
GcrCertificateChainPrivate *pv = g_slice_new0 (GcrCertificateChainPrivate);
109
pv->certificates = g_ptr_array_new_with_free_func (g_object_unref);
113
static GcrCertificateChainPrivate*
114
prep_chain_private (GcrCertificateChainPrivate *orig, const gchar *purpose,
115
const gchar *peer, guint flags)
117
GcrCertificateChainPrivate *pv;
118
GcrCertificate *certificate;
124
pv = new_chain_private ();
125
for (i = 0; i < orig->certificates->len; ++i) {
126
certificate = g_ptr_array_index (orig->certificates, i);
127
g_ptr_array_add (pv->certificates, g_object_ref (certificate));
130
pv->status = orig->status;
131
pv->purpose = g_strdup (purpose);
132
pv->peer = g_strdup (peer);
137
static GcrCertificateChainPrivate*
138
prep_chain_private_thread_safe (GcrCertificateChainPrivate *orig, const gchar *purpose,
139
const gchar *peer, guint flags)
141
GcrCertificateChainPrivate *pv;
142
GcrCertificate *certificate, *safe;
149
pv = prep_chain_private (orig, purpose, peer, flags);
151
for (i = 0; i < pv->certificates->len; ++i) {
152
certificate = g_ptr_array_index (pv->certificates, i);
154
/* We regard these types as thread safe */
155
if (GCR_IS_SIMPLE_CERTIFICATE (certificate) ||
156
GCR_IS_PKCS11_CERTIFICATE (certificate)) {
157
safe = g_object_ref (certificate);
159
/* Otherwise copy the certificate data */
161
der = gcr_certificate_get_der_data (certificate, &n_der);
162
g_return_val_if_fail (der, NULL);
163
safe = gcr_simple_certificate_new (der, n_der);
165
/* Always set the original certificate onto the safe one */
166
g_object_set_qdata_full (G_OBJECT (safe), Q_ORIGINAL_CERT,
167
g_object_ref (certificate), g_object_unref);
170
g_ptr_array_index (pv->certificates, i) = safe;
171
g_object_unref (certificate);
177
static GcrCertificateChainPrivate*
178
cleanup_chain_private (GcrCertificateChainPrivate *pv)
180
GcrCertificate *certificate, *orig;
183
for (i = 0; i < pv->certificates->len; ++i) {
184
certificate = g_ptr_array_index (pv->certificates, i);
186
/* If there's an original certificate set, then replace it back */
187
orig = g_object_get_qdata (G_OBJECT (certificate), Q_ORIGINAL_CERT);
189
g_ptr_array_index (pv->certificates, i) = g_object_ref (orig);
190
g_object_unref (certificate);
198
perform_build_chain (GcrCertificateChainPrivate *pv, GCancellable *cancellable,
201
GError *error = NULL;
202
GcrCertificate *certificate;
208
g_assert (pv->certificates);
210
pv->status = GCR_CERTIFICATE_CHAIN_UNKNOWN;
211
lookups = !((pv->flags & GCR_CERTIFICATE_CHAIN_FLAG_NO_LOOKUPS) == GCR_CERTIFICATE_CHAIN_FLAG_NO_LOOKUPS);
213
/* This chain is built */
214
if (!pv->certificates->len)
217
/* First check for pinned certificates */
218
certificate = g_ptr_array_index (pv->certificates, 0);
219
if (lookups && pv->peer) {
220
ret = gcr_trust_is_certificate_pinned (certificate, pv->purpose,
221
pv->peer, cancellable, &error);
223
g_propagate_error (rerror, error);
228
* This is a pinned certificate and the rest of the chain
229
* is irrelevant, so truncate chain and consider built.
232
g_ptr_array_set_size (pv->certificates, 1);
233
pv->status = GCR_CERTIFICATE_CHAIN_PINNED;
240
/* The first certificate is always unconditionally in the chain */
241
while (pv->status == GCR_CERTIFICATE_CHAIN_UNKNOWN) {
243
/* Stop the chain if previous was self-signed */
244
if (gcr_certificate_is_issuer (certificate, certificate)) {
245
pv->status = GCR_CERTIFICATE_CHAIN_SELFSIGNED;
249
/* Try the next certificate in the chain */
250
if (length < pv->certificates->len) {
251
certificate = g_ptr_array_index (pv->certificates, length);
253
/* No more in chain, try to lookup */
254
} else if (lookups) {
255
certificate = gcr_pkcs11_certificate_lookup_issuer (certificate,
256
cancellable, &error);
258
g_propagate_error (rerror, error);
260
} else if (certificate) {
261
g_ptr_array_add (pv->certificates, certificate);
264
/* No more in chain, and can't lookup */
269
/* Stop the chain if nothing found */
270
if (certificate == NULL) {
271
pv->status = GCR_CERTIFICATE_CHAIN_INCOMPLETE;
277
/* See if this certificate is an anchor */
279
ret = gcr_trust_is_certificate_anchored (certificate, pv->purpose,
280
cancellable, &error);
283
g_propagate_error (rerror, error);
286
/* Stop the chain at the first anchor */
288
pv->status = GCR_CERTIFICATE_CHAIN_ANCHORED;
294
/* TODO: Need to check each certificate in the chain for distrusted */
296
/* Truncate to the appropriate length */
297
g_assert (length <= pv->certificates->len);
298
g_ptr_array_set_size (pv->certificates, length);
303
thread_build_chain (GSimpleAsyncResult *result, GObject *object,
304
GCancellable *cancellable)
306
GcrCertificateChainPrivate *pv;
307
GError *error = NULL;
309
pv = g_object_get_qdata (G_OBJECT (result), Q_OPERATION_DATA);
312
if (!perform_build_chain (pv, cancellable, &error)) {
313
g_simple_async_result_set_from_error (result, error);
314
g_clear_error (&error);
318
/* -----------------------------------------------------------------------------
323
gcr_certificate_chain_init (GcrCertificateChain *self)
325
self->pv = new_chain_private ();
329
gcr_certificate_chain_dispose (GObject *obj)
331
GcrCertificateChain *self = GCR_CERTIFICATE_CHAIN (obj);
333
g_ptr_array_set_size (self->pv->certificates, 0);
334
self->pv->status = GCR_CERTIFICATE_CHAIN_UNKNOWN;
336
G_OBJECT_CLASS (gcr_certificate_chain_parent_class)->dispose (obj);
340
gcr_certificate_chain_finalize (GObject *obj)
342
GcrCertificateChain *self = GCR_CERTIFICATE_CHAIN (obj);
344
free_chain_private (self->pv);
347
G_OBJECT_CLASS (gcr_certificate_chain_parent_class)->finalize (obj);
351
gcr_certificate_chain_get_property (GObject *obj, guint prop_id, GValue *value,
354
GcrCertificateChain *self = GCR_CERTIFICATE_CHAIN (obj);
358
g_value_set_enum (value, gcr_certificate_chain_get_status (self));
361
g_value_set_uint (value, gcr_certificate_chain_get_length (self));
364
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
370
gcr_certificate_chain_class_init (GcrCertificateChainClass *klass)
372
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
374
gcr_certificate_chain_parent_class = g_type_class_peek_parent (klass);
376
gobject_class->dispose = gcr_certificate_chain_dispose;
377
gobject_class->finalize = gcr_certificate_chain_finalize;
378
gobject_class->get_property = gcr_certificate_chain_get_property;
381
* GcrCertificateChain:status:
383
* The certificate chain status. See #GcrCertificateChainStatus
385
g_object_class_install_property (gobject_class, PROP_STATUS,
386
g_param_spec_enum ("status", "Status", "Status of certificate chain",
387
GCR_TYPE_CERTIFICATE_CHAIN_STATUS,
388
GCR_CERTIFICATE_CHAIN_UNKNOWN, G_PARAM_READABLE));
391
* GcrCertificateChain:length:
393
* The length of the certificate chain.
395
g_object_class_install_property (gobject_class, PROP_LENGTH,
396
g_param_spec_uint ("length", "Length", "Length of certificate chain",
397
0, G_MAXUINT, 0, G_PARAM_READABLE));
399
Q_ORIGINAL_CERT = g_quark_from_static_string ("gcr-certificate-chain-original-cert");
400
Q_OPERATION_DATA = g_quark_from_static_string ("gcr-certificate-chain-operation-data");
403
/* -----------------------------------------------------------------------------
408
* GcrCertificateChainStatus:
409
* @GCR_CERTIFICATE_CHAIN_UNKNOWN: The certificate chain's status is unknown.
410
* When a chain is not yet built it has this status. If a chain is modified after
411
* being built, it has this status.
412
* @GCR_CERTIFICATE_CHAIN_INCOMPLETE: A full chain could not be loaded. The
413
* chain does not end with a self-signed certificate, a trusted anchor, or a
414
* pinned certificate.
415
* @GCR_CERTIFICATE_CHAIN_SELFSIGNED: The chain ends with a self-signed
416
* certificate. No trust anchor was found.
417
* @GCR_CERTIFICATE_CHAIN_DISTRUSTED: The certificate chain contains a revoked
418
* or otherwise explicitly distrusted certificate. The entire chain should
420
* @GCR_CERTIFICATE_CHAIN_ANCHORED: The chain ends with an anchored
421
* certificate. The anchored certificate is not necessarily self-signed.
422
* @GCR_CERTIFICATE_CHAIN_PINNED: The chain represents a pinned certificate. A
423
* pinned certificate is an exception which trusts a given certificate
424
* explicitly for a purpose and communication with a certain peer.
426
* The status of a built certificate chain. Will be set to
427
* %GCR_CERTIFICATE_CHAIN_UNKNOWN for certificate chains that have not been
432
gcr_certificate_chain_status_get_type (void)
434
static volatile gsize initialized = 0;
435
static GType type = 0;
436
static const GEnumValue values[] = {
437
{ GCR_CERTIFICATE_CHAIN_UNKNOWN, "GCR_CERTIFICATE_CHAIN_UNKNOWN", "unknown" },
438
{ GCR_CERTIFICATE_CHAIN_INCOMPLETE, "GCR_CERTIFICATE_CHAIN_INCOMPLETE", "incomplete" },
439
{ GCR_CERTIFICATE_CHAIN_DISTRUSTED, "GCR_CERTIFICATE_CHAIN_DISTRUSTED", "distrusted" },
440
{ GCR_CERTIFICATE_CHAIN_SELFSIGNED, "GCR_CERTIFICATE_CHAIN_SELFSIGNED", "self-signed" },
441
{ GCR_CERTIFICATE_CHAIN_PINNED, "GCR_CERTIFICATE_CHAIN_PINNED", "pinned" },
442
{ GCR_CERTIFICATE_CHAIN_ANCHORED, "GCR_CERTIFICATE_CHAIN_ANCHORED", "anchored" },
446
if (g_once_init_enter (&initialized)) {
447
type = g_enum_register_static ("GcrCertificateChainStatus", values);
448
g_once_init_leave (&initialized, 1);
455
* GcrCertificateChainFlags:
456
* @GCR_CERTIFICATE_CHAIN_FLAG_NO_LOOKUPS: If this flag is specified then no
457
* lookups for anchors or pinned certificates are done, and the resulting chain
458
* will be neither anchored or pinned. Additionally no missing certificate
459
* authorities are looked up in PKCS\#11.
461
* Flags to be used with the gcr_certificate_chain_build() operation.
465
gcr_certificate_chain_flags_get_type (void)
467
static volatile gsize initialized = 0;
468
static GType type = 0;
469
static const GFlagsValue values[] = {
470
{ GCR_CERTIFICATE_CHAIN_FLAG_NO_LOOKUPS, "GCR_CERTIFICATE_CHAIN_FLAG_NO_LOOKUPS", "no-lookups" },
474
if (g_once_init_enter (&initialized)) {
475
type = g_flags_register_static ("GcrCertificateChainFlags", values);
476
g_once_init_leave (&initialized, 1);
483
* gcr_certificate_chain_new:
485
* Create a new #GcrCertificateChain.
487
* Returns: A newly allocated #GcrCertificateChain
490
gcr_certificate_chain_new (void)
492
return g_object_new (GCR_TYPE_CERTIFICATE_CHAIN, NULL);
496
* gcr_certificate_chain_add:
497
* @self: the #GcrCertificateChain
498
* @certificate: a #GcrCertificate to add to the chain
500
* Add @certificate to the chain. The order of certificates in the chain are
501
* important. The first certificate should be the endpoint certificate, and
502
* then come the signers (certificate authorities) each in turn. If a root
503
* certificate authority is present, it should come last.
505
* Adding a certificate an already built chain (see
506
* gcr_certificate_chain_build()) resets the type of the certificate chain
507
* to %GCR_CERTIFICATE_CHAIN_UNKNOWN
510
gcr_certificate_chain_add (GcrCertificateChain *self, GcrCertificate *certificate)
512
g_return_if_fail (GCR_IS_CERTIFICATE_CHAIN (self));
513
g_return_if_fail (GCR_IS_CERTIFICATE (certificate));
514
g_ptr_array_add (self->pv->certificates, g_object_ref (certificate));
515
self->pv->status = GCR_CERTIFICATE_CHAIN_UNKNOWN;
516
g_object_notify (G_OBJECT (self), "status");
517
g_object_notify (G_OBJECT (self), "length");
521
* gcr_certificate_chain_get_status:
522
* @self: the #GcrCertificateChain
524
* Get the status of a certificate chain. If the certificate chain has not
525
* been built, then the status will be %GCR_CERTIFICATE_CHAIN_UNKNOWN.
527
* A status of %GCR_CERTIFICATE_CHAIN_ANCHORED does not mean that the
528
* certificate chain has been verified, but merely that an anchor has been
531
* Returns: the status of the certificate chain.
533
GcrCertificateChainStatus
534
gcr_certificate_chain_get_status (GcrCertificateChain *self)
536
g_return_val_if_fail (GCR_IS_CERTIFICATE_CHAIN (self), GCR_CERTIFICATE_CHAIN_UNKNOWN);
537
return self->pv->status;
541
* gcr_certificate_chain_get_anchor:
542
* @self: the #GcrCertificateChain
544
* If the certificate chain has been built and is of status
545
* %GCR_CERTIFICATE_CHAIN_ANCHORED, then this will return the anchor
546
* certificate that was found. This is not necessarily a root certificate
547
* authority. If an intermediate certificate authority in the chain was
548
* found to be anchored, then that certificate will be returned.
550
* If an anchor is returned it does not mean that the certificate chain has
551
* been verified, but merely that an anchor has been found.
553
* Returns: the anchor certificate, or NULL if not anchored.
556
gcr_certificate_chain_get_anchor (GcrCertificateChain *self)
558
g_return_val_if_fail (GCR_IS_CERTIFICATE_CHAIN (self), NULL);
559
if (self->pv->status != GCR_CERTIFICATE_CHAIN_ANCHORED)
561
g_assert (self->pv->certificates->len > 0);
562
return GCR_CERTIFICATE (g_ptr_array_index (self->pv->certificates,
563
self->pv->certificates->len - 1));
567
* gcr_certificate_chain_get_endpoint:
568
* @self: the #GcrCertificateChain
570
* Get the endpoint certificate in the chain. This is always the first
571
* certificate in the chain. The endpoint certificate cannot be anchored.
573
* Returns: the endpoint certificate, or NULL if the chain is empty.
576
gcr_certificate_chain_get_endpoint (GcrCertificateChain *self)
578
g_return_val_if_fail (GCR_IS_CERTIFICATE_CHAIN (self), NULL);
579
if (!self->pv->certificates->len)
581
return GCR_CERTIFICATE (g_ptr_array_index (self->pv->certificates, 0));
585
* gcr_certificate_chain_get_length:
586
* @self: the #GcrCertificateChain
588
* Get the length of the certificate chain.
590
* Returns: the length of the certificate chain
593
gcr_certificate_chain_get_length (GcrCertificateChain *self)
595
g_return_val_if_fail (GCR_IS_CERTIFICATE_CHAIN (self), 0);
596
return self->pv->certificates->len;
600
* gcr_certificate_chain_get_certificate:
601
* @self: the #GcrCertificateChain
602
* @index: index of the certificate to get
604
* Get a certificate in the chain. It is an error to call this function
605
* with an invalid index.
607
* Returns: the certificate
610
gcr_certificate_chain_get_certificate (GcrCertificateChain *self, guint index)
612
g_return_val_if_fail (GCR_IS_CERTIFICATE_CHAIN (self), NULL);
613
g_return_val_if_fail (index < self->pv->certificates->len, NULL);
614
return GCR_CERTIFICATE (g_ptr_array_index (self->pv->certificates, index));
618
* gcr_certificate_chain_build:
619
* @self: the #GcrCertificateChain
620
* @purpose: the purpose the certificate chain will be used for
621
* @peer: the peer the certificate chain will be used with, or NULL
622
* @flags: chain completion flags
623
* @cancellable: a #GCancellable or %NULL
624
* @error: a #GError or %NULL
626
* Complete a certificate chain. Once a certificate chain has been built
627
* its status can be examined.
629
* This operation will lookup missing certificates in PKCS\#11
630
* modules and also that each certificate in the chain is the signer of the
631
* previous one. If a trust anchor, pinned certificate, or self-signed certificate
632
* is found, then the chain is considered built. Any extra certificates are
633
* removed from the chain.
635
* It's important to understand that building of a certificate chain does not
636
* constitute verifying that chain. This is merely the first step towards
637
* trust verification.
639
* The @purpose is a string like %GCR_PURPOSE_CLIENT_AUTH and is the purpose
640
* for which the certificate chain will be used. Trust anchors are looked up
641
* for this purpose. This argument is required.
643
* The @peer is usually the host name of the peer whith which this certificate
644
* chain is being used. It is used to look up pinned certificates that have
645
* been stored for this peer. If %NULL then no pinned certificates will
648
* If the %GCR_CERTIFICATE_CHAIN_FLAG_NO_LOOKUPS flag is specified then no
649
* lookups for anchors or pinned certificates are done, and the resulting chain
650
* will be neither anchored or pinned. Additionally no missing certificate
651
* authorities are looked up in PKCS\#11
653
* This call will block, see gcr_certificate_chain_build_async() for the
654
* asynchronous version.
656
* Returns: whether the operation completed successfully
659
gcr_certificate_chain_build (GcrCertificateChain *self, const gchar *purpose,
660
const gchar *peer, guint flags,
661
GCancellable *cancellable, GError **error)
663
GcrCertificateChainPrivate *pv;
666
g_return_val_if_fail (GCR_IS_CERTIFICATE_CHAIN (self), FALSE);
667
g_return_val_if_fail (purpose, FALSE);
669
pv = prep_chain_private (self->pv, purpose, peer, flags);
671
ret = perform_build_chain (pv, cancellable, error);
674
free_chain_private (self->pv);
675
self->pv = cleanup_chain_private (pv);
676
g_object_notify (G_OBJECT (self), "status");
677
g_object_notify (G_OBJECT (self), "length");
679
free_chain_private (pv);
686
* gcr_certificate_chain_build_async:
687
* @self: the #GcrCertificateChain
688
* @purpose: the purpose the certificate chain will be used for
689
* @peer: the peer the certificate chain will be used with, or NULL
690
* @flags: chain completion flags
691
* @cancellable: a #GCancellable or %NULL
692
* @callback: this will be called when the operation completes.
693
* @user_data: data to pass to the callback
695
* Complete a certificate chain. Once a certificate chain has been built
696
* its status can be examined.
698
* This will lookup missing certificates in PKCS\#11
699
* modules and also that each certificate in the chain is the signer of the
700
* previous one. If a trust anchor, pinned certificate, or self-signed certificate
701
* is found, then the chain is considered built. Any extra certificates are
702
* removed from the chain.
704
* It's important to understand that building of a certificate chain does not
705
* constitute verifying that chain. This is merely the first step towards
706
* trust verification.
708
* The @purpose is a string like %GCR_PURPOSE_CLIENT_AUTH and is the purpose
709
* for which the certificate chain will be used. Trust anchors are looked up
710
* for this purpose. This argument is required.
712
* The @peer is usually the host name of the peer whith which this certificate
713
* chain is being used. It is used to look up pinned certificates that have
714
* been stored for this peer. If %NULL then no pinned certificates will
717
* If the %GCR_CERTIFICATE_CHAIN_FLAG_NO_LOOKUPS flag is specified then no
718
* lookups for anchors or pinned certificates are done, and the resulting chain
719
* will be neither anchored or pinned. Additionally no missing certificate
720
* authorities are looked up in PKCS\#11
722
* When the operation is finished, @callback will be called. You can then call
723
* gcr_certificate_chain_build_finish() to get the result of the operation.
726
gcr_certificate_chain_build_async (GcrCertificateChain *self, const gchar *purpose,
727
const gchar *peer, guint flags,
728
GCancellable *cancellable, GAsyncReadyCallback callback,
731
GcrCertificateChainPrivate *pv;
732
GSimpleAsyncResult *result;
734
g_return_if_fail (GCR_IS_CERTIFICATE_CHAIN (self));
736
g_return_if_fail (GCR_IS_CERTIFICATE_CHAIN (self));
737
g_return_if_fail (purpose);
739
pv = prep_chain_private_thread_safe (self->pv, purpose, peer, flags);
741
result = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
742
gcr_certificate_chain_build_async);
743
g_object_set_qdata_full (G_OBJECT (result), Q_OPERATION_DATA, pv, free_chain_private);
745
g_simple_async_result_run_in_thread (result, thread_build_chain,
746
G_PRIORITY_DEFAULT, cancellable);
747
g_object_unref (result);
751
* gcr_certificate_chain_build_finish:
752
* @self: the #GcrCertificateChain
753
* @result: the #GAsyncResult passed to the callback
754
* @error: a #GError, or NULL
756
* Finishes an asynchronous operation started by
757
* gcr_certificate_chain_build_async().
759
* Returns: whether the operation succeeded
762
gcr_certificate_chain_build_finish (GcrCertificateChain *self, GAsyncResult *result,
765
GcrCertificateChainPrivate *pv;
767
g_return_val_if_fail (GCR_IS_CERTIFICATE_CHAIN (self), FALSE);
768
g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
769
g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
770
gcr_certificate_chain_build_async), FALSE);
772
if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
775
pv = g_object_steal_qdata (G_OBJECT (result), Q_OPERATION_DATA);
776
g_return_val_if_fail (pv, FALSE);
778
free_chain_private (self->pv);
779
self->pv = cleanup_chain_private (pv);
781
g_object_notify (G_OBJECT (self), "status");
782
g_object_notify (G_OBJECT (self), "length");