Imported Upstream version 2.72.alpha
[platform/upstream/glib-networking.git] / tls / openssl / gtlsserverconnection-openssl.c
1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /*
3  * gtlsserverconnection-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 #include "gtlsserverconnection-openssl.h"
29 #include "gtlscertificate-openssl.h"
30
31 #include "openssl-include.h"
32 #include <glib/gi18n-lib.h>
33
34 struct _GTlsServerConnectionOpenssl
35 {
36   GTlsConnectionOpenssl parent_instance;
37
38   GTlsAuthenticationMode authentication_mode;
39   SSL_SESSION *session;
40   SSL *ssl;
41   SSL_CTX *ssl_ctx;
42 };
43
44 enum
45 {
46   PROP_0,
47   PROP_AUTHENTICATION_MODE
48 };
49
50 static void g_tls_server_connection_openssl_initable_interface_init (GInitableIface  *iface);
51
52 static void g_tls_server_connection_openssl_server_connection_interface_init (GTlsServerConnectionInterface *iface);
53
54 static GInitableIface *g_tls_server_connection_openssl_parent_initable_iface;
55
56 G_DEFINE_TYPE_WITH_CODE (GTlsServerConnectionOpenssl, g_tls_server_connection_openssl, G_TYPE_TLS_CONNECTION_OPENSSL,
57                          G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
58                                                 g_tls_server_connection_openssl_initable_interface_init)
59                          G_IMPLEMENT_INTERFACE (G_TYPE_TLS_SERVER_CONNECTION,
60                                                 g_tls_server_connection_openssl_server_connection_interface_init)
61                          G_IMPLEMENT_INTERFACE (G_TYPE_DTLS_SERVER_CONNECTION,
62                                                 NULL));
63
64 static void
65 g_tls_server_connection_openssl_finalize (GObject *object)
66 {
67   GTlsServerConnectionOpenssl *openssl = G_TLS_SERVER_CONNECTION_OPENSSL (object);
68
69   SSL_free (openssl->ssl);
70   SSL_CTX_free (openssl->ssl_ctx);
71   SSL_SESSION_free (openssl->session);
72
73   G_OBJECT_CLASS (g_tls_server_connection_openssl_parent_class)->finalize (object);
74 }
75
76 static void
77 g_tls_server_connection_openssl_get_property (GObject    *object,
78                                               guint       prop_id,
79                                               GValue     *value,
80                                               GParamSpec *pspec)
81 {
82   GTlsServerConnectionOpenssl *openssl = G_TLS_SERVER_CONNECTION_OPENSSL (object);
83
84   switch (prop_id)
85     {
86     case PROP_AUTHENTICATION_MODE:
87       g_value_set_enum (value, openssl->authentication_mode);
88       break;
89
90     default:
91       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
92     }
93 }
94
95 static void
96 g_tls_server_connection_openssl_set_property (GObject      *object,
97                                               guint         prop_id,
98                                               const GValue *value,
99                                               GParamSpec   *pspec)
100 {
101   GTlsServerConnectionOpenssl *openssl = G_TLS_SERVER_CONNECTION_OPENSSL (object);
102
103   switch (prop_id)
104     {
105     case PROP_AUTHENTICATION_MODE:
106       openssl->authentication_mode = g_value_get_enum (value);
107       break;
108
109     default:
110       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
111     }
112 }
113
114 static int
115 verify_callback (int             preverify_ok,
116                  X509_STORE_CTX *ctx)
117 {
118   return 1;
119 }
120
121 static void
122 g_tls_server_connection_openssl_prepare_handshake (GTlsConnectionBase  *tls,
123                                                    gchar              **advertised_protocols)
124 {
125   GTlsServerConnectionOpenssl *openssl = G_TLS_SERVER_CONNECTION_OPENSSL (tls);
126   GTlsConnectionBaseClass *base_class = G_TLS_CONNECTION_BASE_CLASS (g_tls_server_connection_openssl_parent_class);
127   int req_mode = 0;
128
129   switch (openssl->authentication_mode)
130     {
131     case G_TLS_AUTHENTICATION_REQUIRED:
132       req_mode = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
133       break;
134     case G_TLS_AUTHENTICATION_REQUESTED:
135       req_mode = SSL_VERIFY_PEER;
136       break;
137     case G_TLS_AUTHENTICATION_NONE:
138     default:
139       req_mode = SSL_VERIFY_NONE;
140       break;
141     }
142
143   SSL_set_verify (openssl->ssl, req_mode, verify_callback);
144   /* FIXME: is this ok? */
145   SSL_set_verify_depth (openssl->ssl, 0);
146
147   if (base_class->prepare_handshake)
148     base_class->prepare_handshake (tls, advertised_protocols);
149 }
150
151 static SSL *
152 g_tls_server_connection_openssl_get_ssl (GTlsConnectionOpenssl *connection)
153 {
154   return G_TLS_SERVER_CONNECTION_OPENSSL (connection)->ssl;
155 }
156
157 static gboolean
158 ssl_set_certificate (SSL              *ssl,
159                      GTlsCertificate  *cert,
160                      GError          **error)
161 {
162   EVP_PKEY *key;
163   X509 *x;
164   GTlsCertificate *issuer;
165   char error_buffer[256];
166
167   key = g_tls_certificate_openssl_get_key (G_TLS_CERTIFICATE_OPENSSL (cert));
168
169   if (!key)
170     {
171       g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
172                            _("Certificate has no private key"));
173       return FALSE;
174     }
175
176   /* Note, order is important. If a certificate has been set previously,
177    * OpenSSL requires that the new certificate is set _before_ the new
178    * private key is set. */
179   x = g_tls_certificate_openssl_get_cert (G_TLS_CERTIFICATE_OPENSSL (cert));
180   if (SSL_use_certificate (ssl, x) <= 0)
181     {
182       ERR_error_string_n (ERR_get_error (), error_buffer, sizeof (error_buffer));
183       g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
184                    _("There is a problem with the certificate: %s"),
185                    error_buffer);
186       return FALSE;
187     }
188
189   if (SSL_use_PrivateKey (ssl, key) <= 0)
190     {
191       ERR_error_string_n (ERR_get_error (), error_buffer, sizeof (error_buffer));
192       g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
193                    _("There is a problem with the certificate private key: %s"),
194                    error_buffer);
195       return FALSE;
196     }
197
198   if (SSL_clear_chain_certs (ssl) == 0)
199     {
200       ERR_error_string_n (ERR_get_error (), error_buffer, sizeof (error_buffer));
201       g_warning ("There was a problem clearing the chain certificates: %s",
202                  error_buffer);
203     }
204
205   /* Add all the issuers to create the full certificate chain */
206   for (issuer = g_tls_certificate_get_issuer (G_TLS_CERTIFICATE (cert));
207        issuer;
208        issuer = g_tls_certificate_get_issuer (issuer))
209     {
210       X509 *issuer_x;
211
212       issuer_x = g_tls_certificate_openssl_get_cert (G_TLS_CERTIFICATE_OPENSSL (issuer));
213
214       /* Be careful here and duplicate the certificate since the ssl object
215        * will take the ownership
216        */
217       if (SSL_add1_chain_cert (ssl, issuer_x) == 0)
218         {
219           ERR_error_string_n (ERR_get_error (), error_buffer, sizeof (error_buffer));
220           g_warning ("There was a problem adding the chain certificate: %s",
221                      error_buffer);
222         }
223     }
224
225   return TRUE;
226 }
227
228 static void
229 on_certificate_changed (GObject    *object,
230                         GParamSpec *spec,
231                         gpointer    user_data)
232 {
233   SSL *ssl;
234   GTlsCertificate *cert;
235
236   ssl = g_tls_server_connection_openssl_get_ssl (G_TLS_CONNECTION_OPENSSL (object));
237   cert = g_tls_connection_get_certificate (G_TLS_CONNECTION (object));
238
239   if (ssl && cert)
240     ssl_set_certificate (ssl, cert, NULL);
241 }
242
243 static void
244 g_tls_server_connection_openssl_class_init (GTlsServerConnectionOpensslClass *klass)
245 {
246   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
247   GTlsConnectionBaseClass *base_class = G_TLS_CONNECTION_BASE_CLASS (klass);
248   GTlsConnectionOpensslClass *connection_class = G_TLS_CONNECTION_OPENSSL_CLASS (klass);
249
250   gobject_class->finalize = g_tls_server_connection_openssl_finalize;
251   gobject_class->get_property = g_tls_server_connection_openssl_get_property;
252   gobject_class->set_property = g_tls_server_connection_openssl_set_property;
253
254   base_class->prepare_handshake = g_tls_server_connection_openssl_prepare_handshake;
255
256   connection_class->get_ssl = g_tls_server_connection_openssl_get_ssl;
257
258   g_object_class_override_property (gobject_class, PROP_AUTHENTICATION_MODE, "authentication-mode");
259 }
260
261 static void
262 g_tls_server_connection_openssl_init (GTlsServerConnectionOpenssl *openssl)
263 {
264 }
265
266 static void
267 g_tls_server_connection_openssl_server_connection_interface_init (GTlsServerConnectionInterface *iface)
268 {
269 }
270
271 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined (LIBRESSL_VERSION_NUMBER)
272 static void
273 ssl_info_callback (const SSL *ssl,
274                    int        type,
275                    int        val)
276 {
277   if ((type & SSL_CB_HANDSHAKE_DONE) != 0)
278     {
279       /* Disable renegotiation (CVE-2009-3555) */
280       ssl->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS;
281     }
282 }
283 #endif
284
285 static gboolean
286 set_cipher_list (GTlsServerConnectionOpenssl  *server,
287                  GError                      **error)
288 {
289   const gchar *cipher_list;
290
291   cipher_list = g_getenv ("G_TLS_OPENSSL_CIPHER_LIST");
292   if (cipher_list)
293     {
294       if (!SSL_CTX_set_cipher_list (server->ssl_ctx, cipher_list))
295         {
296           char error_buffer[256];
297           ERR_error_string_n (ERR_get_error (), error_buffer, sizeof (error_buffer));
298           g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
299                        _("Could not set TLS cipher list: %s"),
300                        error_buffer);
301           return FALSE;
302         }
303     }
304
305   return TRUE;
306 }
307
308 static gboolean
309 set_max_protocol (GTlsServerConnectionOpenssl  *server,
310                   GError                      **error)
311 {
312 #ifdef SSL_CTX_set_max_proto_version
313   const gchar *proto;
314
315   proto = g_getenv ("G_TLS_OPENSSL_MAX_PROTO");
316   if (proto)
317     {
318       gint64 version = g_ascii_strtoll (proto, NULL, 0);
319
320       if (version > 0 && version < G_MAXINT)
321         {
322           if (!SSL_CTX_set_max_proto_version (server->ssl_ctx, (int)version))
323             {
324               char error_buffer[256];
325               ERR_error_string_n (ERR_get_error (), error_buffer, sizeof (error_buffer));
326               g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
327                            _("Could not set MAX protocol to %d: %s"),
328                            (int)version, error_buffer);
329               return FALSE;
330             }
331         }
332     }
333 #endif
334
335   return TRUE;
336 }
337
338 #ifdef SSL_CTX_set1_sigalgs_list
339 static void
340 set_signature_algorithm_list (GTlsServerConnectionOpenssl *server)
341 {
342   const gchar *signature_algorithm_list;
343
344   signature_algorithm_list = g_getenv ("G_TLS_OPENSSL_SIGNATURE_ALGORITHM_LIST");
345   if (!signature_algorithm_list)
346     return;
347
348   SSL_CTX_set1_sigalgs_list (server->ssl_ctx, signature_algorithm_list);
349 }
350 #endif
351
352 #ifdef SSL_CTX_set1_curves_list
353 static void
354 set_curve_list (GTlsServerConnectionOpenssl *server)
355 {
356   const gchar *curve_list;
357
358   curve_list = g_getenv ("G_TLS_OPENSSL_CURVE_LIST");
359   if (!curve_list)
360     return;
361
362   SSL_CTX_set1_curves_list (server->ssl_ctx, curve_list);
363 }
364 #endif
365
366 static gboolean
367 g_tls_server_connection_openssl_initable_init (GInitable       *initable,
368                                                GCancellable    *cancellable,
369                                                GError         **error)
370 {
371   GTlsServerConnectionOpenssl *server = G_TLS_SERVER_CONNECTION_OPENSSL (initable);
372   GTlsCertificate *cert;
373   long options;
374   char error_buffer[256];
375
376   server->session = SSL_SESSION_new ();
377
378   server->ssl_ctx = SSL_CTX_new (g_tls_connection_base_is_dtls (G_TLS_CONNECTION_BASE (server))
379 #if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined (LIBRESSL_VERSION_NUMBER)
380                                  ? DTLS_server_method ()
381                                  : TLS_server_method ());
382 #else
383                                  ? DTLSv1_server_method ()
384                                  : SSLv23_server_method ());
385 #endif
386   if (!server->ssl_ctx)
387     {
388       ERR_error_string_n (ERR_get_error (), error_buffer, sizeof (error_buffer));
389       g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
390                    _("Could not create TLS context: %s"),
391                    error_buffer);
392       return FALSE;
393     }
394
395   if (!set_cipher_list (server, error))
396     return FALSE;
397
398   if (!set_max_protocol (server, error))
399     return FALSE;
400
401   /* Only TLS 1.2 or higher */
402   options = SSL_OP_NO_TICKET |
403             SSL_OP_NO_COMPRESSION |
404             SSL_OP_CIPHER_SERVER_PREFERENCE |
405             SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
406             SSL_OP_SINGLE_ECDH_USE |
407 #ifdef SSL_OP_NO_TLSv1_1
408             SSL_OP_NO_TLSv1_1 |
409 #endif
410             SSL_OP_NO_SSLv2 |
411             SSL_OP_NO_SSLv3 |
412             SSL_OP_NO_TLSv1;
413
414 #ifdef SSL_OP_NO_RENEGOTIATION
415   options |= SSL_OP_NO_RENEGOTIATION;
416 #endif
417
418   SSL_CTX_set_options (server->ssl_ctx, options);
419
420   SSL_CTX_add_session (server->ssl_ctx, server->session);
421
422 #ifdef SSL_CTX_set1_sigalgs_list
423   set_signature_algorithm_list (server);
424 #endif
425
426 #ifdef SSL_CTX_set1_curves_list
427   set_curve_list (server);
428 #endif
429
430 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined (LIBRESSL_VERSION_NUMBER)
431 # ifdef SSL_CTX_set_ecdh_auto
432   SSL_CTX_set_ecdh_auto (server->ssl_ctx, 1);
433 # else
434   {
435     EC_KEY *ecdh;
436
437     ecdh = EC_KEY_new_by_curve_name (NID_X9_62_prime256v1);
438     if (ecdh)
439       {
440         SSL_CTX_set_tmp_ecdh (server->ssl_ctx, ecdh);
441         EC_KEY_free (ecdh);
442       }
443   }
444 # endif
445
446   SSL_CTX_set_info_callback (server->ssl_ctx, ssl_info_callback);
447 #endif
448
449   cert = g_tls_connection_get_certificate (G_TLS_CONNECTION (initable));
450
451   server->ssl = SSL_new (server->ssl_ctx);
452   if (!server->ssl)
453     {
454       ERR_error_string_n (ERR_get_error (), error_buffer, sizeof (error_buffer));
455       g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
456                    _("Could not create TLS connection: %s"),
457                    error_buffer);
458       return FALSE;
459     }
460
461   if (cert && !ssl_set_certificate (server->ssl, cert, error))
462     return FALSE;
463
464   SSL_set_accept_state (server->ssl);
465
466   if (!g_tls_server_connection_openssl_parent_initable_iface->
467       init (initable, cancellable, error))
468     return FALSE;
469
470   g_signal_connect (server, "notify::certificate", G_CALLBACK (on_certificate_changed), NULL);
471
472   return TRUE;
473 }
474
475 static void
476 g_tls_server_connection_openssl_initable_interface_init (GInitableIface  *iface)
477 {
478   g_tls_server_connection_openssl_parent_initable_iface = g_type_interface_peek_parent (iface);
479
480   iface->init = g_tls_server_connection_openssl_initable_init;
481 }