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, write to the
17 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18 * Boston, MA 02111-1307, USA.
25 #include <gnutls/gnutls.h>
26 #include <gnutls/x509.h>
28 #include "gtlsconnection-gnutls.h"
29 #include "gtlsbackend-gnutls.h"
30 #include "gtlscertificate-gnutls.h"
31 #include "gtlsinputstream-gnutls.h"
32 #include "gtlsoutputstream-gnutls.h"
33 #include "gtlsserverconnection-gnutls.h"
34 #include "gnutls-marshal.h"
35 #include <glib/gi18n-lib.h>
37 static void g_tls_connection_gnutls_get_property (GObject *object,
41 static void g_tls_connection_gnutls_set_property (GObject *object,
45 static void g_tls_connection_gnutls_finalize (GObject *object);
47 static gboolean g_tls_connection_gnutls_handshake (GTlsConnection *connection,
48 GCancellable *cancellable,
50 static void g_tls_connection_gnutls_handshake_async (GTlsConnection *conn,
52 GCancellable *cancellable,
53 GAsyncReadyCallback callback,
55 static gboolean g_tls_connection_gnutls_handshake_finish (GTlsConnection *conn,
59 static GInputStream *g_tls_connection_gnutls_get_input_stream (GIOStream *stream);
60 static GOutputStream *g_tls_connection_gnutls_get_output_stream (GIOStream *stream);
62 static gboolean g_tls_connection_gnutls_close (GIOStream *stream,
63 GCancellable *cancellable,
65 static void g_tls_connection_gnutls_close_async (GIOStream *stream,
67 GCancellable *cancellable,
68 GAsyncReadyCallback callback,
70 static gboolean g_tls_connection_gnutls_close_finish (GIOStream *stream,
74 static ssize_t g_tls_connection_gnutls_push_func (gnutls_transport_ptr_t transport_data,
77 static ssize_t g_tls_connection_gnutls_pull_func (gnutls_transport_ptr_t transport_data,
81 static void g_tls_connection_gnutls_initable_iface_init (GInitableIface *iface);
82 static gboolean g_tls_connection_gnutls_initable_init (GInitable *initable,
83 GCancellable *cancellable,
86 static void g_tls_connection_gnutls_init_priorities (void);
88 G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GTlsConnectionGnutls, g_tls_connection_gnutls, G_TYPE_TLS_CONNECTION,
89 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
90 g_tls_connection_gnutls_initable_iface_init);
91 g_tls_connection_gnutls_init_priorities ();
99 PROP_REQUIRE_CLOSE_NOTIFY,
100 PROP_REHANDSHAKE_MODE,
101 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;
114 gnutls_certificate_credentials creds;
115 gnutls_session session;
117 GTlsCertificate *certificate, *peer_certificate;
118 GTlsCertificateFlags peer_certificate_errors;
119 gboolean require_close_notify;
120 GTlsRehandshakeMode rehandshake_mode;
121 gboolean use_system_certdb;
122 gboolean need_handshake, handshaking, ever_handshaked;
125 GInputStream *tls_istream;
126 GOutputStream *tls_ostream;
129 GCancellable *cancellable;
130 gboolean blocking, eof;
131 GIOCondition internal_direction;
135 g_tls_connection_gnutls_class_init (GTlsConnectionGnutlsClass *klass)
137 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
138 GTlsConnectionClass *connection_class = G_TLS_CONNECTION_CLASS (klass);
139 GIOStreamClass *iostream_class = G_IO_STREAM_CLASS (klass);
141 g_type_class_add_private (klass, sizeof (GTlsConnectionGnutlsPrivate));
143 gobject_class->get_property = g_tls_connection_gnutls_get_property;
144 gobject_class->set_property = g_tls_connection_gnutls_set_property;
145 gobject_class->finalize = g_tls_connection_gnutls_finalize;
147 connection_class->handshake = g_tls_connection_gnutls_handshake;
148 connection_class->handshake_async = g_tls_connection_gnutls_handshake_async;
149 connection_class->handshake_finish = g_tls_connection_gnutls_handshake_finish;
151 iostream_class->get_input_stream = g_tls_connection_gnutls_get_input_stream;
152 iostream_class->get_output_stream = g_tls_connection_gnutls_get_output_stream;
153 iostream_class->close_fn = g_tls_connection_gnutls_close;
154 iostream_class->close_async = g_tls_connection_gnutls_close_async;
155 iostream_class->close_finish = g_tls_connection_gnutls_close_finish;
157 g_object_class_override_property (gobject_class, PROP_BASE_IO_STREAM, "base-io-stream");
158 g_object_class_override_property (gobject_class, PROP_REQUIRE_CLOSE_NOTIFY, "require-close-notify");
159 g_object_class_override_property (gobject_class, PROP_REHANDSHAKE_MODE, "rehandshake-mode");
160 g_object_class_override_property (gobject_class, PROP_USE_SYSTEM_CERTDB, "use-system-certdb");
161 g_object_class_override_property (gobject_class, PROP_CERTIFICATE, "certificate");
162 g_object_class_override_property (gobject_class, PROP_PEER_CERTIFICATE, "peer-certificate");
163 g_object_class_override_property (gobject_class, PROP_PEER_CERTIFICATE_ERRORS, "peer-certificate-errors");
167 g_tls_connection_gnutls_initable_iface_init (GInitableIface *iface)
169 iface->init = g_tls_connection_gnutls_initable_init;
173 g_tls_connection_gnutls_init (GTlsConnectionGnutls *gnutls)
175 gnutls->priv = G_TYPE_INSTANCE_GET_PRIVATE (gnutls, G_TYPE_TLS_CONNECTION_GNUTLS, GTlsConnectionGnutlsPrivate);
177 gnutls_certificate_allocate_credentials (&gnutls->priv->creds);
178 gnutls_certificate_set_verify_flags (gnutls->priv->creds,
179 GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
181 gnutls->priv->need_handshake = TRUE;
184 static gnutls_priority_t priorities[2][2];
187 g_tls_connection_gnutls_init_priorities (void)
189 /* First field is "ssl3 only", second is "allow unsafe rehandshaking" */
191 gnutls_priority_init (&priorities[FALSE][FALSE],
194 gnutls_priority_init (&priorities[TRUE][FALSE],
195 "NORMAL:!VERS-TLS1.2:!VERS-TLS1.1:!VERS-TLS1.0",
197 gnutls_priority_init (&priorities[FALSE][TRUE],
198 "NORMAL:%UNSAFE_RENEGOTIATION",
200 gnutls_priority_init (&priorities[TRUE][TRUE],
201 "NORMAL:!VERS-TLS1.2:!VERS-TLS1.1:!VERS-TLS1.0:%UNSAFE_RENEGOTIATION",
206 g_tls_connection_gnutls_set_handshake_priority (GTlsConnectionGnutls *gnutls)
208 gboolean use_ssl3, unsafe_rehandshake;
210 if (G_IS_TLS_CLIENT_CONNECTION (gnutls))
211 use_ssl3 = g_tls_client_connection_get_use_ssl3 (G_TLS_CLIENT_CONNECTION (gnutls));
214 unsafe_rehandshake = (gnutls->priv->rehandshake_mode == G_TLS_REHANDSHAKE_UNSAFELY);
215 gnutls_priority_set (gnutls->priv->session,
216 priorities[use_ssl3][unsafe_rehandshake]);
220 g_tls_connection_gnutls_initable_init (GInitable *initable,
221 GCancellable *cancellable,
224 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (initable);
227 g_return_val_if_fail (gnutls->priv->base_istream != NULL &&
228 gnutls->priv->base_ostream != NULL, FALSE);
230 /* Make sure gnutls->priv->session has been initialized (it may have
231 * already been initialized by a construct-time property setter).
233 g_tls_connection_gnutls_get_session (gnutls);
235 status = gnutls_credentials_set (gnutls->priv->session,
236 GNUTLS_CRD_CERTIFICATE,
237 gnutls->priv->creds);
240 g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
241 _("Could not create TLS connection: %s"),
242 gnutls_strerror (status));
246 gnutls_transport_set_push_function (gnutls->priv->session,
247 g_tls_connection_gnutls_push_func);
248 gnutls_transport_set_pull_function (gnutls->priv->session,
249 g_tls_connection_gnutls_pull_func);
250 gnutls_transport_set_ptr (gnutls->priv->session, gnutls);
252 gnutls->priv->tls_istream = g_tls_input_stream_gnutls_new (gnutls);
253 gnutls->priv->tls_ostream = g_tls_output_stream_gnutls_new (gnutls);
259 g_tls_connection_gnutls_finalize (GObject *object)
261 GTlsConnectionGnutls *connection = G_TLS_CONNECTION_GNUTLS (object);
263 if (connection->priv->base_io_stream)
264 g_object_unref (connection->priv->base_io_stream);
266 if (connection->priv->session)
267 gnutls_deinit (connection->priv->session);
269 if (connection->priv->tls_istream)
270 g_object_unref (connection->priv->tls_istream);
271 if (connection->priv->tls_ostream)
272 g_object_unref (connection->priv->tls_ostream);
274 if (connection->priv->creds)
275 gnutls_certificate_free_credentials (connection->priv->creds);
277 if (connection->priv->certificate)
278 g_object_unref (connection->priv->certificate);
279 if (connection->priv->peer_certificate)
280 g_object_unref (connection->priv->peer_certificate);
282 if (connection->priv->error)
283 g_error_free (connection->priv->error);
285 G_OBJECT_CLASS (g_tls_connection_gnutls_parent_class)->finalize (object);
289 g_tls_connection_gnutls_get_property (GObject *object,
294 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (object);
298 case PROP_BASE_IO_STREAM:
299 g_value_set_object (value, gnutls->priv->base_io_stream);
302 case PROP_REQUIRE_CLOSE_NOTIFY:
303 g_value_set_boolean (value, gnutls->priv->require_close_notify);
306 case PROP_REHANDSHAKE_MODE:
307 g_value_set_enum (value, gnutls->priv->rehandshake_mode);
310 case PROP_USE_SYSTEM_CERTDB:
311 g_value_set_boolean (value, gnutls->priv->use_system_certdb);
314 case PROP_CERTIFICATE:
315 g_value_set_object (value, gnutls->priv->certificate);
318 case PROP_PEER_CERTIFICATE:
319 g_value_set_object (value, gnutls->priv->peer_certificate);
322 case PROP_PEER_CERTIFICATE_ERRORS:
323 g_value_set_flags (value, gnutls->priv->peer_certificate_errors);
327 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
332 g_tls_connection_gnutls_set_property (GObject *object,
337 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (object);
338 GInputStream *istream;
339 GOutputStream *ostream;
343 case PROP_BASE_IO_STREAM:
344 if (gnutls->priv->base_io_stream)
346 g_object_unref (gnutls->priv->base_io_stream);
347 gnutls->priv->base_istream = NULL;
348 gnutls->priv->base_ostream = NULL;
350 gnutls->priv->base_io_stream = g_value_dup_object (value);
351 if (!gnutls->priv->base_io_stream)
354 istream = g_io_stream_get_input_stream (gnutls->priv->base_io_stream);
355 ostream = g_io_stream_get_output_stream (gnutls->priv->base_io_stream);
357 if (G_IS_POLLABLE_INPUT_STREAM (istream) &&
358 g_pollable_input_stream_can_poll (G_POLLABLE_INPUT_STREAM (istream)))
359 gnutls->priv->base_istream = G_POLLABLE_INPUT_STREAM (istream);
360 if (G_IS_POLLABLE_OUTPUT_STREAM (ostream) &&
361 g_pollable_output_stream_can_poll (G_POLLABLE_OUTPUT_STREAM (ostream)))
362 gnutls->priv->base_ostream = G_POLLABLE_OUTPUT_STREAM (ostream);
365 case PROP_REQUIRE_CLOSE_NOTIFY:
366 gnutls->priv->require_close_notify = g_value_get_boolean (value);
369 case PROP_REHANDSHAKE_MODE:
370 gnutls->priv->rehandshake_mode = g_value_get_enum (value);
373 case PROP_USE_SYSTEM_CERTDB:
374 gnutls->priv->use_system_certdb = g_value_get_boolean (value);
376 gnutls_certificate_free_cas (gnutls->priv->creds);
377 if (gnutls->priv->use_system_certdb)
379 gnutls_x509_crt_t *cas;
382 g_tls_backend_gnutls_get_system_ca_list_gnutls (&cas, &num_cas);
383 gnutls_certificate_set_x509_trust (gnutls->priv->creds, cas, num_cas);
387 case PROP_CERTIFICATE:
388 if (gnutls->priv->certificate)
389 g_object_unref (gnutls->priv->certificate);
390 gnutls->priv->certificate = g_value_dup_object (value);
394 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
398 gnutls_certificate_credentials
399 g_tls_connection_gnutls_get_credentials (GTlsConnectionGnutls *gnutls)
401 return gnutls->priv->creds;
405 g_tls_connection_gnutls_get_session (GTlsConnectionGnutls *gnutls)
407 /* Ideally we would initialize gnutls->priv->session from
408 * g_tls_connection_gnutls_init(), but we can't tell if it's a
409 * client or server connection at that point... And
410 * g_tls_connection_gnutls_initiable_init() is too late, because
411 * construct-time property setters may need to modify it.
413 if (!gnutls->priv->session)
415 gboolean client = G_IS_TLS_CLIENT_CONNECTION (gnutls);
416 gnutls_init (&gnutls->priv->session, client ? GNUTLS_CLIENT : GNUTLS_SERVER);
419 return gnutls->priv->session;
423 g_tls_connection_gnutls_get_certificate (GTlsConnectionGnutls *gnutls,
426 GTlsCertificate *cert;
428 cert = g_tls_connection_get_certificate (G_TLS_CONNECTION (gnutls));
430 st->type = GNUTLS_CRT_X509;
433 GTlsCertificateGnutls *gnutlscert = G_TLS_CERTIFICATE_GNUTLS (cert);
436 st->cert.x509 = gnutls_malloc (sizeof (gnutls_x509_crt_t));
437 st->cert.x509[0] = g_tls_certificate_gnutls_copy_cert (gnutlscert);
438 st->key.x509 = g_tls_certificate_gnutls_copy_key (gnutlscert);
439 st->deinit_all = TRUE;
446 begin_gnutls_io (GTlsConnectionGnutls *gnutls,
448 GCancellable *cancellable)
450 gnutls->priv->blocking = blocking;
451 gnutls->priv->cancellable = cancellable;
452 gnutls->priv->internal_direction = 0;
453 g_clear_error (&gnutls->priv->error);
457 end_gnutls_io (GTlsConnectionGnutls *gnutls,
459 const char *generic_error,
462 gnutls->priv->cancellable = NULL;
466 g_clear_error (&gnutls->priv->error);
470 if (gnutls->priv->handshaking && !gnutls->priv->ever_handshaked)
472 if (g_error_matches (gnutls->priv->error, G_IO_ERROR, G_IO_ERROR_FAILED) ||
473 status == GNUTLS_E_UNEXPECTED_PACKET_LENGTH ||
474 status == GNUTLS_E_FATAL_ALERT_RECEIVED ||
475 status == GNUTLS_E_UNSUPPORTED_VERSION_PACKET)
477 g_clear_error (&gnutls->priv->error);
478 g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_NOT_TLS,
479 _("Peer failed to perform TLS handshake"));
480 return GNUTLS_E_PULL_ERROR;
484 if (gnutls->priv->error)
486 if (g_error_matches (gnutls->priv->error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
487 status = GNUTLS_E_AGAIN;
488 g_propagate_error (error, gnutls->priv->error);
489 gnutls->priv->error = NULL;
492 else if (status == GNUTLS_E_REHANDSHAKE)
494 if (gnutls->priv->rehandshake_mode == G_TLS_REHANDSHAKE_NEVER)
496 g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
497 _("Peer requested illegal TLS rehandshake"));
498 return GNUTLS_E_PULL_ERROR;
501 gnutls->priv->need_handshake = TRUE;
504 else if (status == GNUTLS_E_UNEXPECTED_PACKET_LENGTH)
506 if (gnutls->priv->eof)
508 if (gnutls->priv->require_close_notify)
510 g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_EOF,
511 _("TLS connection closed unexpectedly"));
519 g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
520 generic_error, gnutls_strerror (status));
524 #define BEGIN_GNUTLS_IO(gnutls, blocking, cancellable) \
525 begin_gnutls_io (gnutls, blocking, cancellable); \
528 #define END_GNUTLS_IO(gnutls, ret, errmsg, error) \
529 } while ((ret == GNUTLS_E_AGAIN || \
530 ret == GNUTLS_E_WARNING_ALERT_RECEIVED) && \
531 !gnutls->priv->error); \
532 ret = end_gnutls_io (gnutls, ret, errmsg, error)
535 g_tls_connection_gnutls_check (GTlsConnectionGnutls *gnutls,
536 GIOCondition condition)
538 if (!gnutls->priv->internal_direction)
541 if (gnutls->priv->handshaking || gnutls->priv->closing)
542 condition = gnutls->priv->internal_direction;
544 if (condition & G_IO_IN)
545 return g_pollable_input_stream_is_readable (gnutls->priv->base_istream);
547 return g_pollable_output_stream_is_writable (gnutls->priv->base_ostream);
553 GTlsConnectionGnutls *gnutls;
556 GSource *child_source;
557 GIOCondition base_direction;
558 GIOCondition current_direction;
559 } GTlsConnectionGnutlsSource;
562 gnutls_source_prepare (GSource *source,
570 gnutls_source_check (GSource *source)
576 gnutls_source_sync_child_source (GTlsConnectionGnutlsSource *gnutls_source,
577 GIOCondition direction)
579 GTlsConnectionGnutls *gnutls = gnutls_source->gnutls;
580 GSource *source = (GSource *)gnutls_source;
582 if (direction == gnutls_source->current_direction)
585 if (gnutls_source->child_source)
587 g_source_remove_child_source (source, gnutls_source->child_source);
588 g_source_unref (gnutls_source->child_source);
591 if (direction & G_IO_IN)
592 gnutls_source->child_source = g_pollable_input_stream_create_source (gnutls->priv->base_istream, NULL);
594 gnutls_source->child_source = g_pollable_output_stream_create_source (gnutls->priv->base_ostream, NULL);
596 g_source_set_dummy_callback (gnutls_source->child_source);
597 g_source_add_child_source (source, gnutls_source->child_source);
598 gnutls_source->current_direction = direction;
602 gnutls_source_dispatch (GSource *source,
603 GSourceFunc callback,
606 GPollableSourceFunc func = (GPollableSourceFunc)callback;
607 GTlsConnectionGnutlsSource *gnutls_source = (GTlsConnectionGnutlsSource *)source;
608 GTlsConnectionGnutls *gnutls = gnutls_source->gnutls;
611 ret = (*func) (gnutls_source->stream, user_data);
614 GIOCondition direction = gnutls->priv->internal_direction ? gnutls->priv->internal_direction : gnutls_source->base_direction;
616 gnutls_source_sync_child_source (gnutls_source, direction);
623 gnutls_source_finalize (GSource *source)
625 GTlsConnectionGnutlsSource *gnutls_source = (GTlsConnectionGnutlsSource *)source;
627 g_object_unref (gnutls_source->gnutls);
629 if (gnutls_source->child_source)
630 g_source_unref (gnutls_source->child_source);
634 g_tls_connection_gnutls_source_closure_callback (GObject *stream,
637 GClosure *closure = data;
639 GValue param = { 0, };
640 GValue result_value = { 0, };
643 g_value_init (&result_value, G_TYPE_BOOLEAN);
645 g_value_init (¶m, G_TYPE_OBJECT);
646 g_value_set_object (¶m, stream);
648 g_closure_invoke (closure, &result_value, 1, ¶m, NULL);
650 result = g_value_get_boolean (&result_value);
651 g_value_unset (&result_value);
652 g_value_unset (¶m);
657 static GSourceFuncs gnutls_source_funcs =
659 gnutls_source_prepare,
661 gnutls_source_dispatch,
662 gnutls_source_finalize,
663 (GSourceFunc)g_tls_connection_gnutls_source_closure_callback,
664 (GSourceDummyMarshal)_gnutls_marshal_BOOLEAN__VOID,
668 g_tls_connection_gnutls_create_source (GTlsConnectionGnutls *gnutls,
669 GIOCondition condition,
670 GCancellable *cancellable)
672 GSource *source, *cancellable_source;
673 GTlsConnectionGnutlsSource *gnutls_source;
675 source = g_source_new (&gnutls_source_funcs, sizeof (GTlsConnectionGnutlsSource));
676 g_source_set_name (source, "GTlsConnectionGnutlsSource");
677 gnutls_source = (GTlsConnectionGnutlsSource *)source;
678 gnutls_source->gnutls = g_object_ref (gnutls);
679 gnutls_source->base_direction = condition & (G_IO_IN | G_IO_OUT);
680 if (gnutls_source->base_direction == G_IO_IN)
681 gnutls_source->stream = G_OBJECT (gnutls->priv->tls_istream);
682 else if (gnutls_source->base_direction == G_IO_OUT)
683 gnutls_source->stream = G_OBJECT (gnutls->priv->tls_ostream);
686 gnutls_source->base_direction = gnutls->priv->internal_direction;
687 gnutls_source->stream = NULL;
689 gnutls_source_sync_child_source (gnutls_source, gnutls_source->base_direction);
693 cancellable_source = g_cancellable_source_new (cancellable);
694 g_source_set_dummy_callback (cancellable_source);
695 g_source_add_child_source (source, cancellable_source);
696 g_source_unref (cancellable_source);
703 set_gnutls_error (GTlsConnectionGnutls *gnutls, GIOCondition direction)
705 if (g_error_matches (gnutls->priv->error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
706 gnutls_transport_set_errno (gnutls->priv->session, EINTR);
707 else if (g_error_matches (gnutls->priv->error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
709 gnutls_transport_set_errno (gnutls->priv->session, EAGAIN);
710 gnutls->priv->internal_direction = direction;
713 gnutls_transport_set_errno (gnutls->priv->session, EIO);
717 g_tls_connection_gnutls_pull_func (gnutls_transport_ptr_t transport_data,
721 GTlsConnectionGnutls *gnutls = transport_data;
724 /* If gnutls->priv->error is non-%NULL when we're called, it means
725 * that an error previously occurred, but gnutls decided not to
726 * propagate it. So it's correct for us to just clear it. (Usually
727 * this means it ignored an EAGAIN after a short read, and now
728 * we'll return EAGAIN again, which it will obey this time.)
730 g_clear_error (&gnutls->priv->error);
732 if (gnutls->priv->blocking)
734 ret = g_input_stream_read (G_INPUT_STREAM (gnutls->priv->base_istream),
736 gnutls->priv->cancellable,
737 &gnutls->priv->error);
741 ret = g_pollable_input_stream_read_nonblocking (gnutls->priv->base_istream,
743 gnutls->priv->cancellable,
744 &gnutls->priv->error);
748 set_gnutls_error (gnutls, G_IO_IN);
750 gnutls->priv->eof = TRUE;
756 g_tls_connection_gnutls_push_func (gnutls_transport_ptr_t transport_data,
760 GTlsConnectionGnutls *gnutls = transport_data;
763 /* See comment in pull_func. */
764 g_clear_error (&gnutls->priv->error);
766 if (gnutls->priv->blocking)
768 ret = g_output_stream_write (G_OUTPUT_STREAM (gnutls->priv->base_ostream),
770 gnutls->priv->cancellable,
771 &gnutls->priv->error);
775 ret = g_pollable_output_stream_write_nonblocking (gnutls->priv->base_ostream,
777 gnutls->priv->cancellable,
778 &gnutls->priv->error);
781 set_gnutls_error (gnutls, G_IO_OUT);
787 handshake_internal (GTlsConnectionGnutls *gnutls,
789 GCancellable *cancellable,
792 GTlsCertificate *peer_certificate = NULL;
793 GTlsCertificateFlags peer_certificate_errors = 0;
796 if (G_IS_TLS_SERVER_CONNECTION_GNUTLS (gnutls) &&
797 gnutls->priv->ever_handshaked && !gnutls->priv->need_handshake)
799 BEGIN_GNUTLS_IO (gnutls, blocking, cancellable);
800 ret = gnutls_rehandshake (gnutls->priv->session);
801 END_GNUTLS_IO (gnutls, ret, _("Error performing TLS handshake: %s"), error);
807 if (!gnutls->priv->handshaking)
809 gnutls->priv->handshaking = TRUE;
811 if (gnutls->priv->peer_certificate)
813 g_object_unref (gnutls->priv->peer_certificate);
814 gnutls->priv->peer_certificate = NULL;
815 gnutls->priv->peer_certificate_errors = 0;
817 g_object_notify (G_OBJECT (gnutls), "peer-certificate");
818 g_object_notify (G_OBJECT (gnutls), "peer-certificate-errors");
821 g_tls_connection_gnutls_set_handshake_priority (gnutls);
822 G_TLS_CONNECTION_GNUTLS_GET_CLASS (gnutls)->begin_handshake (gnutls);
825 BEGIN_GNUTLS_IO (gnutls, blocking, cancellable);
826 ret = gnutls_handshake (gnutls->priv->session);
827 END_GNUTLS_IO (gnutls, ret, _("Error performing TLS handshake: %s"), error);
829 if (ret == GNUTLS_E_AGAIN)
832 gnutls->priv->handshaking = FALSE;
833 gnutls->priv->need_handshake = FALSE;
834 gnutls->priv->ever_handshaked = TRUE;
837 gnutls_certificate_type_get (gnutls->priv->session) == GNUTLS_CRT_X509)
839 GTlsCertificate *chain, *cert;
840 const gnutls_datum_t *certs;
841 unsigned int num_certs;
844 certs = gnutls_certificate_get_peers (gnutls->priv->session, &num_certs);
848 for (i = num_certs - 1; i >= 0; i--)
850 cert = g_tls_certificate_gnutls_new (&certs[i], chain);
855 peer_certificate = chain;
858 if (peer_certificate)
862 status = gnutls_certificate_verify_peers (gnutls->priv->session);
863 peer_certificate_errors = g_tls_certificate_gnutls_convert_flags (status);
864 if (peer_certificate_errors)
866 /* gnutls_certificate_verify_peers() bails out on the first
867 * error, which may be G_TLS_CERTIFICATE_UNKNOWN_CA, but the
868 * caller may be planning to check that part themselves. So
869 * call g_tls_certificate_verify() to get any other errors.
871 peer_certificate_errors |= g_tls_certificate_verify (peer_certificate, NULL, NULL);
874 if (!G_TLS_CONNECTION_GNUTLS_GET_CLASS (gnutls)->verify_peer (gnutls, peer_certificate, &peer_certificate_errors))
876 g_object_unref (peer_certificate);
877 g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
878 _("Unacceptable TLS certificate"));
883 G_TLS_CONNECTION_GNUTLS_GET_CLASS (gnutls)->finish_handshake (gnutls, error);
887 gnutls->priv->peer_certificate = peer_certificate;
888 gnutls->priv->peer_certificate_errors = peer_certificate_errors;
890 g_object_notify (G_OBJECT (gnutls), "peer-certificate");
891 g_object_notify (G_OBJECT (gnutls), "peer-certificate-errors");
900 handshake_in_progress_or_failed (GTlsConnectionGnutls *gnutls,
902 GCancellable *cancellable,
905 if (!(gnutls->priv->need_handshake || gnutls->priv->handshaking))
908 return !handshake_internal (gnutls, blocking, cancellable, error);
912 g_tls_connection_gnutls_handshake (GTlsConnection *conn,
913 GCancellable *cancellable,
916 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (conn);
918 return handshake_internal (gnutls, TRUE, cancellable, error);
922 g_tls_connection_gnutls_handshake_ready (GObject *pollable_stream,
925 GTlsConnectionGnutls *gnutls;
926 GSimpleAsyncResult *simple = user_data;
928 GError *error = NULL;
930 gnutls = G_TLS_CONNECTION_GNUTLS (g_async_result_get_source_object (G_ASYNC_RESULT (simple)));
931 g_object_unref (gnutls);
933 success = handshake_internal (gnutls, FALSE, NULL, &error);
934 if (!success && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
936 g_error_free (error);
942 g_simple_async_result_set_from_error (simple, error);
943 g_error_free (error);
946 g_simple_async_result_set_op_res_gboolean (simple, success);
947 g_simple_async_result_complete (simple);
948 g_object_unref (simple);
954 g_tls_connection_gnutls_handshake_async (GTlsConnection *conn,
956 GCancellable *cancellable,
957 GAsyncReadyCallback callback,
960 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (conn);
961 GSimpleAsyncResult *simple;
963 GError *error = NULL;
966 simple = g_simple_async_result_new (G_OBJECT (conn), callback, user_data,
967 g_tls_connection_gnutls_handshake_async);
968 success = handshake_internal (gnutls, FALSE, cancellable, &error);
971 g_simple_async_result_set_op_res_gboolean (simple, TRUE);
972 g_simple_async_result_complete_in_idle (simple);
973 g_object_unref (simple);
975 else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
977 g_simple_async_result_set_from_error (simple, error);
978 g_error_free (error);
979 g_simple_async_result_complete_in_idle (simple);
980 g_object_unref (simple);
983 source = g_tls_connection_gnutls_create_source (gnutls, 0, cancellable);
984 g_source_set_callback (source,
985 (GSourceFunc) g_tls_connection_gnutls_handshake_ready,
987 g_source_set_priority (source, io_priority);
988 g_source_attach (source, g_main_context_get_thread_default ());
989 g_source_unref (source);
993 g_tls_connection_gnutls_handshake_finish (GTlsConnection *conn,
994 GAsyncResult *result,
997 GSimpleAsyncResult *simple;
999 g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (conn), g_tls_connection_gnutls_handshake_async), FALSE);
1001 simple = G_SIMPLE_ASYNC_RESULT (result);
1003 if (g_simple_async_result_propagate_error (simple, error))
1006 return g_simple_async_result_get_op_res_gboolean (simple);
1010 g_tls_connection_gnutls_read (GTlsConnectionGnutls *gnutls,
1014 GCancellable *cancellable,
1020 if (handshake_in_progress_or_failed (gnutls, blocking, cancellable, error))
1023 BEGIN_GNUTLS_IO (gnutls, blocking, cancellable);
1024 ret = gnutls_record_recv (gnutls->priv->session, buffer, count);
1025 END_GNUTLS_IO (gnutls, ret, _("Error reading data from TLS socket: %s"), error);
1029 else if (ret == GNUTLS_E_REHANDSHAKE)
1036 g_tls_connection_gnutls_write (GTlsConnectionGnutls *gnutls,
1040 GCancellable *cancellable,
1046 if (handshake_in_progress_or_failed (gnutls, blocking, cancellable, error))
1049 BEGIN_GNUTLS_IO (gnutls, blocking, cancellable);
1050 ret = gnutls_record_send (gnutls->priv->session, buffer, count);
1051 END_GNUTLS_IO (gnutls, ret, _("Error writing data to TLS socket: %s"), error);
1055 else if (ret == GNUTLS_E_REHANDSHAKE)
1061 static GInputStream *
1062 g_tls_connection_gnutls_get_input_stream (GIOStream *stream)
1064 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (stream);
1066 return gnutls->priv->tls_istream;
1069 static GOutputStream *
1070 g_tls_connection_gnutls_get_output_stream (GIOStream *stream)
1072 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (stream);
1074 return gnutls->priv->tls_ostream;
1078 close_internal (GTlsConnectionGnutls *gnutls,
1080 GCancellable *cancellable,
1085 /* If we haven't finished the initial handshake yet, there's no
1086 * reason to finish it just so we can close.
1088 if (gnutls->priv->handshaking && !gnutls->priv->ever_handshaked)
1091 if (handshake_in_progress_or_failed (gnutls, blocking, cancellable, error))
1094 gnutls->priv->closing = TRUE;
1095 BEGIN_GNUTLS_IO (gnutls, blocking, cancellable);
1096 ret = gnutls_bye (gnutls->priv->session, GNUTLS_SHUT_WR);
1097 END_GNUTLS_IO (gnutls, ret, _("Error performing TLS close: %s"), error);
1098 if (ret == 0 || !error || !g_error_matches (*error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
1099 gnutls->priv->closing = FALSE;
1105 g_tls_connection_gnutls_close (GIOStream *stream,
1106 GCancellable *cancellable,
1109 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (stream);
1111 if (!close_internal (gnutls, TRUE, cancellable, error))
1113 return g_io_stream_close (gnutls->priv->base_io_stream,
1114 cancellable, error);
1118 GSimpleAsyncResult *simple;
1119 GCancellable *cancellable;
1124 close_base_stream_cb (GObject *base_stream,
1125 GAsyncResult *result,
1129 GError *error = NULL;
1130 AsyncCloseData *acd = user_data;
1132 success = g_io_stream_close_finish (G_IO_STREAM (base_stream),
1135 g_simple_async_result_set_op_res_gboolean (acd->simple, TRUE);
1138 g_simple_async_result_set_from_error (acd->simple, error);
1139 g_error_free (error);
1142 g_simple_async_result_complete (acd->simple);
1143 g_object_unref (acd->simple);
1144 if (acd->cancellable)
1145 g_object_unref (acd->cancellable);
1146 g_slice_free (AsyncCloseData, acd);
1150 g_tls_connection_gnutls_close_ready (GObject *pollable_stream,
1153 GTlsConnectionGnutls *gnutls;
1154 AsyncCloseData *acd = user_data;
1156 GError *error = NULL;
1158 gnutls = G_TLS_CONNECTION_GNUTLS (g_async_result_get_source_object (G_ASYNC_RESULT (acd->simple)));
1159 g_object_unref (gnutls);
1161 success = close_internal (gnutls, FALSE, NULL, &error);
1162 if (!success && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
1164 g_error_free (error);
1170 g_simple_async_result_set_from_error (acd->simple, error);
1171 g_simple_async_result_complete (acd->simple);
1172 g_error_free (error);
1173 g_object_unref (acd->simple);
1174 if (acd->cancellable)
1175 g_object_unref (acd->cancellable);
1176 g_slice_free (AsyncCloseData, acd);
1180 g_io_stream_close_async (gnutls->priv->base_io_stream,
1181 acd->io_priority, acd->cancellable,
1182 close_base_stream_cb, acd);
1189 g_tls_connection_gnutls_close_async (GIOStream *stream,
1191 GCancellable *cancellable,
1192 GAsyncReadyCallback callback,
1195 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (stream);
1196 GSimpleAsyncResult *simple;
1198 GError *error = NULL;
1199 AsyncCloseData *acd;
1202 simple = g_simple_async_result_new (G_OBJECT (stream), callback, user_data,
1203 g_tls_connection_gnutls_close_async);
1205 success = close_internal (gnutls, FALSE, cancellable, &error);
1206 if (error && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
1208 g_simple_async_result_set_from_error (simple, error);
1209 g_error_free (error);
1210 g_simple_async_result_complete_in_idle (simple);
1211 g_object_unref (simple);
1215 g_error_free (error);
1217 acd = g_slice_new (AsyncCloseData);
1218 acd->simple = simple;
1219 acd->cancellable = g_object_ref (cancellable);
1220 acd->io_priority = io_priority;
1224 g_io_stream_close_async (gnutls->priv->base_io_stream,
1225 io_priority, cancellable,
1226 close_base_stream_cb, acd);
1230 source = g_tls_connection_gnutls_create_source (gnutls, 0, acd->cancellable);
1231 g_source_set_callback (source,
1232 (GSourceFunc) g_tls_connection_gnutls_close_ready,
1234 g_source_set_priority (source, acd->io_priority);
1235 g_source_attach (source, g_main_context_get_thread_default ());
1236 g_source_unref (source);
1240 g_tls_connection_gnutls_close_finish (GIOStream *stream,
1241 GAsyncResult *result,
1244 GSimpleAsyncResult *simple;
1246 g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (stream), g_tls_connection_gnutls_close_async), FALSE);
1248 simple = G_SIMPLE_ASYNC_RESULT (result);
1250 if (g_simple_async_result_propagate_error (simple, error))
1253 return g_simple_async_result_get_op_res_gboolean (simple);