From 99d140332dec888814dc3ca0ff5d7bedb3c6a5f0 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 7 Jul 2016 10:58:51 -0400 Subject: examples/get: Add TLS client certificate support I'm trying to debug an ostree issue with client cert interaction with a specific server, and it's easier to drop ostree out of the picture and use this libsoup equivalent of `curl`. https://bugzilla.gnome.org/show_bug.cgi?id=768524 --- examples/get.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/examples/get.c b/examples/get.c index df052892..a760592c 100644 --- a/examples/get.c +++ b/examples/get.c @@ -92,7 +92,60 @@ get_url (const char *url) } } +/* Inline class for providing a pre-configured client certificate */ +typedef struct _GetTlsCertInteraction GetTlsCertInteraction; +typedef struct _GetTlsCertInteractionClass GetTlsCertInteractionClass; + +static GType _get_tls_cert_interaction_get_type (void) G_GNUC_CONST; +static GetTlsCertInteraction * _get_tls_cert_interaction_new (GTlsCertificate *cert); + +struct _GetTlsCertInteraction +{ + GTlsInteraction parent_instance; + GTlsCertificate *cert; +}; + +struct _GetTlsCertInteractionClass +{ + GTlsInteractionClass parent_class; +}; + +G_DEFINE_TYPE (GetTlsCertInteraction, _get_tls_cert_interaction, G_TYPE_TLS_INTERACTION); + +static GTlsInteractionResult +request_certificate (GTlsInteraction *interaction, + GTlsConnection *connection, + GTlsCertificateRequestFlags flags, + GCancellable *cancellable, + GError **error) +{ + GetTlsCertInteraction *self = (GetTlsCertInteraction*)interaction; + g_tls_connection_set_certificate (connection, self->cert); + return G_TLS_INTERACTION_HANDLED; +} + +static void +_get_tls_cert_interaction_init (GetTlsCertInteraction *interaction) +{ +} + +static void +_get_tls_cert_interaction_class_init (GetTlsCertInteractionClass *klass) +{ + GTlsInteractionClass *interaction_class = G_TLS_INTERACTION_CLASS (klass); + interaction_class->request_certificate = request_certificate; +} + +GetTlsCertInteraction * +_get_tls_cert_interaction_new (GTlsCertificate *cert) +{ + GetTlsCertInteraction *self = g_object_new (_get_tls_cert_interaction_get_type (), NULL); + self->cert = g_object_ref (cert); + return self; +} + static const char *ca_file, *proxy; +static char *client_cert_file, *client_key_file; static gboolean synchronous, ntlm; static gboolean negotiate; @@ -100,6 +153,12 @@ static GOptionEntry entries[] = { { "ca-file", 'c', 0, G_OPTION_ARG_STRING, &ca_file, "Use FILE as the TLS CA file", "FILE" }, + { "cert", 0, 0, + G_OPTION_ARG_STRING, &client_cert_file, + "Use FILE as the TLS client certificate file", "FILE" }, + { "key", 0, 0, + G_OPTION_ARG_STRING, &client_key_file, + "Use FILE as the TLS client key file", "FILE" }, { "debug", 'd', 0, G_OPTION_ARG_NONE, &debug, "Show HTTP headers", NULL }, @@ -177,6 +236,22 @@ main (int argc, char **argv) if (ntlm) soup_session_add_feature_by_type (session, SOUP_TYPE_AUTH_NTLM); + if (client_cert_file) { + GTlsCertificate *client_cert; + GetTlsCertInteraction *interaction; + if (!client_key_file) { + g_printerr ("--key is required with --cert\n"); + exit (1); + } + client_cert = g_tls_certificate_new_from_files (client_cert_file, client_key_file, &error); + if (!client_cert) { + g_printerr ("%s\n", error->message); + exit (1); + } + interaction = _get_tls_cert_interaction_new (client_cert); + g_object_set (session, SOUP_SESSION_TLS_INTERACTION, interaction, NULL); + } + if (debug) { logger = soup_logger_new (SOUP_LOGGER_LOG_BODY, -1); soup_session_add_feature (session, SOUP_SESSION_FEATURE (logger)); -- cgit v1.2.1