1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /*
3  * gtlscertificate-openssl.c
4  *
5  * Copyright (C) 2015 NICE s.r.l.
6  *
7  * This file 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.
11  *
12  * This file 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.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this program. If not, see <http://www.gnu.org/licenses/>.
19  *
20  * In addition, when the library is used with OpenSSL, a special
21  * exception applies. Refer to the LICENSE_EXCEPTION file for details.
22  *
23  * Authors: Ignacio Casal Quinteiro
24  */
25 
26 #include "config.h"
27 
28 #include <string.h>
29 #include "openssl-include.h"
30 
31 #include "gtlscertificate-openssl.h"
32 #include "openssl-util.h"
33 #include <glib/gi18n-lib.h>
34 
35 struct _GTlsCertificateOpenssl
36 {
37   GTlsCertificate parent_instance;
38 
39   X509 *cert;
40   EVP_PKEY *key;
41 
42   GTlsCertificateOpenssl *issuer;
43 
44   GError *construct_error;
45 
46   guint have_cert : 1;
47   guint have_key  : 1;
48 };
49 
50 enum
51 {
52   PROP_0,
53 
54   PROP_CERTIFICATE,
55   PROP_CERTIFICATE_PEM,
56   PROP_PRIVATE_KEY,
57   PROP_PRIVATE_KEY_PEM,
58   PROP_ISSUER
59 };
60 
61 static void     g_tls_certificate_openssl_initable_iface_init (GInitableIface  *iface);
62 
G_DEFINE_TYPE_WITH_CODE(GTlsCertificateOpenssl,g_tls_certificate_openssl,G_TYPE_TLS_CERTIFICATE,G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,g_tls_certificate_openssl_initable_iface_init))63 G_DEFINE_TYPE_WITH_CODE (GTlsCertificateOpenssl, g_tls_certificate_openssl, G_TYPE_TLS_CERTIFICATE,
64                          G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
65                                                 g_tls_certificate_openssl_initable_iface_init))
66 
67 static void
68 g_tls_certificate_openssl_finalize (GObject *object)
69 {
70   GTlsCertificateOpenssl *openssl = G_TLS_CERTIFICATE_OPENSSL (object);
71 
72   if (openssl->cert)
73     X509_free (openssl->cert);
74   if (openssl->key)
75     EVP_PKEY_free (openssl->key);
76 
77   g_clear_object (&openssl->issuer);
78 
79   g_clear_error (&openssl->construct_error);
80 
81   G_OBJECT_CLASS (g_tls_certificate_openssl_parent_class)->finalize (object);
82 }
83 
84 static void
g_tls_certificate_openssl_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)85 g_tls_certificate_openssl_get_property (GObject    *object,
86                                         guint       prop_id,
87                                         GValue     *value,
88                                         GParamSpec *pspec)
89 {
90   GTlsCertificateOpenssl *openssl = G_TLS_CERTIFICATE_OPENSSL (object);
91   GByteArray *certificate;
92   guint8 *data;
93   BIO *bio;
94   char *certificate_pem;
95   int size;
96 
97   switch (prop_id)
98     {
99     case PROP_CERTIFICATE:
100       /* NOTE: we do the two calls to avoid openssl allocating the buffer for us */
101       size = i2d_X509 (openssl->cert, NULL);
102       if (size < 0)
103         certificate = NULL;
104       else
105         {
106           certificate = g_byte_array_sized_new (size);
107           certificate->len = size;
108           data = certificate->data;
109           size = i2d_X509 (openssl->cert, &data);
110           if (size < 0)
111             {
112               g_byte_array_free (certificate, TRUE);
113               certificate = NULL;
114             }
115         }
116       g_value_take_boxed (value, certificate);
117       break;
118 
119     case PROP_CERTIFICATE_PEM:
120       bio = BIO_new (BIO_s_mem ());
121 
122       if (!PEM_write_bio_X509 (bio, openssl->cert) || !BIO_write (bio, "\0", 1))
123         certificate_pem = NULL;
124       else
125         {
126           BIO_get_mem_data (bio, &certificate_pem);
127           g_value_set_string (value, certificate_pem);
128 
129           BIO_free_all (bio);
130         }
131       break;
132 
133     case PROP_ISSUER:
134       g_value_set_object (value, openssl->issuer);
135       break;
136 
137     default:
138       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
139     }
140 }
141 
142 static void
g_tls_certificate_openssl_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)143 g_tls_certificate_openssl_set_property (GObject      *object,
144                                        guint         prop_id,
145                                        const GValue *value,
146                                        GParamSpec   *pspec)
147 {
148   GTlsCertificateOpenssl *openssl = G_TLS_CERTIFICATE_OPENSSL (object);
149   GByteArray *bytes;
150   guint8 *data;
151   BIO *bio;
152   const char *string;
153 
154   switch (prop_id)
155     {
156     case PROP_CERTIFICATE:
157       bytes = g_value_get_boxed (value);
158       if (!bytes)
159         break;
160       g_return_if_fail (openssl->have_cert == FALSE);
161       /* see that we cannot use bytes->data directly since it will move the pointer */
162       data = bytes->data;
163       openssl->cert = d2i_X509 (NULL, (const unsigned char **)&data, bytes->len);
164       if (openssl->cert)
165         openssl->have_cert = TRUE;
166       else if (!openssl->construct_error)
167         {
168           openssl->construct_error =
169             g_error_new (G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
170                          _("Could not parse DER certificate: %s"),
171                          ERR_error_string (ERR_get_error (), NULL));
172         }
173 
174       break;
175 
176     case PROP_CERTIFICATE_PEM:
177       string = g_value_get_string (value);
178       if (!string)
179         break;
180       g_return_if_fail (openssl->have_cert == FALSE);
181       bio = BIO_new_mem_buf ((gpointer)string, -1);
182       openssl->cert = PEM_read_bio_X509 (bio, NULL, NULL, NULL);
183       BIO_free (bio);
184       if (openssl->cert)
185         openssl->have_cert = TRUE;
186       else if (!openssl->construct_error)
187         {
188           openssl->construct_error =
189             g_error_new (G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
190                          _("Could not parse PEM certificate: %s"),
191                          ERR_error_string (ERR_get_error (), NULL));
192         }
193       break;
194 
195     case PROP_PRIVATE_KEY:
196       bytes = g_value_get_boxed (value);
197       if (!bytes)
198         break;
199       g_return_if_fail (openssl->have_key == FALSE);
200       bio = BIO_new_mem_buf (bytes->data, bytes->len);
201       openssl->key = d2i_PrivateKey_bio (bio, NULL);
202       BIO_free (bio);
203       if (openssl->key)
204         openssl->have_key = TRUE;
205       else if (!openssl->construct_error)
206         {
207           openssl->construct_error =
208             g_error_new (G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
209                          _("Could not parse DER private key: %s"),
210                          ERR_error_string (ERR_get_error (), NULL));
211         }
212       break;
213 
214     case PROP_PRIVATE_KEY_PEM:
215       string = g_value_get_string (value);
216       if (!string)
217         break;
218       g_return_if_fail (openssl->have_key == FALSE);
219       bio = BIO_new_mem_buf ((gpointer)string, -1);
220       openssl->key = PEM_read_bio_PrivateKey (bio, NULL, NULL, NULL);
221       BIO_free (bio);
222       if (openssl->key)
223         openssl->have_key = TRUE;
224       else if (!openssl->construct_error)
225         {
226           openssl->construct_error =
227             g_error_new (G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
228                          _("Could not parse PEM private key: %s"),
229                          ERR_error_string (ERR_get_error (), NULL));
230         }
231       break;
232 
233     case PROP_ISSUER:
234       openssl->issuer = g_value_dup_object (value);
235       break;
236 
237     default:
238       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
239     }
240 }
241 
242 static void
g_tls_certificate_openssl_init(GTlsCertificateOpenssl * openssl)243 g_tls_certificate_openssl_init (GTlsCertificateOpenssl *openssl)
244 {
245 }
246 
247 static gboolean
g_tls_certificate_openssl_initable_init(GInitable * initable,GCancellable * cancellable,GError ** error)248 g_tls_certificate_openssl_initable_init (GInitable       *initable,
249                                          GCancellable    *cancellable,
250                                          GError         **error)
251 {
252   GTlsCertificateOpenssl *openssl = G_TLS_CERTIFICATE_OPENSSL (initable);
253 
254   if (openssl->construct_error)
255     {
256       g_propagate_error (error, openssl->construct_error);
257       openssl->construct_error = NULL;
258       return FALSE;
259     }
260   else if (!openssl->have_cert)
261     {
262       g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
263                            _("No certificate data provided"));
264       return FALSE;
265     }
266   else
267     return TRUE;
268 }
269 
270 static GTlsCertificateFlags
g_tls_certificate_openssl_verify(GTlsCertificate * cert,GSocketConnectable * identity,GTlsCertificate * trusted_ca)271 g_tls_certificate_openssl_verify (GTlsCertificate     *cert,
272                                   GSocketConnectable  *identity,
273                                   GTlsCertificate     *trusted_ca)
274 {
275   GTlsCertificateOpenssl *cert_openssl;
276   GTlsCertificateFlags gtls_flags;
277   X509 *x;
278   STACK_OF(X509) *untrusted;
279   gint i;
280 
281   cert_openssl = G_TLS_CERTIFICATE_OPENSSL (cert);
282   x = cert_openssl->cert;
283 
284   untrusted = sk_X509_new_null ();
285   for (; cert_openssl; cert_openssl = cert_openssl->issuer)
286     sk_X509_push (untrusted, cert_openssl->cert);
287 
288   gtls_flags = 0;
289 
290   if (trusted_ca)
291     {
292       X509_STORE *store;
293       X509_STORE_CTX *csc;
294       STACK_OF(X509) *trusted;
295 
296       store = X509_STORE_new ();
297       csc = X509_STORE_CTX_new ();
298 
299       if (!X509_STORE_CTX_init (csc, store, x, untrusted))
300         {
301           sk_X509_free (untrusted);
302           X509_STORE_CTX_free (csc);
303           X509_STORE_free (store);
304           return G_TLS_CERTIFICATE_GENERIC_ERROR;
305         }
306 
307       trusted = sk_X509_new_null ();
308       cert_openssl = G_TLS_CERTIFICATE_OPENSSL (trusted_ca);
309       for (; cert_openssl; cert_openssl = cert_openssl->issuer)
310         sk_X509_push (trusted, cert_openssl->cert);
311 
312       X509_STORE_CTX_trusted_stack (csc, trusted);
313       if (X509_verify_cert (csc) <= 0)
314         gtls_flags |= g_tls_certificate_openssl_convert_error (X509_STORE_CTX_get_error (csc));
315 
316       sk_X509_free (trusted);
317       X509_STORE_CTX_free (csc);
318       X509_STORE_free (store);
319     }
320 
321   /* We have to check these ourselves since openssl
322    * does not give us flags and UNKNOWN_CA will take priority.
323    */
324   for (i = 0; i < sk_X509_num (untrusted); i++)
325     {
326       X509 *c = sk_X509_value (untrusted, i);
327       ASN1_TIME *not_before = X509_get_notBefore (c);
328       ASN1_TIME *not_after = X509_get_notAfter (c);
329 
330       if (X509_cmp_current_time (not_before) > 0)
331         gtls_flags |= G_TLS_CERTIFICATE_NOT_ACTIVATED;
332 
333       if (X509_cmp_current_time (not_after) < 0)
334         gtls_flags |= G_TLS_CERTIFICATE_EXPIRED;
335     }
336 
337   sk_X509_free (untrusted);
338 
339   if (identity)
340     gtls_flags |= g_tls_certificate_openssl_verify_identity (G_TLS_CERTIFICATE_OPENSSL (cert), identity);
341 
342   return gtls_flags;
343 }
344 
345 static void
g_tls_certificate_openssl_class_init(GTlsCertificateOpensslClass * klass)346 g_tls_certificate_openssl_class_init (GTlsCertificateOpensslClass *klass)
347 {
348   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
349   GTlsCertificateClass *certificate_class = G_TLS_CERTIFICATE_CLASS (klass);
350 
351   gobject_class->get_property = g_tls_certificate_openssl_get_property;
352   gobject_class->set_property = g_tls_certificate_openssl_set_property;
353   gobject_class->finalize     = g_tls_certificate_openssl_finalize;
354 
355   certificate_class->verify = g_tls_certificate_openssl_verify;
356 
357   g_object_class_override_property (gobject_class, PROP_CERTIFICATE, "certificate");
358   g_object_class_override_property (gobject_class, PROP_CERTIFICATE_PEM, "certificate-pem");
359   g_object_class_override_property (gobject_class, PROP_PRIVATE_KEY, "private-key");
360   g_object_class_override_property (gobject_class, PROP_PRIVATE_KEY_PEM, "private-key-pem");
361   g_object_class_override_property (gobject_class, PROP_ISSUER, "issuer");
362 }
363 
364 static void
g_tls_certificate_openssl_initable_iface_init(GInitableIface * iface)365 g_tls_certificate_openssl_initable_iface_init (GInitableIface  *iface)
366 {
367   iface->init = g_tls_certificate_openssl_initable_init;
368 }
369 
370 GTlsCertificate *
g_tls_certificate_openssl_new(GBytes * bytes,GTlsCertificate * issuer)371 g_tls_certificate_openssl_new (GBytes          *bytes,
372                                GTlsCertificate *issuer)
373 {
374   GTlsCertificateOpenssl *openssl;
375 
376   openssl = g_object_new (G_TYPE_TLS_CERTIFICATE_OPENSSL,
377                           "issuer", issuer,
378                           NULL);
379   g_tls_certificate_openssl_set_data (openssl, bytes);
380 
381   return G_TLS_CERTIFICATE (openssl);
382 }
383 
384 GTlsCertificate *
g_tls_certificate_openssl_new_from_x509(X509 * x,GTlsCertificate * issuer)385 g_tls_certificate_openssl_new_from_x509 (X509            *x,
386                                          GTlsCertificate *issuer)
387 {
388   GTlsCertificateOpenssl *openssl;
389 
390   openssl = g_object_new (G_TYPE_TLS_CERTIFICATE_OPENSSL,
391                           "issuer", issuer,
392                           NULL);
393 
394   openssl->cert = X509_dup (x);
395   openssl->have_cert = TRUE;
396 
397   return G_TLS_CERTIFICATE (openssl);
398 }
399 
400 void
g_tls_certificate_openssl_set_data(GTlsCertificateOpenssl * openssl,GBytes * bytes)401 g_tls_certificate_openssl_set_data (GTlsCertificateOpenssl *openssl,
402                                     GBytes                 *bytes)
403 {
404   const unsigned char *data;
405 
406   g_return_if_fail (G_IS_TLS_CERTIFICATE_OPENSSL (openssl));
407 
408   g_return_if_fail (!openssl->have_cert);
409 
410   data = (const unsigned char *)g_bytes_get_data (bytes, NULL);
411   openssl->cert = d2i_X509 (NULL, &data, g_bytes_get_size (bytes));
412 
413   if (openssl->cert)
414     openssl->have_cert = TRUE;
415 }
416 
417 GBytes *
g_tls_certificate_openssl_get_bytes(GTlsCertificateOpenssl * openssl)418 g_tls_certificate_openssl_get_bytes (GTlsCertificateOpenssl *openssl)
419 {
420   GByteArray *array;
421 
422   g_return_val_if_fail (G_IS_TLS_CERTIFICATE_OPENSSL (openssl), NULL);
423 
424   g_object_get (openssl, "certificate", &array, NULL);
425   return g_byte_array_free_to_bytes (array);
426 }
427 
428 X509 *
g_tls_certificate_openssl_get_cert(GTlsCertificateOpenssl * openssl)429 g_tls_certificate_openssl_get_cert (GTlsCertificateOpenssl *openssl)
430 {
431   g_return_val_if_fail (G_IS_TLS_CERTIFICATE_OPENSSL (openssl), FALSE);
432 
433   return openssl->cert;
434 }
435 
436 EVP_PKEY *
g_tls_certificate_openssl_get_key(GTlsCertificateOpenssl * openssl)437 g_tls_certificate_openssl_get_key (GTlsCertificateOpenssl *openssl)
438 {
439   g_return_val_if_fail (G_IS_TLS_CERTIFICATE_OPENSSL (openssl), FALSE);
440 
441   return openssl->key;
442 }
443 
444 void
g_tls_certificate_openssl_set_issuer(GTlsCertificateOpenssl * openssl,GTlsCertificateOpenssl * issuer)445 g_tls_certificate_openssl_set_issuer (GTlsCertificateOpenssl *openssl,
446                                       GTlsCertificateOpenssl *issuer)
447 {
448   g_return_if_fail (G_IS_TLS_CERTIFICATE_OPENSSL (openssl));
449   g_return_if_fail (!issuer || G_IS_TLS_CERTIFICATE_OPENSSL (issuer));
450 
451   if (g_set_object (&openssl->issuer, issuer))
452     g_object_notify (G_OBJECT (openssl), "issuer");
453 }
454 
455 static gboolean
verify_identity_hostname(GTlsCertificateOpenssl * openssl,GSocketConnectable * identity)456 verify_identity_hostname (GTlsCertificateOpenssl *openssl,
457                           GSocketConnectable     *identity)
458 {
459   const char *hostname;
460 
461   if (G_IS_NETWORK_ADDRESS (identity))
462     hostname = g_network_address_get_hostname (G_NETWORK_ADDRESS (identity));
463   else if (G_IS_NETWORK_SERVICE (identity))
464     hostname = g_network_service_get_domain (G_NETWORK_SERVICE (identity));
465   else
466     return FALSE;
467 
468   return g_tls_X509_check_host (openssl->cert, hostname, strlen (hostname), 0, NULL) == 1;
469 }
470 
471 static gboolean
verify_identity_ip(GTlsCertificateOpenssl * openssl,GSocketConnectable * identity)472 verify_identity_ip (GTlsCertificateOpenssl *openssl,
473                     GSocketConnectable     *identity)
474 {
475   GInetAddress *addr;
476   gsize addr_size;
477   const guint8 *addr_bytes;
478   gboolean ret;
479 
480   if (G_IS_INET_SOCKET_ADDRESS (identity))
481     addr = g_object_ref (g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (identity)));
482   else {
483     const char *hostname;
484 
485     if (G_IS_NETWORK_ADDRESS (identity))
486       hostname = g_network_address_get_hostname (G_NETWORK_ADDRESS (identity));
487     else if (G_IS_NETWORK_SERVICE (identity))
488       hostname = g_network_service_get_domain (G_NETWORK_SERVICE (identity));
489     else
490       return FALSE;
491 
492     addr = g_inet_address_new_from_string (hostname);
493     if (!addr)
494       return FALSE;
495   }
496 
497   addr_bytes = g_inet_address_to_bytes (addr);
498   addr_size = g_inet_address_get_native_size (addr);
499 
500   ret = g_tls_X509_check_ip (openssl->cert, addr_bytes, addr_size, 0) == 1;
501 
502   g_object_unref (addr);
503   return ret;
504 }
505 
506 GTlsCertificateFlags
g_tls_certificate_openssl_verify_identity(GTlsCertificateOpenssl * openssl,GSocketConnectable * identity)507 g_tls_certificate_openssl_verify_identity (GTlsCertificateOpenssl *openssl,
508                                            GSocketConnectable     *identity)
509 {
510   if (verify_identity_hostname (openssl, identity))
511     return 0;
512   else if (verify_identity_ip (openssl, identity))
513     return 0;
514 
515   /* FIXME: check sRVName and uniformResourceIdentifier
516    * subjectAltNames, if appropriate for @identity.
517    */
518 
519   return G_TLS_CERTIFICATE_BAD_IDENTITY;
520 }
521 
522 GTlsCertificateFlags
g_tls_certificate_openssl_convert_error(guint openssl_error)523 g_tls_certificate_openssl_convert_error (guint openssl_error)
524 {
525   GTlsCertificateFlags gtls_flags;
526 
527   gtls_flags = 0;
528 
529   /* FIXME: should we add more ? */
530   switch (openssl_error)
531     {
532     case X509_V_OK:
533       break;
534     case X509_V_ERR_CERT_NOT_YET_VALID:
535       gtls_flags = G_TLS_CERTIFICATE_NOT_ACTIVATED;
536       break;
537     case X509_V_ERR_CERT_HAS_EXPIRED:
538       gtls_flags = G_TLS_CERTIFICATE_EXPIRED;
539       break;
540     case X509_V_ERR_CERT_REVOKED:
541       gtls_flags = G_TLS_CERTIFICATE_REVOKED;
542       break;
543     case X509_V_ERR_AKID_SKID_MISMATCH:
544       gtls_flags = G_TLS_CERTIFICATE_BAD_IDENTITY;
545       break;
546     case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
547     case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
548       gtls_flags = G_TLS_CERTIFICATE_UNKNOWN_CA;
549       break;
550     default:
551       g_message ("certificate error: %s", X509_verify_cert_error_string (openssl_error));
552       gtls_flags = G_TLS_CERTIFICATE_GENERIC_ERROR;
553     }
554 
555   return gtls_flags;
556 }
557 
558 static gboolean
is_issuer(GTlsCertificateOpenssl * cert,GTlsCertificateOpenssl * issuer)559 is_issuer (GTlsCertificateOpenssl *cert,
560            GTlsCertificateOpenssl *issuer)
561 {
562   X509 *x;
563   X509 *issuer_x;
564   X509_STORE *store;
565   X509_STORE_CTX *csc;
566   STACK_OF(X509) *trusted;
567   gboolean ret = FALSE;
568   gint err;
569 
570   x = g_tls_certificate_openssl_get_cert (cert);
571   issuer_x = g_tls_certificate_openssl_get_cert (issuer);
572 
573   store = X509_STORE_new ();
574   csc = X509_STORE_CTX_new ();
575 
576   if (!X509_STORE_CTX_init (csc, store, x, NULL))
577     goto end;
578 
579   trusted = sk_X509_new_null ();
580   sk_X509_push (trusted, issuer_x);
581 
582   X509_STORE_CTX_trusted_stack (csc, trusted);
583   X509_STORE_CTX_set_flags (csc, X509_V_FLAG_CB_ISSUER_CHECK);
584 
585   /* FIXME: is this the right way to do it? */
586   if (X509_verify_cert (csc) <= 0)
587     {
588       err = X509_STORE_CTX_get_error (csc);
589       if (err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT)
590         ret = TRUE;
591     }
592   else
593     ret = TRUE;
594 
595   sk_X509_free (trusted);
596 
597 end:
598   X509_STORE_CTX_free (csc);
599   X509_STORE_free (store);
600 
601   return ret;
602 }
603 
604 GTlsCertificateOpenssl *
g_tls_certificate_openssl_build_chain(X509 * x,STACK_OF (X509)* chain)605 g_tls_certificate_openssl_build_chain (X509            *x,
606                                        STACK_OF (X509) *chain)
607 {
608   GPtrArray *glib_certs;
609   GTlsCertificateOpenssl *issuer;
610   GTlsCertificateOpenssl *result;
611   guint i, j;
612 
613   g_return_val_if_fail (x, NULL);
614   g_return_val_if_fail (chain, NULL);
615 
616   glib_certs = g_ptr_array_new_full (sk_X509_num (chain), g_object_unref);
617   g_ptr_array_add (glib_certs, g_tls_certificate_openssl_new_from_x509 (x, NULL));
618   for (i = 1; i < sk_X509_num (chain); i++)
619     g_ptr_array_add (glib_certs, g_tls_certificate_openssl_new_from_x509 (sk_X509_value (chain, i), NULL));
620 
621   /* Some servers send certs out of order, or will send duplicate
622    * certs, so we need to be careful when assigning the issuer of
623    * our new GTlsCertificateOpenssl.
624    */
625   for (i = 0; i < glib_certs->len; i++)
626     {
627       issuer = NULL;
628 
629       /* Check if the cert issued itself */
630       if (is_issuer (glib_certs->pdata[i], glib_certs->pdata[i]))
631         continue;
632 
633       if (i < glib_certs->len - 1 &&
634           is_issuer (glib_certs->pdata[i], glib_certs->pdata[i + 1]))
635         {
636           issuer = glib_certs->pdata[i + 1];
637         }
638       else
639         {
640           for (j = 0; j < glib_certs->len; j++)
641             {
642               if (j != i &&
643                   is_issuer (glib_certs->pdata[i], glib_certs->pdata[j]))
644                 {
645                   issuer = glib_certs->pdata[j];
646                   break;
647                 }
648             }
649         }
650 
651       if (issuer)
652         g_tls_certificate_openssl_set_issuer (glib_certs->pdata[i], issuer);
653     }
654 
655   result = g_object_ref (glib_certs->pdata[0]);
656   g_ptr_array_unref (glib_certs);
657 
658   return result;
659 }
660