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



commit 25ad4a9f65a5dae9348fd38c7f4b8b0df1f9773a
Author: Colin Walters <walters verbum org>
Date:   Thu May 1 12:55:13 2014 -0400

    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

 Makefile-libostree.am                       |    8 +++-
 configure.ac                                |    9 ++++
 doc/ostree.repo-config.xml                  |   20 +++++++-
 src/libostree/ostree-fetcher.c              |   28 +++++++++++
 src/libostree/ostree-fetcher.h              |    3 +
 src/libostree/ostree-repo-pull.c            |   35 ++++++++++++++
 src/libostree/ostree-tls-cert-interaction.c |   69 +++++++++++++++++++++++++++
 src/libostree/ostree-tls-cert-interaction.h |   39 +++++++++++++++
 8 files changed, 209 insertions(+), 2 deletions(-)
---
diff --git a/Makefile-libostree.am b/Makefile-libostree.am
index 5fd6000..d2c039c 100644
--- a/Makefile-libostree.am
+++ b/Makefile-libostree.am
@@ -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_'
diff --git a/configure.ac b/configure.ac
index 9089ddc..74094c9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -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])
diff --git a/doc/ostree.repo-config.xml b/doc/ostree.repo-config.xml
index 07244d0..4240814 100644
--- a/doc/ostree.repo-config.xml
+++ b/doc/ostree.repo-config.xml
@@ -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>
diff --git a/src/libostree/ostree-fetcher.c b/src/libostree/ostree-fetcher.c
index c8db3a0..06023c6 100644
--- a/src/libostree/ostree-fetcher.c
+++ b/src/libostree/ostree-fetcher.c
@@ -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);
diff --git a/src/libostree/ostree-fetcher.h b/src/libostree/ostree-fetcher.h
index 220bd93..928d2a3 100644
--- a/src/libostree/ostree-fetcher.h
+++ b/src/libostree/ostree-fetcher.h
@@ -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);
diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c
index 427bd92..e3e5a77 100644
--- a/src/libostree/ostree-repo-pull.c
+++ b/src/libostree/ostree-repo-pull.c
@@ -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,
diff --git a/src/libostree/ostree-tls-cert-interaction.c b/src/libostree/ostree-tls-cert-interaction.c
new file mode 100644
index 0000000..63de917
--- /dev/null
+++ b/src/libostree/ostree-tls-cert-interaction.c
@@ -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;
+}
diff --git a/src/libostree/ostree-tls-cert-interaction.h b/src/libostree/ostree-tls-cert-interaction.h
new file mode 100644
index 0000000..ca9cd32
--- /dev/null
+++ b/src/libostree/ostree-tls-cert-interaction.h
@@ -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


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]