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