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