[glib-networking/nss] nss: the start of an NSS-based GTlsBackend
- From: Dan Winship <danw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib-networking/nss] nss: the start of an NSS-based GTlsBackend
- Date: Wed, 12 Oct 2011 19:03:07 +0000 (UTC)
commit b0231a6a9f8de5e832e895e1e30d865d866b5822
Author: Dan Winship <danw gnome org>
Date: Thu Sep 29 10:54:00 2011 -0400
nss: the start of an NSS-based GTlsBackend
At the moment it passes tls/tests/certificate, meaning
GTlsCertificate, GTlsDatabase, and GTlsFileDatabase are more or less
working (though without any support for private keys or PKCS#11
callbacks). GTlsConnection and associated classes are just stubs right
now though.
.gitignore | 4 +-
Makefile.am | 4 +
configure.ac | 22 ++-
tls/nss/Makefile.am | 33 ++
tls/nss/gtlsbackend-nss.c | 111 +++++++
tls/nss/gtlsbackend-nss.h | 52 +++
tls/nss/gtlscertificate-nss.c | 621 ++++++++++++++++++++++++++++++++++++
tls/nss/gtlscertificate-nss.h | 61 ++++
tls/nss/gtlsclientconnection-nss.c | 162 ++++++++++
tls/nss/gtlsclientconnection-nss.h | 46 +++
tls/nss/gtlsconnection-nss.c | 365 +++++++++++++++++++++
tls/nss/gtlsconnection-nss.h | 48 +++
tls/nss/gtlsdatabase-nss.c | 283 ++++++++++++++++
tls/nss/gtlsdatabase-nss.h | 60 ++++
tls/nss/gtlsfiledatabase-nss.c | 318 ++++++++++++++++++
tls/nss/gtlsfiledatabase-nss.h | 51 +++
tls/nss/gtlsinputstream-nss.c | 147 +++++++++
tls/nss/gtlsinputstream-nss.h | 48 +++
tls/nss/gtlsoutputstream-nss.c | 147 +++++++++
tls/nss/gtlsoutputstream-nss.h | 48 +++
tls/nss/gtlsserverconnection-nss.c | 105 ++++++
tls/nss/gtlsserverconnection-nss.h | 47 +++
tls/nss/nss-module.c | 47 +++
tls/tests/Makefile.am | 20 +-
tls/tests/certificate.c | 34 ++-
tls/tests/connection.c | 5 +-
26 files changed, 2871 insertions(+), 18 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index 8806e90..e71bdbd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -34,5 +34,5 @@ proxy/libproxy/glib-pacrunner
proxy/libproxy/org.gtk.GLib.PACRunner.service
proxy/tests/gnome
-/tls/tests/certificate
-/tls/tests/connection
+/tls/tests/certificate-*
+/tls/tests/connection-*
diff --git a/Makefile.am b/Makefile.am
index 0a55026..71d5116 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -19,6 +19,10 @@ if HAVE_GNUTLS
SUBDIRS += tls/gnutls
endif
+if HAVE_NSS
+SUBDIRS += tls/nss
+endif
+
SUBDIRS += tls/tests
install-exec-hook:
diff --git a/configure.ac b/configure.ac
index b7833d4..02316b0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -124,6 +124,25 @@ if test "x$with_gnutls" = "xyes"; then
fi
fi
+dnl **********************
+dnl *** Checks for NSS ***
+dnl **********************
+
+AC_ARG_WITH(nss,
+ [AC_HELP_STRING([--with-nss],
+ [support for NSS @<:@default=check@:>@])],
+ [],
+ [with_nss=check])
+AS_IF([test "$with_nss" != "no"],
+ [PKG_CHECK_MODULES(NSS, [nss],
+ [with_nss=yes
+ tls_support="nss $tls_support"],
+ [AS_IF([test "x$with_nss" = "xyes"],
+ [AC_MSG_FAILURE("$NSS_PKG_ERRORS")])])])
+AM_CONDITIONAL(HAVE_NSS, [test "$with_nss" = "yes"])
+AC_SUBST(NSS_CFLAGS)
+AC_SUBST(NSS_LIBS)
+
dnl *************************************
dnl *** Warnings to show if using GCC ***
dnl *************************************
@@ -220,6 +239,7 @@ AC_CONFIG_FILES([Makefile
proxy/gnome/Makefile
proxy/tests/Makefile
tls/gnutls/Makefile
+ tls/nss/Makefile
tls/tests/Makefile
])
AC_OUTPUT
@@ -227,7 +247,7 @@ AC_OUTPUT
echo ""
echo " Proxy support: ${proxy_support:-no}"
echo " TLS support: ${tls_support:-no}"
-if test "$tls_support" != "no"; then
+if test "$with_gnutls" = "yes"; then
echo " TLS CA file: ${with_ca_certificates:-(none)}"
if test -n "$with_ca_certificates"; then
if ! test -f "$with_ca_certificates"; then
diff --git a/tls/nss/Makefile.am b/tls/nss/Makefile.am
new file mode 100644
index 0000000..26ab41d
--- /dev/null
+++ b/tls/nss/Makefile.am
@@ -0,0 +1,33 @@
+include $(top_srcdir)/Makefile.decl
+
+giomodule_LTLIBRARIES = libgionss.la
+
+libgionss_la_SOURCES = \
+ nss-module.c \
+ gtlsbackend-nss.c \
+ gtlsbackend-nss.h \
+ gtlscertificate-nss.c \
+ gtlscertificate-nss.h \
+ gtlsclientconnection-nss.c \
+ gtlsclientconnection-nss.h \
+ gtlsconnection-nss.c \
+ gtlsconnection-nss.h \
+ gtlsdatabase-nss.c \
+ gtlsdatabase-nss.h \
+ gtlsfiledatabase-nss.c \
+ gtlsfiledatabase-nss.h \
+ gtlsinputstream-nss.c \
+ gtlsinputstream-nss.h \
+ gtlsoutputstream-nss.c \
+ gtlsoutputstream-nss.h \
+ gtlsserverconnection-nss.c \
+ gtlsserverconnection-nss.h \
+ $(NULL)
+
+INCLUDES += $(NSS_CFLAGS)
+
+libgionss_la_LDFLAGS = $(module_flags)
+libgionss_la_LIBADD = \
+ $(GLIB_LIBS) \
+ $(NSS_LIBS) \
+ $(NULL)
diff --git a/tls/nss/gtlsbackend-nss.c b/tls/nss/gtlsbackend-nss.c
new file mode 100644
index 0000000..47157fd
--- /dev/null
+++ b/tls/nss/gtlsbackend-nss.c
@@ -0,0 +1,111 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright 2011 Red Hat, Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include "glib.h"
+
+#include <errno.h>
+
+#include <nss.h>
+
+#include "gtlsbackend-nss.h"
+#include "gtlscertificate-nss.h"
+#include "gtlsclientconnection-nss.h"
+#include "gtlsfiledatabase-nss.h"
+#include "gtlsserverconnection-nss.h"
+
+GTlsDatabaseNss *g_tls_backend_nss_default_database;
+CERTCertDBHandle *g_tls_backend_nss_certdbhandle;
+
+struct _GTlsBackendNssPrivate
+{
+ NSSInitContext *context;
+};
+
+static void g_tls_backend_nss_interface_init (GTlsBackendInterface *iface);
+
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (GTlsBackendNss, g_tls_backend_nss, G_TYPE_OBJECT, 0,
+ G_IMPLEMENT_INTERFACE_DYNAMIC (G_TYPE_TLS_BACKEND,
+ g_tls_backend_nss_interface_init);)
+
+static void
+g_tls_backend_nss_init (GTlsBackendNss *backend)
+{
+ backend->priv = G_TYPE_INSTANCE_GET_PRIVATE (backend, G_TYPE_TLS_BACKEND_NSS, GTlsBackendNssPrivate);
+
+ backend->priv->context = NSS_InitContext ("sql:/etc/pki/nssdb", "", "",
+ SECMOD_DB, NULL, 0);
+
+ g_tls_backend_nss_certdbhandle = CERT_GetDefaultCertDB ();
+ if (!g_tls_backend_nss_default_database)
+ g_tls_backend_nss_default_database = g_object_new (G_TYPE_TLS_DATABASE_NSS, NULL);
+}
+
+static void
+g_tls_backend_nss_finalize (GObject *object)
+{
+ GTlsBackendNss *backend = G_TLS_BACKEND_NSS (object);
+
+ if (backend->priv->context)
+ NSS_ShutdownContext (backend->priv->context);
+
+ G_OBJECT_CLASS (g_tls_backend_nss_parent_class)->finalize (object);
+}
+
+static void
+g_tls_backend_nss_class_init (GTlsBackendNssClass *backend_class)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (backend_class);
+
+ g_type_class_add_private (backend_class, sizeof (GTlsBackendNssPrivate));
+
+ gobject_class->finalize = g_tls_backend_nss_finalize;
+}
+
+static void
+g_tls_backend_nss_class_finalize (GTlsBackendNssClass *backend_class)
+{
+}
+
+static GTlsDatabase *
+g_tls_backend_nss_get_default_database (GTlsBackend *backend)
+{
+ return g_object_ref (g_tls_backend_nss_default_database);
+}
+
+static void
+g_tls_backend_nss_interface_init (GTlsBackendInterface *iface)
+{
+ iface->get_certificate_type = g_tls_certificate_nss_get_type;
+ iface->get_client_connection_type = g_tls_client_connection_nss_get_type;
+ iface->get_server_connection_type = g_tls_server_connection_nss_get_type;
+ iface->get_file_database_type = g_tls_file_database_nss_get_type;
+ iface->get_default_database = g_tls_backend_nss_get_default_database;
+}
+
+void
+g_tls_backend_nss_register (GIOModule *module)
+{
+ g_tls_backend_nss_register_type (G_TYPE_MODULE (module));
+ g_io_extension_point_implement (G_TLS_BACKEND_EXTENSION_POINT_NAME,
+ g_tls_backend_nss_get_type(),
+ "nss",
+ 0);
+}
diff --git a/tls/nss/gtlsbackend-nss.h b/tls/nss/gtlsbackend-nss.h
new file mode 100644
index 0000000..450cacf
--- /dev/null
+++ b/tls/nss/gtlsbackend-nss.h
@@ -0,0 +1,52 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright 2011 Red Hat, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the licence or (at
+ * your option) any later version.
+ *
+ * See the included COPYING file for more information.
+ */
+
+#ifndef __G_TLS_BACKEND_NSS_H__
+#define __G_TLS_BACKEND_NSS_H__
+
+#include <gio/gio.h>
+
+#include "gtlsdatabase-nss.h"
+
+G_BEGIN_DECLS
+
+#define G_TYPE_TLS_BACKEND_NSS (g_tls_backend_nss_get_type ())
+#define G_TLS_BACKEND_NSS(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), G_TYPE_TLS_BACKEND_NSS, GTlsBackendNss))
+#define G_TLS_BACKEND_NSS_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), G_TYPE_TLS_BACKEND_NSS, GTlsBackendNssClass))
+#define G_IS_TLS_BACKEND_NSS(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), G_TYPE_TLS_BACKEND_NSS))
+#define G_IS_TLS_BACKEND_NSS_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), G_TYPE_TLS_BACKEND_NSS))
+#define G_TLS_BACKEND_NSS_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), G_TYPE_TLS_BACKEND_NSS, GTlsBackendNssClass))
+
+typedef struct _GTlsBackendNss GTlsBackendNss;
+typedef struct _GTlsBackendNssClass GTlsBackendNssClass;
+typedef struct _GTlsBackendNssPrivate GTlsBackendNssPrivate;
+
+struct _GTlsBackendNssClass
+{
+ GObjectClass parent_class;
+};
+
+struct _GTlsBackendNss
+{
+ GObject parent_instance;
+ GTlsBackendNssPrivate *priv;
+};
+
+GType g_tls_backend_nss_get_type (void) G_GNUC_CONST;
+void g_tls_backend_nss_register (GIOModule *module);
+
+extern GTlsDatabaseNss *g_tls_backend_nss_default_database;
+extern CERTCertDBHandle *g_tls_backend_nss_certdbhandle;
+
+G_END_DECLS
+
+#endif /* __G_TLS_BACKEND_NSS_H___ */
diff --git a/tls/nss/gtlscertificate-nss.c b/tls/nss/gtlscertificate-nss.c
new file mode 100644
index 0000000..71c1847
--- /dev/null
+++ b/tls/nss/gtlscertificate-nss.c
@@ -0,0 +1,621 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright 2011 Red Hat, Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include "glib.h"
+
+#include <nss.h>
+#include <cert.h>
+#include <keyhi.h>
+#include <secerr.h>
+
+#include "gtlscertificate-nss.h"
+#include "gtlsbackend-nss.h"
+#include "gtlsdatabase-nss.h"
+#include "gtlsfiledatabase-nss.h"
+#include <glib/gi18n-lib.h>
+
+static void g_tls_certificate_nss_initable_iface_init (GInitableIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GTlsCertificateNss, g_tls_certificate_nss, G_TYPE_TLS_CERTIFICATE,
+ G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
+ g_tls_certificate_nss_initable_iface_init);)
+
+enum
+{
+ PROP_0,
+
+ PROP_CERTIFICATE,
+ PROP_CERTIFICATE_PEM,
+ PROP_PRIVATE_KEY,
+ PROP_PRIVATE_KEY_PEM,
+ PROP_ISSUER
+};
+
+struct _GTlsCertificateNssPrivate
+{
+ CERTCertificate *cert;
+ SECKEYPrivateKey *key;
+ gboolean need_private_key;
+
+ GTlsCertificateNss *issuer;
+ gboolean expanded;
+
+ GError *construct_error;
+};
+
+static GObject *
+g_tls_certificate_nss_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GObject *obj;
+ GTlsCertificateNss *nss, *existing;
+
+ obj = G_OBJECT_CLASS (g_tls_certificate_nss_parent_class)->constructor (type, n_construct_properties, construct_properties);
+ nss = G_TLS_CERTIFICATE_NSS (obj);
+
+ /* If it's invalid, return it as-is */
+ if (nss->priv->construct_error || !nss->priv->cert)
+ return obj;
+
+ /* If we already have a GTlsCertificate for this CERTCertificate,
+ * return that instead.
+ */
+ existing = g_tls_database_nss_get_gcert (g_tls_backend_nss_default_database,
+ nss->priv->cert, FALSE);
+ if (existing)
+ {
+ if (nss->priv->cert)
+ {
+ CERT_DestroyCertificate (nss->priv->cert);
+ nss->priv->cert = NULL;
+ }
+ if (nss->priv->key && !existing->priv->key)
+ {
+ existing->priv->key = nss->priv->key;
+ nss->priv->key = NULL;
+ }
+ if (nss->priv->issuer && !existing->priv->issuer)
+ {
+ existing->priv->issuer = nss->priv->issuer;
+ nss->priv->issuer = NULL;
+ }
+
+ g_object_unref (obj);
+ obj = G_OBJECT (existing);
+ }
+ else
+ {
+ g_tls_database_nss_gcert_created (g_tls_backend_nss_default_database,
+ nss->priv->cert, nss);
+ }
+
+ return obj;
+}
+
+static void
+g_tls_certificate_nss_finalize (GObject *object)
+{
+ GTlsCertificateNss *nss = G_TLS_CERTIFICATE_NSS (object);
+
+ if (nss->priv->cert)
+ {
+ g_tls_database_nss_gcert_destroyed (g_tls_backend_nss_default_database,
+ nss->priv->cert);
+ CERT_DestroyCertificate (nss->priv->cert);
+ }
+ if (nss->priv->key)
+ SECKEY_DestroyPrivateKey (nss->priv->key);
+
+ if (nss->priv->issuer)
+ g_object_unref (nss->priv->issuer);
+
+ g_clear_error (&nss->priv->construct_error);
+
+ G_OBJECT_CLASS (g_tls_certificate_nss_parent_class)->finalize (object);
+}
+
+#define PEM_CERTIFICATE_HEADER "-----BEGIN CERTIFICATE-----"
+#define PEM_CERTIFICATE_FOOTER "-----END CERTIFICATE-----"
+#define PEM_PRIVKEY_HEADER "-----BEGIN RSA PRIVATE KEY-----"
+#define PEM_PRIVKEY_FOOTER "-----END RSA PRIVATE KEY-----"
+
+static char *
+encode_pem (const char *header,
+ const char *footer,
+ guint8 *data,
+ gsize length)
+{
+ GString *pem;
+ char *out;
+ int encoded_len, broken_len, full_len;
+ int state = 0, save = 0;
+
+ encoded_len = (length / 3 + 1) * 4;
+ broken_len = encoded_len + (encoded_len / 72) + 1;
+ full_len = strlen (header) + 1 + broken_len + strlen (footer) + 1;
+
+ pem = g_string_sized_new (full_len + 1);
+ g_string_append (pem, header);
+ g_string_append_c (pem, '\n');
+ out = pem->str + pem->len;
+ out += g_base64_encode_step (data, length, TRUE, out, &state, &save);
+ out += g_base64_encode_close (TRUE, out, &state, &save);
+ pem->len = out - pem->str;
+ g_string_append (pem, footer);
+ g_string_append_c (pem, '\n');
+
+ return g_string_free (pem, FALSE);
+}
+
+static void
+g_tls_certificate_nss_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GTlsCertificateNss *nss = G_TLS_CERTIFICATE_NSS (object);
+ CERTCertificate *nss_cert = nss->priv->cert;
+
+ switch (prop_id)
+ {
+ case PROP_CERTIFICATE:
+ if (nss_cert)
+ {
+ GByteArray *certificate;
+
+ certificate = g_byte_array_sized_new (nss_cert->derCert.len);
+ certificate->len = nss_cert->derCert.len;
+ memcpy (certificate->data, nss_cert->derCert.data,
+ nss_cert->derCert.len);
+ g_value_take_boxed (value, certificate);
+ }
+ else
+ g_value_set_boxed (value, NULL);
+ break;
+
+ case PROP_CERTIFICATE_PEM:
+ if (nss_cert)
+ {
+ g_value_take_string (value, encode_pem (PEM_CERTIFICATE_HEADER,
+ PEM_CERTIFICATE_FOOTER,
+ nss_cert->derCert.data,
+ nss_cert->derCert.len));
+ }
+ else
+ g_value_set_string (value, NULL);
+ break;
+
+ case PROP_ISSUER:
+ g_value_set_object (value, nss->priv->issuer);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+g_tls_certificate_nss_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GTlsCertificateNss *nss = G_TLS_CERTIFICATE_NSS (object);
+ GByteArray *bytes;
+ const gchar *string;
+
+ switch (prop_id)
+ {
+ case PROP_CERTIFICATE:
+ bytes = g_value_get_boxed (value);
+ if (!bytes)
+ break;
+ g_return_if_fail (nss->priv->cert == NULL);
+
+ /* Make sure it's really DER */
+ if (!g_strstr_len ((gchar *)bytes->data, bytes->len, "BEGIN CERTIFICATE"))
+ nss->priv->cert = CERT_DecodeCertFromPackage ((gchar *)bytes->data, bytes->len);
+
+ if (!nss->priv->cert && !nss->priv->construct_error)
+ {
+ nss->priv->construct_error =
+ g_error_new (G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
+ _("Could not parse DER certificate"));
+ }
+ break;
+
+ case PROP_CERTIFICATE_PEM:
+ string = g_value_get_string (value);
+ if (!string)
+ break;
+ g_return_if_fail (nss->priv->cert == NULL);
+
+ /* Make sure it's really PEM */
+ if (strstr (string, "BEGIN CERTIFICATE"))
+ nss->priv->cert = CERT_DecodeCertFromPackage ((gchar *)string, strlen (string));
+
+ if (!nss->priv->cert && !nss->priv->construct_error)
+ {
+ nss->priv->construct_error =
+ g_error_new (G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
+ _("Could not parse PEM certificate"));
+ }
+ break;
+
+ case PROP_PRIVATE_KEY:
+ case PROP_PRIVATE_KEY_PEM:
+ /* FIXME! */
+ break;
+
+ case PROP_ISSUER:
+ nss->priv->issuer = g_value_dup_object (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+g_tls_certificate_nss_init (GTlsCertificateNss *nss)
+{
+ nss->priv = G_TYPE_INSTANCE_GET_PRIVATE (nss,
+ G_TYPE_TLS_CERTIFICATE_NSS,
+ GTlsCertificateNssPrivate);
+}
+
+static gboolean
+g_tls_certificate_nss_initable_init (GInitable *initable,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GTlsCertificateNss *nss = G_TLS_CERTIFICATE_NSS (initable);
+
+ if (nss->priv->construct_error)
+ {
+ g_propagate_error (error, nss->priv->construct_error);
+ nss->priv->construct_error = NULL;
+ return FALSE;
+ }
+ else if (!nss->priv->cert)
+ {
+ g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
+ _("No certificate data provided"));
+ return FALSE;
+ }
+ else
+ return TRUE;
+}
+
+/* FIXME: mostly dup from gnutls */
+static GTlsCertificateFlags
+g_tls_certificate_nss_verify_identity (GTlsCertificateNss *nss,
+ GSocketConnectable *identity)
+{
+ const char *hostname;
+
+ if (G_IS_NETWORK_ADDRESS (identity))
+ hostname = g_network_address_get_hostname (G_NETWORK_ADDRESS (identity));
+ else if (G_IS_NETWORK_SERVICE (identity))
+ hostname = g_network_service_get_domain (G_NETWORK_SERVICE (identity));
+ else
+ hostname = NULL;
+
+ if (hostname)
+ {
+ if (CERT_VerifyCertName (nss->priv->cert, hostname) == SECSuccess)
+ return 0;
+ }
+
+ /* FIXME: check sRVName and uniformResourceIdentifier
+ * subjectAltNames, if appropriate for @identity.
+ */
+
+ return G_TLS_CERTIFICATE_BAD_IDENTITY;
+}
+
+static void
+g_tls_certificate_nss_expand_chain (GTlsCertificateNss *nss_cert)
+{
+ GTlsCertificateNss *c, *issuer = NULL;
+ CERTCertificateList *list;
+ CERTCertificate *cert;
+ SECCertUsage usage;
+ int i;
+
+ g_return_if_fail (nss_cert->priv->cert->nsCertType != 0);
+
+ if (nss_cert->priv->expanded)
+ return;
+
+ if (nss_cert->priv->cert->nsCertType & NS_CERT_TYPE_SSL_CLIENT)
+ usage = certUsageSSLClient;
+ else
+ usage = certUsageSSLServer;
+
+ list = CERT_CertChainFromCert (nss_cert->priv->cert, usage, PR_TRUE);
+ /* list->certs[0] is nss_cert itself, so start from index 1 */
+ for (i = 1, c = nss_cert; i < list->len; i++, c = c->priv->issuer)
+ {
+ cert = CERT_FindCertByDERCert (g_tls_backend_nss_certdbhandle,
+ &list->certs[i]);
+ issuer = g_tls_database_nss_get_gcert (g_tls_backend_nss_default_database, cert, TRUE);
+ CERT_DestroyCertificate (cert);
+
+ if (c->priv->issuer == issuer)
+ {
+ g_object_unref (issuer);
+ break;
+ }
+
+ if (c->priv->issuer)
+ g_object_unref (c->priv->issuer);
+ c->priv->issuer = issuer;
+ c->priv->expanded = TRUE;
+ }
+
+ if (i == list->len && issuer)
+ {
+ issuer->priv->expanded = TRUE;
+ g_clear_object (&issuer->priv->issuer);
+ }
+
+ CERT_DestroyCertificateList (list);
+}
+
+/* Our certificate verification routine... called by both
+ * g_tls_certificate_nss_verify() and g_tls_database_nss_verify_chain().
+ *
+ * For our verification purposes, we have to treat the certificates in
+ * @database or @trusted_ca as though they were trusted, but we can't
+ * actually mark them trusted because we don't know why our caller is
+ * currently considering them trusted, so we can't let that trust
+ * "leak" into the rest of the program.
+ *
+ * Fortunately, NSS will tell us in excruciating detail exactly what it
+ * doesn't like about a certificate, and so if the only problem with
+ * the cert is that it's signed by a @database or @trusted_ca cert that
+ * NSS doesn't like, then we can just ignore that error.
+ */
+GTlsCertificateFlags
+g_tls_certificate_nss_verify_full (GTlsCertificate *chain,
+ GTlsDatabase *database,
+ GTlsCertificate *trusted_ca,
+ const gchar *purpose,
+ GSocketConnectable *identity,
+ GTlsInteraction *interaction,
+ GTlsDatabaseVerifyFlags flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GTlsCertificateNss *nss_cert = G_TLS_CERTIFICATE_NSS (chain);
+ GTlsCertificateFlags result;
+ SECCertificateUsage usage;
+ PLArenaPool *arena;
+ CERTVerifyLog *log;
+ CERTVerifyLogNode *node;
+ PRTime now = PR_Now ();
+ SECCertTimeValidity time_validity;
+ int trusted_ca_index = -1;
+
+ g_return_val_if_fail (database == NULL || trusted_ca == NULL, G_TLS_CERTIFICATE_GENERIC_ERROR);
+
+ if (database == (GTlsDatabase *)g_tls_backend_nss_default_database)
+ database = NULL;
+
+ if (!strcmp (purpose, G_TLS_DATABASE_PURPOSE_AUTHENTICATE_SERVER))
+ usage = certificateUsageSSLServer;
+ else if (!strcmp (purpose, G_TLS_DATABASE_PURPOSE_AUTHENTICATE_CLIENT))
+ usage = certificateUsageSSLClient;
+ else
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
+ _("Unsupported key purpose OID '%s'"), purpose);
+ return G_TLS_CERTIFICATE_GENERIC_ERROR;
+ }
+
+ result = 0;
+
+ /* Verify the certificate and log all errors. As a side effect, this
+ * will ensure that nss_cert->priv->cert->nsCertType is set.
+ */
+ arena = PORT_NewArena (512);
+ log = PORT_ArenaZNew (arena, CERTVerifyLog);
+ log->arena = arena;
+ CERT_VerifyCert (g_tls_backend_nss_certdbhandle, nss_cert->priv->cert,
+ PR_TRUE, usage, now, interaction, log);
+
+ /* Now expand the gtls-level chain, and see if it contains a cert
+ * from @trusted_ca or @database, and if so, remember where in the
+ * chain it is.
+ */
+ g_tls_certificate_nss_expand_chain (nss_cert);
+ if (database || trusted_ca)
+ {
+ GTlsFileDatabaseNss *db_nss = database ? G_TLS_FILE_DATABASE_NSS (database) : NULL;
+ GTlsCertificateNss *c;
+ int n;
+
+ for (c = nss_cert, n = 0; c; c = c->priv->issuer, n++)
+ {
+ if (trusted_ca && c == (GTlsCertificateNss *)trusted_ca)
+ break;
+ if (db_nss && g_tls_file_database_nss_contains (db_nss, c))
+ break;
+ }
+
+ if (c)
+ trusted_ca_index = n;
+ else
+ result |= G_TLS_CERTIFICATE_UNKNOWN_CA;
+ }
+
+ /* Now go through the verification log translating the errors */
+ for (node = log->head; node; node = node->next)
+ {
+ if (trusted_ca_index != -1 && node->depth > trusted_ca_index)
+ break;
+
+ switch (node->error)
+ {
+ case SEC_ERROR_INADEQUATE_KEY_USAGE:
+ /* Cert is not appropriately tagged for signing. For
+ * historical/compatibility reasons, we ignore this when
+ * using PEM certificates.
+ */
+ if (database || trusted_ca)
+ break;
+ /* else fall through */
+
+ case SEC_ERROR_UNKNOWN_ISSUER:
+ /* Cert was issued by an unknown CA */
+ case SEC_ERROR_UNTRUSTED_ISSUER:
+ /* Cert is a CA that is not marked trusted */
+ case SEC_ERROR_CA_CERT_INVALID:
+ /* Cert is not a CA */
+
+ /* These are all OK if they occur on the trusted CA, but not
+ * before it.
+ */
+ if (node->depth != trusted_ca_index)
+ result |= G_TLS_CERTIFICATE_UNKNOWN_CA;
+ break;
+
+ case SEC_ERROR_CERT_NOT_IN_NAME_SPACE:
+ /* Cert is not authorized to sign the cert it signed */
+ result |= G_TLS_CERTIFICATE_UNKNOWN_CA;
+ break;
+
+ case SEC_ERROR_EXPIRED_CERTIFICATE:
+ case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
+ /* Cert is either expired or not yet valid;
+ * CERT_VerifyCert() doesn't distinguish.
+ */
+ time_validity = CERT_CheckCertValidTimes (node->cert, now, PR_FALSE);
+ if (time_validity == secCertTimeNotValidYet)
+ result |= G_TLS_CERTIFICATE_NOT_ACTIVATED;
+ else if (time_validity == secCertTimeExpired)
+ result |= G_TLS_CERTIFICATE_EXPIRED;
+ break;
+
+ case SEC_ERROR_REVOKED_CERTIFICATE:
+ result |= G_TLS_CERTIFICATE_REVOKED;
+ break;
+
+ default:
+ result |= G_TLS_CERTIFICATE_GENERIC_ERROR;
+ break;
+ }
+
+ CERT_DestroyCertificate (node->cert);
+ }
+
+ for (; node; node = node->next)
+ CERT_DestroyCertificate (node->cert);
+ PORT_FreeArena (log->arena, PR_FALSE);
+
+ if (identity)
+ result |= g_tls_certificate_nss_verify_identity (nss_cert, identity);
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, error))
+ result = G_TLS_CERTIFICATE_GENERIC_ERROR;
+
+ return result;
+}
+
+static GTlsCertificateFlags
+g_tls_certificate_nss_verify (GTlsCertificate *cert,
+ GSocketConnectable *identity,
+ GTlsCertificate *trusted_ca)
+{
+ GTlsCertificateNss *nss_cert = G_TLS_CERTIFICATE_NSS (cert);
+ GTlsCertificateFlags flags;
+
+ /* nss_cert->priv->cert->nsCertType may not have been set yet, but
+ * it will get set as a side effect of verifying the cert. If we
+ * don't know yet what kind of key it is, we'll try server first.
+ */
+
+ if ((nss_cert->priv->cert->nsCertType & NS_CERT_TYPE_SSL_SERVER) ||
+ (nss_cert->priv->cert->nsCertType == 0))
+ {
+ flags = g_tls_certificate_nss_verify_full (cert, NULL, trusted_ca,
+ G_TLS_DATABASE_PURPOSE_AUTHENTICATE_SERVER,
+ identity, NULL, 0, NULL, NULL);
+ }
+
+ if (!(nss_cert->priv->cert->nsCertType & NS_CERT_TYPE_SSL_SERVER))
+ {
+ flags = g_tls_certificate_nss_verify_full (cert, NULL, trusted_ca,
+ G_TLS_DATABASE_PURPOSE_AUTHENTICATE_CLIENT,
+ identity, NULL, 0, NULL, NULL);
+ }
+
+ return flags;
+}
+
+static void
+g_tls_certificate_nss_class_init (GTlsCertificateNssClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GTlsCertificateClass *certificate_class = G_TLS_CERTIFICATE_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (GTlsCertificateNssPrivate));
+
+ gobject_class->constructor = g_tls_certificate_nss_constructor;
+ gobject_class->get_property = g_tls_certificate_nss_get_property;
+ gobject_class->set_property = g_tls_certificate_nss_set_property;
+ gobject_class->finalize = g_tls_certificate_nss_finalize;
+
+ certificate_class->verify = g_tls_certificate_nss_verify;
+
+ g_object_class_override_property (gobject_class, PROP_CERTIFICATE, "certificate");
+ g_object_class_override_property (gobject_class, PROP_CERTIFICATE_PEM, "certificate-pem");
+ g_object_class_override_property (gobject_class, PROP_PRIVATE_KEY, "private-key");
+ g_object_class_override_property (gobject_class, PROP_PRIVATE_KEY_PEM, "private-key-pem");
+ g_object_class_override_property (gobject_class, PROP_ISSUER, "issuer");
+}
+
+static void
+g_tls_certificate_nss_initable_iface_init (GInitableIface *iface)
+{
+ iface->init = g_tls_certificate_nss_initable_init;
+}
+
+GTlsCertificateNss *
+g_tls_certificate_nss_new_for_cert (CERTCertificate *cert)
+{
+ GTlsCertificateNss *nss;
+
+ nss = g_object_new (G_TYPE_TLS_CERTIFICATE_NSS, NULL);
+ nss->priv->cert = CERT_DupCertificate (cert);
+
+ return nss;
+}
+
+CERTCertificate *
+g_tls_certificate_nss_get_cert (GTlsCertificateNss *nss)
+{
+ return nss->priv->cert;
+}
+
+
diff --git a/tls/nss/gtlscertificate-nss.h b/tls/nss/gtlscertificate-nss.h
new file mode 100644
index 0000000..578448d
--- /dev/null
+++ b/tls/nss/gtlscertificate-nss.h
@@ -0,0 +1,61 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright 2011 Red Hat, Inc
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the licence or (at
+ * your option) any later version.
+ *
+ * See the included COPYING file for more information.
+ */
+
+#ifndef __G_TLS_CERTIFICATE_NSS_H__
+#define __G_TLS_CERTIFICATE_NSS_H__
+
+#include <gio/gio.h>
+#include <nss.h>
+
+G_BEGIN_DECLS
+
+#define G_TYPE_TLS_CERTIFICATE_NSS (g_tls_certificate_nss_get_type ())
+#define G_TLS_CERTIFICATE_NSS(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), G_TYPE_TLS_CERTIFICATE_NSS, GTlsCertificateNss))
+#define G_TLS_CERTIFICATE_NSS_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), G_TYPE_TLS_CERTIFICATE_NSS, GTlsCertificateNssClass))
+#define G_IS_TLS_CERTIFICATE_NSS(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), G_TYPE_TLS_CERTIFICATE_NSS))
+#define G_IS_TLS_CERTIFICATE_NSS_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), G_TYPE_TLS_CERTIFICATE_NSS))
+#define G_TLS_CERTIFICATE_NSS_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), G_TYPE_TLS_CERTIFICATE_NSS, GTlsCertificateNssClass))
+
+typedef struct _GTlsCertificateNssPrivate GTlsCertificateNssPrivate;
+typedef struct _GTlsCertificateNssClass GTlsCertificateNssClass;
+typedef struct _GTlsCertificateNss GTlsCertificateNss;
+
+struct _GTlsCertificateNssClass
+{
+ GTlsCertificateClass parent_class;
+};
+
+struct _GTlsCertificateNss
+{
+ GTlsCertificate parent_instance;
+ GTlsCertificateNssPrivate *priv;
+};
+
+GType g_tls_certificate_nss_get_type (void) G_GNUC_CONST;
+
+GTlsCertificateNss *g_tls_certificate_nss_new_for_cert (CERTCertificate *cert);
+
+CERTCertificate *g_tls_certificate_nss_get_cert (GTlsCertificateNss *nss);
+
+GTlsCertificateFlags g_tls_certificate_nss_verify_full (GTlsCertificate *chain,
+ GTlsDatabase *database,
+ GTlsCertificate *trusted_ca,
+ const gchar *purpose,
+ GSocketConnectable *identity,
+ GTlsInteraction *interaction,
+ GTlsDatabaseVerifyFlags flags,
+ GCancellable *cancellable,
+ GError **error);
+
+G_END_DECLS
+
+#endif /* __G_TLS_CERTIFICATE_NSS_H___ */
diff --git a/tls/nss/gtlsclientconnection-nss.c b/tls/nss/gtlsclientconnection-nss.c
new file mode 100644
index 0000000..327cfc1
--- /dev/null
+++ b/tls/nss/gtlsclientconnection-nss.c
@@ -0,0 +1,162 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright 2011 Red Hat, Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include <glib.h>
+
+#include "gtlsclientconnection-nss.h"
+#include <glib/gi18n-lib.h>
+
+enum
+{
+ PROP_0,
+ PROP_VALIDATION_FLAGS,
+ PROP_SERVER_IDENTITY,
+ PROP_USE_SSL3,
+ PROP_ACCEPTED_CAS
+};
+
+static void g_tls_client_connection_nss_client_connection_interface_init (GTlsClientConnectionInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GTlsClientConnectionNss, g_tls_client_connection_nss, G_TYPE_TLS_CONNECTION_NSS,
+ G_IMPLEMENT_INTERFACE (G_TYPE_TLS_CLIENT_CONNECTION,
+ g_tls_client_connection_nss_client_connection_interface_init));
+
+struct _GTlsClientConnectionNssPrivate
+{
+ GTlsCertificateFlags validation_flags;
+ GSocketConnectable *server_identity;
+ gboolean use_ssl3;
+ GPtrArray *accepted_cas;
+};
+
+static void
+g_tls_client_connection_nss_init (GTlsClientConnectionNss *nss)
+{
+ nss->priv = G_TYPE_INSTANCE_GET_PRIVATE (nss, G_TYPE_TLS_CLIENT_CONNECTION_NSS, GTlsClientConnectionNssPrivate);
+}
+
+static void
+g_tls_client_connection_nss_finalize (GObject *object)
+{
+ GTlsClientConnectionNss *nss = G_TLS_CLIENT_CONNECTION_NSS (object);
+
+ if (nss->priv->server_identity)
+ g_object_unref (nss->priv->server_identity);
+ if (nss->priv->accepted_cas)
+ g_ptr_array_unref (nss->priv->accepted_cas);
+
+ G_OBJECT_CLASS (g_tls_client_connection_nss_parent_class)->finalize (object);
+}
+
+static void
+g_tls_client_connection_nss_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GTlsClientConnectionNss *nss = G_TLS_CLIENT_CONNECTION_NSS (object);
+ GList *accepted_cas;
+ gint i;
+
+ switch (prop_id)
+ {
+ case PROP_VALIDATION_FLAGS:
+ g_value_set_flags (value, nss->priv->validation_flags);
+ break;
+
+ case PROP_SERVER_IDENTITY:
+ g_value_set_object (value, nss->priv->server_identity);
+ break;
+
+ case PROP_USE_SSL3:
+ g_value_set_boolean (value, nss->priv->use_ssl3);
+ break;
+
+ case PROP_ACCEPTED_CAS:
+ accepted_cas = NULL;
+ if (nss->priv->accepted_cas)
+ {
+ for (i = 0; i < nss->priv->accepted_cas->len; ++i)
+ {
+ accepted_cas = g_list_prepend (accepted_cas, g_byte_array_ref (
+ nss->priv->accepted_cas->pdata[i]));
+ }
+ accepted_cas = g_list_reverse (accepted_cas);
+ }
+ g_value_set_pointer (value, accepted_cas);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+g_tls_client_connection_nss_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GTlsClientConnectionNss *nss = G_TLS_CLIENT_CONNECTION_NSS (object);
+
+ switch (prop_id)
+ {
+ case PROP_VALIDATION_FLAGS:
+ nss->priv->validation_flags = g_value_get_flags (value);
+ break;
+
+ case PROP_SERVER_IDENTITY:
+ if (nss->priv->server_identity)
+ g_object_unref (nss->priv->server_identity);
+ nss->priv->server_identity = g_value_dup_object (value);
+ break;
+
+ case PROP_USE_SSL3:
+ nss->priv->use_ssl3 = g_value_get_boolean (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+g_tls_client_connection_nss_class_init (GTlsClientConnectionNssClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (GTlsClientConnectionNssPrivate));
+
+ gobject_class->get_property = g_tls_client_connection_nss_get_property;
+ gobject_class->set_property = g_tls_client_connection_nss_set_property;
+ gobject_class->finalize = g_tls_client_connection_nss_finalize;
+
+ g_object_class_override_property (gobject_class, PROP_VALIDATION_FLAGS, "validation-flags");
+ g_object_class_override_property (gobject_class, PROP_SERVER_IDENTITY, "server-identity");
+ g_object_class_override_property (gobject_class, PROP_USE_SSL3, "use-ssl3");
+ g_object_class_override_property (gobject_class, PROP_ACCEPTED_CAS, "accepted-cas");
+}
+
+static void
+g_tls_client_connection_nss_client_connection_interface_init (GTlsClientConnectionInterface *iface)
+{
+}
+
diff --git a/tls/nss/gtlsclientconnection-nss.h b/tls/nss/gtlsclientconnection-nss.h
new file mode 100644
index 0000000..294a8a7
--- /dev/null
+++ b/tls/nss/gtlsclientconnection-nss.h
@@ -0,0 +1,46 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright 2011 Red Hat, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the licence or (at
+ * your option) any later version.
+ *
+ * See the included COPYING file for more information.
+ */
+
+#ifndef __G_TLS_CLIENT_CONNECTION_NSS_H__
+#define __G_TLS_CLIENT_CONNECTION_NSS_H__
+
+#include "gtlsconnection-nss.h"
+
+G_BEGIN_DECLS
+
+#define G_TYPE_TLS_CLIENT_CONNECTION_NSS (g_tls_client_connection_nss_get_type ())
+#define G_TLS_CLIENT_CONNECTION_NSS(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), G_TYPE_TLS_CLIENT_CONNECTION_NSS, GTlsClientConnectionNss))
+#define G_TLS_CLIENT_CONNECTION_NSS_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), G_TYPE_TLS_CLIENT_CONNECTION_NSS, GTlsClientConnectionNssClass))
+#define G_IS_TLS_CLIENT_CONNECTION_NSS(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), G_TYPE_TLS_CLIENT_CONNECTION_NSS))
+#define G_IS_TLS_CLIENT_CONNECTION_NSS_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), G_TYPE_TLS_CLIENT_CONNECTION_NSS))
+#define G_TLS_CLIENT_CONNECTION_NSS_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), G_TYPE_TLS_CLIENT_CONNECTION_NSS, GTlsClientConnectionNssClass))
+
+typedef struct _GTlsClientConnectionNssPrivate GTlsClientConnectionNssPrivate;
+typedef struct _GTlsClientConnectionNssClass GTlsClientConnectionNssClass;
+typedef struct _GTlsClientConnectionNss GTlsClientConnectionNss;
+
+struct _GTlsClientConnectionNssClass
+{
+ GTlsConnectionNssClass parent_class;
+};
+
+struct _GTlsClientConnectionNss
+{
+ GTlsConnectionNss parent_instance;
+ GTlsClientConnectionNssPrivate *priv;
+};
+
+GType g_tls_client_connection_nss_get_type (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* __G_TLS_CLIENT_CONNECTION_NSS_H___ */
diff --git a/tls/nss/gtlsconnection-nss.c b/tls/nss/gtlsconnection-nss.c
new file mode 100644
index 0000000..c42a77d
--- /dev/null
+++ b/tls/nss/gtlsconnection-nss.c
@@ -0,0 +1,365 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright 2011 Red Hat, Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include <glib.h>
+
+#include "gtlsconnection-nss.h"
+#include <glib/gi18n-lib.h>
+
+static void g_tls_connection_nss_initable_iface_init (GInitableIface *iface);
+
+
+G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GTlsConnectionNss, g_tls_connection_nss, G_TYPE_TLS_CONNECTION,
+ G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
+ g_tls_connection_nss_initable_iface_init););
+
+
+enum
+{
+ PROP_0,
+ PROP_BASE_IO_STREAM,
+ PROP_REQUIRE_CLOSE_NOTIFY,
+ PROP_REHANDSHAKE_MODE,
+ PROP_USE_SYSTEM_CERTDB,
+ PROP_DATABASE,
+ PROP_CERTIFICATE,
+ PROP_INTERACTION,
+ PROP_PEER_CERTIFICATE,
+ PROP_PEER_CERTIFICATE_ERRORS
+};
+
+struct _GTlsConnectionNssPrivate
+{
+ GIOStream *base_io_stream;
+ GPollableInputStream *base_istream;
+ GPollableOutputStream *base_ostream;
+
+ GTlsCertificate *certificate, *peer_certificate;
+ GTlsCertificateFlags peer_certificate_errors;
+ gboolean require_close_notify;
+ GTlsRehandshakeMode rehandshake_mode;
+ gboolean is_system_certdb;
+ GTlsDatabase *database;
+ gboolean database_is_unset;
+
+ GInputStream *tls_istream;
+ GOutputStream *tls_ostream;
+
+ GTlsInteraction *interaction;
+};
+
+static void
+g_tls_connection_nss_init (GTlsConnectionNss *nss)
+{
+ nss->priv = G_TYPE_INSTANCE_GET_PRIVATE (nss, G_TYPE_TLS_CONNECTION_NSS, GTlsConnectionNssPrivate);
+
+ nss->priv->database_is_unset = TRUE;
+ nss->priv->is_system_certdb = TRUE;
+}
+
+static gboolean
+g_tls_connection_nss_initable_init (GInitable *initable,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GTlsConnectionNss *nss = G_TLS_CONNECTION_NSS (initable);
+
+ g_return_val_if_fail (nss->priv->base_istream != NULL &&
+ nss->priv->base_ostream != NULL, FALSE);
+
+ return TRUE;
+}
+
+static void
+g_tls_connection_nss_finalize (GObject *object)
+{
+ GTlsConnectionNss *nss = G_TLS_CONNECTION_NSS (object);
+
+ if (nss->priv->base_io_stream)
+ g_object_unref (nss->priv->base_io_stream);
+
+ if (nss->priv->tls_istream)
+ g_object_unref (nss->priv->tls_istream);
+ if (nss->priv->tls_ostream)
+ g_object_unref (nss->priv->tls_ostream);
+
+ if (nss->priv->database)
+ g_object_unref (nss->priv->database);
+ if (nss->priv->certificate)
+ g_object_unref (nss->priv->certificate);
+ if (nss->priv->peer_certificate)
+ g_object_unref (nss->priv->peer_certificate);
+
+ if (nss->priv->interaction)
+ g_object_unref (nss->priv->interaction);
+
+ G_OBJECT_CLASS (g_tls_connection_nss_parent_class)->finalize (object);
+}
+
+static void
+g_tls_connection_nss_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GTlsConnectionNss *nss = G_TLS_CONNECTION_NSS (object);
+ GTlsBackend *backend;
+
+ switch (prop_id)
+ {
+ case PROP_BASE_IO_STREAM:
+ g_value_set_object (value, nss->priv->base_io_stream);
+ break;
+
+ case PROP_REQUIRE_CLOSE_NOTIFY:
+ g_value_set_boolean (value, nss->priv->require_close_notify);
+ break;
+
+ case PROP_REHANDSHAKE_MODE:
+ g_value_set_enum (value, nss->priv->rehandshake_mode);
+ break;
+
+ case PROP_USE_SYSTEM_CERTDB:
+ g_value_set_boolean (value, nss->priv->is_system_certdb);
+ break;
+
+ case PROP_DATABASE:
+ if (nss->priv->database_is_unset)
+ {
+ backend = g_tls_backend_get_default ();
+ nss->priv->database = g_tls_backend_get_default_database (backend);
+ nss->priv->database_is_unset = FALSE;
+ }
+ g_value_set_object (value, nss->priv->database);
+ break;
+
+ case PROP_CERTIFICATE:
+ g_value_set_object (value, nss->priv->certificate);
+ break;
+
+ case PROP_INTERACTION:
+ g_value_set_object (value, nss->priv->interaction);
+ break;
+
+ case PROP_PEER_CERTIFICATE:
+ g_value_set_object (value, nss->priv->peer_certificate);
+ break;
+
+ case PROP_PEER_CERTIFICATE_ERRORS:
+ g_value_set_flags (value, nss->priv->peer_certificate_errors);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+g_tls_connection_nss_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GTlsConnectionNss *nss = G_TLS_CONNECTION_NSS (object);
+ GInputStream *istream;
+ GOutputStream *ostream;
+ gboolean system_certdb;
+ GTlsBackend *backend;
+
+ switch (prop_id)
+ {
+ case PROP_BASE_IO_STREAM:
+ if (nss->priv->base_io_stream)
+ {
+ g_object_unref (nss->priv->base_io_stream);
+ nss->priv->base_istream = NULL;
+ nss->priv->base_ostream = NULL;
+ }
+ nss->priv->base_io_stream = g_value_dup_object (value);
+ if (!nss->priv->base_io_stream)
+ return;
+
+ istream = g_io_stream_get_input_stream (nss->priv->base_io_stream);
+ ostream = g_io_stream_get_output_stream (nss->priv->base_io_stream);
+
+ if (G_IS_POLLABLE_INPUT_STREAM (istream) &&
+ g_pollable_input_stream_can_poll (G_POLLABLE_INPUT_STREAM (istream)))
+ nss->priv->base_istream = G_POLLABLE_INPUT_STREAM (istream);
+ if (G_IS_POLLABLE_OUTPUT_STREAM (ostream) &&
+ g_pollable_output_stream_can_poll (G_POLLABLE_OUTPUT_STREAM (ostream)))
+ nss->priv->base_ostream = G_POLLABLE_OUTPUT_STREAM (ostream);
+ break;
+
+ case PROP_REQUIRE_CLOSE_NOTIFY:
+ nss->priv->require_close_notify = g_value_get_boolean (value);
+ break;
+
+ case PROP_REHANDSHAKE_MODE:
+ nss->priv->rehandshake_mode = g_value_get_enum (value);
+ break;
+
+ case PROP_USE_SYSTEM_CERTDB:
+ system_certdb = g_value_get_boolean (value);
+ if (system_certdb != nss->priv->is_system_certdb)
+ {
+ g_clear_object (&nss->priv->database);
+ if (system_certdb)
+ {
+ backend = g_tls_backend_get_default ();
+ nss->priv->database = g_tls_backend_get_default_database (backend);
+ }
+ nss->priv->is_system_certdb = system_certdb;
+ }
+ break;
+
+ case PROP_DATABASE:
+ if (nss->priv->database)
+ g_object_unref (nss->priv->database);
+ nss->priv->database = g_value_dup_object (value);
+ nss->priv->is_system_certdb = FALSE;
+ nss->priv->database_is_unset = FALSE;
+ break;
+
+ case PROP_CERTIFICATE:
+ if (nss->priv->certificate)
+ g_object_unref (nss->priv->certificate);
+ nss->priv->certificate = g_value_dup_object (value);
+ break;
+
+ case PROP_INTERACTION:
+ if (nss->priv->interaction)
+ g_object_unref (nss->priv->interaction);
+ nss->priv->interaction = g_value_dup_object (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static gboolean
+g_tls_connection_nss_handshake (GTlsConnection *conn,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_return_val_if_reached (FALSE);
+}
+
+static void
+g_tls_connection_nss_handshake_async (GTlsConnection *conn,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_return_if_reached ();
+}
+
+static gboolean
+g_tls_connection_nss_handshake_finish (GTlsConnection *conn,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_reached (FALSE);
+}
+
+static GInputStream *
+g_tls_connection_nss_get_input_stream (GIOStream *stream)
+{
+ GTlsConnectionNss *nss = G_TLS_CONNECTION_NSS (stream);
+
+ return nss->priv->tls_istream;
+}
+
+static GOutputStream *
+g_tls_connection_nss_get_output_stream (GIOStream *stream)
+{
+ GTlsConnectionNss *nss = G_TLS_CONNECTION_NSS (stream);
+
+ return nss->priv->tls_ostream;
+}
+
+static gboolean
+g_tls_connection_nss_close (GIOStream *stream,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_return_val_if_reached (FALSE);
+}
+
+static void
+g_tls_connection_nss_close_async (GIOStream *stream,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_return_if_reached ();
+}
+
+static gboolean
+g_tls_connection_nss_close_finish (GIOStream *stream,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_reached (FALSE);
+}
+
+static void
+g_tls_connection_nss_class_init (GTlsConnectionNssClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GTlsConnectionClass *connection_class = G_TLS_CONNECTION_CLASS (klass);
+ GIOStreamClass *iostream_class = G_IO_STREAM_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (GTlsConnectionNssPrivate));
+
+ gobject_class->get_property = g_tls_connection_nss_get_property;
+ gobject_class->set_property = g_tls_connection_nss_set_property;
+ gobject_class->finalize = g_tls_connection_nss_finalize;
+
+ connection_class->handshake = g_tls_connection_nss_handshake;
+ connection_class->handshake_async = g_tls_connection_nss_handshake_async;
+ connection_class->handshake_finish = g_tls_connection_nss_handshake_finish;
+
+ iostream_class->get_input_stream = g_tls_connection_nss_get_input_stream;
+ iostream_class->get_output_stream = g_tls_connection_nss_get_output_stream;
+ iostream_class->close_fn = g_tls_connection_nss_close;
+ iostream_class->close_async = g_tls_connection_nss_close_async;
+ iostream_class->close_finish = g_tls_connection_nss_close_finish;
+
+ g_object_class_override_property (gobject_class, PROP_BASE_IO_STREAM, "base-io-stream");
+ g_object_class_override_property (gobject_class, PROP_REQUIRE_CLOSE_NOTIFY, "require-close-notify");
+ g_object_class_override_property (gobject_class, PROP_REHANDSHAKE_MODE, "rehandshake-mode");
+ g_object_class_override_property (gobject_class, PROP_USE_SYSTEM_CERTDB, "use-system-certdb");
+ g_object_class_override_property (gobject_class, PROP_DATABASE, "database");
+ g_object_class_override_property (gobject_class, PROP_CERTIFICATE, "certificate");
+ g_object_class_override_property (gobject_class, PROP_INTERACTION, "interaction");
+ g_object_class_override_property (gobject_class, PROP_PEER_CERTIFICATE, "peer-certificate");
+ g_object_class_override_property (gobject_class, PROP_PEER_CERTIFICATE_ERRORS, "peer-certificate-errors");
+}
+
+static void
+g_tls_connection_nss_initable_iface_init (GInitableIface *iface)
+{
+ iface->init = g_tls_connection_nss_initable_init;
+}
+
diff --git a/tls/nss/gtlsconnection-nss.h b/tls/nss/gtlsconnection-nss.h
new file mode 100644
index 0000000..26bcc6c
--- /dev/null
+++ b/tls/nss/gtlsconnection-nss.h
@@ -0,0 +1,48 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright 2011 Red Hat, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the licence or (at
+ * your option) any later version.
+ *
+ * See the included COPYING file for more information.
+ */
+
+#ifndef __G_TLS_CONNECTION_NSS_H__
+#define __G_TLS_CONNECTION_NSS_H__
+
+#include <gio/gio.h>
+#include <nss.h>
+
+G_BEGIN_DECLS
+
+#define G_TYPE_TLS_CONNECTION_NSS (g_tls_connection_nss_get_type ())
+#define G_TLS_CONNECTION_NSS(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), G_TYPE_TLS_CONNECTION_NSS, GTlsConnectionNss))
+#define G_TLS_CONNECTION_NSS_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), G_TYPE_TLS_CONNECTION_NSS, GTlsConnectionNssClass))
+#define G_IS_TLS_CONNECTION_NSS(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), G_TYPE_TLS_CONNECTION_NSS))
+#define G_IS_TLS_CONNECTION_NSS_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), G_TYPE_TLS_CONNECTION_NSS))
+#define G_TLS_CONNECTION_NSS_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), G_TYPE_TLS_CONNECTION_NSS, GTlsConnectionNssClass))
+
+typedef struct _GTlsConnectionNssPrivate GTlsConnectionNssPrivate;
+typedef struct _GTlsConnectionNssClass GTlsConnectionNssClass;
+typedef struct _GTlsConnectionNss GTlsConnectionNss;
+
+struct _GTlsConnectionNssClass
+{
+ GTlsConnectionClass parent_class;
+
+};
+
+struct _GTlsConnectionNss
+{
+ GTlsConnection parent_instance;
+ GTlsConnectionNssPrivate *priv;
+};
+
+GType g_tls_connection_nss_get_type (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* __G_TLS_CONNECTION_NSS_H___ */
diff --git a/tls/nss/gtlsdatabase-nss.c b/tls/nss/gtlsdatabase-nss.c
new file mode 100644
index 0000000..53f1156
--- /dev/null
+++ b/tls/nss/gtlsdatabase-nss.c
@@ -0,0 +1,283 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright 2011 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <nss.h>
+#include <pk11pub.h>
+#include <secerr.h>
+
+#include "gtlsdatabase-nss.h"
+#include "gtlsbackend-nss.h"
+#include "gtlscertificate-nss.h"
+
+#include <glib/gi18n-lib.h>
+
+G_DEFINE_TYPE (GTlsDatabaseNss, g_tls_database_nss, G_TYPE_TLS_DATABASE);
+
+struct _GTlsDatabaseNssPrivate
+{
+ GMutex *mutex;
+ GHashTable *gcerts;
+};
+
+static void
+g_tls_database_nss_init (GTlsDatabaseNss *nss)
+{
+ nss->priv = G_TYPE_INSTANCE_GET_PRIVATE (nss,
+ G_TYPE_TLS_DATABASE_NSS,
+ GTlsDatabaseNssPrivate);
+
+ nss->priv->mutex = g_mutex_new ();
+
+ /* gcerts is a cache of CERTCertificate to GTlsCertificateNss
+ * mappings, including every live GTlsCertificateNss. Note that both
+ * types enforce uniqueness, so there should be a one-to-one
+ * mapping.
+ */
+ nss->priv->gcerts = g_hash_table_new (NULL, NULL);
+}
+
+static void
+g_tls_database_nss_finalize (GObject *object)
+{
+ GTlsDatabaseNss *nss = G_TLS_DATABASE_NSS (object);
+ GHashTableIter iter;
+ gpointer cert, gcert;
+
+ g_mutex_free (nss->priv->mutex);
+
+ g_hash_table_iter_init (&iter, nss->priv->gcerts);
+ while (g_hash_table_iter_next (&iter, &cert, &gcert))
+ CERT_DestroyCertificate (cert);
+ g_hash_table_destroy (nss->priv->gcerts);
+
+ G_OBJECT_CLASS (g_tls_database_nss_parent_class)->finalize (object);
+}
+
+GTlsCertificateNss *
+g_tls_database_nss_get_gcert (GTlsDatabaseNss *nss,
+ CERTCertificate *cert,
+ gboolean create)
+{
+ GTlsCertificateNss *gcert;
+
+ g_mutex_lock (nss->priv->mutex);
+
+ gcert = g_hash_table_lookup (nss->priv->gcerts, cert);
+ if (gcert)
+ g_object_ref (gcert);
+ else if (create)
+ {
+ gcert = g_tls_certificate_nss_new_for_cert (cert);
+ /* The GTlsCertificate constructor will call
+ * g_tls_database_nss_gcert_created() to add it to the hash.
+ */
+ }
+
+ g_mutex_unlock (nss->priv->mutex);
+ return gcert;
+}
+
+void
+g_tls_database_nss_gcert_created (GTlsDatabaseNss *nss,
+ CERTCertificate *cert,
+ GTlsCertificateNss *gcert)
+{
+ g_mutex_lock (nss->priv->mutex);
+ /* We keep a ref on the CERTCertificate, but not the GTlsCertificate */
+ g_hash_table_insert (nss->priv->gcerts, CERT_DupCertificate (cert), gcert);
+ g_mutex_unlock (nss->priv->mutex);
+}
+
+void
+g_tls_database_nss_gcert_destroyed (GTlsDatabaseNss *nss,
+ CERTCertificate *cert)
+{
+ g_mutex_lock (nss->priv->mutex);
+ g_hash_table_remove (nss->priv->gcerts, cert);
+ CERT_DestroyCertificate (cert);
+ g_mutex_unlock (nss->priv->mutex);
+}
+
+static GTlsCertificateFlags
+g_tls_database_nss_verify_chain (GTlsDatabase *database,
+ GTlsCertificate *chain,
+ const gchar *purpose,
+ GSocketConnectable *identity,
+ GTlsInteraction *interaction,
+ GTlsDatabaseVerifyFlags flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+ return g_tls_certificate_nss_verify_full (chain, database, NULL,
+ purpose, identity, interaction,
+ flags, cancellable, error);
+}
+
+static gchar *
+g_tls_database_nss_create_certificate_handle (GTlsDatabase *database,
+ GTlsCertificate *certificate)
+{
+
+ CERTCertificate *cert = g_tls_certificate_nss_get_cert (G_TLS_CERTIFICATE_NSS (certificate));
+ gchar *issuer, *serial, *handle;
+
+ issuer = g_base64_encode ((guchar *)cert->derIssuer.data,
+ cert->derIssuer.len);
+ serial = g_base64_encode ((guchar *)cert->serialNumber.data,
+ cert->serialNumber.len);
+
+ handle = g_strdup_printf ("nss:%s#%s", issuer, serial);
+ g_free (issuer);
+ g_free (serial);
+
+ return handle;
+}
+
+static GTlsCertificate *
+g_tls_database_nss_lookup_certificate_for_handle (GTlsDatabase *database,
+ const gchar *handle,
+ GTlsInteraction *interaction,
+ GTlsDatabaseLookupFlags flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GTlsDatabaseNss *nss = G_TLS_DATABASE_NSS (database);
+ const gchar *split, *issuer, *serial;
+ CERTIssuerAndSN issuerAndSN;
+ CERTCertificate *cert;
+ GTlsCertificateNss *ret;
+ gsize length;
+
+ if (!g_str_has_prefix (handle, "nss:"))
+ return NULL;
+
+ issuer = handle + 4;
+ split = strchr (issuer, '#');
+ if (!split)
+ return NULL;
+ serial = split + 1;
+
+ issuerAndSN.derIssuer.data = g_base64_decode (issuer, &length);
+ issuerAndSN.derIssuer.len = length;
+
+ issuerAndSN.serialNumber.data = g_base64_decode (serial, &length);
+ issuerAndSN.serialNumber.len = length;
+
+ cert = CERT_FindCertByIssuerAndSN (g_tls_backend_nss_certdbhandle, &issuerAndSN);
+ g_free (issuerAndSN.derIssuer.data);
+ g_free (issuerAndSN.serialNumber.data);
+ if (!cert)
+ return NULL;
+
+ ret = g_tls_database_nss_get_gcert (nss, cert, TRUE);
+ CERT_DestroyCertificate (cert);
+ return G_TLS_CERTIFICATE (ret);
+}
+
+static GTlsCertificate *
+g_tls_database_nss_lookup_certificate_issuer (GTlsDatabase *database,
+ GTlsCertificate *certificate,
+ GTlsInteraction *interaction,
+ GTlsDatabaseLookupFlags flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GTlsDatabaseNss *nss = G_TLS_DATABASE_NSS (database);
+ GTlsCertificateNss *cert_nss = G_TLS_CERTIFICATE_NSS (certificate);
+ CERTCertificate *cert, *issuer_cert;
+ GTlsCertificateNss *issuer;
+
+ cert = g_tls_certificate_nss_get_cert (cert_nss);
+ issuer_cert = CERT_FindCertIssuer(cert, PR_Now (),
+ /* FIXME? Though it seems to not actually
+ * matter if this is wrong.
+ */
+ certUsageSSLServer);
+ if (issuer_cert)
+ {
+ issuer = g_tls_database_nss_get_gcert (nss, issuer_cert, TRUE);
+ CERT_DestroyCertificate (issuer_cert);
+ return G_TLS_CERTIFICATE (issuer);
+ }
+ else
+ return NULL;
+}
+
+static GList *
+g_tls_database_nss_lookup_certificates_issued_by (GTlsDatabase *database,
+ GByteArray *issuer_raw_dn,
+ GTlsInteraction *interaction,
+ GTlsDatabaseLookupFlags flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GTlsDatabaseNss *nss = G_TLS_DATABASE_NSS (database);
+ GList *certs;
+ CERTCertNicknames *nicknames;
+ CERTCertificate *cert;
+ SECItem issuerName;
+ int i;
+
+ nicknames = CERT_GetCertNicknames (g_tls_backend_nss_certdbhandle,
+ SEC_CERT_NICKNAMES_ALL, interaction);
+ if (!nicknames)
+ return NULL;
+
+ certs = NULL;
+ for (i = 0; i < nicknames->numnicknames; i++)
+ {
+ cert = PK11_FindCertFromNickname (nicknames->nicknames[i], interaction);
+ if (!cert)
+ continue;
+
+ if (CERT_IssuerNameFromDERCert (&cert->derCert, &issuerName) == SECSuccess)
+ {
+ if (issuer_raw_dn->len == issuerName.len &&
+ memcmp (issuer_raw_dn->data, issuerName.data, issuerName.len) == 0)
+ certs = g_list_prepend (certs, g_tls_database_nss_get_gcert (nss, cert, TRUE));
+
+ SECITEM_FreeItem (&issuerName, PR_FALSE);
+ }
+
+ CERT_DestroyCertificate (cert);
+ }
+
+ CERT_FreeNicknames (nicknames);
+ return certs;
+}
+
+static void
+g_tls_database_nss_class_init (GTlsDatabaseNssClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GTlsDatabaseClass *database_class = G_TLS_DATABASE_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (GTlsDatabaseNssPrivate));
+
+ object_class->finalize = g_tls_database_nss_finalize;
+
+ database_class->verify_chain = g_tls_database_nss_verify_chain;
+ database_class->create_certificate_handle = g_tls_database_nss_create_certificate_handle;
+ database_class->lookup_certificate_for_handle = g_tls_database_nss_lookup_certificate_for_handle;
+ database_class->lookup_certificate_issuer = g_tls_database_nss_lookup_certificate_issuer;
+ database_class->lookup_certificates_issued_by = g_tls_database_nss_lookup_certificates_issued_by;
+}
diff --git a/tls/nss/gtlsdatabase-nss.h b/tls/nss/gtlsdatabase-nss.h
new file mode 100644
index 0000000..ac85e10
--- /dev/null
+++ b/tls/nss/gtlsdatabase-nss.h
@@ -0,0 +1,60 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright 2011 Red Hat, Inc..
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the licence or (at
+ * your option) any later version.
+ *
+ * See the included COPYING file for more information.
+ */
+
+#ifndef __G_TLS_DATABASE_NSS_H__
+#define __G_TLS_DATABASE_NSS_H__
+
+#include <gio/gio.h>
+#include <cert.h>
+
+#include "gtlscertificate-nss.h"
+
+G_BEGIN_DECLS
+
+#define G_TYPE_TLS_DATABASE_NSS (g_tls_database_nss_get_type ())
+#define G_TLS_DATABASE_NSS(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), G_TYPE_TLS_DATABASE_NSS, GTlsDatabaseNss))
+#define G_TLS_DATABASE_NSS_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), G_TYPE_TLS_DATABASE_NSS, GTlsDatabaseNssClass))
+#define G_IS_TLS_DATABASE_NSS(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), G_TYPE_TLS_DATABASE_NSS))
+#define G_IS_TLS_DATABASE_NSS_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), G_TYPE_TLS_DATABASE_NSS))
+#define G_TLS_DATABASE_NSS_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), G_TYPE_TLS_DATABASE_NSS, GTlsDatabaseNssClass))
+
+typedef struct _GTlsDatabaseNssPrivate GTlsDatabaseNssPrivate;
+typedef struct _GTlsDatabaseNssClass GTlsDatabaseNssClass;
+typedef struct _GTlsDatabaseNss GTlsDatabaseNss;
+
+struct _GTlsDatabaseNssClass
+{
+ GTlsDatabaseClass parent_class;
+
+};
+
+struct _GTlsDatabaseNss
+{
+ GTlsDatabase parent_instance;
+ GTlsDatabaseNssPrivate *priv;
+};
+
+GType g_tls_database_nss_get_type (void) G_GNUC_CONST;
+
+GTlsCertificateNss *g_tls_database_nss_get_gcert (GTlsDatabaseNss *nss,
+ CERTCertificate *cert,
+ gboolean create);
+void g_tls_database_nss_gcert_created (GTlsDatabaseNss *nss,
+ CERTCertificate *cert,
+ GTlsCertificateNss *gcert);
+
+void g_tls_database_nss_gcert_destroyed (GTlsDatabaseNss *nss,
+ CERTCertificate *cert);
+
+G_END_DECLS
+
+#endif /* __G_TLS_DATABASE_NSS_H___ */
diff --git a/tls/nss/gtlsfiledatabase-nss.c b/tls/nss/gtlsfiledatabase-nss.c
new file mode 100644
index 0000000..96917cd
--- /dev/null
+++ b/tls/nss/gtlsfiledatabase-nss.c
@@ -0,0 +1,318 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright 2011 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "gtlsfiledatabase-nss.h"
+#include "gtlsbackend-nss.h"
+
+#include <gio/gio.h>
+#include <glib/gi18n-lib.h>
+#include <nss.h>
+
+/* NSS only has a single global database. The strategy here then is to
+ * remember which certificates we read out of this file, and then when
+ * asked to do some operation, we have the default database do it, and
+ * then filter the results to only the certs in this database.
+ */
+
+/* The handle format is the same as the GNUTLS backend, for no real
+ * reason other than "that's what the regression tests test for". We
+ * could just as easily chain up.
+ */
+
+static void g_tls_file_database_nss_file_database_interface_init (GTlsFileDatabaseInterface *iface);
+
+static void g_tls_file_database_nss_initable_interface_init (GInitableIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GTlsFileDatabaseNss, g_tls_file_database_nss, G_TYPE_TLS_DATABASE_NSS,
+ G_IMPLEMENT_INTERFACE (G_TYPE_TLS_FILE_DATABASE,
+ g_tls_file_database_nss_file_database_interface_init);
+ G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
+ g_tls_file_database_nss_initable_interface_init);
+);
+
+enum
+{
+ PROP_0,
+ PROP_ANCHORS,
+};
+
+struct _GTlsFileDatabaseNssPrivate
+{
+ /* read-only after construct */
+ gchar *anchor_filename;
+ GHashTable *certs;
+ GTlsDatabase *default_db;
+
+ GHashTable *hashes, *certs_by_hash;
+};
+
+static void
+g_tls_file_database_nss_init (GTlsFileDatabaseNss *nss)
+{
+ nss->priv = G_TYPE_INSTANCE_GET_PRIVATE (nss,
+ G_TYPE_TLS_FILE_DATABASE_NSS,
+ GTlsFileDatabaseNssPrivate);
+ nss->priv->certs = g_hash_table_new_full (NULL, NULL, g_object_unref, NULL);
+ nss->priv->default_db = G_TLS_DATABASE (g_tls_backend_nss_default_database);
+
+ nss->priv->hashes = g_hash_table_new (NULL, NULL);
+ nss->priv->certs_by_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, NULL);
+}
+
+static void
+g_tls_file_database_nss_finalize (GObject *object)
+{
+ GTlsFileDatabaseNss *nss = G_TLS_FILE_DATABASE_NSS (object);
+
+ if (nss->priv->certs)
+ g_hash_table_destroy (nss->priv->certs);
+ if (nss->priv->hashes)
+ g_hash_table_destroy (nss->priv->hashes);
+ if (nss->priv->certs_by_hash)
+ g_hash_table_destroy (nss->priv->certs_by_hash);
+ g_free (nss->priv->anchor_filename);
+
+ G_OBJECT_CLASS (g_tls_file_database_nss_parent_class)->finalize (object);
+}
+
+static void
+g_tls_file_database_nss_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GTlsFileDatabaseNss *nss = G_TLS_FILE_DATABASE_NSS (object);
+
+ switch (prop_id)
+ {
+ case PROP_ANCHORS:
+ g_value_set_string (value, nss->priv->anchor_filename);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+g_tls_file_database_nss_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GTlsFileDatabaseNss *nss = G_TLS_FILE_DATABASE_NSS (object);
+ const gchar *anchor_path;
+
+ switch (prop_id)
+ {
+ case PROP_ANCHORS:
+ anchor_path = g_value_get_string (value);
+ if (anchor_path && !g_path_is_absolute (anchor_path))
+ {
+ g_warning ("The anchor file name for used with a GTlsFileDatabase "
+ "must be an absolute path, and not relative: %s", anchor_path);
+ }
+ else
+ {
+ nss->priv->anchor_filename = g_strdup (anchor_path);
+ }
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static gchar *
+g_tls_file_database_nss_create_certificate_handle (GTlsDatabase *database,
+ GTlsCertificate *certificate)
+{
+ GTlsFileDatabaseNss *nss = G_TLS_FILE_DATABASE_NSS (database);
+ const gchar *hash;
+
+ hash = g_strdup (g_hash_table_lookup (nss->priv->hashes, certificate));
+ if (!hash)
+ return NULL;
+
+ return g_strdup_printf ("file://%s#%s", nss->priv->anchor_filename, hash);
+}
+
+static GTlsCertificate *
+g_tls_file_database_nss_lookup_certificate_for_handle (GTlsDatabase *database,
+ const gchar *handle,
+ GTlsInteraction *interaction,
+ GTlsDatabaseLookupFlags flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GTlsFileDatabaseNss *nss = G_TLS_FILE_DATABASE_NSS (database);
+ GTlsCertificate *cert;
+
+ if (!g_str_has_prefix (handle, "file://"))
+ return NULL;
+ handle += 7;
+ if (!g_str_has_prefix (handle, nss->priv->anchor_filename))
+ return NULL;
+ handle += strlen (nss->priv->anchor_filename);
+ if (*handle != '#')
+ return NULL;
+ handle++;
+
+ cert = g_hash_table_lookup (nss->priv->certs_by_hash, handle);
+ if (cert)
+ g_object_ref (cert);
+ return cert;
+}
+
+static GTlsCertificate *
+g_tls_file_database_nss_lookup_certificate_issuer (GTlsDatabase *database,
+ GTlsCertificate *certificate,
+ GTlsInteraction *interaction,
+ GTlsDatabaseLookupFlags flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GTlsFileDatabaseNss *nss = G_TLS_FILE_DATABASE_NSS (database);
+ GTlsCertificate *issuer;
+
+ issuer = g_tls_database_lookup_certificate_issuer (nss->priv->default_db,
+ certificate, interaction,
+ flags, cancellable,
+ error);
+ if (issuer && g_hash_table_lookup (nss->priv->certs, issuer))
+ return issuer;
+ else if (issuer)
+ g_object_unref (issuer);
+ return NULL;
+}
+
+static GList*
+g_tls_file_database_nss_lookup_certificates_issued_by (GTlsDatabase *database,
+ GByteArray *issuer_raw_dn,
+ GTlsInteraction *interaction,
+ GTlsDatabaseLookupFlags flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GTlsFileDatabaseNss *nss = G_TLS_FILE_DATABASE_NSS (database);
+ GList *certs, *l, *next;
+ GTlsCertificate *cert;
+
+ certs = g_tls_database_lookup_certificates_issued_by (nss->priv->default_db,
+ issuer_raw_dn,
+ interaction, flags,
+ cancellable, error);
+ if (!certs)
+ return NULL;
+
+ for (l = certs; l; l = next)
+ {
+ cert = l->data;
+ next = l->next;
+ if (!g_hash_table_lookup (nss->priv->certs, cert))
+ {
+ g_object_unref (cert);
+ certs = g_list_delete_link (certs, l);
+ }
+ }
+
+ return certs;
+}
+
+static void
+g_tls_file_database_nss_class_init (GTlsFileDatabaseNssClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GTlsDatabaseClass *database_class = G_TLS_DATABASE_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (GTlsFileDatabaseNssPrivate));
+
+ gobject_class->get_property = g_tls_file_database_nss_get_property;
+ gobject_class->set_property = g_tls_file_database_nss_set_property;
+ gobject_class->finalize = g_tls_file_database_nss_finalize;
+
+ database_class->create_certificate_handle = g_tls_file_database_nss_create_certificate_handle;
+ database_class->lookup_certificate_for_handle = g_tls_file_database_nss_lookup_certificate_for_handle;
+ database_class->lookup_certificate_issuer = g_tls_file_database_nss_lookup_certificate_issuer;
+ database_class->lookup_certificates_issued_by = g_tls_file_database_nss_lookup_certificates_issued_by;
+
+ g_object_class_override_property (gobject_class, PROP_ANCHORS, "anchors");
+}
+
+static void
+g_tls_file_database_nss_file_database_interface_init (GTlsFileDatabaseInterface *iface)
+{
+
+}
+
+static gboolean
+g_tls_file_database_nss_initable_init (GInitable *initable,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GTlsFileDatabaseNss *nss = G_TLS_FILE_DATABASE_NSS (initable);
+ GError *my_error = NULL;
+ GList *certs, *c;
+
+ if (!nss->priv->anchor_filename)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
+ _("No certificate database filename specified"));
+ return FALSE;
+ }
+
+ certs = g_tls_certificate_list_new_from_file (nss->priv->anchor_filename,
+ &my_error);
+ if (my_error)
+ {
+ g_propagate_error (error, my_error);
+ return FALSE;
+ }
+
+ for (c = certs; c; c = c->next)
+ {
+ GTlsCertificateNss *nss_cert = c->data;
+ CERTCertificate *cert = g_tls_certificate_nss_get_cert (nss_cert);
+ gchar *hash = g_compute_checksum_for_data (G_CHECKSUM_SHA256,
+ cert->derCert.data,
+ cert->derCert.len);
+
+ g_hash_table_insert (nss->priv->certs, nss_cert, nss_cert);
+ g_hash_table_insert (nss->priv->certs_by_hash, hash, nss_cert);
+ g_hash_table_insert (nss->priv->hashes, nss_cert, hash);
+ }
+ g_list_free (certs);
+
+ return TRUE;
+}
+
+static void
+g_tls_file_database_nss_initable_interface_init (GInitableIface *iface)
+{
+ iface->init = g_tls_file_database_nss_initable_init;
+}
+
+gboolean
+g_tls_file_database_nss_contains (GTlsFileDatabaseNss *nss,
+ GTlsCertificateNss *nss_cert)
+{
+ return g_hash_table_lookup (nss->priv->certs, nss_cert) == nss_cert;
+}
diff --git a/tls/nss/gtlsfiledatabase-nss.h b/tls/nss/gtlsfiledatabase-nss.h
new file mode 100644
index 0000000..8139864
--- /dev/null
+++ b/tls/nss/gtlsfiledatabase-nss.h
@@ -0,0 +1,51 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright 2011 Red Hat, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the licence or (at
+ * your option) any later version.
+ *
+ * See the included COPYING file for more information.
+ */
+
+#ifndef __G_TLS_FILE_DATABASE_NSS_H__
+#define __G_TLS_FILE_DATABASE_NSS_H__
+
+#include <gio/gio.h>
+
+#include "gtlsdatabase-nss.h"
+
+G_BEGIN_DECLS
+
+#define G_TYPE_TLS_FILE_DATABASE_NSS (g_tls_file_database_nss_get_type ())
+#define G_TLS_FILE_DATABASE_NSS(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), G_TYPE_TLS_FILE_DATABASE_NSS, GTlsFileDatabaseNss))
+#define G_TLS_FILE_DATABASE_NSS_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), G_TYPE_TLS_FILE_DATABASE_NSS, GTlsFileDatabaseNssClass))
+#define G_IS_TLS_FILE_DATABASE_NSS(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), G_TYPE_TLS_FILE_DATABASE_NSS))
+#define G_IS_TLS_FILE_DATABASE_NSS_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), G_TYPE_TLS_FILE_DATABASE_NSS))
+#define G_TLS_FILE_DATABASE_NSS_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), G_TYPE_TLS_FILE_DATABASE_NSS, GTlsFileDatabaseNssClass))
+
+typedef struct _GTlsFileDatabaseNssPrivate GTlsFileDatabaseNssPrivate;
+typedef struct _GTlsFileDatabaseNssClass GTlsFileDatabaseNssClass;
+typedef struct _GTlsFileDatabaseNss GTlsFileDatabaseNss;
+
+struct _GTlsFileDatabaseNssClass
+{
+ GTlsDatabaseNssClass parent_class;
+};
+
+struct _GTlsFileDatabaseNss
+{
+ GTlsDatabaseNss parent_instance;
+ GTlsFileDatabaseNssPrivate *priv;
+};
+
+GType g_tls_file_database_nss_get_type (void) G_GNUC_CONST;
+
+gboolean g_tls_file_database_nss_contains (GTlsFileDatabaseNss *nss,
+ GTlsCertificateNss *nss_cert);
+
+G_END_DECLS
+
+#endif /* __G_TLS_FILE_DATABASE_NSS_H___ */
diff --git a/tls/nss/gtlsinputstream-nss.c b/tls/nss/gtlsinputstream-nss.c
new file mode 100644
index 0000000..75ce952
--- /dev/null
+++ b/tls/nss/gtlsinputstream-nss.c
@@ -0,0 +1,147 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright 2011 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include "gtlsinputstream-nss.h"
+
+static void g_tls_input_stream_nss_pollable_iface_init (GPollableInputStreamInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GTlsInputStreamNss, g_tls_input_stream_nss, G_TYPE_INPUT_STREAM,
+ G_IMPLEMENT_INTERFACE (G_TYPE_POLLABLE_INPUT_STREAM, g_tls_input_stream_nss_pollable_iface_init)
+ )
+
+struct _GTlsInputStreamNssPrivate
+{
+ GTlsConnectionNss *conn;
+
+ /* pending operation metadata */
+ GCancellable *cancellable;
+ gpointer buffer;
+ gsize count;
+};
+
+static void
+g_tls_input_stream_nss_dispose (GObject *object)
+{
+ GTlsInputStreamNss *stream = G_TLS_INPUT_STREAM_NSS (object);
+
+ if (stream->priv->conn)
+ {
+ g_object_remove_weak_pointer (G_OBJECT (stream->priv->conn),
+ (gpointer *)&stream->priv->conn);
+ stream->priv->conn = NULL;
+ }
+
+ G_OBJECT_CLASS (g_tls_input_stream_nss_parent_class)->dispose (object);
+}
+
+static gssize
+g_tls_input_stream_nss_read (GInputStream *stream,
+ void *buffer,
+ gsize count,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_return_val_if_reached (-1);
+}
+
+static void
+g_tls_input_stream_nss_read_async (GInputStream *stream,
+ void *buffer,
+ gsize count,
+ gint io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_return_if_reached ();
+}
+
+static gssize
+g_tls_input_stream_nss_read_finish (GInputStream *stream,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_reached (-1);
+}
+
+static gboolean
+g_tls_input_stream_nss_pollable_is_readable (GPollableInputStream *pollable)
+{
+ g_return_val_if_reached (FALSE);
+}
+
+static GSource *
+g_tls_input_stream_nss_pollable_create_source (GPollableInputStream *pollable,
+ GCancellable *cancellable)
+{
+ g_return_val_if_reached (NULL);
+}
+
+static gssize
+g_tls_input_stream_nss_pollable_read_nonblocking (GPollableInputStream *pollable,
+ void *buffer,
+ gsize size,
+ GError **error)
+{
+ g_return_val_if_reached (-1);
+}
+
+static void
+g_tls_input_stream_nss_class_init (GTlsInputStreamNssClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GInputStreamClass *input_stream_class = G_INPUT_STREAM_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (GTlsInputStreamNssPrivate));
+
+ gobject_class->dispose = g_tls_input_stream_nss_dispose;
+
+ input_stream_class->read_fn = g_tls_input_stream_nss_read;
+ input_stream_class->read_async = g_tls_input_stream_nss_read_async;
+ input_stream_class->read_finish = g_tls_input_stream_nss_read_finish;
+}
+
+static void
+g_tls_input_stream_nss_pollable_iface_init (GPollableInputStreamInterface *iface)
+{
+ iface->is_readable = g_tls_input_stream_nss_pollable_is_readable;
+ iface->create_source = g_tls_input_stream_nss_pollable_create_source;
+ iface->read_nonblocking = g_tls_input_stream_nss_pollable_read_nonblocking;
+}
+
+static void
+g_tls_input_stream_nss_init (GTlsInputStreamNss *stream)
+{
+ stream->priv = G_TYPE_INSTANCE_GET_PRIVATE (stream, G_TYPE_TLS_INPUT_STREAM_NSS, GTlsInputStreamNssPrivate);
+}
+
+GInputStream *
+g_tls_input_stream_nss_new (GTlsConnectionNss *conn)
+{
+ GTlsInputStreamNss *tls_stream;
+
+ tls_stream = g_object_new (G_TYPE_TLS_INPUT_STREAM_NSS, NULL);
+ tls_stream->priv->conn = conn;
+ g_object_add_weak_pointer (G_OBJECT (conn),
+ (gpointer *)&tls_stream->priv->conn);
+
+ return G_INPUT_STREAM (tls_stream);
+}
diff --git a/tls/nss/gtlsinputstream-nss.h b/tls/nss/gtlsinputstream-nss.h
new file mode 100644
index 0000000..a1edb5d
--- /dev/null
+++ b/tls/nss/gtlsinputstream-nss.h
@@ -0,0 +1,48 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright 2011 Red Hat, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the licence or (at
+ * your option) any later version.
+ *
+ * See the included COPYING file for more information.
+ */
+
+#ifndef __G_TLS_INPUT_STREAM_NSS_H__
+#define __G_TLS_INPUT_STREAM_NSS_H__
+
+#include <gio/gio.h>
+#include "gtlsconnection-nss.h"
+
+G_BEGIN_DECLS
+
+#define G_TYPE_TLS_INPUT_STREAM_NSS (g_tls_input_stream_nss_get_type ())
+#define G_TLS_INPUT_STREAM_NSS(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), G_TYPE_TLS_INPUT_STREAM_NSS, GTlsInputStreamNss))
+#define G_TLS_INPUT_STREAM_NSS_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), G_TYPE_TLS_INPUT_STREAM_NSS, GTlsInputStreamNssClass))
+#define G_IS_TLS_INPUT_STREAM_NSS(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), G_TYPE_TLS_INPUT_STREAM_NSS))
+#define G_IS_TLS_INPUT_STREAM_NSS_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), G_TYPE_TLS_INPUT_STREAM_NSS))
+#define G_TLS_INPUT_STREAM_NSS_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), G_TYPE_TLS_INPUT_STREAM_NSS, GTlsInputStreamNssClass))
+
+typedef struct _GTlsInputStreamNssPrivate GTlsInputStreamNssPrivate;
+typedef struct _GTlsInputStreamNssClass GTlsInputStreamNssClass;
+typedef struct _GTlsInputStreamNss GTlsInputStreamNss;
+
+struct _GTlsInputStreamNssClass
+{
+ GInputStreamClass parent_class;
+};
+
+struct _GTlsInputStreamNss
+{
+ GInputStream parent_instance;
+ GTlsInputStreamNssPrivate *priv;
+};
+
+GType g_tls_input_stream_nss_get_type (void) G_GNUC_CONST;
+GInputStream *g_tls_input_stream_nss_new (GTlsConnectionNss *conn);
+
+G_END_DECLS
+
+#endif /* __G_TLS_INPUT_STREAM_NSS_H___ */
diff --git a/tls/nss/gtlsoutputstream-nss.c b/tls/nss/gtlsoutputstream-nss.c
new file mode 100644
index 0000000..8c1b7aa
--- /dev/null
+++ b/tls/nss/gtlsoutputstream-nss.c
@@ -0,0 +1,147 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright 2011 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include "gtlsoutputstream-nss.h"
+
+static void g_tls_output_stream_nss_pollable_iface_init (GPollableOutputStreamInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GTlsOutputStreamNss, g_tls_output_stream_nss, G_TYPE_OUTPUT_STREAM,
+ G_IMPLEMENT_INTERFACE (G_TYPE_POLLABLE_OUTPUT_STREAM, g_tls_output_stream_nss_pollable_iface_init)
+ )
+
+struct _GTlsOutputStreamNssPrivate
+{
+ GTlsConnectionNss *conn;
+
+ /* pending operation metadata */
+ GCancellable *cancellable;
+ gconstpointer buffer;
+ gsize count;
+};
+
+static void
+g_tls_output_stream_nss_dispose (GObject *object)
+{
+ GTlsOutputStreamNss *stream = G_TLS_OUTPUT_STREAM_NSS (object);
+
+ if (stream->priv->conn)
+ {
+ g_object_remove_weak_pointer (G_OBJECT (stream->priv->conn),
+ (gpointer *)&stream->priv->conn);
+ stream->priv->conn = NULL;
+ }
+
+ G_OBJECT_CLASS (g_tls_output_stream_nss_parent_class)->dispose (object);
+}
+
+static gssize
+g_tls_output_stream_nss_write (GOutputStream *stream,
+ const void *buffer,
+ gsize count,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_return_val_if_reached (-1);
+}
+
+static void
+g_tls_output_stream_nss_write_async (GOutputStream *stream,
+ const void *buffer,
+ gsize count,
+ gint io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_return_if_reached ();
+}
+
+static gssize
+g_tls_output_stream_nss_write_finish (GOutputStream *stream,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_reached (-1);
+}
+
+static gboolean
+g_tls_output_stream_nss_pollable_is_writable (GPollableOutputStream *pollable)
+{
+ g_return_val_if_reached (FALSE);
+}
+
+static GSource *
+g_tls_output_stream_nss_pollable_create_source (GPollableOutputStream *pollable,
+ GCancellable *cancellable)
+{
+ g_return_val_if_reached (NULL);
+}
+
+static gssize
+g_tls_output_stream_nss_pollable_write_nonblocking (GPollableOutputStream *pollable,
+ const void *buffer,
+ gsize size,
+ GError **error)
+{
+ g_return_val_if_reached (-1);
+}
+
+static void
+g_tls_output_stream_nss_class_init (GTlsOutputStreamNssClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GOutputStreamClass *output_stream_class = G_OUTPUT_STREAM_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (GTlsOutputStreamNssPrivate));
+
+ gobject_class->dispose = g_tls_output_stream_nss_dispose;
+
+ output_stream_class->write_fn = g_tls_output_stream_nss_write;
+ output_stream_class->write_async = g_tls_output_stream_nss_write_async;
+ output_stream_class->write_finish = g_tls_output_stream_nss_write_finish;
+}
+
+static void
+g_tls_output_stream_nss_pollable_iface_init (GPollableOutputStreamInterface *iface)
+{
+ iface->is_writable = g_tls_output_stream_nss_pollable_is_writable;
+ iface->create_source = g_tls_output_stream_nss_pollable_create_source;
+ iface->write_nonblocking = g_tls_output_stream_nss_pollable_write_nonblocking;
+}
+
+static void
+g_tls_output_stream_nss_init (GTlsOutputStreamNss *stream)
+{
+ stream->priv = G_TYPE_INSTANCE_GET_PRIVATE (stream, G_TYPE_TLS_OUTPUT_STREAM_NSS, GTlsOutputStreamNssPrivate);
+}
+
+GOutputStream *
+g_tls_output_stream_nss_new (GTlsConnectionNss *conn)
+{
+ GTlsOutputStreamNss *tls_stream;
+
+ tls_stream = g_object_new (G_TYPE_TLS_OUTPUT_STREAM_NSS, NULL);
+ tls_stream->priv->conn = conn;
+ g_object_add_weak_pointer (G_OBJECT (conn),
+ (gpointer *)&tls_stream->priv->conn);
+
+ return G_OUTPUT_STREAM (tls_stream);
+}
diff --git a/tls/nss/gtlsoutputstream-nss.h b/tls/nss/gtlsoutputstream-nss.h
new file mode 100644
index 0000000..9f56e0f
--- /dev/null
+++ b/tls/nss/gtlsoutputstream-nss.h
@@ -0,0 +1,48 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright 2011 Red Hat, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the licence or (at
+ * your option) any later version.
+ *
+ * See the included COPYING file for more information.
+ */
+
+#ifndef __G_TLS_OUTPUT_STREAM_NSS_H__
+#define __G_TLS_OUTPUT_STREAM_NSS_H__
+
+#include <gio/gio.h>
+#include "gtlsconnection-nss.h"
+
+G_BEGIN_DECLS
+
+#define G_TYPE_TLS_OUTPUT_STREAM_NSS (g_tls_output_stream_nss_get_type ())
+#define G_TLS_OUTPUT_STREAM_NSS(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), G_TYPE_TLS_OUTPUT_STREAM_NSS, GTlsOutputStreamNss))
+#define G_TLS_OUTPUT_STREAM_NSS_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), G_TYPE_TLS_OUTPUT_STREAM_NSS, GTlsOutputStreamNssClass))
+#define G_IS_TLS_OUTPUT_STREAM_NSS(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), G_TYPE_TLS_OUTPUT_STREAM_NSS))
+#define G_IS_TLS_OUTPUT_STREAM_NSS_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), G_TYPE_TLS_OUTPUT_STREAM_NSS))
+#define G_TLS_OUTPUT_STREAM_NSS_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), G_TYPE_TLS_OUTPUT_STREAM_NSS, GTlsOutputStreamNssClass))
+
+typedef struct _GTlsOutputStreamNssPrivate GTlsOutputStreamNssPrivate;
+typedef struct _GTlsOutputStreamNssClass GTlsOutputStreamNssClass;
+typedef struct _GTlsOutputStreamNss GTlsOutputStreamNss;
+
+struct _GTlsOutputStreamNssClass
+{
+ GOutputStreamClass parent_class;
+};
+
+struct _GTlsOutputStreamNss
+{
+ GOutputStream parent_instance;
+ GTlsOutputStreamNssPrivate *priv;
+};
+
+GType g_tls_output_stream_nss_get_type (void) G_GNUC_CONST;
+GOutputStream *g_tls_output_stream_nss_new (GTlsConnectionNss *conn);
+
+G_END_DECLS
+
+#endif /* __G_TLS_OUTPUT_STREAM_NSS_H___ */
diff --git a/tls/nss/gtlsserverconnection-nss.c b/tls/nss/gtlsserverconnection-nss.c
new file mode 100644
index 0000000..db7417c
--- /dev/null
+++ b/tls/nss/gtlsserverconnection-nss.c
@@ -0,0 +1,105 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright 2011 Red Hat, Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include <glib.h>
+
+#include "gtlsserverconnection-nss.h"
+#include <glib/gi18n-lib.h>
+
+enum
+{
+ PROP_0,
+ PROP_AUTHENTICATION_MODE
+};
+
+static void g_tls_server_connection_nss_server_connection_interface_init (GTlsServerConnectionInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GTlsServerConnectionNss, g_tls_server_connection_nss, G_TYPE_TLS_CONNECTION_NSS,
+ G_IMPLEMENT_INTERFACE (G_TYPE_TLS_SERVER_CONNECTION,
+ g_tls_server_connection_nss_server_connection_interface_init))
+
+struct _GTlsServerConnectionNssPrivate
+{
+ GTlsAuthenticationMode authentication_mode;
+};
+
+static void
+g_tls_server_connection_nss_init (GTlsServerConnectionNss *nss)
+{
+ nss->priv = G_TYPE_INSTANCE_GET_PRIVATE (nss, G_TYPE_TLS_SERVER_CONNECTION_NSS, GTlsServerConnectionNssPrivate);
+}
+
+static void
+g_tls_server_connection_nss_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GTlsServerConnectionNss *nss = G_TLS_SERVER_CONNECTION_NSS (object);
+
+ switch (prop_id)
+ {
+ case PROP_AUTHENTICATION_MODE:
+ g_value_set_enum (value, nss->priv->authentication_mode);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+g_tls_server_connection_nss_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GTlsServerConnectionNss *nss = G_TLS_SERVER_CONNECTION_NSS (object);
+
+ switch (prop_id)
+ {
+ case PROP_AUTHENTICATION_MODE:
+ nss->priv->authentication_mode = g_value_get_enum (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+g_tls_server_connection_nss_class_init (GTlsServerConnectionNssClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (GTlsServerConnectionNssPrivate));
+
+ gobject_class->get_property = g_tls_server_connection_nss_get_property;
+ gobject_class->set_property = g_tls_server_connection_nss_set_property;
+
+ g_object_class_override_property (gobject_class, PROP_AUTHENTICATION_MODE, "authentication-mode");
+}
+
+static void
+g_tls_server_connection_nss_server_connection_interface_init (GTlsServerConnectionInterface *iface)
+{
+}
+
diff --git a/tls/nss/gtlsserverconnection-nss.h b/tls/nss/gtlsserverconnection-nss.h
new file mode 100644
index 0000000..6da6a86
--- /dev/null
+++ b/tls/nss/gtlsserverconnection-nss.h
@@ -0,0 +1,47 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright 2011 Red Hat, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the licence or (at
+ * your option) any later version.
+ *
+ * See the included COPYING file for more information.
+ */
+
+#ifndef __G_TLS_SERVER_CONNECTION_NSS_H__
+#define __G_TLS_SERVER_CONNECTION_NSS_H__
+
+#include <gio/gio.h>
+#include "gtlsconnection-nss.h"
+
+G_BEGIN_DECLS
+
+#define G_TYPE_TLS_SERVER_CONNECTION_NSS (g_tls_server_connection_nss_get_type ())
+#define G_TLS_SERVER_CONNECTION_NSS(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), G_TYPE_TLS_SERVER_CONNECTION_NSS, GTlsServerConnectionNss))
+#define G_TLS_SERVER_CONNECTION_NSS_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), G_TYPE_TLS_SERVER_CONNECTION_NSS, GTlsServerConnectionNssClass))
+#define G_IS_TLS_SERVER_CONNECTION_NSS(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), G_TYPE_TLS_SERVER_CONNECTION_NSS))
+#define G_IS_TLS_SERVER_CONNECTION_NSS_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), G_TYPE_TLS_SERVER_CONNECTION_NSS))
+#define G_TLS_SERVER_CONNECTION_NSS_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), G_TYPE_TLS_SERVER_CONNECTION_NSS, GTlsServerConnectionNssClass))
+
+typedef struct _GTlsServerConnectionNssPrivate GTlsServerConnectionNssPrivate;
+typedef struct _GTlsServerConnectionNssClass GTlsServerConnectionNssClass;
+typedef struct _GTlsServerConnectionNss GTlsServerConnectionNss;
+
+struct _GTlsServerConnectionNssClass
+{
+ GTlsConnectionNssClass parent_class;
+};
+
+struct _GTlsServerConnectionNss
+{
+ GTlsConnectionNss parent_instance;
+ GTlsServerConnectionNssPrivate *priv;
+};
+
+GType g_tls_server_connection_nss_get_type (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* __G_TLS_SERVER_CONNECTION_NSS_H___ */
diff --git a/tls/nss/nss-module.c b/tls/nss/nss-module.c
new file mode 100644
index 0000000..a1c36d2
--- /dev/null
+++ b/tls/nss/nss-module.c
@@ -0,0 +1,47 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright 2011 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <gio/gio.h>
+
+#include "gtlsbackend-nss.h"
+
+
+void
+g_io_module_load (GIOModule *module)
+{
+ g_tls_backend_nss_register (module);
+}
+
+void
+g_io_module_unload (GIOModule *module)
+{
+}
+
+gchar **
+g_io_module_query (void)
+{
+ gchar *eps[] = {
+ G_TLS_BACKEND_EXTENSION_POINT_NAME,
+ NULL
+ };
+ return g_strdupv (eps);
+}
diff --git a/tls/tests/Makefile.am b/tls/tests/Makefile.am
index eff0570..daa95de 100644
--- a/tls/tests/Makefile.am
+++ b/tls/tests/Makefile.am
@@ -10,11 +10,25 @@ noinst_PROGRAMS = $(TEST_PROGS)
LDADD = \
$(GLIB_LIBS)
-TEST_PROGS += \
- certificate \
- connection \
+TEST_PROGS += \
+ certificate-gnutls \
+ certificate-nss \
+ connection-gnutls \
+ connection-nss \
$(NULL)
+certificate_gnutls_SOURCES = certificate.c
+certificate_gnutls_CPPFLAGS = -DBACKEND=\""gnutls"\"
+
+connection_gnutls_SOURCES = connection.c
+connection_gnutls_CPPFLAGS = -DBACKEND=\""gnutls"\"
+
+certificate_nss_SOURCES = certificate.c
+certificate_nss_CPPFLAGS = -DBACKEND=\""nss"\"
+
+connection_nss_SOURCES = connection.c
+connection_nss_CPPFLAGS = -DBACKEND=\""nss"\"
+
EXTRA_DIST += \
files \
$(NULL)
diff --git a/tls/tests/certificate.c b/tls/tests/certificate.c
index 79e65e9..a082cac 100644
--- a/tls/tests/certificate.c
+++ b/tls/tests/certificate.c
@@ -63,15 +63,28 @@ static void
test_create_destroy_certificate_pem (TestCertificate *test, gconstpointer data)
{
GTlsCertificate *cert;
- gchar *pem = NULL;
+ gchar *pem = NULL, *test_pem_clean, *cert_pem_clean;
GError *error = NULL;
+ GRegex *re;
cert = g_tls_certificate_new_from_pem (test->pem, test->pem_length, &error);
g_assert_no_error (error);
g_assert (G_IS_TLS_CERTIFICATE (cert));
g_object_get (cert, "certificate-pem", &pem, NULL);
- g_assert_cmpstr (pem, ==, test->pem);
+ g_assert (pem != NULL);
+
+ /* It's OK if they differ in the placement of newlines */
+ re = g_regex_new ("\n", 0, 0, &error);
+ g_assert_no_error (error);
+ test_pem_clean = g_regex_replace_literal (re, test->pem, -1, 0, "", 0, &error);
+ g_assert_no_error (error);
+ cert_pem_clean = g_regex_replace_literal (re, pem, -1, 0, "", 0, &error);
+ g_assert_no_error (error);
+
+ g_assert_cmpstr (cert_pem_clean, ==, test_pem_clean);
+ g_free (test_pem_clean);
+ g_free (cert_pem_clean);
g_free (pem);
g_object_add_weak_pointer (G_OBJECT (cert), (gpointer *)&cert);
@@ -175,6 +188,12 @@ static void
teardown_verify (TestVerify *test,
gconstpointer data)
{
+ g_assert (G_IS_TLS_DATABASE (test->database));
+ g_object_add_weak_pointer (G_OBJECT (test->database),
+ (gpointer *)&test->database);
+ g_object_unref (test->database);
+ g_assert (test->database == NULL);
+
g_assert (G_IS_TLS_CERTIFICATE (test->cert));
g_object_add_weak_pointer (G_OBJECT (test->cert),
(gpointer *)&test->cert);
@@ -187,12 +206,6 @@ teardown_verify (TestVerify *test,
g_object_unref (test->anchor);
g_assert (test->anchor == NULL);
- g_assert (G_IS_TLS_DATABASE (test->database));
- g_object_add_weak_pointer (G_OBJECT (test->database),
- (gpointer *)&test->database);
- g_object_unref (test->database);
- g_assert (test->database == NULL);
-
g_object_add_weak_pointer (G_OBJECT (test->identity),
(gpointer *)&test->identity);
g_object_unref (test->identity);
@@ -566,8 +579,9 @@ main (int argc,
g_type_init ();
g_test_init (&argc, &argv, NULL);
- g_setenv ("GIO_EXTRA_MODULES", TOP_BUILDDIR "/tls/gnutls/.libs", TRUE);
- g_setenv ("GIO_USE_TLS", "gnutls", TRUE);
+ g_setenv ("GIO_EXTRA_MODULES", TOP_BUILDDIR "/tls/" BACKEND "/.libs", TRUE);
+ g_setenv ("GIO_USE_TLS", BACKEND, TRUE);
+ g_assert (g_ascii_strcasecmp (G_OBJECT_TYPE_NAME (g_tls_backend_get_default ()), "GTlsBackend" BACKEND) == 0);
g_test_add_func ("/tls/backend/default-database-is-singleton",
test_default_database_is_singleton);
diff --git a/tls/tests/connection.c b/tls/tests/connection.c
index 1edc7ad..ede441a 100644
--- a/tls/tests/connection.c
+++ b/tls/tests/connection.c
@@ -492,8 +492,9 @@ main (int argc,
g_type_init ();
g_test_init (&argc, &argv, NULL);
- g_setenv ("GIO_EXTRA_MODULES", TOP_BUILDDIR "/tls/gnutls/.libs", TRUE);
- g_setenv ("GIO_USE_TLS", "gnutls", TRUE);
+ g_setenv ("GIO_EXTRA_MODULES", TOP_BUILDDIR "/tls/" BACKEND "/.libs", TRUE);
+ g_setenv ("GIO_USE_TLS", BACKEND, TRUE);
+ g_assert (g_ascii_strcasecmp (G_OBJECT_TYPE_NAME (g_tls_backend_get_default ()), "GTlsBackend" BACKEND) == 0);
g_test_add ("/tls/connection/basic", TestConnection, NULL,
setup_connection, test_basic_connection, teardown_connection);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]