facc0a779719fad22404afd27fbccec792d7d3c1
[platform/upstream/glib-networking.git] / tls / openssl / gtlsclientconnection-openssl.c
1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /*
3  * gtlsclientconnection-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 #include "glib.h"
28
29 #include <errno.h>
30 #include <string.h>
31
32 #include "openssl-include.h"
33 #include "gtlsconnection-base.h"
34 #include "gtlsclientconnection-openssl.h"
35 #include "gtlsbackend-openssl.h"
36 #include "gtlscertificate-openssl.h"
37 #include "gtlsdatabase-openssl.h"
38 #include <glib/gi18n-lib.h>
39
40 struct _GTlsClientConnectionOpenssl
41 {
42   GTlsConnectionOpenssl parent_instance;
43
44   GTlsCertificateFlags validation_flags;
45   GSocketConnectable *server_identity;
46   gboolean use_ssl3;
47
48   STACK_OF (X509_NAME) *ca_list;
49
50   SSL_SESSION *session;
51   SSL *ssl;
52   SSL_CTX *ssl_ctx;
53 };
54
55 enum
56 {
57   PROP_0,
58   PROP_VALIDATION_FLAGS,
59   PROP_SERVER_IDENTITY,
60   PROP_USE_SSL3,
61   PROP_ACCEPTED_CAS
62 };
63
64 static void g_tls_client_connection_openssl_initable_interface_init (GInitableIface  *iface);
65
66 static void g_tls_client_connection_openssl_client_connection_interface_init (GTlsClientConnectionInterface *iface);
67
68 static GInitableIface *g_tls_client_connection_openssl_parent_initable_iface;
69
70 G_DEFINE_TYPE_WITH_CODE (GTlsClientConnectionOpenssl, g_tls_client_connection_openssl, G_TYPE_TLS_CONNECTION_OPENSSL,
71                          G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
72                                                 g_tls_client_connection_openssl_initable_interface_init)
73                          G_IMPLEMENT_INTERFACE (G_TYPE_TLS_CLIENT_CONNECTION,
74                                                 g_tls_client_connection_openssl_client_connection_interface_init)
75                          G_IMPLEMENT_INTERFACE (G_TYPE_DTLS_CLIENT_CONNECTION,
76                                                 NULL));
77
78 static void
79 g_tls_client_connection_openssl_finalize (GObject *object)
80 {
81   GTlsClientConnectionOpenssl *openssl = G_TLS_CLIENT_CONNECTION_OPENSSL (object);
82
83   g_clear_object (&openssl->server_identity);
84
85   SSL_free (openssl->ssl);
86   SSL_CTX_free (openssl->ssl_ctx);
87   SSL_SESSION_free (openssl->session);
88
89   G_OBJECT_CLASS (g_tls_client_connection_openssl_parent_class)->finalize (object);
90 }
91
92 static const gchar *
93 get_server_identity (GTlsClientConnectionOpenssl *openssl)
94 {
95   if (G_IS_NETWORK_ADDRESS (openssl->server_identity))
96     return g_network_address_get_hostname (G_NETWORK_ADDRESS (openssl->server_identity));
97   else if (G_IS_NETWORK_SERVICE (openssl->server_identity))
98     return g_network_service_get_domain (G_NETWORK_SERVICE (openssl->server_identity));
99   else
100     return NULL;
101 }
102
103 static void
104 g_tls_client_connection_openssl_get_property (GObject    *object,
105                                              guint       prop_id,
106                                              GValue     *value,
107                                              GParamSpec *pspec)
108 {
109   GTlsClientConnectionOpenssl *openssl = G_TLS_CLIENT_CONNECTION_OPENSSL (object);
110   GList *accepted_cas;
111   gint i;
112
113   switch (prop_id)
114     {
115     case PROP_VALIDATION_FLAGS:
116       g_value_set_flags (value, openssl->validation_flags);
117       break;
118
119     case PROP_SERVER_IDENTITY:
120       g_value_set_object (value, openssl->server_identity);
121       break;
122
123     case PROP_USE_SSL3:
124       g_value_set_boolean (value, openssl->use_ssl3);
125       break;
126
127     case PROP_ACCEPTED_CAS:
128       accepted_cas = NULL;
129       if (openssl->ca_list)
130         {
131           for (i = 0; i < sk_X509_NAME_num (openssl->ca_list); ++i)
132             {
133               int size;
134
135               size = i2d_X509_NAME (sk_X509_NAME_value (openssl->ca_list, i), NULL);
136               if (size > 0)
137                 {
138                   unsigned char *ca;
139
140                   ca = g_malloc (size);
141                   size = i2d_X509_NAME (sk_X509_NAME_value (openssl->ca_list, i), &ca);
142                   if (size > 0)
143                     accepted_cas = g_list_prepend (accepted_cas, g_byte_array_new_take (
144                                                    ca, size));
145                   else
146                     g_free (ca);
147                 }
148             }
149           accepted_cas = g_list_reverse (accepted_cas);
150         }
151       g_value_set_pointer (value, accepted_cas);
152       break;
153
154     default:
155       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
156     }
157 }
158
159 static void
160 g_tls_client_connection_openssl_set_property (GObject      *object,
161                                              guint         prop_id,
162                                              const GValue *value,
163                                              GParamSpec   *pspec)
164 {
165   GTlsClientConnectionOpenssl *openssl = G_TLS_CLIENT_CONNECTION_OPENSSL (object);
166
167   switch (prop_id)
168     {
169     case PROP_VALIDATION_FLAGS:
170       openssl->validation_flags = g_value_get_flags (value);
171       break;
172
173     case PROP_SERVER_IDENTITY:
174       if (openssl->server_identity)
175         g_object_unref (openssl->server_identity);
176       openssl->server_identity = g_value_dup_object (value);
177       break;
178
179     case PROP_USE_SSL3:
180       openssl->use_ssl3 = g_value_get_boolean (value);
181       break;
182
183     default:
184       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
185     }
186 }
187
188 static void
189 g_tls_client_connection_openssl_complete_handshake (GTlsConnectionBase   *tls,
190                                                     gboolean              handshake_succeeded,
191                                                     gchar               **negotiated_protocol,
192                                                     GTlsProtocolVersion  *protocol_version,
193                                                     gchar               **ciphersuite_name,
194                                                     GError              **error)
195 {
196   GTlsClientConnectionOpenssl *client = G_TLS_CLIENT_CONNECTION_OPENSSL (tls);
197
198   if (G_TLS_CONNECTION_BASE_CLASS (g_tls_client_connection_openssl_parent_class)->complete_handshake)
199     G_TLS_CONNECTION_BASE_CLASS (g_tls_client_connection_openssl_parent_class)->complete_handshake (tls,
200                                                                                                     handshake_succeeded,
201                                                                                                     negotiated_protocol,
202                                                                                                     protocol_version,
203                                                                                                     ciphersuite_name,
204                                                                                                     error);
205
206   /* It may have changed during the handshake, but we have to wait until here
207    * because we can't emit notifies on the handshake thread.
208    */
209   g_object_notify (G_OBJECT (client), "accepted-cas");
210 }
211
212 static GTlsCertificateFlags
213 verify_ocsp_response (GTlsClientConnectionOpenssl *openssl,
214                       GTlsCertificate             *peer_certificate)
215 {
216   SSL *ssl = NULL;
217   OCSP_RESPONSE *resp = NULL;
218   GTlsDatabase *database;
219   long len = 0;
220   unsigned char *p = NULL;
221
222   ssl = g_tls_connection_openssl_get_ssl (G_TLS_CONNECTION_OPENSSL (openssl));
223   len = SSL_get_tlsext_status_ocsp_resp (ssl, &p);
224   if (p)
225     {
226       resp = d2i_OCSP_RESPONSE (NULL, (const unsigned char **)&p, len);
227       if (!resp)
228         return G_TLS_CERTIFICATE_GENERIC_ERROR;
229     }
230
231   database = g_tls_connection_get_database (G_TLS_CONNECTION (openssl));
232
233   /* If there's no database, then G_TLS_CERTIFICATE_UNKNOWN_CA must be flagged,
234    * and this function is only called if there are no flags.
235    */
236   g_assert (database);
237
238   /* Note we have to call this even if resp is NULL, because it will check
239    * whether Must-Staple is set.
240    */
241   return g_tls_database_openssl_verify_ocsp_response (G_TLS_DATABASE_OPENSSL (database),
242                                                       peer_certificate,
243                                                       resp);
244 }
245
246 static GTlsCertificateFlags
247 g_tls_client_connection_openssl_verify_peer_certificate (GTlsConnectionBase   *tls,
248                                                          GTlsCertificate      *certificate,
249                                                          GTlsCertificateFlags  flags)
250 {
251   GTlsClientConnectionOpenssl *openssl = G_TLS_CLIENT_CONNECTION_OPENSSL (tls);
252
253   if (flags == 0)
254     flags = verify_ocsp_response (openssl, certificate);
255
256   return flags;
257 }
258
259 static SSL *
260 g_tls_client_connection_openssl_get_ssl (GTlsConnectionOpenssl *connection)
261 {
262   return G_TLS_CLIENT_CONNECTION_OPENSSL (connection)->ssl;
263 }
264
265 static void
266 g_tls_client_connection_openssl_class_init (GTlsClientConnectionOpensslClass *klass)
267 {
268   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
269   GTlsConnectionBaseClass *base_class = G_TLS_CONNECTION_BASE_CLASS (klass);
270   GTlsConnectionOpensslClass *openssl_class = G_TLS_CONNECTION_OPENSSL_CLASS (klass);
271
272   gobject_class->finalize             = g_tls_client_connection_openssl_finalize;
273   gobject_class->get_property         = g_tls_client_connection_openssl_get_property;
274   gobject_class->set_property         = g_tls_client_connection_openssl_set_property;
275
276   base_class->complete_handshake      = g_tls_client_connection_openssl_complete_handshake;
277   base_class->verify_peer_certificate = g_tls_client_connection_openssl_verify_peer_certificate;
278
279   openssl_class->get_ssl              = g_tls_client_connection_openssl_get_ssl;
280
281   g_object_class_override_property (gobject_class, PROP_VALIDATION_FLAGS, "validation-flags");
282   g_object_class_override_property (gobject_class, PROP_SERVER_IDENTITY, "server-identity");
283   g_object_class_override_property (gobject_class, PROP_USE_SSL3, "use-ssl3");
284   g_object_class_override_property (gobject_class, PROP_ACCEPTED_CAS, "accepted-cas");
285 }
286
287 static void
288 g_tls_client_connection_openssl_init (GTlsClientConnectionOpenssl *openssl)
289 {
290 }
291
292 static void
293 g_tls_client_connection_openssl_copy_session_state (GTlsClientConnection *conn,
294                                                     GTlsClientConnection *source)
295 {
296 }
297
298 static void
299 g_tls_client_connection_openssl_client_connection_interface_init (GTlsClientConnectionInterface *iface)
300 {
301   iface->copy_session_state = g_tls_client_connection_openssl_copy_session_state;
302 }
303
304 static int data_index = -1;
305 #ifdef TIZEN_EXT
306 G_LOCK_DEFINE_STATIC(data_index);
307 #define DATA_INDEX_LOCK(m) G_LOCK(m)
308 #define DATA_INDEX_UNLOCK(m) G_UNLOCK(m)
309 #else
310 #define DATA_INDEX_LOCK(m)
311 #define DATA_INDEX_UNLOCK(m)
312 #endif
313
314 static int
315 handshake_thread_retrieve_certificate (SSL       *ssl,
316                                        X509     **x509,
317                                        EVP_PKEY **pkey)
318 {
319   GTlsClientConnectionOpenssl *client;
320   GTlsConnectionBase *tls;
321   GTlsCertificate *cert;
322   int idx;
323
324   DATA_INDEX_LOCK(data_index);
325   idx = data_index;
326   client = SSL_get_ex_data (ssl, data_index);
327   DATA_INDEX_UNLOCK(data_index);
328   if (!client)
329   {
330           TIZEN_LOGE("SSL_get_ex_data(%p) returns NULL.", ssl);
331           return 0;
332   }
333   tls = G_TLS_CONNECTION_BASE (client);
334
335   TIZEN_LOGI("ssl[%p] client[%p] tls[%p] data_index[%d]", ssl, client, tls, idx);
336
337   client->ca_list = SSL_get_client_CA_list (client->ssl);
338
339   cert = g_tls_connection_get_certificate (G_TLS_CONNECTION (client));
340   if (!cert)
341     {
342       if (g_tls_connection_base_handshake_thread_request_certificate (tls))
343         cert = g_tls_connection_get_certificate (G_TLS_CONNECTION (client));
344     }
345
346   if (cert)
347     {
348       EVP_PKEY *key;
349
350       key = g_tls_certificate_openssl_get_key (G_TLS_CERTIFICATE_OPENSSL (cert));
351
352       if (key != NULL)
353         {
354           /* increase ref count */
355 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined (LIBRESSL_VERSION_NUMBER)
356           CRYPTO_add (&key->references, 1, CRYPTO_LOCK_EVP_PKEY);
357 #else
358           EVP_PKEY_up_ref (key);
359 #endif
360           *pkey = key;
361
362           *x509 = X509_dup (g_tls_certificate_openssl_get_cert (G_TLS_CERTIFICATE_OPENSSL (cert)));
363
364           return 1;
365         }
366     }
367
368   g_tls_connection_base_handshake_thread_set_missing_requested_client_certificate (tls);
369
370   return 0;
371 }
372
373 static gboolean
374 set_cipher_list (GTlsClientConnectionOpenssl  *client,
375                  GError                      **error)
376 {
377   const gchar *cipher_list;
378
379   cipher_list = g_getenv ("G_TLS_OPENSSL_CIPHER_LIST");
380   if (cipher_list)
381     {
382       if (!SSL_CTX_set_cipher_list (client->ssl_ctx, cipher_list))
383         {
384           char error_buffer[256];
385           ERR_error_string_n (ERR_get_error (), error_buffer, sizeof (error_buffer));
386           g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
387                        _("Could not set TLS cipher list: %s"),
388                        error_buffer);
389           return FALSE;
390         }
391     }
392
393   return TRUE;
394 }
395
396 static gboolean
397 set_max_protocol (GTlsClientConnectionOpenssl  *client,
398                   GError                      **error)
399 {
400 #ifdef SSL_CTX_set_max_proto_version
401   const gchar *proto;
402
403   proto = g_getenv ("G_TLS_OPENSSL_MAX_PROTO");
404   if (proto)
405     {
406       gint64 version = g_ascii_strtoll (proto, NULL, 0);
407
408       if (version > 0 && version < G_MAXINT)
409         {
410           if (!SSL_CTX_set_max_proto_version (client->ssl_ctx, (int)version))
411             {
412               char error_buffer[256];
413               ERR_error_string_n (ERR_get_error (), error_buffer, sizeof (error_buffer));
414               g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
415                            _("Could not set MAX protocol to %d: %s"),
416                            (int)version, error_buffer);
417               return FALSE;
418             }
419         }
420     }
421 #endif
422
423   return TRUE;
424 }
425
426 #ifdef SSL_CTX_set1_sigalgs_list
427 static void
428 set_signature_algorithm_list (GTlsClientConnectionOpenssl *client)
429 {
430   const gchar *signature_algorithm_list;
431
432   signature_algorithm_list = g_getenv ("G_TLS_OPENSSL_SIGNATURE_ALGORITHM_LIST");
433   if (!signature_algorithm_list)
434     return;
435
436   SSL_CTX_set1_sigalgs_list (client->ssl_ctx, signature_algorithm_list);
437 }
438 #endif
439
440 #ifdef SSL_CTX_set1_curves_list
441 static void
442 set_curve_list (GTlsClientConnectionOpenssl *client)
443 {
444   const gchar *curve_list;
445
446   curve_list = g_getenv ("G_TLS_OPENSSL_CURVE_LIST");
447   if (!curve_list)
448     return;
449
450   SSL_CTX_set1_curves_list (client->ssl_ctx, curve_list);
451 }
452 #endif
453
454 static gboolean
455 g_tls_client_connection_openssl_initable_init (GInitable       *initable,
456                                                GCancellable    *cancellable,
457                                                GError         **error)
458 {
459   GTlsClientConnectionOpenssl *client = G_TLS_CLIENT_CONNECTION_OPENSSL (initable);
460   long options;
461   const char *hostname;
462   char error_buffer[256];
463
464   client->session = SSL_SESSION_new ();
465
466   client->ssl_ctx = SSL_CTX_new (g_tls_connection_base_is_dtls (G_TLS_CONNECTION_BASE (client))
467 #if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined (LIBRESSL_VERSION_NUMBER)
468                                  ? DTLS_client_method ()
469                                  : TLS_client_method ());
470 #else
471                                  ? DTLSv1_client_method ()
472                                  : SSLv23_client_method ());
473 #endif
474   if (!client->ssl_ctx)
475     {
476       ERR_error_string_n (ERR_get_error (), error_buffer, sizeof (error_buffer));
477       g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
478                    _("Could not create TLS context: %s"),
479                    error_buffer);
480       return FALSE;
481     }
482
483   if (!set_cipher_list (client, error))
484     return FALSE;
485
486   if (!set_max_protocol (client, error))
487     return FALSE;
488
489   /* Only TLS 1.2 or higher */
490   options = SSL_OP_NO_TICKET |
491             SSL_OP_NO_COMPRESSION |
492 #ifdef SSL_OP_NO_TLSv1_1
493             SSL_OP_NO_TLSv1_1 |
494 #endif
495             SSL_OP_NO_SSLv2 |
496             SSL_OP_NO_SSLv3 |
497             SSL_OP_NO_TLSv1;
498   SSL_CTX_set_options (client->ssl_ctx, options);
499
500   SSL_CTX_clear_options (client->ssl_ctx, SSL_OP_LEGACY_SERVER_CONNECT);
501
502   hostname = get_server_identity (client);
503
504   if (hostname)
505     {
506       X509_VERIFY_PARAM *param;
507
508       param = X509_VERIFY_PARAM_new ();
509       X509_VERIFY_PARAM_set1_host (param, hostname, 0);
510       SSL_CTX_set1_param (client->ssl_ctx, param);
511       X509_VERIFY_PARAM_free (param);
512     }
513
514   SSL_CTX_add_session (client->ssl_ctx, client->session);
515
516   SSL_CTX_set_client_cert_cb (client->ssl_ctx, handshake_thread_retrieve_certificate);
517
518 #ifdef SSL_CTX_set1_sigalgs_list
519   set_signature_algorithm_list (client);
520 #endif
521
522 #ifdef SSL_CTX_set1_curves_list
523   set_curve_list (client);
524 #endif
525
526   client->ssl = SSL_new (client->ssl_ctx);
527   if (!client->ssl)
528     {
529       ERR_error_string_n (ERR_get_error (), error_buffer, sizeof (error_buffer));
530       g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
531                    _("Could not create TLS connection: %s"),
532                    error_buffer);
533       return FALSE;
534     }
535
536   DATA_INDEX_LOCK(data_index);
537   if (data_index == -1) {
538       data_index = SSL_get_ex_new_index (0, (void *)"gtlsclientconnection", NULL, NULL, NULL);
539   }
540   SSL_set_ex_data (client->ssl, data_index, client);
541   DATA_INDEX_UNLOCK(data_index);
542
543 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
544   if (hostname && !g_hostname_is_ip_address (hostname))
545     SSL_set_tlsext_host_name (client->ssl, hostname);
546 #endif
547
548   SSL_set_connect_state (client->ssl);
549
550 #if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
551     !defined(OPENSSL_NO_OCSP)
552   SSL_set_tlsext_status_type (client->ssl, TLSEXT_STATUSTYPE_ocsp);
553 #endif
554
555   if (!g_tls_client_connection_openssl_parent_initable_iface->
556       init (initable, cancellable, error))
557     return FALSE;
558
559   return TRUE;
560 }
561
562 static void
563 g_tls_client_connection_openssl_initable_interface_init (GInitableIface  *iface)
564 {
565   g_tls_client_connection_openssl_parent_initable_iface = g_type_interface_peek_parent (iface);
566
567   iface->init = g_tls_client_connection_openssl_initable_init;
568 }