diff --git a/docs/reference/gio/gio-docs.xml b/docs/reference/gio/gio-docs.xml
index d67b79ec5..c7e511e8e 100644
--- a/docs/reference/gio/gio-docs.xml
+++ b/docs/reference/gio/gio-docs.xml
@@ -138,6 +138,10 @@
+
+
+
+
DNS resolution
diff --git a/docs/reference/gio/gio-sections.txt b/docs/reference/gio/gio-sections.txt
index 879f521c3..7aac55876 100644
--- a/docs/reference/gio/gio-sections.txt
+++ b/docs/reference/gio/gio-sections.txt
@@ -3028,9 +3028,11 @@ GTlsBackend
GTlsBackendInterface
g_tls_backend_get_default
g_tls_backend_supports_tls
+g_tls_backend_get_default_database
g_tls_backend_get_certificate_type
g_tls_backend_get_client_connection_type
g_tls_backend_get_server_connection_type
+g_tls_backend_get_file_database_type
G_IS_TLS_BACKEND
G_TLS_BACKEND
@@ -3079,6 +3081,10 @@ g_tls_connection_set_rehandshake_mode
g_tls_connection_get_rehandshake_mode
g_tls_connection_set_use_system_certdb
g_tls_connection_get_use_system_certdb
+g_tls_connection_get_database
+g_tls_connection_set_database
+g_tls_connection_get_interaction
+g_tls_connection_set_interaction
g_tls_connection_handshake
g_tls_connection_handshake_async
@@ -3120,6 +3126,58 @@ G_TYPE_TLS_CLIENT_CONNECTION
g_tls_client_connection_get_type
+
+gtlsdatabase
+GTlsDatabase
+GTlsDatabase
+GTlsDatabaseVerifyFlags
+G_TLS_DATABASE_PURPOSE_AUTHENTICATE_SERVER
+G_TLS_DATABASE_PURPOSE_AUTHENTICATE_CLIENT
+g_tls_database_verify_chain
+g_tls_database_verify_chain_async
+g_tls_database_verify_chain_finish
+GTlsDatabaseLookupFlags
+g_tls_database_lookup_certificate_issuer
+g_tls_database_lookup_certificate_issuer_async
+g_tls_database_lookup_certificate_issuer_finish
+g_tls_database_lookup_certificates_issued_by
+g_tls_database_lookup_certificates_issued_by_async
+g_tls_database_lookup_certificates_issued_by_finish
+g_tls_database_create_certificate_handle
+g_tls_database_lookup_certificate_for_handle
+g_tls_database_lookup_certificate_for_handle_async
+g_tls_database_lookup_certificate_for_handle_finish
+
+G_IS_TLS_DATABASE
+G_IS_TLS_DATABASE_CLASS
+G_TLS_DATABASE
+G_TLS_DATABASE_CLASS
+G_TLS_DATABASE_GET_CLASS
+G_TYPE_TLS_DATABASE
+G_TYPE_TLS_DATABASE_LOOKUP_FLAGS
+G_TYPE_TLS_DATABASE_VERIFY_FLAGS
+
+g_tls_database_lookup_flags_get_type
+g_tls_database_verify_flags_get_type
+g_tls_database_get_type
+GTlsDatabasePrivate
+
+
+
+gtlsfiledatabase
+GTlsFileDatabase
+GTlsFileDatabase
+GTlsFileDatabaseInterface
+g_tls_file_database_new
+
+G_TLS_FILE_DATABASE
+G_TLS_FILE_DATABASE_GET_INTERFACE
+G_TYPE_TLS_FILE_DATABASE
+G_IS_TLS_FILE_DATABASE
+
+g_tls_file_database_get_type
+
+
gtlsserverconnection
GTlsServerConnection
@@ -3135,6 +3193,65 @@ G_TYPE_TLS_SERVER_CONNECTION
g_tls_server_connection_get_type
+
+gtlspassword
+GTlsPassword
+GTlsPassword
+GTlsPasswordInterface
+GTlsPasswordFlags
+g_tls_password_new
+g_tls_password_get_value
+g_tls_password_set_value
+g_tls_password_set_value_full
+g_tls_password_get_description
+g_tls_password_set_description
+g_tls_password_get_flags
+g_tls_password_set_flags
+g_tls_password_get_warning
+g_tls_password_set_warning
+
+g_tls_password_flags_get_type
+g_tls_password_get_type
+G_IS_TLS_PASSWORD
+G_TLS_PASSWORD
+G_TLS_PASSWORD_GET_INTERFACE
+G_TYPE_TLS_PASSWORD
+G_TYPE_TLS_PASSWORD_FLAGS
+
+
+
+gtlsinteraction
+GTlsInteraction
+GTlsInteraction
+GTlsInteractionResult
+g_tls_interaction_ask_password
+g_tls_interaction_ask_password_async
+g_tls_interaction_ask_password_finish
+
+GTlsInteractionClass
+G_IS_TLS_INTERACTION
+G_IS_TLS_INTERACTION_CLASS
+G_TYPE_TLS_INTERACTION
+G_TLS_INTERACTION
+G_TLS_INTERACTION_CLASS
+G_TLS_INTERACTION_GET_CLASS
+G_TYPE_TLS_INTERACTION_RESULT
+
+GTlsInteractionPrivate
+g_tls_interaction_get_type
+g_tls_interaction_result_get_type
+GTlsConsoleInteraction
+GTlsConsoleInteractionClass
+G_IS_TLS_CONSOLE_INTERACTION
+G_IS_TLS_CONSOLE_INTERACTION_CLASS
+g_tls_console_interaction_new
+G_TLS_CONSOLE_INTERACTION
+G_TYPE_TLS_CONSOLE_INTERACTION
+G_TLS_CONSOLE_INTERACTION_CLASS
+G_TLS_CONSOLE_INTERACTION_GET_CLASS
+g_tls_console_interaction_get_type
+
+
gtimezonemonitor
GTimeZoneMonitor
diff --git a/docs/reference/gio/gio.types b/docs/reference/gio/gio.types
index 335e0eba9..685a9008f 100644
--- a/docs/reference/gio/gio.types
+++ b/docs/reference/gio/gio.types
@@ -110,6 +110,8 @@ g_tls_backend_get_type
g_tls_certificate_get_type
g_tls_client_connection_get_type
g_tls_connection_get_type
+g_tls_database_get_type
+g_tls_file_database_get_type
g_tls_server_connection_get_type
g_unix_connection_get_type
g_unix_fd_list_get_type
diff --git a/gio/Makefile.am b/gio/Makefile.am
index 295c60d40..b9f96e80d 100644
--- a/gio/Makefile.am
+++ b/gio/Makefile.am
@@ -382,6 +382,10 @@ libgio_2_0_la_SOURCES = \
gtlscertificate.c \
gtlsclientconnection.c \
gtlsconnection.c \
+ gtlsdatabase.c \
+ gtlsfiledatabase.c \
+ gtlsinteraction.c \
+ gtlspassword.c \
gtlsserverconnection.c \
gunionvolumemonitor.c \
gunionvolumemonitor.h \
@@ -535,6 +539,10 @@ gio_headers = \
gtlscertificate.h \
gtlsclientconnection.h \
gtlsconnection.h \
+ gtlsdatabase.h \
+ gtlsfiledatabase.h \
+ gtlsinteraction.h \
+ gtlspassword.h \
gtlsserverconnection.h \
gvfs.h \
gvolume.h \
diff --git a/gio/gdummytlsbackend.c b/gio/gdummytlsbackend.c
index f297f7401..5a2463bcf 100644
--- a/gio/gdummytlsbackend.c
+++ b/gio/gdummytlsbackend.c
@@ -30,6 +30,8 @@
#include "gtlsbackend.h"
#include "gtlscertificate.h"
#include "gtlsclientconnection.h"
+#include "gtlsdatabase.h"
+#include "gtlsfiledatabase.h"
#include "gtlsserverconnection.h"
#include "gsimpleasyncresult.h"
@@ -40,9 +42,11 @@
static GType _g_dummy_tls_certificate_get_type (void);
static GType _g_dummy_tls_connection_get_type (void);
+static GType _g_dummy_tls_database_get_type (void);
struct _GDummyTlsBackend {
- GObject parent_instance;
+ GObject parent_instance;
+ GTlsDatabase *database;
};
static void g_dummy_tls_backend_iface_init (GTlsBackendInterface *iface);
@@ -67,12 +71,20 @@ g_dummy_tls_backend_class_init (GDummyTlsBackendClass *backend_class)
{
}
+static GTlsDatabase*
+g_dummy_tls_backend_get_default_database (GTlsBackend *backend)
+{
+ return g_object_new (_g_dummy_tls_database_get_type (), NULL);
+}
+
static void
g_dummy_tls_backend_iface_init (GTlsBackendInterface *iface)
{
iface->get_certificate_type = _g_dummy_tls_certificate_get_type;
iface->get_client_connection_type = _g_dummy_tls_connection_get_type;
iface->get_server_connection_type = _g_dummy_tls_connection_get_type;
+ iface->get_file_database_type = _g_dummy_tls_database_get_type;
+ iface->get_default_database = g_dummy_tls_backend_get_default_database;
}
/* Dummy certificate type */
@@ -188,6 +200,7 @@ enum
PROP_CONN_REQUIRE_CLOSE_NOTIFY,
PROP_CONN_REHANDSHAKE_MODE,
PROP_CONN_CERTIFICATE,
+ PROP_CONN_DATABASE,
PROP_CONN_PEER_CERTIFICATE,
PROP_CONN_PEER_CERTIFICATE_ERRORS,
PROP_CONN_VALIDATION_FLAGS,
@@ -251,6 +264,7 @@ g_dummy_tls_connection_class_init (GDummyTlsConnectionClass *connection_class)
g_object_class_override_property (gobject_class, PROP_CONN_REQUIRE_CLOSE_NOTIFY, "require-close-notify");
g_object_class_override_property (gobject_class, PROP_CONN_REHANDSHAKE_MODE, "rehandshake-mode");
g_object_class_override_property (gobject_class, PROP_CONN_CERTIFICATE, "certificate");
+ g_object_class_override_property (gobject_class, PROP_CONN_DATABASE, "database");
g_object_class_override_property (gobject_class, PROP_CONN_PEER_CERTIFICATE, "peer-certificate");
g_object_class_override_property (gobject_class, PROP_CONN_PEER_CERTIFICATE_ERRORS, "peer-certificate-errors");
g_object_class_override_property (gobject_class, PROP_CONN_VALIDATION_FLAGS, "validation-flags");
@@ -281,3 +295,92 @@ g_dummy_tls_connection_initable_iface_init (GInitableIface *iface)
iface->init = g_dummy_tls_connection_initable_init;
}
+/* Dummy database type.
+ */
+
+typedef struct _GDummyTlsDatabase GDummyTlsDatabase;
+typedef struct _GDummyTlsDatabaseClass GDummyTlsDatabaseClass;
+
+struct _GDummyTlsDatabase {
+ GTlsDatabase parent_instance;
+};
+
+struct _GDummyTlsDatabaseClass {
+ GTlsDatabaseClass parent_class;
+};
+
+enum
+{
+ PROP_DATABASE_0,
+
+ PROP_ANCHORS,
+};
+
+static void g_dummy_tls_database_file_database_iface_init (GTlsFileDatabaseInterface *iface);
+static void g_dummy_tls_database_initable_iface_init (GInitableIface *iface);
+
+#define g_dummy_tls_database_get_type _g_dummy_tls_database_get_type
+G_DEFINE_TYPE_WITH_CODE (GDummyTlsDatabase, g_dummy_tls_database, G_TYPE_TLS_DATABASE,
+ G_IMPLEMENT_INTERFACE (G_TYPE_TLS_FILE_DATABASE,
+ g_dummy_tls_database_file_database_iface_init);
+ G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
+ g_dummy_tls_database_initable_iface_init);)
+
+
+static void
+g_dummy_tls_database_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ /* We need to define this method to make GObject happy, but it will
+ * never be possible to construct a working GDummyTlsDatabase, so
+ * it doesn't have to do anything useful.
+ */
+}
+
+static void
+g_dummy_tls_database_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ /* Just ignore all attempts to set properties. */
+}
+
+static void
+g_dummy_tls_database_class_init (GDummyTlsDatabaseClass *database_class)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (database_class);
+
+ gobject_class->get_property = g_dummy_tls_database_get_property;
+ gobject_class->set_property = g_dummy_tls_database_set_property;
+
+ g_object_class_override_property (gobject_class, PROP_ANCHORS, "anchors");
+}
+
+static void
+g_dummy_tls_database_init (GDummyTlsDatabase *database)
+{
+}
+
+static void
+g_dummy_tls_database_file_database_iface_init (GTlsFileDatabaseInterface *iface)
+{
+}
+
+static gboolean
+g_dummy_tls_database_initable_init (GInitable *initable,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_UNAVAILABLE,
+ _("TLS support is not available"));
+ return FALSE;
+}
+
+static void
+g_dummy_tls_database_initable_iface_init (GInitableIface *iface)
+{
+ iface->init = g_dummy_tls_database_initable_init;
+}
diff --git a/gio/gio.h b/gio/gio.h
index 295805992..9281ddef0 100644
--- a/gio/gio.h
+++ b/gio/gio.h
@@ -124,7 +124,11 @@
#include
#include
#include
+#include
+#include
+#include
#include
+#include
#include
#include
#include
diff --git a/gio/gio.symbols b/gio/gio.symbols
index 5189d560a..a1ee3b00f 100644
--- a/gio/gio.symbols
+++ b/gio/gio.symbols
@@ -782,6 +782,7 @@ g_tls_authentication_mode_get_type
g_tls_certificate_flags_get_type
g_tls_rehandshake_mode_get_type
g_emblemed_icon_get_type
+g_tls_database_verify_flags_get_type
g_emblemed_icon_new
g_emblemed_icon_get_icon
g_emblemed_icon_get_emblems
@@ -1428,6 +1429,7 @@ g_tls_certificate_new_from_pem
g_tls_certificate_verify
g_tls_connection_emit_accept_certificate
g_tls_connection_get_certificate
+g_tls_connection_get_interaction
g_tls_connection_get_peer_certificate
g_tls_connection_get_peer_certificate_errors
g_tls_connection_get_rehandshake_mode
@@ -1438,6 +1440,7 @@ g_tls_connection_handshake
g_tls_connection_handshake_async
g_tls_connection_handshake_finish
g_tls_connection_set_certificate
+g_tls_connection_set_interaction
g_tls_connection_set_rehandshake_mode
g_tls_connection_set_require_close_notify
g_tls_connection_set_use_system_certdb
@@ -1452,6 +1455,24 @@ g_tls_client_connection_set_use_ssl3
g_tls_client_connection_set_validation_flags
g_tls_server_connection_get_type
g_tls_server_connection_new
+g_tls_database_get_type
+g_tls_database_lookup_issuer
+g_tls_database_lookup_issuer_async
+g_tls_database_lookup_issuer_finish
+g_tls_database_verify_chain
+g_tls_database_verify_chain_async
+g_tls_database_verify_chain_finish
+g_tls_file_database_get_type
+g_tls_file_database_new
+g_tls_interaction_get_type
+g_tls_interaction_ask_password
+g_tls_interaction_ask_password_finish
+g_tls_password_get_type
+g_tls_password_get_value
+g_tls_password_set_value
+g_tls_password_take_value
+g_tls_password_get_flags
+g_tls_password_get_description
g_time_zone_monitor_get_type
g_time_zone_monitor_get
g_dbus_interface_get_info
diff --git a/gio/gioenums.h b/gio/gioenums.h
index 4ea72a9b5..b724f2a30 100644
--- a/gio/gioenums.h
+++ b/gio/gioenums.h
@@ -1392,6 +1392,48 @@ typedef enum {
G_TLS_REHANDSHAKE_UNSAFELY
} GTlsRehandshakeMode;
+/**
+ * GTlsPasswordFlags:
+ * @G_TLS_PASSWORD_NONE: No flags
+ * @G_TLS_PASSWORD_RETRY: The password was wrong, and the user should retry.
+ * @G_TLS_PASSWORD_MANY_TRIES: Hint to the user that the password has been
+ * wrong many times, and the user may not have many chances left.
+ * @G_TLS_PASSWORD_FINAL_TRY: Hint to the user that this is the last try to get
+ * this password right.
+ *
+ * Various flags for the password.
+ *
+ * Since: 2.30
+ */
+
+typedef enum _GTlsPasswordFlags
+{
+ G_TLS_PASSWORD_NONE = 0,
+ G_TLS_PASSWORD_RETRY = 1 << 1,
+ G_TLS_PASSWORD_MANY_TRIES = 1 << 2,
+ G_TLS_PASSWORD_FINAL_TRY = 1 << 3
+} GTlsPasswordFlags;
+
+/**
+ * GTlsInteractionResult:
+ * @G_TLS_INTERACTION_HANDLED: The interaction completed, and resulting data
+ * is available.
+ * @G_TLS_INTERACTION_ABORTED: The user cancelled the interaction, and requested
+ * the operation to be aborted.
+ * @G_TLS_INTERACTION_UNHANDLED: The interaction was unhandled (i.e. not
+ * implemented).
+ *
+ * #GTlsInteractionResult is returned by various functions in #GTlsInteraction
+ * when finishing an interaction request.
+ *
+ * Since: 2.30
+ */
+typedef enum {
+ G_TLS_INTERACTION_HANDLED,
+ G_TLS_INTERACTION_ABORTED,
+ G_TLS_INTERACTION_UNHANDLED
+} GTlsInteractionResult;
+
/**
* GDBusInterfaceSkeletonFlags:
* @G_DBUS_INTERFACE_SKELETON_FLAGS_NONE: No flags set.
@@ -1428,6 +1470,34 @@ typedef enum
G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_DO_NOT_AUTO_START = (1<<0)
} GDBusObjectManagerClientFlags;
+/**
+ * GTlsDatabaseVerifyFlags:
+ * @G_TLS_DATABASE_VERIFY_NONE: No verification flags
+ *
+ * Flags for g_tls_database_verify_chain().
+ *
+ * Since: 2.30
+ */
+typedef enum {
+ G_TLS_DATABASE_VERIFY_NONE = 0,
+} GTlsDatabaseVerifyFlags;
+
+/**
+ * GTlsDatabaseLookupFlags:
+ * @G_TLS_DATABASE_LOOKUP_NONE: No lookup flags
+ * @G_TLS_DATABASE_LOOKUP_KEYPAIR: Restrict lookup to certificates that have
+ * a private key.
+ *
+ * Flags for g_tls_database_lookup_handle(), g_tls_database_lookup_issuer(),
+ * and g_tls_database_lookup_issued().
+ *
+ * Since: 2.30
+ */
+typedef enum {
+ G_TLS_DATABASE_LOOKUP_NONE = 0,
+ G_TLS_DATABASE_LOOKUP_KEYPAIR = 1,
+} GTlsDatabaseLookupFlags;
+
G_END_DECLS
#endif /* __GIO_ENUMS_H__ */
diff --git a/gio/giotypes.h b/gio/giotypes.h
index af2758681..22855ac3b 100644
--- a/gio/giotypes.h
+++ b/gio/giotypes.h
@@ -206,6 +206,10 @@ typedef struct _GThemedIcon GThemedIcon;
typedef struct _GTlsCertificate GTlsCertificate;
typedef struct _GTlsClientConnection GTlsClientConnection; /* Dummy typedef */
typedef struct _GTlsConnection GTlsConnection;
+typedef struct _GTlsDatabase GTlsDatabase;
+typedef struct _GTlsFileDatabase GTlsFileDatabase;
+typedef struct _GTlsInteraction GTlsInteraction;
+typedef struct _GTlsPassword GTlsPassword;
typedef struct _GTlsServerConnection GTlsServerConnection; /* Dummy typedef */
typedef struct _GVfs GVfs; /* Dummy typedef */
diff --git a/gio/gtlsbackend.c b/gio/gtlsbackend.c
index a87137f36..6cd0e4dae 100644
--- a/gio/gtlsbackend.c
+++ b/gio/gtlsbackend.c
@@ -149,6 +149,28 @@ g_tls_backend_supports_tls (GTlsBackend *backend)
return TRUE;
}
+/**
+ * g_tls_backend_get_default_database:
+ * @backend: the #GTlsBackend
+ *
+ * Gets the default #GTlsDatabase used to verify TLS connections.
+ *
+ * Return value: the default database, which should be unreffed when done.
+ *
+ * Since: 2.30
+ */
+GTlsDatabase *
+g_tls_backend_get_default_database (GTlsBackend *backend)
+{
+ g_return_val_if_fail (G_IS_TLS_BACKEND (backend), NULL);
+
+ /* This method was added later, so accept the (remote) possibility it can be NULL */
+ if (!G_TLS_BACKEND_GET_INTERFACE (backend)->get_default_database)
+ return NULL;
+
+ return G_TLS_BACKEND_GET_INTERFACE (backend)->get_default_database (backend);
+}
+
/**
* g_tls_backend_get_certificate_type:
* @backend: the #GTlsBackend
@@ -199,3 +221,25 @@ g_tls_backend_get_server_connection_type (GTlsBackend *backend)
{
return G_TLS_BACKEND_GET_INTERFACE (backend)->get_server_connection_type ();
}
+
+/**
+ * g_tls_backend_get_file_database_type:
+ * @backend: the #GTlsBackend
+ *
+ * Gets the #GTyep of @backend's #GTlsFileDatabase implementation.
+ *
+ * Return value: the #GType of backend's #GTlsFileDatabase implementation.
+ *
+ * Since: 2.30
+ */
+GType
+g_tls_backend_get_file_database_type (GTlsBackend *backend)
+{
+ g_return_val_if_fail (G_IS_TLS_BACKEND (backend), 0);
+
+ /* This method was added later, so accept the (remote) possibility it can be NULL */
+ if (!G_TLS_BACKEND_GET_INTERFACE (backend)->get_file_database_type)
+ return 0;
+
+ return G_TLS_BACKEND_GET_INTERFACE (backend)->get_file_database_type ();
+}
diff --git a/gio/gtlsbackend.h b/gio/gtlsbackend.h
index 24ae91122..089463f97 100644
--- a/gio/gtlsbackend.h
+++ b/gio/gtlsbackend.h
@@ -58,9 +58,12 @@ typedef struct _GTlsBackendInterface GTlsBackendInterface;
/**
* GTlsBackendInterface:
* @g_iface: The parent interface.
+ * @supports_tls: returns whether the backend supports TLS.
+ * @get_default_database: returns a default #GTlsDatabase instance.
* @get_certificate_type: returns the #GTlsCertificate implementation type
* @get_client_connection_type: returns the #GTlsClientConnection implementation type
* @get_server_connection_type: returns the #GTlsServerConnection implementation type
+ * @get_file_database_type: returns the #GTlsFileDatabase implementation type.
*
* Provides an interface for describing TLS-related types.
*
@@ -71,21 +74,26 @@ struct _GTlsBackendInterface
GTypeInterface g_iface;
/* methods */
- gboolean ( *supports_tls) (GTlsBackend *backend);
- GType ( *get_certificate_type) (void);
- GType ( *get_client_connection_type) (void);
- GType ( *get_server_connection_type) (void);
+ gboolean ( *supports_tls) (GTlsBackend *backend);
+ GType ( *get_certificate_type) (void);
+ GType ( *get_client_connection_type) (void);
+ GType ( *get_server_connection_type) (void);
+ GType ( *get_file_database_type) (void);
+ GTlsDatabase * ( *get_default_database) (GTlsBackend *backend);
};
-GType g_tls_backend_get_type (void) G_GNUC_CONST;
+GType g_tls_backend_get_type (void) G_GNUC_CONST;
-GTlsBackend *g_tls_backend_get_default (void);
+GTlsBackend * g_tls_backend_get_default (void);
-gboolean g_tls_backend_supports_tls (GTlsBackend *backend);
+GTlsDatabase * g_tls_backend_get_default_database (GTlsBackend *backend);
-GType g_tls_backend_get_certificate_type (GTlsBackend *backend);
-GType g_tls_backend_get_client_connection_type (GTlsBackend *backend);
-GType g_tls_backend_get_server_connection_type (GTlsBackend *backend);
+gboolean g_tls_backend_supports_tls (GTlsBackend *backend);
+
+GType g_tls_backend_get_certificate_type (GTlsBackend *backend);
+GType g_tls_backend_get_client_connection_type (GTlsBackend *backend);
+GType g_tls_backend_get_server_connection_type (GTlsBackend *backend);
+GType g_tls_backend_get_file_database_type (GTlsBackend *backend);
G_END_DECLS
diff --git a/gio/gtlsconnection.c b/gio/gtlsconnection.c
index 60c90bfe2..5a8441e49 100644
--- a/gio/gtlsconnection.c
+++ b/gio/gtlsconnection.c
@@ -28,6 +28,8 @@
#include "gtlsbackend.h"
#include "gtlscertificate.h"
#include "gtlsclientconnection.h"
+#include "gtlsdatabase.h"
+#include "gtlsinteraction.h"
#include "glibintl.h"
/**
@@ -77,6 +79,8 @@ enum {
PROP_REQUIRE_CLOSE_NOTIFY,
PROP_REHANDSHAKE_MODE,
PROP_USE_SYSTEM_CERTDB,
+ PROP_DATABASE,
+ PROP_INTERACTION,
PROP_CERTIFICATE,
PROP_PEER_CERTIFICATE,
PROP_PEER_CERTIFICATE_ERRORS
@@ -112,7 +116,7 @@ g_tls_connection_class_init (GTlsConnectionClass *klass)
* verify peer certificates. See
* g_tls_connection_set_use_system_certdb().
*
- * Since: 2.28
+ * Deprecated: 2.30: Use GTlsConnection:database instead
*/
g_object_class_install_property (gobject_class, PROP_USE_SYSTEM_CERTDB,
g_param_spec_boolean ("use-system-certdb",
@@ -122,6 +126,38 @@ g_tls_connection_class_init (GTlsConnectionClass *klass)
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT |
G_PARAM_STATIC_STRINGS));
+ /**
+ * GTlsConnection:database:
+ *
+ * The certificate database to use when verifying this TLS connection.
+ * If no cerificate database is set, then the default database will be
+ * used. See g_tls_backend_get_default_database().
+ *
+ * Since: 2.30
+ */
+ g_object_class_install_property (gobject_class, PROP_DATABASE,
+ g_param_spec_object ("database",
+ P_("Database"),
+ P_("Certificate database to use for looking up or verifying certificates"),
+ G_TYPE_TLS_DATABASE,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+ /**
+ * GTlsConnection:interaction:
+ *
+ * A #GTlsInteraction object to be used when the connection or certificate
+ * database need to interact with the user. This will be used to prompt the
+ * user for passwords where necessary.
+ *
+ * Since: 2.30
+ */
+ g_object_class_install_property (gobject_class, PROP_INTERACTION,
+ g_param_spec_object ("interaction",
+ P_("Interaction"),
+ P_("Optional object for user interaction"),
+ G_TYPE_TLS_INTERACTION,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
/**
* GTlsConnection:require-close-notify:
*
@@ -306,7 +342,7 @@ g_tls_connection_set_property (GObject *object,
* client-side connections, unless that bit is not set in
* #GTlsClientConnection:validation-flags).
*
- * Since: 2.28
+ * Deprecated: 2.30: Use g_tls_connection_set_database() instead
*/
void
g_tls_connection_set_use_system_certdb (GTlsConnection *conn,
@@ -328,7 +364,7 @@ g_tls_connection_set_use_system_certdb (GTlsConnection *conn,
*
* Return value: whether @conn uses the system certificate database
*
- * Since: 2.28
+ * Deprecated: 2.30: Use g_tls_connection_get_database() instead
*/
gboolean
g_tls_connection_get_use_system_certdb (GTlsConnection *conn)
@@ -343,6 +379,60 @@ g_tls_connection_get_use_system_certdb (GTlsConnection *conn)
return use_system_certdb;
}
+/**
+ * g_tls_connection_set_database:
+ * @conn: a #GTlsConnection
+ * @database: a #GTlsDatabase
+ *
+ * Sets the certificate database that is used to verify peer certificates.
+ * This is set to the default database by default. See
+ * g_tls_backend_get_default_database(). If set to %NULL, then
+ * peer certificate validation will always set the
+ * %G_TLS_CERTIFICATE_UNKNOWN_CA error (meaning
+ * #GTlsConnection::accept-certificate will always be emitted on
+ * client-side connections, unless that bit is not set in
+ * #GTlsClientConnection:validation-flags).
+ *
+ * Since: 2.30
+ */
+void
+g_tls_connection_set_database (GTlsConnection *conn,
+ GTlsDatabase *database)
+{
+ g_return_if_fail (G_IS_TLS_CONNECTION (conn));
+ g_return_if_fail (database == NULL || G_IS_TLS_DATABASE (database));
+
+ g_object_set (G_OBJECT (conn),
+ "database", database,
+ NULL);
+}
+
+/**
+ * g_tls_connection_get_database:
+ * @conn: a #GTlsConnection
+ *
+ * Gets the certificate database that @conn uses to verify
+ * peer certificates. See g_tls_connection_set_database().
+ *
+ * Return value: the certificate database that @conn uses or %NULL
+ *
+ * Since: 2.30
+ */
+GTlsDatabase*
+g_tls_connection_get_database (GTlsConnection *conn)
+{
+ GTlsDatabase *database = NULL;
+
+ g_return_val_if_fail (G_IS_TLS_CONNECTION (conn), NULL);
+
+ g_object_get (G_OBJECT (conn),
+ "database", &database,
+ NULL);
+ if (database)
+ g_object_unref (database);
+ return database;
+}
+
/**
* g_tls_connection_set_certificate:
* @conn: a #GTlsConnection
@@ -404,6 +494,56 @@ g_tls_connection_get_certificate (GTlsConnection *conn)
return certificate;
}
+/**
+ * g_tls_connection_set_interaction:
+ * @conn: a connection
+ * @interaction: (allow-none): an interaction object, or %NULL
+ *
+ * Set the object that will be used to interact with the user. It will be used
+ * for things like prompting the user for passwords.
+ *
+ * The @interaction argument will normally be a derived subclass of
+ * #GTlsInteraction. %NULL can also be provided if no user interaction
+ * should occur for this connection.
+ *
+ * Since: 2.30
+ */
+void
+g_tls_connection_set_interaction (GTlsConnection *conn,
+ GTlsInteraction *interaction)
+{
+ g_return_if_fail (G_IS_TLS_CONNECTION (conn));
+ g_return_if_fail (interaction == NULL || G_IS_TLS_INTERACTION (interaction));
+
+ g_object_set (G_OBJECT (conn), "interaction", interaction, NULL);
+}
+
+/**
+ * g_tls_connection_get_interaction:
+ * @conn: a connection
+ *
+ * Get the object that will be used to interact with the user. It will be used
+ * for things like prompting the user for passwords. If %NULL is returned, then
+ * no user interaction will occur for this connection.
+ *
+ * Returns: (transfer none): The interaction object.
+ *
+ * Since: 2.30
+ */
+GTlsInteraction *
+g_tls_connection_get_interaction (GTlsConnection *conn)
+{
+ GTlsInteraction *interaction = NULL;
+
+ g_return_val_if_fail (G_IS_TLS_CONNECTION (conn), NULL);
+
+ g_object_get (G_OBJECT (conn), "interaction", &interaction, NULL);
+ if (interaction)
+ g_object_unref (interaction);
+
+ return interaction;
+}
+
/**
* g_tls_connection_get_peer_certificate:
* @conn: a #GTlsConnection
diff --git a/gio/gtlsconnection.h b/gio/gtlsconnection.h
index 7786c4302..79a8f85ac 100644
--- a/gio/gtlsconnection.h
+++ b/gio/gtlsconnection.h
@@ -83,14 +83,24 @@ struct _GTlsConnectionClass
GType g_tls_connection_get_type (void) G_GNUC_CONST;
+#ifndef G_DISABLE_DEPRECATED
void g_tls_connection_set_use_system_certdb (GTlsConnection *conn,
gboolean use_system_certdb);
gboolean g_tls_connection_get_use_system_certdb (GTlsConnection *conn);
+#endif /* G_DISABLE_DEPRECATED */
+
+void g_tls_connection_set_database (GTlsConnection *conn,
+ GTlsDatabase *database);
+GTlsDatabase * g_tls_connection_get_database (GTlsConnection *conn);
void g_tls_connection_set_certificate (GTlsConnection *conn,
- GTlsCertificate *certificate);
+ GTlsCertificate *certificate);
GTlsCertificate *g_tls_connection_get_certificate (GTlsConnection *conn);
+void g_tls_connection_set_interaction (GTlsConnection *conn,
+ GTlsInteraction *interaction);
+GTlsInteraction * g_tls_connection_get_interaction (GTlsConnection *conn);
+
GTlsCertificate *g_tls_connection_get_peer_certificate (GTlsConnection *conn);
GTlsCertificateFlags g_tls_connection_get_peer_certificate_errors (GTlsConnection *conn);
diff --git a/gio/gtlsdatabase.c b/gio/gtlsdatabase.c
new file mode 100644
index 000000000..9f2ff7bab
--- /dev/null
+++ b/gio/gtlsdatabase.c
@@ -0,0 +1,967 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2010 Collabora, Ltd.
+ *
+ * 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.
+ *
+ * Author: Stef Walter
+ */
+
+#include "config.h"
+
+#include "gtlsdatabase.h"
+
+#include "gasyncresult.h"
+#include "gcancellable.h"
+#include "glibintl.h"
+#include "gsimpleasyncresult.h"
+#include "gsocketconnectable.h"
+#include "gtlscertificate.h"
+#include "gtlsinteraction.h"
+
+/**
+ * SECTION:gtlsdatabase
+ * @short_description: TLS database type
+ * @include: gio/gio.h
+ *
+ * #GTlsDatabase is used to lookup certificates and other information
+ * from a certificate or key store. It is an abstract base class which
+ * TLS library specific subtypes override.
+ *
+ * Most common client applications will not directly interact with
+ * #GTlsDatabase. It is used internally by #GTlsConnection.
+ *
+ * Since: 2.30
+ */
+
+/**
+ * GTlsDatabase:
+ *
+ * Abstract base class for the backend-specific database types.
+ *
+ * Since: 2.30
+ */
+
+G_DEFINE_ABSTRACT_TYPE (GTlsDatabase, g_tls_database, G_TYPE_OBJECT);
+
+enum {
+ UNLOCK_REQUIRED,
+
+ LAST_SIGNAL
+};
+
+/**
+ * G_TLS_DATABASE_PURPOSE_AUTHENTICATE_SERVER:
+ *
+ * The purpose used to verify the server certificate in a TLS connection. This
+ * is the most common purpose in use. Used by TLS clients.
+ */
+
+/**
+ * G_TLS_DATABASE_PURPOSE_AUTHENTICATE_CLIENT:
+ *
+ * The purpose used to verify the client certificate in a TLS connection.
+ * Used by TLS servers.
+ */
+
+static void
+g_tls_database_init (GTlsDatabase *cert)
+{
+
+}
+
+typedef struct _AsyncVerifyChain {
+ GTlsCertificate *chain;
+ gchar *purpose;
+ GSocketConnectable *identity;
+ GTlsInteraction *interaction;
+ GTlsDatabaseVerifyFlags flags;
+ GTlsCertificateFlags verify_result;
+} AsyncVerifyChain;
+
+static void
+async_verify_chain_free (gpointer data)
+{
+ AsyncVerifyChain *args = data;
+ g_clear_object (&args->chain);
+ g_free (args->purpose);
+ g_clear_object (&args->identity);
+ g_clear_object (&args->interaction);
+ g_slice_free (AsyncVerifyChain, args);
+}
+
+static void
+async_verify_chain_thread (GSimpleAsyncResult *res,
+ GObject *object,
+ GCancellable *cancellable)
+{
+ AsyncVerifyChain *args = g_simple_async_result_get_op_res_gpointer (res);
+ GError *error = NULL;
+
+ args->verify_result = g_tls_database_verify_chain (G_TLS_DATABASE (object),
+ args->chain,
+ args->purpose,
+ args->identity,
+ args->interaction,
+ args->flags,
+ cancellable,
+ &error);
+
+ if (error)
+ g_simple_async_result_take_error (res, error);
+}
+
+static void
+g_tls_database_real_verify_chain_async (GTlsDatabase *self,
+ GTlsCertificate *chain,
+ const gchar *purpose,
+ GSocketConnectable *identity,
+ GTlsInteraction *interaction,
+ GTlsDatabaseVerifyFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *res;
+ AsyncVerifyChain *args;
+
+ args = g_slice_new0 (AsyncVerifyChain);
+ args->chain = g_object_ref (chain);
+ args->purpose = g_strdup (purpose);
+ args->identity = identity ? g_object_ref (identity) : NULL;
+ args->interaction = interaction ? g_object_ref (interaction) : NULL;
+ args->flags = flags;
+
+ res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
+ g_tls_database_real_verify_chain_async);
+ g_simple_async_result_set_op_res_gpointer (res, args, async_verify_chain_free);
+ g_simple_async_result_run_in_thread (res, async_verify_chain_thread,
+ G_PRIORITY_DEFAULT, cancellable);
+ g_object_unref (res);
+}
+
+static GTlsCertificateFlags
+g_tls_database_real_verify_chain_finish (GTlsDatabase *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ AsyncVerifyChain *args;
+
+ g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), G_TLS_CERTIFICATE_GENERIC_ERROR);
+ g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
+ g_tls_database_real_verify_chain_async), FALSE);
+
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
+ return G_TLS_CERTIFICATE_GENERIC_ERROR;
+
+ args = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
+ return args->verify_result;
+}
+
+typedef struct {
+ gchar *handle;
+ GTlsInteraction *interaction;
+ GTlsDatabaseLookupFlags flags;
+ GTlsCertificate *result;
+} AsyncLookupCertificateForHandle;
+
+static void
+async_lookup_certificate_for_handle_free (gpointer data)
+{
+ AsyncLookupCertificateForHandle *args = data;
+
+ g_free (args->handle);
+ g_clear_object (&args->interaction);
+ g_clear_object (&args->result);
+ g_slice_free (AsyncLookupCertificateForHandle, args);
+}
+
+static void
+async_lookup_certificate_for_handle_thread (GSimpleAsyncResult *res,
+ GObject *object,
+ GCancellable *cancellable)
+{
+ AsyncLookupCertificateForHandle *args = g_simple_async_result_get_op_res_gpointer (res);
+ GError *error = NULL;
+
+ args->result = g_tls_database_lookup_certificate_for_handle (G_TLS_DATABASE (object),
+ args->handle,
+ args->interaction,
+ args->flags,
+ cancellable,
+ &error);
+
+ if (error)
+ g_simple_async_result_take_error (res, error);
+}
+
+static void
+g_tls_database_real_lookup_certificate_for_handle_async (GTlsDatabase *self,
+ const gchar *handle,
+ GTlsInteraction *interaction,
+ GTlsDatabaseLookupFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *res;
+ AsyncLookupCertificateForHandle *args;
+
+ g_return_if_fail (callback != NULL);
+
+ args = g_slice_new0 (AsyncLookupCertificateForHandle);
+ args->handle = g_strdup (handle);
+ args->interaction = interaction ? g_object_ref (interaction) : NULL;
+
+ res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
+ g_tls_database_real_lookup_certificate_for_handle_async);
+ g_simple_async_result_set_op_res_gpointer (res, args, async_lookup_certificate_for_handle_free);
+ g_simple_async_result_run_in_thread (res, async_lookup_certificate_for_handle_thread,
+ G_PRIORITY_DEFAULT, cancellable);
+ g_object_unref (res);
+}
+
+static GTlsCertificate*
+g_tls_database_real_lookup_certificate_for_handle_finish (GTlsDatabase *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ AsyncLookupCertificateForHandle *args;
+ GTlsCertificate *certificate;
+
+ g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), NULL);
+ g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
+ g_tls_database_real_lookup_certificate_for_handle_async), FALSE);
+
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
+ return NULL;
+
+ args = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
+ certificate = args->result;
+ args->result = NULL;
+ return certificate;
+}
+
+
+typedef struct {
+ GTlsCertificate *certificate;
+ GTlsInteraction *interaction;
+ GTlsDatabaseLookupFlags flags;
+ GTlsCertificate *issuer;
+} AsyncLookupCertificateIssuer;
+
+static void
+async_lookup_certificate_issuer_free (gpointer data)
+{
+ AsyncLookupCertificateIssuer *args = data;
+
+ g_clear_object (&args->certificate);
+ g_clear_object (&args->interaction);
+ g_clear_object (&args->issuer);
+ g_slice_free (AsyncLookupCertificateIssuer, args);
+}
+
+static void
+async_lookup_certificate_issuer_thread (GSimpleAsyncResult *res,
+ GObject *object,
+ GCancellable *cancellable)
+{
+ AsyncLookupCertificateIssuer *args = g_simple_async_result_get_op_res_gpointer (res);
+ GError *error = NULL;
+
+ args->issuer = g_tls_database_lookup_certificate_issuer (G_TLS_DATABASE (object),
+ args->certificate,
+ args->interaction,
+ args->flags,
+ cancellable,
+ &error);
+
+ if (error)
+ g_simple_async_result_take_error (res, error);
+}
+
+static void
+g_tls_database_real_lookup_certificate_issuer_async (GTlsDatabase *self,
+ GTlsCertificate *certificate,
+ GTlsInteraction *interaction,
+ GTlsDatabaseLookupFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *res;
+ AsyncLookupCertificateIssuer *args;
+
+ g_return_if_fail (G_IS_TLS_CERTIFICATE (certificate));
+ g_return_if_fail (callback != NULL);
+
+ args = g_slice_new0 (AsyncLookupCertificateIssuer);
+ args->certificate = g_object_ref (certificate);
+ args->flags = flags;
+ args->interaction = interaction ? g_object_ref (interaction) : NULL;
+
+ res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
+ g_tls_database_real_lookup_certificate_issuer_async);
+ g_simple_async_result_set_op_res_gpointer (res, args, async_lookup_certificate_issuer_free);
+ g_simple_async_result_run_in_thread (res, async_lookup_certificate_issuer_thread,
+ G_PRIORITY_DEFAULT, cancellable);
+ g_object_unref (res);
+}
+
+static GTlsCertificate*
+g_tls_database_real_lookup_certificate_issuer_finish (GTlsDatabase *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ AsyncLookupCertificateIssuer *args;
+ GTlsCertificate *issuer;
+
+ g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), NULL);
+ g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
+ g_tls_database_real_lookup_certificate_issuer_async), FALSE);
+
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
+ return NULL;
+
+ args = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
+ issuer = args->issuer;
+ args->issuer = NULL;
+ return issuer;
+}
+
+typedef struct {
+ GByteArray *issuer;
+ GTlsInteraction *interaction;
+ GTlsDatabaseLookupFlags flags;
+ GList *results;
+} AsyncLookupCertificatesIssuedBy;
+
+static void
+async_lookup_certificates_issued_by_free (gpointer data)
+{
+ AsyncLookupCertificatesIssuedBy *args = data;
+ GList *l;
+
+ g_byte_array_unref (args->issuer);
+ g_clear_object (&args->interaction);
+ for (l = args->results; l; l = g_list_next (l))
+ g_object_unref (l->data);
+ g_list_free (args->results);
+ g_slice_free (AsyncLookupCertificatesIssuedBy, args);
+}
+
+static void
+async_lookup_certificates_issued_by_thread (GSimpleAsyncResult *res,
+ GObject *object,
+ GCancellable *cancellable)
+{
+ AsyncLookupCertificatesIssuedBy *args = g_simple_async_result_get_op_res_gpointer (res);
+ GError *error = NULL;
+
+ args->results = g_tls_database_lookup_certificates_issued_by (G_TLS_DATABASE (object),
+ args->issuer,
+ args->interaction,
+ args->flags,
+ cancellable,
+ &error);
+
+ if (error)
+ g_simple_async_result_take_error (res, error);
+}
+
+static void
+g_tls_database_real_lookup_certificates_issued_by_async (GTlsDatabase *self,
+ GByteArray *issuer,
+ GTlsInteraction *interaction,
+ GTlsDatabaseLookupFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *res;
+ AsyncLookupCertificatesIssuedBy *args;
+
+ g_return_if_fail (callback);
+
+ args = g_slice_new0 (AsyncLookupCertificatesIssuedBy);
+ args->issuer = g_byte_array_ref (issuer);
+ args->flags = flags;
+ args->interaction = interaction ? g_object_ref (interaction) : NULL;
+
+ res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
+ g_tls_database_real_lookup_certificates_issued_by_async);
+ g_simple_async_result_set_op_res_gpointer (res, args, async_lookup_certificates_issued_by_free);
+ g_simple_async_result_run_in_thread (res, async_lookup_certificates_issued_by_thread,
+ G_PRIORITY_DEFAULT, cancellable);
+ g_object_unref (res);
+}
+
+static GList*
+g_tls_database_real_lookup_certificates_issued_by_finish (GTlsDatabase *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ AsyncLookupCertificatesIssuedBy *args;
+ GList *results;
+
+ g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), NULL);
+ g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
+ g_tls_database_real_lookup_certificates_issued_by_async), FALSE);
+
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
+ return NULL;
+
+ args = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
+ results = args->results;
+ args->results = NULL;
+ return results;
+}
+
+static void
+g_tls_database_class_init (GTlsDatabaseClass *klass)
+{
+ klass->verify_chain_async = g_tls_database_real_verify_chain_async;
+ klass->verify_chain_finish = g_tls_database_real_verify_chain_finish;
+ klass->lookup_certificate_for_handle_async = g_tls_database_real_lookup_certificate_for_handle_async;
+ klass->lookup_certificate_for_handle_finish = g_tls_database_real_lookup_certificate_for_handle_finish;
+ klass->lookup_certificate_issuer_async = g_tls_database_real_lookup_certificate_issuer_async;
+ klass->lookup_certificate_issuer_finish = g_tls_database_real_lookup_certificate_issuer_finish;
+ klass->lookup_certificates_issued_by_async = g_tls_database_real_lookup_certificates_issued_by_async;
+ klass->lookup_certificates_issued_by_finish = g_tls_database_real_lookup_certificates_issued_by_finish;
+}
+
+/**
+ * g_tls_database_verify_chain:
+ * @self: a #GTlsDatabase
+ * @chain: a #GTlsCertificate chain
+ * @purpose: the purpose that this certificate chain will be used for.
+ * @identity: (allow-none): the expected peer identity
+ * @interaction: (allow-none): used to interact with the user if necessary
+ * @flags: additional verify flags
+ * @cancellable: (allow-none): a #GCancellable, or %NULL
+ * @error: (allow-none): a #GError, or %NULL
+ *
+ * Verify's a certificate chain after looking up and adding any missing
+ * certificates to the chain.
+ *
+ * @chain is a chain of #GTlsCertificate objects each pointing to the next
+ * certificate in the chain by its %issuer property. The chain may initially
+ * consist of one or more certificates. After the verification process is
+ * complete, @chain may be modified by adding missing certificates, or removing
+ * extra certificates. If a certificate anchor was found, then it is added to
+ * the @chain.
+ *
+ * @purpose describes the purpose (or usage) for which the certificate
+ * is being used. Typically @purpose will be set to #G_TLS_DATABASE_PURPOSE_AUTHENTICATE_SERVER
+ * which means that the certificate is being used to authenticate a server
+ * (and we are acting as the client).
+ *
+ * The @identity is used to check for pinned certificates (trust exceptions)
+ * in the database. These will override the normal verification process on a
+ * host by host basis.
+ *
+ * Currently there are no @flags, and %G_TLS_DATABASE_VERIFY_NONE should be
+ * used.
+ *
+ * This function can block, use g_tls_database_verify_chain_async() to perform
+ * the verification operation asynchronously.
+ *
+ * Return value: the appropriate #GTlsCertificateFlags which represents the
+ * result of verification.
+ *
+ * Since: 2.30
+ */
+GTlsCertificateFlags
+g_tls_database_verify_chain (GTlsDatabase *self,
+ GTlsCertificate *chain,
+ const gchar *purpose,
+ GSocketConnectable *identity,
+ GTlsInteraction *interaction,
+ GTlsDatabaseVerifyFlags flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_return_val_if_fail (G_IS_TLS_DATABASE (self), G_TLS_CERTIFICATE_GENERIC_ERROR);
+ g_return_val_if_fail (G_IS_TLS_DATABASE (self),
+ G_TLS_CERTIFICATE_GENERIC_ERROR);
+ g_return_val_if_fail (G_IS_TLS_CERTIFICATE (chain),
+ G_TLS_CERTIFICATE_GENERIC_ERROR);
+ g_return_val_if_fail (purpose, G_TLS_CERTIFICATE_GENERIC_ERROR);
+ g_return_val_if_fail (interaction == NULL || G_IS_TLS_INTERACTION (interaction),
+ G_TLS_CERTIFICATE_GENERIC_ERROR);
+ g_return_val_if_fail (identity == NULL || G_IS_SOCKET_CONNECTABLE (identity),
+ G_TLS_CERTIFICATE_GENERIC_ERROR);
+ g_return_val_if_fail (error == NULL || *error == NULL, G_TLS_CERTIFICATE_GENERIC_ERROR);
+
+ g_return_val_if_fail (G_TLS_DATABASE_GET_CLASS (self)->verify_chain,
+ G_TLS_CERTIFICATE_GENERIC_ERROR);
+
+ return G_TLS_DATABASE_GET_CLASS (self)->verify_chain (self,
+ chain,
+ purpose,
+ identity,
+ interaction,
+ flags,
+ cancellable,
+ error);
+}
+
+/**
+ * g_tls_database_verify_chain_async:
+ * @self: a #GTlsDatabase
+ * @chain: a #GTlsCertificate chain
+ * @purpose: the purpose that this certificate chain will be used for.
+ * @identity: (allow-none): the expected peer identity
+ * @interaction: (allow-none): used to interact with the user if necessary
+ * @flags: additional verify flags
+ * @cancellable: (allow-none): a #GCancellable, or %NULL
+ * @callback: callback to call when the operation completes
+ * @user_data: the data to pass to the callback function
+ *
+ * Asynchronously verify's a certificate chain after looking up and adding
+ * any missing certificates to the chain. See g_tls_database_verify_chain()
+ * for more information.
+ *
+ * Since: 2.30
+ */
+void
+g_tls_database_verify_chain_async (GTlsDatabase *self,
+ GTlsCertificate *chain,
+ const gchar *purpose,
+ GSocketConnectable *identity,
+ GTlsInteraction *interaction,
+ GTlsDatabaseVerifyFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_return_if_fail (G_IS_TLS_DATABASE (self));
+ g_return_if_fail (G_IS_TLS_CERTIFICATE (chain));
+ g_return_if_fail (purpose != NULL);
+ g_return_if_fail (interaction == NULL || G_IS_TLS_INTERACTION (interaction));
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (identity == NULL || G_IS_SOCKET_CONNECTABLE (identity));
+ g_return_if_fail (callback != NULL);
+
+ g_return_if_fail (G_TLS_DATABASE_GET_CLASS (self)->verify_chain_async);
+ G_TLS_DATABASE_GET_CLASS (self)->verify_chain_async (self,
+ chain,
+ purpose,
+ identity,
+ interaction,
+ flags,
+ cancellable,
+ callback,
+ user_data);
+}
+
+/**
+ * g_tls_database_verify_chain_finish:
+ * @self: a #GTlsDatabase
+ * @result: a #GAsyncResult.
+ * @error: a #GError pointer, or %NULL
+ *
+ * Finish an asynchronous verify chain operation. See
+ * g_tls_database_verify_chain() for more information. *
+ * Return value: the appropriate #GTlsCertificateFlags which represents the
+ * result of verification.
+ *
+ * Since: 2.30
+ */
+GTlsCertificateFlags
+g_tls_database_verify_chain_finish (GTlsDatabase *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (G_IS_TLS_DATABASE (self), G_TLS_CERTIFICATE_GENERIC_ERROR);
+ g_return_val_if_fail (G_IS_ASYNC_RESULT (result), G_TLS_CERTIFICATE_GENERIC_ERROR);
+ g_return_val_if_fail (error == NULL || *error == NULL, G_TLS_CERTIFICATE_GENERIC_ERROR);
+ g_return_val_if_fail (G_TLS_DATABASE_GET_CLASS (self)->verify_chain_finish,
+ G_TLS_CERTIFICATE_GENERIC_ERROR);
+ return G_TLS_DATABASE_GET_CLASS (self)->verify_chain_finish (self,
+ result,
+ error);
+}
+
+/**
+ * g_tls_database_create_certificate_handle:
+ * @self: a #GTlsDatabase
+ * @certificate: certificate for which to create a handle.
+ *
+ * Create a handle string for the certificate. The database will only be able
+ * to create a handle for certificates that originate from the database. In
+ * cases where the database cannot create a handle for a certificate, %NULL
+ * will be returned.
+ *
+ * This handle should be stable across various instances of the application,
+ * and between applications. If a certificate is modified in the database,
+ * then it is not guaranteed that this handle will continue to point to it.
+ *
+ * Returns: (allow-none): a newly allocated string containing the handle.
+ * Since: 2.30
+ */
+gchar*
+g_tls_database_create_certificate_handle (GTlsDatabase *self,
+ GTlsCertificate *certificate)
+{
+ g_return_val_if_fail (G_IS_TLS_DATABASE (self), NULL);
+ g_return_val_if_fail (G_IS_TLS_CERTIFICATE (certificate), NULL);
+ g_return_val_if_fail (G_TLS_DATABASE_GET_CLASS (self)->create_certificate_handle, NULL);
+ return G_TLS_DATABASE_GET_CLASS (self)->create_certificate_handle (self,
+ certificate);
+}
+
+/**
+ * g_tls_database_lookup_certificate_for_handle:
+ * @self: a #GTlsDatabase
+ * @handle: a certificate handle
+ * @interaction: (allow-none): used to interact with the user if necessary
+ * @flags: Flags which affect the lookup.
+ * @cancellable: (allow-none): a #GCancellable, or %NULL
+ * @error: (allow-none): a #GError, or %NULL
+ *
+ * Lookup a certificate by its handle.
+ *
+ * The handle should have been created by calling g_tls_database_create_handle()
+ * on a #GTlsDatabase object of the same TLS backend. The handle is designed
+ * to remain valid across instantiations of the database.
+ *
+ * If the handle is no longer valid, or does not point to a certificate in
+ * this database, then %NULL will be returned.
+ *
+ * This function can block, use g_tls_database_lookup_certificate_for_handle_async() to perform
+ * the lookup operation asynchronously.
+ *
+ * Return value: (transfer full) (allow-none): a newly allocated
+ * #GTlsCertificate, or %NULL. Use g_object_unref() to release the certificate.
+ *
+ * Since: 2.30
+ */
+GTlsCertificate*
+g_tls_database_lookup_certificate_for_handle (GTlsDatabase *self,
+ const gchar *handle,
+ GTlsInteraction *interaction,
+ GTlsDatabaseLookupFlags flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_return_val_if_fail (G_IS_TLS_DATABASE (self), NULL);
+ g_return_val_if_fail (handle != NULL, NULL);
+ g_return_val_if_fail (interaction == NULL || G_IS_TLS_INTERACTION (interaction), NULL);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+ g_return_val_if_fail (G_TLS_DATABASE_GET_CLASS (self)->lookup_certificate_for_handle, NULL);
+ return G_TLS_DATABASE_GET_CLASS (self)->lookup_certificate_for_handle (self,
+ handle,
+ interaction,
+ flags,
+ cancellable,
+ error);
+}
+
+
+/**
+ * g_tls_database_lookup_certificate_for_handle_async:
+ * @self: a #GTlsDatabase
+ * @handle: a certificate handle
+ * @interaction: (allow-none): used to interact with the user if necessary
+ * @flags: Flags which affect the lookup.
+ * @cancellable: (allow-none): a #GCancellable, or %NULL
+ * @callback: callback to call when the operation completes
+ * @user_data: the data to pass to the callback function
+ *
+ * Asynchronously lookup a certificate by its handle in the database. See
+ * g_tls_database_lookup_handle() for more information.
+ *
+ * Since: 2.30
+ */
+void
+g_tls_database_lookup_certificate_for_handle_async (GTlsDatabase *self,
+ const gchar *handle,
+ GTlsInteraction *interaction,
+ GTlsDatabaseLookupFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_return_if_fail (G_IS_TLS_DATABASE (self));
+ g_return_if_fail (handle != NULL);
+ g_return_if_fail (interaction == NULL || G_IS_TLS_INTERACTION (interaction));
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (G_TLS_DATABASE_GET_CLASS (self)->lookup_certificate_for_handle_async);
+ return G_TLS_DATABASE_GET_CLASS (self)->lookup_certificate_for_handle_async (self,
+ handle,
+ interaction,
+ flags,
+ cancellable,
+ callback,
+ user_data);
+}
+
+/**
+ * g_tls_database_lookup_certificate_for_handle_finish:
+ * @self: a #GTlsDatabase
+ * @result: a #GAsyncResult.
+ * @error: a #GError pointer, or %NULL
+ *
+ * Finish an asynchronous lookup of a certificate by its handle. See
+ * g_tls_database_lookup_handle() for more information.
+ *
+ * If the handle is no longer valid, or does not point to a certificate in
+ * this database, then %NULL will be returned.
+ *
+ * Return value: (transfer full): a newly allocated #GTlsCertificate object.
+ * Use g_object_unref() to release the certificate.
+ *
+ * Since: 2.30
+ */
+GTlsCertificate*
+g_tls_database_lookup_certificate_for_handle_finish (GTlsDatabase *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (G_IS_TLS_DATABASE (self), NULL);
+ g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+ g_return_val_if_fail (G_TLS_DATABASE_GET_CLASS (self)->lookup_certificate_for_handle_finish, NULL);
+ return G_TLS_DATABASE_GET_CLASS (self)->lookup_certificate_for_handle_finish (self,
+ result,
+ error);
+}
+
+/**
+ * g_tls_database_lookup_certificate_issuer:
+ * @self: a #GTlsDatabase
+ * @certificate: a #GTlsCertificate
+ * @interaction: (allow-none): used to interact with the user if necessary
+ * @flags: flags which affect the lookup operation
+ * @cancellable: (allow-none): a #GCancellable, or %NULL
+ * @error: (allow-none): a #GError, or %NULL
+ *
+ * Lookup the issuer of @certificate in the database.
+ *
+ * The %issuer property
+ * of @certificate is not modified, and the two certificates are not hooked
+ * into a chain.
+ *
+ * This function can block, use g_tls_database_lookup_certificate_issuer_async() to perform
+ * the lookup operation asynchronously.
+ *
+ * Return value: (transfer full): a newly allocated issuer #GTlsCertificate,
+ * or %NULL. Use g_object_unref() to release the certificate.
+ *
+ * Since: 2.30
+ */
+GTlsCertificate*
+g_tls_database_lookup_certificate_issuer (GTlsDatabase *self,
+ GTlsCertificate *certificate,
+ GTlsInteraction *interaction,
+ GTlsDatabaseLookupFlags flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_return_val_if_fail (G_IS_TLS_DATABASE (self), NULL);
+ g_return_val_if_fail (G_IS_TLS_CERTIFICATE (certificate), NULL);
+ g_return_val_if_fail (interaction == NULL || G_IS_TLS_INTERACTION (interaction), NULL);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+ g_return_val_if_fail (G_TLS_DATABASE_GET_CLASS (self)->lookup_certificate_issuer, NULL);
+ return G_TLS_DATABASE_GET_CLASS (self)->lookup_certificate_issuer (self,
+ certificate,
+ interaction,
+ flags,
+ cancellable,
+ error);
+}
+
+/**
+ * g_tls_database_lookup_certificate_issuer_async:
+ * @self: a #GTlsDatabase
+ * @certificate: a #GTlsCertificate
+ * @interaction: (allow-none): used to interact with the user if necessary
+ * @flags: flags which affect the lookup operation
+ * @cancellable: (allow-none): a #GCancellable, or %NULL
+ * @callback: callback to call when the operation completes
+ * @user_data: the data to pass to the callback function
+ *
+ * Asynchronously lookup the issuer of @certificate in the database. See
+ * g_tls_database_lookup_certificate_issuer() for more information.
+ *
+ * Since: 2.30
+ */
+void
+g_tls_database_lookup_certificate_issuer_async (GTlsDatabase *self,
+ GTlsCertificate *certificate,
+ GTlsInteraction *interaction,
+ GTlsDatabaseLookupFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_return_if_fail (G_IS_TLS_DATABASE (self));
+ g_return_if_fail (G_IS_TLS_CERTIFICATE (certificate));
+ g_return_if_fail (interaction == NULL || G_IS_TLS_INTERACTION (interaction));
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (callback != NULL);
+ g_return_if_fail (G_TLS_DATABASE_GET_CLASS (self)->lookup_certificate_issuer_async);
+ G_TLS_DATABASE_GET_CLASS (self)->lookup_certificate_issuer_async (self,
+ certificate,
+ interaction,
+ flags,
+ cancellable,
+ callback,
+ user_data);
+}
+
+/**
+ * g_tls_database_lookup_certificate_issuer_finish:
+ * @self: a #GTlsDatabase
+ * @result: a #GAsyncResult.
+ * @error: a #GError pointer, or %NULL
+ *
+ * Finish an asynchronous lookup issuer operation. See
+ * g_tls_database_lookup_certificate_issuer() for more information.
+ *
+ * Return value: (transfer full): a newly allocated issuer #GTlsCertificate,
+ * or %NULL. Use g_object_unref() to release the certificate.
+ *
+ * Since: 2.30
+ */
+GTlsCertificate*
+g_tls_database_lookup_certificate_issuer_finish (GTlsDatabase *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (G_IS_TLS_DATABASE (self), NULL);
+ g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+ g_return_val_if_fail (G_TLS_DATABASE_GET_CLASS (self)->lookup_certificate_issuer_finish, NULL);
+ return G_TLS_DATABASE_GET_CLASS (self)->lookup_certificate_issuer_finish (self,
+ result,
+ error);
+}
+
+/**
+ * g_tls_database_lookup_certificates_issued_by:
+ * @self: a #GTlsDatabase
+ * @issuer_raw_dn: a #GByteArray which holds the DER encoded issuer DN.
+ * @interaction: (allow-none): used to interact with the user if necessary
+ * @flags: Flags which affect the lookup operation.
+ * @cancellable: (allow-none): a #GCancellable, or %NULL
+ * @error: (allow-none): a #GError, or %NULL
+ *
+ * Lookup certificates issued by this issuer in the database.
+ *
+ * This function can block, use g_tls_database_lookup_certificates_issued_by_async() to perform
+ * the lookup operation asynchronously.
+ *
+ * Return value: (transfer full): a newly allocated list of #GTlsCertificate objects.
+ * Use g_object_unref() on each certificate, and g_list_free() on the release the list.
+ *
+ * Since: 2.30
+ */
+GList*
+g_tls_database_lookup_certificates_issued_by (GTlsDatabase *self,
+ GByteArray *issuer_raw_dn,
+ GTlsInteraction *interaction,
+ GTlsDatabaseLookupFlags flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_return_val_if_fail (G_IS_TLS_DATABASE (self), NULL);
+ g_return_val_if_fail (issuer_raw_dn, NULL);
+ g_return_val_if_fail (interaction == NULL || G_IS_TLS_INTERACTION (interaction), NULL);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+ g_return_val_if_fail (G_TLS_DATABASE_GET_CLASS (self)->lookup_certificates_issued_by, NULL);
+ return G_TLS_DATABASE_GET_CLASS (self)->lookup_certificates_issued_by (self,
+ issuer_raw_dn,
+ interaction,
+ flags,
+ cancellable,
+ error);
+}
+
+/**
+ * g_tls_database_lookup_certificates_issued_by_async:
+ * @self: a #GTlsDatabase
+ * @issuer_raw_dn: a #GByteArray which holds the DER encoded issuer DN.
+ * @interaction: (allow-none): used to interact with the user if necessary
+ * @flags: Flags which affect the lookup operation.
+ * @cancellable: (allow-none): a #GCancellable, or %NULL
+ * @callback: callback to call when the operation completes
+ * @user_data: the data to pass to the callback function
+ *
+ * Asynchronously lookup certificates issued by this issuer in the database. See
+ * g_tls_database_lookup_certificates_issued_by() for more information.
+ *
+ * The database may choose to hold a reference to the issuer byte array for the duration
+ * of of this asynchronous operation. The byte array should not be modified during
+ * this time.
+ *
+ * Since: 2.30
+ */
+void
+g_tls_database_lookup_certificates_issued_by_async (GTlsDatabase *self,
+ GByteArray *issuer_raw_dn,
+ GTlsInteraction *interaction,
+ GTlsDatabaseLookupFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_return_if_fail (G_IS_TLS_DATABASE (self));
+ g_return_if_fail (issuer_raw_dn != NULL);
+ g_return_if_fail (interaction == NULL || G_IS_TLS_INTERACTION (interaction));
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ g_return_if_fail (callback != NULL);
+ g_return_if_fail (G_TLS_DATABASE_GET_CLASS (self)->lookup_certificates_issued_by_async);
+ G_TLS_DATABASE_GET_CLASS (self)->lookup_certificates_issued_by_async (self,
+ issuer_raw_dn,
+ interaction,
+ flags,
+ cancellable,
+ callback,
+ user_data);
+}
+
+/**
+ * g_tls_database_lookup_certificates_issued_by_finish:
+ * @self: a #GTlsDatabase
+ * @result: a #GAsyncResult.
+ * @error: a #GError pointer, or %NULL
+ *
+ * Finish an asynchronous lookup of certificates. See
+ * g_tls_database_lookup_certificates_issued_by() for more information.
+ *
+ * Return value: (transfer full): a newly allocated list of #GTlsCertificate objects.
+ * Use g_object_unref() on each certificate, and g_list_free() on the release the list.
+ *
+ * Since: 2.30
+ */
+GList*
+g_tls_database_lookup_certificates_issued_by_finish (GTlsDatabase *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (G_IS_TLS_DATABASE (self), NULL);
+ g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+ g_return_val_if_fail (G_TLS_DATABASE_GET_CLASS (self)->lookup_certificates_issued_by_finish, NULL);
+ return G_TLS_DATABASE_GET_CLASS (self)->lookup_certificates_issued_by_finish (self,
+ result,
+ error);
+}
diff --git a/gio/gtlsdatabase.h b/gio/gtlsdatabase.h
new file mode 100644
index 000000000..9f93cc917
--- /dev/null
+++ b/gio/gtlsdatabase.h
@@ -0,0 +1,235 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2010 Collabora, Ltd.
+ *
+ * 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.
+ *
+ * Author: Stef Walter
+ */
+
+#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION)
+#error "Only can be included directly."
+#endif
+
+#ifndef __G_TLS_DATABASE_H__
+#define __G_TLS_DATABASE_H__
+
+#include
+
+G_BEGIN_DECLS
+
+#define G_TLS_DATABASE_PURPOSE_AUTHENTICATE_SERVER "1.3.6.1.5.5.7.3.1"
+#define G_TLS_DATABASE_PURPOSE_AUTHENTICATE_CLIENT "1.3.6.1.5.5.7.3.2"
+
+#define G_TYPE_TLS_DATABASE (g_tls_database_get_type ())
+#define G_TLS_DATABASE(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), G_TYPE_TLS_DATABASE, GTlsDatabase))
+#define G_TLS_DATABASE_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), G_TYPE_TLS_DATABASE, GTlsDatabaseClass))
+#define G_IS_TLS_DATABASE(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), G_TYPE_TLS_DATABASE))
+#define G_IS_TLS_DATABASE_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), G_TYPE_TLS_DATABASE))
+#define G_TLS_DATABASE_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), G_TYPE_TLS_DATABASE, GTlsDatabaseClass))
+
+typedef struct _GTlsDatabaseClass GTlsDatabaseClass;
+typedef struct _GTlsDatabasePrivate GTlsDatabasePrivate;
+
+struct _GTlsDatabase
+{
+ GObject parent_instance;
+
+ GTlsDatabasePrivate *priv;
+};
+
+struct _GTlsDatabaseClass
+{
+ GObjectClass parent_class;
+
+ /* virtual methods */
+
+ GTlsCertificateFlags (*verify_chain) (GTlsDatabase *self,
+ GTlsCertificate *chain,
+ const gchar *purpose,
+ GSocketConnectable *identity,
+ GTlsInteraction *interaction,
+ GTlsDatabaseVerifyFlags flags,
+ GCancellable *cancellable,
+ GError **error);
+
+ void (*verify_chain_async) (GTlsDatabase *self,
+ GTlsCertificate *chain,
+ const gchar *purpose,
+ GSocketConnectable *identity,
+ GTlsInteraction *interaction,
+ GTlsDatabaseVerifyFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+ GTlsCertificateFlags (*verify_chain_finish) (GTlsDatabase *self,
+ GAsyncResult *result,
+ GError **error);
+
+ gchar* (*create_certificate_handle) (GTlsDatabase *self,
+ GTlsCertificate *certificate);
+
+ GTlsCertificate* (*lookup_certificate_for_handle) (GTlsDatabase *self,
+ const gchar *handle,
+ GTlsInteraction *interaction,
+ GTlsDatabaseLookupFlags flags,
+ GCancellable *cancellable,
+ GError **error);
+
+ void (*lookup_certificate_for_handle_async) (GTlsDatabase *self,
+ const gchar *handle,
+ GTlsInteraction *interaction,
+ GTlsDatabaseLookupFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+ GTlsCertificate* (*lookup_certificate_for_handle_finish) (GTlsDatabase *self,
+ GAsyncResult *result,
+ GError **error);
+
+ GTlsCertificate* (*lookup_certificate_issuer) (GTlsDatabase *self,
+ GTlsCertificate *certificate,
+ GTlsInteraction *interaction,
+ GTlsDatabaseLookupFlags flags,
+ GCancellable *cancellable,
+ GError **error);
+
+ void (*lookup_certificate_issuer_async) (GTlsDatabase *self,
+ GTlsCertificate *certificate,
+ GTlsInteraction *interaction,
+ GTlsDatabaseLookupFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+ GTlsCertificate* (*lookup_certificate_issuer_finish) (GTlsDatabase *self,
+ GAsyncResult *result,
+ GError **error);
+
+ GList* (*lookup_certificates_issued_by) (GTlsDatabase *self,
+ GByteArray *issuer_raw_dn,
+ GTlsInteraction *interaction,
+ GTlsDatabaseLookupFlags flags,
+ GCancellable *cancellable,
+ GError **error);
+
+ void (*lookup_certificates_issued_by_async) (GTlsDatabase *self,
+ GByteArray *issuer_raw_dn,
+ GTlsInteraction *interaction,
+ GTlsDatabaseLookupFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+ GList* (*lookup_certificates_issued_by_finish) (GTlsDatabase *self,
+ GAsyncResult *result,
+ GError **error);
+
+ /*< private >*/
+ /* Padding for future expansion */
+ gpointer padding[16];
+};
+
+GType g_tls_database_get_type (void) G_GNUC_CONST;
+
+GTlsCertificateFlags g_tls_database_verify_chain (GTlsDatabase *self,
+ GTlsCertificate *chain,
+ const gchar *purpose,
+ GSocketConnectable *identity,
+ GTlsInteraction *interaction,
+ GTlsDatabaseVerifyFlags flags,
+ GCancellable *cancellable,
+ GError **error);
+
+void g_tls_database_verify_chain_async (GTlsDatabase *self,
+ GTlsCertificate *chain,
+ const gchar *purpose,
+ GSocketConnectable *identity,
+ GTlsInteraction *interaction,
+ GTlsDatabaseVerifyFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GTlsCertificateFlags g_tls_database_verify_chain_finish (GTlsDatabase *self,
+ GAsyncResult *result,
+ GError **error);
+
+gchar* g_tls_database_create_certificate_handle (GTlsDatabase *self,
+ GTlsCertificate *certificate);
+
+GTlsCertificate* g_tls_database_lookup_certificate_for_handle (GTlsDatabase *self,
+ const gchar *handle,
+ GTlsInteraction *interaction,
+ GTlsDatabaseLookupFlags flags,
+ GCancellable *cancellable,
+ GError **error);
+
+void g_tls_database_lookup_certificate_for_handle_async (GTlsDatabase *self,
+ const gchar *handle,
+ GTlsInteraction *interaction,
+ GTlsDatabaseLookupFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GTlsCertificate* g_tls_database_lookup_certificate_for_handle_finish (GTlsDatabase *self,
+ GAsyncResult *result,
+ GError **error);
+
+GTlsCertificate* g_tls_database_lookup_certificate_issuer (GTlsDatabase *self,
+ GTlsCertificate *certificate,
+ GTlsInteraction *interaction,
+ GTlsDatabaseLookupFlags flags,
+ GCancellable *cancellable,
+ GError **error);
+
+void g_tls_database_lookup_certificate_issuer_async (GTlsDatabase *self,
+ GTlsCertificate *certificate,
+ GTlsInteraction *interaction,
+ GTlsDatabaseLookupFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GTlsCertificate* g_tls_database_lookup_certificate_issuer_finish (GTlsDatabase *self,
+ GAsyncResult *result,
+ GError **error);
+
+GList* g_tls_database_lookup_certificates_issued_by (GTlsDatabase *self,
+ GByteArray *issuer_raw_dn,
+ GTlsInteraction *interaction,
+ GTlsDatabaseLookupFlags flags,
+ GCancellable *cancellable,
+ GError **error);
+
+void g_tls_database_lookup_certificates_issued_by_async (GTlsDatabase *self,
+ GByteArray *issuer_raw_dn,
+ GTlsInteraction *interaction,
+ GTlsDatabaseLookupFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GList* g_tls_database_lookup_certificates_issued_by_finish (GTlsDatabase *self,
+ GAsyncResult *result,
+ GError **error);
+
+G_END_DECLS
+
+#endif /* __G_TLS_DATABASE_H__ */
diff --git a/gio/gtlsfiledatabase.c b/gio/gtlsfiledatabase.c
new file mode 100644
index 000000000..0c5972239
--- /dev/null
+++ b/gio/gtlsfiledatabase.c
@@ -0,0 +1,104 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright © 2010 Collabora, Ltd
+ *
+ * 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.
+ *
+ * Author: Stef Walter
+ */
+
+#include "config.h"
+
+#include "gtlsfiledatabase.h"
+
+#include "ginitable.h"
+#include "gtlsbackend.h"
+#include "gtlsdatabase.h"
+#include "glibintl.h"
+
+/**
+ * SECTION:gtlsfiledatabase
+ * @short_description: TLS file based database type
+ * @include: gio/gio.h
+ *
+ * #GTlsFileDatabase is implemented by #GTlsDatabase objects which load
+ * their certificate information from a file. It is in interface which
+ * TLS library specific subtypes implement.
+ *
+ * Since: 2.30
+ */
+
+/**
+ * GTlsFileDatabase:
+ *
+ * Implemented by a #GTlsDatabase which allows you to load certificates
+ * from a file.
+ *
+ * Since: 2.30
+ */
+G_DEFINE_INTERFACE (GTlsFileDatabase, g_tls_file_database, G_TYPE_TLS_DATABASE)
+
+static void
+g_tls_file_database_default_init (GTlsFileDatabaseInterface *iface)
+{
+ /**
+ * GTlsFileDatabase:anchors:
+ *
+ * The path to a file containing PEM encoded certificate authority
+ * root anchors. The certificates in this file will be treated as
+ * root authorities for the purpose of verifying other certificates
+ * via the g_tls_database_verify_chain() operation.
+ *
+ * Since: 2.30
+ */
+ g_object_interface_install_property (iface,
+ g_param_spec_string ("anchors",
+ P_("Anchors"),
+ P_("The certificate authority anchor file"),
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
+}
+
+/**
+ * g_tls_file_database_new:
+ * @anchors: filename of anchor certificate authorities.
+ * @error: #GError for error reporting, or %NULL to ignore.
+ *
+ * Creates a new #GTlsFileDatabase which uses anchor certificate authorities
+ * in @anchors to verify certificate chains.
+ *
+ * The certificates in @anchors must be PEM encoded.
+ *
+ * Return value: the new #GTlsFileDatabase, or %NULL on error
+ *
+ * Since: 2.30
+ */
+GTlsDatabase*
+g_tls_file_database_new (const gchar *anchors,
+ GError **error)
+{
+ GObject *database;
+ GTlsBackend *backend;
+
+ backend = g_tls_backend_get_default ();
+ database = g_initable_new (g_tls_backend_get_file_database_type (backend),
+ NULL, error,
+ "anchors", anchors,
+ NULL);
+ return G_TLS_DATABASE (database);
+}
diff --git a/gio/gtlsfiledatabase.h b/gio/gtlsfiledatabase.h
new file mode 100644
index 000000000..bc6a17ffd
--- /dev/null
+++ b/gio/gtlsfiledatabase.h
@@ -0,0 +1,56 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright © 2010 Collabora, Ltd.
+ *
+ * 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.
+ *
+ * Author: Stef Walter
+ */
+
+#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION)
+#error "Only can be included directly."
+#endif
+
+#ifndef __G_TLS_FILE_DATABASE_H__
+#define __G_TLS_FILE_DATABASE_H__
+
+#include
+
+G_BEGIN_DECLS
+
+#define G_TYPE_TLS_FILE_DATABASE (g_tls_file_database_get_type ())
+#define G_TLS_FILE_DATABASE(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), G_TYPE_TLS_FILE_DATABASE, GTlsFileDatabase))
+#define G_IS_TLS_FILE_DATABASE(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), G_TYPE_TLS_FILE_DATABASE))
+#define G_TLS_FILE_DATABASE_GET_INTERFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), G_TYPE_TLS_FILE_DATABASE, GTlsFileDatabaseInterface))
+
+typedef struct _GTlsFileDatabaseInterface GTlsFileDatabaseInterface;
+
+/**
+ * GTlsFileDatabaseInterface:
+ * @g_iface: The parent interface.
+ *
+ * Provides an interface for #GTlsFileDatabase implementations.
+ *
+ */
+struct _GTlsFileDatabaseInterface
+{
+ GTypeInterface g_iface;
+
+ /*< private >*/
+ /* Padding for future expansion */
+ gpointer padding[8];
+};
+
+GType g_tls_file_database_get_type (void) G_GNUC_CONST;
+
+GTlsDatabase* g_tls_file_database_new (const gchar *anchors,
+ GError **error);
+
+G_END_DECLS
+
+#endif /* __G_TLS_FILE_DATABASE_H___ */
diff --git a/gio/gtlsinteraction.c b/gio/gtlsinteraction.c
new file mode 100644
index 000000000..2e1f7ad71
--- /dev/null
+++ b/gio/gtlsinteraction.c
@@ -0,0 +1,197 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2011 Collabora, Ltd.
+ *
+ * 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.
+ *
+ * Author: Stef Walter
+ */
+
+#include "config.h"
+
+#include
+
+#include "gtlsinteraction.h"
+#include "gtlspassword.h"
+#include "gasyncresult.h"
+#include "gsimpleasyncresult.h"
+#include "gioenumtypes.h"
+#include "glibintl.h"
+
+
+/**
+ * SECTION:gtlsinteraction
+ * @short_description: Interaction with the user during TLS operations.
+ * @include: gio/gio.h
+ *
+ * #GTlsInteraction provides a mechanism for the TLS connection and database
+ * code to interact with the user. It can be used to ask the user for passwords.
+ *
+ * To use a #GTlsInteraction with a TLS connection use
+ * g_tls_connection_set_interaction().
+ *
+ * Callers should instantiate a subclass of this that implements all the
+ * various callbacks to show the required dialogs, such as
+ * #GtkTlsInteraction. If no interaction is desired, usually %NULL can be
+ * passed, see each method taking a #GTlsInteraction for details.
+ */
+
+/**
+ * GTlsInteraction:
+ *
+ * An object representing interaction that the TLS connection and database
+ * might have with the user.
+ *
+ * Since: 2.30
+ */
+
+/**
+ * GTlsInteractionClass:
+ *
+ * The class for #GTlsInteraction.
+ *
+ * Since: 2.30
+ */
+
+G_DEFINE_TYPE (GTlsInteraction, g_tls_interaction, G_TYPE_OBJECT);
+
+GTlsInteractionResult
+g_tls_interaction_default_ask_password (GTlsInteraction *interaction,
+ GTlsPassword *password)
+{
+ return G_TLS_INTERACTION_UNHANDLED;
+}
+
+void
+g_tls_interaction_default_ask_password_async (GTlsInteraction *interaction,
+ GTlsPassword *password,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *res;
+
+ res = g_simple_async_result_new (G_OBJECT (interaction), callback, user_data,
+ g_tls_interaction_default_ask_password);
+ g_simple_async_result_complete_in_idle (res);
+ g_object_unref (res);
+}
+
+GTlsInteractionResult
+g_tls_interaction_default_ask_password_finish (GTlsInteraction *interaction,
+ GAsyncResult *result)
+{
+ g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (interaction),
+ g_tls_interaction_default_ask_password), G_TLS_INTERACTION_UNHANDLED);
+ return G_TLS_INTERACTION_UNHANDLED;
+}
+
+static void
+g_tls_interaction_init (GTlsInteraction *interaction)
+{
+}
+
+static void
+g_tls_interaction_class_init (GTlsInteractionClass *klass)
+{
+ klass->ask_password = g_tls_interaction_default_ask_password;
+ klass->ask_password_async = g_tls_interaction_default_ask_password_async;
+ klass->ask_password_finish = g_tls_interaction_default_ask_password_finish;
+}
+
+/**
+ * g_tls_interaction_ask_password:
+ * @interaction: a #GTlsInteraction object
+ * @password: a #GTlsPassword object
+ *
+ * This function is normally called by #GTlsConnection or #GTlsDatabase to
+ * ask the user for a password.
+ *
+ * Derived subclasses usually implement a password prompt, although they may
+ * also choose to provide a password from elsewhere. The @password value will
+ * be filled in and then @callback will be called. Alternatively the user may
+ * abort this password request, which will usually abort the TLS connection.
+ *
+ * Returns: The status of the ask password interaction.
+ *
+ * Since: 2.30
+ */
+GTlsInteractionResult
+g_tls_interaction_ask_password (GTlsInteraction *interaction,
+ GTlsPassword *password)
+{
+ g_return_val_if_fail (G_IS_TLS_INTERACTION (interaction), G_TLS_INTERACTION_UNHANDLED);
+ g_return_val_if_fail (G_IS_TLS_PASSWORD (password), G_TLS_INTERACTION_UNHANDLED);
+ return G_TLS_INTERACTION_GET_CLASS (interaction)->ask_password (interaction, password);
+}
+
+/**
+ * g_tls_interaction_ask_password_async:
+ * @interaction: a #GTlsInteraction object
+ * @password: a #GTlsPassword object
+ * @callback: will be called when the interaction completes
+ * @user_data: (allow-none): data to pass to the @callback
+ *
+ * This function is normally called by #GTlsConnection or #GTlsDatabase to
+ * ask the user for a password.
+ *
+ * Derived subclasses usually implement a password prompt, although they may
+ * also choose to provide a password from elsewhere. The @password value will
+ * be filled in and then @callback will be called. Alternatively the user may
+ * abort this password request, which will usually abort the TLS connection.
+ *
+ * The @callback will be invoked on thread-default main context of the thread
+ * that called this function. The @callback should call
+ * g_tls_interaction_ask_password_finish() to get the status of the user
+ * interaction.
+ *
+ * Since: 2.30
+ */
+void
+g_tls_interaction_ask_password_async (GTlsInteraction *interaction,
+ GTlsPassword *password,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_return_if_fail (G_IS_TLS_INTERACTION (interaction));
+ g_return_if_fail (G_IS_TLS_PASSWORD (password));
+ g_return_if_fail (callback != NULL);
+ G_TLS_INTERACTION_GET_CLASS (interaction)->ask_password_async (interaction, password,
+ callback, user_data);
+}
+
+/**
+ * g_tls_interaction_ask_password_finish:
+ * @interaction: a #GTlsInteraction object
+ * @result: the result passed to the callback
+ *
+ * Complete an ask password user interaction request. This should be once
+ * the g_tls_interaction_ask_password() completion callback is called.
+ *
+ * If %G_TLS_INTERACTION_HANDLED is returned, then the #GTlsPassword passed
+ * to g_tls_interaction_ask_password() will have its password filled in.
+ *
+ * Returns: The status of the ask password interaction.
+ *
+ * Since: 2.30
+ */
+GTlsInteractionResult
+g_tls_interaction_ask_password_finish (GTlsInteraction *interaction,
+ GAsyncResult *result)
+{
+ g_return_val_if_fail (G_IS_TLS_INTERACTION (interaction), G_TLS_INTERACTION_UNHANDLED);
+ g_return_val_if_fail (G_IS_ASYNC_RESULT (result), G_TLS_INTERACTION_UNHANDLED);
+ return G_TLS_INTERACTION_GET_CLASS (interaction)->ask_password_finish (interaction, result);
+}
diff --git a/gio/gtlsinteraction.h b/gio/gtlsinteraction.h
new file mode 100644
index 000000000..19e234e26
--- /dev/null
+++ b/gio/gtlsinteraction.h
@@ -0,0 +1,88 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2011 Collabora, Ltd.
+ *
+ * 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.
+ *
+ * Author: Stef Walter
+ */
+
+#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION)
+#error "Only can be included directly."
+#endif
+
+#ifndef __G_TLS_INTERACTION_H__
+#define __G_TLS_INTERACTION_H__
+
+#include
+
+G_BEGIN_DECLS
+
+#define G_TYPE_TLS_INTERACTION (g_tls_interaction_get_type ())
+#define G_TLS_INTERACTION(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_TLS_INTERACTION, GTlsInteraction))
+#define G_TLS_INTERACTION_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_TLS_INTERACTION, GTlsInteractionClass))
+#define G_IS_TLS_INTERACTION(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_TLS_INTERACTION))
+#define G_IS_TLS_INTERACTION_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_TLS_INTERACTION))
+#define G_TLS_INTERACTION_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_TLS_INTERACTION, GTlsInteractionClass))
+
+typedef struct _GTlsInteractionClass GTlsInteractionClass;
+typedef struct _GTlsInteractionPrivate GTlsInteractionPrivate;
+
+struct _GTlsInteraction
+{
+ GObject parent_instance;
+
+ GTlsInteractionPrivate *priv;
+};
+
+struct _GTlsInteractionClass
+{
+ GObjectClass parent_class;
+
+ /* virtual methods: */
+
+ GTlsInteractionResult (* ask_password) (GTlsInteraction *interaction,
+ GTlsPassword *password);
+
+ void (* ask_password_async) (GTlsInteraction *interaction,
+ GTlsPassword *password,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+ GTlsInteractionResult (* ask_password_finish) (GTlsInteraction *interaction,
+ GAsyncResult *result);
+
+ /*< private >*/
+ /* Padding for future expansion */
+ gpointer padding[16];
+};
+
+GType g_tls_interaction_get_type (void) G_GNUC_CONST;
+
+GTlsInteractionResult g_tls_interaction_ask_password (GTlsInteraction *interaction,
+ GTlsPassword *password);
+
+void g_tls_interaction_ask_password_async (GTlsInteraction *interaction,
+ GTlsPassword *password,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GTlsInteractionResult g_tls_interaction_ask_password_finish (GTlsInteraction *interaction,
+ GAsyncResult *result);
+
+G_END_DECLS
+
+#endif /* __G_TLS_INTERACTION_H__ */
diff --git a/gio/gtlspassword.c b/gio/gtlspassword.c
new file mode 100644
index 000000000..aa1c35ce1
--- /dev/null
+++ b/gio/gtlspassword.c
@@ -0,0 +1,436 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2011 Collabora, Ltd.
+ *
+ * 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.
+ *
+ * Author: Stef Walter
+ */
+
+#include "config.h"
+#include "glib.h"
+#include "glibintl.h"
+
+#include "gioenumtypes.h"
+#include "gtlspassword.h"
+
+#include
+
+/**
+ * SECTION:gtlspassword
+ * @title: GTlsPassword
+ * @short_description: TLS Passwords for prompting
+ * @include: gio/gio.h
+ *
+ * Holds a password used in TLS.
+ */
+
+/**
+ * GTlsPassword:
+ *
+ * An abstract interface representing a password used in TLS. Often used in
+ * user interaction such as unlocking a key storage token.
+ *
+ * Since: 2.30
+ */
+
+enum
+{
+ PROP_0,
+ PROP_FLAGS,
+ PROP_DESCRIPTION,
+ PROP_WARNING
+};
+
+struct _GTlsPasswordPrivate
+{
+ guchar *value;
+ gsize length;
+ GDestroyNotify destroy;
+ GTlsPasswordFlags flags;
+ gchar *description;
+ gchar *warning;
+};
+
+G_DEFINE_TYPE (GTlsPassword, g_tls_password, G_TYPE_OBJECT);
+
+static void
+g_tls_password_init (GTlsPassword *password)
+{
+ password->priv = G_TYPE_INSTANCE_GET_PRIVATE (password, G_TYPE_TLS_PASSWORD,
+ GTlsPasswordPrivate);
+}
+
+static const guchar *
+g_tls_password_real_get_value (GTlsPassword *password,
+ gsize *length)
+{
+ if (length)
+ *length = password->priv->length;
+ return password->priv->value;
+}
+
+static void
+g_tls_password_real_set_value (GTlsPassword *password,
+ guchar *value,
+ gssize length,
+ GDestroyNotify destroy)
+{
+ if (password->priv->destroy)
+ (password->priv->destroy) (password->priv->value);
+ password->priv->destroy = NULL;
+ password->priv->value = NULL;
+ password->priv->length = 0;
+
+ if (length < 0)
+ length = strlen ((gchar*) value);
+
+ password->priv->value = value;
+ password->priv->length = length;
+ password->priv->destroy = destroy;
+}
+
+static const gchar*
+g_tls_password_real_get_default_warning (GTlsPassword *password)
+{
+ GTlsPasswordFlags flags;
+
+ flags = g_tls_password_get_flags (password);
+
+ if (flags & G_TLS_PASSWORD_FINAL_TRY)
+ return _("This is the last chance to ether the password correctly before your access is locked out.");
+ if (flags & G_TLS_PASSWORD_MANY_TRIES)
+ return _("Several password entered have been incorrect, and your access will be locked out after further failures.");
+ if (flags & G_TLS_PASSWORD_RETRY)
+ return _("The password entered is incorrect.");
+
+ return NULL;
+}
+
+static void
+g_tls_password_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GTlsPassword *password = G_TLS_PASSWORD (object);
+
+ switch (prop_id)
+ {
+ case PROP_FLAGS:
+ g_value_set_flags (value, g_tls_password_get_flags (password));
+ break;
+ case PROP_WARNING:
+ g_value_set_string (value, g_tls_password_get_warning (password));
+ break;
+ case PROP_DESCRIPTION:
+ g_value_set_string (value, g_tls_password_get_description (password));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+g_tls_password_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GTlsPassword *password = G_TLS_PASSWORD (object);
+
+ switch (prop_id)
+ {
+ case PROP_FLAGS:
+ g_tls_password_set_flags (password, g_value_get_flags (value));
+ break;
+ case PROP_WARNING:
+ g_tls_password_set_warning (password, g_value_get_string (value));
+ break;
+ case PROP_DESCRIPTION:
+ g_tls_password_set_description (password, g_value_get_string (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+g_tls_password_finalize (GObject *object)
+{
+ GTlsPassword *password = G_TLS_PASSWORD (object);
+
+ g_tls_password_real_set_value (password, NULL, 0, NULL);
+ g_free (password->priv->warning);
+ g_free (password->priv->description);
+
+ G_OBJECT_CLASS (g_tls_password_parent_class)->finalize (object);
+}
+
+static void
+g_tls_password_class_init (GTlsPasswordClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ klass->get_value = g_tls_password_real_get_value;
+ klass->set_value = g_tls_password_real_set_value;
+ klass->get_default_warning = g_tls_password_real_get_default_warning;
+
+ gobject_class->get_property = g_tls_password_get_property;
+ gobject_class->set_property = g_tls_password_set_property;
+ gobject_class->finalize = g_tls_password_finalize;
+
+ g_type_class_add_private (klass, sizeof (GTlsPasswordPrivate));
+
+ g_object_class_install_property (gobject_class, PROP_FLAGS,
+ g_param_spec_flags ("flags", "Flags", "Flags about the password",
+ G_TYPE_TLS_PASSWORD_FLAGS, G_TLS_PASSWORD_NONE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (gobject_class, PROP_DESCRIPTION,
+ g_param_spec_string ("description", "Description", "Description of what the password is for",
+ "", G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (gobject_class, PROP_WARNING,
+ g_param_spec_string ("warning", "Warning", "Warning about the password",
+ "", G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+}
+
+/**
+ * g_tls_password_new:
+ * @flags: the password flags
+ * @description: description of what the password is for
+ *
+ * Create a new #GTlsPassword object.
+ *
+ * Returns: (transfer full): The newly allocated password object
+ */
+GTlsPassword *
+g_tls_password_new (GTlsPasswordFlags flags,
+ const gchar *description)
+{
+ return g_object_new (G_TYPE_TLS_PASSWORD,
+ "flags", flags,
+ "description", description,
+ NULL);
+}
+
+/**
+ * g_tls_password_get_value:
+ * @password: a #GTlsPassword object
+ * @length: (allow-none): location to place the length of the password.
+ *
+ * Get the password value. If @length is not %NULL then it will be filled
+ * in with the length of the password value.
+ *
+ * Returns: The password value owned by the password object.
+ *
+ * Since: 2.30
+ */
+const guchar *
+g_tls_password_get_value (GTlsPassword *password,
+ gsize *length)
+{
+ g_return_val_if_fail (G_IS_TLS_PASSWORD (password), NULL);
+ return G_TLS_PASSWORD_GET_CLASS (password)->get_value (password, length);
+}
+
+/**
+ * g_tls_password_set_value:
+ * @password: a #GTlsPassword object
+ * @value: the new password value
+ * @length: the length of the password, or -1
+ *
+ * Set the value for this password. The @value will be copied by the password
+ * object.
+ *
+ * Specify the @length, for a non-null-terminated password. Pass -1 as
+ * @length if using a null-terminated password, and @length will be calculated
+ * automatically.
+ *
+ * Since: 2.30
+ */
+void
+g_tls_password_set_value (GTlsPassword *password,
+ const guchar *value,
+ gssize length)
+{
+ g_return_if_fail (G_IS_TLS_PASSWORD (password));
+
+ if (length < 0)
+ length = strlen ((gchar *)value);
+
+ g_tls_password_set_value_full (password, g_memdup (value, length), length, g_free);
+}
+
+/**
+ * g_tls_password_set_value_full:
+ * @password: a #GTlsPassword object
+ * @value: the value for the password
+ * @length: the length of the password, or -1
+ * @destroy: (allow-none): a function to use to free the password.
+ *
+ * Provide the value for this password.
+ *
+ * The @value will be owned by the password object, and later freed using
+ * the @destroy function callback.
+ *
+ * Specify the @length, for a non-null-terminated password. Pass -1 as
+ * @length if using a null-terminated password, and @length will be calculated
+ * automatically.
+ *
+ * Since: 2.30
+ */
+void
+g_tls_password_set_value_full (GTlsPassword *password,
+ guchar *value,
+ gssize length,
+ GDestroyNotify destroy)
+{
+ g_return_if_fail (G_IS_TLS_PASSWORD (password));
+ G_TLS_PASSWORD_GET_CLASS (password)->set_value (password, value,
+ length, destroy);
+}
+
+/**
+ * g_tls_password_get_flags:
+ * @password: a #GTlsPassword object
+ *
+ * Get flags about the password.
+ *
+ * Return value: The flags about the password.
+ *
+ * Since: 2.30
+ */
+GTlsPasswordFlags
+g_tls_password_get_flags (GTlsPassword *password)
+{
+ g_return_val_if_fail (G_IS_TLS_PASSWORD (password), G_TLS_PASSWORD_NONE);
+ return password->priv->flags;
+}
+
+/**
+ * g_tls_password_set_flags:
+ * @password: a #GTlsPassword object
+ * @flags: The flags about the password
+ *
+ * Set flags about the password.
+ *
+ * Since: 2.30
+ */
+void
+g_tls_password_set_flags (GTlsPassword *password,
+ GTlsPasswordFlags flags)
+{
+ g_return_if_fail (G_IS_TLS_PASSWORD (password));
+
+ password->priv->flags = flags;
+
+ g_object_notify (G_OBJECT (password), "flags");
+}
+
+/**
+ * g_tls_password_get_description:
+ * @password: a #GTlsPassword object
+ *
+ * Get a description string about what the password will be used for.
+ *
+ * Return value: The description of the password.
+ *
+ * Since: 2.30
+ */
+const gchar*
+g_tls_password_get_description (GTlsPassword *password)
+{
+ g_return_val_if_fail (G_IS_TLS_PASSWORD (password), NULL);
+ return password->priv->description;
+}
+
+/**
+ * g_tls_password_set_description:
+ * @password: a #GTlsPassword object
+ * @flags: The description of the password
+ *
+ * Set a description string about what the password will be used for.
+ *
+ * Since: 2.30
+ */
+void
+g_tls_password_set_description (GTlsPassword *password,
+ const gchar *description)
+{
+ gchar *copy;
+
+ g_return_if_fail (G_IS_TLS_PASSWORD (password));
+
+ copy = g_strdup (description);
+ g_free (password->priv->description);
+ password->priv->description = copy;
+
+ g_object_notify (G_OBJECT (password), "description");
+}
+
+/**
+ * g_tls_password_get_warning:
+ * @password: a #GTlsPassword object
+ *
+ * Get a user readable translated warning. Usually this warning is a
+ * representation of the password flags returned from
+ * g_tls_password_get_flags().
+ *
+ * Return value: The warning.
+ *
+ * Since: 2.30
+ */
+const gchar *
+g_tls_password_get_warning (GTlsPassword *password)
+{
+ g_return_val_if_fail (G_IS_TLS_PASSWORD (password), NULL);
+
+ if (password->priv->warning == NULL)
+ return G_TLS_PASSWORD_GET_CLASS (password)->get_default_warning (password);
+
+ return password->priv->warning;
+}
+
+/**
+ * g_tls_password_set_warning:
+ * @password: a #GTlsPassword object
+ * @warning: The user readable warning
+ *
+ * Set a user readable translated warning. Usually this warning is a
+ * representation of the password flags returned from
+ * g_tls_password_get_flags().
+ *
+ * Since: 2.30
+ */
+void
+g_tls_password_set_warning (GTlsPassword *password,
+ const gchar *warning)
+{
+ gchar *copy;
+
+ g_return_if_fail (G_IS_TLS_PASSWORD (password));
+
+ copy = g_strdup (warning);
+ g_free (password->priv->warning);
+ password->priv->warning = copy;
+
+ g_object_notify (G_OBJECT (password), "warning");
+}
diff --git a/gio/gtlspassword.h b/gio/gtlspassword.h
new file mode 100644
index 000000000..ef581b61e
--- /dev/null
+++ b/gio/gtlspassword.h
@@ -0,0 +1,101 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2011 Collabora, Ltd.
+ *
+ * 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.
+ *
+ * Author: Stef Walter
+ */
+
+#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION)
+#error "Only can be included directly."
+#endif
+
+#ifndef __G_TLS_PASSWORD_H__
+#define __G_TLS_PASSWORD_H__
+
+#include
+
+G_BEGIN_DECLS
+
+#define G_TYPE_TLS_PASSWORD (g_tls_password_get_type ())
+#define G_TLS_PASSWORD(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_TLS_PASSWORD, GTlsPassword))
+#define G_TLS_PASSWORD_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_TLS_PASSWORD, GTlsPasswordClass))
+#define G_IS_TLS_PASSWORD(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_TLS_PASSWORD))
+#define G_IS_TLS_PASSWORD_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_TLS_PASSWORD))
+#define G_TLS_PASSWORD_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_TLS_PASSWORD, GTlsPasswordClass))
+
+typedef struct _GTlsPasswordClass GTlsPasswordClass;
+typedef struct _GTlsPasswordPrivate GTlsPasswordPrivate;
+
+struct _GTlsPassword
+{
+ GObject parent_instance;
+
+ GTlsPasswordPrivate *priv;
+};
+
+struct _GTlsPasswordClass
+{
+ GObjectClass parent_class;
+
+ /* methods */
+
+ const guchar * ( *get_value) (GTlsPassword *password,
+ gsize *length);
+
+ void ( *set_value) (GTlsPassword *password,
+ guchar *value,
+ gssize length,
+ GDestroyNotify destroy);
+
+ const gchar* ( *get_default_warning) (GTlsPassword *password);
+
+ /*< private >*/
+ /* Padding for future expansion */
+ gpointer padding[4];
+};
+
+GType g_tls_password_get_type (void) G_GNUC_CONST;
+
+GTlsPassword * g_tls_password_new (GTlsPasswordFlags flags,
+ const gchar *description);
+
+const guchar * g_tls_password_get_value (GTlsPassword *password,
+ gsize *length);
+void g_tls_password_set_value (GTlsPassword *password,
+ const guchar *value,
+ gssize length);
+void g_tls_password_set_value_full (GTlsPassword *password,
+ guchar *value,
+ gssize length,
+ GDestroyNotify destroy);
+
+GTlsPasswordFlags g_tls_password_get_flags (GTlsPassword *password);
+void g_tls_password_set_flags (GTlsPassword *password,
+ GTlsPasswordFlags flags);
+
+const gchar* g_tls_password_get_description (GTlsPassword *password);
+void g_tls_password_set_description (GTlsPassword *password,
+ const gchar *description);
+
+const gchar * g_tls_password_get_warning (GTlsPassword *password);
+void g_tls_password_set_warning (GTlsPassword *password,
+ const gchar *warning);
+
+G_END_DECLS
+
+#endif /* __G_TLS_PASSWORD_H__ */
diff --git a/gio/tests/.gitignore b/gio/tests/.gitignore
index 7df867e94..a24e33207 100644
--- a/gio/tests/.gitignore
+++ b/gio/tests/.gitignore
@@ -78,6 +78,7 @@ socket-client
socket-server
srvtarget
test.mo
+tls
unix-fd
unix-streams
volumemonitor
diff --git a/gio/tests/Makefile.am b/gio/tests/Makefile.am
index f7d8e084c..d27c68f0d 100644
--- a/gio/tests/Makefile.am
+++ b/gio/tests/Makefile.am
@@ -202,7 +202,9 @@ socket_server_SOURCES = socket-server.c
socket_server_LDADD = $(progs_ldadd) \
$(top_builddir)/gthread/libgthread-2.0.la
-socket_client_SOURCES = socket-client.c
+socket_client_SOURCES = socket-client.c \
+ gtlsconsoleinteraction.c \
+ gtlsconsoleinteraction.h
socket_client_LDADD = $(progs_ldadd) \
$(top_builddir)/gthread/libgthread-2.0.la
diff --git a/gio/tests/gtlsconsoleinteraction.c b/gio/tests/gtlsconsoleinteraction.c
new file mode 100644
index 000000000..470e6dbef
--- /dev/null
+++ b/gio/tests/gtlsconsoleinteraction.c
@@ -0,0 +1,107 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2011 Collabora, Ltd.
+ *
+ * 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.
+ *
+ * Author: Stef Walter
+ */
+
+#include "config.h"
+
+#include
+
+#include "gtlsconsoleinteraction.h"
+
+/*
+ * WARNING: This is not the example you're looking for [slow hand wave]. This
+ * is not industrial strength, it's just for testing. It uses embarassing
+ * functions like getpass() and does lazy things with threads.
+ */
+
+G_DEFINE_TYPE (GTlsConsoleInteraction, g_tls_console_interaction, G_TYPE_TLS_INTERACTION);
+
+static GTlsInteractionResult
+g_tls_console_interaction_ask_password (GTlsInteraction *interaction,
+ GTlsPassword *password)
+{
+ const gchar *value;
+ gchar *prompt;
+
+ prompt = g_strdup_printf ("Password \"%s\"': ", g_tls_password_get_description (password));
+ value = getpass (prompt);
+ g_free (prompt);
+
+ g_tls_password_set_value (password, (guchar *)value, -1);
+ return G_TLS_INTERACTION_HANDLED;
+}
+
+static void
+ask_password_with_getpass (GSimpleAsyncResult *res,
+ GObject *object,
+ GCancellable *cancellable)
+{
+ GTlsPassword *password;
+
+ password = g_simple_async_result_get_op_res_gpointer (res);
+ g_tls_console_interaction_ask_password (G_TLS_INTERACTION (object), password);
+}
+
+void
+g_tls_console_interaction_ask_password_async (GTlsInteraction *interaction,
+ GTlsPassword *password,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *res;
+
+ res = g_simple_async_result_new (G_OBJECT (interaction), callback, user_data,
+ g_tls_console_interaction_ask_password);
+ g_simple_async_result_set_op_res_gpointer (res, g_object_ref (password), g_object_unref);
+ g_simple_async_result_run_in_thread (res, ask_password_with_getpass,
+ G_PRIORITY_DEFAULT, NULL);
+ g_object_unref (res);
+}
+
+GTlsInteractionResult
+g_tls_console_interaction_ask_password_finish (GTlsInteraction *interaction,
+ GAsyncResult *result)
+{
+ g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (interaction),
+ g_tls_console_interaction_ask_password), G_TLS_INTERACTION_ABORTED);
+ return G_TLS_INTERACTION_HANDLED;
+}
+
+static void
+g_tls_console_interaction_init (GTlsConsoleInteraction *interaction)
+{
+
+}
+
+static void
+g_tls_console_interaction_class_init (GTlsConsoleInteractionClass *klass)
+{
+ GTlsInteractionClass *interaction_class = G_TLS_INTERACTION_CLASS (klass);
+ interaction_class->ask_password = g_tls_console_interaction_ask_password;
+ interaction_class->ask_password_async = g_tls_console_interaction_ask_password_async;
+ interaction_class->ask_password_finish = g_tls_console_interaction_ask_password_finish;
+}
+
+GTlsInteraction *
+g_tls_console_interaction_new (void)
+{
+ return g_object_new (G_TYPE_TLS_CONSOLE_INTERACTION, NULL);
+}
diff --git a/gio/tests/gtlsconsoleinteraction.h b/gio/tests/gtlsconsoleinteraction.h
new file mode 100644
index 000000000..eaf4d1885
--- /dev/null
+++ b/gio/tests/gtlsconsoleinteraction.h
@@ -0,0 +1,56 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2011 Collabora, Ltd.
+ *
+ * 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.
+ *
+ * Author: Stef Walter
+ */
+
+#ifndef __G_TLS_CONSOLE_INTERACTION_H__
+#define __G_TLS_CONSOLE_INTERACTION_H__
+
+#include
+
+G_BEGIN_DECLS
+
+#define G_TYPE_TLS_CONSOLE_INTERACTION (g_tls_console_interaction_get_type ())
+#define G_TLS_CONSOLE_INTERACTION(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_TLS_CONSOLE_INTERACTION, GTlsConsoleInteraction))
+#define G_TLS_CONSOLE_INTERACTION_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_TLS_CONSOLE_INTERACTION, GTlsConsoleInteractionClass))
+#define G_IS_TLS_CONSOLE_INTERACTION(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_TLS_CONSOLE_INTERACTION))
+#define G_IS_TLS_CONSOLE_INTERACTION_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_TLS_CONSOLE_INTERACTION))
+#define G_TLS_CONSOLE_INTERACTION_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_TLS_CONSOLE_INTERACTION, GTlsConsoleInteractionClass))
+
+typedef struct _GTlsConsoleInteraction GTlsConsoleInteraction;
+typedef struct _GTlsConsoleInteractionClass GTlsConsoleInteractionClass;
+
+struct _GTlsConsoleInteraction
+{
+ GTlsInteraction parent_instance;
+};
+
+struct _GTlsConsoleInteractionClass
+{
+ GTlsInteractionClass parent_class;
+};
+
+GType g_tls_console_interaction_get_type (void) G_GNUC_CONST;
+
+GTlsInteraction * g_tls_console_interaction_new (void);
+
+G_END_DECLS
+
+#endif /* __G_TLS_CONSOLE_INTERACTION_H__ */
diff --git a/gio/tests/socket-client.c b/gio/tests/socket-client.c
index 6068034af..578b0c88b 100644
--- a/gio/tests/socket-client.c
+++ b/gio/tests/socket-client.c
@@ -5,6 +5,8 @@
#include
#include
+#include "gtlsconsoleinteraction.h"
+
GMainLoop *loop;
gboolean verbose = FALSE;
@@ -59,23 +61,196 @@ accept_certificate (GTlsClientConnection *conn, GTlsCertificate *cert,
return TRUE;
}
+static GTlsCertificate *
+lookup_client_certificate (GTlsClientConnection *conn, GError **error)
+{
+ GList *l, *accepted;
+ GList *c, *certificates;
+ GTlsDatabase *database;
+ GTlsCertificate *certificate = NULL;
+ GTlsConnection *base;
+
+ accepted = g_tls_client_connection_get_accepted_cas (conn);
+ for (l = accepted; l != NULL; l = g_list_next (l))
+ {
+ base = G_TLS_CONNECTION (conn);
+ database = g_tls_connection_get_database (base);
+ certificates = g_tls_database_lookup_certificates_issued_by (database, l->data,
+ g_tls_connection_get_interaction (base),
+ G_TLS_DATABASE_LOOKUP_KEYPAIR,
+ NULL, error);
+ if (error && *error)
+ break;
+
+ if (certificates)
+ certificate = g_object_ref (certificates->data);
+
+ for (c = certificates; c != NULL; c = g_list_next (c))
+ g_object_unref (c->data);
+ g_list_free (certificates);
+ }
+
+ for (l = accepted; l != NULL; l = g_list_next (l))
+ g_byte_array_unref (l->data);
+ g_list_free (accepted);
+
+ if (certificate == NULL && error && !*error)
+ g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_CERTIFICATE_REQUIRED,
+ "Server requested a certificate, but could not find relevant certificate in database.");
+ return certificate;
+}
+
+static gboolean
+make_connection (const char *argument, GTlsCertificate *certificate, GCancellable *cancellable,
+ GSocket **socket, GSocketAddress **address, GIOStream **connection,
+ GInputStream **istream, GOutputStream **ostream, GError **error)
+{
+ GSocketType socket_type;
+ GSocketFamily socket_family;
+ GSocketAddressEnumerator *enumerator;
+ GSocketConnectable *connectable;
+ GSocketAddress *src_address;
+ GTlsInteraction *interaction;
+ GError *err = NULL;
+
+ if (use_udp)
+ socket_type = G_SOCKET_TYPE_DATAGRAM;
+ else
+ socket_type = G_SOCKET_TYPE_STREAM;
+
+ if (unix_socket)
+ socket_family = G_SOCKET_FAMILY_UNIX;
+ else
+ socket_family = G_SOCKET_FAMILY_IPV4;
+
+ *socket = g_socket_new (socket_family, socket_type, 0, error);
+ if (*socket == NULL)
+ return FALSE;
+
+ if (read_timeout)
+ g_socket_set_timeout (*socket, read_timeout);
+
+ if (unix_socket)
+ {
+ GSocketAddress *addr;
+
+ addr = socket_address_from_string (argument);
+ if (addr == NULL)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Could not parse '%s' as unix socket name", argument);
+ return FALSE;
+ }
+ connectable = G_SOCKET_CONNECTABLE (addr);
+ }
+ else
+ {
+ connectable = g_network_address_parse (argument, 7777, error);
+ if (connectable == NULL)
+ return FALSE;
+ }
+
+ enumerator = g_socket_connectable_enumerate (connectable);
+ while (TRUE)
+ {
+ *address = g_socket_address_enumerator_next (enumerator, cancellable, error);
+ if (*address == NULL)
+ {
+ if (error == NULL)
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "No more addresses to try");
+ return FALSE;
+ }
+
+ if (g_socket_connect (*socket, *address, cancellable, &err))
+ break;
+ g_message ("Connection to %s failed: %s, trying next\n", socket_address_to_string (*address), err->message);
+ g_clear_error (&err);
+
+ g_object_unref (*address);
+ }
+ g_object_unref (enumerator);
+
+ g_print ("Connected to %s\n",
+ socket_address_to_string (*address));
+
+ src_address = g_socket_get_local_address (*socket, error);
+ if (!src_address)
+ {
+ g_prefix_error (error, "Error getting local address: ");
+ return FALSE;
+ }
+
+ g_print ("local address: %s\n",
+ socket_address_to_string (src_address));
+ g_object_unref (src_address);
+
+ if (use_udp)
+ {
+ *connection = NULL;
+ *istream = NULL;
+ *ostream = NULL;
+ }
+ else
+ *connection = G_IO_STREAM (g_socket_connection_factory_create_connection (*socket));
+
+ if (tls)
+ {
+ GIOStream *tls_conn;
+
+ tls_conn = g_tls_client_connection_new (*connection, connectable, error);
+ if (!tls_conn)
+ {
+ g_prefix_error (error, "Could not create TLS connection: ");
+ return FALSE;
+ }
+
+ g_signal_connect (tls_conn, "accept-certificate",
+ G_CALLBACK (accept_certificate), NULL);
+
+ interaction = g_tls_console_interaction_new ();
+ g_tls_connection_set_interaction (G_TLS_CONNECTION (tls_conn), interaction);
+ g_object_unref (interaction);
+
+ if (certificate)
+ g_tls_connection_set_certificate (G_TLS_CONNECTION (tls_conn), certificate);
+
+ g_object_unref (*connection);
+ *connection = G_IO_STREAM (tls_conn);
+
+ if (!g_tls_connection_handshake (G_TLS_CONNECTION (tls_conn),
+ cancellable, error))
+ {
+ g_prefix_error (error, "Error during TLS handshake: ");
+ return FALSE;
+ }
+ }
+ g_object_unref (connectable);
+
+ if (*connection)
+ {
+ *istream = g_io_stream_get_input_stream (*connection);
+ *ostream = g_io_stream_get_output_stream (*connection);
+ }
+
+ return TRUE;
+}
+
int
main (int argc,
char *argv[])
{
GSocket *socket;
- GSocketAddress *src_address;
GSocketAddress *address;
- GSocketType socket_type;
- GSocketFamily socket_family;
GError *error = NULL;
GOptionContext *context;
GCancellable *cancellable;
- GSocketAddressEnumerator *enumerator;
- GSocketConnectable *connectable;
GIOStream *connection;
GInputStream *istream;
GOutputStream *ostream;
+ GSocketAddress *src_address;
+ GTlsCertificate *certificate = NULL;
+ gint i;
g_thread_init (NULL);
@@ -113,128 +288,24 @@ main (int argc,
loop = g_main_loop_new (NULL, FALSE);
- if (use_udp)
- socket_type = G_SOCKET_TYPE_DATAGRAM;
- else
- socket_type = G_SOCKET_TYPE_STREAM;
-
- if (unix_socket)
- socket_family = G_SOCKET_FAMILY_UNIX;
- else
- socket_family = G_SOCKET_FAMILY_IPV4;
-
- socket = g_socket_new (socket_family, socket_type, 0, &error);
- if (socket == NULL)
+ for (i = 0; i < 2; i++)
{
- g_printerr ("%s: %s\n", argv[0], error->message);
+ if (make_connection (argv[1], certificate, cancellable, &socket, &address,
+ &connection, &istream, &ostream, &error))
+ break;
+
+ if (g_error_matches (error, G_TLS_ERROR, G_TLS_ERROR_CERTIFICATE_REQUIRED))
+ {
+ g_clear_error (&error);
+ certificate = lookup_client_certificate (G_TLS_CLIENT_CONNECTION (connection), &error);
+ if (certificate != NULL)
+ continue;
+ }
+
+ g_printerr ("%s: %s", argv[0], error->message);
return 1;
}
- if (read_timeout)
- g_socket_set_timeout (socket, read_timeout);
-
- if (unix_socket)
- {
- GSocketAddress *addr;
-
- addr = socket_address_from_string (argv[1]);
- if (addr == NULL)
- {
- g_printerr ("%s: Could not parse '%s' as unix socket name\n", argv[0], argv[1]);
- return 1;
- }
- connectable = G_SOCKET_CONNECTABLE (addr);
- }
- else
- {
- connectable = g_network_address_parse (argv[1], 7777, &error);
- if (connectable == NULL)
- {
- g_printerr ("%s: %s\n", argv[0], error->message);
- return 1;
- }
- }
-
- enumerator = g_socket_connectable_enumerate (connectable);
- while (TRUE)
- {
- address = g_socket_address_enumerator_next (enumerator, cancellable, &error);
- if (address == NULL)
- {
- if (error == NULL)
- g_printerr ("%s: No more addresses to try\n", argv[0]);
- else
- g_printerr ("%s: %s\n", argv[0], error->message);
- return 1;
- }
-
- if (g_socket_connect (socket, address, cancellable, &error))
- break;
- g_printerr ("%s: Connection to %s failed: %s, trying next\n", argv[0], socket_address_to_string (address), error->message);
- g_error_free (error);
- error = NULL;
-
- g_object_unref (address);
- }
- g_object_unref (enumerator);
-
- g_print ("Connected to %s\n",
- socket_address_to_string (address));
-
- src_address = g_socket_get_local_address (socket, &error);
- if (!src_address)
- {
- g_printerr ("Error getting local address: %s\n",
- error->message);
- return 1;
- }
- g_print ("local address: %s\n",
- socket_address_to_string (src_address));
- g_object_unref (src_address);
-
- if (use_udp)
- {
- connection = NULL;
- istream = NULL;
- ostream = NULL;
- }
- else
- connection = G_IO_STREAM (g_socket_connection_factory_create_connection (socket));
-
- if (tls)
- {
- GIOStream *tls_conn;
-
- tls_conn = g_tls_client_connection_new (connection, connectable, &error);
- if (!tls_conn)
- {
- g_printerr ("Could not create TLS connection: %s\n",
- error->message);
- return 1;
- }
-
- g_signal_connect (tls_conn, "accept-certificate",
- G_CALLBACK (accept_certificate), NULL);
-
- if (!g_tls_connection_handshake (G_TLS_CONNECTION (tls_conn),
- cancellable, &error))
- {
- g_printerr ("Error during TLS handshake: %s\n",
- error->message);
- return 1;
- }
-
- g_object_unref (connection);
- connection = G_IO_STREAM (tls_conn);
- }
- g_object_unref (connectable);
-
- if (connection)
- {
- istream = g_io_stream_get_input_stream (connection);
- ostream = g_io_stream_get_output_stream (connection);
- }
-
/* TODO: Test non-blocking connect/handshake */
if (non_blocking)
g_socket_set_blocking (socket, FALSE);