mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-25 15:06:14 +01:00
Implement support for ALPN in GTlsConnection, GDtlsConnection
This commit is contained in:
parent
26f783576d
commit
9032e8897d
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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__ */
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user