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 <glib/gi18n-lib.h>
36 static void g_tls_connection_gnutls_get_property (GObject *object,
40 static void g_tls_connection_gnutls_set_property (GObject *object,
44 static void g_tls_connection_gnutls_finalize (GObject *object);
46 static gboolean g_tls_connection_gnutls_handshake (GTlsConnection *connection,
47 GCancellable *cancellable,
49 static void g_tls_connection_gnutls_handshake_async (GTlsConnection *conn,
51 GCancellable *cancellable,
52 GAsyncReadyCallback callback,
54 static gboolean g_tls_connection_gnutls_handshake_finish (GTlsConnection *conn,
58 static GInputStream *g_tls_connection_gnutls_get_input_stream (GIOStream *stream);
59 static GOutputStream *g_tls_connection_gnutls_get_output_stream (GIOStream *stream);
61 static gboolean g_tls_connection_gnutls_close (GIOStream *stream,
62 GCancellable *cancellable,
64 static void g_tls_connection_gnutls_close_async (GIOStream *stream,
66 GCancellable *cancellable,
67 GAsyncReadyCallback callback,
69 static gboolean g_tls_connection_gnutls_close_finish (GIOStream *stream,
73 static ssize_t g_tls_connection_gnutls_push_func (gnutls_transport_ptr_t transport_data,
76 static ssize_t g_tls_connection_gnutls_pull_func (gnutls_transport_ptr_t transport_data,
80 static void g_tls_connection_gnutls_initable_iface_init (GInitableIface *iface);
81 static gboolean g_tls_connection_gnutls_initable_init (GInitable *initable,
82 GCancellable *cancellable,
85 static void g_tls_connection_gnutls_init_priorities (void);
87 G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GTlsConnectionGnutls, g_tls_connection_gnutls, G_TYPE_TLS_CONNECTION,
88 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
89 g_tls_connection_gnutls_initable_iface_init);
90 g_tls_connection_gnutls_init_priorities ();
98 PROP_REQUIRE_CLOSE_NOTIFY,
102 struct _GTlsConnectionGnutlsPrivate
104 GIOStream *base_io_stream;
105 GPollableInputStream *base_istream;
106 GPollableOutputStream *base_ostream;
109 gnutls_certificate_credentials creds;
110 gnutls_session session;
111 gboolean require_close_notify;
112 GTlsRehandshakeMode rehandshake_mode;
113 gboolean need_handshake, handshaking, ever_handshaked;
116 GInputStream *tls_istream;
117 GOutputStream *tls_ostream;
120 GCancellable *cancellable;
121 gboolean blocking, eof;
122 GIOCondition internal_direction;
126 g_tls_connection_gnutls_class_init (GTlsConnectionGnutlsClass *klass)
128 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
129 GTlsConnectionClass *connection_class = G_TLS_CONNECTION_CLASS (klass);
130 GIOStreamClass *iostream_class = G_IO_STREAM_CLASS (klass);
132 g_type_class_add_private (klass, sizeof (GTlsConnectionGnutlsPrivate));
134 gobject_class->get_property = g_tls_connection_gnutls_get_property;
135 gobject_class->set_property = g_tls_connection_gnutls_set_property;
136 gobject_class->finalize = g_tls_connection_gnutls_finalize;
138 connection_class->handshake = g_tls_connection_gnutls_handshake;
139 connection_class->handshake_async = g_tls_connection_gnutls_handshake_async;
140 connection_class->handshake_finish = g_tls_connection_gnutls_handshake_finish;
142 iostream_class->get_input_stream = g_tls_connection_gnutls_get_input_stream;
143 iostream_class->get_output_stream = g_tls_connection_gnutls_get_output_stream;
144 iostream_class->close_fn = g_tls_connection_gnutls_close;
145 iostream_class->close_async = g_tls_connection_gnutls_close_async;
146 iostream_class->close_finish = g_tls_connection_gnutls_close_finish;
148 g_object_class_override_property (gobject_class, PROP_BASE_IO_STREAM, "base-io-stream");
149 g_object_class_override_property (gobject_class, PROP_REQUIRE_CLOSE_NOTIFY, "require-close-notify");
150 g_object_class_override_property (gobject_class, PROP_REHANDSHAKE_MODE, "rehandshake-mode");
154 g_tls_connection_gnutls_initable_iface_init (GInitableIface *iface)
156 iface->init = g_tls_connection_gnutls_initable_init;
160 g_tls_connection_gnutls_init (GTlsConnectionGnutls *gnutls)
162 gnutls->priv = G_TYPE_INSTANCE_GET_PRIVATE (gnutls, G_TYPE_TLS_CONNECTION_GNUTLS, GTlsConnectionGnutlsPrivate);
164 gnutls_certificate_allocate_credentials (&gnutls->priv->creds);
165 gnutls_certificate_set_verify_flags (gnutls->priv->creds,
166 GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
168 gnutls->priv->need_handshake = TRUE;
171 static gnutls_priority_t priorities[2][2];
174 g_tls_connection_gnutls_init_priorities (void)
176 /* First field is "ssl3 only", second is "allow unsafe rehandshaking" */
178 gnutls_priority_init (&priorities[FALSE][FALSE],
181 gnutls_priority_init (&priorities[TRUE][FALSE],
182 "NORMAL:!VERS-TLS1.2:!VERS-TLS1.1:!VERS-TLS1.0",
184 gnutls_priority_init (&priorities[FALSE][TRUE],
185 "NORMAL:%UNSAFE_RENEGOTIATION",
187 gnutls_priority_init (&priorities[TRUE][TRUE],
188 "NORMAL:!VERS-TLS1.2:!VERS-TLS1.1:!VERS-TLS1.0:%UNSAFE_RENEGOTIATION",
193 g_tls_connection_gnutls_set_handshake_priority (GTlsConnectionGnutls *gnutls)
195 gboolean use_ssl3, unsafe_rehandshake;
197 if (G_IS_TLS_CLIENT_CONNECTION (gnutls))
198 use_ssl3 = g_tls_client_connection_get_use_ssl3 (G_TLS_CLIENT_CONNECTION (gnutls));
199 unsafe_rehandshake = (gnutls->priv->rehandshake_mode == G_TLS_REHANDSHAKE_UNSAFELY);
200 gnutls_priority_set (gnutls->priv->session,
201 priorities[use_ssl3][unsafe_rehandshake]);
205 g_tls_connection_gnutls_initable_init (GInitable *initable,
206 GCancellable *cancellable,
209 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (initable);
210 gnutls_x509_crt_t *cas;
214 g_return_val_if_fail (gnutls->priv->base_istream != NULL &&
215 gnutls->priv->base_ostream != NULL, FALSE);
217 /* Make sure gnutls->priv->session has been initialized (it may have
218 * already been initialized by a construct-time property setter).
220 g_tls_connection_gnutls_get_session (gnutls);
222 g_tls_backend_gnutls_get_system_ca_list_gnutls (&cas, &num_cas);
223 gnutls_certificate_set_x509_trust (gnutls->priv->creds, cas, num_cas);
225 status = gnutls_credentials_set (gnutls->priv->session,
226 GNUTLS_CRD_CERTIFICATE,
227 gnutls->priv->creds);
230 g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
231 _("Could not create TLS connection: %s"),
232 gnutls_strerror (status));
236 gnutls_transport_set_push_function (gnutls->priv->session,
237 g_tls_connection_gnutls_push_func);
238 gnutls_transport_set_pull_function (gnutls->priv->session,
239 g_tls_connection_gnutls_pull_func);
240 gnutls_transport_set_ptr (gnutls->priv->session, gnutls);
242 gnutls->priv->tls_istream = g_tls_input_stream_gnutls_new (gnutls);
243 gnutls->priv->tls_ostream = g_tls_output_stream_gnutls_new (gnutls);
249 g_tls_connection_gnutls_finalize (GObject *object)
251 GTlsConnectionGnutls *connection = G_TLS_CONNECTION_GNUTLS (object);
253 if (connection->priv->base_io_stream)
254 g_object_unref (connection->priv->base_io_stream);
256 if (connection->priv->session)
257 gnutls_deinit (connection->priv->session);
259 if (connection->priv->tls_istream)
260 g_object_unref (connection->priv->tls_istream);
261 if (connection->priv->tls_ostream)
262 g_object_unref (connection->priv->tls_ostream);
264 if (connection->priv->creds)
265 gnutls_certificate_free_credentials (connection->priv->creds);
267 if (connection->priv->error)
268 g_error_free (connection->priv->error);
270 G_OBJECT_CLASS (g_tls_connection_gnutls_parent_class)->finalize (object);
274 g_tls_connection_gnutls_get_property (GObject *object,
279 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (object);
283 case PROP_BASE_IO_STREAM:
284 g_value_set_object (value, gnutls->priv->base_io_stream);
287 case PROP_REQUIRE_CLOSE_NOTIFY:
288 g_value_set_boolean (value, gnutls->priv->require_close_notify);
291 case PROP_REHANDSHAKE_MODE:
292 g_value_set_enum (value, gnutls->priv->rehandshake_mode);
296 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
301 g_tls_connection_gnutls_set_property (GObject *object,
306 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (object);
307 GInputStream *istream;
308 GOutputStream *ostream;
312 case PROP_BASE_IO_STREAM:
313 if (gnutls->priv->base_io_stream)
315 g_object_unref (gnutls->priv->base_io_stream);
316 gnutls->priv->base_istream = NULL;
317 gnutls->priv->base_ostream = NULL;
319 gnutls->priv->base_io_stream = g_value_dup_object (value);
320 if (!gnutls->priv->base_io_stream)
323 istream = g_io_stream_get_input_stream (gnutls->priv->base_io_stream);
324 ostream = g_io_stream_get_output_stream (gnutls->priv->base_io_stream);
326 if (G_IS_POLLABLE_INPUT_STREAM (istream) &&
327 g_pollable_input_stream_can_poll (G_POLLABLE_INPUT_STREAM (istream)))
328 gnutls->priv->base_istream = G_POLLABLE_INPUT_STREAM (istream);
329 if (G_IS_POLLABLE_OUTPUT_STREAM (ostream) &&
330 g_pollable_output_stream_can_poll (G_POLLABLE_OUTPUT_STREAM (ostream)))
331 gnutls->priv->base_ostream = G_POLLABLE_OUTPUT_STREAM (ostream);
334 case PROP_REQUIRE_CLOSE_NOTIFY:
335 gnutls->priv->require_close_notify = g_value_get_boolean (value);
338 case PROP_REHANDSHAKE_MODE:
339 gnutls->priv->rehandshake_mode = g_value_get_enum (value);
343 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
347 gnutls_certificate_credentials
348 g_tls_connection_gnutls_get_credentials (GTlsConnectionGnutls *gnutls)
350 return gnutls->priv->creds;
354 g_tls_connection_gnutls_get_session (GTlsConnectionGnutls *gnutls)
356 /* Ideally we would initialize gnutls->priv->session from
357 * g_tls_connection_gnutls_init(), but we can't tell if it's a
358 * client or server connection at that point... And
359 * g_tls_connection_gnutls_initiable_init() is too late, because
360 * construct-time property setters may need to modify it.
362 if (!gnutls->priv->session)
364 gboolean client = G_IS_TLS_CLIENT_CONNECTION (gnutls);
365 gnutls_init (&gnutls->priv->session, client ? GNUTLS_CLIENT : GNUTLS_SERVER);
368 return gnutls->priv->session;
372 g_tls_connection_gnutls_get_certificate (GTlsConnectionGnutls *gnutls,
375 GTlsCertificate *cert;
377 cert = g_tls_connection_get_certificate (G_TLS_CONNECTION (gnutls));
381 cert = g_tls_connection_emit_need_certificate (G_TLS_CONNECTION (gnutls));
383 st->type = GNUTLS_CRT_X509;
386 GTlsCertificateGnutls *gnutlscert = G_TLS_CERTIFICATE_GNUTLS (cert);
389 st->cert.x509 = gnutls_malloc (sizeof (gnutls_x509_crt_t));
390 st->cert.x509[0] = g_tls_certificate_gnutls_copy_cert (gnutlscert);
391 st->key.x509 = g_tls_certificate_gnutls_copy_key (gnutlscert);
392 st->deinit_all = TRUE;
394 g_object_unref (cert);
400 static const struct {
402 GTlsCertificateFlags gtls_flag;
404 { GNUTLS_CERT_SIGNER_NOT_FOUND | GNUTLS_CERT_SIGNER_NOT_CA, G_TLS_CERTIFICATE_UNKNOWN_CA },
405 { GNUTLS_CERT_NOT_ACTIVATED, G_TLS_CERTIFICATE_NOT_ACTIVATED },
406 { GNUTLS_CERT_EXPIRED, G_TLS_CERTIFICATE_EXPIRED },
407 { GNUTLS_CERT_REVOKED, G_TLS_CERTIFICATE_REVOKED },
408 { GNUTLS_CERT_INSECURE_ALGORITHM, G_TLS_CERTIFICATE_INSECURE }
410 static const int flags_map_size = G_N_ELEMENTS (flags_map);
413 g_tls_connection_gnutls_validate_peer (GTlsConnectionGnutls *gnutls)
416 GTlsCertificateFlags gtls_errors;
418 status = gnutls_certificate_verify_peers (gnutls->priv->session);
420 /* Convert GNUTLS status to GTlsCertificateFlags. GNUTLS sets
421 * GNUTLS_CERT_INVALID if it sets any other flag, so we want to
422 * strip that out unless it's the only flag set. Then we convert
423 * specific flags we recognize, and if there are any flags left over
424 * at the end, we add G_TLS_CERTIFICATE_GENERIC_ERROR.
428 if (status != GNUTLS_CERT_INVALID)
429 status = status & ~GNUTLS_CERT_INVALID;
430 for (i = 0; i < flags_map_size && status != 0; i++)
432 if (status & flags_map[i].gnutls_flag)
434 status &= ~flags_map[i].gnutls_flag;
435 gtls_errors |= flags_map[i].gtls_flag;
439 gtls_errors |= G_TLS_CERTIFICATE_GENERIC_ERROR;
445 begin_gnutls_io (GTlsConnectionGnutls *gnutls,
447 GCancellable *cancellable)
449 gnutls->priv->blocking = blocking;
450 gnutls->priv->cancellable = cancellable;
451 gnutls->priv->internal_direction = 0;
452 g_clear_error (&gnutls->priv->error);
456 end_gnutls_io (GTlsConnectionGnutls *gnutls,
458 const char *generic_error,
461 gnutls->priv->cancellable = NULL;
465 g_clear_error (&gnutls->priv->error);
469 if (gnutls->priv->handshaking && !gnutls->priv->ever_handshaked)
471 if (g_error_matches (gnutls->priv->error, G_IO_ERROR, G_IO_ERROR_FAILED) ||
472 status == GNUTLS_E_UNEXPECTED_PACKET_LENGTH ||
473 status == GNUTLS_E_FATAL_ALERT_RECEIVED ||
474 status == GNUTLS_E_UNSUPPORTED_VERSION_PACKET)
476 g_clear_error (&gnutls->priv->error);
477 g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_NOT_TLS,
478 _("Peer failed to perform TLS handshake"));
479 return GNUTLS_E_PULL_ERROR;
483 if (gnutls->priv->error)
485 if (g_error_matches (gnutls->priv->error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
486 status = GNUTLS_E_AGAIN;
487 g_propagate_error (error, gnutls->priv->error);
488 gnutls->priv->error = NULL;
491 else if (status == GNUTLS_E_REHANDSHAKE)
493 if (gnutls->priv->rehandshake_mode == G_TLS_REHANDSHAKE_NEVER)
495 g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
496 _("Peer requested illegal TLS rehandshake"));
497 return GNUTLS_E_PULL_ERROR;
500 gnutls->priv->need_handshake = TRUE;
503 else if (status == GNUTLS_E_UNEXPECTED_PACKET_LENGTH)
505 if (gnutls->priv->eof)
507 if (gnutls->priv->require_close_notify)
509 g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_EOF,
510 _("TLS connection closed unexpectedly"));
518 g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
519 generic_error, gnutls_strerror (status));
523 #define BEGIN_GNUTLS_IO(gnutls, blocking, cancellable) \
524 begin_gnutls_io (gnutls, blocking, cancellable); \
527 #define END_GNUTLS_IO(gnutls, ret, errmsg, error) \
528 } while ((ret == GNUTLS_E_AGAIN || \
529 ret == GNUTLS_E_WARNING_ALERT_RECEIVED) && \
530 !gnutls->priv->error); \
531 ret = end_gnutls_io (gnutls, ret, errmsg, error)
534 g_tls_connection_gnutls_check (GTlsConnectionGnutls *gnutls,
535 GIOCondition condition)
537 if (gnutls->priv->handshaking || gnutls->priv->closing)
538 condition = gnutls->priv->internal_direction;
540 if (condition & G_IO_IN)
541 return g_pollable_input_stream_is_readable (gnutls->priv->base_istream);
543 return g_pollable_output_stream_is_writable (gnutls->priv->base_ostream);
549 GTlsConnectionGnutls *gnutls;
552 GSource *child_source;
553 GIOCondition base_direction;
554 GIOCondition current_direction;
555 } GTlsConnectionGnutlsSource;
558 gnutls_source_prepare (GSource *source,
566 gnutls_source_check (GSource *source)
572 gnutls_source_sync_child_source (GTlsConnectionGnutlsSource *gnutls_source,
573 GIOCondition direction)
575 GTlsConnectionGnutls *gnutls = gnutls_source->gnutls;
576 GSource *source = (GSource *)gnutls_source;
578 if (direction == gnutls_source->current_direction)
581 if (gnutls_source->child_source)
583 g_source_remove_child_source (source, gnutls_source->child_source);
584 g_source_unref (gnutls_source->child_source);
587 if (direction & G_IO_IN)
588 gnutls_source->child_source = g_pollable_input_stream_create_source (gnutls->priv->base_istream, NULL);
590 gnutls_source->child_source = g_pollable_output_stream_create_source (gnutls->priv->base_ostream, NULL);
592 g_source_set_dummy_callback (gnutls_source->child_source);
593 g_source_add_child_source (source, gnutls_source->child_source);
594 gnutls_source->current_direction = direction;
598 gnutls_source_dispatch (GSource *source,
599 GSourceFunc callback,
602 GPollableSourceFunc func = (GPollableSourceFunc)callback;
603 GTlsConnectionGnutlsSource *gnutls_source = (GTlsConnectionGnutlsSource *)source;
604 GTlsConnectionGnutls *gnutls = gnutls_source->gnutls;
607 ret = (*func) (gnutls_source->stream, user_data);
610 GIOCondition direction = gnutls->priv->internal_direction ? gnutls->priv->internal_direction : gnutls_source->base_direction;
612 gnutls_source_sync_child_source (gnutls_source, direction);
619 gnutls_source_finalize (GSource *source)
621 GTlsConnectionGnutlsSource *gnutls_source = (GTlsConnectionGnutlsSource *)source;
623 g_object_unref (gnutls_source->gnutls);
625 if (gnutls_source->child_source)
626 g_source_unref (gnutls_source->child_source);
629 static GSourceFuncs gnutls_source_funcs =
631 gnutls_source_prepare,
633 gnutls_source_dispatch,
634 gnutls_source_finalize
638 g_tls_connection_gnutls_create_source (GTlsConnectionGnutls *gnutls,
639 GIOCondition condition,
640 GCancellable *cancellable)
642 GSource *source, *cancellable_source;
643 GTlsConnectionGnutlsSource *gnutls_source;
645 source = g_source_new (&gnutls_source_funcs, sizeof (GTlsConnectionGnutlsSource));
646 g_source_set_name (source, "GTlsConnectionGnutlsSource");
647 gnutls_source = (GTlsConnectionGnutlsSource *)source;
648 gnutls_source->gnutls = g_object_ref (gnutls);
649 gnutls_source->base_direction = condition & (G_IO_IN | G_IO_OUT);
650 if (gnutls_source->base_direction == G_IO_IN)
651 gnutls_source->stream = G_OBJECT (gnutls->priv->tls_istream);
652 else if (gnutls_source->base_direction == G_IO_OUT)
653 gnutls_source->stream = G_OBJECT (gnutls->priv->tls_ostream);
656 gnutls_source->base_direction = gnutls->priv->internal_direction;
657 gnutls_source->stream = NULL;
659 gnutls_source_sync_child_source (gnutls_source, gnutls_source->base_direction);
663 cancellable_source = g_cancellable_source_new (cancellable);
664 g_source_set_dummy_callback (cancellable_source);
665 g_source_add_child_source (source, cancellable_source);
666 g_source_unref (cancellable_source);
673 set_gnutls_error (GTlsConnectionGnutls *gnutls, GIOCondition direction)
675 if (g_error_matches (gnutls->priv->error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
676 gnutls_transport_set_errno (gnutls->priv->session, EINTR);
677 else if (g_error_matches (gnutls->priv->error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
679 gnutls_transport_set_errno (gnutls->priv->session, EAGAIN);
680 gnutls->priv->internal_direction = direction;
683 gnutls_transport_set_errno (gnutls->priv->session, EIO);
687 g_tls_connection_gnutls_pull_func (gnutls_transport_ptr_t transport_data,
691 GTlsConnectionGnutls *gnutls = transport_data;
694 /* If gnutls->priv->error is non-%NULL when we're called, it means
695 * that an error previously occurred, but gnutls decided not to
696 * propagate it. So it's correct for us to just clear it. (Usually
697 * this means it ignored an EAGAIN after a short read, and now
698 * we'll return EAGAIN again, which it will obey this time.)
700 g_clear_error (&gnutls->priv->error);
702 if (gnutls->priv->blocking)
704 ret = g_input_stream_read (G_INPUT_STREAM (gnutls->priv->base_istream),
706 gnutls->priv->cancellable,
707 &gnutls->priv->error);
711 ret = g_pollable_input_stream_read_nonblocking (gnutls->priv->base_istream,
713 gnutls->priv->cancellable,
714 &gnutls->priv->error);
718 set_gnutls_error (gnutls, G_IO_IN);
720 gnutls->priv->eof = TRUE;
726 g_tls_connection_gnutls_push_func (gnutls_transport_ptr_t transport_data,
730 GTlsConnectionGnutls *gnutls = transport_data;
733 /* See comment in pull_func. */
734 g_clear_error (&gnutls->priv->error);
736 if (gnutls->priv->blocking)
738 ret = g_output_stream_write (G_OUTPUT_STREAM (gnutls->priv->base_ostream),
740 gnutls->priv->cancellable,
741 &gnutls->priv->error);
745 ret = g_pollable_output_stream_write_nonblocking (gnutls->priv->base_ostream,
747 gnutls->priv->cancellable,
748 &gnutls->priv->error);
751 set_gnutls_error (gnutls, G_IO_OUT);
757 handshake_internal (GTlsConnectionGnutls *gnutls,
759 GCancellable *cancellable,
764 if (G_IS_TLS_SERVER_CONNECTION_GNUTLS (gnutls) &&
765 gnutls->priv->ever_handshaked && !gnutls->priv->need_handshake)
767 BEGIN_GNUTLS_IO (gnutls, blocking, cancellable);
768 ret = gnutls_rehandshake (gnutls->priv->session);
769 END_GNUTLS_IO (gnutls, ret, _("Error performing TLS handshake: %s"), error);
775 g_tls_connection_gnutls_set_handshake_priority (gnutls);
777 gnutls->priv->handshaking = TRUE;
778 G_TLS_CONNECTION_GNUTLS_GET_CLASS (gnutls)->begin_handshake (gnutls);
780 BEGIN_GNUTLS_IO (gnutls, blocking, cancellable);
781 ret = gnutls_handshake (gnutls->priv->session);
782 END_GNUTLS_IO (gnutls, ret, _("Error performing TLS handshake: %s"), error);
784 if (ret == GNUTLS_E_AGAIN)
787 gnutls->priv->handshaking = FALSE;
788 gnutls->priv->need_handshake = FALSE;
789 gnutls->priv->ever_handshaked = TRUE;
792 gnutls_certificate_type_get (gnutls->priv->session) == GNUTLS_CRT_X509)
794 GTlsCertificate *chain, *cert;
795 const gnutls_datum_t *certs;
796 unsigned int num_certs;
799 certs = gnutls_certificate_get_peers (gnutls->priv->session, &num_certs);
803 for (i = num_certs - 1; i >= 0; i--)
805 cert = g_tls_certificate_gnutls_new (&certs[i], chain);
810 g_tls_connection_set_peer_certificate (G_TLS_CONNECTION (gnutls), chain);
813 g_tls_connection_set_peer_certificate (G_TLS_CONNECTION (gnutls), NULL);
815 return G_TLS_CONNECTION_GNUTLS_GET_CLASS (gnutls)->finish_handshake (gnutls, ret == 0, error);
819 handshake_in_progress_or_failed (GTlsConnectionGnutls *gnutls,
821 GCancellable *cancellable,
824 if (!(gnutls->priv->need_handshake || gnutls->priv->handshaking))
827 return !handshake_internal (gnutls, blocking, cancellable, error);
831 g_tls_connection_gnutls_handshake (GTlsConnection *conn,
832 GCancellable *cancellable,
835 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (conn);
837 return handshake_internal (gnutls, TRUE, cancellable, error);
841 g_tls_connection_gnutls_handshake_ready (GObject *pollable_stream,
844 GTlsConnectionGnutls *gnutls;
845 GSimpleAsyncResult *simple = user_data;
847 GError *error = NULL;
849 gnutls = G_TLS_CONNECTION_GNUTLS (g_async_result_get_source_object (G_ASYNC_RESULT (simple)));
850 g_object_unref (gnutls);
852 success = handshake_internal (gnutls, FALSE, NULL, &error);
853 if (!success && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
855 g_error_free (error);
861 g_simple_async_result_set_from_error (simple, error);
862 g_error_free (error);
865 g_simple_async_result_set_op_res_gboolean (simple, success);
866 g_simple_async_result_complete (simple);
867 g_object_unref (simple);
873 g_tls_connection_gnutls_handshake_async (GTlsConnection *conn,
875 GCancellable *cancellable,
876 GAsyncReadyCallback callback,
879 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (conn);
880 GSimpleAsyncResult *simple;
882 GError *error = NULL;
885 simple = g_simple_async_result_new (G_OBJECT (conn), callback, user_data,
886 g_tls_connection_gnutls_handshake_async);
887 success = handshake_internal (gnutls, FALSE, cancellable, &error);
890 g_simple_async_result_set_op_res_gboolean (simple, TRUE);
891 g_simple_async_result_complete_in_idle (simple);
892 g_object_unref (simple);
894 else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
896 g_simple_async_result_set_from_error (simple, error);
897 g_error_free (error);
898 g_simple_async_result_complete_in_idle (simple);
899 g_object_unref (simple);
902 source = g_tls_connection_gnutls_create_source (gnutls, 0, cancellable);
903 g_source_set_callback (source,
904 (GSourceFunc) g_tls_connection_gnutls_handshake_ready,
906 g_source_set_priority (source, io_priority);
907 g_source_attach (source, g_main_context_get_thread_default ());
908 g_source_unref (source);
912 g_tls_connection_gnutls_handshake_finish (GTlsConnection *conn,
913 GAsyncResult *result,
916 GSimpleAsyncResult *simple;
918 g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (conn), g_tls_connection_gnutls_handshake_async), FALSE);
920 simple = G_SIMPLE_ASYNC_RESULT (result);
922 if (g_simple_async_result_propagate_error (simple, error))
925 return g_simple_async_result_get_op_res_gboolean (simple);
929 g_tls_connection_gnutls_read (GTlsConnectionGnutls *gnutls,
933 GCancellable *cancellable,
939 if (handshake_in_progress_or_failed (gnutls, blocking, cancellable, error))
942 BEGIN_GNUTLS_IO (gnutls, blocking, cancellable);
943 ret = gnutls_record_recv (gnutls->priv->session, buffer, count);
944 END_GNUTLS_IO (gnutls, ret, _("Error reading data from TLS socket: %s"), error);
948 else if (ret == GNUTLS_E_REHANDSHAKE)
955 g_tls_connection_gnutls_write (GTlsConnectionGnutls *gnutls,
959 GCancellable *cancellable,
965 if (handshake_in_progress_or_failed (gnutls, blocking, cancellable, error))
968 BEGIN_GNUTLS_IO (gnutls, blocking, cancellable);
969 ret = gnutls_record_send (gnutls->priv->session, buffer, count);
970 END_GNUTLS_IO (gnutls, ret, _("Error writing data to TLS socket: %s"), error);
974 else if (ret == GNUTLS_E_REHANDSHAKE)
980 static GInputStream *
981 g_tls_connection_gnutls_get_input_stream (GIOStream *stream)
983 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (stream);
985 return gnutls->priv->tls_istream;
988 static GOutputStream *
989 g_tls_connection_gnutls_get_output_stream (GIOStream *stream)
991 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (stream);
993 return gnutls->priv->tls_ostream;
997 close_internal (GTlsConnectionGnutls *gnutls,
999 GCancellable *cancellable,
1004 if (!gnutls->priv->require_close_notify)
1007 /* If we haven't finished the initial handshake yet, there's no
1008 * reason to finish it just so we can close.
1010 if (gnutls->priv->handshaking && !gnutls->priv->ever_handshaked)
1013 if (handshake_in_progress_or_failed (gnutls, blocking, cancellable, error))
1016 gnutls->priv->closing = TRUE;
1017 BEGIN_GNUTLS_IO (gnutls, blocking, cancellable);
1018 ret = gnutls_bye (gnutls->priv->session, GNUTLS_SHUT_WR);
1019 END_GNUTLS_IO (gnutls, ret, _("Error performing TLS close: %s"), error);
1020 if (ret == 0 || !error || !g_error_matches (*error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
1021 gnutls->priv->closing = FALSE;
1027 g_tls_connection_gnutls_close (GIOStream *stream,
1028 GCancellable *cancellable,
1031 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (stream);
1033 if (!close_internal (gnutls, TRUE, cancellable, error))
1035 return g_io_stream_close (gnutls->priv->base_io_stream,
1036 cancellable, error);
1040 GSimpleAsyncResult *simple;
1041 GCancellable *cancellable;
1046 close_base_stream_cb (GObject *base_stream,
1047 GAsyncResult *result,
1051 GError *error = NULL;
1052 AsyncCloseData *acd = user_data;
1054 success = g_io_stream_close_finish (G_IO_STREAM (base_stream),
1057 g_simple_async_result_set_op_res_gboolean (acd->simple, TRUE);
1060 g_simple_async_result_set_from_error (acd->simple, error);
1061 g_error_free (error);
1064 g_simple_async_result_complete (acd->simple);
1065 g_object_unref (acd->simple);
1066 if (acd->cancellable)
1067 g_object_unref (acd->cancellable);
1068 g_slice_free (AsyncCloseData, acd);
1072 g_tls_connection_gnutls_close_ready (GObject *pollable_stream,
1075 GTlsConnectionGnutls *gnutls;
1076 AsyncCloseData *acd = user_data;
1078 GError *error = NULL;
1080 gnutls = G_TLS_CONNECTION_GNUTLS (g_async_result_get_source_object (G_ASYNC_RESULT (acd->simple)));
1081 g_object_unref (gnutls);
1083 success = close_internal (gnutls, FALSE, NULL, &error);
1084 if (!success && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
1086 g_error_free (error);
1092 g_simple_async_result_set_from_error (acd->simple, error);
1093 g_simple_async_result_complete (acd->simple);
1094 g_error_free (error);
1095 g_object_unref (acd->simple);
1096 if (acd->cancellable)
1097 g_object_unref (acd->cancellable);
1098 g_slice_free (AsyncCloseData, acd);
1102 g_io_stream_close_async (gnutls->priv->base_io_stream,
1103 acd->io_priority, acd->cancellable,
1104 close_base_stream_cb, acd);
1111 g_tls_connection_gnutls_close_async (GIOStream *stream,
1113 GCancellable *cancellable,
1114 GAsyncReadyCallback callback,
1117 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (stream);
1118 GSimpleAsyncResult *simple;
1120 GError *error = NULL;
1121 AsyncCloseData *acd;
1124 simple = g_simple_async_result_new (G_OBJECT (stream), callback, user_data,
1125 g_tls_connection_gnutls_close_async);
1127 success = close_internal (gnutls, FALSE, cancellable, &error);
1128 if (error && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
1130 g_simple_async_result_set_from_error (simple, error);
1131 g_error_free (error);
1132 g_simple_async_result_complete_in_idle (simple);
1133 g_object_unref (simple);
1137 g_error_free (error);
1139 acd = g_slice_new (AsyncCloseData);
1140 acd->simple = simple;
1141 acd->cancellable = g_object_ref (cancellable);
1142 acd->io_priority = io_priority;
1146 g_io_stream_close_async (gnutls->priv->base_io_stream,
1147 io_priority, cancellable,
1148 close_base_stream_cb, acd);
1152 source = g_tls_connection_gnutls_create_source (gnutls, 0, acd->cancellable);
1153 g_source_set_callback (source,
1154 (GSourceFunc) g_tls_connection_gnutls_close_ready,
1156 g_source_set_priority (source, acd->io_priority);
1157 g_source_attach (source, g_main_context_get_thread_default ());
1158 g_source_unref (source);
1162 g_tls_connection_gnutls_close_finish (GIOStream *stream,
1163 GAsyncResult *result,
1166 GSimpleAsyncResult *simple;
1168 g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (stream), g_tls_connection_gnutls_close_async), FALSE);
1170 simple = G_SIMPLE_ASYNC_RESULT (result);
1172 if (g_simple_async_result_propagate_error (simple, error))
1175 return g_simple_async_result_get_op_res_gboolean (simple);