pull: Add tls-client-cert-{path,key} (if we have new enough libsoup)

This is an actually working version of client-side certificates.
Depends on:
See: https://bugzilla.gnome.org/show_bug.cgi?id=334021

We detect whether libsoup is new enough for this.

https://bugzilla.gnome.org/show_bug.cgi?id=729356
This commit is contained in:
Colin Walters 2014-05-01 12:55:13 -04:00
parent 64b4ec6ef0
commit 25ad4a9f65
8 changed files with 209 additions and 2 deletions

View File

@ -1,6 +1,6 @@
# Makefile for C source code
#
# Copyright (C) 2011 Colin Walters <walters@verbum.org>
# Copyright (C) 2011,2014 Colin Walters <walters@verbum.org>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
@ -88,6 +88,12 @@ libostree_1_la_SOURCES += src/libostree/ostree-libarchive-input-stream.h \
src/libostree/ostree-libarchive-input-stream.c \
$(NULL)
endif
if HAVE_LIBSOUP_CLIENT_CERTS
libostree_1_la_SOURCES += \
src/libostree/ostree-tls-cert-interaction.c \
src/libostree/ostree-tls-cert-interaction.h \
$(NULL)
endif
libostree_1_la_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/src/libotutil -I$(srcdir)/src/libostree -DLOCALEDIR=\"$(datadir)/locale\" -DGPGVPATH=\"$(GPGVPATH)\" $(OT_INTERNAL_GIO_UNIX_CFLAGS) $(OT_DEP_LZMA_CFLAGS)
libostree_1_la_LDFLAGS = -version-number 1:0:0 -Bsymbolic-functions -export-symbols-regex '^ostree_'

View File

@ -63,12 +63,21 @@ AS_IF([test x$with_soup != xno ], [
PKG_CHECK_MODULES(OT_DEP_SOUP, $SOUP_DEPENDENCY)
AC_DEFINE(HAVE_LIBSOUP, 1, [Define if we have libsoup.pc])
with_soup=yes
save_CFLAGS=$CFLAGS
CFLAGS=$OT_DEP_SOUP_CFLAGS
have_libsoup_client_certs=no
AC_CHECK_DECL([SOUP_SESSION_TLS_INTERACTION], [
AC_DEFINE(HAVE_LIBSOUP_CLIENT_CERTS, 1, [Define if we have libsoup client certs])
have_libsoup_client_certs=yes
], [], [#include <libsoup/soup.h>])
CFLAGS=$save_CFLAGS
], [
with_soup=no
])
], [ with_soup=no ])
if test x$with_soup != xno; then OSTREE_FEATURES="$OSTREE_FEATURES +libsoup"; fi
AM_CONDITIONAL(USE_LIBSOUP, test x$with_soup != xno)
AM_CONDITIONAL(HAVE_LIBSOUP_CLIENT_CERTS, test x$have_libsoup_client_certs = xyes)
m4_ifdef([GOBJECT_INTROSPECTION_CHECK], [
GOBJECT_INTROSPECTION_CHECK([1.34.0])

View File

@ -104,12 +104,30 @@ Boston, MA 02111-1307, USA.
<varlistentry>
<term><varname>gpg-verify</varname></term>
<listitem><para>A boolean value, defaults to <tt>true</tt>.
<listitem><para>A boolean value, defaults to true.
Controls whether or not OSTree will require commits to be
signed by a known GPG key. For more information, see the
<citerefentry><refentrytitle>ostree</refentrytitle><manvolnum>1</manvolnum></citerefentry>
manual under GPG.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>tls-permissive</varname></term>
<listitem><para>A boolean value, defaults to false. By
default, server TLS certificates will be checked against the
system certificate store. If this variable is set, any
certificate will be accepted.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>tls-client-cert-path</varname></term>
<listitem><para>Path to file for client-side certificate, to present when making requests to this repository.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>tls-client-key-path</varname></term>
<listitem><para>Path to file containing client-side certificate key, to present when making requests to this repository.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>

View File

@ -25,6 +25,9 @@
#include <gio/gfiledescriptorbased.h>
#include "ostree-fetcher.h"
#ifdef HAVE_LIBSOUP_CLIENT_CERTS
#include "ostree-tls-cert-interaction.h"
#endif
#include "ostree.h"
#include "otutil.h"
#include "libgsystem.h"
@ -79,6 +82,8 @@ struct OstreeFetcher
GFile *tmpdir;
GTlsCertificate *client_cert;
SoupSession *session;
SoupRequester *requester;
@ -107,6 +112,7 @@ ostree_fetcher_finalize (GObject *object)
g_clear_object (&self->session);
g_clear_object (&self->tmpdir);
g_clear_object (&self->client_cert);
g_hash_table_destroy (self->sending_messages);
g_hash_table_destroy (self->message_to_request);
@ -175,6 +181,9 @@ ostree_fetcher_init (OstreeFetcher *self)
}
}
if (g_getenv ("OSTREE_DEBUG_HTTP"))
soup_session_add_feature (self->session, (SoupSessionFeature*)soup_logger_new (SOUP_LOGGER_LOG_BODY, 500));
self->requester = (SoupRequester *)soup_session_get_feature (self->session, SOUP_TYPE_REQUESTER);
g_object_get (self->session, "max-conns-per-host", &max_conns, NULL);
self->max_outstanding = 3 * max_conns;
@ -204,6 +213,24 @@ ostree_fetcher_new (GFile *tmpdir,
return self;
}
void
ostree_fetcher_set_client_cert (OstreeFetcher *fetcher,
GTlsCertificate *cert)
{
g_clear_object (&fetcher->client_cert);
fetcher->client_cert = g_object_ref (cert);
if (fetcher->client_cert)
{
#ifdef HAVE_LIBSOUP_CLIENT_CERTS
gs_unref_object GTlsInteraction *interaction =
(GTlsInteraction*)ostree_tls_cert_interaction_new (fetcher->client_cert);
g_object_set (fetcher->session, "tls-interaction", interaction, NULL);
#else
g_warning ("This version of OSTree is compiled without client side certificate support");
#endif
}
}
static void
on_request_sent (GObject *object, GAsyncResult *result, gpointer user_data);
@ -215,6 +242,7 @@ ostree_fetcher_process_pending_queue (OstreeFetcher *self)
self->outstanding < self->max_outstanding)
{
OstreeFetcherPendingURI *next = g_queue_pop_head (&self->pending_queue);
self->outstanding++;
soup_request_send_async (next->request, next->cancellable,
on_request_sent, next);

View File

@ -54,6 +54,9 @@ GType ostree_fetcher_get_type (void) G_GNUC_CONST;
OstreeFetcher *ostree_fetcher_new (GFile *tmpdir,
OstreeFetcherConfigFlags flags);
void ostree_fetcher_set_client_cert (OstreeFetcher *fetcher,
GTlsCertificate *cert);
char * ostree_fetcher_query_state_text (OstreeFetcher *self);
guint64 ostree_fetcher_bytes_transferred (OstreeFetcher *self);

View File

@ -1086,6 +1086,41 @@ ostree_repo_pull (OstreeRepo *self,
pull_data->fetcher = ostree_fetcher_new (pull_data->repo->tmp_dir,
fetcher_flags);
{
gs_free char *tls_client_cert_path = NULL;
gs_free char *tls_client_key_path = NULL;
if (!ot_keyfile_get_value_with_default (config, remote_key,
"tls-client-cert-path",
NULL, &tls_client_cert_path, error))
goto out;
if (!ot_keyfile_get_value_with_default (config, remote_key,
"tls-client-key-path",
NULL, &tls_client_key_path, error))
goto out;
if ((tls_client_cert_path != NULL) != (tls_client_key_path != NULL))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"\"%s\" must specify both \"tls-client-cert-path\" and \"tls-client-key-path\"", remote_key);
goto out;
}
else if (tls_client_cert_path)
{
gs_unref_object GTlsCertificate *client_cert = NULL;
g_assert (tls_client_key_path);
client_cert = g_tls_certificate_new_from_files (tls_client_cert_path,
tls_client_key_path,
error);
if (!client_cert)
goto out;
ostree_fetcher_set_client_cert (pull_data->fetcher, client_cert);
}
}
if (!pull_data->base_uri)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,

