Imported Upstream version 2.72.alpha
[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
306 static int
307 handshake_thread_retrieve_certificate (SSL       *ssl,
308                                        X509     **x509,
309                                        EVP_PKEY **pkey)
310 {
311   GTlsClientConnectionOpenssl *client;
312   GTlsConnectionBase *tls;
313   GTlsCertificate *cert;
314
315   client = SSL_get_ex_data (ssl, data_index);
316   tls = G_TLS_CONNECTION_BASE (client);
317
318   client->ca_list = SSL_get_client_CA_list (client->ssl);
319
320   cert = g_tls_connection_get_certificate (G_TLS_CONNECTION (client));
321   if (!cert)
322     {
323       if (g_tls_connection_base_handshake_thread_request_certificate (tls))
324         cert = g_tls_connection_get_certificate (G_TLS_CONNECTION (client));
325     }
326
327   if (cert)
328     {
329       EVP_PKEY *key;
330
331       key = g_tls_certificate_openssl_get_key (G_TLS_CERTIFICATE_OPENSSL (cert));
332
333       if (key != NULL)
334         {
335           /* increase ref count */
336 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined (LIBRESSL_VERSION_NUMBER)
337           CRYPTO_add (&key->references, 1, CRYPTO_LOCK_EVP_PKEY);
338 #else
339           EVP_PKEY_up_ref (key);
340 #endif
341           *pkey = key;
342
343           *x509 = X509_dup (g_tls_certificate_openssl_get_cert (G_TLS_CERTIFICATE_OPENSSL (cert)));
344
345           return 1;
346         }
347     }
348
349   g_tls_connection_base_handshake_thread_set_missing_requested_client_certificate (tls);
350
351   return 0;
352 }
353
354 static gboolean
355 set_cipher_list (GTlsClientConnectionOpenssl  *client,
356                  GError                      **error)
357 {
358   const gchar *cipher_list;
359
360   cipher_list = g_getenv ("G_TLS_OPENSSL_CIPHER_LIST");
361   if (cipher_list)
362     {
363       if (!SSL_CTX_set_cipher_list (client->ssl_ctx, cipher_list))
364         {
365           char error_buffer[256];
366           ERR_error_string_n (ERR_get_error (), error_buffer, sizeof (error_buffer));
367           g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
368                        _("Could not set TLS cipher list: %s"),
369                        error_buffer);
370           return FALSE;
371         }
372     }
373
374   return TRUE;
375 }
376
377 static gboolean
378 set_max_protocol (GTlsClientConnectionOpenssl  *client,
379                   GError                      **error)
380 {
381 #ifdef SSL_CTX_set_max_proto_version
382   const gchar *proto;
383
384   proto = g_getenv ("G_TLS_OPENSSL_MAX_PROTO");
385   if (proto)
386     {
387       gint64 version = g_ascii_strtoll (proto, NULL, 0);
388
389       if (version > 0 && version < G_MAXINT)
390         {
391           if (!SSL_CTX_set_max_proto_version (client->ssl_ctx, (int)version))
392             {
393               char error_buffer[256];
394               ERR_error_string_n (ERR_get_error (), error_buffer, sizeof (error_buffer));
395               g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
396                            _("Could not set MAX protocol to %d: %s"),
397                            (int)version, error_buffer);
398               return FALSE;
399             }
400         }
401     }
402 #endif
403
404   return TRUE;
405 }
406
407 #ifdef SSL_CTX_set1_sigalgs_list
408 static void
409 set_signature_algorithm_list (GTlsClientConnectionOpenssl *client)
410 {
411   const gchar *signature_algorithm_list;
412
413   signature_algorithm_list = g_getenv ("G_TLS_OPENSSL_SIGNATURE_ALGORITHM_LIST");
414   if (!signature_algorithm_list)
415     return;
416
417   SSL_CTX_set1_sigalgs_list (client->ssl_ctx, signature_algorithm_list);
418 }
419 #endif
420
421 #ifdef SSL_CTX_set1_curves_list
422 static void
423 set_curve_list (GTlsClientConnectionOpenssl *client)
424 {
425   const gchar *curve_list;
426
427   curve_list = g_getenv ("G_TLS_OPENSSL_CURVE_LIST");
428   if (!curve_list)
429     return;
430
431   SSL_CTX_set1_curves_list (client->ssl_ctx, curve_list);
432 }
433 #endif
434
435 static gboolean
436 g_tls_client_connection_openssl_initable_init (GInitable       *initable,
437                                                GCancellable    *cancellable,
438                                                GError         **error)
439 {
440   GTlsClientConnectionOpenssl *client = G_TLS_CLIENT_CONNECTION_OPENSSL (initable);
441   long options;
442   const char *hostname;
443   char error_buffer[256];
444
445   client->session = SSL_SESSION_new ();
446
447   client->ssl_ctx = SSL_CTX_new (g_tls_connection_base_is_dtls (G_TLS_CONNECTION_BASE (client))
448 #if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined (LIBRESSL_VERSION_NUMBER)
449                                  ? DTLS_client_method ()
450                                  : TLS_client_method ());
451 #else
452                                  ? DTLSv1_client_method ()
453                                  : SSLv23_client_method ());
454 #endif
455   if (!client->ssl_ctx)
456     {
457       ERR_error_string_n (ERR_get_error (), error_buffer, sizeof (error_buffer));
458       g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
459                    _("Could not create TLS context: %s"),
460                    error_buffer);
461       return FALSE;
462     }
463
464   if (!set_cipher_list (client, error))
465     return FALSE;
466
467   if (!set_max_protocol (client, error))
468     return FALSE;
469
470   /* Only TLS 1.2 or higher */
471   options = SSL_OP_NO_TICKET |
472             SSL_OP_NO_COMPRESSION |
473 #ifdef SSL_OP_NO_TLSv1_1
474             SSL_OP_NO_TLSv1_1 |
475 #endif
476             SSL_OP_NO_SSLv2 |
477             SSL_OP_NO_SSLv3 |
478             SSL_OP_NO_TLSv1;
479   SSL_CTX_set_options (client->ssl_ctx, options);
480
481   SSL_CTX_clear_options (client->ssl_ctx, SSL_OP_LEGACY_SERVER_CONNECT);
482
483   hostname = get_server_identity (client);
484
485   if (hostname)
486     {
487       X509_VERIFY_PARAM *param;
488
489       param = X509_VERIFY_PARAM_new ();
490       X509_VERIFY_PARAM_set1_host (param, hostname, 0);
491       SSL_CTX_set1_param (client->ssl_ctx, param);
492       X509_VERIFY_PARAM_free (param);
493     }
494
495   SSL_CTX_add_session (client->ssl_ctx, client->session);
496
497   SSL_CTX_set_client_cert_cb (client->ssl_ctx, handshake_thread_retrieve_certificate);
498
499 #ifdef SSL_CTX_set1_sigalgs_list
500   set_signature_algorithm_list (client);
501 #endif
502
503 #ifdef SSL_CTX_set1_curves_list
504   set_curve_list (client);
505 #endif
506
507   client->ssl = SSL_new (client->ssl_ctx);
508   if (!client->ssl)
509     {
510       ERR_error_string_n (ERR_get_error (), error_buffer, sizeof (error_buffer));
511       g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
512                    _("Could not create TLS connection: %s"),
513                    error_buffer);
514       return FALSE;
515     }
516
517   if (data_index == -1) {
518       data_index = SSL_get_ex_new_index (0, (void *)"gtlsclientconnection", NULL, NULL, NULL);
519   }
520   SSL_set_ex_data (client->ssl, data_index, client);
521
522 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
523   if (hostname && !g_hostname_is_ip_address (hostname))
524     SSL_set_tlsext_host_name (client->ssl, hostname);
525 #endif
526
527   SSL_set_connect_state (client->ssl);
528
529 #if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
530     !defined(OPENSSL_NO_OCSP)
531   SSL_set_tlsext_status_type (client->ssl, TLSEXT_STATUSTYPE_ocsp);
532 #endif
533
534   if (!g_tls_client_connection_openssl_parent_initable_iface->
535       init (initable, cancellable, error))
536     return FALSE;
537
538   return TRUE;
539 }
540
541 static void
542 g_tls_client_connection_openssl_initable_interface_init (GInitableIface  *iface)
543 {
544   g_tls_client_connection_openssl_parent_initable_iface = g_type_interface_peek_parent (iface);
545
546   iface->init = g_tls_client_connection_openssl_initable_init;
547 }