70e26a0895c6588855606b41663953325550f0d4
[platform/upstream/glib-networking.git] / tls / openssl / gtlsclientconnection-openssl.c
1 /*
2  * gtlsclientconnection-openssl.c
3  *
4  * Copyright (C) 2015 NICE s.r.l.
5  *
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.
10  *
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.
15  *
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/>.
18  *
19  * In addition, when the library is used with OpenSSL, a special
20  * exception applies. Refer to the LICENSE_EXCEPTION file for details.
21  *
22  * Authors: Ignacio Casal Quinteiro
23  */
24
25 #include "config.h"
26 #include "glib.h"
27
28 #include <errno.h>
29 #include <string.h>
30
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>
37
38 #define DEFAULT_CIPHER_LIST "HIGH:!DSS:!aNULL@STRENGTH"
39
40 typedef struct _GTlsClientConnectionOpensslPrivate
41 {
42   GTlsCertificateFlags validation_flags;
43   GSocketConnectable *server_identity;
44   gboolean use_ssl3;
45   gboolean session_data_override;
46
47   GBytes *session_id;
48   GBytes *session_data;
49
50   STACK_OF (X509_NAME) *ca_list;
51
52   SSL_SESSION *session;
53   SSL *ssl;
54   SSL_CTX *ssl_ctx;
55 } GTlsClientConnectionOpensslPrivate;
56
57 enum
58 {
59   PROP_0,
60   PROP_VALIDATION_FLAGS,
61   PROP_SERVER_IDENTITY,
62   PROP_USE_SSL3,
63   PROP_ACCEPTED_CAS
64 };
65
66 static void g_tls_client_connection_openssl_initable_interface_init (GInitableIface  *iface);
67
68 static void g_tls_client_connection_openssl_client_connection_interface_init (GTlsClientConnectionInterface *iface);
69
70 static GInitableIface *g_tls_client_connection_openssl_parent_initable_iface;
71
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))
78
79 static void
80 g_tls_client_connection_openssl_finalize (GObject *object)
81 {
82   GTlsClientConnectionOpenssl *openssl = G_TLS_CLIENT_CONNECTION_OPENSSL (object);
83   GTlsClientConnectionOpensslPrivate *priv;
84
85   priv = g_tls_client_connection_openssl_get_instance_private (openssl);
86
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);
90
91   SSL_free (priv->ssl);
92   SSL_CTX_free (priv->ssl_ctx);
93   SSL_SESSION_free (priv->session);
94
95   G_OBJECT_CLASS (g_tls_client_connection_openssl_parent_class)->finalize (object);
96 }
97
98 static const gchar *
99 get_server_identity (GTlsClientConnectionOpenssl *openssl)
100 {
101   GTlsClientConnectionOpensslPrivate *priv;
102
103   priv = g_tls_client_connection_openssl_get_instance_private (openssl);
104
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));
109   else
110     return NULL;
111 }
112
113 static void
114 g_tls_client_connection_openssl_get_property (GObject    *object,
115                                              guint       prop_id,
116                                              GValue     *value,
117                                              GParamSpec *pspec)
118 {
119   GTlsClientConnectionOpenssl *openssl = G_TLS_CLIENT_CONNECTION_OPENSSL (object);
120   GTlsClientConnectionOpensslPrivate *priv;
121   GList *accepted_cas;
122   gint i;
123
124   priv = g_tls_client_connection_openssl_get_instance_private (openssl);
125
126   switch (prop_id)
127     {
128     case PROP_VALIDATION_FLAGS:
129       g_value_set_flags (value, priv->validation_flags);
130       break;
131
132     case PROP_SERVER_IDENTITY:
133       g_value_set_object (value, priv->server_identity);
134       break;
135
136     case PROP_USE_SSL3:
137       g_value_set_boolean (value, priv->use_ssl3);
138       break;
139
140     case PROP_ACCEPTED_CAS:
141       accepted_cas = NULL;
142       if (priv->ca_list)
143         {
144           for (i = 0; i < sk_X509_NAME_num (priv->ca_list); ++i)
145             {
146               int size;
147
148               size = i2d_X509_NAME (sk_X509_NAME_value (priv->ca_list, i), NULL);
149               if (size > 0)
150                 {
151                   unsigned char *ca;
152
153                   ca = g_malloc (size);
154                   size = i2d_X509_NAME (sk_X509_NAME_value (priv->ca_list, i), &ca);
155                   if (size > 0)
156                     accepted_cas = g_list_prepend (accepted_cas, g_byte_array_new_take (
157                                                    ca, size));
158                   else
159                     g_free (ca);
160                 }
161             }
162           accepted_cas = g_list_reverse (accepted_cas);
163         }
164       g_value_set_pointer (value, accepted_cas);
165       break;
166
167     default:
168       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
169     }
170 }
171
172 static void
173 g_tls_client_connection_openssl_set_property (GObject      *object,
174                                              guint         prop_id,
175                                              const GValue *value,
176                                              GParamSpec   *pspec)
177 {
178   GTlsClientConnectionOpenssl *openssl = G_TLS_CLIENT_CONNECTION_OPENSSL (object);
179   GTlsClientConnectionOpensslPrivate *priv;
180
181   priv = g_tls_client_connection_openssl_get_instance_private (openssl);
182
183   switch (prop_id)
184     {
185     case PROP_VALIDATION_FLAGS:
186       priv->validation_flags = g_value_get_flags (value);
187       break;
188
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);
193       break;
194
195     case PROP_USE_SSL3:
196       priv->use_ssl3 = g_value_get_boolean (value);
197       break;
198
199     default:
200       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
201     }
202 }
203
204 static void
205 g_tls_client_connection_openssl_constructed (GObject *object)
206 {
207   GTlsClientConnectionOpenssl *openssl = G_TLS_CLIENT_CONNECTION_OPENSSL (object);
208   GTlsClientConnectionOpensslPrivate *priv;
209   GSocketConnection *base_conn;
210   GSocketAddress *remote_addr;
211   GInetAddress *iaddr;
212   guint port;
213
214   priv = g_tls_client_connection_openssl_get_instance_private (openssl);
215
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)
222    */
223   g_object_get (G_OBJECT (openssl), "base-io-stream", &base_conn, NULL);
224   if (G_IS_SOCKET_CONNECTION (base_conn))
225     {
226       remote_addr = g_socket_connection_get_remote_address (base_conn, NULL);
227       if (G_IS_INET_SOCKET_ADDRESS (remote_addr))
228         {
229           GInetSocketAddress *isaddr = G_INET_SOCKET_ADDRESS (remote_addr);
230           const gchar *server_hostname;
231           gchar *addrstr, *session_id;
232
233           iaddr = g_inet_socket_address_get_address (isaddr);
234           port = g_inet_socket_address_get_port (isaddr);
235
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 : "",
240                                         port);
241           priv->session_id = g_bytes_new_take (session_id, strlen (session_id));
242           g_free (addrstr);
243         }
244       g_object_unref (remote_addr);
245     }
246   g_object_unref (base_conn);
247
248   G_OBJECT_CLASS (g_tls_client_connection_openssl_parent_class)->constructed (object);
249 }
250
251 static GTlsConnectionBaseStatus
252 g_tls_client_connection_openssl_handshake (GTlsConnectionBase  *tls,
253                                            GCancellable        *cancellable,
254                                            GError             **error)
255 {
256   return G_TLS_CONNECTION_BASE_CLASS (g_tls_client_connection_openssl_parent_class)->
257     handshake (tls, cancellable, error);
258 }
259
260 static GTlsConnectionBaseStatus
261 g_tls_client_connection_openssl_complete_handshake (GTlsConnectionBase  *tls,
262                                                     GError             **error)
263 {
264   GTlsConnectionBaseStatus status;
265
266   status = G_TLS_CONNECTION_BASE_CLASS (g_tls_client_connection_openssl_parent_class)->
267     complete_handshake (tls, error);
268
269   return status;
270 }
271
272 static SSL *
273 g_tls_client_connection_openssl_get_ssl (GTlsConnectionOpenssl *connection)
274 {
275   GTlsClientConnectionOpenssl *client = G_TLS_CLIENT_CONNECTION_OPENSSL (connection);
276   GTlsClientConnectionOpensslPrivate *priv;
277
278   priv = g_tls_client_connection_openssl_get_instance_private (client);
279
280   return priv->ssl;
281 }
282
283 static void
284 g_tls_client_connection_openssl_class_init (GTlsClientConnectionOpensslClass *klass)
285 {
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);
289
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;
294
295   base_class->handshake          = g_tls_client_connection_openssl_handshake;
296   base_class->complete_handshake = g_tls_client_connection_openssl_complete_handshake;
297
298   connection_class->get_ssl = g_tls_client_connection_openssl_get_ssl;
299
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");
304 }
305
306 static void
307 g_tls_client_connection_openssl_init (GTlsClientConnectionOpenssl *openssl)
308 {
309 }
310
311
312 static void
313 g_tls_client_connection_openssl_copy_session_state (GTlsClientConnection *conn,
314                                                     GTlsClientConnection *source)
315 {
316 }
317
318 static void
319 g_tls_client_connection_openssl_client_connection_interface_init (GTlsClientConnectionInterface *iface)
320 {
321   iface->copy_session_state = g_tls_client_connection_openssl_copy_session_state;
322 }
323
324 static int data_index = -1;
325
326 static int
327 retrieve_certificate (SSL       *ssl,
328                       X509     **x509,
329                       EVP_PKEY **pkey)
330 {
331   GTlsClientConnectionOpenssl *client;
332   GTlsClientConnectionOpensslPrivate *priv;
333   GTlsConnectionBase *tls;
334   GTlsConnectionOpenssl *openssl;
335   GTlsCertificate *cert;
336   gboolean set_certificate = FALSE;
337
338   client = SSL_get_ex_data (ssl, data_index);
339   tls = G_TLS_CONNECTION_BASE (client);
340   openssl = G_TLS_CONNECTION_OPENSSL (client);
341
342   priv = g_tls_client_connection_openssl_get_instance_private (client);
343
344   tls->certificate_requested = TRUE;
345
346   priv->ca_list = SSL_get_client_CA_list (priv->ssl);
347   g_object_notify (G_OBJECT (client), "accepted-cas");
348
349   cert = g_tls_connection_get_certificate (G_TLS_CONNECTION (client));
350   if (cert != NULL)
351     set_certificate = TRUE;
352   else
353     {
354       g_clear_error (&tls->certificate_error);
355       if (g_tls_connection_openssl_request_certificate (openssl, &tls->certificate_error))
356         {
357           cert = g_tls_connection_get_certificate (G_TLS_CONNECTION (client));
358           set_certificate = (cert != NULL);
359         }
360     }
361
362   if (set_certificate)
363     {
364       EVP_PKEY *key;
365
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);
370 #else
371       EVP_PKEY_up_ref (key);
372 #endif
373       *pkey = key;
374
375       *x509 = X509_dup (g_tls_certificate_openssl_get_cert (G_TLS_CERTIFICATE_OPENSSL (cert)));
376
377       return 1;
378     }
379
380   return 0;
381 }
382
383 static int
384 generate_session_id (SSL           *ssl,
385                      unsigned char *id,
386                      unsigned int  *id_len)
387 {
388   GTlsClientConnectionOpenssl *client;
389   GTlsClientConnectionOpensslPrivate *priv;
390   int len;
391
392   client = SSL_get_ex_data (ssl, data_index);
393   priv = g_tls_client_connection_openssl_get_instance_private (client);
394
395   len = MIN (*id_len, g_bytes_get_size (priv->session_id));
396   memcpy (id, g_bytes_get_data (priv->session_id, NULL), len);
397
398   return 1;
399 }
400
401 static gboolean
402 set_cipher_list (GTlsClientConnectionOpenssl  *client,
403                  GError                      **error)
404 {
405   GTlsClientConnectionOpensslPrivate *priv;
406   const gchar *cipher_list;
407
408   priv = g_tls_client_connection_openssl_get_instance_private (client);
409
410   cipher_list = g_getenv ("G_TLS_OPENSSL_CIPHER_LIST");
411   if (cipher_list == NULL)
412     cipher_list = DEFAULT_CIPHER_LIST;
413
414   if (!SSL_CTX_set_cipher_list (priv->ssl_ctx, cipher_list))
415     {
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));
419       return FALSE;
420     }
421
422   return TRUE;
423 }
424
425 #ifdef SSL_CTX_set1_sigalgs_list
426 static void
427 set_signature_algorithm_list (GTlsClientConnectionOpenssl *client)
428 {
429   GTlsClientConnectionOpensslPrivate *priv;
430   const gchar *signature_algorithm_list;
431
432   priv = g_tls_client_connection_openssl_get_instance_private (client);
433
434   signature_algorithm_list = g_getenv ("G_TLS_OPENSSL_SIGNATURE_ALGORITHM_LIST");
435   if (signature_algorithm_list == NULL)
436     return;
437
438   SSL_CTX_set1_sigalgs_list (priv->ssl_ctx, signature_algorithm_list);
439 }
440 #endif
441
442 #ifdef SSL_CTX_set1_curves_list
443 static void
444 set_curve_list (GTlsClientConnectionOpenssl *client)
445 {
446   GTlsClientConnectionOpensslPrivate *priv;
447   const gchar *curve_list;
448
449   priv = g_tls_client_connection_openssl_get_instance_private (client);
450
451   curve_list = g_getenv ("G_TLS_OPENSSL_CURVE_LIST");
452   if (curve_list == NULL)
453     return;
454
455   SSL_CTX_set1_curves_list (priv->ssl_ctx, curve_list);
456 }
457 #endif
458
459 static gboolean
460 use_ocsp (void)
461 {
462   return g_getenv ("G_TLS_OPENSSL_OCSP_ENABLED") != NULL;
463 }
464
465 static gboolean
466 g_tls_client_connection_openssl_initable_init (GInitable       *initable,
467                                                GCancellable    *cancellable,
468                                                GError         **error)
469 {
470   GTlsClientConnectionOpenssl *client = G_TLS_CLIENT_CONNECTION_OPENSSL (initable);
471   GTlsClientConnectionOpensslPrivate *priv;
472   long options;
473   const char *hostname;
474
475   priv = g_tls_client_connection_openssl_get_instance_private (client);
476
477   priv->session = SSL_SESSION_new ();
478
479   priv->ssl_ctx = SSL_CTX_new (SSLv23_client_method ());
480   if (priv->ssl_ctx == NULL)
481     {
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));
485       return FALSE;
486     }
487
488   if (!set_cipher_list (client, error))
489     return FALSE;
490
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
495             SSL_OP_NO_TLSv1_1 |
496 #endif
497             SSL_OP_NO_SSLv2 |
498             SSL_OP_NO_SSLv3 |
499             SSL_OP_NO_TLSv1;
500   SSL_CTX_set_options (priv->ssl_ctx, options);
501
502   SSL_CTX_clear_options (priv->ssl_ctx, SSL_OP_LEGACY_SERVER_CONNECT);
503
504   hostname = get_server_identity (client);
505
506 #if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined (LIBRESSL_VERSION_NUMBER)
507   if (hostname)
508     {
509       X509_VERIFY_PARAM *param;
510
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);
515     }
516 #endif
517
518   SSL_CTX_set_generate_session_id (priv->ssl_ctx, (GEN_SESSION_CB)generate_session_id);
519
520   SSL_CTX_add_session (priv->ssl_ctx, priv->session);
521
522   SSL_CTX_set_client_cert_cb (priv->ssl_ctx, retrieve_certificate);
523
524 #ifdef SSL_CTX_set1_sigalgs_list
525   set_signature_algorithm_list (client);
526 #endif
527
528 #ifdef SSL_CTX_set1_curves_list
529   set_curve_list (client);
530 #endif
531
532   priv->ssl = SSL_new (priv->ssl_ctx);
533   if (priv->ssl == NULL)
534     {
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));
538       return FALSE;
539     }
540
541   if (data_index == -1) {
542       data_index = SSL_get_ex_new_index (0, (void *)"gtlsclientconnection", NULL, NULL, NULL);
543   }
544   SSL_set_ex_data (priv->ssl, data_index, client);
545
546 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
547   if (hostname)
548     SSL_set_tlsext_host_name (priv->ssl, hostname);
549 #endif
550
551   SSL_set_connect_state (priv->ssl);
552
553 #if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
554     !defined(OPENSSL_NO_OCSP)
555   if (use_ocsp())
556     SSL_set_tlsext_status_type (priv->ssl, TLSEXT_STATUSTYPE_ocsp);
557 #endif
558
559   if (!g_tls_client_connection_openssl_parent_initable_iface->
560       init (initable, cancellable, error))
561     return FALSE;
562
563   return TRUE;
564 }
565
566 static void
567 g_tls_client_connection_openssl_initable_interface_init (GInitableIface  *iface)
568 {
569   g_tls_client_connection_openssl_parent_initable_iface = g_type_interface_peek_parent (iface);
570
571   iface->init = g_tls_client_connection_openssl_initable_init;
572 }