View File

@ -0,0 +1,69 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
*
* Copyright (C) 2014 Colin Walters <walters@verbum.org>
*
* 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, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "ostree-tls-cert-interaction.h"
struct _OstreeTlsCertInteraction
{
GTlsInteraction parent_instance;
GTlsCertificate *cert;
};
struct _OstreeTlsCertInteractionClass
{
GTlsInteractionClass parent_class;
};
#include <string.h>
G_DEFINE_TYPE (OstreeTlsCertInteraction, ostree_tls_cert_interaction, G_TYPE_TLS_INTERACTION);
static GTlsInteractionResult
request_certificate (GTlsInteraction *interaction,
GTlsConnection *connection,
GTlsCertificateRequestFlags flags,
GCancellable *cancellable,
GError **error)
{
OstreeTlsCertInteraction *self = (OstreeTlsCertInteraction*)interaction;
g_tls_connection_set_certificate (connection, self->cert);
return G_TLS_INTERACTION_HANDLED;
}
static void
ostree_tls_cert_interaction_init (OstreeTlsCertInteraction *interaction)
{
}
static void
ostree_tls_cert_interaction_class_init (OstreeTlsCertInteractionClass *klass)
{
GTlsInteractionClass *interaction_class = G_TLS_INTERACTION_CLASS (klass);
interaction_class->request_certificate = request_certificate;
}
OstreeTlsCertInteraction *
ostree_tls_cert_interaction_new (GTlsCertificate *cert)
{
OstreeTlsCertInteraction *self = g_object_new (OSTREE_TYPE_TLS_CERT_INTERACTION, NULL);
self->cert = g_object_ref (cert);
return self;
}

View File

@ -0,0 +1,39 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
*
* Copyright (C) 2013 Colin Walters <walters@verbum.org>
*
* 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, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <gio/gio.h>
G_BEGIN_DECLS
#define OSTREE_TYPE_TLS_CERT_INTERACTION (ostree_tls_cert_interaction_get_type ())
#define OSTREE_TLS_CERT_INTERACTION(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), OSTREE_TYPE_TLS_CERT_INTERACTION, OstreeTlsCertInteraction))
#define OSTREE_TLS_CERT_INTERACTION_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), OSTREE_TYPE_TLS_CERT_INTERACTION, OstreeTlsCertInteractionClass))
#define OSTREE_IS_TLS_CERT_INTERACTION(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), OSTREE_TYPE_TLS_CERT_INTERACTION))
#define OSTREE_IS_TLS_CERT_INTERACTION_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), OSTREE_TYPE_TLS_CERT_INTERACTION))
#define OSTREE_TLS_CERT_INTERACTION_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), OSTREE_TYPE_TLS_CERT_INTERACTION, OstreeTlsCertInteractionClass))
typedef struct _OstreeTlsCertInteraction OstreeTlsCertInteraction;
typedef struct _OstreeTlsCertInteractionClass OstreeTlsCertInteractionClass;
GType ostree_tls_cert_interaction_get_type (void) G_GNUC_CONST;
OstreeTlsCertInteraction * ostree_tls_cert_interaction_new (GTlsCertificate *cert);
G_END_DECLS