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);