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"
35 #include <p11-kit/pin.h>
36 #include "pkcs11/gpkcs11pin.h"
39 #include <glib/gi18n-lib.h>
41 static void g_tls_connection_gnutls_get_property (GObject *object,
45 static void g_tls_connection_gnutls_set_property (GObject *object,
49 static void g_tls_connection_gnutls_finalize (GObject *object);
51 static gboolean g_tls_connection_gnutls_handshake (GTlsConnection *connection,
52 GCancellable *cancellable,
54 static void g_tls_connection_gnutls_handshake_async (GTlsConnection *conn,
56 GCancellable *cancellable,
57 GAsyncReadyCallback callback,
59 static gboolean g_tls_connection_gnutls_handshake_finish (GTlsConnection *conn,
63 static GInputStream *g_tls_connection_gnutls_get_input_stream (GIOStream *stream);
64 static GOutputStream *g_tls_connection_gnutls_get_output_stream (GIOStream *stream);
66 static gboolean g_tls_connection_gnutls_close (GIOStream *stream,
67 GCancellable *cancellable,
69 static void g_tls_connection_gnutls_close_async (GIOStream *stream,
71 GCancellable *cancellable,
72 GAsyncReadyCallback callback,
74 static gboolean g_tls_connection_gnutls_close_finish (GIOStream *stream,
78 static ssize_t g_tls_connection_gnutls_push_func (gnutls_transport_ptr_t transport_data,
81 static ssize_t g_tls_connection_gnutls_pull_func (gnutls_transport_ptr_t transport_data,
85 static void g_tls_connection_gnutls_initable_iface_init (GInitableIface *iface);
86 static gboolean g_tls_connection_gnutls_initable_init (GInitable *initable,
87 GCancellable *cancellable,
91 static P11KitPin* on_pin_prompt_callback (const char *pinfile,
93 const char *pin_description,
94 P11KitPinFlags pin_flags,
98 static void g_tls_connection_gnutls_init_priorities (void);
100 G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GTlsConnectionGnutls, g_tls_connection_gnutls, G_TYPE_TLS_CONNECTION,
101 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
102 g_tls_connection_gnutls_initable_iface_init);
103 g_tls_connection_gnutls_init_priorities ();
111 PROP_REQUIRE_CLOSE_NOTIFY,
112 PROP_REHANDSHAKE_MODE,
113 PROP_USE_SYSTEM_CERTDB,
117 PROP_PEER_CERTIFICATE,
118 PROP_PEER_CERTIFICATE_ERRORS
121 struct _GTlsConnectionGnutlsPrivate
123 GIOStream *base_io_stream;
124 GPollableInputStream *base_istream;
125 GPollableOutputStream *base_ostream;
127 gnutls_certificate_credentials creds;
128 gnutls_session session;
130 GTlsCertificate *certificate, *peer_certificate;
131 GTlsCertificateFlags peer_certificate_errors;
132 gboolean require_close_notify;
133 GTlsRehandshakeMode rehandshake_mode;
134 gboolean is_system_certdb;
135 GTlsDatabase *database;
136 gboolean database_is_unset;
137 gboolean need_handshake, handshaking, ever_handshaked;
140 GInputStream *tls_istream;
141 GOutputStream *tls_ostream;
143 GTlsInteraction *interaction;
144 gchar *interaction_id;
147 GCancellable *cancellable;
149 #ifndef GNUTLS_E_PREMATURE_TERMINATION
152 GIOCondition internal_direction;
155 static gint unique_interaction_id = 0;
158 g_tls_connection_gnutls_class_init (GTlsConnectionGnutlsClass *klass)
160 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
161 GTlsConnectionClass *connection_class = G_TLS_CONNECTION_CLASS (klass);
162 GIOStreamClass *iostream_class = G_IO_STREAM_CLASS (klass);
164 g_type_class_add_private (klass, sizeof (GTlsConnectionGnutlsPrivate));
166 gobject_class->get_property = g_tls_connection_gnutls_get_property;
167 gobject_class->set_property = g_tls_connection_gnutls_set_property;
168 gobject_class->finalize = g_tls_connection_gnutls_finalize;
170 connection_class->handshake = g_tls_connection_gnutls_handshake;
171 connection_class->handshake_async = g_tls_connection_gnutls_handshake_async;
172 connection_class->handshake_finish = g_tls_connection_gnutls_handshake_finish;
174 iostream_class->get_input_stream = g_tls_connection_gnutls_get_input_stream;
175 iostream_class->get_output_stream = g_tls_connection_gnutls_get_output_stream;
176 iostream_class->close_fn = g_tls_connection_gnutls_close;
177 iostream_class->close_async = g_tls_connection_gnutls_close_async;
178 iostream_class->close_finish = g_tls_connection_gnutls_close_finish;
180 g_object_class_override_property (gobject_class, PROP_BASE_IO_STREAM, "base-io-stream");
181 g_object_class_override_property (gobject_class, PROP_REQUIRE_CLOSE_NOTIFY, "require-close-notify");
182 g_object_class_override_property (gobject_class, PROP_REHANDSHAKE_MODE, "rehandshake-mode");
183 g_object_class_override_property (gobject_class, PROP_USE_SYSTEM_CERTDB, "use-system-certdb");
184 g_object_class_override_property (gobject_class, PROP_DATABASE, "database");
185 g_object_class_override_property (gobject_class, PROP_CERTIFICATE, "certificate");
186 g_object_class_override_property (gobject_class, PROP_INTERACTION, "interaction");
187 g_object_class_override_property (gobject_class, PROP_PEER_CERTIFICATE, "peer-certificate");
188 g_object_class_override_property (gobject_class, PROP_PEER_CERTIFICATE_ERRORS, "peer-certificate-errors");
192 g_tls_connection_gnutls_initable_iface_init (GInitableIface *iface)
194 iface->init = g_tls_connection_gnutls_initable_init;
198 g_tls_connection_gnutls_init (GTlsConnectionGnutls *gnutls)
202 gnutls->priv = G_TYPE_INSTANCE_GET_PRIVATE (gnutls, G_TYPE_TLS_CONNECTION_GNUTLS, GTlsConnectionGnutlsPrivate);
204 gnutls_certificate_allocate_credentials (&gnutls->priv->creds);
205 gnutls_certificate_set_verify_flags (gnutls->priv->creds,
206 GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
208 gnutls->priv->need_handshake = TRUE;
210 gnutls->priv->database_is_unset = TRUE;
211 gnutls->priv->is_system_certdb = TRUE;
213 unique_id = g_atomic_int_add (&unique_interaction_id, 1);
214 gnutls->priv->interaction_id = g_strdup_printf ("gtls:%d", unique_id);
217 p11_kit_pin_register_callback (gnutls->priv->interaction_id,
218 on_pin_prompt_callback, gnutls, NULL);
222 static gnutls_priority_t priorities[2][2];
225 g_tls_connection_gnutls_init_priorities (void)
227 /* First field is "ssl3 only", second is "allow unsafe rehandshaking" */
229 gnutls_priority_init (&priorities[FALSE][FALSE],
232 gnutls_priority_init (&priorities[TRUE][FALSE],
233 "NORMAL:%COMPAT:!VERS-TLS1.2:!VERS-TLS1.1:!VERS-TLS1.0",
235 gnutls_priority_init (&priorities[FALSE][TRUE],
236 "NORMAL:%COMPAT:%UNSAFE_RENEGOTIATION",
238 gnutls_priority_init (&priorities[TRUE][TRUE],
239 "NORMAL:%COMPAT:!VERS-TLS1.2:!VERS-TLS1.1:!VERS-TLS1.0:%UNSAFE_RENEGOTIATION",
244 g_tls_connection_gnutls_set_handshake_priority (GTlsConnectionGnutls *gnutls)
246 gboolean use_ssl3, unsafe_rehandshake;
248 if (G_IS_TLS_CLIENT_CONNECTION (gnutls))
249 use_ssl3 = g_tls_client_connection_get_use_ssl3 (G_TLS_CLIENT_CONNECTION (gnutls));
252 unsafe_rehandshake = (gnutls->priv->rehandshake_mode == G_TLS_REHANDSHAKE_UNSAFELY);
253 gnutls_priority_set (gnutls->priv->session,
254 priorities[use_ssl3][unsafe_rehandshake]);
258 g_tls_connection_gnutls_initable_init (GInitable *initable,
259 GCancellable *cancellable,
262 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (initable);
265 g_return_val_if_fail (gnutls->priv->base_istream != NULL &&
266 gnutls->priv->base_ostream != NULL, FALSE);
268 /* Make sure gnutls->priv->session has been initialized (it may have
269 * already been initialized by a construct-time property setter).
271 g_tls_connection_gnutls_get_session (gnutls);
273 status = gnutls_credentials_set (gnutls->priv->session,
274 GNUTLS_CRD_CERTIFICATE,
275 gnutls->priv->creds);
278 g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
279 _("Could not create TLS connection: %s"),
280 gnutls_strerror (status));
284 /* Some servers (especially on embedded devices) use tiny keys that
285 * gnutls will reject by default. We want it to accept them.
287 gnutls_dh_set_prime_bits (gnutls->priv->session, 256);
289 gnutls_transport_set_push_function (gnutls->priv->session,
290 g_tls_connection_gnutls_push_func);
291 gnutls_transport_set_pull_function (gnutls->priv->session,
292 g_tls_connection_gnutls_pull_func);
293 gnutls_transport_set_ptr (gnutls->priv->session, gnutls);
295 gnutls->priv->tls_istream = g_tls_input_stream_gnutls_new (gnutls);
296 gnutls->priv->tls_ostream = g_tls_output_stream_gnutls_new (gnutls);
302 g_tls_connection_gnutls_finalize (GObject *object)
304 GTlsConnectionGnutls *connection = G_TLS_CONNECTION_GNUTLS (object);
306 if (connection->priv->base_io_stream)
307 g_object_unref (connection->priv->base_io_stream);
309 if (connection->priv->session)
310 gnutls_deinit (connection->priv->session);
312 if (connection->priv->tls_istream)
313 g_object_unref (connection->priv->tls_istream);
314 if (connection->priv->tls_ostream)
315 g_object_unref (connection->priv->tls_ostream);
317 if (connection->priv->creds)
318 gnutls_certificate_free_credentials (connection->priv->creds);
320 if (connection->priv->database)
321 g_object_unref (connection->priv->database);
322 if (connection->priv->certificate)
323 g_object_unref (connection->priv->certificate);
324 if (connection->priv->peer_certificate)
325 g_object_unref (connection->priv->peer_certificate);
327 g_clear_object (&connection->priv->interaction);
329 if (connection->priv->error)
330 g_error_free (connection->priv->error);
333 p11_kit_pin_unregister_callback (connection->priv->interaction_id,
334 on_pin_prompt_callback, connection);
336 g_free (connection->priv->interaction_id);
338 G_OBJECT_CLASS (g_tls_connection_gnutls_parent_class)->finalize (object);
342 g_tls_connection_gnutls_get_property (GObject *object,
347 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (object);
348 GTlsBackend *backend;
352 case PROP_BASE_IO_STREAM:
353 g_value_set_object (value, gnutls->priv->base_io_stream);
356 case PROP_REQUIRE_CLOSE_NOTIFY:
357 g_value_set_boolean (value, gnutls->priv->require_close_notify);
360 case PROP_REHANDSHAKE_MODE:
361 g_value_set_enum (value, gnutls->priv->rehandshake_mode);
364 case PROP_USE_SYSTEM_CERTDB:
365 g_value_set_boolean (value, gnutls->priv->is_system_certdb);
369 if (gnutls->priv->database_is_unset)
371 backend = g_tls_backend_get_default ();
372 gnutls->priv->database = g_tls_backend_get_default_database (backend);
373 gnutls->priv->database_is_unset = FALSE;
375 g_value_set_object (value, gnutls->priv->database);
378 case PROP_CERTIFICATE:
379 g_value_set_object (value, gnutls->priv->certificate);
382 case PROP_INTERACTION:
383 g_value_set_object (value, gnutls->priv->interaction);
386 case PROP_PEER_CERTIFICATE:
387 g_value_set_object (value, gnutls->priv->peer_certificate);
390 case PROP_PEER_CERTIFICATE_ERRORS:
391 g_value_set_flags (value, gnutls->priv->peer_certificate_errors);
395 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
400 g_tls_connection_gnutls_set_property (GObject *object,
405 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (object);
406 GInputStream *istream;
407 GOutputStream *ostream;
408 gboolean system_certdb;
409 GTlsBackend *backend;
413 case PROP_BASE_IO_STREAM:
414 if (gnutls->priv->base_io_stream)
416 g_object_unref (gnutls->priv->base_io_stream);
417 gnutls->priv->base_istream = NULL;
418 gnutls->priv->base_ostream = NULL;
420 gnutls->priv->base_io_stream = g_value_dup_object (value);
421 if (!gnutls->priv->base_io_stream)
424 istream = g_io_stream_get_input_stream (gnutls->priv->base_io_stream);
425 ostream = g_io_stream_get_output_stream (gnutls->priv->base_io_stream);
427 if (G_IS_POLLABLE_INPUT_STREAM (istream) &&
428 g_pollable_input_stream_can_poll (G_POLLABLE_INPUT_STREAM (istream)))
429 gnutls->priv->base_istream = G_POLLABLE_INPUT_STREAM (istream);
430 if (G_IS_POLLABLE_OUTPUT_STREAM (ostream) &&
431 g_pollable_output_stream_can_poll (G_POLLABLE_OUTPUT_STREAM (ostream)))
432 gnutls->priv->base_ostream = G_POLLABLE_OUTPUT_STREAM (ostream);
435 case PROP_REQUIRE_CLOSE_NOTIFY:
436 gnutls->priv->require_close_notify = g_value_get_boolean (value);
439 case PROP_REHANDSHAKE_MODE:
440 gnutls->priv->rehandshake_mode = g_value_get_enum (value);
443 case PROP_USE_SYSTEM_CERTDB:
444 system_certdb = g_value_get_boolean (value);
445 if (system_certdb != gnutls->priv->is_system_certdb)
447 g_clear_object (&gnutls->priv->database);
450 backend = g_tls_backend_get_default ();
451 gnutls->priv->database = g_tls_backend_get_default_database (backend);
453 gnutls->priv->is_system_certdb = system_certdb;
458 g_clear_object (&gnutls->priv->database);
459 gnutls->priv->database = g_value_dup_object (value);
460 gnutls->priv->is_system_certdb = FALSE;
461 gnutls->priv->database_is_unset = FALSE;
464 case PROP_CERTIFICATE:
465 if (gnutls->priv->certificate)
466 g_object_unref (gnutls->priv->certificate);
467 gnutls->priv->certificate = g_value_dup_object (value);
470 case PROP_INTERACTION:
471 g_clear_object (&gnutls->priv->interaction);
472 gnutls->priv->interaction = g_value_dup_object (value);
476 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
480 gnutls_certificate_credentials
481 g_tls_connection_gnutls_get_credentials (GTlsConnectionGnutls *gnutls)
483 return gnutls->priv->creds;
487 g_tls_connection_gnutls_get_session (GTlsConnectionGnutls *gnutls)
489 /* Ideally we would initialize gnutls->priv->session from
490 * g_tls_connection_gnutls_init(), but we can't tell if it's a
491 * client or server connection at that point... And
492 * g_tls_connection_gnutls_initiable_init() is too late, because
493 * construct-time property setters may need to modify it.
495 if (!gnutls->priv->session)
497 gboolean client = G_IS_TLS_CLIENT_CONNECTION (gnutls);
498 gnutls_init (&gnutls->priv->session, client ? GNUTLS_CLIENT : GNUTLS_SERVER);
501 return gnutls->priv->session;
505 g_tls_connection_gnutls_get_certificate (GTlsConnectionGnutls *gnutls,
508 GTlsCertificate *cert;
510 cert = g_tls_connection_get_certificate (G_TLS_CONNECTION (gnutls));
512 st->cert_type = GNUTLS_CRT_X509;
516 g_tls_certificate_gnutls_copy (G_TLS_CERTIFICATE_GNUTLS (cert),
517 gnutls->priv->interaction_id, st);
521 begin_gnutls_io (GTlsConnectionGnutls *gnutls,
523 GCancellable *cancellable)
525 gnutls->priv->blocking = blocking;
526 gnutls->priv->cancellable = cancellable;
527 gnutls->priv->internal_direction = 0;
529 g_cancellable_push_current (cancellable);
530 g_clear_error (&gnutls->priv->error);
534 end_gnutls_io (GTlsConnectionGnutls *gnutls,
538 if (gnutls->priv->cancellable)
539 g_cancellable_pop_current (gnutls->priv->cancellable);
540 gnutls->priv->cancellable = NULL;
544 g_clear_error (&gnutls->priv->error);
548 if (gnutls->priv->handshaking && !gnutls->priv->ever_handshaked)
550 if (g_error_matches (gnutls->priv->error, G_IO_ERROR, G_IO_ERROR_FAILED) ||
551 status == GNUTLS_E_UNEXPECTED_PACKET_LENGTH ||
552 status == GNUTLS_E_FATAL_ALERT_RECEIVED ||
553 status == GNUTLS_E_DECRYPTION_FAILED ||
554 status == GNUTLS_E_UNSUPPORTED_VERSION_PACKET)
556 g_clear_error (&gnutls->priv->error);
557 g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_NOT_TLS,
558 _("Peer failed to perform TLS handshake"));
559 return GNUTLS_E_PULL_ERROR;
563 if (gnutls->priv->error)
565 if (g_error_matches (gnutls->priv->error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
566 status = GNUTLS_E_AGAIN;
567 g_propagate_error (error, gnutls->priv->error);
568 gnutls->priv->error = NULL;
571 else if (status == GNUTLS_E_REHANDSHAKE)
573 if (gnutls->priv->rehandshake_mode == G_TLS_REHANDSHAKE_NEVER)
575 g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
576 _("Peer requested illegal TLS rehandshake"));
577 return GNUTLS_E_PULL_ERROR;
580 gnutls->priv->need_handshake = TRUE;
584 #ifdef GNUTLS_E_PREMATURE_TERMINATION
585 status == GNUTLS_E_PREMATURE_TERMINATION
587 status == GNUTLS_E_UNEXPECTED_PACKET_LENGTH && gnutls->priv->eof
591 if (gnutls->priv->require_close_notify)
593 g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_EOF,
594 _("TLS connection closed unexpectedly"));
604 #define BEGIN_GNUTLS_IO(gnutls, blocking, cancellable) \
605 begin_gnutls_io (gnutls, blocking, cancellable); \
608 #define END_GNUTLS_IO(gnutls, ret, errmsg, error) \
609 } while ((ret == GNUTLS_E_AGAIN || \
610 ret == GNUTLS_E_WARNING_ALERT_RECEIVED) && \
611 !gnutls->priv->error); \
612 ret = end_gnutls_io (gnutls, ret, error); \
613 if (ret < 0 && ret != GNUTLS_E_REHANDSHAKE && error && !*error) \
615 g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,\
616 errmsg, gnutls_strerror (ret)); \
621 g_tls_connection_gnutls_check (GTlsConnectionGnutls *gnutls,
622 GIOCondition condition)
624 if (!gnutls->priv->internal_direction)
627 if (gnutls->priv->handshaking || gnutls->priv->closing)
628 condition = gnutls->priv->internal_direction;
630 if (condition & G_IO_IN)
631 return g_pollable_input_stream_is_readable (gnutls->priv->base_istream);
633 return g_pollable_output_stream_is_writable (gnutls->priv->base_ostream);
639 GTlsConnectionGnutls *gnutls;
642 GSource *child_source;
643 GIOCondition current_direction;
644 } GTlsConnectionGnutlsSource;
647 gnutls_source_prepare (GSource *source,
655 gnutls_source_check (GSource *source)
661 gnutls_source_sync_child_source (GTlsConnectionGnutlsSource *gnutls_source)
663 GTlsConnectionGnutls *gnutls = gnutls_source->gnutls;
664 GSource *source = (GSource *)gnutls_source;
665 GIOCondition direction;
667 if (gnutls->priv->handshaking || gnutls->priv->closing)
668 direction = gnutls->priv->internal_direction;
669 else if (!gnutls_source->stream)
671 else if (G_IS_TLS_INPUT_STREAM_GNUTLS (gnutls_source->stream))
674 direction = G_IO_OUT;
676 if (direction == gnutls_source->current_direction)
679 if (gnutls_source->child_source)
681 g_source_remove_child_source (source, gnutls_source->child_source);
682 g_source_unref (gnutls_source->child_source);
685 if (direction & G_IO_IN)
686 gnutls_source->child_source = g_pollable_input_stream_create_source (gnutls->priv->base_istream, NULL);
688 gnutls_source->child_source = g_pollable_output_stream_create_source (gnutls->priv->base_ostream, NULL);
690 g_source_set_dummy_callback (gnutls_source->child_source);
691 g_source_add_child_source (source, gnutls_source->child_source);
692 gnutls_source->current_direction = direction;
697 gnutls_source_dispatch (GSource *source,
698 GSourceFunc callback,
701 GPollableSourceFunc func = (GPollableSourceFunc)callback;
702 GTlsConnectionGnutlsSource *gnutls_source = (GTlsConnectionGnutlsSource *)source;
705 ret = (*func) (gnutls_source->stream, user_data);
707 ret = gnutls_source_sync_child_source (gnutls_source);
713 gnutls_source_finalize (GSource *source)
715 GTlsConnectionGnutlsSource *gnutls_source = (GTlsConnectionGnutlsSource *)source;
717 g_object_unref (gnutls_source->gnutls);
719 if (gnutls_source->child_source)
720 g_source_unref (gnutls_source->child_source);
724 g_tls_connection_gnutls_source_closure_callback (GObject *stream,
727 GClosure *closure = data;
729 GValue param = { 0, };
730 GValue result_value = { 0, };
733 g_value_init (&result_value, G_TYPE_BOOLEAN);
735 g_value_init (¶m, G_TYPE_OBJECT);
736 g_value_set_object (¶m, stream);
738 g_closure_invoke (closure, &result_value, 1, ¶m, NULL);
740 result = g_value_get_boolean (&result_value);
741 g_value_unset (&result_value);
742 g_value_unset (¶m);
747 static GSourceFuncs gnutls_source_funcs =
749 gnutls_source_prepare,
751 gnutls_source_dispatch,
752 gnutls_source_finalize,
753 (GSourceFunc)g_tls_connection_gnutls_source_closure_callback,
754 (GSourceDummyMarshal)g_cclosure_marshal_generic
758 g_tls_connection_gnutls_create_source (GTlsConnectionGnutls *gnutls,
759 GIOCondition condition,
760 GCancellable *cancellable)
762 GSource *source, *cancellable_source;
763 GTlsConnectionGnutlsSource *gnutls_source;
765 source = g_source_new (&gnutls_source_funcs, sizeof (GTlsConnectionGnutlsSource));
766 g_source_set_name (source, "GTlsConnectionGnutlsSource");
767 gnutls_source = (GTlsConnectionGnutlsSource *)source;
768 gnutls_source->gnutls = g_object_ref (gnutls);
769 if (condition & G_IO_IN)
770 gnutls_source->stream = G_OBJECT (gnutls->priv->tls_istream);
771 else if (condition & G_IO_OUT)
772 gnutls_source->stream = G_OBJECT (gnutls->priv->tls_ostream);
773 gnutls_source_sync_child_source (gnutls_source);
777 cancellable_source = g_cancellable_source_new (cancellable);
778 g_source_set_dummy_callback (cancellable_source);
779 g_source_add_child_source (source, cancellable_source);
780 g_source_unref (cancellable_source);
787 set_gnutls_error (GTlsConnectionGnutls *gnutls, GIOCondition direction)
789 if (g_error_matches (gnutls->priv->error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
790 gnutls_transport_set_errno (gnutls->priv->session, EINTR);
791 else if (g_error_matches (gnutls->priv->error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
793 gnutls_transport_set_errno (gnutls->priv->session, EAGAIN);
794 gnutls->priv->internal_direction = direction;
797 gnutls_transport_set_errno (gnutls->priv->session, EIO);
801 g_tls_connection_gnutls_pull_func (gnutls_transport_ptr_t transport_data,
805 GTlsConnectionGnutls *gnutls = transport_data;
808 /* If gnutls->priv->error is non-%NULL when we're called, it means
809 * that an error previously occurred, but gnutls decided not to
810 * propagate it. So it's correct for us to just clear it. (Usually
811 * this means it ignored an EAGAIN after a short read, and now
812 * we'll return EAGAIN again, which it will obey this time.)
814 g_clear_error (&gnutls->priv->error);
816 if (gnutls->priv->blocking)
818 ret = g_input_stream_read (G_INPUT_STREAM (gnutls->priv->base_istream),
820 gnutls->priv->cancellable,
821 &gnutls->priv->error);
825 ret = g_pollable_input_stream_read_nonblocking (gnutls->priv->base_istream,
827 gnutls->priv->cancellable,
828 &gnutls->priv->error);
832 set_gnutls_error (gnutls, G_IO_IN);
833 #ifndef GNUTLS_E_PREMATURE_TERMINATION
835 gnutls->priv->eof = TRUE;
842 g_tls_connection_gnutls_push_func (gnutls_transport_ptr_t transport_data,
846 GTlsConnectionGnutls *gnutls = transport_data;
849 /* See comment in pull_func. */
850 g_clear_error (&gnutls->priv->error);
852 if (gnutls->priv->blocking)
854 ret = g_output_stream_write (G_OUTPUT_STREAM (gnutls->priv->base_ostream),
856 gnutls->priv->cancellable,
857 &gnutls->priv->error);
861 ret = g_pollable_output_stream_write_nonblocking (gnutls->priv->base_ostream,
863 gnutls->priv->cancellable,
864 &gnutls->priv->error);
867 set_gnutls_error (gnutls, G_IO_OUT);
873 handshake_internal (GTlsConnectionGnutls *gnutls,
875 GCancellable *cancellable,
878 GTlsCertificate *peer_certificate = NULL;
879 GTlsCertificateFlags peer_certificate_errors = 0;
882 if (G_IS_TLS_SERVER_CONNECTION_GNUTLS (gnutls) &&
883 gnutls->priv->ever_handshaked && !gnutls->priv->handshaking &&
884 !gnutls->priv->need_handshake)
886 BEGIN_GNUTLS_IO (gnutls, blocking, cancellable);
887 ret = gnutls_rehandshake (gnutls->priv->session);
888 END_GNUTLS_IO (gnutls, ret, _("Error performing TLS handshake: %s"), error);
894 if (!gnutls->priv->handshaking)
896 gnutls->priv->handshaking = TRUE;
898 if (gnutls->priv->peer_certificate)
900 g_object_unref (gnutls->priv->peer_certificate);
901 gnutls->priv->peer_certificate = NULL;
902 gnutls->priv->peer_certificate_errors = 0;
904 g_object_notify (G_OBJECT (gnutls), "peer-certificate");
905 g_object_notify (G_OBJECT (gnutls), "peer-certificate-errors");
908 g_tls_connection_gnutls_set_handshake_priority (gnutls);
909 G_TLS_CONNECTION_GNUTLS_GET_CLASS (gnutls)->begin_handshake (gnutls);
912 BEGIN_GNUTLS_IO (gnutls, blocking, cancellable);
913 ret = gnutls_handshake (gnutls->priv->session);
914 END_GNUTLS_IO (gnutls, ret, _("Error performing TLS handshake: %s"), error);
916 if (ret == GNUTLS_E_AGAIN)
919 gnutls->priv->handshaking = FALSE;
920 gnutls->priv->need_handshake = FALSE;
921 gnutls->priv->ever_handshaked = TRUE;
924 gnutls_certificate_type_get (gnutls->priv->session) == GNUTLS_CRT_X509)
926 GTlsCertificate *chain, *cert;
927 const gnutls_datum_t *certs;
928 unsigned int num_certs;
931 certs = gnutls_certificate_get_peers (gnutls->priv->session, &num_certs);
935 for (i = num_certs - 1; i >= 0; i--)
937 cert = g_tls_certificate_gnutls_new (&certs[i], chain);
939 g_object_unref (chain);
944 peer_certificate = chain;
947 if (peer_certificate)
951 accepted = G_TLS_CONNECTION_GNUTLS_GET_CLASS (gnutls)->verify_peer (gnutls, peer_certificate, &peer_certificate_errors);
953 gnutls->priv->peer_certificate = peer_certificate;
954 gnutls->priv->peer_certificate_errors = peer_certificate_errors;
956 g_object_notify (G_OBJECT (gnutls), "peer-certificate");
957 g_object_notify (G_OBJECT (gnutls), "peer-certificate-errors");
961 g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
962 _("Unacceptable TLS certificate"));
967 G_TLS_CONNECTION_GNUTLS_GET_CLASS (gnutls)->finish_handshake (gnutls, ret == 0, error);
972 handshake_in_progress_or_failed (GTlsConnectionGnutls *gnutls,
974 GCancellable *cancellable,
977 if (!(gnutls->priv->need_handshake || gnutls->priv->handshaking))
980 return !handshake_internal (gnutls, blocking, cancellable, error);
984 g_tls_connection_gnutls_handshake (GTlsConnection *conn,
985 GCancellable *cancellable,
988 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (conn);
990 return handshake_internal (gnutls, TRUE, cancellable, error);
994 g_tls_connection_gnutls_handshake_ready (GObject *pollable_stream,
997 GTlsConnectionGnutls *gnutls;
998 GSimpleAsyncResult *simple = user_data;
1000 GError *error = NULL;
1002 gnutls = G_TLS_CONNECTION_GNUTLS (g_async_result_get_source_object (G_ASYNC_RESULT (simple)));
1003 g_object_unref (gnutls);
1005 success = handshake_internal (gnutls, FALSE, NULL, &error);
1006 if (!success && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
1008 g_error_free (error);
1014 g_simple_async_result_set_from_error (simple, error);
1015 g_error_free (error);
1018 g_simple_async_result_set_op_res_gboolean (simple, success);
1019 g_simple_async_result_complete (simple);
1020 g_object_unref (simple);
1026 g_tls_connection_gnutls_handshake_async (GTlsConnection *conn,
1028 GCancellable *cancellable,
1029 GAsyncReadyCallback callback,
1032 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (conn);
1033 GSimpleAsyncResult *simple;
1035 GError *error = NULL;
1038 simple = g_simple_async_result_new (G_OBJECT (conn), callback, user_data,
1039 g_tls_connection_gnutls_handshake_async);
1040 success = handshake_internal (gnutls, FALSE, cancellable, &error);
1043 g_simple_async_result_set_op_res_gboolean (simple, TRUE);
1044 g_simple_async_result_complete_in_idle (simple);
1045 g_object_unref (simple);
1047 else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
1049 g_simple_async_result_set_from_error (simple, error);
1050 g_error_free (error);
1051 g_simple_async_result_complete_in_idle (simple);
1052 g_object_unref (simple);
1055 g_error_free (error);
1057 source = g_tls_connection_gnutls_create_source (gnutls, 0, cancellable);
1058 g_source_set_callback (source,
1059 (GSourceFunc) g_tls_connection_gnutls_handshake_ready,
1061 g_source_set_priority (source, io_priority);
1062 g_source_attach (source, g_main_context_get_thread_default ());
1063 g_source_unref (source);
1067 g_tls_connection_gnutls_handshake_finish (GTlsConnection *conn,
1068 GAsyncResult *result,
1071 GSimpleAsyncResult *simple;
1073 g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (conn), g_tls_connection_gnutls_handshake_async), FALSE);
1075 simple = G_SIMPLE_ASYNC_RESULT (result);
1077 if (g_simple_async_result_propagate_error (simple, error))
1080 return g_simple_async_result_get_op_res_gboolean (simple);
1084 g_tls_connection_gnutls_read (GTlsConnectionGnutls *gnutls,
1088 GCancellable *cancellable,
1094 if (handshake_in_progress_or_failed (gnutls, blocking, cancellable, error))
1097 BEGIN_GNUTLS_IO (gnutls, blocking, cancellable);
1098 ret = gnutls_record_recv (gnutls->priv->session, buffer, count);
1099 END_GNUTLS_IO (gnutls, ret, _("Error reading data from TLS socket: %s"), error);
1103 else if (ret == GNUTLS_E_REHANDSHAKE)
1110 g_tls_connection_gnutls_write (GTlsConnectionGnutls *gnutls,
1114 GCancellable *cancellable,
1120 if (handshake_in_progress_or_failed (gnutls, blocking, cancellable, error))
1123 BEGIN_GNUTLS_IO (gnutls, blocking, cancellable);
1124 ret = gnutls_record_send (gnutls->priv->session, buffer, count);
1125 END_GNUTLS_IO (gnutls, ret, _("Error writing data to TLS socket: %s"), error);
1129 else if (ret == GNUTLS_E_REHANDSHAKE)
1135 static GInputStream *
1136 g_tls_connection_gnutls_get_input_stream (GIOStream *stream)
1138 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (stream);
1140 return gnutls->priv->tls_istream;
1143 static GOutputStream *
1144 g_tls_connection_gnutls_get_output_stream (GIOStream *stream)
1146 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (stream);
1148 return gnutls->priv->tls_ostream;
1152 close_internal (GTlsConnectionGnutls *gnutls,
1154 GCancellable *cancellable,
1159 /* If we haven't finished the initial handshake yet, there's no
1160 * reason to finish it just so we can close.
1162 if (gnutls->priv->handshaking && !gnutls->priv->ever_handshaked)
1165 if (handshake_in_progress_or_failed (gnutls, blocking, cancellable, error))
1168 gnutls->priv->closing = TRUE;
1169 BEGIN_GNUTLS_IO (gnutls, blocking, cancellable);
1170 ret = gnutls_bye (gnutls->priv->session, GNUTLS_SHUT_WR);
1171 END_GNUTLS_IO (gnutls, ret, _("Error performing TLS close: %s"), error);
1172 if (ret == 0 || !error || !g_error_matches (*error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
1173 gnutls->priv->closing = FALSE;
1179 g_tls_connection_gnutls_close (GIOStream *stream,
1180 GCancellable *cancellable,
1183 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (stream);
1185 if (!close_internal (gnutls, TRUE, cancellable, error))
1187 return g_io_stream_close (gnutls->priv->base_io_stream,
1188 cancellable, error);
1192 GSimpleAsyncResult *simple;
1193 GCancellable *cancellable;
1198 close_base_stream_cb (GObject *base_stream,
1199 GAsyncResult *result,
1203 GError *error = NULL;
1204 AsyncCloseData *acd = user_data;
1206 success = g_io_stream_close_finish (G_IO_STREAM (base_stream),
1209 g_simple_async_result_set_op_res_gboolean (acd->simple, TRUE);
1212 g_simple_async_result_set_from_error (acd->simple, error);
1213 g_error_free (error);
1216 g_simple_async_result_complete (acd->simple);
1217 g_object_unref (acd->simple);
1218 if (acd->cancellable)
1219 g_object_unref (acd->cancellable);
1220 g_slice_free (AsyncCloseData, acd);
1224 g_tls_connection_gnutls_close_ready (GObject *pollable_stream,
1227 GTlsConnectionGnutls *gnutls;
1228 AsyncCloseData *acd = user_data;
1230 GError *error = NULL;
1232 gnutls = G_TLS_CONNECTION_GNUTLS (g_async_result_get_source_object (G_ASYNC_RESULT (acd->simple)));
1233 g_object_unref (gnutls);
1235 success = close_internal (gnutls, FALSE, NULL, &error);
1236 if (!success && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
1238 g_error_free (error);
1244 g_simple_async_result_set_from_error (acd->simple, error);
1245 g_simple_async_result_complete (acd->simple);
1246 g_error_free (error);
1247 g_object_unref (acd->simple);
1248 if (acd->cancellable)
1249 g_object_unref (acd->cancellable);
1250 g_slice_free (AsyncCloseData, acd);
1254 g_io_stream_close_async (gnutls->priv->base_io_stream,
1255 acd->io_priority, acd->cancellable,
1256 close_base_stream_cb, acd);
1263 g_tls_connection_gnutls_close_async (GIOStream *stream,
1265 GCancellable *cancellable,
1266 GAsyncReadyCallback callback,
1269 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (stream);
1270 GSimpleAsyncResult *simple;
1272 GError *error = NULL;
1273 AsyncCloseData *acd;
1276 simple = g_simple_async_result_new (G_OBJECT (stream), callback, user_data,
1277 g_tls_connection_gnutls_close_async);
1279 success = close_internal (gnutls, FALSE, cancellable, &error);
1280 if (error && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
1282 g_simple_async_result_set_from_error (simple, error);
1283 g_error_free (error);
1284 g_simple_async_result_complete_in_idle (simple);
1285 g_object_unref (simple);
1289 g_error_free (error);
1291 acd = g_slice_new (AsyncCloseData);
1292 acd->simple = simple;
1293 acd->cancellable = cancellable ? g_object_ref (cancellable) : cancellable;
1294 acd->io_priority = io_priority;
1298 g_io_stream_close_async (gnutls->priv->base_io_stream,
1299 io_priority, cancellable,
1300 close_base_stream_cb, acd);
1304 source = g_tls_connection_gnutls_create_source (gnutls, 0, acd->cancellable);
1305 g_source_set_callback (source,
1306 (GSourceFunc) g_tls_connection_gnutls_close_ready,
1308 g_source_set_priority (source, acd->io_priority);
1309 g_source_attach (source, g_main_context_get_thread_default ());
1310 g_source_unref (source);
1314 g_tls_connection_gnutls_close_finish (GIOStream *stream,
1315 GAsyncResult *result,
1318 GSimpleAsyncResult *simple;
1320 g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (stream), g_tls_connection_gnutls_close_async), FALSE);
1322 simple = G_SIMPLE_ASYNC_RESULT (result);
1324 if (g_simple_async_result_propagate_error (simple, error))
1327 return g_simple_async_result_get_op_res_gboolean (simple);
1333 on_pin_prompt_callback (const char *pinfile,
1335 const char *pin_description,
1336 P11KitPinFlags pin_flags,
1337 void *callback_data)
1339 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (callback_data);
1340 GTlsInteractionResult result;
1341 GTlsPasswordFlags flags = 0;
1342 GTlsPassword *password;
1343 P11KitPin *pin = NULL;
1344 GError *error = NULL;
1346 if (!gnutls->priv->interaction)
1349 if (pin_flags & P11_KIT_PIN_FLAGS_RETRY)
1350 flags |= G_TLS_PASSWORD_RETRY;
1351 if (pin_flags & P11_KIT_PIN_FLAGS_MANY_TRIES)
1352 flags |= G_TLS_PASSWORD_MANY_TRIES;
1353 if (pin_flags & P11_KIT_PIN_FLAGS_FINAL_TRY)
1354 flags |= G_TLS_PASSWORD_FINAL_TRY;
1356 password = g_pkcs11_pin_new (flags, pin_description);
1358 result = g_tls_interaction_ask_password (gnutls->priv->interaction, password,
1359 g_cancellable_get_current (), &error);
1363 case G_TLS_INTERACTION_FAILED:
1364 if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
1365 g_warning ("couldn't ask for password: %s", error->message);
1368 case G_TLS_INTERACTION_UNHANDLED:
1371 case G_TLS_INTERACTION_HANDLED:
1372 pin = g_pkcs11_pin_steal_internal (G_PKCS11_PIN (password));
1376 g_object_unref (password);
1380 #endif /* HAVE_PKCS11 */