[Spice-commits] 2 commits - gtk/spice-channel.c gtk/spice-session.c gtk/spice-session-priv.h

Marc-André Lureau elmarco at kemper.freedesktop.org
Thu Nov 22 10:11:39 PST 2012


 gtk/spice-channel.c      |   69 +++++++++++++++++++++++++++++++++++++++++------
 gtk/spice-session-priv.h |    2 +
 gtk/spice-session.c      |   46 +++++++++++++++++++++++++++++--
 3 files changed, 107 insertions(+), 10 deletions(-)

New commits:
commit 1625aef30129d1961bead56bfcc1727ed46d1df3
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Mon Nov 19 21:47:41 2012 +0100

    channel: learn to load certificate from memory
    
    Sadly, OpenSSL doesn't provide a way to load certificate from memory,
    but all the functions necessary to do so are actually public, so we
    can implement our own version and avoid files, how awesome!

diff --git a/gtk/spice-channel.c b/gtk/spice-channel.c
index fea46d7..500935a 100644
--- a/gtk/spice-channel.c
+++ b/gtk/spice-channel.c
@@ -2087,6 +2087,64 @@ static gboolean spice_channel_delayed_unref(gpointer data)
     return FALSE;
 }
 
+static X509_LOOKUP_METHOD spice_x509_mem_lookup = {
+    "spice_x509_mem_lookup",
+    0
+};
+
+static int spice_channel_load_ca(SpiceChannel *channel)
+{
+    SpiceChannelPrivate *c = channel->priv;
+    STACK_OF(X509_INFO) *inf;
+    X509_INFO *itmp;
+    X509_LOOKUP *lookup;
+    BIO *in;
+    int i, count = 0;
+    guint8 *ca;
+    guint size;
+    const gchar *ca_file;
+
+    g_return_val_if_fail(c->ctx != NULL, 0);
+
+    lookup = X509_STORE_add_lookup(c->ctx->cert_store, &spice_x509_mem_lookup);
+    ca_file = spice_session_get_ca_file(c->session);
+    spice_session_get_ca(c->session, &ca, &size);
+
+    CHANNEL_DEBUG(channel, "Load CA, file: %s, data: %p", ca_file, ca);
+    g_warn_if_fail(ca_file || ca);
+
+    if (ca != NULL) {
+        in = BIO_new_mem_buf(ca, size);
+        inf = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL);
+        BIO_free(in);
+
+        for (i = 0; i < sk_X509_INFO_num(inf); i++) {
+            itmp = sk_X509_INFO_value(inf, i);
+            if (itmp->x509) {
+                X509_STORE_add_cert(lookup->store_ctx, itmp->x509);
+                count++;
+            }
+            if (itmp->crl) {
+                X509_STORE_add_crl(lookup->store_ctx, itmp->crl);
+                count++;
+            }
+        }
+
+        sk_X509_INFO_pop_free(inf, X509_INFO_free);
+    }
+
+    if (ca_file != NULL) {
+        int rc = SSL_CTX_load_verify_locations(c->ctx, ca_file, NULL);
+        if (rc != 1)
+            g_warning("loading ca certs from %s failed", ca_file);
+        else
+            count++;
+    }
+
+    return count;
+}
+
+
 /* coroutine context */
 static void *spice_channel_coroutine(void *data)
 {
@@ -2142,14 +2200,9 @@ reconnect:
         verify = spice_session_get_verify(c->session);
         if (verify &
             (SPICE_SESSION_VERIFY_SUBJECT | SPICE_SESSION_VERIFY_HOSTNAME)) {
-            const gchar *ca_file = spice_session_get_ca_file (c->session);
-
-            g_warn_if_fail(ca_file != NULL);
-            CHANNEL_DEBUG(channel, "CA file: %s", ca_file);
-            rc = SSL_CTX_load_verify_locations(c->ctx, ca_file, NULL);
-
-            if (rc != 1) {
-                g_warning("loading ca certs from %s failed", ca_file);
+            rc = spice_channel_load_ca(channel);
+            if (rc == 0) {
+                g_warning("no cert loaded");
                 if (verify & SPICE_SESSION_VERIFY_PUBKEY) {
                     g_warning("only pubkey active");
                     verify = SPICE_SESSION_VERIFY_PUBKEY;
commit caeb29b507996b9e70e10c568ed5c85deeddda11
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Thu Nov 22 19:05:52 2012 +0100

    Add SpiceSession:ca property

diff --git a/gtk/spice-session-priv.h b/gtk/spice-session-priv.h
index 13345b4..804658d 100644
--- a/gtk/spice-session-priv.h
+++ b/gtk/spice-session-priv.h
@@ -40,6 +40,7 @@ struct _SpiceSessionPrivate {
     char              *ca_file;
     char              *ciphers;
     GByteArray        *pubkey;
+    GByteArray        *ca;
     char              *cert_subject;
     guint             verify;
     gboolean          read_only;
@@ -135,6 +136,7 @@ const gchar* spice_session_get_host(SpiceSession *session);
 const gchar* spice_session_get_cert_subject(SpiceSession *session);
 const gchar* spice_session_get_ciphers(SpiceSession *session);
 const gchar* spice_session_get_ca_file(SpiceSession *session);
+void spice_session_get_ca(SpiceSession *session, guint8 **ca, guint *size);
 
 void spice_session_set_caches_hints(SpiceSession *session,
                                     uint32_t pci_ram_size,
diff --git a/gtk/spice-session.c b/gtk/spice-session.c
index 526d05b..85cc14d 100644
--- a/gtk/spice-session.c
+++ b/gtk/spice-session.c
@@ -103,6 +103,7 @@ enum {
     PROP_GLZ_WINDOW_SIZE,
     PROP_UUID,
     PROP_NAME,
+    PROP_CA,
 };
 
 /* signals */
@@ -233,8 +234,8 @@ spice_session_finalize(GObject *gobject)
     spice_session_images_clear(session);
     glz_decoder_window_destroy(s->glz_window);
 
-    if (s->pubkey)
-        g_byte_array_unref(s->pubkey);
+    g_clear_pointer(&s->pubkey, g_byte_array_unref);
+    g_clear_pointer(&s->ca, g_byte_array_unref);
 
     /* Chain up to the parent class */
     if (G_OBJECT_CLASS(spice_session_parent_class)->finalize)
@@ -437,6 +438,9 @@ static void spice_session_get_property(GObject    *gobject,
     case PROP_PUBKEY:
         g_value_set_boxed(value, s->pubkey);
 	break;
+    case PROP_CA:
+        g_value_set_boxed(value, s->ca);
+	break;
     case PROP_CERT_SUBJECT:
         g_value_set_string(value, s->cert_subject);
 	break;
@@ -596,6 +600,10 @@ static void spice_session_set_property(GObject      *gobject,
     case PROP_GLZ_WINDOW_SIZE:
         s->glz_window_size = g_value_get_int(value);
         break;
+    case PROP_CA:
+        g_clear_pointer(&s->ca, g_byte_array_unref);
+        s->ca = g_value_dup_boxed(value);
+        break;
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, pspec);
         break;
@@ -950,6 +958,27 @@ static void spice_session_class_init(SpiceSessionClass *klass)
                         G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
     /**
+     * SpiceSession:ca:
+     *
+     * CA certificates in PEM format. The text data can contain
+     * several CA certificates identified by:
+     *
+     *  -----BEGIN CERTIFICATE-----
+     *  ... (CA certificate in base64 encoding) ...
+     *  -----END CERTIFICATE-----
+     *
+     * Since: 0.15
+     **/
+    g_object_class_install_property
+        (gobject_class, PROP_CA,
+         g_param_spec_boxed("ca",
+                            "CA",
+                            "The CA certificates data",
+                            G_TYPE_BYTE_ARRAY,
+                            G_PARAM_READWRITE |
+                            G_PARAM_STATIC_STRINGS));
+
+    /**
      * SpiceSession::channel-new:
      * @session: the session that emitted the signal
      * @channel: the new #SpiceChannel
@@ -1772,6 +1801,19 @@ void spice_session_get_pubkey(SpiceSession *session, guint8 **pubkey, guint *siz
 }
 
 G_GNUC_INTERNAL
+void spice_session_get_ca(SpiceSession *session, guint8 **ca, guint *size)
+{
+    SpiceSessionPrivate *s = SPICE_SESSION_GET_PRIVATE(session);
+
+    g_return_if_fail(s != NULL);
+    g_return_if_fail(ca != NULL);
+    g_return_if_fail(size != NULL);
+
+    *ca = s->ca ? s->ca->data : NULL;
+    *size = s->ca ? s->ca->len : 0;
+}
+
+G_GNUC_INTERNAL
 guint spice_session_get_verify(SpiceSession *session)
 {
     SpiceSessionPrivate *s = SPICE_SESSION_GET_PRIVATE(session);


More information about the Spice-commits mailing list