tls: add functions to get protocol version and ciphersuite name

This adds g_tls_connection_get_protocol_version(),
g_tls_connection_get_ciphersuite_name(), and DTLS variants. This will
allow populating TLS connection information in the WebKit web inspector.

This is WIP because we found it's not quite possibly to implement
correctly with GnuTLS. See glib-networking!151.
This commit is contained in:
Michael Catanzaro 2021-04-28 16:08:00 -05:00 committed by Michael Catanzaro
parent fbcd653bd9
commit bf37392045
6 changed files with 245 additions and 0 deletions

View File

@ -3667,16 +3667,19 @@ GTlsChannelBindingError
<SUBSECTION>
GTlsAuthenticationMode
GTlsCertificateFlags
GTlsProtocolVersion
<SUBSECTION Standard>
G_TYPE_TLS_AUTHENTICATION_MODE
G_TYPE_TLS_CERTIFICATE_FLAGS
G_TYPE_TLS_CHANNEL_BINDING_ERROR
G_TYPE_TLS_ERROR
G_TYPE_TLS_PROTOCOL_VERSION
g_tls_authentication_mode_get_type
g_tls_certificate_flags_get_type
g_tls_channel_binding_error_get_type
g_tls_channel_binding_error_quark
g_tls_error_get_type
g_tls_protocol_version_get_type
</SECTION>
<SECTION>
@ -3758,6 +3761,8 @@ g_tls_connection_get_database
g_tls_connection_set_database
g_tls_connection_get_interaction
g_tls_connection_set_interaction
g_tls_connection_get_protocol_version
g_tls_connection_get_ciphersuite_name
<SUBSECTION>
g_tls_connection_handshake
g_tls_connection_handshake_async
@ -3952,6 +3957,8 @@ g_dtls_connection_get_database
g_dtls_connection_set_database
g_dtls_connection_get_interaction
g_dtls_connection_set_interaction
g_dtls_connection_get_protocol_version
g_dtls_connection_get_ciphersuite_name
<SUBSECTION>
g_dtls_connection_handshake
g_dtls_connection_handshake_async

View File

