[glib: 1/2] Implement support for ALPN in GTlsConnection, GDtlsConnection
- From: Philip Withnall <pwithnall src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib: 1/2] Implement support for ALPN in GTlsConnection, GDtlsConnection
- Date: Wed, 19 Dec 2018 12:02:05 +0000 (UTC)
commit 9032e8897da5b93df16fd33e200523243dfc50ac
Author: Scott Hutton <schutton cisco com>
Date: Tue Dec 18 16:32:55 2018 -0800
Implement support for ALPN in GTlsConnection, GDtlsConnection
docs/reference/gio/gio-sections.txt | 4 ++
gio/gdtlsconnection.c | 91 +++++++++++++++++++++++++
gio/gdtlsconnection.h | 13 ++++
gio/gtlsconnection.c | 131 +++++++++++++++++++++++++++++++++++-
gio/gtlsconnection.h | 7 ++
5 files changed, 244 insertions(+), 2 deletions(-)
---
diff --git a/docs/reference/gio/gio-sections.txt b/docs/reference/gio/gio-sections.txt
index 3c0491a7b..02c461fc2 100644
--- a/docs/reference/gio/gio-sections.txt
+++ b/docs/reference/gio/gio-sections.txt
@@ -3747,6 +3747,8 @@ g_tls_connection_get_require_close_notify
GTlsRehandshakeMode
g_tls_connection_set_rehandshake_mode
g_tls_connection_get_rehandshake_mode
+g_tls_connection_set_advertised_protocols
+g_tls_connection_get_negotiated_protocol
g_tls_connection_set_use_system_certdb
g_tls_connection_get_use_system_certdb
g_tls_connection_get_database
@@ -3938,6 +3940,8 @@ g_dtls_connection_set_require_close_notify
g_dtls_connection_get_require_close_notify
g_dtls_connection_set_rehandshake_mode
g_dtls_connection_get_rehandshake_mode
+g_dtls_connection_set_advertised_protocols
+g_dtls_connection_get_negotiated_protocol
g_dtls_connection_get_database
g_dtls_connection_set_database
g_dtls_connection_get_interaction
diff --git a/gio/gdtlsconnection.c b/gio/gdtlsconnection.c
index 4177fb4aa..254537198 100644
--- a/gio/gdtlsconnection.c
+++ b/gio/gdtlsconnection.c
@@ -232,6 +232,37 @@ g_dtls_connection_default_init (GDtlsConnectionInterface *iface)
0,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
+ /**
+ * GDtlsConnection:advertised-protocols:
+ *
+ * The list of application-layer protocols that the connection
+ * advertises that it is willing to speak. See
+ * g_dtls_connection_set_advertised_protocols().
+ *
+ * Since: 2.60
+ */
+ g_object_interface_install_property (iface,
+ g_param_spec_boxed ("advertised-protocols",
+ P_("Advertised Protocols"),
+ P_("Application-layer protocols available on this
connection"),
+ G_TYPE_STRV,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+ /**
+ * GDtlsConnection:negotiated-protocol:
+ *
+ * The application-layer protocol negotiated during the TLS
+ * handshake. See g_dtls_connection_get_negotiated_protocol().
+ *
+ * Since: 2.60
+ */
+ g_object_interface_install_property (iface,
+ g_param_spec_string ("negotiated-protocol",
+ P_("Negotiated Protocol"),
+ P_("Application-layer protocol negotiated for
this connection"),
+ NULL,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_STRINGS));
/**
* GDtlsConnection::accept-certificate:
@@ -989,3 +1020,63 @@ g_dtls_connection_emit_accept_certificate (GDtlsConnection *conn,
peer_cert, errors, &accept);
return accept;
}
+
+/**
+ * g_dtls_connection_set_advertised_protocols:
+ * @conn: a #GDtlsConnection
+ * @protocols: (array zero-terminated=1) (nullable): a %NULL-terminated
+ * array of ALPN protocol names (eg, "http/1.1", "h2"), or %NULL
+ *
+ * Sets the list of application-layer protocols to advertise that the
+ * caller is willing to speak on this connection. The
+ * Application-Layer Protocol Negotiation (ALPN) extension will be
+ * used to negotiate a compatible protocol with the peer; use
+ * g_dtls_connection_get_negotiated_protocol() to find the negotiated
+ * protocol after the handshake. Specifying %NULL for the the value
+ * of @protocols will disable ALPN negotiation.
+ *
+ * See [IANA TLS ALPN Protocol
IDs](https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids)
+ * for a list of registered protocol IDs.
+ *
+ * Since: 2.60
+ */
+void
+g_dtls_connection_set_advertised_protocols (GDtlsConnection *conn,
+ const gchar * const *protocols)
+{
+ GDtlsConnectionInterface *iface;
+
+ iface = G_DTLS_CONNECTION_GET_INTERFACE (conn);
+ if (iface->set_advertised_protocols == NULL)
+ return;
+
+ return iface->set_advertised_protocols (conn, protocols);
+}
+
+/**
+ * g_dtls_connection_get_negotiated_protocol:
+ * @conn: a #GDtlsConnection
+ *
+ * Gets the name of the application-layer protocol negotiated during
+ * the handshake.
+ *
+ * If the peer did not use the ALPN extension, or did not advertise a
+ * protocol that matched one of @conn's protocols, or the TLS backend
+ * does not support ALPN, then this will be %NULL. See
+ * g_dtls_connection_set_advertised_protocols().
+ *
+ * Returns: (nullable): the negotiated protocol, or %NULL
+ *
+ * Since: 2.60
+ */
+const gchar *
+g_dtls_connection_get_negotiated_protocol (GDtlsConnection *conn)
+{
+ GDtlsConnectionInterface *iface;
+
+ iface = G_DTLS_CONNECTION_GET_INTERFACE (conn);
+ if (iface->set_advertised_protocols == NULL)
+ return NULL;
+
+ return iface->get_negotiated_protocol (conn);
+}
diff --git a/gio/gdtlsconnection.h b/gio/gdtlsconnection.h
index 3cf6cb31c..364be935e 100644
--- a/gio/gdtlsconnection.h
+++ b/gio/gdtlsconnection.h
@@ -45,6 +45,8 @@ typedef struct _GDtlsConnectionInterface GDtlsConnectionInterface;
* @shutdown: Shut down one or both directions of the connection.
* @shutdown_async: Start an asynchronous shutdown operation.
* @shutdown_finish: Finish an asynchronous shutdown operation.
+ * @set_advertised_protocols: Set APLN protocol list
+ * @get_negotiated_protocol: Retrieve ALPN-negotiated protocol
*
* Virtual method table for a #GDtlsConnection implementation.
*
@@ -89,6 +91,10 @@ struct _GDtlsConnectionInterface
gboolean (*shutdown_finish) (GDtlsConnection *conn,
GAsyncResult *result,
GError **error);
+
+ void (*set_advertised_protocols) (GDtlsConnection *conn,
+ const gchar * const *protocols);
+ const gchar *(*get_negotiated_protocol) (GDtlsConnection *conn);
};
GLIB_AVAILABLE_IN_2_48
@@ -186,6 +192,13 @@ GLIB_AVAILABLE_IN_2_48
gboolean g_dtls_connection_emit_accept_certificate (GDtlsConnection *conn,
GTlsCertificate *peer_cert,
GTlsCertificateFlags errors);
+GLIB_AVAILABLE_IN_2_60
+void g_dtls_connection_set_advertised_protocols (GDtlsConnection *conn,
+ const gchar * const *protocols);
+
+GLIB_AVAILABLE_IN_2_60
+const gchar * g_dtls_connection_get_negotiated_protocol (GDtlsConnection *conn);
+
G_END_DECLS
#endif /* __G_DTLS_CONNECTION_H__ */
diff --git a/gio/gtlsconnection.c b/gio/gtlsconnection.c
index 26d1881c3..a1e98c0c9 100644
--- a/gio/gtlsconnection.c
+++ b/gio/gtlsconnection.c
@@ -54,7 +54,12 @@
* Since: 2.28
*/
-G_DEFINE_ABSTRACT_TYPE (GTlsConnection, g_tls_connection, G_TYPE_IO_STREAM)
+struct _GTlsConnectionPrivate
+{
+ gchar *negotiated_protocol;
+};
+
+G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GTlsConnection, g_tls_connection, G_TYPE_IO_STREAM)
static void g_tls_connection_get_property (GObject *object,
guint prop_id,
@@ -64,6 +69,7 @@ static void g_tls_connection_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec);
+static void g_tls_connection_finalize (GObject *object);
enum {
ACCEPT_CERTIFICATE,
@@ -83,7 +89,9 @@ enum {
PROP_INTERACTION,
PROP_CERTIFICATE,
PROP_PEER_CERTIFICATE,
- PROP_PEER_CERTIFICATE_ERRORS
+ PROP_PEER_CERTIFICATE_ERRORS,
+ PROP_ADVERTISED_PROTOCOLS,
+ PROP_NEGOTIATED_PROTOCOL,
};
static void
@@ -93,6 +101,7 @@ g_tls_connection_class_init (GTlsConnectionClass *klass)
gobject_class->get_property = g_tls_connection_get_property;
gobject_class->set_property = g_tls_connection_set_property;
+ gobject_class->finalize = g_tls_connection_finalize;
/**
* GTlsConnection:base-io-stream:
@@ -251,6 +260,37 @@ g_tls_connection_class_init (GTlsConnectionClass *klass)
0,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
+ /**
+ * GTlsConnection:advertised-protocols:
+ *
+ * The list of application-layer protocols that the connection
+ * advertises that it is willing to speak. See
+ * g_tls_connection_set_advertised_protocols().
+ *
+ * Since: 2.60
+ */
+ g_object_class_install_property (gobject_class, PROP_ADVERTISED_PROTOCOLS,
+ g_param_spec_boxed ("advertised-protocols",
+ P_("Advertised Protocols"),
+ P_("Application-layer protocols available on this
connection"),
+ G_TYPE_STRV,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+ /**
+ * GTlsConnection:negotiated-protocol:
+ *
+ * The application-layer protocol negotiated during the TLS
+ * handshake. See g_tls_connection_get_negotiated_protocol().
+ *
+ * Since: 2.60
+ */
+ g_object_class_install_property (gobject_class, PROP_NEGOTIATED_PROTOCOL,
+ g_param_spec_string ("negotiated-protocol",
+ P_("Negotiated Protocol"),
+ P_("Application-layer protocol negotiated for this
connection"),
+ NULL,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_STRINGS));
/**
* GTlsConnection::accept-certificate:
@@ -334,6 +374,17 @@ g_tls_connection_set_property (GObject *object,
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
+static void
+g_tls_connection_finalize (GObject *object)
+{
+ GTlsConnection *conn = G_TLS_CONNECTION(object);
+ GTlsConnectionPrivate *priv = g_tls_connection_get_instance_private (conn);
+
+ g_clear_pointer (&priv->negotiated_protocol, g_free);
+
+ G_OBJECT_CLASS (g_tls_connection_parent_class)->finalize (object);
+}
+
/**
* g_tls_connection_set_use_system_certdb:
* @conn: a #GTlsConnection
@@ -742,6 +793,82 @@ g_tls_connection_get_rehandshake_mode (GTlsConnection *conn)
return mode;
}
+/**
+ * g_tls_connection_set_advertised_protocols:
+ * @conn: a #GTlsConnection
+ * @protocols: (array zero-terminated=1) (nullable): a %NULL-terminated
+ * array of ALPN protocol names (eg, "http/1.1", "h2"), or %NULL
+ *
+ * Sets the list of application-layer protocols to advertise that the
+ * caller is willing to speak on this connection. The
+ * Application-Layer Protocol Negotiation (ALPN) extension will be
+ * used to negotiate a compatible protocol with the peer; use
+ * g_tls_connection_get_negotiated_protocol() to find the negotiated
+ * protocol after the handshake. Specifying %NULL for the the value
+ * of @protocols will disable ALPN negotiation.
+ *
+ * See [IANA TLS ALPN Protocol
IDs](https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids)
+ * for a list of registered protocol IDs.
+ *
+ * Since: 2.60
+ */
+void
+g_tls_connection_set_advertised_protocols (GTlsConnection *conn,
+ const gchar * const *protocols)
+{
+ g_return_if_fail (G_IS_TLS_CONNECTION (conn));
+
+ g_object_set (G_OBJECT (conn),
+ "advertised-protocols", protocols,
+ NULL);
+}
+
+/**
+ * g_tls_connection_get_negotiated_protocol:
+ * @conn: a #GTlsConnection
+ *
+ * Gets the name of the application-layer protocol negotiated during
+ * the handshake.
+ *
+ * If the peer did not use the ALPN extension, or did not advertise a
+ * protocol that matched one of @conn's protocols, or the TLS backend
+ * does not support ALPN, then this will be %NULL. See
+ * g_tls_connection_set_advertised_protocols().
+ *
+ * Returns: (nullable): the negotiated protocol, or %NULL
+ *
+ * Since: 2.60
+ */
+const gchar *
+g_tls_connection_get_negotiated_protocol (GTlsConnection *conn)
+{
+ GTlsConnectionPrivate *priv;
+ gchar *protocol;
+
+ g_return_val_if_fail (G_IS_TLS_CONNECTION (conn), NULL);
+
+ g_object_get (G_OBJECT (conn),
+ "negotiated-protocol", &protocol,
+ NULL);
+
+ /*
+ * Cache the property internally so we can return a `const` pointer
+ * to the caller.
+ */
+ priv = g_tls_connection_get_instance_private (conn);
+ if (g_strcmp0 (priv->negotiated_protocol, protocol) != 0)
+ {
+ g_free (priv->negotiated_protocol);
+ priv->negotiated_protocol = protocol;
+ }
+ else
+ {
+ g_free (protocol);
+ }
+
+ return priv->negotiated_protocol;
+}
+
/**
* g_tls_connection_handshake:
* @conn: a #GTlsConnection
diff --git a/gio/gtlsconnection.h b/gio/gtlsconnection.h
index 0cfcb5910..39ec3fa02 100644
--- a/gio/gtlsconnection.h
+++ b/gio/gtlsconnection.h
@@ -115,6 +115,13 @@ void g_tls_connection_set_rehandshake_mode (GTlsConnecti
GLIB_DEPRECATED_IN_2_60
GTlsRehandshakeMode g_tls_connection_get_rehandshake_mode (GTlsConnection *conn);
+GLIB_AVAILABLE_IN_2_60
+void g_tls_connection_set_advertised_protocols (GTlsConnection *conn,
+ const gchar * const *protocols);
+
+GLIB_AVAILABLE_IN_2_60
+const gchar * g_tls_connection_get_negotiated_protocol (GTlsConnection *conn);
+
GLIB_AVAILABLE_IN_ALL
gboolean g_tls_connection_handshake (GTlsConnection *conn,
GCancellable *cancellable,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]