2 * gtlsclientconnection-openssl.c
4 * Copyright (C) 2015 NICE s.r.l.
6 * This file is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This file is distributed in the hope that it will be useful,
12 * but 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 License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 * In addition, when the library is used with OpenSSL, a special
20 * exception applies. Refer to the LICENSE_EXCEPTION file for details.
22 * Authors: Ignacio Casal Quinteiro
31 #include "openssl-include.h"
32 #include "gtlsconnection-base.h"
33 #include "gtlsclientconnection-openssl.h"
34 #include "gtlsbackend-openssl.h"
35 #include "gtlscertificate-openssl.h"
36 #include <glib/gi18n-lib.h>
38 #define DEFAULT_CIPHER_LIST "HIGH:!DSS:!aNULL@STRENGTH"
40 typedef struct _GTlsClientConnectionOpensslPrivate
42 GTlsCertificateFlags validation_flags;
43 GSocketConnectable *server_identity;
45 gboolean session_data_override;
50 STACK_OF (X509_NAME) *ca_list;
55 } GTlsClientConnectionOpensslPrivate;
60 PROP_VALIDATION_FLAGS,
66 static void g_tls_client_connection_openssl_initable_interface_init (GInitableIface *iface);
68 static void g_tls_client_connection_openssl_client_connection_interface_init (GTlsClientConnectionInterface *iface);
70 static GInitableIface *g_tls_client_connection_openssl_parent_initable_iface;
72 G_DEFINE_TYPE_WITH_CODE (GTlsClientConnectionOpenssl, g_tls_client_connection_openssl, G_TYPE_TLS_CONNECTION_OPENSSL,
73 G_ADD_PRIVATE (GTlsClientConnectionOpenssl)
74 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
75 g_tls_client_connection_openssl_initable_interface_init)
76 G_IMPLEMENT_INTERFACE (G_TYPE_TLS_CLIENT_CONNECTION,
77 g_tls_client_connection_openssl_client_connection_interface_init))
80 g_tls_client_connection_openssl_finalize (GObject *object)
82 GTlsClientConnectionOpenssl *openssl = G_TLS_CLIENT_CONNECTION_OPENSSL (object);
83 GTlsClientConnectionOpensslPrivate *priv;
85 priv = g_tls_client_connection_openssl_get_instance_private (openssl);
87 g_clear_object (&priv->server_identity);
88 g_clear_pointer (&priv->session_id, g_bytes_unref);
89 g_clear_pointer (&priv->session_data, g_bytes_unref);
92 SSL_CTX_free (priv->ssl_ctx);
93 SSL_SESSION_free (priv->session);
95 G_OBJECT_CLASS (g_tls_client_connection_openssl_parent_class)->finalize (object);
99 get_server_identity (GTlsClientConnectionOpenssl *openssl)
101 GTlsClientConnectionOpensslPrivate *priv;
103 priv = g_tls_client_connection_openssl_get_instance_private (openssl);
105 if (G_IS_NETWORK_ADDRESS (priv->server_identity))
106 return g_network_address_get_hostname (G_NETWORK_ADDRESS (priv->server_identity));
107 else if (G_IS_NETWORK_SERVICE (priv->server_identity))
108 return g_network_service_get_domain (G_NETWORK_SERVICE (priv->server_identity));
114 g_tls_client_connection_openssl_get_property (GObject *object,
119 GTlsClientConnectionOpenssl *openssl = G_TLS_CLIENT_CONNECTION_OPENSSL (object);
120 GTlsClientConnectionOpensslPrivate *priv;
124 priv = g_tls_client_connection_openssl_get_instance_private (openssl);
128 case PROP_VALIDATION_FLAGS:
129 g_value_set_flags (value, priv->validation_flags);
132 case PROP_SERVER_IDENTITY:
133 g_value_set_object (value, priv->server_identity);
137 g_value_set_boolean (value, priv->use_ssl3);
140 case PROP_ACCEPTED_CAS:
144 for (i = 0; i < sk_X509_NAME_num (priv->ca_list); ++i)
148 size = i2d_X509_NAME (sk_X509_NAME_value (priv->ca_list, i), NULL);
153 ca = g_malloc (size);
154 size = i2d_X509_NAME (sk_X509_NAME_value (priv->ca_list, i), &ca);
156 accepted_cas = g_list_prepend (accepted_cas, g_byte_array_new_take (
162 accepted_cas = g_list_reverse (accepted_cas);
164 g_value_set_pointer (value, accepted_cas);
168 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
173 g_tls_client_connection_openssl_set_property (GObject *object,
178 GTlsClientConnectionOpenssl *openssl = G_TLS_CLIENT_CONNECTION_OPENSSL (object);
179 GTlsClientConnectionOpensslPrivate *priv;
181 priv = g_tls_client_connection_openssl_get_instance_private (openssl);
185 case PROP_VALIDATION_FLAGS:
186 priv->validation_flags = g_value_get_flags (value);
189 case PROP_SERVER_IDENTITY:
190 if (priv->server_identity)
191 g_object_unref (priv->server_identity);
192 priv->server_identity = g_value_dup_object (value);
196 priv->use_ssl3 = g_value_get_boolean (value);
200 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
205 g_tls_client_connection_openssl_constructed (GObject *object)
207 GTlsClientConnectionOpenssl *openssl = G_TLS_CLIENT_CONNECTION_OPENSSL (object);
208 GTlsClientConnectionOpensslPrivate *priv;
209 GSocketConnection *base_conn;
210 GSocketAddress *remote_addr;
214 priv = g_tls_client_connection_openssl_get_instance_private (openssl);
216 /* Create a TLS session ID. We base it on the IP address since
217 * different hosts serving the same hostname/service will probably
218 * not share the same session cache. We base it on the
219 * server-identity because at least some servers will fail (rather
220 * than just failing to resume the session) if we don't.
221 * (https://bugs.launchpad.net/bugs/823325)
223 g_object_get (G_OBJECT (openssl), "base-io-stream", &base_conn, NULL);
224 if (G_IS_SOCKET_CONNECTION (base_conn))
226 remote_addr = g_socket_connection_get_remote_address (base_conn, NULL);
227 if (G_IS_INET_SOCKET_ADDRESS (remote_addr))
229 GInetSocketAddress *isaddr = G_INET_SOCKET_ADDRESS (remote_addr);
230 const gchar *server_hostname;
231 gchar *addrstr, *session_id;
233 iaddr = g_inet_socket_address_get_address (isaddr);
234 port = g_inet_socket_address_get_port (isaddr);
236 addrstr = g_inet_address_to_string (iaddr);
237 server_hostname = get_server_identity (openssl);
238 session_id = g_strdup_printf ("%s/%s/%d", addrstr,
239 server_hostname ? server_hostname : "",
241 priv->session_id = g_bytes_new_take (session_id, strlen (session_id));
244 g_object_unref (remote_addr);
246 g_object_unref (base_conn);
248 G_OBJECT_CLASS (g_tls_client_connection_openssl_parent_class)->constructed (object);
251 static GTlsConnectionBaseStatus
252 g_tls_client_connection_openssl_handshake (GTlsConnectionBase *tls,
253 GCancellable *cancellable,
256 return G_TLS_CONNECTION_BASE_CLASS (g_tls_client_connection_openssl_parent_class)->
257 handshake (tls, cancellable, error);
260 static GTlsConnectionBaseStatus
261 g_tls_client_connection_openssl_complete_handshake (GTlsConnectionBase *tls,
264 GTlsConnectionBaseStatus status;
266 status = G_TLS_CONNECTION_BASE_CLASS (g_tls_client_connection_openssl_parent_class)->
267 complete_handshake (tls, error);
273 g_tls_client_connection_openssl_get_ssl (GTlsConnectionOpenssl *connection)
275 GTlsClientConnectionOpenssl *client = G_TLS_CLIENT_CONNECTION_OPENSSL (connection);
276 GTlsClientConnectionOpensslPrivate *priv;
278 priv = g_tls_client_connection_openssl_get_instance_private (client);
284 g_tls_client_connection_openssl_class_init (GTlsClientConnectionOpensslClass *klass)
286 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
287 GTlsConnectionBaseClass *base_class = G_TLS_CONNECTION_BASE_CLASS (klass);
288 GTlsConnectionOpensslClass *connection_class = G_TLS_CONNECTION_OPENSSL_CLASS (klass);
290 gobject_class->finalize = g_tls_client_connection_openssl_finalize;
291 gobject_class->get_property = g_tls_client_connection_openssl_get_property;
292 gobject_class->set_property = g_tls_client_connection_openssl_set_property;
293 gobject_class->constructed = g_tls_client_connection_openssl_constructed;
295 base_class->handshake = g_tls_client_connection_openssl_handshake;
296 base_class->complete_handshake = g_tls_client_connection_openssl_complete_handshake;
298 connection_class->get_ssl = g_tls_client_connection_openssl_get_ssl;
300 g_object_class_override_property (gobject_class, PROP_VALIDATION_FLAGS, "validation-flags");
301 g_object_class_override_property (gobject_class, PROP_SERVER_IDENTITY, "server-identity");
302 g_object_class_override_property (gobject_class, PROP_USE_SSL3, "use-ssl3");
303 g_object_class_override_property (gobject_class, PROP_ACCEPTED_CAS, "accepted-cas");
307 g_tls_client_connection_openssl_init (GTlsClientConnectionOpenssl *openssl)
313 g_tls_client_connection_openssl_copy_session_state (GTlsClientConnection *conn,
314 GTlsClientConnection *source)
319 g_tls_client_connection_openssl_client_connection_interface_init (GTlsClientConnectionInterface *iface)
321 iface->copy_session_state = g_tls_client_connection_openssl_copy_session_state;
324 static int data_index = -1;
327 retrieve_certificate (SSL *ssl,
331 GTlsClientConnectionOpenssl *client;
332 GTlsClientConnectionOpensslPrivate *priv;
333 GTlsConnectionBase *tls;
334 GTlsConnectionOpenssl *openssl;
335 GTlsCertificate *cert;
336 gboolean set_certificate = FALSE;
338 client = SSL_get_ex_data (ssl, data_index);
339 tls = G_TLS_CONNECTION_BASE (client);
340 openssl = G_TLS_CONNECTION_OPENSSL (client);
342 priv = g_tls_client_connection_openssl_get_instance_private (client);
344 tls->certificate_requested = TRUE;
346 priv->ca_list = SSL_get_client_CA_list (priv->ssl);
347 g_object_notify (G_OBJECT (client), "accepted-cas");
349 cert = g_tls_connection_get_certificate (G_TLS_CONNECTION (client));
351 set_certificate = TRUE;
354 g_clear_error (&tls->certificate_error);
355 if (g_tls_connection_openssl_request_certificate (openssl, &tls->certificate_error))
357 cert = g_tls_connection_get_certificate (G_TLS_CONNECTION (client));
358 set_certificate = (cert != NULL);
366 key = g_tls_certificate_openssl_get_key (G_TLS_CERTIFICATE_OPENSSL (cert));
367 /* increase ref count */
368 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined (LIBRESSL_VERSION_NUMBER)
369 CRYPTO_add (&key->references, 1, CRYPTO_LOCK_EVP_PKEY);
371 EVP_PKEY_up_ref (key);
375 *x509 = X509_dup (g_tls_certificate_openssl_get_cert (G_TLS_CERTIFICATE_OPENSSL (cert)));
384 generate_session_id (SSL *ssl,
386 unsigned int *id_len)
388 GTlsClientConnectionOpenssl *client;
389 GTlsClientConnectionOpensslPrivate *priv;
392 client = SSL_get_ex_data (ssl, data_index);
393 priv = g_tls_client_connection_openssl_get_instance_private (client);
395 len = MIN (*id_len, g_bytes_get_size (priv->session_id));
396 memcpy (id, g_bytes_get_data (priv->session_id, NULL), len);
402 set_cipher_list (GTlsClientConnectionOpenssl *client,
405 GTlsClientConnectionOpensslPrivate *priv;
406 const gchar *cipher_list;
408 priv = g_tls_client_connection_openssl_get_instance_private (client);
410 cipher_list = g_getenv ("G_TLS_OPENSSL_CIPHER_LIST");
411 if (cipher_list == NULL)
412 cipher_list = DEFAULT_CIPHER_LIST;
414 if (!SSL_CTX_set_cipher_list (priv->ssl_ctx, cipher_list))
416 g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
417 _("Could not create TLS context: %s"),
418 ERR_error_string (ERR_get_error (), NULL));
425 #ifdef SSL_CTX_set1_sigalgs_list
427 set_signature_algorithm_list (GTlsClientConnectionOpenssl *client)
429 GTlsClientConnectionOpensslPrivate *priv;
430 const gchar *signature_algorithm_list;
432 priv = g_tls_client_connection_openssl_get_instance_private (client);
434 signature_algorithm_list = g_getenv ("G_TLS_OPENSSL_SIGNATURE_ALGORITHM_LIST");
435 if (signature_algorithm_list == NULL)
438 SSL_CTX_set1_sigalgs_list (priv->ssl_ctx, signature_algorithm_list);
442 #ifdef SSL_CTX_set1_curves_list
444 set_curve_list (GTlsClientConnectionOpenssl *client)
446 GTlsClientConnectionOpensslPrivate *priv;
447 const gchar *curve_list;
449 priv = g_tls_client_connection_openssl_get_instance_private (client);
451 curve_list = g_getenv ("G_TLS_OPENSSL_CURVE_LIST");
452 if (curve_list == NULL)
455 SSL_CTX_set1_curves_list (priv->ssl_ctx, curve_list);
462 return g_getenv ("G_TLS_OPENSSL_OCSP_ENABLED") != NULL;
466 g_tls_client_connection_openssl_initable_init (GInitable *initable,
467 GCancellable *cancellable,
470 GTlsClientConnectionOpenssl *client = G_TLS_CLIENT_CONNECTION_OPENSSL (initable);
471 GTlsClientConnectionOpensslPrivate *priv;
473 const char *hostname;
475 priv = g_tls_client_connection_openssl_get_instance_private (client);
477 priv->session = SSL_SESSION_new ();
479 priv->ssl_ctx = SSL_CTX_new (SSLv23_client_method ());
480 if (priv->ssl_ctx == NULL)
482 g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
483 _("Could not create TLS context: %s"),
484 ERR_error_string (ERR_get_error (), NULL));
488 if (!set_cipher_list (client, error))
491 /* Only TLS 1.2 or higher */
492 options = SSL_OP_NO_TICKET |
493 SSL_OP_NO_COMPRESSION |
494 #ifdef SSL_OP_NO_TLSv1_1
500 SSL_CTX_set_options (priv->ssl_ctx, options);
502 SSL_CTX_clear_options (priv->ssl_ctx, SSL_OP_LEGACY_SERVER_CONNECT);
504 hostname = get_server_identity (client);
506 #if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined (LIBRESSL_VERSION_NUMBER)
509 X509_VERIFY_PARAM *param;
511 param = X509_VERIFY_PARAM_new ();
512 X509_VERIFY_PARAM_set1_host (param, hostname, 0);
513 SSL_CTX_set1_param (priv->ssl_ctx, param);
514 X509_VERIFY_PARAM_free (param);
518 SSL_CTX_set_generate_session_id (priv->ssl_ctx, (GEN_SESSION_CB)generate_session_id);
520 SSL_CTX_add_session (priv->ssl_ctx, priv->session);
522 SSL_CTX_set_client_cert_cb (priv->ssl_ctx, retrieve_certificate);
524 #ifdef SSL_CTX_set1_sigalgs_list
525 set_signature_algorithm_list (client);
528 #ifdef SSL_CTX_set1_curves_list
529 set_curve_list (client);
532 priv->ssl = SSL_new (priv->ssl_ctx);
533 if (priv->ssl == NULL)
535 g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
536 _("Could not create TLS connection: %s"),
537 ERR_error_string (ERR_get_error (), NULL));
541 if (data_index == -1) {
542 data_index = SSL_get_ex_new_index (0, (void *)"gtlsclientconnection", NULL, NULL, NULL);
544 SSL_set_ex_data (priv->ssl, data_index, client);
546 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
548 SSL_set_tlsext_host_name (priv->ssl, hostname);
551 SSL_set_connect_state (priv->ssl);
553 #if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
554 !defined(OPENSSL_NO_OCSP)
556 SSL_set_tlsext_status_type (priv->ssl, TLSEXT_STATUSTYPE_ocsp);
559 if (!g_tls_client_connection_openssl_parent_initable_iface->
560 init (initable, cancellable, error))
567 g_tls_client_connection_openssl_initable_interface_init (GInitableIface *iface)
569 g_tls_client_connection_openssl_parent_initable_iface = g_type_interface_peek_parent (iface);
571 iface->init = g_tls_client_connection_openssl_initable_init;