@ -88,6 +88,8 @@ enum {
PROP_CERTIFICATE,
PROP_PEER_CERTIFICATE,
PROP_PEER_CERTIFICATE_ERRORS,
PROP_PROTOCOL_VERSION,
PROP_CIPHERSUITE_NAME,
};
static void
@ -263,6 +265,37 @@ g_dtls_connection_default_init (GDtlsConnectionInterface *iface)
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
/**
* GDtlsConnection:protocol-version:
*
* The DTLS protocol version in use. See g_dtls_connection_get_protocol_version().
*
* Since: 2.70
*/
g_object_interface_install_property (iface,
g_param_spec_enum ("protocol-version",
P_("Protocol Version"),
P_("DTLS protocol version negotiated for this connection"),
G_TYPE_TLS_PROTOCOL_VERSION,
G_TLS_PROTOCOL_VERSION_UNKNOWN,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
/**
* GDtlsConnection:ciphersuite-name: (nullable)
*
* The name of the DTLS ciphersuite in use. See g_dtls_connection_get_ciphersuite_name().
*
* Since: 2.70
*/
g_object_interface_install_property (iface,
g_param_spec_string ("ciphersuite-name",
P_("Ciphersuite Name"),
P_("Name of ciphersuite negotiated for this connection"),
NULL,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
/**
* GDtlsConnection::accept-certificate:
* @conn: a #GDtlsConnection
@ -1123,3 +1156,66 @@ g_dtls_connection_get_channel_binding_data (GDtlsConnection *conn,
return iface->get_binding_data (conn, type, data, error);
}
/**
* g_dtls_connection_get_protocol_version:
* @conn: a #GDTlsConnection
*
* Returns the current DTLS protocol version, which may be
* %G_TLS_PROTOCOL_VERSION_UNKNOWN if the connection has not handshaked, or
* has been closed, or if the TLS backend has implemented a protocol version
* that is not a recognized #GTlsProtocolVersion.
*
* Returns: The current DTLS protocol version
*
* Since: 2.70
*/
GTlsProtocolVersion
g_dtls_connection_get_protocol_version (GDtlsConnection *conn)
{
GTlsProtocolVersion protocol_version;
GEnumClass *enum_class;
GEnumValue *enum_value;
g_return_val_if_fail (G_IS_DTLS_CONNECTION (conn), G_TLS_PROTOCOL_VERSION_UNKNOWN);
g_object_get (G_OBJECT (conn),
"protocol-version", &protocol_version,
NULL);
/* Convert unknown values to G_TLS_PROTOCOL_VERSION_UNKNOWN. */
enum_class = g_type_class_peek_static (G_TYPE_TLS_PROTOCOL_VERSION);
enum_value = g_enum_get_value (enum_class, protocol_version);
return enum_value ? protocol_version : G_TLS_PROTOCOL_VERSION_UNKNOWN;
}
/**
* g_dtls_connection_get_ciphersuite_name:
* @conn: a #GDTlsConnection
*
* Returns the name of the current DTLS ciphersuite, or %NULL if the
* connection has not handshaked or has been closed. Beware that the TLS
* backend may use any of multiple different naming conventions, because
* OpenSSL and GnuTLS have their own ciphersuite naming conventions that
* are different from each other and different from the standard, IANA-
* registered ciphersuite names. The ciphersuite name is intended to be
* displayed to the user for informative purposes only, and parsing it
* is not recommended.
*
* Returns: (nullable): The name of the current DTLS ciphersuite, or %NULL
*
* Since: 2.70
*/
gchar *
g_dtls_connection_get_ciphersuite_name (GDtlsConnection *conn)
{
gchar *ciphersuite_name;
g_return_val_if_fail (G_IS_DTLS_CONNECTION (conn), NULL);
g_object_get (G_OBJECT (conn),
"ciphersuite-name", &ciphersuite_name,
NULL);
return g_steal_pointer (&ciphersuite_name);
}

View File

@ -216,6 +216,12 @@ gboolean g_dtls_connection_get_channel_binding_data (GDtlsConnec
GError **error);
G_GNUC_END_IGNORE_DEPRECATIONS
GLIB_AVAILABLE_IN_2_70
GTlsProtocolVersion g_dtls_connection_get_protocol_version (GDtlsConnection *conn);
GLIB_AVAILABLE_IN_2_70
gchar * g_dtls_connection_get_ciphersuite_name (GDtlsConnection *conn);
G_END_DECLS
#endif /* __G_DTLS_CONNECTION_H__ */

View File

@ -1825,6 +1825,40 @@ typedef enum {
G_TLS_CERTIFICATE_REQUEST_NONE = 0
} GTlsCertificateRequestFlags;
/**
* GTlsProtocolVersion:
* @G_TLS_PROTOCOL_VERSION_UNKNOWN: No protocol version or unknown protocol version
* @G_TLS_PROTOCOL_VERSION_SSL_3_0: SSL 3.0, which is insecure and should not be used
* @G_TLS_PROTOCOL_VERSION_TLS_1_0: TLS 1.0, which is insecure and should not be used
* @G_TLS_PROTOCOL_VERSION_TLS_1_1: TLS 1.1, which is insecure and should not be used
* @G_TLS_PROTOCOL_VERSION_TLS_1_2: TLS 1.2, defined by [RFC 5246](https://datatracker.ietf.org/doc/html/rfc5246)
* @G_TLS_PROTOCOL_VERSION_TLS_1_3: TLS 1.3, defined by [RFC 8446](https://datatracker.ietf.org/doc/html/rfc8446)
* @G_TLS_PROTOCOL_VERSION_DTLS_1_0: DTLS 1.0, which is insecure and should not be used
* @G_TLS_PROTOCOL_VERSION_DTLS_1_2: DTLS 1.2, defined by [RFC 6347](https://datatracker.ietf.org/doc/html/rfc6347)
*
* The TLS or DTLS protocol version used by a #GTlsConnection or
* #GDtlsConnection. The integer values of these versions are sequential
* to ensure newer known protocol versions compare greater than older
* known versions. Any known DTLS protocol version will compare greater
* than any SSL or TLS protocol version. The protocol version may be
* %G_TLS_PROTOCOL_VERSION_UNKNOWN if the TLS backend supports a newer
* protocol version that GLib does not yet know about. This means that
* it's possible for an unknown DTLS protocol version to compare less
* than the TLS protocol versions.
*
* Since: 2.70
*/
typedef enum {
G_TLS_PROTOCOL_VERSION_UNKNOWN = 0,
G_TLS_PROTOCOL_VERSION_SSL_3_0 = 1,
G_TLS_PROTOCOL_VERSION_TLS_1_0 = 2,
G_TLS_PROTOCOL_VERSION_TLS_1_1 = 3,
G_TLS_PROTOCOL_VERSION_TLS_1_2 = 4,
G_TLS_PROTOCOL_VERSION_TLS_1_3 = 5,
G_TLS_PROTOCOL_VERSION_DTLS_1_0 = 201,
G_TLS_PROTOCOL_VERSION_DTLS_1_2 = 202,
} GTlsProtocolVersion;
/**
* GIOModuleScopeFlags:
* @G_IO_MODULE_SCOPE_NONE: No module scan flags

View File

@ -93,6 +93,8 @@ enum {
PROP_PEER_CERTIFICATE_ERRORS,
PROP_ADVERTISED_PROTOCOLS,
PROP_NEGOTIATED_PROTOCOL,
PROP_PROTOCOL_VERSION,
PROP_CIPHERSUITE_NAME,
};
static void
@ -295,6 +297,37 @@ g_tls_connection_class_init (GTlsConnectionClass *klass)
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
/**
* GTlsConnection:protocol-version:
*
* The TLS protocol version in use. See g_tls_connection_get_protocol_version().
*
* Since: 2.70
*/
g_object_class_install_property (gobject_class, PROP_PROTOCOL_VERSION,
g_param_spec_enum ("protocol-version",
P_("Protocol Version"),
P_("TLS protocol version negotiated for this connection"),
G_TYPE_TLS_PROTOCOL_VERSION,
G_TLS_PROTOCOL_VERSION_UNKNOWN,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
/**
* GTlsConnection:ciphersuite-name: (nullable)
*
* The name of the TLS ciphersuite in use. See g_tls_connection_get_ciphersuite_name().
*
* Since: 2.70
*/
g_object_class_install_property (gobject_class, PROP_CIPHERSUITE_NAME,
g_param_spec_string ("ciphersuite-name",
P_("Ciphersuite Name"),
P_("Name of ciphersuite negotiated for this connection"),
NULL,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
/**
* GTlsConnection::accept-certificate:
* @conn: a #GTlsConnection
@ -1028,6 +1061,69 @@ g_tls_connection_handshake_finish (GTlsConnection *conn,
return G_TLS_CONNECTION_GET_CLASS (conn)->handshake_finish (conn, result, error);
}
/**
* g_tls_connection_get_protocol_version:
* @conn: a #GTlsConnection
*
* Returns the current TLS protocol version, which may be
* %G_TLS_PROTOCOL_VERSION_UNKNOWN if the connection has not handshaked, or
* has been closed, or if the TLS backend has implemented a protocol version
* that is not a recognized #GTlsProtocolVersion.
*
* Returns: The current TLS protocol version
*
* Since: 2.70
*/
GTlsProtocolVersion
g_tls_connection_get_protocol_version (GTlsConnection *conn)
{
GTlsProtocolVersion protocol_version;
GEnumClass *enum_class;
GEnumValue *enum_value;
g_return_val_if_fail (G_IS_TLS_CONNECTION (conn), G_TLS_PROTOCOL_VERSION_UNKNOWN);
g_object_get (G_OBJECT (conn),
"protocol-version", &protocol_version,
NULL);
/* Convert unknown values to G_TLS_PROTOCOL_VERSION_UNKNOWN. */
enum_class = g_type_class_peek_static (G_TYPE_TLS_PROTOCOL_VERSION);
enum_value = g_enum_get_value (enum_class, protocol_version);
return enum_value ? protocol_version : G_TLS_PROTOCOL_VERSION_UNKNOWN;
}
/**
* g_tls_connection_get_ciphersuite_name:
* @conn: a #GTlsConnection
*
* Returns the name of the current TLS ciphersuite, or %NULL if the
* connection has not handshaked or has been closed. Beware that the TLS
* backend may use any of multiple different naming conventions, because
* OpenSSL and GnuTLS have their own ciphersuite naming conventions that
* are different from each other and different from the standard, IANA-
* registered ciphersuite names. The ciphersuite name is intended to be
* displayed to the user for informative purposes only, and parsing it
* is not recommended.
*
* Returns: (nullable): The name of the current TLS ciphersuite, or %NULL
*
* Since: 2.70
*/
gchar *
g_tls_connection_get_ciphersuite_name (GTlsConnection *conn)
{
gchar *ciphersuite_name;
g_return_val_if_fail (G_IS_TLS_CONNECTION (conn), NULL);
g_object_get (G_OBJECT (conn),
"ciphersuite-name", &ciphersuite_name,
NULL);
return g_steal_pointer (&ciphersuite_name);
}
/**
* g_tls_error_quark:
*

View File

@ -155,6 +155,12 @@ gboolean g_tls_connection_handshake_finish (GTlsConnecti
GAsyncResult *result,
GError **error);
GLIB_AVAILABLE_IN_2_70
GTlsProtocolVersion g_tls_connection_get_protocol_version (GTlsConnection *conn);
GLIB_AVAILABLE_IN_2_70
gchar * g_tls_connection_get_ciphersuite_name (GTlsConnection *conn);
/**
* G_TLS_ERROR:
*