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 ssize_t g_tls_connection_gnutls_push_func (gnutls_transport_ptr_t transport_data,
44 static ssize_t g_tls_connection_gnutls_pull_func (gnutls_transport_ptr_t transport_data,
48 static void g_tls_connection_gnutls_initable_iface_init (GInitableIface *iface);
49 static gboolean g_tls_connection_gnutls_initable_init (GInitable *initable,
50 GCancellable *cancellable,
54 static P11KitPin* on_pin_prompt_callback (const char *pinfile,
56 const char *pin_description,
57 P11KitPinFlags pin_flags,
61 static void g_tls_connection_gnutls_init_priorities (void);
63 G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GTlsConnectionGnutls, g_tls_connection_gnutls, G_TYPE_TLS_CONNECTION,
64 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
65 g_tls_connection_gnutls_initable_iface_init);
66 g_tls_connection_gnutls_init_priorities ();
74 PROP_REQUIRE_CLOSE_NOTIFY,
75 PROP_REHANDSHAKE_MODE,
76 PROP_USE_SYSTEM_CERTDB,
80 PROP_PEER_CERTIFICATE,
81 PROP_PEER_CERTIFICATE_ERRORS
84 struct _GTlsConnectionGnutlsPrivate
86 GIOStream *base_io_stream;
87 GPollableInputStream *base_istream;
88 GPollableOutputStream *base_ostream;
90 gnutls_certificate_credentials creds;
91 gnutls_session session;
93 GTlsCertificate *certificate, *peer_certificate;
94 GTlsCertificateFlags peer_certificate_errors;
95 gboolean require_close_notify;
96 GTlsRehandshakeMode rehandshake_mode;
97 gboolean is_system_certdb;
98 GTlsDatabase *database;
99 gboolean database_is_unset;
100 gboolean need_handshake, handshaking, ever_handshaked;
103 GInputStream *tls_istream;
104 GOutputStream *tls_ostream;
106 GTlsInteraction *interaction;
107 gchar *interaction_id;
110 GCancellable *cancellable;
112 #ifndef GNUTLS_E_PREMATURE_TERMINATION
115 GIOCondition internal_direction;
118 static gint unique_interaction_id = 0;
121 g_tls_connection_gnutls_init (GTlsConnectionGnutls *gnutls)
125 gnutls->priv = G_TYPE_INSTANCE_GET_PRIVATE (gnutls, G_TYPE_TLS_CONNECTION_GNUTLS, GTlsConnectionGnutlsPrivate);
127 gnutls_certificate_allocate_credentials (&gnutls->priv->creds);
128 gnutls_certificate_set_verify_flags (gnutls->priv->creds,
129 GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
131 gnutls->priv->need_handshake = TRUE;
133 gnutls->priv->database_is_unset = TRUE;
134 gnutls->priv->is_system_certdb = TRUE;
136 unique_id = g_atomic_int_add (&unique_interaction_id, 1);
137 gnutls->priv->interaction_id = g_strdup_printf ("gtls:%d", unique_id);
140 p11_kit_pin_register_callback (gnutls->priv->interaction_id,
141 on_pin_prompt_callback, gnutls, NULL);
145 static gnutls_priority_t priorities[2][2];
148 g_tls_connection_gnutls_init_priorities (void)
150 /* First field is "ssl3 only", second is "allow unsafe rehandshaking" */
152 gnutls_priority_init (&priorities[FALSE][FALSE],
155 gnutls_priority_init (&priorities[TRUE][FALSE],
156 "NORMAL:%COMPAT:!VERS-TLS1.2:!VERS-TLS1.1:!VERS-TLS1.0",
158 gnutls_priority_init (&priorities[FALSE][TRUE],
159 "NORMAL:%COMPAT:%UNSAFE_RENEGOTIATION",
161 gnutls_priority_init (&priorities[TRUE][TRUE],
162 "NORMAL:%COMPAT:!VERS-TLS1.2:!VERS-TLS1.1:!VERS-TLS1.0:%UNSAFE_RENEGOTIATION",
167 g_tls_connection_gnutls_set_handshake_priority (GTlsConnectionGnutls *gnutls)
169 gboolean use_ssl3, unsafe_rehandshake;
171 if (G_IS_TLS_CLIENT_CONNECTION (gnutls))
172 use_ssl3 = g_tls_client_connection_get_use_ssl3 (G_TLS_CLIENT_CONNECTION (gnutls));
175 unsafe_rehandshake = (gnutls->priv->rehandshake_mode == G_TLS_REHANDSHAKE_UNSAFELY);
176 gnutls_priority_set (gnutls->priv->session,
177 priorities[use_ssl3][unsafe_rehandshake]);
181 g_tls_connection_gnutls_initable_init (GInitable *initable,
182 GCancellable *cancellable,
185 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (initable);
188 g_return_val_if_fail (gnutls->priv->base_istream != NULL &&
189 gnutls->priv->base_ostream != NULL, FALSE);
191 /* Make sure gnutls->priv->session has been initialized (it may have
192 * already been initialized by a construct-time property setter).
194 g_tls_connection_gnutls_get_session (gnutls);
196 status = gnutls_credentials_set (gnutls->priv->session,
197 GNUTLS_CRD_CERTIFICATE,
198 gnutls->priv->creds);
201 g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
202 _("Could not create TLS connection: %s"),
203 gnutls_strerror (status));
207 /* Some servers (especially on embedded devices) use tiny keys that
208 * gnutls will reject by default. We want it to accept them.
210 gnutls_dh_set_prime_bits (gnutls->priv->session, 256);
212 gnutls_transport_set_push_function (gnutls->priv->session,
213 g_tls_connection_gnutls_push_func);
214 gnutls_transport_set_pull_function (gnutls->priv->session,
215 g_tls_connection_gnutls_pull_func);
216 gnutls_transport_set_ptr (gnutls->priv->session, gnutls);
218 gnutls->priv->tls_istream = g_tls_input_stream_gnutls_new (gnutls);
219 gnutls->priv->tls_ostream = g_tls_output_stream_gnutls_new (gnutls);
225 g_tls_connection_gnutls_finalize (GObject *object)
227 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (object);
229 g_clear_object (&gnutls->priv->base_io_stream);
231 g_clear_object (&gnutls->priv->tls_istream);
232 g_clear_object (&gnutls->priv->tls_ostream);
234 if (gnutls->priv->session)
235 gnutls_deinit (gnutls->priv->session);
236 if (gnutls->priv->creds)
237 gnutls_certificate_free_credentials (gnutls->priv->creds);
239 g_clear_object (&gnutls->priv->database);
240 g_clear_object (&gnutls->priv->certificate);
241 g_clear_object (&gnutls->priv->peer_certificate);
244 p11_kit_pin_unregister_callback (gnutls->priv->interaction_id,
245 on_pin_prompt_callback, gnutls);
247 g_free (gnutls->priv->interaction_id);
248 g_clear_object (&gnutls->priv->interaction);
250 g_clear_error (&gnutls->priv->error);
252 G_OBJECT_CLASS (g_tls_connection_gnutls_parent_class)->finalize (object);
256 g_tls_connection_gnutls_get_property (GObject *object,
261 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (object);
262 GTlsBackend *backend;
266 case PROP_BASE_IO_STREAM:
267 g_value_set_object (value, gnutls->priv->base_io_stream);
270 case PROP_REQUIRE_CLOSE_NOTIFY:
271 g_value_set_boolean (value, gnutls->priv->require_close_notify);
274 case PROP_REHANDSHAKE_MODE:
275 g_value_set_enum (value, gnutls->priv->rehandshake_mode);
278 case PROP_USE_SYSTEM_CERTDB:
279 g_value_set_boolean (value, gnutls->priv->is_system_certdb);
283 if (gnutls->priv->database_is_unset)
285 backend = g_tls_backend_get_default ();
286 gnutls->priv->database = g_tls_backend_get_default_database (backend);
287 gnutls->priv->database_is_unset = FALSE;
289 g_value_set_object (value, gnutls->priv->database);
292 case PROP_CERTIFICATE:
293 g_value_set_object (value, gnutls->priv->certificate);
296 case PROP_INTERACTION:
297 g_value_set_object (value, gnutls->priv->interaction);
300 case PROP_PEER_CERTIFICATE:
301 g_value_set_object (value, gnutls->priv->peer_certificate);
304 case PROP_PEER_CERTIFICATE_ERRORS:
305 g_value_set_flags (value, gnutls->priv->peer_certificate_errors);
309 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
314 g_tls_connection_gnutls_set_property (GObject *object,
319 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (object);
320 GInputStream *istream;
321 GOutputStream *ostream;
322 gboolean system_certdb;
323 GTlsBackend *backend;
327 case PROP_BASE_IO_STREAM:
328 if (gnutls->priv->base_io_stream)
330 g_object_unref (gnutls->priv->base_io_stream);
331 gnutls->priv->base_istream = NULL;
332 gnutls->priv->base_ostream = NULL;
334 gnutls->priv->base_io_stream = g_value_dup_object (value);
335 if (!gnutls->priv->base_io_stream)
338 istream = g_io_stream_get_input_stream (gnutls->priv->base_io_stream);
339 ostream = g_io_stream_get_output_stream (gnutls->priv->base_io_stream);
341 if (G_IS_POLLABLE_INPUT_STREAM (istream) &&
342 g_pollable_input_stream_can_poll (G_POLLABLE_INPUT_STREAM (istream)))
343 gnutls->priv->base_istream = G_POLLABLE_INPUT_STREAM (istream);
344 if (G_IS_POLLABLE_OUTPUT_STREAM (ostream) &&
345 g_pollable_output_stream_can_poll (G_POLLABLE_OUTPUT_STREAM (ostream)))
346 gnutls->priv->base_ostream = G_POLLABLE_OUTPUT_STREAM (ostream);
349 case PROP_REQUIRE_CLOSE_NOTIFY:
350 gnutls->priv->require_close_notify = g_value_get_boolean (value);
353 case PROP_REHANDSHAKE_MODE:
354 gnutls->priv->rehandshake_mode = g_value_get_enum (value);
357 case PROP_USE_SYSTEM_CERTDB:
358 system_certdb = g_value_get_boolean (value);
359 if (system_certdb != gnutls->priv->is_system_certdb)
361 g_clear_object (&gnutls->priv->database);
364 backend = g_tls_backend_get_default ();
365 gnutls->priv->database = g_tls_backend_get_default_database (backend);
367 gnutls->priv->is_system_certdb = system_certdb;
368 gnutls->priv->database_is_unset = FALSE;
373 g_clear_object (&gnutls->priv->database);
374 gnutls->priv->database = g_value_dup_object (value);
375 gnutls->priv->is_system_certdb = FALSE;
376 gnutls->priv->database_is_unset = FALSE;
379 case PROP_CERTIFICATE:
380 if (gnutls->priv->certificate)
381 g_object_unref (gnutls->priv->certificate);
382 gnutls->priv->certificate = g_value_dup_object (value);
385 case PROP_INTERACTION:
386 g_clear_object (&gnutls->priv->interaction);
387 gnutls->priv->interaction = g_value_dup_object (value);
391 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
395 gnutls_certificate_credentials
396 g_tls_connection_gnutls_get_credentials (GTlsConnectionGnutls *gnutls)
398 return gnutls->priv->creds;
402 g_tls_connection_gnutls_get_session (GTlsConnectionGnutls *gnutls)
404 /* Ideally we would initialize gnutls->priv->session from
405 * g_tls_connection_gnutls_init(), but we can't tell if it's a
406 * client or server connection at that point... And
407 * g_tls_connection_gnutls_initiable_init() is too late, because
408 * construct-time property setters may need to modify it.
410 if (!gnutls->priv->session)
412 gboolean client = G_IS_TLS_CLIENT_CONNECTION (gnutls);
413 gnutls_init (&gnutls->priv->session, client ? GNUTLS_CLIENT : GNUTLS_SERVER);
416 return gnutls->priv->session;
420 g_tls_connection_gnutls_get_certificate (GTlsConnectionGnutls *gnutls,
423 GTlsCertificate *cert;
425 cert = g_tls_connection_get_certificate (G_TLS_CONNECTION (gnutls));
427 st->cert_type = GNUTLS_CRT_X509;
431 g_tls_certificate_gnutls_copy (G_TLS_CERTIFICATE_GNUTLS (cert),
432 gnutls->priv->interaction_id, st);
436 begin_gnutls_io (GTlsConnectionGnutls *gnutls,
438 GCancellable *cancellable)
440 gnutls->priv->blocking = blocking;
441 gnutls->priv->cancellable = cancellable;
442 gnutls->priv->internal_direction = 0;
444 g_cancellable_push_current (cancellable);
445 g_clear_error (&gnutls->priv->error);
449 end_gnutls_io (GTlsConnectionGnutls *gnutls,
453 if (gnutls->priv->cancellable)
454 g_cancellable_pop_current (gnutls->priv->cancellable);
455 gnutls->priv->cancellable = NULL;
459 g_clear_error (&gnutls->priv->error);
463 if (gnutls->priv->handshaking && !gnutls->priv->ever_handshaked)
465 if (g_error_matches (gnutls->priv->error, G_IO_ERROR, G_IO_ERROR_FAILED) ||
466 status == GNUTLS_E_UNEXPECTED_PACKET_LENGTH ||
467 status == GNUTLS_E_FATAL_ALERT_RECEIVED ||
468 status == GNUTLS_E_DECRYPTION_FAILED ||
469 status == GNUTLS_E_UNSUPPORTED_VERSION_PACKET)
471 g_clear_error (&gnutls->priv->error);
472 g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_NOT_TLS,
473 _("Peer failed to perform TLS handshake"));
474 return GNUTLS_E_PULL_ERROR;
478 if (gnutls->priv->error)
480 if (g_error_matches (gnutls->priv->error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
481 status = GNUTLS_E_AGAIN;
483 G_TLS_CONNECTION_GNUTLS_GET_CLASS (gnutls)->failed (gnutls);
484 g_propagate_error (error, gnutls->priv->error);
485 gnutls->priv->error = NULL;
488 else if (status == GNUTLS_E_REHANDSHAKE)
490 if (gnutls->priv->rehandshake_mode == G_TLS_REHANDSHAKE_NEVER)
492 g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
493 _("Peer requested illegal TLS rehandshake"));
494 return GNUTLS_E_PULL_ERROR;
497 gnutls->priv->need_handshake = TRUE;
501 #ifdef GNUTLS_E_PREMATURE_TERMINATION
502 status == GNUTLS_E_PREMATURE_TERMINATION
504 status == GNUTLS_E_UNEXPECTED_PACKET_LENGTH && 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"));
512 G_TLS_CONNECTION_GNUTLS_GET_CLASS (gnutls)->failed (gnutls);
522 #define BEGIN_GNUTLS_IO(gnutls, blocking, cancellable) \
523 begin_gnutls_io (gnutls, blocking, cancellable); \
526 #define END_GNUTLS_IO(gnutls, ret, errmsg, error) \
527 } while ((ret == GNUTLS_E_AGAIN || \
528 ret == GNUTLS_E_WARNING_ALERT_RECEIVED) && \
529 !gnutls->priv->error); \
530 ret = end_gnutls_io (gnutls, ret, error); \
531 if (ret < 0 && ret != GNUTLS_E_REHANDSHAKE && error && !*error) \
533 g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,\
534 errmsg, gnutls_strerror (ret)); \
539 g_tls_connection_gnutls_check (GTlsConnectionGnutls *gnutls,
540 GIOCondition condition)
542 if (!gnutls->priv->internal_direction)
545 if (gnutls->priv->handshaking || gnutls->priv->closing)
546 condition = gnutls->priv->internal_direction;
548 if (condition & G_IO_IN)
549 return g_pollable_input_stream_is_readable (gnutls->priv->base_istream);
551 return g_pollable_output_stream_is_writable (gnutls->priv->base_ostream);
557 GTlsConnectionGnutls *gnutls;
560 GSource *child_source;
561 GIOCondition current_direction;
562 } GTlsConnectionGnutlsSource;
565 gnutls_source_prepare (GSource *source,
573 gnutls_source_check (GSource *source)
579 gnutls_source_sync_child_source (GTlsConnectionGnutlsSource *gnutls_source)
581 GTlsConnectionGnutls *gnutls = gnutls_source->gnutls;
582 GSource *source = (GSource *)gnutls_source;
583 GIOCondition direction;
585 if (gnutls->priv->handshaking || gnutls->priv->closing)
586 direction = gnutls->priv->internal_direction;
587 else if (!gnutls_source->stream)
589 else if (G_IS_TLS_INPUT_STREAM_GNUTLS (gnutls_source->stream))
592 direction = G_IO_OUT;
594 if (direction == gnutls_source->current_direction)
597 if (gnutls_source->child_source)
599 g_source_remove_child_source (source, gnutls_source->child_source);
600 g_source_unref (gnutls_source->child_source);
603 if (direction & G_IO_IN)
604 gnutls_source->child_source = g_pollable_input_stream_create_source (gnutls->priv->base_istream, NULL);
606 gnutls_source->child_source = g_pollable_output_stream_create_source (gnutls->priv->base_ostream, NULL);
608 g_source_set_dummy_callback (gnutls_source->child_source);
609 g_source_add_child_source (source, gnutls_source->child_source);
610 gnutls_source->current_direction = direction;
615 gnutls_source_dispatch (GSource *source,
616 GSourceFunc callback,
619 GPollableSourceFunc func = (GPollableSourceFunc)callback;
620 GTlsConnectionGnutlsSource *gnutls_source = (GTlsConnectionGnutlsSource *)source;
623 ret = (*func) (gnutls_source->stream, user_data);
625 ret = gnutls_source_sync_child_source (gnutls_source);
631 gnutls_source_finalize (GSource *source)
633 GTlsConnectionGnutlsSource *gnutls_source = (GTlsConnectionGnutlsSource *)source;
635 g_object_unref (gnutls_source->gnutls);
637 if (gnutls_source->child_source)
638 g_source_unref (gnutls_source->child_source);
642 g_tls_connection_gnutls_source_closure_callback (GObject *stream,
645 GClosure *closure = data;
647 GValue param = { 0, };
648 GValue result_value = { 0, };
651 g_value_init (&result_value, G_TYPE_BOOLEAN);
653 g_value_init (¶m, G_TYPE_OBJECT);
654 g_value_set_object (¶m, stream);
656 g_closure_invoke (closure, &result_value, 1, ¶m, NULL);
658 result = g_value_get_boolean (&result_value);
659 g_value_unset (&result_value);
660 g_value_unset (¶m);
665 static GSourceFuncs gnutls_source_funcs =
667 gnutls_source_prepare,
669 gnutls_source_dispatch,
670 gnutls_source_finalize,
671 (GSourceFunc)g_tls_connection_gnutls_source_closure_callback,
672 (GSourceDummyMarshal)g_cclosure_marshal_generic
676 g_tls_connection_gnutls_create_source (GTlsConnectionGnutls *gnutls,
677 GIOCondition condition,
678 GCancellable *cancellable)
680 GSource *source, *cancellable_source;
681 GTlsConnectionGnutlsSource *gnutls_source;
683 source = g_source_new (&gnutls_source_funcs, sizeof (GTlsConnectionGnutlsSource));
684 g_source_set_name (source, "GTlsConnectionGnutlsSource");
685 gnutls_source = (GTlsConnectionGnutlsSource *)source;
686 gnutls_source->gnutls = g_object_ref (gnutls);
687 if (condition & G_IO_IN)
688 gnutls_source->stream = G_OBJECT (gnutls->priv->tls_istream);
689 else if (condition & G_IO_OUT)
690 gnutls_source->stream = G_OBJECT (gnutls->priv->tls_ostream);
691 gnutls_source_sync_child_source (gnutls_source);
695 cancellable_source = g_cancellable_source_new (cancellable);
696 g_source_set_dummy_callback (cancellable_source);
697 g_source_add_child_source (source, cancellable_source);
698 g_source_unref (cancellable_source);
705 set_gnutls_error (GTlsConnectionGnutls *gnutls, GIOCondition direction)
707 if (g_error_matches (gnutls->priv->error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
708 gnutls_transport_set_errno (gnutls->priv->session, EINTR);
709 else if (g_error_matches (gnutls->priv->error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
711 gnutls_transport_set_errno (gnutls->priv->session, EAGAIN);
712 gnutls->priv->internal_direction = direction;
715 gnutls_transport_set_errno (gnutls->priv->session, EIO);
719 g_tls_connection_gnutls_pull_func (gnutls_transport_ptr_t transport_data,
723 GTlsConnectionGnutls *gnutls = transport_data;
726 /* If gnutls->priv->error is non-%NULL when we're called, it means
727 * that an error previously occurred, but gnutls decided not to
728 * propagate it. So it's correct for us to just clear it. (Usually
729 * this means it ignored an EAGAIN after a short read, and now
730 * we'll return EAGAIN again, which it will obey this time.)
732 g_clear_error (&gnutls->priv->error);
734 ret = g_pollable_stream_read (G_INPUT_STREAM (gnutls->priv->base_istream),
735 buf, buflen, gnutls->priv->blocking,
736 gnutls->priv->cancellable,
737 &gnutls->priv->error);
740 set_gnutls_error (gnutls, G_IO_IN);
741 #ifndef GNUTLS_E_PREMATURE_TERMINATION
743 gnutls->priv->eof = TRUE;
750 g_tls_connection_gnutls_push_func (gnutls_transport_ptr_t transport_data,
754 GTlsConnectionGnutls *gnutls = transport_data;
757 /* See comment in pull_func. */
758 g_clear_error (&gnutls->priv->error);
760 ret = g_pollable_stream_write (G_OUTPUT_STREAM (gnutls->priv->base_ostream),
761 buf, buflen, gnutls->priv->blocking,
762 gnutls->priv->cancellable,
763 &gnutls->priv->error);
765 set_gnutls_error (gnutls, G_IO_OUT);
771 handshake_internal (GTlsConnectionGnutls *gnutls,
773 GCancellable *cancellable,
776 GTlsCertificate *peer_certificate = NULL;
777 GTlsCertificateFlags peer_certificate_errors = 0;
780 if (G_IS_TLS_SERVER_CONNECTION_GNUTLS (gnutls) &&
781 gnutls->priv->ever_handshaked && !gnutls->priv->handshaking &&
782 !gnutls->priv->need_handshake)
784 BEGIN_GNUTLS_IO (gnutls, blocking, cancellable);
785 ret = gnutls_rehandshake (gnutls->priv->session);
786 END_GNUTLS_IO (gnutls, ret, _("Error performing TLS handshake: %s"), error);
792 if (!gnutls->priv->handshaking)
794 gnutls->priv->handshaking = TRUE;
796 if (gnutls->priv->peer_certificate)
798 g_clear_object (&gnutls->priv->peer_certificate);
799 gnutls->priv->peer_certificate_errors = 0;
801 g_object_notify (G_OBJECT (gnutls), "peer-certificate");
802 g_object_notify (G_OBJECT (gnutls), "peer-certificate-errors");
805 g_tls_connection_gnutls_set_handshake_priority (gnutls);
806 G_TLS_CONNECTION_GNUTLS_GET_CLASS (gnutls)->begin_handshake (gnutls);
809 BEGIN_GNUTLS_IO (gnutls, blocking, cancellable);
810 ret = gnutls_handshake (gnutls->priv->session);
811 END_GNUTLS_IO (gnutls, ret, _("Error performing TLS handshake: %s"), error);
813 if (ret == GNUTLS_E_AGAIN)
816 gnutls->priv->handshaking = FALSE;
817 gnutls->priv->need_handshake = FALSE;
818 gnutls->priv->ever_handshaked = TRUE;
821 gnutls_certificate_type_get (gnutls->priv->session) == GNUTLS_CRT_X509)
823 GTlsCertificate *chain, *cert;
824 const gnutls_datum_t *certs;
825 unsigned int num_certs;
828 certs = gnutls_certificate_get_peers (gnutls->priv->session, &num_certs);
832 for (i = num_certs - 1; i >= 0; i--)
834 cert = g_tls_certificate_gnutls_new (&certs[i], chain);
836 g_object_unref (chain);
841 peer_certificate = chain;
844 if (peer_certificate)
848 accepted = G_TLS_CONNECTION_GNUTLS_GET_CLASS (gnutls)->verify_peer (gnutls, peer_certificate, &peer_certificate_errors);
850 gnutls->priv->peer_certificate = peer_certificate;
851 gnutls->priv->peer_certificate_errors = peer_certificate_errors;
853 g_object_notify (G_OBJECT (gnutls), "peer-certificate");
854 g_object_notify (G_OBJECT (gnutls), "peer-certificate-errors");
858 g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
859 _("Unacceptable TLS certificate"));
864 G_TLS_CONNECTION_GNUTLS_GET_CLASS (gnutls)->finish_handshake (gnutls, ret == 0, error);
869 handshake_in_progress_or_failed (GTlsConnectionGnutls *gnutls,
871 GCancellable *cancellable,
874 if (!(gnutls->priv->need_handshake || gnutls->priv->handshaking))
877 return !handshake_internal (gnutls, blocking, cancellable, error);
881 g_tls_connection_gnutls_handshake (GTlsConnection *conn,
882 GCancellable *cancellable,
885 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (conn);
887 return handshake_internal (gnutls, TRUE, cancellable, error);
891 g_tls_connection_gnutls_handshake_ready (GObject *pollable_stream,
894 GTlsConnectionGnutls *gnutls;
895 GSimpleAsyncResult *simple = user_data;
897 GError *error = NULL;
899 gnutls = G_TLS_CONNECTION_GNUTLS (g_async_result_get_source_object (G_ASYNC_RESULT (simple)));
900 g_object_unref (gnutls);
902 success = handshake_internal (gnutls, FALSE, NULL, &error);
903 if (!success && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
905 g_error_free (error);
911 g_simple_async_result_set_from_error (simple, error);
912 g_error_free (error);
915 g_simple_async_result_set_op_res_gboolean (simple, success);
916 g_simple_async_result_complete (simple);
917 g_object_unref (simple);
923 g_tls_connection_gnutls_handshake_async (GTlsConnection *conn,
925 GCancellable *cancellable,
926 GAsyncReadyCallback callback,
929 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (conn);
930 GSimpleAsyncResult *simple;
932 GError *error = NULL;
935 simple = g_simple_async_result_new (G_OBJECT (conn), callback, user_data,
936 g_tls_connection_gnutls_handshake_async);
937 success = handshake_internal (gnutls, FALSE, cancellable, &error);
940 g_simple_async_result_set_op_res_gboolean (simple, TRUE);
941 g_simple_async_result_complete_in_idle (simple);
942 g_object_unref (simple);
945 else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
947 g_simple_async_result_set_from_error (simple, error);
948 g_error_free (error);
949 g_simple_async_result_complete_in_idle (simple);
950 g_object_unref (simple);
954 g_error_free (error);
956 source = g_tls_connection_gnutls_create_source (gnutls, 0, cancellable);
957 g_source_set_callback (source,
958 (GSourceFunc) g_tls_connection_gnutls_handshake_ready,
960 g_source_set_priority (source, io_priority);
961 g_source_attach (source, g_main_context_get_thread_default ());
962 g_source_unref (source);
966 g_tls_connection_gnutls_handshake_finish (GTlsConnection *conn,
967 GAsyncResult *result,
970 GSimpleAsyncResult *simple;
972 g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (conn), g_tls_connection_gnutls_handshake_async), FALSE);
974 simple = G_SIMPLE_ASYNC_RESULT (result);
976 if (g_simple_async_result_propagate_error (simple, error))
979 return g_simple_async_result_get_op_res_gboolean (simple);
983 g_tls_connection_gnutls_read (GTlsConnectionGnutls *gnutls,
987 GCancellable *cancellable,
993 if (handshake_in_progress_or_failed (gnutls, blocking, cancellable, error))
996 BEGIN_GNUTLS_IO (gnutls, blocking, cancellable);
997 ret = gnutls_record_recv (gnutls->priv->session, buffer, count);
998 END_GNUTLS_IO (gnutls, ret, _("Error reading data from TLS socket: %s"), error);
1002 else if (ret == GNUTLS_E_REHANDSHAKE)
1009 g_tls_connection_gnutls_write (GTlsConnectionGnutls *gnutls,
1013 GCancellable *cancellable,
1019 if (handshake_in_progress_or_failed (gnutls, blocking, cancellable, error))
1022 BEGIN_GNUTLS_IO (gnutls, blocking, cancellable);
1023 ret = gnutls_record_send (gnutls->priv->session, buffer, count);
1024 END_GNUTLS_IO (gnutls, ret, _("Error writing data to TLS socket: %s"), error);
1028 else if (ret == GNUTLS_E_REHANDSHAKE)
1034 static GInputStream *
1035 g_tls_connection_gnutls_get_input_stream (GIOStream *stream)
1037 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (stream);
1039 return gnutls->priv->tls_istream;
1042 static GOutputStream *
1043 g_tls_connection_gnutls_get_output_stream (GIOStream *stream)
1045 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (stream);
1047 return gnutls->priv->tls_ostream;
1051 close_internal (GTlsConnectionGnutls *gnutls,
1053 GCancellable *cancellable,
1058 /* If we haven't finished the initial handshake yet, there's no
1059 * reason to finish it just so we can close.
1061 if (!gnutls->priv->ever_handshaked)
1064 if (handshake_in_progress_or_failed (gnutls, blocking, cancellable, error))
1067 gnutls->priv->closing = TRUE;
1068 BEGIN_GNUTLS_IO (gnutls, blocking, cancellable);
1069 ret = gnutls_bye (gnutls->priv->session, GNUTLS_SHUT_WR);
1070 END_GNUTLS_IO (gnutls, ret, _("Error performing TLS close: %s"), error);
1071 if (ret == 0 || !error || !g_error_matches (*error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
1072 gnutls->priv->closing = FALSE;
1078 g_tls_connection_gnutls_close (GIOStream *stream,
1079 GCancellable *cancellable,
1082 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (stream);
1084 if (!close_internal (gnutls, TRUE, cancellable, error))
1086 return g_io_stream_close (gnutls->priv->base_io_stream,
1087 cancellable, error);
1091 GSimpleAsyncResult *simple;
1092 GCancellable *cancellable;
1097 close_base_stream_cb (GObject *base_stream,
1098 GAsyncResult *result,
1102 GError *error = NULL;
1103 AsyncCloseData *acd = user_data;
1105 success = g_io_stream_close_finish (G_IO_STREAM (base_stream),
1108 g_simple_async_result_set_op_res_gboolean (acd->simple, TRUE);
1111 g_simple_async_result_set_from_error (acd->simple, error);
1112 g_error_free (error);
1115 g_simple_async_result_complete (acd->simple);
1116 g_object_unref (acd->simple);
1117 if (acd->cancellable)
1118 g_object_unref (acd->cancellable);
1119 g_slice_free (AsyncCloseData, acd);
1123 g_tls_connection_gnutls_close_ready (GObject *pollable_stream,
1126 GTlsConnectionGnutls *gnutls;
1127 AsyncCloseData *acd = user_data;
1129 GError *error = NULL;
1131 gnutls = G_TLS_CONNECTION_GNUTLS (g_async_result_get_source_object (G_ASYNC_RESULT (acd->simple)));
1132 g_object_unref (gnutls);
1134 success = close_internal (gnutls, FALSE, NULL, &error);
1135 if (!success && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
1137 g_error_free (error);
1143 g_simple_async_result_set_from_error (acd->simple, error);
1144 g_simple_async_result_complete (acd->simple);
1145 g_error_free (error);
1146 g_object_unref (acd->simple);
1147 if (acd->cancellable)
1148 g_object_unref (acd->cancellable);
1149 g_slice_free (AsyncCloseData, acd);
1153 g_io_stream_close_async (gnutls->priv->base_io_stream,
1154 acd->io_priority, acd->cancellable,
1155 close_base_stream_cb, acd);
1162 g_tls_connection_gnutls_close_async (GIOStream *stream,
1164 GCancellable *cancellable,
1165 GAsyncReadyCallback callback,
1168 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (stream);
1169 GSimpleAsyncResult *simple;
1171 GError *error = NULL;
1172 AsyncCloseData *acd;
1175 simple = g_simple_async_result_new (G_OBJECT (stream), callback, user_data,
1176 g_tls_connection_gnutls_close_async);
1178 success = close_internal (gnutls, FALSE, cancellable, &error);
1179 if (error && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
1181 g_simple_async_result_set_from_error (simple, error);
1182 g_error_free (error);
1183 g_simple_async_result_complete_in_idle (simple);
1184 g_object_unref (simple);
1188 g_error_free (error);
1190 acd = g_slice_new (AsyncCloseData);
1191 acd->simple = simple;
1192 acd->cancellable = cancellable ? g_object_ref (cancellable) : cancellable;
1193 acd->io_priority = io_priority;
1197 g_io_stream_close_async (gnutls->priv->base_io_stream,
1198 io_priority, cancellable,
1199 close_base_stream_cb, acd);
1203 source = g_tls_connection_gnutls_create_source (gnutls, 0, acd->cancellable);
1204 g_source_set_callback (source,
1205 (GSourceFunc) g_tls_connection_gnutls_close_ready,
1207 g_source_set_priority (source, acd->io_priority);
1208 g_source_attach (source, g_main_context_get_thread_default ());
1209 g_source_unref (source);
1213 g_tls_connection_gnutls_close_finish (GIOStream *stream,
1214 GAsyncResult *result,
1217 GSimpleAsyncResult *simple;
1219 g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (stream), g_tls_connection_gnutls_close_async), FALSE);
1221 simple = G_SIMPLE_ASYNC_RESULT (result);
1223 if (g_simple_async_result_propagate_error (simple, error))
1226 return g_simple_async_result_get_op_res_gboolean (simple);
1232 on_pin_prompt_callback (const char *pinfile,
1234 const char *pin_description,
1235 P11KitPinFlags pin_flags,
1236 void *callback_data)
1238 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (callback_data);
1239 GTlsInteractionResult result;
1240 GTlsPasswordFlags flags = 0;
1241 GTlsPassword *password;
1242 P11KitPin *pin = NULL;
1243 GError *error = NULL;
1245 if (!gnutls->priv->interaction)
1248 if (pin_flags & P11_KIT_PIN_FLAGS_RETRY)
1249 flags |= G_TLS_PASSWORD_RETRY;
1250 if (pin_flags & P11_KIT_PIN_FLAGS_MANY_TRIES)
1251 flags |= G_TLS_PASSWORD_MANY_TRIES;
1252 if (pin_flags & P11_KIT_PIN_FLAGS_FINAL_TRY)
1253 flags |= G_TLS_PASSWORD_FINAL_TRY;
1255 password = g_pkcs11_pin_new (flags, pin_description);
1257 result = g_tls_interaction_ask_password (gnutls->priv->interaction, password,
1258 g_cancellable_get_current (), &error);
1262 case G_TLS_INTERACTION_FAILED:
1263 if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
1264 g_warning ("couldn't ask for password: %s", error->message);
1267 case G_TLS_INTERACTION_UNHANDLED:
1270 case G_TLS_INTERACTION_HANDLED:
1271 pin = g_pkcs11_pin_steal_internal (G_PKCS11_PIN (password));
1275 g_object_unref (password);
1279 #endif /* HAVE_PKCS11 */
1282 g_tls_connection_gnutls_class_init (GTlsConnectionGnutlsClass *klass)
1284 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
1285 GTlsConnectionClass *connection_class = G_TLS_CONNECTION_CLASS (klass);
1286 GIOStreamClass *iostream_class = G_IO_STREAM_CLASS (klass);
1288 g_type_class_add_private (klass, sizeof (GTlsConnectionGnutlsPrivate));
1290 gobject_class->get_property = g_tls_connection_gnutls_get_property;
1291 gobject_class->set_property = g_tls_connection_gnutls_set_property;
1292 gobject_class->finalize = g_tls_connection_gnutls_finalize;
1294 connection_class->handshake = g_tls_connection_gnutls_handshake;
1295 connection_class->handshake_async = g_tls_connection_gnutls_handshake_async;
1296 connection_class->handshake_finish = g_tls_connection_gnutls_handshake_finish;
1298 iostream_class->get_input_stream = g_tls_connection_gnutls_get_input_stream;
1299 iostream_class->get_output_stream = g_tls_connection_gnutls_get_output_stream;
1300 iostream_class->close_fn = g_tls_connection_gnutls_close;
1301 iostream_class->close_async = g_tls_connection_gnutls_close_async;
1302 iostream_class->close_finish = g_tls_connection_gnutls_close_finish;
1304 g_object_class_override_property (gobject_class, PROP_BASE_IO_STREAM, "base-io-stream");
1305 g_object_class_override_property (gobject_class, PROP_REQUIRE_CLOSE_NOTIFY, "require-close-notify");
1306 g_object_class_override_property (gobject_class, PROP_REHANDSHAKE_MODE, "rehandshake-mode");
1307 g_object_class_override_property (gobject_class, PROP_USE_SYSTEM_CERTDB, "use-system-certdb");
1308 g_object_class_override_property (gobject_class, PROP_DATABASE, "database");
1309 g_object_class_override_property (gobject_class, PROP_CERTIFICATE, "certificate");
1310 g_object_class_override_property (gobject_class, PROP_INTERACTION, "interaction");
1311 g_object_class_override_property (gobject_class, PROP_PEER_CERTIFICATE, "peer-certificate");
1312 g_object_class_override_property (gobject_class, PROP_PEER_CERTIFICATE_ERRORS, "peer-certificate-errors");
1316 g_tls_connection_gnutls_initable_iface_init (GInitableIface *iface)
1318 iface->init = g_tls_connection_gnutls_initable_init;