1 /* GIO - GLib Input, Output and Streaming Library
3 * Copyright 2009 Red Hat, Inc
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General
16 * Public License along with this library; if not, see
17 * <http://www.gnu.org/licenses/>.
24 #include <gnutls/gnutls.h>
25 #include <gnutls/x509.h>
27 #include "gtlsconnection-gnutls.h"
28 #include "gtlsbackend-gnutls.h"
29 #include "gtlscertificate-gnutls.h"
30 #include "gtlsinputstream-gnutls.h"
31 #include "gtlsoutputstream-gnutls.h"
32 #include "gtlsserverconnection-gnutls.h"
33 #include <glib/gi18n-lib.h>
35 static void g_tls_connection_gnutls_get_property (GObject *object,
39 static void g_tls_connection_gnutls_set_property (GObject *object,
43 static void g_tls_connection_gnutls_finalize (GObject *object);
45 static gboolean g_tls_connection_gnutls_handshake (GTlsConnection *connection,
46 GCancellable *cancellable,
48 static void g_tls_connection_gnutls_handshake_async (GTlsConnection *conn,
50 GCancellable *cancellable,
51 GAsyncReadyCallback callback,
53 static gboolean g_tls_connection_gnutls_handshake_finish (GTlsConnection *conn,
57 static GInputStream *g_tls_connection_gnutls_get_input_stream (GIOStream *stream);
58 static GOutputStream *g_tls_connection_gnutls_get_output_stream (GIOStream *stream);
60 static gboolean g_tls_connection_gnutls_close (GIOStream *stream,
61 GCancellable *cancellable,
63 static void g_tls_connection_gnutls_close_async (GIOStream *stream,
65 GCancellable *cancellable,
66 GAsyncReadyCallback callback,
68 static gboolean g_tls_connection_gnutls_close_finish (GIOStream *stream,
72 static ssize_t g_tls_connection_gnutls_push_func (gnutls_transport_ptr_t transport_data,
75 static ssize_t g_tls_connection_gnutls_pull_func (gnutls_transport_ptr_t transport_data,
79 static void g_tls_connection_gnutls_initable_iface_init (GInitableIface *iface);
80 static gboolean g_tls_connection_gnutls_initable_init (GInitable *initable,
81 GCancellable *cancellable,
84 static void g_tls_connection_gnutls_init_priorities (void);
86 G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GTlsConnectionGnutls, g_tls_connection_gnutls, G_TYPE_TLS_CONNECTION,
87 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
88 g_tls_connection_gnutls_initable_iface_init);
89 g_tls_connection_gnutls_init_priorities ();
97 PROP_REQUIRE_CLOSE_NOTIFY,
98 PROP_REHANDSHAKE_MODE,
99 PROP_USE_SYSTEM_CERTDB,
103 PROP_PEER_CERTIFICATE,
104 PROP_PEER_CERTIFICATE_ERRORS
107 struct _GTlsConnectionGnutlsPrivate
109 GIOStream *base_io_stream;
110 GPollableInputStream *base_istream;
111 GPollableOutputStream *base_ostream;
113 gnutls_certificate_credentials creds;
114 gnutls_session session;
116 GTlsCertificate *certificate, *peer_certificate;
117 GTlsCertificateFlags peer_certificate_errors;
118 gboolean require_close_notify;
119 GTlsRehandshakeMode rehandshake_mode;
120 gboolean is_system_certdb;
121 GTlsDatabase *database;
122 gboolean database_is_unset;
123 gboolean need_handshake, handshaking, ever_handshaked;
126 GInputStream *tls_istream;
127 GOutputStream *tls_ostream;
129 GTlsInteraction *interaction;
132 GCancellable *cancellable;
134 #ifndef GNUTLS_E_PREMATURE_TERMINATION
137 GIOCondition internal_direction;
141 g_tls_connection_gnutls_class_init (GTlsConnectionGnutlsClass *klass)
143 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
144 GTlsConnectionClass *connection_class = G_TLS_CONNECTION_CLASS (klass);
145 GIOStreamClass *iostream_class = G_IO_STREAM_CLASS (klass);
147 g_type_class_add_private (klass, sizeof (GTlsConnectionGnutlsPrivate));
149 gobject_class->get_property = g_tls_connection_gnutls_get_property;
150 gobject_class->set_property = g_tls_connection_gnutls_set_property;
151 gobject_class->finalize = g_tls_connection_gnutls_finalize;
153 connection_class->handshake = g_tls_connection_gnutls_handshake;
154 connection_class->handshake_async = g_tls_connection_gnutls_handshake_async;
155 connection_class->handshake_finish = g_tls_connection_gnutls_handshake_finish;
157 iostream_class->get_input_stream = g_tls_connection_gnutls_get_input_stream;
158 iostream_class->get_output_stream = g_tls_connection_gnutls_get_output_stream;
159 iostream_class->close_fn = g_tls_connection_gnutls_close;
160 iostream_class->close_async = g_tls_connection_gnutls_close_async;
161 iostream_class->close_finish = g_tls_connection_gnutls_close_finish;
163 g_object_class_override_property (gobject_class, PROP_BASE_IO_STREAM, "base-io-stream");
164 g_object_class_override_property (gobject_class, PROP_REQUIRE_CLOSE_NOTIFY, "require-close-notify");
165 g_object_class_override_property (gobject_class, PROP_REHANDSHAKE_MODE, "rehandshake-mode");
166 g_object_class_override_property (gobject_class, PROP_USE_SYSTEM_CERTDB, "use-system-certdb");
167 g_object_class_override_property (gobject_class, PROP_DATABASE, "database");
168 g_object_class_override_property (gobject_class, PROP_CERTIFICATE, "certificate");
169 g_object_class_override_property (gobject_class, PROP_INTERACTION, "interaction");
170 g_object_class_override_property (gobject_class, PROP_PEER_CERTIFICATE, "peer-certificate");
171 g_object_class_override_property (gobject_class, PROP_PEER_CERTIFICATE_ERRORS, "peer-certificate-errors");
175 g_tls_connection_gnutls_initable_iface_init (GInitableIface *iface)
177 iface->init = g_tls_connection_gnutls_initable_init;
181 g_tls_connection_gnutls_init (GTlsConnectionGnutls *gnutls)
183 gnutls->priv = G_TYPE_INSTANCE_GET_PRIVATE (gnutls, G_TYPE_TLS_CONNECTION_GNUTLS, GTlsConnectionGnutlsPrivate);
185 gnutls_certificate_allocate_credentials (&gnutls->priv->creds);
186 gnutls_certificate_set_verify_flags (gnutls->priv->creds,
187 GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
189 gnutls->priv->need_handshake = TRUE;
191 gnutls->priv->database_is_unset = TRUE;
192 gnutls->priv->is_system_certdb = TRUE;
195 static gnutls_priority_t priorities[2][2];
198 g_tls_connection_gnutls_init_priorities (void)
200 /* First field is "ssl3 only", second is "allow unsafe rehandshaking" */
202 gnutls_priority_init (&priorities[FALSE][FALSE],
205 gnutls_priority_init (&priorities[TRUE][FALSE],
206 "NORMAL:%COMPAT:!VERS-TLS1.2:!VERS-TLS1.1:!VERS-TLS1.0",
208 gnutls_priority_init (&priorities[FALSE][TRUE],
209 "NORMAL:%COMPAT:%UNSAFE_RENEGOTIATION",
211 gnutls_priority_init (&priorities[TRUE][TRUE],
212 "NORMAL:%COMPAT:!VERS-TLS1.2:!VERS-TLS1.1:!VERS-TLS1.0:%UNSAFE_RENEGOTIATION",
217 g_tls_connection_gnutls_set_handshake_priority (GTlsConnectionGnutls *gnutls)
219 gboolean use_ssl3, unsafe_rehandshake;
221 if (G_IS_TLS_CLIENT_CONNECTION (gnutls))
222 use_ssl3 = g_tls_client_connection_get_use_ssl3 (G_TLS_CLIENT_CONNECTION (gnutls));
225 unsafe_rehandshake = (gnutls->priv->rehandshake_mode == G_TLS_REHANDSHAKE_UNSAFELY);
226 gnutls_priority_set (gnutls->priv->session,
227 priorities[use_ssl3][unsafe_rehandshake]);
231 g_tls_connection_gnutls_initable_init (GInitable *initable,
232 GCancellable *cancellable,
235 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (initable);
238 g_return_val_if_fail (gnutls->priv->base_istream != NULL &&
239 gnutls->priv->base_ostream != NULL, FALSE);
241 /* Make sure gnutls->priv->session has been initialized (it may have
242 * already been initialized by a construct-time property setter).
244 g_tls_connection_gnutls_get_session (gnutls);
246 status = gnutls_credentials_set (gnutls->priv->session,
247 GNUTLS_CRD_CERTIFICATE,
248 gnutls->priv->creds);
251 g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
252 _("Could not create TLS connection: %s"),
253 gnutls_strerror (status));
257 /* Some servers (especially on embedded devices) use tiny keys that
258 * gnutls will reject by default. We want it to accept them.
260 gnutls_dh_set_prime_bits (gnutls->priv->session, 256);
262 gnutls_transport_set_push_function (gnutls->priv->session,
263 g_tls_connection_gnutls_push_func);
264 gnutls_transport_set_pull_function (gnutls->priv->session,
265 g_tls_connection_gnutls_pull_func);
266 gnutls_transport_set_ptr (gnutls->priv->session, gnutls);
268 gnutls->priv->tls_istream = g_tls_input_stream_gnutls_new (gnutls);
269 gnutls->priv->tls_ostream = g_tls_output_stream_gnutls_new (gnutls);
275 g_tls_connection_gnutls_finalize (GObject *object)
277 GTlsConnectionGnutls *connection = G_TLS_CONNECTION_GNUTLS (object);
279 if (connection->priv->base_io_stream)
280 g_object_unref (connection->priv->base_io_stream);
282 if (connection->priv->session)
283 gnutls_deinit (connection->priv->session);
285 if (connection->priv->tls_istream)
286 g_object_unref (connection->priv->tls_istream);
287 if (connection->priv->tls_ostream)
288 g_object_unref (connection->priv->tls_ostream);
290 if (connection->priv->creds)
291 gnutls_certificate_free_credentials (connection->priv->creds);
293 if (connection->priv->database)
294 g_object_unref (connection->priv->database);
295 if (connection->priv->certificate)
296 g_object_unref (connection->priv->certificate);
297 if (connection->priv->peer_certificate)
298 g_object_unref (connection->priv->peer_certificate);
300 g_clear_object (&connection->priv->interaction);
302 if (connection->priv->error)
303 g_error_free (connection->priv->error);
305 G_OBJECT_CLASS (g_tls_connection_gnutls_parent_class)->finalize (object);
309 g_tls_connection_gnutls_get_property (GObject *object,
314 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (object);
315 GTlsBackend *backend;
319 case PROP_BASE_IO_STREAM:
320 g_value_set_object (value, gnutls->priv->base_io_stream);
323 case PROP_REQUIRE_CLOSE_NOTIFY:
324 g_value_set_boolean (value, gnutls->priv->require_close_notify);
327 case PROP_REHANDSHAKE_MODE:
328 g_value_set_enum (value, gnutls->priv->rehandshake_mode);
331 case PROP_USE_SYSTEM_CERTDB:
332 g_value_set_boolean (value, gnutls->priv->is_system_certdb);
336 if (gnutls->priv->database_is_unset)
338 backend = g_tls_backend_get_default ();
339 gnutls->priv->database = g_tls_backend_get_default_database (backend);
340 gnutls->priv->database_is_unset = FALSE;
342 g_value_set_object (value, gnutls->priv->database);
345 case PROP_CERTIFICATE:
346 g_value_set_object (value, gnutls->priv->certificate);
349 case PROP_INTERACTION:
350 g_value_set_object (value, gnutls->priv->interaction);
353 case PROP_PEER_CERTIFICATE:
354 g_value_set_object (value, gnutls->priv->peer_certificate);
357 case PROP_PEER_CERTIFICATE_ERRORS:
358 g_value_set_flags (value, gnutls->priv->peer_certificate_errors);
362 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
367 g_tls_connection_gnutls_set_property (GObject *object,
372 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (object);
373 GInputStream *istream;
374 GOutputStream *ostream;
375 gboolean system_certdb;
376 GTlsBackend *backend;
380 case PROP_BASE_IO_STREAM:
381 if (gnutls->priv->base_io_stream)
383 g_object_unref (gnutls->priv->base_io_stream);
384 gnutls->priv->base_istream = NULL;
385 gnutls->priv->base_ostream = NULL;
387 gnutls->priv->base_io_stream = g_value_dup_object (value);
388 if (!gnutls->priv->base_io_stream)
391 istream = g_io_stream_get_input_stream (gnutls->priv->base_io_stream);
392 ostream = g_io_stream_get_output_stream (gnutls->priv->base_io_stream);
394 if (G_IS_POLLABLE_INPUT_STREAM (istream) &&
395 g_pollable_input_stream_can_poll (G_POLLABLE_INPUT_STREAM (istream)))
396 gnutls->priv->base_istream = G_POLLABLE_INPUT_STREAM (istream);
397 if (G_IS_POLLABLE_OUTPUT_STREAM (ostream) &&
398 g_pollable_output_stream_can_poll (G_POLLABLE_OUTPUT_STREAM (ostream)))
399 gnutls->priv->base_ostream = G_POLLABLE_OUTPUT_STREAM (ostream);
402 case PROP_REQUIRE_CLOSE_NOTIFY:
403 gnutls->priv->require_close_notify = g_value_get_boolean (value);
406 case PROP_REHANDSHAKE_MODE:
407 gnutls->priv->rehandshake_mode = g_value_get_enum (value);
410 case PROP_USE_SYSTEM_CERTDB:
411 system_certdb = g_value_get_boolean (value);
412 if (system_certdb != gnutls->priv->is_system_certdb)
414 g_clear_object (&gnutls->priv->database);
417 backend = g_tls_backend_get_default ();
418 gnutls->priv->database = g_tls_backend_get_default_database (backend);
420 gnutls->priv->is_system_certdb = system_certdb;
425 g_clear_object (&gnutls->priv->database);
426 gnutls->priv->database = g_value_dup_object (value);
427 gnutls->priv->is_system_certdb = FALSE;
428 gnutls->priv->database_is_unset = FALSE;
431 case PROP_CERTIFICATE:
432 if (gnutls->priv->certificate)
433 g_object_unref (gnutls->priv->certificate);
434 gnutls->priv->certificate = g_value_dup_object (value);
437 case PROP_INTERACTION:
438 g_clear_object (&gnutls->priv->interaction);
439 gnutls->priv->interaction = g_value_dup_object (value);
443 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
447 gnutls_certificate_credentials
448 g_tls_connection_gnutls_get_credentials (GTlsConnectionGnutls *gnutls)
450 return gnutls->priv->creds;
454 g_tls_connection_gnutls_get_session (GTlsConnectionGnutls *gnutls)
456 /* Ideally we would initialize gnutls->priv->session from
457 * g_tls_connection_gnutls_init(), but we can't tell if it's a
458 * client or server connection at that point... And
459 * g_tls_connection_gnutls_initiable_init() is too late, because
460 * construct-time property setters may need to modify it.
462 if (!gnutls->priv->session)
464 gboolean client = G_IS_TLS_CLIENT_CONNECTION (gnutls);
465 gnutls_init (&gnutls->priv->session, client ? GNUTLS_CLIENT : GNUTLS_SERVER);
468 return gnutls->priv->session;
472 g_tls_connection_gnutls_get_certificate (GTlsConnectionGnutls *gnutls,
475 GTlsCertificate *cert;
477 cert = g_tls_connection_get_certificate (G_TLS_CONNECTION (gnutls));
479 st->cert_type = GNUTLS_CRT_X509;
482 GTlsCertificateGnutls *gnutlscert = G_TLS_CERTIFICATE_GNUTLS (cert);
485 st->cert.x509 = gnutls_malloc (sizeof (gnutls_x509_crt_t));
486 st->cert.x509[0] = g_tls_certificate_gnutls_copy_cert (gnutlscert);
487 st->key.x509 = g_tls_certificate_gnutls_copy_key (gnutlscert);
488 st->deinit_all = TRUE;
495 begin_gnutls_io (GTlsConnectionGnutls *gnutls,
497 GCancellable *cancellable)
499 gnutls->priv->blocking = blocking;
500 gnutls->priv->cancellable = cancellable;
501 gnutls->priv->internal_direction = 0;
502 g_clear_error (&gnutls->priv->error);
506 end_gnutls_io (GTlsConnectionGnutls *gnutls,
510 gnutls->priv->cancellable = NULL;
514 g_clear_error (&gnutls->priv->error);
518 if (gnutls->priv->handshaking && !gnutls->priv->ever_handshaked)
520 if (g_error_matches (gnutls->priv->error, G_IO_ERROR, G_IO_ERROR_FAILED) ||
521 status == GNUTLS_E_UNEXPECTED_PACKET_LENGTH ||
522 status == GNUTLS_E_FATAL_ALERT_RECEIVED ||
523 status == GNUTLS_E_DECRYPTION_FAILED ||
524 status == GNUTLS_E_UNSUPPORTED_VERSION_PACKET)
526 g_clear_error (&gnutls->priv->error);
527 g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_NOT_TLS,
528 _("Peer failed to perform TLS handshake"));
529 return GNUTLS_E_PULL_ERROR;
533 if (gnutls->priv->error)
535 if (g_error_matches (gnutls->priv->error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
536 status = GNUTLS_E_AGAIN;
537 g_propagate_error (error, gnutls->priv->error);
538 gnutls->priv->error = NULL;
541 else if (status == GNUTLS_E_REHANDSHAKE)
543 if (gnutls->priv->rehandshake_mode == G_TLS_REHANDSHAKE_NEVER)
545 g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
546 _("Peer requested illegal TLS rehandshake"));
547 return GNUTLS_E_PULL_ERROR;
550 gnutls->priv->need_handshake = TRUE;
554 #ifdef GNUTLS_E_PREMATURE_TERMINATION
555 status == GNUTLS_E_PREMATURE_TERMINATION
557 status == GNUTLS_E_UNEXPECTED_PACKET_LENGTH && gnutls->priv->eof
561 if (gnutls->priv->require_close_notify)
563 g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_EOF,
564 _("TLS connection closed unexpectedly"));
574 #define BEGIN_GNUTLS_IO(gnutls, blocking, cancellable) \
575 begin_gnutls_io (gnutls, blocking, cancellable); \
578 #define END_GNUTLS_IO(gnutls, ret, errmsg, error) \
579 } while ((ret == GNUTLS_E_AGAIN || \
580 ret == GNUTLS_E_WARNING_ALERT_RECEIVED) && \
581 !gnutls->priv->error); \
582 ret = end_gnutls_io (gnutls, ret, error); \
583 if (ret < 0 && ret != GNUTLS_E_REHANDSHAKE && error && !*error) \
585 g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,\
586 errmsg, gnutls_strerror (ret)); \
591 g_tls_connection_gnutls_check (GTlsConnectionGnutls *gnutls,
592 GIOCondition condition)
594 if (!gnutls->priv->internal_direction)
597 if (gnutls->priv->handshaking || gnutls->priv->closing)
598 condition = gnutls->priv->internal_direction;
600 if (condition & G_IO_IN)
601 return g_pollable_input_stream_is_readable (gnutls->priv->base_istream);
603 return g_pollable_output_stream_is_writable (gnutls->priv->base_ostream);
609 GTlsConnectionGnutls *gnutls;
612 GSource *child_source;
613 GIOCondition current_direction;
614 } GTlsConnectionGnutlsSource;
617 gnutls_source_prepare (GSource *source,
625 gnutls_source_check (GSource *source)
631 gnutls_source_sync_child_source (GTlsConnectionGnutlsSource *gnutls_source)
633 GTlsConnectionGnutls *gnutls = gnutls_source->gnutls;
634 GSource *source = (GSource *)gnutls_source;
635 GIOCondition direction;
637 if (gnutls->priv->handshaking || gnutls->priv->closing)
638 direction = gnutls->priv->internal_direction;
639 else if (!gnutls_source->stream)
641 else if (G_IS_TLS_INPUT_STREAM_GNUTLS (gnutls_source->stream))
644 direction = G_IO_OUT;
646 if (direction == gnutls_source->current_direction)
649 if (gnutls_source->child_source)
651 g_source_remove_child_source (source, gnutls_source->child_source);
652 g_source_unref (gnutls_source->child_source);
655 if (direction & G_IO_IN)
656 gnutls_source->child_source = g_pollable_input_stream_create_source (gnutls->priv->base_istream, NULL);
658 gnutls_source->child_source = g_pollable_output_stream_create_source (gnutls->priv->base_ostream, NULL);
660 g_source_set_dummy_callback (gnutls_source->child_source);
661 g_source_add_child_source (source, gnutls_source->child_source);
662 gnutls_source->current_direction = direction;
667 gnutls_source_dispatch (GSource *source,
668 GSourceFunc callback,
671 GPollableSourceFunc func = (GPollableSourceFunc)callback;
672 GTlsConnectionGnutlsSource *gnutls_source = (GTlsConnectionGnutlsSource *)source;
675 ret = (*func) (gnutls_source->stream, user_data);
677 ret = gnutls_source_sync_child_source (gnutls_source);
683 gnutls_source_finalize (GSource *source)
685 GTlsConnectionGnutlsSource *gnutls_source = (GTlsConnectionGnutlsSource *)source;
687 g_object_unref (gnutls_source->gnutls);
689 if (gnutls_source->child_source)
690 g_source_unref (gnutls_source->child_source);
694 g_tls_connection_gnutls_source_closure_callback (GObject *stream,
697 GClosure *closure = data;
699 GValue param = { 0, };
700 GValue result_value = { 0, };
703 g_value_init (&result_value, G_TYPE_BOOLEAN);
705 g_value_init (¶m, G_TYPE_OBJECT);
706 g_value_set_object (¶m, stream);
708 g_closure_invoke (closure, &result_value, 1, ¶m, NULL);
710 result = g_value_get_boolean (&result_value);
711 g_value_unset (&result_value);
712 g_value_unset (¶m);
717 static GSourceFuncs gnutls_source_funcs =
719 gnutls_source_prepare,
721 gnutls_source_dispatch,
722 gnutls_source_finalize,
723 (GSourceFunc)g_tls_connection_gnutls_source_closure_callback,
724 (GSourceDummyMarshal)g_cclosure_marshal_generic
728 g_tls_connection_gnutls_create_source (GTlsConnectionGnutls *gnutls,
729 GIOCondition condition,
730 GCancellable *cancellable)
732 GSource *source, *cancellable_source;
733 GTlsConnectionGnutlsSource *gnutls_source;
735 source = g_source_new (&gnutls_source_funcs, sizeof (GTlsConnectionGnutlsSource));
736 g_source_set_name (source, "GTlsConnectionGnutlsSource");
737 gnutls_source = (GTlsConnectionGnutlsSource *)source;
738 gnutls_source->gnutls = g_object_ref (gnutls);
739 if (condition & G_IO_IN)
740 gnutls_source->stream = G_OBJECT (gnutls->priv->tls_istream);
741 else if (condition & G_IO_OUT)
742 gnutls_source->stream = G_OBJECT (gnutls->priv->tls_ostream);
743 gnutls_source_sync_child_source (gnutls_source);
747 cancellable_source = g_cancellable_source_new (cancellable);
748 g_source_set_dummy_callback (cancellable_source);
749 g_source_add_child_source (source, cancellable_source);
750 g_source_unref (cancellable_source);
757 set_gnutls_error (GTlsConnectionGnutls *gnutls, GIOCondition direction)
759 if (g_error_matches (gnutls->priv->error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
760 gnutls_transport_set_errno (gnutls->priv->session, EINTR);
761 else if (g_error_matches (gnutls->priv->error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
763 gnutls_transport_set_errno (gnutls->priv->session, EAGAIN);
764 gnutls->priv->internal_direction = direction;
767 gnutls_transport_set_errno (gnutls->priv->session, EIO);
771 g_tls_connection_gnutls_pull_func (gnutls_transport_ptr_t transport_data,
775 GTlsConnectionGnutls *gnutls = transport_data;
778 /* If gnutls->priv->error is non-%NULL when we're called, it means
779 * that an error previously occurred, but gnutls decided not to
780 * propagate it. So it's correct for us to just clear it. (Usually
781 * this means it ignored an EAGAIN after a short read, and now
782 * we'll return EAGAIN again, which it will obey this time.)
784 g_clear_error (&gnutls->priv->error);
786 if (gnutls->priv->blocking)
788 ret = g_input_stream_read (G_INPUT_STREAM (gnutls->priv->base_istream),
790 gnutls->priv->cancellable,
791 &gnutls->priv->error);
795 ret = g_pollable_input_stream_read_nonblocking (gnutls->priv->base_istream,
797 gnutls->priv->cancellable,
798 &gnutls->priv->error);
802 set_gnutls_error (gnutls, G_IO_IN);
803 #ifndef GNUTLS_E_PREMATURE_TERMINATION
805 gnutls->priv->eof = TRUE;
812 g_tls_connection_gnutls_push_func (gnutls_transport_ptr_t transport_data,
816 GTlsConnectionGnutls *gnutls = transport_data;
819 /* See comment in pull_func. */
820 g_clear_error (&gnutls->priv->error);
822 if (gnutls->priv->blocking)
824 ret = g_output_stream_write (G_OUTPUT_STREAM (gnutls->priv->base_ostream),
826 gnutls->priv->cancellable,
827 &gnutls->priv->error);
831 ret = g_pollable_output_stream_write_nonblocking (gnutls->priv->base_ostream,
833 gnutls->priv->cancellable,
834 &gnutls->priv->error);
837 set_gnutls_error (gnutls, G_IO_OUT);
843 handshake_internal (GTlsConnectionGnutls *gnutls,
845 GCancellable *cancellable,
848 GTlsCertificate *peer_certificate = NULL;
849 GTlsCertificateFlags peer_certificate_errors = 0;
852 if (G_IS_TLS_SERVER_CONNECTION_GNUTLS (gnutls) &&
853 gnutls->priv->ever_handshaked && !gnutls->priv->handshaking &&
854 !gnutls->priv->need_handshake)
856 BEGIN_GNUTLS_IO (gnutls, blocking, cancellable);
857 ret = gnutls_rehandshake (gnutls->priv->session);
858 END_GNUTLS_IO (gnutls, ret, _("Error performing TLS handshake: %s"), error);
864 if (!gnutls->priv->handshaking)
866 gnutls->priv->handshaking = TRUE;
868 if (gnutls->priv->peer_certificate)
870 g_object_unref (gnutls->priv->peer_certificate);
871 gnutls->priv->peer_certificate = NULL;
872 gnutls->priv->peer_certificate_errors = 0;
874 g_object_notify (G_OBJECT (gnutls), "peer-certificate");
875 g_object_notify (G_OBJECT (gnutls), "peer-certificate-errors");
878 g_tls_connection_gnutls_set_handshake_priority (gnutls);
879 G_TLS_CONNECTION_GNUTLS_GET_CLASS (gnutls)->begin_handshake (gnutls);
882 BEGIN_GNUTLS_IO (gnutls, blocking, cancellable);
883 ret = gnutls_handshake (gnutls->priv->session);
884 END_GNUTLS_IO (gnutls, ret, _("Error performing TLS handshake: %s"), error);
886 if (ret == GNUTLS_E_AGAIN)
889 gnutls->priv->handshaking = FALSE;
890 gnutls->priv->need_handshake = FALSE;
891 gnutls->priv->ever_handshaked = TRUE;
894 gnutls_certificate_type_get (gnutls->priv->session) == GNUTLS_CRT_X509)
896 GTlsCertificate *chain, *cert;
897 const gnutls_datum_t *certs;
898 unsigned int num_certs;
901 certs = gnutls_certificate_get_peers (gnutls->priv->session, &num_certs);
905 for (i = num_certs - 1; i >= 0; i--)
907 cert = g_tls_certificate_gnutls_new (&certs[i], chain);
909 g_object_unref (chain);
914 peer_certificate = chain;
917 if (peer_certificate)
919 if (!G_TLS_CONNECTION_GNUTLS_GET_CLASS (gnutls)->verify_peer (gnutls, peer_certificate, &peer_certificate_errors))
921 g_object_unref (peer_certificate);
922 g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
923 _("Unacceptable TLS certificate"));
928 G_TLS_CONNECTION_GNUTLS_GET_CLASS (gnutls)->finish_handshake (gnutls, ret == 0, error);
932 gnutls->priv->peer_certificate = peer_certificate;
933 gnutls->priv->peer_certificate_errors = peer_certificate_errors;
935 g_object_notify (G_OBJECT (gnutls), "peer-certificate");
936 g_object_notify (G_OBJECT (gnutls), "peer-certificate-errors");
945 handshake_in_progress_or_failed (GTlsConnectionGnutls *gnutls,
947 GCancellable *cancellable,
950 if (!(gnutls->priv->need_handshake || gnutls->priv->handshaking))
953 return !handshake_internal (gnutls, blocking, cancellable, error);
957 g_tls_connection_gnutls_handshake (GTlsConnection *conn,
958 GCancellable *cancellable,
961 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (conn);
963 return handshake_internal (gnutls, TRUE, cancellable, error);
967 g_tls_connection_gnutls_handshake_ready (GObject *pollable_stream,
970 GTlsConnectionGnutls *gnutls;
971 GSimpleAsyncResult *simple = user_data;
973 GError *error = NULL;
975 gnutls = G_TLS_CONNECTION_GNUTLS (g_async_result_get_source_object (G_ASYNC_RESULT (simple)));
976 g_object_unref (gnutls);
978 success = handshake_internal (gnutls, FALSE, NULL, &error);
979 if (!success && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
981 g_error_free (error);
987 g_simple_async_result_set_from_error (simple, error);
988 g_error_free (error);
991 g_simple_async_result_set_op_res_gboolean (simple, success);
992 g_simple_async_result_complete (simple);
993 g_object_unref (simple);
999 g_tls_connection_gnutls_handshake_async (GTlsConnection *conn,
1001 GCancellable *cancellable,
1002 GAsyncReadyCallback callback,
1005 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (conn);
1006 GSimpleAsyncResult *simple;
1008 GError *error = NULL;
1011 simple = g_simple_async_result_new (G_OBJECT (conn), callback, user_data,
1012 g_tls_connection_gnutls_handshake_async);
1013 success = handshake_internal (gnutls, FALSE, cancellable, &error);
1016 g_simple_async_result_set_op_res_gboolean (simple, TRUE);
1017 g_simple_async_result_complete_in_idle (simple);
1018 g_object_unref (simple);
1020 else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
1022 g_simple_async_result_set_from_error (simple, error);
1023 g_error_free (error);
1024 g_simple_async_result_complete_in_idle (simple);
1025 g_object_unref (simple);
1028 g_error_free (error);
1030 source = g_tls_connection_gnutls_create_source (gnutls, 0, cancellable);
1031 g_source_set_callback (source,
1032 (GSourceFunc) g_tls_connection_gnutls_handshake_ready,
1034 g_source_set_priority (source, io_priority);
1035 g_source_attach (source, g_main_context_get_thread_default ());
1036 g_source_unref (source);
1040 g_tls_connection_gnutls_handshake_finish (GTlsConnection *conn,
1041 GAsyncResult *result,
1044 GSimpleAsyncResult *simple;
1046 g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (conn), g_tls_connection_gnutls_handshake_async), FALSE);
1048 simple = G_SIMPLE_ASYNC_RESULT (result);
1050 if (g_simple_async_result_propagate_error (simple, error))
1053 return g_simple_async_result_get_op_res_gboolean (simple);
1057 g_tls_connection_gnutls_read (GTlsConnectionGnutls *gnutls,
1061 GCancellable *cancellable,
1067 if (handshake_in_progress_or_failed (gnutls, blocking, cancellable, error))
1070 BEGIN_GNUTLS_IO (gnutls, blocking, cancellable);
1071 ret = gnutls_record_recv (gnutls->priv->session, buffer, count);
1072 END_GNUTLS_IO (gnutls, ret, _("Error reading data from TLS socket: %s"), error);
1076 else if (ret == GNUTLS_E_REHANDSHAKE)
1083 g_tls_connection_gnutls_write (GTlsConnectionGnutls *gnutls,
1087 GCancellable *cancellable,
1093 if (handshake_in_progress_or_failed (gnutls, blocking, cancellable, error))
1096 BEGIN_GNUTLS_IO (gnutls, blocking, cancellable);
1097 ret = gnutls_record_send (gnutls->priv->session, buffer, count);
1098 END_GNUTLS_IO (gnutls, ret, _("Error writing data to TLS socket: %s"), error);
1102 else if (ret == GNUTLS_E_REHANDSHAKE)
1108 static GInputStream *
1109 g_tls_connection_gnutls_get_input_stream (GIOStream *stream)
1111 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (stream);
1113 return gnutls->priv->tls_istream;
1116 static GOutputStream *
1117 g_tls_connection_gnutls_get_output_stream (GIOStream *stream)
1119 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (stream);
1121 return gnutls->priv->tls_ostream;
1125 close_internal (GTlsConnectionGnutls *gnutls,
1127 GCancellable *cancellable,
1132 /* If we haven't finished the initial handshake yet, there's no
1133 * reason to finish it just so we can close.
1135 if (gnutls->priv->handshaking && !gnutls->priv->ever_handshaked)
1138 if (handshake_in_progress_or_failed (gnutls, blocking, cancellable, error))
1141 gnutls->priv->closing = TRUE;
1142 BEGIN_GNUTLS_IO (gnutls, blocking, cancellable);
1143 ret = gnutls_bye (gnutls->priv->session, GNUTLS_SHUT_WR);
1144 END_GNUTLS_IO (gnutls, ret, _("Error performing TLS close: %s"), error);
1145 if (ret == 0 || !error || !g_error_matches (*error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
1146 gnutls->priv->closing = FALSE;
1152 g_tls_connection_gnutls_close (GIOStream *stream,
1153 GCancellable *cancellable,
1156 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (stream);
1158 if (!close_internal (gnutls, TRUE, cancellable, error))
1160 return g_io_stream_close (gnutls->priv->base_io_stream,
1161 cancellable, error);
1165 GSimpleAsyncResult *simple;
1166 GCancellable *cancellable;
1171 close_base_stream_cb (GObject *base_stream,
1172 GAsyncResult *result,
1176 GError *error = NULL;
1177 AsyncCloseData *acd = user_data;
1179 success = g_io_stream_close_finish (G_IO_STREAM (base_stream),
1182 g_simple_async_result_set_op_res_gboolean (acd->simple, TRUE);
1185 g_simple_async_result_set_from_error (acd->simple, error);
1186 g_error_free (error);
1189 g_simple_async_result_complete (acd->simple);
1190 g_object_unref (acd->simple);
1191 if (acd->cancellable)
1192 g_object_unref (acd->cancellable);
1193 g_slice_free (AsyncCloseData, acd);
1197 g_tls_connection_gnutls_close_ready (GObject *pollable_stream,
1200 GTlsConnectionGnutls *gnutls;
1201 AsyncCloseData *acd = user_data;
1203 GError *error = NULL;
1205 gnutls = G_TLS_CONNECTION_GNUTLS (g_async_result_get_source_object (G_ASYNC_RESULT (acd->simple)));
1206 g_object_unref (gnutls);
1208 success = close_internal (gnutls, FALSE, NULL, &error);
1209 if (!success && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
1211 g_error_free (error);
1217 g_simple_async_result_set_from_error (acd->simple, error);
1218 g_simple_async_result_complete (acd->simple);
1219 g_error_free (error);
1220 g_object_unref (acd->simple);
1221 if (acd->cancellable)
1222 g_object_unref (acd->cancellable);
1223 g_slice_free (AsyncCloseData, acd);
1227 g_io_stream_close_async (gnutls->priv->base_io_stream,
1228 acd->io_priority, acd->cancellable,
1229 close_base_stream_cb, acd);
1236 g_tls_connection_gnutls_close_async (GIOStream *stream,
1238 GCancellable *cancellable,
1239 GAsyncReadyCallback callback,
1242 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (stream);
1243 GSimpleAsyncResult *simple;
1245 GError *error = NULL;
1246 AsyncCloseData *acd;
1249 simple = g_simple_async_result_new (G_OBJECT (stream), callback, user_data,
1250 g_tls_connection_gnutls_close_async);
1252 success = close_internal (gnutls, FALSE, cancellable, &error);
1253 if (error && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
1255 g_simple_async_result_set_from_error (simple, error);
1256 g_error_free (error);
1257 g_simple_async_result_complete_in_idle (simple);
1258 g_object_unref (simple);
1262 g_error_free (error);
1264 acd = g_slice_new (AsyncCloseData);
1265 acd->simple = simple;
1266 acd->cancellable = cancellable ? g_object_ref (cancellable) : cancellable;
1267 acd->io_priority = io_priority;
1271 g_io_stream_close_async (gnutls->priv->base_io_stream,
1272 io_priority, cancellable,
1273 close_base_stream_cb, acd);
1277 source = g_tls_connection_gnutls_create_source (gnutls, 0, acd->cancellable);
1278 g_source_set_callback (source,
1279 (GSourceFunc) g_tls_connection_gnutls_close_ready,
1281 g_source_set_priority (source, acd->io_priority);
1282 g_source_attach (source, g_main_context_get_thread_default ());
1283 g_source_unref (source);
1287 g_tls_connection_gnutls_close_finish (GIOStream *stream,
1288 GAsyncResult *result,
1291 GSimpleAsyncResult *simple;
1293 g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (stream), g_tls_connection_gnutls_close_async), FALSE);
1295 simple = G_SIMPLE_ASYNC_RESULT (result);
1297 if (g_simple_async_result_propagate_error (simple, error))
1300 return g_simple_async_result_get_op_res_gboolean (simple);