summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Winship <danw@gnome.org>2010-10-24 15:42:04 -0400
committerRuslan N. Marchenko <me@ruff.mobi>2020-05-09 15:51:26 +0200
commitf993fb4a8ed42f34599f796fbe98d43f18231945 (patch)
tree7fa03c75c0bc656cd7fcaf956115edf016f5fe86
parent1e62674a8e234cc368f720748b16f3266dad7987 (diff)
wocky-tls: port to gio TLS
A few minor things, marked DANWFIXME, are unimplemented https://bugs.freedesktop.org/show_bug.cgi?id=31447
-rw-r--r--wocky/wocky-tls-handler.c13
-rw-r--r--wocky/wocky-tls.c1631
-rw-r--r--wocky/wocky-tls.h33
3 files changed, 144 insertions, 1533 deletions
diff --git a/wocky/wocky-tls-handler.c b/wocky/wocky-tls-handler.c
index 00e813e..ef005f7 100644
--- a/wocky/wocky-tls-handler.c
+++ b/wocky/wocky-tls-handler.c
@@ -159,7 +159,8 @@ real_verify_async (WockyTLSHandler *self,
GSimpleAsyncResult *result;
glong flags = WOCKY_TLS_VERIFY_NORMAL;
WockyTLSCertStatus status = WOCKY_TLS_CERT_UNKNOWN_ERROR;
- gchar *peername;
+ GSocketConnectable *identity;
+ const gchar *peername = NULL;
GStrv verify_extra_identities = NULL;
result = g_simple_async_result_new (G_OBJECT (self),
@@ -178,8 +179,12 @@ real_verify_async (WockyTLSHandler *self,
verify_extra_identities = extra_identities;
}
- g_object_get (G_OBJECT (tls_session), "peername", &peername, NULL);
- DEBUG ("Verifying certificate (peername: %s)", peername);
+ identity = g_tls_client_connection_get_server_identity (G_TLS_CLIENT_CONNECTION (tls_session));
+ if (G_IS_NETWORK_ADDRESS (identity))
+ peername = g_network_address_get_hostname (G_NETWORK_ADDRESS (identity));
+
+ DEBUG ("Verifying certificate (peername: %s)",
+ (peername == NULL) ? "-" : peername);
wocky_tls_session_verify_peer (tls_session,
verify_extra_identities, flags, &status);
@@ -235,7 +240,6 @@ real_verify_async (WockyTLSHandler *self,
g_simple_async_result_complete_in_idle (result);
g_object_unref (result);
- g_free (peername);
return;
}
else
@@ -250,7 +254,6 @@ real_verify_async (WockyTLSHandler *self,
g_simple_async_result_complete_in_idle (result);
g_object_unref (result);
- g_free (peername);
}
static gboolean
diff --git a/wocky/wocky-tls.c b/wocky/wocky-tls.c
index cc3a385..b8f0cde 100644
--- a/wocky/wocky-tls.c
+++ b/wocky/wocky-tls.c
@@ -50,14 +50,12 @@
#include "wocky-tls.h"
-#include <gnutls/x509.h>
-#include <gnutls/openpgp.h>
-
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
+/* DANWFIXME: allow configuring compression options */
#ifdef ENABLE_PREFER_STREAM_CIPHERS
#define DEFAULT_TLS_OPTIONS \
/* start with nothing enabled by default */ \
@@ -83,6 +81,7 @@
#define DEBUG_HANDSHAKE_LEVEL 5
#define DEBUG_ASYNC_DETAIL_LEVEL 6
+#ifdef DANWFIXME
#define VERIFY_STRICT GNUTLS_VERIFY_DO_NOT_ALLOW_SAME
#define VERIFY_NORMAL GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT
#define VERIFY_LENIENT ( GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT | \
@@ -91,437 +90,51 @@
GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5 | \
GNUTLS_VERIFY_DISABLE_TIME_CHECKS | \
GNUTLS_VERIFY_DISABLE_CA_SIGN )
+#else
+#define VERIFY_STRICT G_TLS_CERTIFICATE_VALIDATE_ALL
+#define VERIFY_NORMAL G_TLS_CERTIFICATE_VALIDATE_ALL
+#define VERIFY_LENIENT 0
+#endif
#include "wocky-debug-internal.h"
#include "wocky-utils.h"
-#include <gnutls/gnutls.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>
-enum
-{
- PROP_S_NONE,
- PROP_S_STREAM,
- PROP_S_PEERNAME,
- PROP_S_SERVER,
- PROP_S_DHBITS,
- PROP_S_KEYFILE,
- PROP_S_CERTFILE,
-};
-
-enum
-{
- PROP_O_NONE,
- PROP_O_SESSION
-};
-
-enum
-{
- PROP_I_NONE,
- PROP_I_SESSION
-};
-
-typedef struct
-{
- gboolean active;
-
- gint io_priority;
- GCancellable *cancellable;
- GObject *source_object;
- GAsyncReadyCallback callback;
- gpointer user_data;
- gpointer source_tag;
- GError *error;
-} WockyTLSJob;
-
-typedef enum
-{
- WOCKY_TLS_OP_READ,
- WOCKY_TLS_OP_WRITE
-} WockyTLSOperation;
-
-typedef enum
-{
- WOCKY_TLS_OP_STATE_IDLE,
- WOCKY_TLS_OP_STATE_ACTIVE,
- WOCKY_TLS_OP_STATE_DONE
-} WockyTLSOpState;
-
-typedef struct
-{
- WockyTLSJob job;
-} WockyTLSJobHandshake;
-
-typedef struct
-{
- WockyTLSJob job;
-
- gconstpointer buffer;
- gsize count;
-} WockyTLSJobWrite;
-
-typedef struct
-{
- WockyTLSJob job;
-
- gpointer buffer;
- gsize count;
-} WockyTLSJobRead;
-
-typedef struct
-{
- WockyTLSOpState state;
-
- guint8 *buffer;
- gssize requested;
- gssize result;
- GError *error;
-} WockyTLSOp;
-
-typedef GIOStreamClass WockyTLSSessionClass;
-typedef GInputStreamClass WockyTLSInputStreamClass;
-typedef GOutputStreamClass WockyTLSOutputStreamClass;
-
-static gnutls_dh_params_t dh_0768 = NULL;
-static gnutls_dh_params_t dh_1024 = NULL;
-static gnutls_dh_params_t dh_2048 = NULL;
-static gnutls_dh_params_t dh_3072 = NULL;
-static gnutls_dh_params_t dh_4096 = NULL;
-
-typedef struct _WockyTLSInputStream WockyTLSInputStream;
-typedef struct _WockyTLSInputStream WockyTLSOutputStream;
-
-struct _WockyTLSSession
-{
- GIOStream parent;
-
- GIOStream *stream;
- GCancellable *cancellable;
- GError *error;
- gboolean async;
-
- /* tls client support */
- gchar *peername;
-
- /* tls server support */
- gboolean server;
- gnutls_dh_params_t dh_params;
- guint dh_bits;
- gchar *key_file;
- gchar *cert_file;
-
- /* frontend jobs */
- WockyTLSJobHandshake handshake_job;
- WockyTLSJobRead read_job;
- WockyTLSJobWrite write_job;
-
- /* backend jobs */
- WockyTLSOp read_op;
- WockyTLSOp write_op;
-
- gnutls_session_t session;
-
- gnutls_certificate_credentials_t gnutls_cert_cred;
-
- WockyTLSInputStream *input;
- WockyTLSOutputStream *output;
-};
-
-struct _WockyTLSInputStream
-{
- GInputStream parent;
- WockyTLSSession *session;
-};
-
-struct _WockyTLSOutputStream
-{
- GOutputStream parent;
- WockyTLSSession *session;
-};
-
-static guint tls_debug_level = 0;
-
-static GType wocky_tls_input_stream_get_type (void);
-static GType wocky_tls_output_stream_get_type (void);
-G_DEFINE_TYPE (WockyTLSSession, wocky_tls_session, G_TYPE_IO_STREAM);
-G_DEFINE_TYPE (WockyTLSInputStream, wocky_tls_input_stream, G_TYPE_INPUT_STREAM);
-G_DEFINE_TYPE (WockyTLSOutputStream, wocky_tls_output_stream, G_TYPE_OUTPUT_STREAM);
-#define WOCKY_TYPE_TLS_INPUT_STREAM (wocky_tls_input_stream_get_type ())
-#define WOCKY_TYPE_TLS_OUTPUT_STREAM (wocky_tls_output_stream_get_type ())
-#define WOCKY_TLS_INPUT_STREAM(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \
- WOCKY_TYPE_TLS_INPUT_STREAM, \
- WockyTLSInputStream))
-#define WOCKY_TLS_OUTPUT_STREAM(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \
- WOCKY_TYPE_TLS_OUTPUT_STREAM, \
- WockyTLSOutputStream))
-
-static const gchar *hdesc_to_string (long desc)
-{
-#define HDESC(x) case GNUTLS_HANDSHAKE_##x: return #x; break;
- switch (desc)
- {
- HDESC (HELLO_REQUEST);
- HDESC (CLIENT_HELLO);
- HDESC (SERVER_HELLO);
- HDESC (CERTIFICATE_PKT);
- HDESC (SERVER_KEY_EXCHANGE);
- HDESC (CERTIFICATE_REQUEST);
- HDESC (SERVER_HELLO_DONE);
- HDESC (CERTIFICATE_VERIFY);
- HDESC (CLIENT_KEY_EXCHANGE);
- HDESC (FINISHED);
- HDESC (SUPPLEMENTAL);
- }
- return "Unknown State";
-}
-
-static const gchar *error_to_string (long error)
-{
- const gchar *result;
-
- result = gnutls_strerror_name (error);
- if (result != NULL)
- return result;
-
- return "Unknown Error";
-}
-
-static gboolean
-wocky_tls_set_error (GError **error,
- gssize result)
-{
- int code = (int) result;
-
- if (result < 0)
- g_set_error (error, WOCKY_TLS_ERROR, 0, "%d: %s",
- code, error_to_string (code));
-
- return result < 0;
-}
-
-static GSimpleAsyncResult *
-wocky_tls_job_make_result (WockyTLSJob *job,
- gssize result)
-{
- if (result != GNUTLS_E_AGAIN)
- {
- GSimpleAsyncResult *simple;
- GError *error = NULL;
-
- simple = g_simple_async_result_new (job->source_object,
- job->callback,
- job->user_data,
- job->source_tag);
-
- if (job->error != NULL)
- {
-#ifdef WOCKY_TLS_STRICT_ERROR_ASSERTIONS
- g_assert (result == GNUTLS_E_PUSH_ERROR ||
- result == GNUTLS_E_PULL_ERROR);
-#endif
- g_simple_async_result_set_from_error (simple, job->error);
- g_error_free (job->error);
- }
- else if (wocky_tls_set_error (&error, result))
- {
- g_simple_async_result_set_from_error (simple, error);
- g_error_free (error);
- }
-
- if (job->cancellable != NULL)
- g_object_unref (job->cancellable);
- job->cancellable = NULL;
-
- g_object_unref (job->source_object);
- job->source_object = NULL;
-
- job->active = FALSE;
-
- return simple;
- }
- else
- {
- g_assert (job->active);
- return NULL;
- }
-}
-
-static void
-wocky_tls_job_result_gssize (WockyTLSJob *job,
- gssize result)
-{
- GSimpleAsyncResult *simple;
-
- if ((simple = wocky_tls_job_make_result (job, result)))
- {
- if (result >= 0)
- g_simple_async_result_set_op_res_gssize (simple, result);
-
- g_simple_async_result_complete (simple);
- g_object_unref (simple);
- }
-}
-
-static void
-wocky_tls_job_result_boolean (WockyTLSJob *job,
- gint result)
-{
- GSimpleAsyncResult *simple;
-
- if ((simple = wocky_tls_job_make_result (job, result)))
- {
- g_simple_async_result_complete (simple);
- g_object_unref (simple);
- }
-}
-
-static void
-wocky_tls_session_try_operation (WockyTLSSession *session,
- WockyTLSOperation operation)
-{
- if (session->handshake_job.job.active)
- {
- gint result;
- DEBUG ("session %p: async job handshake", session);
- session->async = TRUE;
- result = gnutls_handshake (session->session);
- g_assert (result != GNUTLS_E_INTERRUPTED);
-
- if (tls_debug_level >= DEBUG_HANDSHAKE_LEVEL)
- {
- gnutls_handshake_description_t i;
- gnutls_handshake_description_t o;
-
- DEBUG ("session %p: async job handshake: %d %s", session,
- result, error_to_string(result));
- i = gnutls_handshake_get_last_in (session->session);
- o = gnutls_handshake_get_last_out (session->session);
- DEBUG ("session %p: async job handshake: { in: %s; out: %s }",
- session, hdesc_to_string (i), hdesc_to_string (o));
- }
-
- session->async = FALSE;
-
- wocky_tls_job_result_boolean (&session->handshake_job.job, result);
- }
-
- else if (operation == WOCKY_TLS_OP_READ)
- {
- gssize result = 0;
-
- if (tls_debug_level >= DEBUG_ASYNC_DETAIL_LEVEL)
- DEBUG ("async job OP_READ");
- g_assert (session->read_job.job.active);
-
- /* If the read result is 0, the remote end disconnected us, no need to
- * pull data through gnutls_record_recv in that case */
-
- if (session->read_op.result != 0)
- {
-
- session->async = TRUE;
- result = gnutls_record_recv (session->session,
- session->read_job.buffer,
- session->read_job.count);
- g_assert (result != GNUTLS_E_INTERRUPTED);
- session->async = FALSE;
- }
-
- wocky_tls_job_result_gssize (&session->read_job.job, result);
- }
-
- else
- {
- gssize result;
- if (tls_debug_level >= DEBUG_ASYNC_DETAIL_LEVEL)
- DEBUG ("async job OP_WRITE: %"G_GSIZE_FORMAT,
- session->write_job.count);
- g_assert (operation == WOCKY_TLS_OP_WRITE);
- g_assert (session->write_job.job.active);
-
-
- session->async = TRUE;
- result = gnutls_record_send (session->session,
- session->write_job.buffer,
- session->write_job.count);
- g_assert (result != GNUTLS_E_INTERRUPTED);
- session->async = FALSE;
-
- wocky_tls_job_result_gssize (&session->write_job.job, result);
- }
-}
static void
-wocky_tls_job_start (WockyTLSJob *job,
- gpointer source_object,
- gint io_priority,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data,
- gpointer source_tag)
+free_cas (gpointer cas)
{
- g_assert (job->active == FALSE);
- g_assert (job->cancellable == NULL);
-
- /* this is always a circular reference, so it will keep the
- * session alive for as long as the job is running.
- */
- job->source_object = g_object_ref (source_object);
-
- job->io_priority = io_priority;
- if (cancellable != NULL)
- job->cancellable = g_object_ref (cancellable);
- job->callback = callback;
- job->user_data = user_data;
- job->source_tag = source_tag;
- job->error = NULL;
- job->active = TRUE;
-}
-
-gboolean
-wocky_tls_session_handshake (WockyTLSSession *session,
- GCancellable *cancellable,
- GError **error)
-{
- gint result;
-
- DEBUG ("sync job handshake");
- session->error = NULL;
- session->cancellable = cancellable;
- result = gnutls_handshake (session->session);
- g_assert (result != GNUTLS_E_INTERRUPTED);
- g_assert (result != GNUTLS_E_AGAIN);
- session->cancellable = NULL;
-
- if (tls_debug_level >= DEBUG_HANDSHAKE_LEVEL)
- DEBUG ("sync job handshake: %d %s", result, error_to_string (result));
-
- if (session->error != NULL)
- {
- g_assert (result == GNUTLS_E_PULL_ERROR ||
- result == GNUTLS_E_PUSH_ERROR);
-
- g_propagate_error (error, session->error);
- return FALSE;
- }
- else if (wocky_tls_set_error (error, result))
- return FALSE;
+ GList *c;
- return TRUE;
+ for (c = cas; c; c = c->next)
+ g_object_unref (c->data);
+ g_list_free (cas);
}
/* ************************************************************************* */
/* adding CA certificates lists for peer certificate verification */
void
-wocky_tls_session_add_ca (WockyTLSSession *session,
+wocky_tls_session_add_ca (GTlsConnection *conn,
const gchar *ca_path)
{
+ GList *cas, *certs, *c;
int n = 0;
struct stat target;
+ cas = g_object_get_data (G_OBJECT (conn), "wocky-ca-list");
+ if (cas)
+ {
+ /* Copy, since the old value will be freed when we set the
+ * new value.
+ */
+ for (c = cas; c; c = c->next)
+ g_object_ref (c->data);
+ cas = g_list_copy (cas);
+ }
DEBUG ("adding CA CERT path '%s'", (gchar *) ca_path);
if (stat (ca_path, &target) != 0)
@@ -544,8 +157,11 @@ wocky_tls_session_add_ca (WockyTLSSession *session,
gchar *path = g_build_path ("/", ca_path, entry->d_name, NULL);
if ((stat (path, &file) == 0) && S_ISREG (file.st_mode))
- n += gnutls_certificate_set_x509_trust_file (
- session->gnutls_cert_cred, path, GNUTLS_X509_FMT_PEM);
+ {
+ certs = g_tls_certificate_list_new_from_file (path, NULL);
+ n += g_list_length (certs);
+ cas = g_list_concat (cas, certs);
+ }
g_free (path);
}
@@ -555,148 +171,50 @@ wocky_tls_session_add_ca (WockyTLSSession *session,
}
else if (S_ISREG (target.st_mode))
{
- n = gnutls_certificate_set_x509_trust_file (session->gnutls_cert_cred,
- ca_path, GNUTLS_X509_FMT_PEM);
+ certs = g_tls_certificate_list_new_from_file (ca_path, NULL);
+ n += g_list_length (certs);
+ cas = g_list_concat (cas, certs);
DEBUG ("+ %s: %d certs from file", ca_path, n);
}
+ g_object_set_data_full (G_OBJECT (conn), "wocky-ca-list", cas, free_cas);
}
void
wocky_tls_session_add_crl (WockyTLSSession *session, const gchar *crl_path)
{
- int n = 0;
- struct stat target;
-
- DEBUG ("adding CRL CERT path '%s'", (gchar *) crl_path);
-
- if (stat (crl_path, &target) != 0)
- {
- DEBUG ("CRL file '%s': stat failed)", crl_path);
- return;
- }
-
- if (S_ISDIR (target.st_mode))
- {
- DIR *dir;
- struct dirent *entry;
-
- if ((dir = opendir (crl_path)) == NULL)
- return;
-
- for (entry = readdir (dir); entry != NULL; entry = readdir (dir))
- {
- struct stat file;
- gchar *path = g_build_path ("/", crl_path, entry->d_name, NULL);
-
- if ((stat (path, &file) == 0) && S_ISREG (file.st_mode))
- {
- int x = gnutls_certificate_set_x509_crl_file (
- session->gnutls_cert_cred, path, GNUTLS_X509_FMT_PEM);
-
- if (x < 0)
- DEBUG ("Error loading %s: %d %s", path, x, gnutls_strerror (x));
- else
- n += x;
- }
-
- g_free (path);
- }
-
- DEBUG ("+ %s: %d certs from dir", crl_path, n);
- closedir (dir);
- }
- else if (S_ISREG (target.st_mode))
- {
- n = gnutls_certificate_set_x509_trust_file (session->gnutls_cert_cred,
- crl_path, GNUTLS_X509_FMT_PEM);
-
- if (n < 0)
- DEBUG ("Error loading '%s': %d %s", crl_path, n, gnutls_strerror(n));
- else
- DEBUG ("+ %s: %d certs from file", crl_path, n);
- }
-}
-
-/* ************************************************************************* */
-
-void
-wocky_tls_session_handshake_async (WockyTLSSession *session,
- gint io_priority,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- wocky_tls_job_start (&session->handshake_job.job, session,
- io_priority, cancellable, callback, user_data,
- wocky_tls_session_handshake_async);
- wocky_tls_session_try_operation (session, 0);
-}
-
-gboolean
-wocky_tls_session_handshake_finish (WockyTLSSession *session,
- GAsyncResult *result,
- GError **error)
-{
- GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
-
- {
- GObject *source_object;
-
- source_object = g_async_result_get_source_object (result);
- g_object_unref (source_object);
- g_return_val_if_fail (G_OBJECT (session) == source_object, FALSE);
- }
-
- g_return_val_if_fail (wocky_tls_session_handshake_async ==
- g_simple_async_result_get_source_tag (simple), FALSE);
-
- if (g_simple_async_result_propagate_error (simple, error))
- return FALSE;
-
- DEBUG ("connection OK");
- return TRUE;
+ /* DANWFIXME */
}
GPtrArray *
-wocky_tls_session_get_peers_certificate (WockyTLSSession *session,
+wocky_tls_session_get_peers_certificate (GTlsConnection *conn,
WockyTLSCertType *type)
{
- guint idx;
- guint n_peers;
- const gnutls_datum_t *peers = NULL;
+ GTlsCertificate *tlscert;
GPtrArray *certificates;
- peers = gnutls_certificate_get_peers (session->session, &n_peers);
-
- if (peers == NULL)
+ tlscert = g_tls_connection_get_peer_certificate (conn);
+ if (tlscert == NULL)
return NULL;
certificates =
g_ptr_array_new_with_free_func ((GDestroyNotify) g_array_unref);
- for (idx = 0; idx < n_peers; idx++)
+ while (tlscert)
{
- GArray *cert = g_array_sized_new (TRUE, TRUE, sizeof (guchar),
- peers[idx].size);
- g_array_append_vals (cert, peers[idx].data, peers[idx].size);
+ GArray *cert;
+ GByteArray *der_data;
+
+ g_object_get (G_OBJECT (tlscert),
+ "certificate", &der_data,
+ NULL);
+ cert = g_array_sized_new (TRUE, TRUE, sizeof (guchar), der_data->len);
+ g_array_append_vals (cert, der_data->data, der_data->len);
+ g_byte_array_unref (der_data);
g_ptr_array_add (certificates, cert);
}
if (type != NULL)
- {
- switch (gnutls_certificate_type_get (session->session))
- {
- case GNUTLS_CRT_X509:
- *type = WOCKY_TLS_CERT_TYPE_X509;
- break;
- case GNUTLS_CRT_OPENPGP:
- *type = WOCKY_TLS_CERT_TYPE_OPENPGP;
- break;
- default:
- *type = WOCKY_TLS_CERT_TYPE_NONE;
- break;
- }
- }
+ *type = WOCKY_TLS_CERT_TYPE_X509;
return certificates;
}
@@ -776,23 +294,25 @@ wocky_tls_session_verify_peer (WockyTLSSession *session,
{
int rval = -1;
guint peer_cert_status = 0;
- gboolean peer_name_ok = TRUE;
- gnutls_certificate_verify_flags check;
+ GTlsCertificateFlags check;
- /* list gnutls cert error conditions in descending order of noteworthiness *
+ /* list gio cert error conditions in descending order of noteworthiness *
* and map them to wocky cert error conditions */
static const struct
{
- gnutls_certificate_status_t gnutls;
+ GTlsCertificateFlags gio;
WockyTLSCertStatus wocky;
} status_map[] =
- { { GNUTLS_CERT_REVOKED, WOCKY_TLS_CERT_REVOKED },
- { GNUTLS_CERT_NOT_ACTIVATED, WOCKY_TLS_CERT_NOT_ACTIVE },
- { GNUTLS_CERT_EXPIRED, WOCKY_TLS_CERT_EXPIRED },
- { GNUTLS_CERT_SIGNER_NOT_FOUND, WOCKY_TLS_CERT_SIGNER_UNKNOWN },
+ { { G_TLS_CERTIFICATE_BAD_IDENTITY, WOCKY_TLS_CERT_NAME_MISMATCH },
+ { G_TLS_CERTIFICATE_REVOKED, WOCKY_TLS_CERT_REVOKED },
+ { G_TLS_CERTIFICATE_NOT_ACTIVATED,WOCKY_TLS_CERT_NOT_ACTIVE },
+ { G_TLS_CERTIFICATE_EXPIRED, WOCKY_TLS_CERT_EXPIRED },
+ { G_TLS_CERTIFICATE_UNKNOWN_CA, WOCKY_TLS_CERT_SIGNER_UNKNOWN },
+#ifdef DANWFIXME /* does it matter? */
{ GNUTLS_CERT_SIGNER_NOT_CA, WOCKY_TLS_CERT_SIGNER_UNAUTHORISED },
- { GNUTLS_CERT_INSECURE_ALGORITHM, WOCKY_TLS_CERT_INSECURE },
- { GNUTLS_CERT_INVALID, WOCKY_TLS_CERT_INVALID },
+#endif
+ { G_TLS_CERTIFICATE_INSECURE, WOCKY_TLS_CERT_INSECURE },
+ { G_TLS_CERTIFICATE_GENERIC_ERROR,WOCKY_TLS_CERT_INVALID },
{ ~((long) 0), WOCKY_TLS_CERT_UNKNOWN_ERROR },
{ 0, WOCKY_TLS_CERT_OK } };
@@ -816,6 +336,7 @@ wocky_tls_session_verify_peer (WockyTLSSession *session,
break;
}
+#ifdef DANWFIXME
DEBUG ("setting gnutls verify flags level to: %s",
wocky_enum_to_nick (WOCKY_TYPE_TLS_VERIFICATION_LEVEL, level));
gnutls_certificate_set_verify_flags (session->gnutls_cert_cred, check);
@@ -844,679 +365,54 @@ wocky_tls_session_verify_peer (WockyTLSSession *session,
return rval;
}
+#endif
- /* if we get this far, we have a structurally valid certificate *
- * signed by _someone_: check the hostname matches the peername */
- if ((session->peername != NULL && level != WOCKY_TLS_VERIFY_LENIENT)
- || extra_identities != NULL)
- {
- const gnutls_datum_t *peers;
- guint n_peers;
- gnutls_x509_crt_t x509;
- gnutls_openpgp_crt_t opgp;
-
- /* we know these ops must succeed, or verify_peers2 would have *
- * failed before we got here: We just need to duplicate a bit *
- * of what it does: */
- peers = gnutls_certificate_get_peers (session->session, &n_peers);
-
- switch (gnutls_certificate_type_get (session->session))
- {
- case GNUTLS_CRT_X509:
- DEBUG ("checking X509 cert");
- if ((rval = gnutls_x509_crt_init (&x509)) == GNUTLS_E_SUCCESS)
- {
- gnutls_x509_crt_import (x509, &peers[0], GNUTLS_X509_FMT_DER);
-
- if (peername != NULL)
- {
- if (!cert_names_are_valid (x509))
- {
- rval = 0;
- }
- else
- {
- rval = gnutls_x509_crt_check_hostname (x509, session->peername);
- DEBUG ("gnutls_x509_crt_check_hostname: %s -> %d",
- session->peername, rval);
- }
- }
- else
- {
- rval = 0;
- }
-
- if (rval == 0 && extra_identities != NULL)
- {
- if (!cert_names_are_valid (x509))
- {
- rval = 0;
- }
- else
- {
- gint i;
-
- for (i = 0; extra_identities[i] != NULL; i++)
- {
- rval = gnutls_x509_crt_check_hostname (x509,
- extra_identities[i]);
- DEBUG ("gnutls_x509_crt_check_hostname: %s -> %d",
- extra_identities[i], rval);
-
- if (rval != 0)
- break;
- }
- }
- }
-
- rval = (rval == 0) ? -1 : GNUTLS_E_SUCCESS;
-
- gnutls_x509_crt_deinit (x509);
- }
- break;
- case GNUTLS_CRT_OPENPGP:
- DEBUG ("checking PGP cert");
- if ((rval = gnutls_openpgp_crt_init (&opgp)) == GNUTLS_E_SUCCESS)
- {
- gnutls_openpgp_crt_import (opgp, &peers[0], GNUTLS_OPENPGP_FMT_RAW);
-
- if (session->peername != NULL)
- {
- rval = gnutls_openpgp_crt_check_hostname (opgp, session->peername);
- DEBUG ("gnutls_openpgp_crt_check_hostname: %s -> %d",
- session->peername, rval);
- }
- else
- {
- rval = 0;
- }
-
- if (rval == 0 && extra_identities != NULL)
- {
- gint i;
-
- for (i = 0; extra_identities[i] != NULL; i++)
- {
- rval = gnutls_openpgp_crt_check_hostname (opgp,
- extra_identities[i]);
- DEBUG ("gnutls_openpgp_crt_check_hostname: %s -> %d",
- extra_identities[i], rval);
-
- if (rval != 0)
- break;
- }
- }
-
- rval = (rval == 0) ? -1 : GNUTLS_E_SUCCESS;
-
- gnutls_openpgp_crt_deinit (opgp);
- }
- break;
- default:
- /* theoretically, this can't happen if ...verify_peers2 is working: */
- DEBUG ("unknown cert type!");
- rval = GNUTLS_E_INVALID_REQUEST;
- }
- peer_name_ok = (rval == GNUTLS_E_SUCCESS);
+ peer_cert_status = g_tls_connection_get_peer_certificate_errors (G_TLS_CONNECTION (session));
+ if (check & G_TLS_CERTIFICATE_UNKNOWN_CA)
+ {
+ GTlsCertificate *peer = g_tls_connection_get_peer_certificate (G_TLS_CONNECTION (session));
+ GList *cas = g_object_get_data (G_OBJECT (session), "wocky-ca-list"), *c;
+ GTlsCertificateFlags flags;
+
+ for (c = cas; c; c = c->next)
+ {
+ flags = g_tls_certificate_verify (peer, NULL, c->data);
+ if (flags == 0)
+ {
+ peer_cert_status &= ~G_TLS_CERTIFICATE_UNKNOWN_CA;
+ break;
+ }
+ else if (flags & G_TLS_CERTIFICATE_GENERIC_ERROR)
+ {
+ peer_cert_status = flags;
+ break;
+ }
+ }
}
- DEBUG ("peer_name_ok: %d", peer_name_ok );
-
- /* if the hostname didn't match, we can just bail out with an error here *
- * otherwise we need to figure out which error (if any) our verification *
- * call failed with: */
- if (!peer_name_ok)
- *status = WOCKY_TLS_CERT_NAME_MISMATCH;
- else
- { /* Gnutls cert checking can return multiple errors bitwise &ed together *
+ if (peer_cert_status & check)
+ { /* gio cert checking can return multiple errors bitwise &ed together *
* but we are realy only interested in the "most important" error: */
int x;
*status = WOCKY_TLS_CERT_OK;
- for (x = 0; status_map[x].gnutls != 0; x++)
+ for (x = 0; status_map[x].gio != 0; x++)
{
- DEBUG ("checking gnutls error %d", status_map[x].gnutls);
- if (peer_cert_status & status_map[x].gnutls)
+ DEBUG ("checking gio error %d", status_map[x].gio);
+ if (_stat & status_map[x].gio)
{
- DEBUG ("gnutls error %d set", status_map[x].gnutls);
+ DEBUG ("gio error %d set", status_map[x].gio);
*status = status_map[x].wocky;
- rval = GNUTLS_E_CERTIFICATE_ERROR;
+ rval = -1;
break;
}
}
}
- return rval;
-}
-
-static gssize
-wocky_tls_input_stream_read (GInputStream *stream,
- void *buffer,
- gsize count,
- GCancellable *cancellable,
- GError **error)
-{
- WockyTLSSession *session = WOCKY_TLS_INPUT_STREAM (stream)->session;
- gssize result;
-
- session->cancellable = cancellable;
- result = gnutls_record_recv (session->session, buffer, count);
- g_assert (result != GNUTLS_E_INTERRUPTED);
- g_assert (result != GNUTLS_E_AGAIN);
- session->cancellable = NULL;
-
- if (session->error != NULL)
- {
- g_assert (result == GNUTLS_E_PULL_ERROR);
- g_propagate_error (error, session->error);
- return -1;
- }
- else if (wocky_tls_set_error (error, result))
- return -1;
-
- return result;
-}
-
-static void
-wocky_tls_input_stream_read_async (GInputStream *stream,
- void *buffer,
- gsize count,
- gint io_priority,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- WockyTLSSession *session = WOCKY_TLS_INPUT_STREAM (stream)->session;
-
- wocky_tls_job_start (&session->read_job.job, stream,
- io_priority, cancellable, callback, user_data,
- wocky_tls_input_stream_read_async);
-
- session->read_job.buffer = buffer;
- session->read_job.count = count;
-
- wocky_tls_session_try_operation (session, WOCKY_TLS_OP_READ);
-}
-
-static gssize
-wocky_tls_input_stream_read_finish (GInputStream *stream,
- GAsyncResult *result,
- GError **error)
-{
- GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
-
- {
- GObject *source_object;
-
- source_object = g_async_result_get_source_object (result);
- g_object_unref (source_object);
- g_return_val_if_fail (G_OBJECT (stream) == source_object, -1);
- }
-
- g_return_val_if_fail (wocky_tls_input_stream_read_async ==
- g_simple_async_result_get_source_tag (simple), -1);
-
- if (g_simple_async_result_propagate_error (simple, error))
- return -1;
-
- return g_simple_async_result_get_op_res_gssize (simple);
-}
-
-static gssize
-wocky_tls_output_stream_write (GOutputStream *stream,
- const void *buffer,
- gsize count,
- GCancellable *cancellable,
- GError **error)
-{
- WockyTLSSession *session = WOCKY_TLS_OUTPUT_STREAM (stream)->session;
- gssize result;
-
- session->cancellable = cancellable;
- result = gnutls_record_send (session->session, buffer, count);
- g_assert (result != GNUTLS_E_INTERRUPTED);
- g_assert (result != GNUTLS_E_AGAIN);
- session->cancellable = NULL;
-
- if (session->error != NULL)
- {
- g_assert (result == GNUTLS_E_PUSH_ERROR);
- g_propagate_error (error, session->error);
- return -1;
- }
- else if (wocky_tls_set_error (error, result))
- return -1;
-
- return result;
-}
-
-static void
-wocky_tls_output_stream_write_async (GOutputStream *stream,
- const void *buffer,
- gsize count,
- gint io_priority,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- WockyTLSSession *session = WOCKY_TLS_OUTPUT_STREAM (stream)->session;
-
- wocky_tls_job_start (&session->write_job.job, stream,
- io_priority, cancellable, callback, user_data,
- wocky_tls_output_stream_write_async);
-
- session->write_job.buffer = buffer;
- session->write_job.count = count;
-
- wocky_tls_session_try_operation (session, WOCKY_TLS_OP_WRITE);
-}
-
-static gssize
-wocky_tls_output_stream_write_finish (GOutputStream *stream,
- GAsyncResult *result,
- GError **error)
-{
- GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
-
- {
- GObject *source_object;
-
- source_object = g_async_result_get_source_object (result);
- g_object_unref (source_object);
- g_return_val_if_fail (G_OBJECT (stream) == source_object, -1);
- }
-
- g_return_val_if_fail (wocky_tls_output_stream_write_async ==
- g_simple_async_result_get_source_tag (simple), -1);
-
- if (g_simple_async_result_propagate_error (simple, error))
- return -1;
-
- return g_simple_async_result_get_op_res_gssize (simple);
-}
-
-static void
-wocky_tls_output_stream_init (WockyTLSOutputStream *stream)
-{
-}
-
-static void
-wocky_tls_input_stream_init (WockyTLSInputStream *stream)
-{
-}
-
-static void
-wocky_tls_output_stream_set_property (GObject *object, guint prop_id,
- const GValue *value, GParamSpec *pspec)
-{
- WockyTLSOutputStream *stream = WOCKY_TLS_OUTPUT_STREAM (object);
-
- switch (prop_id)
- {
- case PROP_O_SESSION:
- stream->session = g_value_dup_object (value);
- break;
-
- default:
- g_assert_not_reached ();
- }
-}
-
-static void
-wocky_tls_output_stream_constructed (GObject *object)
-{
- WockyTLSOutputStream *stream = WOCKY_TLS_OUTPUT_STREAM (object);
-
- g_assert (stream->session);
-}
-
-static void
-wocky_tls_output_stream_finalize (GObject *object)
-{
- WockyTLSOutputStream *stream = WOCKY_TLS_OUTPUT_STREAM (object);
-
- g_object_unref (stream->session);
-
- G_OBJECT_CLASS (wocky_tls_output_stream_parent_class)
- ->finalize (object);
-}
-
-static void
-wocky_tls_output_stream_class_init (GOutputStreamClass *class)
-{
- GObjectClass *obj_class = G_OBJECT_CLASS (class);
-
- class->write_fn = wocky_tls_output_stream_write;
- class->write_async = wocky_tls_output_stream_write_async;
- class->write_finish = wocky_tls_output_stream_write_finish;
- obj_class->set_property = wocky_tls_output_stream_set_property;
- obj_class->constructed = wocky_tls_output_stream_constructed;
- obj_class->finalize = wocky_tls_output_stream_finalize;
-
- g_object_class_install_property (obj_class, PROP_O_SESSION,
- g_param_spec_object ("session", "TLS session",
- "the TLS session object for this stream",
- WOCKY_TYPE_TLS_SESSION, G_PARAM_WRITABLE |
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-}
-
-static void
-wocky_tls_input_stream_set_property (GObject *object, guint prop_id,
- const GValue *value, GParamSpec *pspec)
-{
- WockyTLSInputStream *stream = WOCKY_TLS_INPUT_STREAM (object);
-
- switch (prop_id)
- {
- case PROP_I_SESSION:
- stream->session = g_value_dup_object (value);
- break;
-
- default:
- g_assert_not_reached ();
- }
-}
-
-static void
-wocky_tls_input_stream_constructed (GObject *object)
-{
- WockyTLSInputStream *stream = WOCKY_TLS_INPUT_STREAM (object);
-
- g_assert (stream->session);
-}
-
-static void
-wocky_tls_input_stream_finalize (GObject *object)
-{
- WockyTLSInputStream *stream = WOCKY_TLS_INPUT_STREAM (object);
-
- g_object_unref (stream->session);
-
- G_OBJECT_CLASS (wocky_tls_input_stream_parent_class)
- ->finalize (object);
-}
-
-static void
-wocky_tls_input_stream_class_init (GInputStreamClass *class)
-{
- GObjectClass *obj_class = G_OBJECT_CLASS (class);
-
- class->read_fn = wocky_tls_input_stream_read;
- class->read_async = wocky_tls_input_stream_read_async;
- class->read_finish = wocky_tls_input_stream_read_finish;
- obj_class->set_property = wocky_tls_input_stream_set_property;
- obj_class->constructed = wocky_tls_input_stream_constructed;
- obj_class->finalize = wocky_tls_input_stream_finalize;
-
- g_object_class_install_property (obj_class, PROP_I_SESSION,
- g_param_spec_object ("session", "TLS session",
- "the TLS session object for this stream",
- WOCKY_TYPE_TLS_SESSION, G_PARAM_WRITABLE |
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-}
-
-static void
-wocky_tls_session_read_ready (GObject *object,
- GAsyncResult *result,
- gpointer user_data)
-{
- WockyTLSSession *session = WOCKY_TLS_SESSION (user_data);
-
- g_assert (session->read_op.state == WOCKY_TLS_OP_STATE_ACTIVE);
-
- session->read_op.result =
- g_input_stream_read_finish (G_INPUT_STREAM (object), result,
- &session->read_op.error);
- session->read_op.state = WOCKY_TLS_OP_STATE_DONE;
-
- /* don't recurse if the async handler is already running */
- if (!session->async)
- wocky_tls_session_try_operation (session, WOCKY_TLS_OP_READ);
-}
-
-static void
-wocky_tls_session_write_ready (GObject *object,
- GAsyncResult *result,
- gpointer user_data)
-{
- WockyTLSSession *session = WOCKY_TLS_SESSION (user_data);
- gssize ret;
-
- g_assert (session->write_op.state == WOCKY_TLS_OP_STATE_ACTIVE);
-
- ret = g_output_stream_write_finish (G_OUTPUT_STREAM (object), result,
- &session->write_op.error);
- if (ret > 0)
- {
- session->write_op.result += ret;
-
- if (session->write_op.result < session->write_op.requested)
- {
- GOutputStream *stream;
- WockyTLSJob *active_job;
-
- stream = g_io_stream_get_output_stream (session->stream);
-
- if (session->handshake_job.job.active)
- active_job = &session->handshake_job.job;
- else
- active_job = &session->write_job.job;
-
- g_output_stream_write_async (stream,
- session->write_op.buffer + session->write_op.result,
- session->write_op.requested - session->write_op.result,
- active_job->io_priority,
- active_job->cancellable,
- wocky_tls_session_write_ready,
- session);
- return;
- }
- }
- else
- {
- /* Error or EOF, we're done */
- session->write_op.result = ret;
- }
-
- session->write_op.state = WOCKY_TLS_OP_STATE_DONE;
-
- /* don't recurse if the async handler is already running */
- if (!session->async)
- wocky_tls_session_try_operation (session, WOCKY_TLS_OP_WRITE);
-}
-
-static ssize_t
-wocky_tls_session_push_func (gpointer user_data,
- const void *buffer,
- size_t count)
-{
- WockyTLSSession *session = WOCKY_TLS_SESSION (user_data);
- GOutputStream *stream;
-
- stream = g_io_stream_get_output_stream (session->stream);
-
- if (session->async)
- {
- WockyTLSJob *active_job;
-
- g_assert (session->handshake_job.job.active ||
- session->write_job.job.active);
-
- if (session->handshake_job.job.active)
- active_job = &session->handshake_job.job;
- else
- active_job = &session->write_job.job;
-
- g_assert (active_job->active);
-
- if (session->write_op.state == WOCKY_TLS_OP_STATE_IDLE)
- {
- session->write_op.state = WOCKY_TLS_OP_STATE_ACTIVE;
- session->write_op.buffer = g_memdup (buffer, count);
- session->write_op.requested = count;
- session->write_op.error = NULL;
- session->write_op.result = 0;
-
- g_output_stream_write_async (stream,
- session->write_op.buffer,
- session->write_op.requested,
- active_job->io_priority,
- active_job->cancellable,
- wocky_tls_session_write_ready,
- session);
-
- if G_UNLIKELY (session->write_op.state != WOCKY_TLS_OP_STATE_ACTIVE)
- g_warning ("The underlying stream '%s' used by the WockyTLSSession "
- "called the GAsyncResultCallback recursively. This "
- "is an error in the underlying implementation: in "
- "some cases it may lead to unbounded recursion. "
- "Result callbacks should always be dispatched from "
- "the mainloop.",
- G_OBJECT_TYPE_NAME (stream));
- }
-
- g_assert (session->write_op.state != WOCKY_TLS_OP_STATE_IDLE);
- g_assert_cmpint (session->write_op.requested, ==, count);
- g_assert (memcmp (session->write_op.buffer, buffer, count) == 0);
-
- if (session->write_op.state == WOCKY_TLS_OP_STATE_DONE)
- {
- session->write_op.state = WOCKY_TLS_OP_STATE_IDLE;
- g_free (session->write_op.buffer);
-
- if (session->write_op.result < 0)
- {
- active_job->error = session->write_op.error;
- gnutls_transport_set_errno (session->session, EIO);
-
- return -1;
- }
- else
- {
- g_assert_cmpint (session->write_op.result, <=, count);
-
- return session->write_op.result;
- }
- }
-
- gnutls_transport_set_errno (session->session, EAGAIN);
-
- return -1;
- }
- else
- {
- gssize result;
-
- result = g_output_stream_write (stream, buffer, count,
- session->cancellable,
- &session->error);
-
- if (result < 0)
- gnutls_transport_set_errno (session->session, EIO);
-
- return result;
- }
-}
-
-static ssize_t
-wocky_tls_session_pull_func (gpointer user_data,
- void *buffer,
- size_t count)
-{
- WockyTLSSession *session = WOCKY_TLS_SESSION (user_data);
- GInputStream *stream;
-
- stream = g_io_stream_get_input_stream (session->stream);
-
- if (session->async)
- {
- WockyTLSJob *active_job;
-
- g_assert (session->handshake_job.job.active ||
- session->read_job.job.active);
-
- if (session->handshake_job.job.active)
- active_job = &session->handshake_job.job;
- else
- active_job = &session->read_job.job;
-
- g_assert (active_job->active);
-
- if (session->read_op.state == WOCKY_TLS_OP_STATE_IDLE)
- {
- session->read_op.state = WOCKY_TLS_OP_STATE_ACTIVE;
- session->read_op.buffer = g_malloc (count);
- session->read_op.requested = count;
- session->read_op.error = NULL;
-
- g_input_stream_read_async (stream,
- session->read_op.buffer,
- session->read_op.requested,
- active_job->io_priority,
- active_job->cancellable,
- wocky_tls_session_read_ready,
- session);
-
- if G_UNLIKELY (session->read_op.state != WOCKY_TLS_OP_STATE_ACTIVE)
- g_warning ("The underlying stream '%s' used by the WockyTLSSession "
- "called the GAsyncResultCallback recursively. This "
- "is an error in the underlying implementation: in "
- "some cases it may lead to unbounded recursion. "
- "Result callbacks should always be dispatched from "
- "the mainloop.",
- G_OBJECT_TYPE_NAME (stream));
- }
-
- g_assert (session->read_op.state != WOCKY_TLS_OP_STATE_IDLE);
- g_assert_cmpint (session->read_op.requested, ==, count);
-
- if (session->read_op.state == WOCKY_TLS_OP_STATE_DONE)
- {
- session->read_op.state = WOCKY_TLS_OP_STATE_IDLE;
-
- if (session->read_op.result < 0)
- {
- g_free (session->read_op.buffer);
- session->read_op.buffer = NULL;
- active_job->error = session->read_op.error;
- gnutls_transport_set_errno (session->session, EIO);
-
- return -1;
- }
- else
- {
- g_assert_cmpint (session->read_op.result, <=, count);
-
- memcpy (buffer,
- session->read_op.buffer,
- session->read_op.result);
- g_free (session->read_op.buffer);
- session->read_op.buffer = NULL;
-
- return session->read_op.result;
- }
- }
-
- gnutls_transport_set_errno (session->session, EAGAIN);
-
- return -1;
- }
- else
- {
- gssize result;
-
- result = g_input_stream_read (stream, buffer, count,
- session->cancellable,
- &session->error);
- if (result < 0)
- gnutls_transport_set_errno (session->session, EIO);
-
- return result;
- }
+ return 0;
}
+#ifdef DANWFIXME
static void
tls_debug (int level,
const char *msg)
@@ -1524,316 +420,42 @@ tls_debug (int level,
DEBUG ("[%d] [%02d] %s", getpid(), level, msg);
}
-static void
-wocky_tls_session_init (WockyTLSSession *session)
-{
- const char *level;
- guint64 lvl = 0;
- static gsize initialised;
-
- if G_UNLIKELY (g_once_init_enter (&initialised))
- {
- gnutls_global_init ();
- gnutls_global_set_log_function (tls_debug);
- g_once_init_leave (&initialised, 1);
- }
-
- if ((level = g_getenv ("WOCKY_TLS_DEBUG_LEVEL")) != NULL)
- lvl = g_ascii_strtoull (level, NULL, 10);
-
- tls_debug_level = lvl;
- gnutls_global_set_log_level (lvl);
-}
-
-static void
-wocky_tls_session_set_property (GObject *object, guint prop_id,
- const GValue *value, GParamSpec *pspec)
-{
- WockyTLSSession *session = WOCKY_TLS_SESSION (object);
-
- switch (prop_id)
- {
- case PROP_S_STREAM:
- session->stream = g_value_dup_object (value);
- break;
- case PROP_S_PEERNAME:
- session->peername = g_value_dup_string (value);
- break;
- case PROP_S_SERVER:
- session->server = g_value_get_boolean (value);
- break;
- case PROP_S_DHBITS:
- session->dh_bits = g_value_get_uint (value);
- break;
- case PROP_S_KEYFILE:
- session->key_file = g_value_dup_string (value);
- break;
- case PROP_S_CERTFILE:
- session->cert_file = g_value_dup_string (value);
- break;
- default:
- g_assert_not_reached ();
- }
-}
-
-static void
-wocky_tls_session_get_property (GObject *object, guint prop_id,
- GValue *value, GParamSpec *pspec)
-{
- WockyTLSSession *session = WOCKY_TLS_SESSION (object);
-
- switch (prop_id)
- {
- case PROP_S_PEERNAME:
- g_value_set_string (value, session->peername);
- break;
- default:
- g_assert_not_reached ();
- }
-}
-
static const char *
tls_options (void)
{
const char *options = g_getenv ("WOCKY_GNUTLS_OPTIONS");
return (options != NULL && *options != '\0') ? options : DEFAULT_TLS_OPTIONS;
}
+#endif
-static void
-wocky_tls_session_constructed (GObject *object)
-{
- WockyTLSSession *session = WOCKY_TLS_SESSION (object);
-
- gboolean server = session->server;
- gint code;
- const gchar *opt = tls_options ();
- const gchar *pos = NULL;
-
- /* gnutls_handshake_set_private_extensions (session->session, 1); */
- gnutls_certificate_allocate_credentials (&(session->gnutls_cert_cred));
-
- /* I think this all needs to be done per connection: conceivably
- the DH parameters could be moved to the global section above,
- but IANA cryptographer */
- if (server)
- {
- gnutls_dh_params_t *dhp;
-
- if ((session->key_file != NULL) && (session->cert_file != NULL))
- {
- DEBUG ("cert/key pair: %s/%s", session->cert_file, session->key_file);
- gnutls_certificate_set_x509_key_file (session->gnutls_cert_cred,
- session->cert_file,
- session->key_file,
- GNUTLS_X509_FMT_PEM);
- }
-
- switch (session->dh_bits)
- {
- case 768:
- dhp = &dh_0768;
- break;
- case 1024:
- dhp = &dh_1024;
- break;
- case 2048:
- dhp = &dh_2048;
- break;
- case 3072:
- dhp = &dh_3072;
- break;
- case 4096:
- dhp = &dh_4096;
- break;
- default:
- dhp = &dh_1024;
- break;
- }
-
- if (*dhp == NULL)
- {
- DEBUG ("Initialising DH parameters (%d bits)", session->dh_bits);
- gnutls_dh_params_init (dhp);
- gnutls_dh_params_generate2 (*dhp, session->dh_bits);
- }
-
- session->dh_params = *dhp;
- gnutls_certificate_set_dh_params (session->gnutls_cert_cred, *dhp);
- gnutls_init (&session->session, GNUTLS_SERVER);
- }
- else
- gnutls_init (&session->session, GNUTLS_CLIENT);
-
- code = gnutls_priority_set_direct (session->session, opt, &pos);
- if (code != GNUTLS_E_SUCCESS)
- {
- DEBUG ("could not set priority string: %s", error_to_string (code));
- DEBUG (" '%s'", opt);
- if (pos >= opt)
- DEBUG (" %*s^", (int) (pos - opt), "");
- }
- else
- {
- DEBUG ("priority set to: '%s'", opt);
- }
-
- code = gnutls_credentials_set (session->session,
- GNUTLS_CRD_CERTIFICATE,
- session->gnutls_cert_cred);
- if (code != GNUTLS_E_SUCCESS)
- DEBUG ("could not set credentials: %s", error_to_string (code));
-
- gnutls_transport_set_push_function (session->session,
- wocky_tls_session_push_func);
- gnutls_transport_set_pull_function (session->session,
- wocky_tls_session_pull_func);
- gnutls_transport_set_ptr (session->session, session);
-
- g_assert (session->stream);
-}
-
-static void
-wocky_tls_session_finalize (GObject *object)
-{
- WockyTLSSession *session = WOCKY_TLS_SESSION (object);
-
- if (session->input != NULL)
- g_object_unref (session->input);
-
- if (session->output != NULL)
- g_object_unref (session->output);
-
- gnutls_deinit (session->session);
- gnutls_certificate_free_credentials (session->gnutls_cert_cred);
- g_object_unref (session->stream);
-
- G_OBJECT_CLASS (wocky_tls_session_parent_class)
- ->finalize (object);
-}
-
-static void
-wocky_tls_session_dispose (GObject *object)
-{
- WockyTLSSession *session = WOCKY_TLS_SESSION (object);
-
- g_free (session->peername);
- session->peername = NULL;
-
- g_free (session->key_file);
- session->key_file = NULL;
-
- g_free (session->cert_file);
- session->cert_file = NULL;
-
- g_free (session->read_op.buffer);
- session->read_op.buffer = NULL;
-
- G_OBJECT_CLASS (wocky_tls_session_parent_class)->dispose (object);
-}
-
-static gboolean
-wocky_tls_session_close (GIOStream *stream,
- GCancellable *cancellable,
- GError **error)
-{
- WockyTLSSession *session = WOCKY_TLS_SESSION (stream);
-
- return g_io_stream_close (session->stream, cancellable, error);
-}
-
-static GInputStream *
-wocky_tls_session_get_input_stream (GIOStream *io_stream)
+WockyTLSSession *
+wocky_tls_session_new (GIOStream *stream,
+ const char *peername)
{
- WockyTLSSession *session = WOCKY_TLS_SESSION (io_stream);
+ GTlsClientConnection *conn;
+ GSocketConnectable *peer;
- if (session->input == NULL)
- session->input = g_object_new (WOCKY_TYPE_TLS_INPUT_STREAM,
- "session", session,
- NULL);
+ peer = peername ? g_network_address_new (peername, 0) : NULL;
+ conn = g_tls_client_connection_new (stream, peer, NULL);
+ if (peer)
+ g_object_unref (peer);
- return (GInputStream *)session->input;
-}
+ if (!conn)
+ return NULL;
-static GOutputStream *
-wocky_tls_session_get_output_stream (GIOStream *io_stream)
-{
- WockyTLSSession *session = WOCKY_TLS_SESSION (io_stream);
+ g_object_set (G_OBJECT (conn),
- if (session->output == NULL)
- session->output = g_object_new (WOCKY_TYPE_TLS_OUTPUT_STREAM,
- "session", session,
- NULL);
+ /* FIXME: just use the system certdb rather than
+ * reimplementing it ourselves.
+ */
+ "use-system-certdb", FALSE,
- return (GOutputStream *)session->output;
-}
+ /* Accept everything; we'll check it afterwards */
+ "validation-flags", 0,
-static void
-wocky_tls_session_class_init (WockyTLSSessionClass *class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (class);
- GIOStreamClass *stream_class = G_IO_STREAM_CLASS (class);
-
- object_class->get_property = wocky_tls_session_get_property;
- object_class->set_property = wocky_tls_session_set_property;
- object_class->constructed = wocky_tls_session_constructed;
- object_class->finalize = wocky_tls_session_finalize;
- object_class->dispose = wocky_tls_session_dispose;
-
- stream_class->get_input_stream = wocky_tls_session_get_input_stream;
- stream_class->get_output_stream = wocky_tls_session_get_output_stream;
- stream_class->close_fn = wocky_tls_session_close;
-
- g_object_class_install_property (object_class, PROP_S_STREAM,
- g_param_spec_object ("base-stream", "base stream",
- "the stream that TLS communicates over",
- G_TYPE_IO_STREAM, G_PARAM_WRITABLE |
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- g_object_class_install_property (object_class, PROP_S_PEERNAME,
- g_param_spec_string ("peername", "peer name",
- "Peer host/domain name",
- NULL, G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- g_object_class_install_property (object_class, PROP_S_SERVER,
- g_param_spec_boolean ("server", "server",
- "whether this is a server",
- FALSE, G_PARAM_WRITABLE |
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- g_object_class_install_property (object_class, PROP_S_DHBITS,
- g_param_spec_uint ("dh-bits", "Diffie-Hellman bits",
- "Diffie-Hellmann bits: 768, 1024, 2048, 3072 0r 4096",
- 768, 4096, 1024, G_PARAM_WRITABLE |
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- g_object_class_install_property (object_class, PROP_S_KEYFILE,
- g_param_spec_string ("x509-key", "x509 key",
- "x509 PEM key file",
- NULL, G_PARAM_WRITABLE |
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- g_object_class_install_property (object_class, PROP_S_CERTFILE,
- g_param_spec_string ("x509-cert", "x509 certificate",
- "x509 PEM certificate file",
- NULL, G_PARAM_WRITABLE |
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-}
+ NULL);
-WockyTLSSession *
-wocky_tls_session_new (GIOStream *stream,
- const gchar *peername)
-{
- return g_object_new (WOCKY_TYPE_TLS_SESSION,
- "base-stream", stream,
- "peername", peername,
- "server", FALSE, NULL);
+ return WOCKY_TLS_SESSION (conn);
}
/**
@@ -1851,15 +473,18 @@ WockyTLSSession *
wocky_tls_session_server_new (GIOStream *stream, guint dhbits,
const gchar* key, const gchar* cert)
{
- if (dhbits == 0)
- dhbits = 1024;
- return g_object_new (WOCKY_TYPE_TLS_SESSION, "base-stream", stream,
- "dh-bits", dhbits, "x509-key", key, "x509-cert", cert,
- "server", TRUE,
- NULL);
-}
+ GTlsServerConnection *conn;
+ GTlsCertificate *tlscert;
+
+ /* DANWFIXME: dhbits */
-/* this file is "borrowed" from an unmerged gnio feature: */
-/* Local Variables: */
-/* c-file-style: "gnu" */
-/* End: */
+ if (key && cert)
+ tlscert = g_tls_certificate_new_from_files (cert, key, NULL);
+ else
+ tlscert = NULL;
+ conn = g_tls_server_connection_new (stream, tlscert, NULL);
+ if (tlscert)
+ g_object_unref (tlscert);
+
+ return WOCKY_TLS_SESSION (conn);
+}
diff --git a/wocky/wocky-tls.h b/wocky/wocky-tls.h
index 753582b..e80489f 100644
--- a/wocky/wocky-tls.h
+++ b/wocky/wocky-tls.h
@@ -33,11 +33,10 @@
#include "wocky-enumtypes.h"
-#define WOCKY_TYPE_TLS_SESSION (wocky_tls_session_get_type ())
-#define WOCKY_TLS_SESSION(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \
- WOCKY_TYPE_TLS_SESSION, WockyTLSSession))
+#define WOCKY_TYPE_TLS_SESSION G_TYPE_TLS_CONNECTION
+#define WOCKY_TLS_SESSION(inst) G_TLS_CONNECTION(inst)
-typedef struct _WockyTLSSession WockyTLSSession;
+typedef GTlsConnection WockyTLSSession;
typedef enum
{
@@ -73,11 +72,9 @@ typedef enum
{
WOCKY_TLS_CERT_TYPE_NONE = 0,
WOCKY_TLS_CERT_TYPE_X509,
- WOCKY_TLS_CERT_TYPE_OPENPGP,
+ WOCKY_TLS_CERT_TYPE_OPENPGP, /* DANWFIXME: unused */
} WockyTLSCertType;
-GType wocky_tls_session_get_type (void);
-
int wocky_tls_session_verify_peer (WockyTLSSession *session,
GStrv extra_identities,
WockyTLSVerificationLevel level,
@@ -85,19 +82,9 @@ int wocky_tls_session_verify_peer (WockyTLSSession *session,
GPtrArray *wocky_tls_session_get_peers_certificate (WockyTLSSession *session,
WockyTLSCertType *type);
-gboolean wocky_tls_session_handshake (WockyTLSSession *session,
- GCancellable *cancellable,
- GError **error);
-void
-wocky_tls_session_handshake_async (WockyTLSSession *session,
- gint io_priority,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-gboolean
-wocky_tls_session_handshake_finish (WockyTLSSession *session,
- GAsyncResult *result,
- GError **error);
+#define wocky_tls_session_handshake g_tls_connection_handshake
+#define wocky_tls_session_handshake_async g_tls_connection_handshake_async
+#define wocky_tls_session_handshake_finish g_tls_connection_handshake_finish
void wocky_tls_session_add_ca (WockyTLSSession *session, const gchar *path);
void wocky_tls_session_add_crl (WockyTLSSession *session, const gchar *path);
@@ -109,9 +96,5 @@ WockyTLSSession *wocky_tls_session_server_new (GIOStream *stream,
guint dhbits,
const gchar* key,
const gchar* cert);
-#endif /* _wocky_tls_h_ */
-/* this file is "borrowed" from an unmerged gnio feature: */
-/* Local Variables: */
-/* c-file-style: "gnu" */
-/* End: */
+#endif /* _wocky_tls_h_ */