[libgovirt] OvirtProxy: take into account RestProxy::ssl-ca-cert
- From: Christophe Fergeau <teuf src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libgovirt] OvirtProxy: take into account RestProxy::ssl-ca-cert
- Date: Tue, 8 Oct 2013 17:06:32 +0000 (UTC)
commit b804e76e6df4e827290184c74837645b1e544b23
Author: Christophe Fergeau <cfergeau redhat com>
Date: Mon Sep 16 18:25:21 2013 +0200
OvirtProxy: take into account RestProxy::ssl-ca-cert
Now that RestProxy has a ssl-ca-cert property, OvirtProxy::ca-cert
is redundant. We want to use ssl-ca-file as the canonical property, and
set ca-cert value from it. However, when the user sets the ca-cert
property, we need to create a temporary file in order to be able to keep
the ssl-ca-file property synced with it, which is why the code changes
are more complicated than expected.
govirt/ovirt-proxy-private.h | 2 +-
govirt/ovirt-proxy.c | 149 ++++++++++++++++++++++++++++++++++++------
2 files changed, 129 insertions(+), 22 deletions(-)
---
diff --git a/govirt/ovirt-proxy-private.h b/govirt/ovirt-proxy-private.h
index cd5544c..c2cbb65 100644
--- a/govirt/ovirt-proxy-private.h
+++ b/govirt/ovirt-proxy-private.h
@@ -31,7 +31,7 @@ G_BEGIN_DECLS
struct _OvirtProxyPrivate {
GHashTable *vms;
- GByteArray *ca_cert;
+ char *tmp_ca_file;
gboolean admin_mode;
OvirtApi *api;
};
diff --git a/govirt/ovirt-proxy.c b/govirt/ovirt-proxy.c
index 2e2ade8..ab70a87 100644
--- a/govirt/ovirt-proxy.c
+++ b/govirt/ovirt-proxy.c
@@ -49,6 +49,12 @@ enum {
#define CA_CERT_FILENAME "ca.crt"
+static gboolean set_ca_cert_from_data(OvirtProxy *proxy,
+ char *ca_cert_data,
+ gsize ca_cert_len);
+static GByteArray *get_ca_cert_data(OvirtProxy *proxy);
+static void ovirt_proxy_set_tmp_ca_file(OvirtProxy *proxy, const char *ca_file);
+
#ifdef OVIRT_DEBUG
static void dump_display(OvirtVmDisplay *display)
{
@@ -392,15 +398,110 @@ error:
return ca_file;
}
-static void set_downloaded_ca_cert(OvirtProxy *proxy,
- char *ca_cert_data,
- gsize ca_cert_len)
+static GByteArray *get_ca_cert_data(OvirtProxy *proxy)
+{
+ char *ca_file;
+ char *content;
+ gsize length;
+ GError *error = NULL;
+ gboolean read_success;
+
+ g_object_get(G_OBJECT(proxy), "ssl-ca-file", &ca_file, NULL);
+ if (ca_file == NULL) {
+ return NULL;
+ }
+ read_success = g_file_get_contents(ca_file, &content, &length, &error);
+ if (!read_success) {
+ if (error != NULL) {
+ g_warning("Couldn't read %s: %s", ca_file, error->message);
+ } else {
+ g_warning("Couldn't read %s", ca_file);
+ }
+ g_free(ca_file);
+ return NULL;
+ }
+ g_free(ca_file);
+
+ return g_byte_array_new_take((guchar *)content, length);
+}
+
+static void ovirt_proxy_set_tmp_ca_file(OvirtProxy *proxy, const char *ca_file)
+{
+ if (proxy->priv->tmp_ca_file != NULL) {
+ int unlink_failed;
+ unlink_failed = g_unlink(proxy->priv->tmp_ca_file);
+ if (unlink_failed == -1) {
+ g_warning("Failed to unlink '%s'", proxy->priv->tmp_ca_file);
+ }
+ g_free(proxy->priv->tmp_ca_file);
+ }
+ proxy->priv->tmp_ca_file = g_strdup(ca_file);
+ if (ca_file != NULL) {
+ g_object_set(G_OBJECT(proxy), "ssl-ca-file", ca_file, NULL);
+ }
+}
+
+static gboolean set_ca_cert_from_data(OvirtProxy *proxy,
+ char *ca_cert_data,
+ gsize ca_cert_len)
{
- if (proxy->priv->ca_cert != NULL)
- g_byte_array_unref(proxy->priv->ca_cert);
- proxy->priv->ca_cert = g_byte_array_new_take((guint8 *)ca_cert_data,
- ca_cert_len);
+ /* This function is quite complicated for historical reasons, we
+ * initially only had a ca-cert property in OvirtProxy with type
+ * GByteArray. RestProxy then got a ssl-ca-file property storing a
+ * filename. We want to use ssl-ca-file as the canonical property,
+ * and set ca-cert value from it. However, when the user sets
+ * the ca-cert property, we need to create a temporary file in order
+ * to be able to keep the ssl-ca-file property synced with it
+ */
+ GFile *ca_file = NULL;
+ GFileIOStream *iostream;
+ GOutputStream *output;
+ char *ca_file_path;
+ gboolean write_ok;
+ GError *error = NULL;
+ gboolean result = FALSE;
+
+ ca_file = g_file_new_tmp("govirt-ca-XXXXXX.crt", &iostream, &error);
+ if (ca_file == NULL) {
+ if (error != NULL) {
+ g_warning("Failed to create temporary file for CA certificate: %s",
+ error->message);
+ } else {
+ g_warning("Failed to create temporary file for CA certificate");
+ }
+
+ goto end;
+ }
+ output = g_io_stream_get_output_stream(G_IO_STREAM(iostream));
+ g_return_val_if_fail(output != NULL, FALSE);
+ write_ok = g_output_stream_write_all(output, ca_cert_data, ca_cert_len,
+ NULL, NULL, &error);
+ if (!write_ok) {
+ char *path;
+ path = g_file_get_path(ca_file);
+ if (error != NULL) {
+ g_warning("Failed to write ca file '%s': %s",
+ path, error->message);
+ } else {
+ g_warning("Failed to write ca file '%s'", path);
+ }
+ g_free(path);
+ goto end;
+ }
+ ca_file_path = g_file_get_path(ca_file);
+ g_warn_if_fail(ca_file_path != NULL);
+ ovirt_proxy_set_tmp_ca_file(proxy, ca_file_path);
+ g_free(ca_file_path);
+
g_object_notify(G_OBJECT(proxy), "ca-cert");
+ result = TRUE;
+
+end:
+ if (ca_file != NULL) {
+ g_object_unref(G_OBJECT(ca_file));
+ }
+ g_clear_error(&error);
+ return result;
}
gboolean ovirt_proxy_fetch_ca_certificate(OvirtProxy *proxy, GError **error)
@@ -426,7 +527,7 @@ gboolean ovirt_proxy_fetch_ca_certificate(OvirtProxy *proxy, GError **error)
if (!load_ok)
goto error;
- set_downloaded_ca_cert(proxy, cert_data, cert_length);
+ set_ca_cert_from_data(proxy, cert_data, cert_length);
error:
if (source != NULL)
@@ -457,7 +558,7 @@ static void ca_file_loaded_cb(GObject *source_object,
proxy = g_async_result_get_source_object(G_ASYNC_RESULT(fetch_result));
- set_downloaded_ca_cert(OVIRT_PROXY(proxy), cert_data, cert_length);
+ set_ca_cert_from_data(OVIRT_PROXY(proxy), cert_data, cert_length);
g_object_unref(proxy);
g_simple_async_result_set_op_res_gboolean(fetch_result, TRUE);
g_simple_async_result_complete (fetch_result);
@@ -503,10 +604,7 @@ GByteArray *ovirt_proxy_fetch_ca_certificate_finish(OvirtProxy *proxy,
if (g_simple_async_result_propagate_error(G_SIMPLE_ASYNC_RESULT(result), err))
return NULL;
- if (proxy->priv->ca_cert == NULL)
- return NULL;
-
- return g_byte_array_ref(proxy->priv->ca_cert);
+ return get_ca_cert_data(proxy);
}
static void ovirt_proxy_get_property(GObject *object,
@@ -518,7 +616,7 @@ static void ovirt_proxy_get_property(GObject *object,
switch (prop_id) {
case PROP_CA_CERT:
- g_value_set_boxed(value, proxy->priv->ca_cert);
+ g_value_take_boxed(value, get_ca_cert_data(proxy));
break;
case PROP_ADMIN:
g_value_set_boolean(value, proxy->priv->admin_mode);
@@ -537,11 +635,12 @@ static void ovirt_proxy_set_property(GObject *object,
OvirtProxy *proxy = OVIRT_PROXY(object);
switch (prop_id) {
- case PROP_CA_CERT:
- if (proxy->priv->ca_cert != NULL)
- g_byte_array_unref(proxy->priv->ca_cert);
- proxy->priv->ca_cert = g_value_dup_boxed(value);
+ case PROP_CA_CERT: {
+ GByteArray *ca_cert;
+ ca_cert = g_value_get_boxed(value);
+ set_ca_cert_from_data(proxy, (char *)ca_cert->data, ca_cert->len);
break;
+ }
case PROP_ADMIN:
proxy->priv->admin_mode = g_value_get_boolean(value);
@@ -570,9 +669,7 @@ ovirt_proxy_finalize(GObject *obj)
{
OvirtProxy *proxy = OVIRT_PROXY(obj);
- if (proxy->priv->ca_cert != NULL)
- g_byte_array_unref(proxy->priv->ca_cert);
- proxy->priv->ca_cert = NULL;
+ ovirt_proxy_set_tmp_ca_file(proxy, NULL);
G_OBJECT_CLASS(ovirt_proxy_parent_class)->finalize(obj);
}
@@ -608,10 +705,20 @@ ovirt_proxy_class_init(OvirtProxyClass *klass)
g_type_class_add_private(klass, sizeof(OvirtProxyPrivate));
}
+static void ssl_ca_file_changed(GObject *gobject,
+ GParamSpec *pspec,
+ gpointer user_data)
+{
+ ovirt_proxy_set_tmp_ca_file(OVIRT_PROXY(gobject), NULL);
+}
+
static void
ovirt_proxy_init(OvirtProxy *self)
{
self->priv = OVIRT_PROXY_GET_PRIVATE(self);
+
+ g_signal_connect(G_OBJECT(self), "notify::ssl-ca-file",
+ (GCallback)ssl_ca_file_changed, NULL);
}
OvirtProxy *ovirt_proxy_new(const char *uri)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]