1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
3 * GIO - GLib Input, Output and Streaming Library
5 * Copyright 2009 Red Hat, Inc
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General
18 * Public License along with this library; if not, see
19 * <http://www.gnu.org/licenses/>.
21 * In addition, when the library is used with OpenSSL, a special
22 * exception applies. Refer to the LICENSE_EXCEPTION file for details.
27 #include <gnutls/gnutls.h>
28 #include <gnutls/x509.h>
31 #include "gtlscertificate-gnutls.h"
32 #include <glib/gi18n-lib.h>
44 PROP_PRIVATE_KEY_PKCS11_URI,
45 PROP_NOT_VALID_BEFORE,
53 struct _GTlsCertificateGnutls
55 GTlsCertificate parent_instance;
57 gnutls_x509_crt_t cert;
61 gchar *private_key_pkcs11_uri;
63 GTlsCertificateGnutls *issuer;
65 GError *construct_error;
71 static void g_tls_certificate_gnutls_initable_iface_init (GInitableIface *iface);
73 G_DEFINE_TYPE_WITH_CODE (GTlsCertificateGnutls, g_tls_certificate_gnutls, G_TYPE_TLS_CERTIFICATE,
74 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
75 g_tls_certificate_gnutls_initable_iface_init);)
78 g_tls_certificate_gnutls_finalize (GObject *object)
80 GTlsCertificateGnutls *gnutls = G_TLS_CERTIFICATE_GNUTLS (object);
82 g_clear_pointer (&gnutls->cert, gnutls_x509_crt_deinit);
83 g_clear_pointer (&gnutls->key, gnutls_privkey_deinit);
85 g_clear_pointer (&gnutls->pkcs11_uri, g_free);
86 g_clear_pointer (&gnutls->private_key_pkcs11_uri, g_free);
88 g_clear_object (&gnutls->issuer);
90 g_clear_error (&gnutls->construct_error);
92 G_OBJECT_CLASS (g_tls_certificate_gnutls_parent_class)->finalize (object);
96 get_subject_alt_names (GTlsCertificateGnutls *cert,
97 gnutls_x509_subject_alt_name_t type)
99 GPtrArray *data = NULL;
107 if (type == GNUTLS_SAN_IPADDRESS)
108 data = g_ptr_array_new_with_free_func (g_object_unref);
110 data = g_ptr_array_new_with_free_func ((GDestroyNotify)g_bytes_unref);
116 status = gnutls_x509_crt_get_subject_alt_name2 (cert->cert, i, san, &san_size, &san_type, &critical);
117 if (status == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
119 else if (san_type != (guint)type)
125 san = g_malloc (san_size);
126 status = gnutls_x509_crt_get_subject_alt_name2 (cert->cert, i, san, &san_size, &san_type, &critical);
127 if (status == (guint)type)
129 if (status == (guint)GNUTLS_SAN_IPADDRESS)
132 g_ptr_array_add (data, g_inet_address_new_from_bytes (san, G_SOCKET_FAMILY_IPV4));
133 else if (san_size == 16)
134 g_ptr_array_add (data, g_inet_address_new_from_bytes (san, G_SOCKET_FAMILY_IPV6));
138 g_assert (status == (guint)GNUTLS_SAN_DNSNAME);
139 g_ptr_array_add (data, g_bytes_new (san, san_size));
150 export_privkey (GTlsCertificateGnutls *gnutls,
151 gnutls_x509_crt_fmt_t format,
155 gnutls_x509_privkey_t x509_privkey = NULL;
161 status = gnutls_privkey_export_x509 (gnutls->key, &x509_privkey);
166 status = gnutls_x509_privkey_export_pkcs8 (x509_privkey,
168 NULL, GNUTLS_PKCS_PLAIN,
170 if (status != GNUTLS_E_SHORT_MEMORY_BUFFER)
173 *output_data = g_malloc (*output_size);
174 status = gnutls_x509_privkey_export_pkcs8 (x509_privkey,
176 NULL, GNUTLS_PKCS_PLAIN,
177 *output_data, output_size);
180 gnutls_x509_privkey_deinit (x509_privkey);
184 g_free (*output_data);
191 gnutls_x509_privkey_deinit (x509_privkey);
195 g_tls_certificate_gnutls_get_property (GObject *object,
200 GTlsCertificateGnutls *gnutls = G_TLS_CERTIFICATE_GNUTLS (object);
201 GByteArray *byte_array;
212 case PROP_CERTIFICATE:
214 status = gnutls_x509_crt_export (gnutls->cert,
217 if (status != GNUTLS_E_SHORT_MEMORY_BUFFER)
221 byte_array = g_byte_array_sized_new (size);
222 byte_array->len = size;
223 status = gnutls_x509_crt_export (gnutls->cert,
225 byte_array->data, &size);
228 g_byte_array_free (byte_array, TRUE);
232 g_value_take_boxed (value, byte_array);
235 case PROP_CERTIFICATE_PEM:
237 status = gnutls_x509_crt_export (gnutls->cert,
240 if (status != GNUTLS_E_SHORT_MEMORY_BUFFER)
244 pem = g_malloc (size);
245 status = gnutls_x509_crt_export (gnutls->cert,
249 g_clear_pointer (&pem, g_free);
251 g_value_take_string (value, pem);
254 case PROP_PRIVATE_KEY:
255 export_privkey (gnutls, GNUTLS_X509_FMT_DER, (void **)&der, &size);
256 if (size > 0 && size <= G_MAXUINT)
258 byte_array = g_byte_array_new_take (der, size);
259 g_value_take_boxed (value, byte_array);
263 case PROP_PRIVATE_KEY_PEM:
264 export_privkey (gnutls, GNUTLS_X509_FMT_PEM, (void **)&pem, &size);
266 g_value_take_string (value, pem);
270 g_value_set_object (value, gnutls->issuer);
273 case PROP_PKCS11_URI:
274 g_value_set_string (value, gnutls->pkcs11_uri);
277 case PROP_PRIVATE_KEY_PKCS11_URI:
278 g_value_set_string (value, gnutls->private_key_pkcs11_uri);
281 case PROP_NOT_VALID_BEFORE:
282 time = gnutls_x509_crt_get_activation_time (gnutls->cert);
283 if (time != (time_t)-1)
284 g_value_take_boxed (value, g_date_time_new_from_unix_utc (time));
287 case PROP_NOT_VALID_AFTER:
288 time = gnutls_x509_crt_get_expiration_time (gnutls->cert);
289 if (time != (time_t)-1)
290 g_value_take_boxed (value, g_date_time_new_from_unix_utc (time));
293 case PROP_SUBJECT_NAME:
294 status = gnutls_x509_crt_get_subject (gnutls->cert, &dn);
295 if (status != GNUTLS_E_SUCCESS)
298 status = gnutls_x509_dn_get_str (dn, &data);
299 if (status != GNUTLS_E_SUCCESS)
302 g_value_take_string (value, g_strndup ((gchar *)data.data, data.size));
303 gnutls_free (data.data);
306 case PROP_ISSUER_NAME:
307 status = gnutls_x509_crt_get_issuer (gnutls->cert, &dn);
308 if (status != GNUTLS_E_SUCCESS)
311 status = gnutls_x509_dn_get_str (dn, &data);
312 if (status != GNUTLS_E_SUCCESS)
315 g_value_take_string (value, g_strndup ((gchar *)data.data, data.size));
316 gnutls_free (data.data);
320 g_value_take_boxed (value, get_subject_alt_names (gnutls, GNUTLS_SAN_DNSNAME));
323 case PROP_IP_ADDRESSES:
324 g_value_take_boxed (value, get_subject_alt_names (gnutls, GNUTLS_SAN_IPADDRESS));
328 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
333 g_tls_certificate_gnutls_set_property (GObject *object,
338 GTlsCertificateGnutls *gnutls = G_TLS_CERTIFICATE_GNUTLS (object);
346 case PROP_CERTIFICATE:
347 bytes = g_value_get_boxed (value);
350 g_return_if_fail (gnutls->have_cert == FALSE);
351 data.data = bytes->data;
352 data.size = bytes->len;
353 status = gnutls_x509_crt_import (gnutls->cert, &data,
354 GNUTLS_X509_FMT_DER);
356 gnutls->have_cert = TRUE;
357 else if (!gnutls->construct_error)
359 gnutls->construct_error =
360 g_error_new (G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
361 _("Could not parse DER certificate: %s"),
362 gnutls_strerror (status));
367 case PROP_CERTIFICATE_PEM:
368 string = g_value_get_string (value);
371 g_return_if_fail (gnutls->have_cert == FALSE);
372 data.data = (void *)string;
373 data.size = strlen (string);
374 status = gnutls_x509_crt_import (gnutls->cert, &data,
375 GNUTLS_X509_FMT_PEM);
377 gnutls->have_cert = TRUE;
378 else if (!gnutls->construct_error)
380 gnutls->construct_error =
381 g_error_new (G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
382 _("Could not parse PEM certificate: %s"),
383 gnutls_strerror (status));
387 case PROP_PRIVATE_KEY:
388 bytes = g_value_get_boxed (value);
391 g_return_if_fail (gnutls->have_key == FALSE);
392 data.data = bytes->data;
393 data.size = bytes->len;
395 gnutls_privkey_init (&gnutls->key);
396 status = gnutls_privkey_import_x509_raw (gnutls->key, &data,
398 NULL, GNUTLS_PKCS_PLAIN);
400 gnutls->have_key = TRUE;
401 else if (!gnutls->construct_error)
403 gnutls->construct_error =
404 g_error_new (G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
405 _("Could not parse DER private key: %s"),
406 gnutls_strerror (status));
410 case PROP_PRIVATE_KEY_PEM:
411 string = g_value_get_string (value);
414 g_return_if_fail (gnutls->have_key == FALSE);
415 data.data = (void *)string;
416 data.size = strlen (string);
418 gnutls_privkey_init (&gnutls->key);
419 status = gnutls_privkey_import_x509_raw (gnutls->key, &data,
421 NULL, GNUTLS_PKCS_PLAIN);
423 gnutls->have_key = TRUE;
424 else if (!gnutls->construct_error)
426 gnutls->construct_error =
427 g_error_new (G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
428 _("Could not parse PEM private key: %s"),
429 gnutls_strerror (status));
434 gnutls->issuer = g_value_dup_object (value);
437 case PROP_PKCS11_URI:
438 string = g_value_get_string (value);
441 g_return_if_fail (gnutls->have_cert == FALSE);
442 g_return_if_fail (!gnutls->pkcs11_uri);
444 gnutls->pkcs11_uri = g_strdup (string);
446 status = gnutls_x509_crt_import_url (gnutls->cert, string, GNUTLS_PKCS11_OBJ_FLAG_CRT);
447 if (status == GNUTLS_E_SUCCESS)
449 gnutls->have_cert = TRUE;
451 else if (!gnutls->construct_error)
453 gnutls->construct_error =
454 g_error_new (G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
455 _("Could not import PKCS #11 certificate URI: %s"),
456 gnutls_strerror (status));
460 case PROP_PRIVATE_KEY_PKCS11_URI:
461 string = g_value_get_string (value);
464 g_return_if_fail (gnutls->have_key == FALSE);
465 g_return_if_fail (!gnutls->private_key_pkcs11_uri);
467 gnutls->private_key_pkcs11_uri = g_strdup (string);
471 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
476 g_tls_certificate_gnutls_init (GTlsCertificateGnutls *gnutls)
478 gnutls_x509_crt_init (&gnutls->cert);
482 g_tls_certificate_gnutls_initable_init (GInitable *initable,
483 GCancellable *cancellable,
486 GTlsCertificateGnutls *gnutls = G_TLS_CERTIFICATE_GNUTLS (initable);
488 if (gnutls->construct_error)
490 g_propagate_error (error, gnutls->construct_error);
491 gnutls->construct_error = NULL;
494 else if (!gnutls->have_cert)
496 g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
497 _("No certificate data provided"));
504 static GTlsCertificateFlags
505 g_tls_certificate_gnutls_verify (GTlsCertificate *cert,
506 GSocketConnectable *identity,
507 GTlsCertificate *trusted_ca)
509 GTlsCertificateGnutls *cert_gnutls;
511 gnutls_x509_crt_t *chain;
512 GTlsCertificateFlags gtls_flags;
513 GError *error = NULL;
515 cert_gnutls = G_TLS_CERTIFICATE_GNUTLS (cert);
519 cert_gnutls = cert_gnutls->issuer;
524 chain = g_new (gnutls_x509_crt_t, num_certs);
525 cert_gnutls = G_TLS_CERTIFICATE_GNUTLS (cert);
526 for (i = 0; i < num_certs; i++)
528 chain[i] = cert_gnutls->cert;
529 cert_gnutls = cert_gnutls->issuer;
531 g_assert (!cert_gnutls);
535 gnutls_x509_crt_t ca;
539 ca = G_TLS_CERTIFICATE_GNUTLS (trusted_ca)->cert;
540 status = gnutls_x509_crt_list_verify (chain, num_certs,
547 return G_TLS_CERTIFICATE_GENERIC_ERROR;
550 gtls_flags = g_tls_certificate_gnutls_convert_flags (gnutls_flags);
559 gtls_flags |= g_tls_certificate_gnutls_verify_identity (G_TLS_CERTIFICATE_GNUTLS (cert), identity, &error);
562 g_warning ("Error verifying TLS certificate: %s", error->message);
563 g_error_free (error);
571 g_tls_certificate_gnutls_class_init (GTlsCertificateGnutlsClass *klass)
573 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
574 GTlsCertificateClass *certificate_class = G_TLS_CERTIFICATE_CLASS (klass);
576 gobject_class->get_property = g_tls_certificate_gnutls_get_property;
577 gobject_class->set_property = g_tls_certificate_gnutls_set_property;
578 gobject_class->finalize = g_tls_certificate_gnutls_finalize;
580 certificate_class->verify = g_tls_certificate_gnutls_verify;
582 g_object_class_override_property (gobject_class, PROP_CERTIFICATE, "certificate");
583 g_object_class_override_property (gobject_class, PROP_CERTIFICATE_PEM, "certificate-pem");
584 g_object_class_override_property (gobject_class, PROP_PRIVATE_KEY, "private-key");
585 g_object_class_override_property (gobject_class, PROP_PRIVATE_KEY_PEM, "private-key-pem");
586 g_object_class_override_property (gobject_class, PROP_ISSUER, "issuer");
587 g_object_class_override_property (gobject_class, PROP_PKCS11_URI, "pkcs11-uri");
588 g_object_class_override_property (gobject_class, PROP_PRIVATE_KEY_PKCS11_URI, "private-key-pkcs11-uri");
589 g_object_class_override_property (gobject_class, PROP_NOT_VALID_BEFORE, "not-valid-before");
590 g_object_class_override_property (gobject_class, PROP_NOT_VALID_AFTER, "not-valid-after");
591 g_object_class_override_property (gobject_class, PROP_SUBJECT_NAME, "subject-name");
592 g_object_class_override_property (gobject_class, PROP_ISSUER_NAME, "issuer-name");
593 g_object_class_override_property (gobject_class, PROP_DNS_NAMES, "dns-names");
594 g_object_class_override_property (gobject_class, PROP_IP_ADDRESSES, "ip-addresses");
598 g_tls_certificate_gnutls_initable_iface_init (GInitableIface *iface)
600 iface->init = g_tls_certificate_gnutls_initable_init;
604 g_tls_certificate_gnutls_new (const gnutls_datum_t *datum,
605 GTlsCertificate *issuer)
607 GTlsCertificateGnutls *gnutls;
609 gnutls = g_object_new (G_TYPE_TLS_CERTIFICATE_GNUTLS,
612 g_tls_certificate_gnutls_set_data (gnutls, datum);
614 return G_TLS_CERTIFICATE (gnutls);
618 g_tls_certificate_gnutls_set_data (GTlsCertificateGnutls *gnutls,
619 const gnutls_datum_t *datum)
621 g_return_if_fail (G_IS_TLS_CERTIFICATE_GNUTLS (gnutls));
622 g_return_if_fail (!gnutls->have_cert);
624 if (gnutls_x509_crt_import (gnutls->cert, datum,
625 GNUTLS_X509_FMT_DER) == 0)
626 gnutls->have_cert = TRUE;
629 const gnutls_x509_crt_t
630 g_tls_certificate_gnutls_get_cert (GTlsCertificateGnutls *gnutls)
636 g_tls_certificate_gnutls_is_pkcs11_backed (GTlsCertificateGnutls *gnutls)
638 return gnutls->pkcs11_uri != NULL;
642 g_tls_certificate_gnutls_has_key (GTlsCertificateGnutls *gnutls)
644 return gnutls->have_key;
648 g_tls_certificate_gnutls_copy (GTlsCertificateGnutls *gnutls,
649 const gchar *interaction_id,
650 gnutls_pcert_st **pcert,
651 unsigned int *pcert_length,
652 gnutls_privkey_t *pkey)
654 GTlsCertificateGnutls *chain;
658 g_return_if_fail (G_IS_TLS_CERTIFICATE_GNUTLS (gnutls));
659 g_return_if_fail (pcert);
660 g_return_if_fail (pcert_length);
661 g_return_if_fail (pkey);
663 /* We will do this loop twice. It's probably more efficient than
664 * re-allocating memory.
670 chain = chain->issuer;
674 *pcert = g_malloc (sizeof (gnutls_pcert_st) * num_certs);
676 /* Now do the actual copy of the whole chain. */
680 gnutls_x509_crt_t cert;
683 gnutls_x509_crt_export2 (chain->cert, GNUTLS_X509_FMT_DER, &data);
685 gnutls_x509_crt_init (&cert);
686 status = gnutls_x509_crt_import (cert, &data, GNUTLS_X509_FMT_DER);
687 g_warn_if_fail (status == 0);
688 gnutls_free (data.data);
690 gnutls_pcert_import_x509 (*pcert + *pcert_length, cert, 0);
691 gnutls_x509_crt_deinit (cert);
694 chain = chain->issuer;
699 gnutls_x509_privkey_t x509_privkey;
701 gnutls_privkey_export_x509 (gnutls->key, &x509_privkey);
702 gnutls_privkey_import_x509 (*pkey, x509_privkey, GNUTLS_PRIVKEY_IMPORT_COPY);
703 gnutls_x509_privkey_deinit (x509_privkey);
705 else if (gnutls->private_key_pkcs11_uri || gnutls->pkcs11_uri)
709 status = gnutls_privkey_import_pkcs11_url (*pkey,
710 gnutls->private_key_pkcs11_uri ? gnutls->private_key_pkcs11_uri : gnutls->pkcs11_uri);
711 if (status != GNUTLS_E_SUCCESS)
713 gnutls_privkey_deinit (*pkey);
715 g_info ("Failed to copy PKCS #11 private key: %s", gnutls_strerror (status));
720 gnutls_privkey_deinit (*pkey);
726 g_tls_certificate_gnutls_copy_free (gnutls_pcert_st *pcert,
727 unsigned int pcert_length,
728 gnutls_privkey_t pkey)
732 for (unsigned int i = 0; i < pcert_length; i++)
733 gnutls_pcert_deinit (&pcert[i]);
738 gnutls_privkey_deinit (pkey);
741 static const struct {
743 GTlsCertificateFlags gtls_flag;
745 { GNUTLS_CERT_SIGNER_NOT_FOUND | GNUTLS_CERT_SIGNER_NOT_CA, G_TLS_CERTIFICATE_UNKNOWN_CA },
746 { GNUTLS_CERT_NOT_ACTIVATED, G_TLS_CERTIFICATE_NOT_ACTIVATED },
747 { GNUTLS_CERT_EXPIRED, G_TLS_CERTIFICATE_EXPIRED },
748 { GNUTLS_CERT_REVOKED, G_TLS_CERTIFICATE_REVOKED },
749 { GNUTLS_CERT_INSECURE_ALGORITHM, G_TLS_CERTIFICATE_INSECURE },
750 { GNUTLS_CERT_UNEXPECTED_OWNER, G_TLS_CERTIFICATE_BAD_IDENTITY }
752 static const int flags_map_size = G_N_ELEMENTS (flags_map);
755 g_tls_certificate_gnutls_convert_flags (guint gnutls_flags)
758 GTlsCertificateFlags gtls_flags;
760 /* Convert GNUTLS status to GTlsCertificateFlags. GNUTLS sets
761 * GNUTLS_CERT_INVALID if it sets any other flag, so we want to
762 * strip that out unless it's the only flag set. Then we convert
763 * specific flags we recognize, and if there are any flags left over
764 * at the end, we add G_TLS_CERTIFICATE_GENERIC_ERROR.
768 if (gnutls_flags != GNUTLS_CERT_INVALID)
769 gnutls_flags = gnutls_flags & ~GNUTLS_CERT_INVALID;
770 for (i = 0; i < flags_map_size && gnutls_flags != 0; i++)
772 if (gnutls_flags & flags_map[i].gnutls_flag)
774 gnutls_flags &= ~flags_map[i].gnutls_flag;
775 gtls_flags |= flags_map[i].gtls_flag;
779 gtls_flags |= G_TLS_CERTIFICATE_GENERIC_ERROR;
785 g_tls_certificate_gnutls_verify_identity (GTlsCertificateGnutls *gnutls,
786 GSocketConnectable *identity,
789 GTlsCertificateFlags result = 0;
790 const char *hostname;
791 char *free_hostname = NULL;
793 if (G_IS_NETWORK_ADDRESS (identity))
794 hostname = g_network_address_get_hostname (G_NETWORK_ADDRESS (identity));
795 else if (G_IS_NETWORK_SERVICE (identity))
796 hostname = g_network_service_get_domain (G_NETWORK_SERVICE (identity));
797 else if (G_IS_INET_SOCKET_ADDRESS (identity))
801 addr = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (identity));
802 hostname = free_hostname = g_inet_address_to_string (addr);
806 g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
807 _("Cannot verify peer identity of unexpected type %s"), G_OBJECT_TYPE_NAME (identity));
808 return G_TLS_CERTIFICATE_BAD_IDENTITY;
812 if (!gnutls_x509_crt_check_hostname (gnutls->cert, hostname))
813 result |= G_TLS_CERTIFICATE_BAD_IDENTITY;
815 g_free (free_hostname);
821 g_tls_certificate_gnutls_set_issuer (GTlsCertificateGnutls *gnutls,
822 GTlsCertificateGnutls *issuer)
824 g_return_if_fail (G_IS_TLS_CERTIFICATE_GNUTLS (gnutls));
825 g_return_if_fail (!issuer || G_IS_TLS_CERTIFICATE_GNUTLS (issuer));
828 g_object_ref (issuer);
830 g_object_unref (gnutls->issuer);
831 gnutls->issuer = issuer;
832 g_object_notify (G_OBJECT (gnutls), "issuer");
836 g_tls_certificate_gnutls_get_bytes (GTlsCertificateGnutls *gnutls)
840 g_return_val_if_fail (G_IS_TLS_CERTIFICATE_GNUTLS (gnutls), NULL);
842 g_object_get (gnutls, "certificate", &array, NULL);
843 return g_byte_array_free_to_bytes (array);
846 static gnutls_x509_crt_t *
847 convert_data_to_gnutls_certs (const gnutls_datum_t *certs,
849 gnutls_x509_crt_fmt_t format)
851 gnutls_x509_crt_t *gnutls_certs;
854 gnutls_certs = g_new (gnutls_x509_crt_t, num_certs);
856 for (i = 0; i < num_certs; i++)
858 if (gnutls_x509_crt_init (&gnutls_certs[i]) < 0)
865 for (i = 0; i < num_certs; i++)
867 if (gnutls_x509_crt_import (gnutls_certs[i], &certs[i], format) < 0)
877 for (; i != G_MAXUINT; i--)
878 gnutls_x509_crt_deinit (gnutls_certs[i]);
879 g_free (gnutls_certs);
883 GTlsCertificateGnutls *
884 g_tls_certificate_gnutls_build_chain (const gnutls_datum_t *certs,
886 gnutls_x509_crt_fmt_t format)
888 GPtrArray *glib_certs;
889 gnutls_x509_crt_t *gnutls_certs;
890 GTlsCertificateGnutls *issuer;
891 GTlsCertificateGnutls *result;
894 g_return_val_if_fail (certs, NULL);
896 gnutls_certs = convert_data_to_gnutls_certs (certs, num_certs, format);
900 glib_certs = g_ptr_array_new_full (num_certs, g_object_unref);
901 for (i = 0; i < num_certs; i++)
902 g_ptr_array_add (glib_certs, g_tls_certificate_gnutls_new (&certs[i], NULL));
904 /* Some servers send certs out of order, or will send duplicate
905 * certs, so we need to be careful when assigning the issuer of
906 * our new GTlsCertificateGnutls.
908 for (i = 0; i < num_certs; i++)
912 /* Check if the cert issued itself */
913 if (gnutls_x509_crt_check_issuer (gnutls_certs[i], gnutls_certs[i]))
916 if (i < num_certs - 1 &&
917 gnutls_x509_crt_check_issuer (gnutls_certs[i], gnutls_certs[i + 1]))
919 issuer = glib_certs->pdata[i + 1];
923 for (j = 0; j < num_certs; j++)
926 gnutls_x509_crt_check_issuer (gnutls_certs[i], gnutls_certs[j]))
928 issuer = glib_certs->pdata[j];
935 g_tls_certificate_gnutls_set_issuer (glib_certs->pdata[i], issuer);
938 result = g_object_ref (glib_certs->pdata[0]);
939 g_ptr_array_unref (glib_certs);
941 for (i = 0; i < num_certs; i++)
942 gnutls_x509_crt_deinit (gnutls_certs[i]);
943 g_free (gnutls_certs);