Add tizen dlog for debugging
[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   TIZEN_LOGI("ssl[%p] client[%p] tls[%p] openssl[%p] priv[%p] data_index[%d]",
345         ssl, client, tls, openssl, priv, data_index);
346
347   tls->certificate_requested = TRUE;
348
349   priv->ca_list = SSL_get_client_CA_list (priv->ssl);
350   g_object_notify (G_OBJECT (client), "accepted-cas");
351
352   cert = g_tls_connection_get_certificate (G_TLS_CONNECTION (client));
353   if (cert != NULL)
354     set_certificate = TRUE;
355   else
356     {
357       g_clear_error (&tls->certificate_error);
358       if (g_tls_connection_openssl_request_certificate (openssl, &tls->certificate_error))
359         {
360           cert = g_tls_connection_get_certificate (G_TLS_CONNECTION (client));
361           set_certificate = (cert != NULL);
362         }
363     }
364
365   if (set_certificate)
366     {
367       EVP_PKEY *key;
368
369       key = g_tls_certificate_openssl_get_key (G_TLS_CERTIFICATE_OPENSSL (cert));
370       /* increase ref count */
371 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined (LIBRESSL_VERSION_NUMBER)
372       CRYPTO_add (&key->references, 1, CRYPTO_LOCK_EVP_PKEY);
373 #else
374       EVP_PKEY_up_ref (key);
375 #endif
376       *pkey = key;
377
378       *x509 = X509_dup (g_tls_certificate_openssl_get_cert (G_TLS_CERTIFICATE_OPENSSL (cert)));
379
380       return 1;
381     }
382
383   return 0;
384 }
385
386 static int
387 generate_session_id (SSL           *ssl,
388                      unsigned char *id,
389                      unsigned int  *id_len)
390 {
391   GTlsClientConnectionOpenssl *client;
392   GTlsClientConnectionOpensslPrivate *priv;
393   int len;
394
395   client = SSL_get_ex_data (ssl, data_index);
396   priv = g_tls_client_connection_openssl_get_instance_private (client);
397
398   TIZEN_LOGI("ssl[%p] client[%p] priv[%p] data_index[%d]",
399                   ssl, client, priv, data_index);
400
401   len = MIN (*id_len, g_bytes_get_size (priv->session_id));
402   memcpy (id, g_bytes_get_data (priv->session_id, NULL), len);
403
404   return 1;
405 }
406
407 static gboolean
408 set_cipher_list (GTlsClientConnectionOpenssl  *client,
409                  GError                      **error)
410 {
411   GTlsClientConnectionOpensslPrivate *priv;
412   const gchar *cipher_list;
413
414   priv = g_tls_client_connection_openssl_get_instance_private (client);
415
416   cipher_list = g_getenv ("G_TLS_OPENSSL_CIPHER_LIST");
417   if (cipher_list == NULL)
418     cipher_list = DEFAULT_CIPHER_LIST;
419
420   if (!SSL_CTX_set_cipher_list (priv->ssl_ctx, cipher_list))
421     {
422       g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
423                    _("Could not create TLS context: %s"),
424                    ERR_error_string (ERR_get_error (), NULL));
425       return FALSE;
426     }
427
428   return TRUE;
429 }
430
431 #ifdef SSL_CTX_set1_sigalgs_list
432 static void
433 set_signature_algorithm_list (GTlsClientConnectionOpenssl *client)
434 {
435   GTlsClientConnectionOpensslPrivate *priv;
436   const gchar *signature_algorithm_list;
437
438   priv = g_tls_client_connection_openssl_get_instance_private (client);
439
440   signature_algorithm_list = g_getenv ("G_TLS_OPENSSL_SIGNATURE_ALGORITHM_LIST");
441   if (signature_algorithm_list == NULL)
442     return;
443
444   SSL_CTX_set1_sigalgs_list (priv->ssl_ctx, signature_algorithm_list);
445 }
446 #endif
447
448 #ifdef SSL_CTX_set1_curves_list
449 static void
450 set_curve_list (GTlsClientConnectionOpenssl *client)
451 {
452   GTlsClientConnectionOpensslPrivate *priv;
453   const gchar *curve_list;
454
455   priv = g_tls_client_connection_openssl_get_instance_private (client);
456
457   curve_list = g_getenv ("G_TLS_OPENSSL_CURVE_LIST");
458   if (curve_list == NULL)
459     return;
460
461   SSL_CTX_set1_curves_list (priv->ssl_ctx, curve_list);
462 }
463 #endif
464
465 static gboolean
466 use_ocsp (void)
467 {
468   return g_getenv ("G_TLS_OPENSSL_OCSP_ENABLED") != NULL;
469 }
470
471 static gboolean
472 g_tls_client_connection_openssl_initable_init (GInitable       *initable,
473                                                GCancellable    *cancellable,
474                                                GError         **error)
475 {
476   GTlsClientConnectionOpenssl *client = G_TLS_CLIENT_CONNECTION_OPENSSL (initable);
477   GTlsClientConnectionOpensslPrivate *priv;
478   long options;
479   const char *hostname;
480
481   priv = g_tls_client_connection_openssl_get_instance_private (client);
482
483   priv->session = SSL_SESSION_new ();
484
485   priv->ssl_ctx = SSL_CTX_new (SSLv23_client_method ());
486   if (priv->ssl_ctx == NULL)
487     {
488       g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
489                    _("Could not create TLS context: %s"),
490                    ERR_error_string (ERR_get_error (), NULL));
491       return FALSE;
492     }
493
494   if (!set_cipher_list (client, error))
495     return FALSE;
496
497   /* Only TLS 1.2 or higher */
498   options = SSL_OP_NO_TICKET |
499             SSL_OP_NO_COMPRESSION |
500 #ifdef SSL_OP_NO_TLSv1_1
501             SSL_OP_NO_TLSv1_1 |
502 #endif
503             SSL_OP_NO_SSLv2 |
504             SSL_OP_NO_SSLv3 |
505             SSL_OP_NO_TLSv1;
506   SSL_CTX_set_options (priv->ssl_ctx, options);
507
508   SSL_CTX_clear_options (priv->ssl_ctx, SSL_OP_LEGACY_SERVER_CONNECT);
509
510   hostname = get_server_identity (client);
511
512 #if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined (LIBRESSL_VERSION_NUMBER)
513   if (hostname)
514     {
515       X509_VERIFY_PARAM *param;
516
517       param = X509_VERIFY_PARAM_new ();
518       X509_VERIFY_PARAM_set1_host (param, hostname, 0);
519       SSL_CTX_set1_param (priv->ssl_ctx, param);
520       X509_VERIFY_PARAM_free (param);
521     }
522 #endif
523
524   SSL_CTX_set_generate_session_id (priv->ssl_ctx, (GEN_SESSION_CB)generate_session_id);
525
526   SSL_CTX_add_session (priv->ssl_ctx, priv->session);
527
528   SSL_CTX_set_client_cert_cb (priv->ssl_ctx, retrieve_certificate);
529
530 #ifdef SSL_CTX_set1_sigalgs_list
531   set_signature_algorithm_list (client);
532 #endif
533
534 #ifdef SSL_CTX_set1_curves_list
535   set_curve_list (client);
536 #endif
537
538   priv->ssl = SSL_new (priv->ssl_ctx);
539   if (priv->ssl == NULL)
540     {
541       g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
542                    _("Could not create TLS connection: %s"),
543                    ERR_error_string (ERR_get_error (), NULL));
544       return FALSE;
545     }
546
547   if (data_index == -1) {
548       data_index = SSL_get_ex_new_index (0, (void *)"gtlsclientconnection", NULL, NULL, NULL);
549           TIZEN_LOGI("new data_index[%d]", data_index);
550   } else {
551           TIZEN_LOGI("data_index[%d] is already exist", data_index);
552   }
553   SSL_set_ex_data (priv->ssl, data_index, client);
554   TIZEN_LOGI("[SSL] set extra data: priv->ssl[%p] data_index[%d] client[%p]", priv->ssl, data_index, client);
555
556 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
557   if (hostname)
558     SSL_set_tlsext_host_name (priv->ssl, hostname);
559 #endif
560
561   SSL_set_connect_state (priv->ssl);
562
563 #if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
564     !defined(OPENSSL_NO_OCSP)
565   if (use_ocsp())
566     SSL_set_tlsext_status_type (priv->ssl, TLSEXT_STATUSTYPE_ocsp);
567 #endif
568
569   if (!g_tls_client_connection_openssl_parent_initable_iface->
570       init (initable, cancellable, error))
571     return FALSE;
572
573   return TRUE;
574 }
575
576 static void
577 g_tls_client_connection_openssl_initable_interface_init (GInitableIface  *iface)
578 {
579   g_tls_client_connection_openssl_parent_initable_iface = g_type_interface_peek_parent (iface);
580
581   iface->init = g_tls_client_connection_openssl_initable_init;
582 }