1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
3 * GIO - GLib Input, Output and Streaming Library
5 * Copyright 2009 Red Hat, Inc
6 * Copyright 2015, 2016 Collabora, Ltd.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General
19 * Public License along with this library; if not, see
20 * <http://www.gnu.org/licenses/>.
22 * In addition, when the library is used with OpenSSL, a special
23 * exception applies. Refer to the LICENSE_EXCEPTION file for details.
31 #include <gnutls/dtls.h>
32 #include <gnutls/gnutls.h>
33 #include <gnutls/x509.h>
35 #include "gtlsconnection-gnutls.h"
36 #include "gtlsbackend-gnutls.h"
37 #include "gtlscertificate-gnutls.h"
38 #include "gtlsclientconnection-gnutls.h"
39 #include "gtlsdatabase-gnutls.h"
41 #include "gtlsgnutls-version.h"
47 /* It isn’t clear whether MinGW always defines EMSGSIZE. */
49 #define EMSGSIZE WSAEMSGSIZE
53 #include <glib/gi18n-lib.h>
54 #include <glib/gprintf.h>
56 static ssize_t g_tls_connection_gnutls_push_func (gnutls_transport_ptr_t transport_data,
59 static ssize_t g_tls_connection_gnutls_vec_push_func (gnutls_transport_ptr_t transport_data,
62 static ssize_t g_tls_connection_gnutls_pull_func (gnutls_transport_ptr_t transport_data,
66 static int g_tls_connection_gnutls_pull_timeout_func (gnutls_transport_ptr_t transport_data,
69 static void g_tls_connection_gnutls_initable_iface_init (GInitableIface *iface);
71 static int verify_certificate_cb (gnutls_session_t session);
73 static gnutls_priority_t priority;
77 gnutls_certificate_credentials_t creds;
78 gnutls_session_t session;
79 gchar *interaction_id;
80 GCancellable *cancellable;
81 } GTlsConnectionGnutlsPrivate;
83 G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GTlsConnectionGnutls, g_tls_connection_gnutls, G_TYPE_TLS_CONNECTION_BASE,
84 G_ADD_PRIVATE (GTlsConnectionGnutls);
85 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
86 g_tls_connection_gnutls_initable_iface_init);
89 static gint unique_interaction_id = 0;
92 g_tls_connection_gnutls_init (GTlsConnectionGnutls *gnutls)
94 GTlsConnectionGnutlsPrivate *priv = g_tls_connection_gnutls_get_instance_private (gnutls);
97 unique_id = g_atomic_int_add (&unique_interaction_id, 1);
98 priv->interaction_id = g_strdup_printf ("gtls:%d", unique_id);
100 priv->cancellable = g_cancellable_new ();
104 g_tls_connection_gnutls_set_handshake_priority (GTlsConnectionGnutls *gnutls)
106 GTlsConnectionGnutlsPrivate *priv = g_tls_connection_gnutls_get_instance_private (gnutls);
111 /* initialize_gnutls_priority() previously failed and printed a warning,
112 * so no need for further warnings here.
117 ret = gnutls_priority_set (priv->session, priority);
118 if (ret != GNUTLS_E_SUCCESS)
119 g_warning ("Failed to set GnuTLS session priority: %s", gnutls_strerror (ret));
123 update_credentials_cb (GObject *gobject,
127 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (gobject);
128 GTlsConnectionGnutlsPrivate *priv = g_tls_connection_gnutls_get_instance_private (gnutls);
129 GTlsConnectionGnutlsClass *connection_class = G_TLS_CONNECTION_GNUTLS_GET_CLASS (gnutls);
130 gnutls_certificate_credentials_t credentials;
131 GTlsDatabase *database;
132 GError *error = NULL;
135 database = g_tls_connection_get_database (G_TLS_CONNECTION (gnutls));
136 if (database && G_IS_TLS_DATABASE_GNUTLS (database))
138 credentials = g_tls_database_gnutls_get_credentials (G_TLS_DATABASE_GNUTLS (database), &error);
141 g_warning ("Failed to update credentials: %s", error->message);
142 g_error_free (error);
148 ret = gnutls_certificate_allocate_credentials (&credentials);
151 g_warning ("Failed to update credentials: %s", gnutls_strerror (ret));
156 ret = gnutls_credentials_set (priv->session, GNUTLS_CRD_CERTIFICATE, credentials);
159 g_warning ("Failed to update credentials: %s", gnutls_strerror (ret));
160 gnutls_certificate_free_credentials (credentials);
164 gnutls_certificate_free_credentials (priv->creds);
165 priv->creds = credentials;
167 g_assert (connection_class->update_credentials);
168 connection_class->update_credentials (gnutls, credentials);
172 g_tls_connection_gnutls_initable_init (GInitable *initable,
173 GCancellable *cancellable,
176 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (initable);
177 GTlsConnectionGnutlsPrivate *priv = g_tls_connection_gnutls_get_instance_private (gnutls);
178 GTlsDatabase *database;
179 GIOStream *base_io_stream = NULL;
180 GDatagramBased *base_socket = NULL;
181 gboolean client = G_IS_TLS_CLIENT_CONNECTION (gnutls);
182 guint flags = client ? GNUTLS_CLIENT : GNUTLS_SERVER;
183 GError *my_error = NULL;
184 gboolean success = FALSE;
187 g_object_get (gnutls,
188 "base-io-stream", &base_io_stream,
189 "base-socket", &base_socket,
192 /* Ensure we are in TLS mode or DTLS mode. */
193 g_return_val_if_fail (!!base_io_stream != !!base_socket, FALSE);
196 flags |= GNUTLS_DATAGRAM;
198 database = g_tls_connection_get_database (G_TLS_CONNECTION (gnutls));
199 if (database && G_IS_TLS_DATABASE_GNUTLS (database))
201 priv->creds = g_tls_database_gnutls_get_credentials (G_TLS_DATABASE_GNUTLS (database), &my_error);
204 g_propagate_prefixed_error (error, my_error, _("Could not create TLS connection:"));
210 ret = gnutls_certificate_allocate_credentials (&priv->creds);
213 g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
214 _("Could not create TLS connection: %s"),
215 gnutls_strerror (ret));
220 g_signal_connect (gnutls, "notify::database", G_CALLBACK (update_credentials_cb), NULL);
221 g_signal_connect (gnutls, "notify::use-system-certdb", G_CALLBACK (update_credentials_cb), NULL);
223 gnutls_init (&priv->session, flags);
225 gnutls_session_set_ptr (priv->session, gnutls);
226 gnutls_session_set_verify_function (priv->session, verify_certificate_cb);
228 ret = gnutls_credentials_set (priv->session,
229 GNUTLS_CRD_CERTIFICATE,
233 g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
234 _("Could not create TLS connection: %s"),
235 gnutls_strerror (ret));
239 gnutls_transport_set_push_function (priv->session,
240 g_tls_connection_gnutls_push_func);
241 gnutls_transport_set_pull_function (priv->session,
242 g_tls_connection_gnutls_pull_func);
243 gnutls_transport_set_pull_timeout_function (priv->session,
244 g_tls_connection_gnutls_pull_timeout_func);
245 gnutls_transport_set_ptr (priv->session, gnutls);
247 /* GDatagramBased supports vectored I/O; GPollableOutputStream does not. */
250 gnutls_transport_set_vec_push_function (priv->session,
251 g_tls_connection_gnutls_vec_push_func);
254 /* Set reasonable MTU */
255 if (flags & GNUTLS_DATAGRAM)
256 gnutls_dtls_set_mtu (priv->session, 1400);
261 g_clear_object (&base_io_stream);
262 g_clear_object (&base_socket);
268 g_tls_connection_gnutls_finalize (GObject *object)
270 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (object);
271 GTlsConnectionGnutlsPrivate *priv = g_tls_connection_gnutls_get_instance_private (gnutls);
274 gnutls_deinit (priv->session);
276 gnutls_certificate_free_credentials (priv->creds);
278 if (priv->cancellable)
280 g_cancellable_cancel (priv->cancellable);
281 g_clear_object (&priv->cancellable);
284 g_free (priv->interaction_id);
286 G_OBJECT_CLASS (g_tls_connection_gnutls_parent_class)->finalize (object);
289 gnutls_certificate_credentials_t
290 g_tls_connection_gnutls_get_credentials (GTlsConnectionGnutls *gnutls)
292 GTlsConnectionGnutlsPrivate *priv = g_tls_connection_gnutls_get_instance_private (gnutls);
298 g_tls_connection_gnutls_get_session (GTlsConnectionGnutls *gnutls)
300 GTlsConnectionGnutlsPrivate *priv = g_tls_connection_gnutls_get_instance_private (gnutls);
302 return priv->session;
306 on_pin_request (void *userdata,
308 const char *token_url,
309 const char *token_label,
310 unsigned int callback_flags,
314 GTlsConnection *connection = G_TLS_CONNECTION (userdata);
315 GTlsInteraction *interaction = g_tls_connection_get_interaction (connection);
316 GTlsPassword *password;
317 GTlsPasswordFlags password_flags = 0;
324 if (callback_flags & GNUTLS_PIN_WRONG)
325 password_flags |= G_TLS_PASSWORD_RETRY;
326 if (callback_flags & GNUTLS_PIN_COUNT_LOW)
327 password_flags |= G_TLS_PASSWORD_MANY_TRIES;
328 if (callback_flags & GNUTLS_PIN_FINAL_TRY || attempt > 5) /* Give up at some point */
329 password_flags |= G_TLS_PASSWORD_FINAL_TRY;
331 if (callback_flags & GNUTLS_PIN_USER)
332 password_flags |= G_TLS_PASSWORD_PKCS11_USER;
333 if (callback_flags & GNUTLS_PIN_SO)
334 password_flags |= G_TLS_PASSWORD_PKCS11_SECURITY_OFFICER;
335 if (callback_flags & GNUTLS_PIN_CONTEXT_SPECIFIC)
336 password_flags |= G_TLS_PASSWORD_PKCS11_CONTEXT_SPECIFIC;
338 description = g_strdup_printf (" %s (%s)", token_label, token_url);
339 password = g_tls_password_new (password_flags, description);
340 if (g_tls_connection_base_handshake_thread_ask_password (G_TLS_CONNECTION_BASE (connection), password))
343 const guchar *password_data = g_tls_password_get_value (password, &password_size);
344 if (password_size > pin_max - 1)
345 g_info ("PIN is larger than max PIN size");
347 /* Ensure NUL-termination */
348 memset (pin, 0, pin_max);
349 memcpy (pin, password_data, MIN (password_size, pin_max - 1));
351 ret = GNUTLS_E_SUCCESS;
354 g_free (description);
355 g_object_unref (password);
360 g_tls_connection_gnutls_handshake_thread_get_certificate (GTlsConnectionGnutls *gnutls,
361 gnutls_pcert_st **pcert,
362 unsigned int *pcert_length,
363 gnutls_privkey_t *pkey)
365 GTlsConnectionGnutlsPrivate *priv = g_tls_connection_gnutls_get_instance_private (gnutls);
366 GTlsCertificate *cert;
368 cert = g_tls_connection_get_certificate (G_TLS_CONNECTION (gnutls));
372 /* Send along a pre-initialized privkey so we can handle the callback here. */
373 gnutls_privkey_t privkey;
374 gnutls_privkey_init (&privkey);
375 gnutls_privkey_set_pin_function (privkey, on_pin_request, gnutls);
377 g_tls_certificate_gnutls_copy (G_TLS_CERTIFICATE_GNUTLS (cert),
378 priv->interaction_id,
379 pcert, pcert_length, &privkey);
390 static GTlsConnectionBaseStatus
391 end_gnutls_io (GTlsConnectionGnutls *gnutls,
392 GIOCondition direction,
395 const char *err_prefix)
397 GTlsConnectionGnutlsPrivate *priv = g_tls_connection_gnutls_get_instance_private (gnutls);
398 GTlsConnectionBase *tls = G_TLS_CONNECTION_BASE (gnutls);
399 GTlsConnectionBaseStatus status;
400 gboolean handshaking;
401 gboolean ever_handshaked;
402 GError *my_error = NULL;
404 /* We intentionally do not check for GNUTLS_E_INTERRUPTED here
405 * Instead, the caller may poll for the source to become ready again.
406 * (Note that GTlsOutputStreamGnutls and GTlsInputStreamGnutls inherit
407 * from GPollableOutputStream and GPollableInputStream, respectively.)
408 * See also the comment in set_gnutls_error().
410 if (ret == GNUTLS_E_AGAIN ||
411 ret == GNUTLS_E_WARNING_ALERT_RECEIVED)
412 return G_TLS_CONNECTION_BASE_TRY_AGAIN;
414 status = g_tls_connection_base_pop_io (tls, direction, ret >= 0, &my_error);
415 if (status == G_TLS_CONNECTION_BASE_OK ||
416 status == G_TLS_CONNECTION_BASE_WOULD_BLOCK ||
417 status == G_TLS_CONNECTION_BASE_TIMED_OUT)
420 g_propagate_error (error, my_error);
424 g_assert (status == G_TLS_CONNECTION_BASE_ERROR);
426 handshaking = g_tls_connection_base_is_handshaking (tls);
427 ever_handshaked = g_tls_connection_base_ever_handshaked (tls);
429 if (handshaking && !ever_handshaked)
431 if (g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_FAILED) ||
432 g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_BROKEN_PIPE))
434 g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_NOT_TLS,
435 _("Peer failed to perform TLS handshake: %s"), my_error->message);
436 g_clear_error (&my_error);
437 return G_TLS_CONNECTION_BASE_ERROR;
440 if (ret == GNUTLS_E_UNEXPECTED_PACKET_LENGTH ||
441 ret == GNUTLS_E_DECRYPTION_FAILED ||
442 ret == GNUTLS_E_UNSUPPORTED_VERSION_PACKET)
444 g_clear_error (&my_error);
445 g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_NOT_TLS,
446 _("Peer failed to perform TLS handshake: %s"), gnutls_strerror (ret));
447 return G_TLS_CONNECTION_BASE_ERROR;
451 if (ret == GNUTLS_E_REHANDSHAKE)
452 return G_TLS_CONNECTION_BASE_REHANDSHAKE;
454 if (ret == GNUTLS_E_PREMATURE_TERMINATION)
456 if (handshaking && !ever_handshaked)
458 g_clear_error (&my_error);
459 g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_NOT_TLS,
460 _("Peer failed to perform TLS handshake: %s"), gnutls_strerror (ret));
461 return G_TLS_CONNECTION_BASE_ERROR;
464 if (g_tls_connection_get_require_close_notify (G_TLS_CONNECTION (gnutls)))
466 g_clear_error (&my_error);
467 g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_EOF,
468 _("TLS connection closed unexpectedly"));
469 return G_TLS_CONNECTION_BASE_ERROR;
472 return G_TLS_CONNECTION_BASE_OK;
475 if (ret == GNUTLS_E_NO_CERTIFICATE_FOUND
476 #ifdef GNUTLS_E_CERTIFICATE_REQUIRED
477 || ret == GNUTLS_E_CERTIFICATE_REQUIRED /* Added in GnuTLS 3.6.7 */
481 g_clear_error (&my_error);
482 g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_CERTIFICATE_REQUIRED,
483 _("TLS connection peer did not send a certificate"));
484 return G_TLS_CONNECTION_BASE_ERROR;
487 if (ret == GNUTLS_E_CERTIFICATE_ERROR)
489 g_clear_error (&my_error);
490 g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
491 _("Unacceptable TLS certificate"));
492 return G_TLS_CONNECTION_BASE_ERROR;
495 if (ret == GNUTLS_E_FATAL_ALERT_RECEIVED)
497 g_clear_error (&my_error);
498 g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
499 _("Peer sent fatal TLS alert: %s"),
500 gnutls_alert_get_name (gnutls_alert_get (priv->session)));
501 return G_TLS_CONNECTION_BASE_ERROR;
504 if (ret == GNUTLS_E_INAPPROPRIATE_FALLBACK)
506 g_clear_error (&my_error);
507 g_set_error_literal (error, G_TLS_ERROR,
508 G_TLS_ERROR_INAPPROPRIATE_FALLBACK,
509 _("Protocol version downgrade attack detected"));
510 return G_TLS_CONNECTION_BASE_ERROR;
513 if (ret == GNUTLS_E_LARGE_PACKET)
515 guint mtu = gnutls_dtls_get_data_mtu (priv->session);
516 g_clear_error (&my_error);
517 g_set_error (error, G_IO_ERROR, G_IO_ERROR_MESSAGE_TOO_LARGE,
518 ngettext ("Message is too large for DTLS connection; maximum is %u byte",
519 "Message is too large for DTLS connection; maximum is %u bytes", mtu), mtu);
520 return G_TLS_CONNECTION_BASE_ERROR;
523 if (ret == GNUTLS_E_TIMEDOUT)
525 g_clear_error (&my_error);
526 g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_TIMED_OUT,
527 _("The operation timed out"));
528 return G_TLS_CONNECTION_BASE_ERROR;
531 if (error && my_error)
532 g_propagate_error (error, my_error);
534 if (error && !*error)
536 *error = g_error_new (G_TLS_ERROR, G_TLS_ERROR_MISC, "%s: %s",
537 err_prefix, gnutls_strerror (ret));
540 return G_TLS_CONNECTION_BASE_ERROR;
543 #define BEGIN_GNUTLS_IO(gnutls, direction, timeout, cancellable) \
544 g_tls_connection_base_push_io (G_TLS_CONNECTION_BASE (gnutls), \
545 direction, timeout, cancellable); \
548 #define END_GNUTLS_IO(gnutls, direction, ret, status, errmsg, err) \
549 status = end_gnutls_io (gnutls, direction, ret, err, errmsg); \
550 } while (status == G_TLS_CONNECTION_BASE_TRY_AGAIN);
553 set_gnutls_error (GTlsConnectionGnutls *gnutls,
556 GTlsConnectionBase *tls = G_TLS_CONNECTION_BASE (gnutls);
557 GTlsConnectionGnutlsPrivate *priv = g_tls_connection_gnutls_get_instance_private (gnutls);
559 /* We set EINTR rather than EAGAIN for G_IO_ERROR_WOULD_BLOCK so
560 * that GNUTLS_E_AGAIN only gets returned for gnutls-internal
561 * reasons, not for actual socket EAGAINs (and we have access
562 * to @error at the higher levels, so we can distinguish them
566 if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
567 gnutls_transport_set_errno (priv->session, EINTR);
568 else if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
570 /* Return EAGAIN while handshaking so that GnuTLS handles retries for us
571 * internally in its handshaking code. */
572 if (g_tls_connection_base_is_dtls (tls) && g_tls_connection_base_is_handshaking (tls))
573 gnutls_transport_set_errno (priv->session, EAGAIN);
575 gnutls_transport_set_errno (priv->session, EINTR);
577 else if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_TIMED_OUT))
578 gnutls_transport_set_errno (priv->session, EINTR);
579 else if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_MESSAGE_TOO_LARGE))
580 gnutls_transport_set_errno (priv->session, EMSGSIZE);
582 gnutls_transport_set_errno (priv->session, EIO);
586 g_tls_connection_gnutls_pull_func (gnutls_transport_ptr_t transport_data,
590 GTlsConnectionBase *tls = transport_data;
591 GTlsConnectionGnutls *gnutls = transport_data;
594 /* If read_error is nonnull when we're called, it means
595 * that an error previously occurred, but GnuTLS decided not to
596 * propagate it. So it's correct for us to just clear it. (Usually
597 * this means it ignored an EAGAIN after a short read, and now
598 * we'll return EAGAIN again, which it will obey this time.)
600 g_clear_error (g_tls_connection_base_get_read_error (tls));
602 if (g_tls_connection_base_is_dtls (tls))
604 GInputVector vector = { buf, buflen };
605 GInputMessage message = { NULL, &vector, 1, 0, 0, NULL, NULL };
607 ret = g_datagram_based_receive_messages (g_tls_connection_base_get_base_socket (tls),
609 g_tls_connection_base_is_handshaking (tls) ? 0 : g_tls_connection_base_get_read_timeout (tls),
610 g_tls_connection_base_get_read_cancellable (tls),
611 g_tls_connection_base_get_read_error (tls));
614 ret = message.bytes_received;
618 ret = g_pollable_stream_read (G_INPUT_STREAM (g_tls_connection_base_get_base_istream (tls)),
620 g_tls_connection_base_get_read_timeout (tls) != 0,
621 g_tls_connection_base_get_read_cancellable (tls),
622 g_tls_connection_base_get_read_error (tls));
626 set_gnutls_error (gnutls, *g_tls_connection_base_get_read_error (tls));
632 g_tls_connection_gnutls_push_func (gnutls_transport_ptr_t transport_data,
636 GTlsConnectionBase *tls = transport_data;
637 GTlsConnectionGnutls *gnutls = transport_data;
640 /* See comment in pull_func. */
641 g_clear_error (g_tls_connection_base_get_write_error (tls));
643 if (g_tls_connection_base_is_dtls (tls))
645 GOutputVector vector = { buf, buflen };
646 GOutputMessage message = { NULL, &vector, 1, 0, NULL, 0 };
648 ret = g_datagram_based_send_messages (g_tls_connection_base_get_base_socket (tls),
650 g_tls_connection_base_get_write_timeout (tls),
651 g_tls_connection_base_get_write_cancellable (tls),
652 g_tls_connection_base_get_write_error (tls));
655 ret = message.bytes_sent;
659 ret = g_pollable_stream_write (G_OUTPUT_STREAM (g_tls_connection_base_get_base_ostream (tls)),
661 g_tls_connection_base_get_write_timeout (tls) != 0,
662 g_tls_connection_base_get_write_cancellable (tls),
663 g_tls_connection_base_get_write_error (tls));
667 set_gnutls_error (gnutls, *g_tls_connection_base_get_write_error (tls));
673 g_tls_connection_gnutls_vec_push_func (gnutls_transport_ptr_t transport_data,
677 GTlsConnectionBase *tls = transport_data;
678 GTlsConnectionGnutls *gnutls = transport_data;
680 GOutputMessage message = { NULL, };
681 GOutputVector *vectors;
683 g_assert (g_tls_connection_base_is_dtls (tls));
685 /* See comment in pull_func. */
686 g_clear_error (g_tls_connection_base_get_write_error (tls));
688 /* this entire expression will be evaluated at compile time */
689 if (sizeof *iov == sizeof *vectors &&
690 sizeof iov->iov_base == sizeof vectors->buffer &&
691 G_STRUCT_OFFSET (giovec_t, iov_base) ==
692 G_STRUCT_OFFSET (GOutputVector, buffer) &&
693 sizeof iov->iov_len == sizeof vectors->size &&
694 G_STRUCT_OFFSET (giovec_t, iov_len) ==
695 G_STRUCT_OFFSET (GOutputVector, size))
696 /* ABI is compatible */
698 message.vectors = (GOutputVector *)iov;
699 message.num_vectors = iovcnt;
702 /* ABI is incompatible */
706 message.vectors = g_newa (GOutputVector, iovcnt);
707 for (i = 0; i < iovcnt; i++)
709 message.vectors[i].buffer = (void *)iov[i].iov_base;
710 message.vectors[i].size = iov[i].iov_len;
712 message.num_vectors = iovcnt;
715 ret = g_datagram_based_send_messages (g_tls_connection_base_get_base_socket (tls),
717 g_tls_connection_base_get_write_timeout (tls),
718 g_tls_connection_base_get_write_cancellable (tls),
719 g_tls_connection_base_get_write_error (tls));
722 ret = message.bytes_sent;
724 set_gnutls_error (gnutls, *g_tls_connection_base_get_write_error (tls));
730 read_pollable_cb (GPollableInputStream *istream,
733 gboolean *done = user_data;
737 return G_SOURCE_REMOVE;
741 read_datagram_based_cb (GDatagramBased *datagram_based,
742 GIOCondition condition,
745 gboolean *done = user_data;
749 return G_SOURCE_REMOVE;
753 read_timeout_cb (gpointer user_data)
755 gboolean *done = user_data;
759 return G_SOURCE_REMOVE;
763 read_cancelled_cb (GCancellable *cancellable,
766 gboolean *done = user_data;
770 return G_SOURCE_REMOVE;
774 g_tls_connection_gnutls_pull_timeout_func (gnutls_transport_ptr_t transport_data,
777 GTlsConnectionBase *tls = transport_data;
780 if (g_tls_connection_base_base_check (tls, G_IO_IN) ||
781 g_cancellable_is_cancelled (g_tls_connection_base_get_read_cancellable (tls)))
784 /* If @ms is 0, GnuTLS wants an instant response, so there’s no need to
785 * construct and query a #GSource. */
788 GMainContext *ctx = NULL;
789 GSource *read_source = NULL;
790 GSource *timeout_source = NULL;
791 GSource *cancellable_source = NULL;
792 gboolean done = FALSE;
794 ctx = g_main_context_new ();
796 /* Create a timeout source. */
797 timeout_source = g_timeout_source_new (ms);
798 g_source_set_callback (timeout_source, (GSourceFunc)read_timeout_cb,
801 /* Create a read source. We cannot use g_source_set_ready_time() on this
802 * to combine it with the @timeout_source, as that could mess with the
803 * internals of the #GDatagramBased’s #GSource implementation. */
804 if (g_tls_connection_base_is_dtls (tls))
806 read_source = g_datagram_based_create_source (g_tls_connection_base_get_base_socket (tls),
808 g_source_set_callback (read_source, (GSourceFunc)read_datagram_based_cb,
813 read_source = g_pollable_input_stream_create_source (g_tls_connection_base_get_base_istream (tls),
815 g_source_set_callback (read_source, (GSourceFunc)read_pollable_cb,
819 cancellable_source = g_cancellable_source_new (g_tls_connection_base_get_read_cancellable (tls));
820 g_source_set_callback (cancellable_source, (GSourceFunc)read_cancelled_cb,
823 g_source_attach (read_source, ctx);
824 g_source_attach (timeout_source, ctx);
825 g_source_attach (cancellable_source, ctx);
828 g_main_context_iteration (ctx, TRUE);
830 g_source_destroy (read_source);
831 g_source_destroy (timeout_source);
832 g_source_destroy (cancellable_source);
834 g_main_context_unref (ctx);
835 g_source_unref (read_source);
836 g_source_unref (timeout_source);
837 g_source_unref (cancellable_source);
839 /* If @read_source was dispatched due to cancellation, the resulting error
840 * will be handled in g_tls_connection_gnutls_pull_func(). */
841 if (g_tls_connection_base_base_check (tls, G_IO_IN) ||
842 g_cancellable_is_cancelled (g_tls_connection_base_get_read_cancellable (tls)))
849 static GTlsSafeRenegotiationStatus
850 g_tls_connection_gnutls_handshake_thread_safe_renegotiation_status (GTlsConnectionBase *tls)
852 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (tls);
853 GTlsConnectionGnutlsPrivate *priv = g_tls_connection_gnutls_get_instance_private (gnutls);
855 return gnutls_safe_renegotiation_status (priv->session) ? G_TLS_SAFE_RENEGOTIATION_SUPPORTED_BY_PEER
856 : G_TLS_SAFE_RENEGOTIATION_UNSUPPORTED;
859 static GTlsConnectionBaseStatus
860 g_tls_connection_gnutls_handshake_thread_request_rehandshake (GTlsConnectionBase *tls,
862 GCancellable *cancellable,
865 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (tls);
866 GTlsConnectionGnutlsPrivate *priv = g_tls_connection_gnutls_get_instance_private (gnutls);
867 GTlsConnectionBaseStatus status;
870 /* On a client-side connection, gnutls_handshake() itself will start
871 * a rehandshake, so we only need to do something special here for
872 * server-side connections.
874 if (!G_IS_TLS_SERVER_CONNECTION (tls))
875 return G_TLS_CONNECTION_BASE_OK;
877 BEGIN_GNUTLS_IO (gnutls, G_IO_IN | G_IO_OUT, timeout, cancellable);
878 ret = gnutls_rehandshake (priv->session);
879 END_GNUTLS_IO (gnutls, G_IO_IN | G_IO_OUT, ret, status, _("Error performing TLS handshake: %s"), error);
884 static GTlsCertificate *
885 g_tls_connection_gnutls_retrieve_peer_certificate (GTlsConnectionBase *tls)
887 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (tls);
888 GTlsConnectionGnutlsPrivate *priv = g_tls_connection_gnutls_get_instance_private (gnutls);
889 const gnutls_datum_t *certs;
890 GTlsCertificateGnutls *chain;
891 unsigned int num_certs;
893 if (gnutls_certificate_type_get (priv->session) != GNUTLS_CRT_X509)
896 certs = gnutls_certificate_get_peers (priv->session, &num_certs);
897 if (!certs || !num_certs)
900 chain = g_tls_certificate_gnutls_build_chain (certs, num_certs, GNUTLS_X509_FMT_DER);
904 return G_TLS_CERTIFICATE (chain);
908 verify_certificate_cb (gnutls_session_t session)
910 GTlsConnectionBase *tls = gnutls_session_get_ptr (session);
912 /* Return 0 for the handshake to continue, non-zero to terminate.
913 * Complete opposite of what OpenSSL does. */
914 return !g_tls_connection_base_handshake_thread_verify_certificate (tls);
918 g_tls_connection_gnutls_prepare_handshake (GTlsConnectionBase *tls,
919 gchar **advertised_protocols)
921 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (tls);
922 GTlsConnectionGnutlsPrivate *priv = g_tls_connection_gnutls_get_instance_private (gnutls);
924 if (advertised_protocols)
926 gnutls_datum_t *protocols;
929 n_protos = g_strv_length (advertised_protocols);
930 protocols = g_new (gnutls_datum_t, n_protos);
931 for (i = 0; advertised_protocols[i]; i++)
933 protocols[i].size = strlen (advertised_protocols[i]);
934 protocols[i].data = (guchar *)advertised_protocols[i];
936 gnutls_alpn_set_protocols (priv->session, protocols, n_protos, 0);
941 static GTlsConnectionBaseStatus
942 g_tls_connection_gnutls_handshake_thread_handshake (GTlsConnectionBase *tls,
944 GCancellable *cancellable,
947 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (tls);
948 GTlsConnectionGnutlsPrivate *priv = g_tls_connection_gnutls_get_instance_private (gnutls);
949 GTlsConnectionBaseStatus status;
952 if (!g_tls_connection_base_ever_handshaked (tls))
953 g_tls_connection_gnutls_set_handshake_priority (gnutls);
957 unsigned int timeout_ms;
959 /* Convert from microseconds to milliseconds, but ensure the timeout
960 * remains positive. */
961 timeout_ms = (timeout + 999) / 1000;
963 gnutls_handshake_set_timeout (priv->session, timeout_ms);
964 gnutls_dtls_set_timeouts (priv->session, 1000 /* default */, timeout_ms);
967 BEGIN_GNUTLS_IO (gnutls, G_IO_IN | G_IO_OUT, timeout, cancellable);
968 ret = gnutls_handshake (priv->session);
969 if (ret == GNUTLS_E_GOT_APPLICATION_DATA)
973 /* Got app data while waiting for rehandshake; buffer it and try again */
974 ret = gnutls_record_recv (priv->session, buf, sizeof (buf));
977 g_tls_connection_base_handshake_thread_buffer_application_data (tls, buf, ret);
978 ret = GNUTLS_E_AGAIN;
981 END_GNUTLS_IO (gnutls, G_IO_IN | G_IO_OUT, ret, status,
982 _("Error performing TLS handshake"), error);
987 static GTlsCertificateFlags
988 g_tls_connection_gnutls_verify_chain (GTlsConnectionBase *tls,
989 GTlsCertificate *chain,
990 const gchar *purpose,
991 GSocketConnectable *identity,
992 GTlsInteraction *interaction,
993 GTlsDatabaseVerifyFlags flags,
994 GCancellable *cancellable,
997 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (tls);
998 GTlsConnectionGnutlsPrivate *priv = g_tls_connection_gnutls_get_instance_private (gnutls);
999 GTlsCertificateFlags errors = 0;
1000 const char *hostname = NULL;
1001 char *free_hostname = NULL;
1002 GTlsDatabase *database;
1003 guint gnutls_result;
1006 /* There are several different ways to perform certificate verification with
1007 * GnuTLS, but they all fall into one of two categories:
1009 * (a) outside the context of a TLS session
1010 * (b) within the context of a TLS session
1012 * (a) is done by g_tls_database_verify_chain() and implemented using one of
1013 * several different functions of gnutls_x509_trust_list_t, e.g.
1014 * gnutls_x509_trust_list_verify_crt2() or one of the related functions.
1015 * This is the best we can do if we have to use a GTlsDatabase that is not a
1016 * GTlsDatabaseGnutls.
1018 database = g_tls_connection_get_database (G_TLS_CONNECTION (gnutls));
1019 if (!G_IS_TLS_DATABASE_GNUTLS (database))
1021 return g_tls_database_verify_chain (database,
1023 G_IS_TLS_CLIENT_CONNECTION (tls) ? G_TLS_DATABASE_PURPOSE_AUTHENTICATE_SERVER : G_TLS_DATABASE_PURPOSE_AUTHENTICATE_CLIENT,
1025 g_tls_connection_get_interaction (G_TLS_CONNECTION (tls)),
1026 G_TLS_DATABASE_VERIFY_NONE,
1031 /* Now for (b). The recommended way is gnutls_session_set_verify_cert(), but
1032 * we can't use that because that would leave no way to implement the
1033 * GTlsConnection::accept-certificate signal. The other way is to use
1034 * gnutls_certificate_verify_peers3() or one of the related functions. This
1035 * adds additional smarts that are not possible when using GTlsDatabase
1036 * directly. For example, it checks name constraints, key usage, and basic
1037 * constraints. It also checks for stapled OCSP responses. Verification will
1038 * fail if the OCSP response indicates the certificate has been revoked.
1039 * Verification will also fail if the Must-Staple flag is set but the OCSP
1040 * response is missing. Nice! This uses the gnutls_certificate_credentials_t
1041 * set on the gnutls_session_t by gnutls_credentials_set().
1044 if (G_IS_NETWORK_ADDRESS (identity))
1045 hostname = g_network_address_get_hostname (G_NETWORK_ADDRESS (identity));
1046 else if (G_IS_NETWORK_SERVICE (identity))
1047 hostname = g_network_service_get_domain (G_NETWORK_SERVICE (identity));
1048 else if (G_IS_INET_SOCKET_ADDRESS (identity))
1052 addr = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (identity));
1053 hostname = free_hostname = g_inet_address_to_string (addr);
1057 g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
1058 _("Cannot verify peer identity of unexpected type %s"), G_OBJECT_TYPE_NAME (identity));
1059 errors |= G_TLS_CERTIFICATE_BAD_IDENTITY;
1062 ret = gnutls_certificate_verify_peers3 (priv->session, hostname, &gnutls_result);
1064 errors |= G_TLS_CERTIFICATE_GENERIC_ERROR;
1066 errors |= g_tls_certificate_gnutls_convert_flags (gnutls_result);
1068 g_free (free_hostname);
1072 static GTlsProtocolVersion
1073 glib_protocol_version_from_gnutls (gnutls_protocol_t protocol_version)
1075 switch (protocol_version)
1078 return G_TLS_PROTOCOL_VERSION_SSL_3_0;
1080 return G_TLS_PROTOCOL_VERSION_TLS_1_0;
1082 return G_TLS_PROTOCOL_VERSION_TLS_1_1;
1084 return G_TLS_PROTOCOL_VERSION_TLS_1_2;
1086 return G_TLS_PROTOCOL_VERSION_TLS_1_3;
1087 case GNUTLS_DTLS0_9:
1088 return G_TLS_PROTOCOL_VERSION_UNKNOWN;
1089 case GNUTLS_DTLS1_0:
1090 return G_TLS_PROTOCOL_VERSION_DTLS_1_0;
1091 case GNUTLS_DTLS1_2:
1092 return G_TLS_PROTOCOL_VERSION_DTLS_1_2;
1094 return G_TLS_PROTOCOL_VERSION_UNKNOWN;
1099 get_ciphersuite_name (gnutls_session_t session)
1101 gnutls_protocol_t protocol_version = gnutls_protocol_get_version (session);
1105 if (protocol_version <= GNUTLS_TLS1_2 ||
1106 (protocol_version >= GNUTLS_DTLS0_9 && protocol_version <= GNUTLS_DTLS1_2))
1108 return g_strdup (gnutls_cipher_suite_get_name (gnutls_kx_get (session),
1109 gnutls_cipher_get (session),
1110 gnutls_mac_get (session)));
1113 cipher_name = g_strdup (gnutls_cipher_get_name (gnutls_cipher_get (session)));
1114 for (char *c = cipher_name; *c != '\0'; c++)
1120 result = g_strdup_printf ("TLS_%s_%s",
1122 gnutls_digest_get_name (gnutls_prf_hash_get (session)));
1123 g_free (cipher_name);
1129 g_tls_connection_gnutls_complete_handshake (GTlsConnectionBase *tls,
1130 gboolean handshake_succeeded,
1131 gchar **negotiated_protocol,
1132 GTlsProtocolVersion *protocol_version,
1133 gchar **ciphersuite_name,
1136 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (tls);
1137 GTlsConnectionGnutlsPrivate *priv = g_tls_connection_gnutls_get_instance_private (gnutls);
1138 gnutls_datum_t protocol;
1140 if (!handshake_succeeded)
1143 if (gnutls_alpn_get_selected_protocol (priv->session, &protocol) == 0 &&
1146 g_assert (!*negotiated_protocol);
1147 *negotiated_protocol = g_strndup ((gchar *)protocol.data, protocol.size);
1150 *protocol_version = glib_protocol_version_from_gnutls (gnutls_protocol_get_version (priv->session));
1151 *ciphersuite_name = get_ciphersuite_name (priv->session);
1155 g_tls_connection_gnutls_is_session_resumed (GTlsConnectionBase *tls)
1157 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (tls);
1158 GTlsConnectionGnutlsPrivate *priv = g_tls_connection_gnutls_get_instance_private (gnutls);
1160 return gnutls_session_is_resumed (priv->session);
1164 gnutls_get_binding (GTlsConnectionGnutls *gnutls,
1166 gnutls_channel_binding_t binding,
1169 GTlsConnectionGnutlsPrivate *priv = g_tls_connection_gnutls_get_instance_private (gnutls);
1171 int ret = gnutls_session_channel_binding (priv->session, binding, &cb);
1173 if (ret == GNUTLS_E_SUCCESS)
1175 /* Older GnuTLS versions are known to return SUCCESS and empty data for TLSv1.3 tls-unique binding.
1176 * While it may look prudent to catch here that specific corner case, the empty binding data is
1177 * definitely not a SUCCESS, regardless of the version and type. */
1180 g_set_error (error, G_TLS_CHANNEL_BINDING_ERROR, G_TLS_CHANNEL_BINDING_ERROR_GENERAL_ERROR,
1181 _("Empty channel binding data indicates a bug in the TLS library implementation"));
1187 g_tls_log_debug (gnutls, "binding size %d", cb.size);
1188 g_free (g_byte_array_steal (data, NULL));
1189 g_byte_array_append (data, cb.data, cb.size);
1197 case GNUTLS_E_UNIMPLEMENTED_FEATURE:
1198 g_set_error (error, G_TLS_CHANNEL_BINDING_ERROR, G_TLS_CHANNEL_BINDING_ERROR_NOT_IMPLEMENTED,
1199 _("Channel binding type is not implemented in the TLS library"));
1201 case GNUTLS_E_CHANNEL_BINDING_NOT_AVAILABLE:
1202 g_set_error (error, G_TLS_CHANNEL_BINDING_ERROR, G_TLS_CHANNEL_BINDING_ERROR_NOT_AVAILABLE,
1203 _("Channel binding data is not yet available"));
1206 g_set_error (error, G_TLS_CHANNEL_BINDING_ERROR, G_TLS_CHANNEL_BINDING_ERROR_GENERAL_ERROR,
1207 "%s", gnutls_strerror (ret));
1213 gnutls_get_binding_tls_unique (GTlsConnectionGnutls *gnutls,
1217 return gnutls_get_binding (gnutls, data, GNUTLS_CB_TLS_UNIQUE, error);
1221 gnutls_get_binding_tls_server_end_point (GTlsConnectionGnutls *gnutls,
1225 #if GTLS_GNUTLS_CHECK_VERSION(3, 7, 2)
1226 return gnutls_get_binding (gnutls, data, GNUTLS_CB_TLS_SERVER_END_POINT, error);
1228 GTlsConnectionGnutlsPrivate *priv = g_tls_connection_gnutls_get_instance_private (gnutls);
1229 const gnutls_datum_t *ders;
1230 unsigned int num_certs = 1;
1233 gnutls_x509_crt_t cert;
1234 gnutls_digest_algorithm_t algo;
1235 gboolean is_client = G_IS_TLS_CLIENT_CONNECTION (gnutls);
1237 ret = gnutls_certificate_type_get (priv->session);
1238 if (ret != GNUTLS_CRT_X509)
1240 g_set_error (error, G_TLS_CHANNEL_BINDING_ERROR, G_TLS_CHANNEL_BINDING_ERROR_NOT_SUPPORTED,
1241 _("X.509 certificate is not available on the connection"));
1246 ders = gnutls_certificate_get_peers (priv->session, &num_certs);
1248 ders = gnutls_certificate_get_ours (priv->session);
1250 if (!ders || num_certs == 0)
1252 g_set_error (error, G_TLS_CHANNEL_BINDING_ERROR, G_TLS_CHANNEL_BINDING_ERROR_NOT_AVAILABLE,
1253 _("X.509 certificate is not available on the connection"));
1257 /* This is a drill */
1261 /* for DER only first cert is imported, but cert will be pre-initialized */
1262 ret = gnutls_x509_crt_list_import (&cert, &num_certs, ders, GNUTLS_X509_FMT_DER, 0);
1263 if (ret < 0 || num_certs == 0)
1265 g_set_error (error, G_TLS_CHANNEL_BINDING_ERROR, G_TLS_CHANNEL_BINDING_ERROR_NOT_AVAILABLE,
1266 _("X.509 certificate is not available or is of unknown format: %s"),
1267 gnutls_strerror (ret));
1271 /* obtain signature algorithm for the certificate - we need hashing algo from it */
1272 ret = gnutls_x509_crt_get_signature_algorithm (cert);
1273 if (ret < 0 || ret == GNUTLS_SIGN_UNKNOWN)
1275 gnutls_x509_crt_deinit (cert);
1276 g_set_error (error, G_TLS_CHANNEL_BINDING_ERROR, G_TLS_CHANNEL_BINDING_ERROR_NOT_SUPPORTED,
1277 _("Unable to obtain certificate signature algorithm"));
1280 /* At this point we either use SHA256 as a fallback, or native algorithm */
1281 algo = gnutls_sign_get_hash_algorithm (ret);
1282 /* Cannot identify signing algorithm or weak security - let try fallback */
1285 case GNUTLS_DIG_MD5:
1286 case GNUTLS_DIG_SHA1:
1287 algo = GNUTLS_DIG_SHA256;
1289 case GNUTLS_DIG_UNKNOWN:
1290 case GNUTLS_DIG_NULL:
1291 case GNUTLS_DIG_MD5_SHA1:
1292 g_set_error (error, G_TLS_CHANNEL_BINDING_ERROR, G_TLS_CHANNEL_BINDING_ERROR_NOT_SUPPORTED,
1293 _("Current X.509 certificate uses unknown or unsupported signature algorithm"));
1294 gnutls_x509_crt_deinit (cert);
1300 /* preallocate 512 bits buffer as maximum supported digest size */
1302 g_byte_array_set_size (data, rlen);
1303 ret = gnutls_x509_crt_get_fingerprint (cert, algo, data->data, &rlen);
1305 /* in case the future is coming on */
1306 if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
1308 g_byte_array_set_size (data, rlen);
1309 ret = gnutls_x509_crt_get_fingerprint (cert, algo, data->data, &rlen);
1312 gnutls_x509_crt_deinit (cert);
1313 g_byte_array_set_size (data, rlen);
1318 /* Still getting error? We cannot do much here to recover */
1319 g_set_error (error, G_TLS_CHANNEL_BINDING_ERROR, G_TLS_CHANNEL_BINDING_ERROR_GENERAL_ERROR,
1320 "%s", gnutls_strerror(ret));
1325 #if !GTLS_GNUTLS_CHECK_VERSION(3, 7, 2)
1326 #define RFC5705_LABEL_DATA "EXPORTER-Channel-Binding"
1327 #define RFC5705_LABEL_LEN 24
1330 /* Experimental binding for TLS1.3, see
1331 * https://datatracker.ietf.org/doc/draft-ietf-kitten-tls-channel-bindings-for-tls13 */
1333 gnutls_get_binding_tls_exporter (GTlsConnectionGnutls *gnutls,
1337 #if GTLS_GNUTLS_CHECK_VERSION(3, 7, 2)
1338 return gnutls_get_binding (gnutls, data, GNUTLS_CB_TLS_EXPORTER, error);
1340 GTlsConnectionGnutlsPrivate *priv = g_tls_connection_gnutls_get_instance_private (gnutls);
1345 /* This is a drill */
1349 g_byte_array_set_size (data, 32);
1350 ret = gnutls_prf_rfc5705 (priv->session,
1351 RFC5705_LABEL_LEN, RFC5705_LABEL_DATA,
1353 data->len, (char *)data->data);
1355 if (ret == GNUTLS_E_SUCCESS)
1358 g_set_error (error, G_TLS_CHANNEL_BINDING_ERROR, G_TLS_CHANNEL_BINDING_ERROR_GENERAL_ERROR,
1359 "%s", gnutls_strerror (ret));
1365 g_tls_connection_gnutls_get_channel_binding_data (GTlsConnectionBase *tls,
1366 GTlsChannelBindingType type,
1370 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (tls);
1372 /* XXX: remove the cast once public enum supports exporter */
1375 case G_TLS_CHANNEL_BINDING_TLS_UNIQUE:
1376 return gnutls_get_binding_tls_unique (gnutls, data, error);
1378 case G_TLS_CHANNEL_BINDING_TLS_SERVER_END_POINT:
1379 return gnutls_get_binding_tls_server_end_point (gnutls, data, error);
1382 return gnutls_get_binding_tls_exporter (gnutls, data, error);
1385 /* Anyone to implement tls-unique-for-telnet? */
1386 g_set_error (error, G_TLS_CHANNEL_BINDING_ERROR, G_TLS_CHANNEL_BINDING_ERROR_NOT_IMPLEMENTED,
1387 _("Requested channel binding type is not implemented"));
1392 static GTlsConnectionBaseStatus
1393 g_tls_connection_gnutls_read (GTlsConnectionBase *tls,
1398 GCancellable *cancellable,
1401 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (tls);
1402 GTlsConnectionGnutlsPrivate *priv = g_tls_connection_gnutls_get_instance_private (gnutls);
1403 GTlsConnectionBaseStatus status;
1406 BEGIN_GNUTLS_IO (gnutls, G_IO_IN, timeout, cancellable);
1407 ret = gnutls_record_recv (priv->session, buffer, count);
1408 END_GNUTLS_IO (gnutls, G_IO_IN, ret, status, _("Error reading data from TLS socket"), error);
1410 *nread = MAX (ret, 0);
1415 input_vectors_from_gnutls_datum_t (GInputVector *vectors,
1417 const gnutls_datum_t *datum)
1422 /* Copy into the receive vectors. */
1423 for (i = 0; i < num_vectors && total < datum->size; i++)
1426 GInputVector *vec = &vectors[i];
1428 count = MIN (vec->size, datum->size - total);
1430 memcpy (vec->buffer, datum->data + total, count);
1434 g_assert (total <= datum->size);
1439 static GTlsConnectionBaseStatus
1440 g_tls_connection_gnutls_read_message (GTlsConnectionBase *tls,
1441 GInputVector *vectors,
1445 GCancellable *cancellable,
1448 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (tls);
1449 GTlsConnectionGnutlsPrivate *priv = g_tls_connection_gnutls_get_instance_private (gnutls);
1450 GTlsConnectionBaseStatus status;
1452 gnutls_packet_t packet = { 0, };
1454 BEGIN_GNUTLS_IO (gnutls, G_IO_IN, timeout, cancellable);
1456 /* Receive the entire datagram (zero-copy). */
1457 ret = gnutls_record_recv_packet (priv->session, &packet);
1461 gnutls_datum_t data = { 0, };
1463 gnutls_packet_get (packet, &data, NULL);
1464 ret = input_vectors_from_gnutls_datum_t (vectors, num_vectors, &data);
1465 gnutls_packet_deinit (packet);
1468 END_GNUTLS_IO (gnutls, G_IO_IN, ret, status, _("Error reading data from TLS socket"), error);
1470 *nread = MAX (ret, 0);
1474 static GTlsConnectionBaseStatus
1475 g_tls_connection_gnutls_write (GTlsConnectionBase *tls,
1480 GCancellable *cancellable,
1483 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (tls);
1484 GTlsConnectionGnutlsPrivate *priv = g_tls_connection_gnutls_get_instance_private (gnutls);
1485 GTlsConnectionBaseStatus status;
1488 BEGIN_GNUTLS_IO (gnutls, G_IO_OUT, timeout, cancellable);
1489 ret = gnutls_record_send (priv->session, buffer, count);
1490 END_GNUTLS_IO (gnutls, G_IO_OUT, ret, status, _("Error writing data to TLS socket"), error);
1492 *nwrote = MAX (ret, 0);
1496 static GTlsConnectionBaseStatus
1497 g_tls_connection_gnutls_write_message (GTlsConnectionBase *tls,
1498 GOutputVector *vectors,
1502 GCancellable *cancellable,
1505 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (tls);
1506 GTlsConnectionGnutlsPrivate *priv = g_tls_connection_gnutls_get_instance_private (gnutls);
1507 GTlsConnectionBaseStatus status;
1510 gsize total_message_size;
1512 /* Calculate the total message size and check it’s not too big. */
1513 for (i = 0, total_message_size = 0; i < num_vectors; i++)
1514 total_message_size += vectors[i].size;
1516 if (g_tls_connection_base_is_dtls (tls) &&
1517 gnutls_dtls_get_data_mtu (priv->session) < total_message_size)
1520 guint mtu = gnutls_dtls_get_data_mtu (priv->session);
1522 message = g_strdup_printf("%s %s",
1523 ngettext ("Message of size %lu byte is too large for DTLS connection",
1524 "Message of size %lu bytes is too large for DTLS connection", total_message_size),
1525 ngettext ("(maximum is %u byte)", "(maximum is %u bytes)", mtu));
1526 g_set_error (error, G_IO_ERROR, G_IO_ERROR_MESSAGE_TOO_LARGE,
1532 return G_TLS_CONNECTION_BASE_ERROR;
1535 /* Queue up the data from all the vectors. */
1536 gnutls_record_cork (priv->session);
1538 for (i = 0; i < num_vectors; i++)
1540 ret = gnutls_record_send (priv->session,
1541 vectors[i].buffer, vectors[i].size);
1543 if (ret < 0 || ret < vectors[i].size)
1545 /* Uncork to restore state, then bail. The peer will receive a
1546 * truncated datagram. */
1551 BEGIN_GNUTLS_IO (gnutls, G_IO_OUT, timeout, cancellable);
1552 ret = gnutls_record_uncork (priv->session, 0 /* flags */);
1553 END_GNUTLS_IO (gnutls, G_IO_OUT, ret, status, _("Error writing data to TLS socket"), error);
1555 *nwrote = MAX (ret, 0);
1559 static GTlsConnectionBaseStatus
1560 g_tls_connection_gnutls_close (GTlsConnectionBase *tls,
1562 GCancellable *cancellable,
1565 GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (tls);
1566 GTlsConnectionGnutlsPrivate *priv = g_tls_connection_gnutls_get_instance_private (gnutls);
1567 GTlsConnectionBaseStatus status;
1570 BEGIN_GNUTLS_IO (gnutls, G_IO_IN | G_IO_OUT, timeout, cancellable);
1571 ret = gnutls_bye (priv->session, GNUTLS_SHUT_WR);
1572 END_GNUTLS_IO (gnutls, G_IO_IN | G_IO_OUT, ret, status, _("Error performing TLS close: %s"), error);
1578 initialize_gnutls_priority (void)
1580 const gchar *priority_override;
1581 const gchar *error_pos = NULL;
1584 g_assert (!priority);
1586 priority_override = g_getenv ("G_TLS_GNUTLS_PRIORITY");
1587 if (priority_override)
1589 ret = gnutls_priority_init2 (&priority, priority_override, &error_pos, 0);
1590 if (ret != GNUTLS_E_SUCCESS)
1591 g_warning ("Failed to set GnuTLS session priority with beginning at %s: %s", error_pos, gnutls_strerror (ret));
1595 ret = gnutls_priority_init2 (&priority, "%COMPAT", &error_pos, GNUTLS_PRIORITY_INIT_DEF_APPEND);
1596 if (ret != GNUTLS_E_SUCCESS)
1597 g_warning ("Failed to set GnuTLS session priority with error beginning at %s: %s", error_pos, gnutls_strerror (ret));
1601 g_tls_connection_gnutls_class_init (GTlsConnectionGnutlsClass *klass)
1603 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
1604 GTlsConnectionBaseClass *base_class = G_TLS_CONNECTION_BASE_CLASS (klass);
1606 gobject_class->finalize = g_tls_connection_gnutls_finalize;
1608 base_class->prepare_handshake = g_tls_connection_gnutls_prepare_handshake;
1609 base_class->handshake_thread_safe_renegotiation_status = g_tls_connection_gnutls_handshake_thread_safe_renegotiation_status;
1610 base_class->handshake_thread_request_rehandshake = g_tls_connection_gnutls_handshake_thread_request_rehandshake;
1611 base_class->handshake_thread_handshake = g_tls_connection_gnutls_handshake_thread_handshake;
1612 base_class->retrieve_peer_certificate = g_tls_connection_gnutls_retrieve_peer_certificate;
1613 base_class->verify_chain = g_tls_connection_gnutls_verify_chain;
1614 base_class->complete_handshake = g_tls_connection_gnutls_complete_handshake;
1615 base_class->is_session_resumed = g_tls_connection_gnutls_is_session_resumed;
1616 base_class->get_channel_binding_data = g_tls_connection_gnutls_get_channel_binding_data;
1617 base_class->read_fn = g_tls_connection_gnutls_read;
1618 base_class->read_message_fn = g_tls_connection_gnutls_read_message;
1619 base_class->write_fn = g_tls_connection_gnutls_write;
1620 base_class->write_message_fn = g_tls_connection_gnutls_write_message;
1621 base_class->close_fn = g_tls_connection_gnutls_close;
1623 initialize_gnutls_priority ();
1627 g_tls_connection_gnutls_initable_iface_init (GInitableIface *iface)
1629 iface->init = g_tls_connection_gnutls_initable_init;