[Spice-devel] [spice-gtk 5/5] Use credentials from config file

Christophe Fergeau cfergeau at redhat.com
Tue Jun 4 07:19:14 PDT 2013


When a ticket is needed to during a connection to a SPICE channel,
if there is no ticket set in the current SPICE session, we can now
use the SpiceAuthFile class to lookup credentials for the connection
stored in a config file, as described on http://libvirt.org/auth.html
---
 gtk/spice-channel.c      | 67 ++++++++++++++++++++++++++++++++++++++++++------
 gtk/spice-session-priv.h |  2 ++
 gtk/spice-session.c      | 18 +++++++++++++
 3 files changed, 79 insertions(+), 8 deletions(-)

diff --git a/gtk/spice-channel.c b/gtk/spice-channel.c
index 74a02fb..335f8e5 100644
--- a/gtk/spice-channel.c
+++ b/gtk/spice-channel.c
@@ -19,6 +19,7 @@
 #include "spice-common.h"
 #include "glib-compat.h"
 
+#include "spice-auth-file.h"
 #include "spice-channel-priv.h"
 #include "spice-session-priv.h"
 #include "spice-marshal.h"
@@ -1018,6 +1019,40 @@ static int spice_channel_read(SpiceChannel *channel, void *data, size_t length)
     return length;
 }
 
+static char *spice_channel_get_session_password(SpiceChannel *channel)
+{
+    const char *password;
+    const char *hostname;
+    const char *port;
+    char *host;
+    const char *auth_file;
+    SpiceChannelPrivate *priv = channel->priv;
+
+    password = spice_session_get_password(priv->session);
+    if (password != NULL)
+        return g_strdup(password);
+
+    hostname = spice_session_get_host(priv->session);
+    if (hostname == NULL)
+        return NULL;
+
+    if (priv->tls) {
+        port = spice_session_get_tls_port(priv->session);
+    } else {
+        port = spice_session_get_port(priv->session);
+    }
+    if (port == NULL)
+        return NULL;
+
+    auth_file = spice_session_get_auth_file(priv->session);
+    host = g_strdup_printf("%s:%s", hostname, port);
+    password = spice_auth_file_lookup_credential(auth_file, host,
+                                                 "password", NULL);
+    g_free(host);
+
+    return (char *)password;
+}
+
 /* coroutine context */
 static void spice_channel_send_spice_ticket(SpiceChannel *channel)
 {
@@ -1045,7 +1080,7 @@ static void spice_channel_send_spice_ticket(SpiceChannel *channel)
       The use of RSA encryption limit the potential maximum password length.
       for RSA_PKCS1_OAEP_PADDING it is RSA_size(rsa) - 41.
     */
-    g_object_get(c->session, "password", &password, NULL);
+    password = spice_channel_get_session_password(channel);
     if (password == NULL)
         password = g_strdup("");
     rc = RSA_public_encrypt(strlen(password) + 1, (uint8_t*)password,
@@ -1242,18 +1277,29 @@ static gchar *addr_to_string(GSocketAddress *addr)
     return ret;
 }
 
+static void
+spice_channel_free_sasl_credentials(sasl_interact_t *interact)
+{
+    unsigned int ninteract;
+
+    if (interact == NULL)
+        return;
+
+    for (ninteract = 0 ; interact[ninteract].id != 0 ; ninteract++) {
+        if (interact[ninteract].id == SASL_CB_PASS)
+            g_free((char *)interact[ninteract].result);
+    }
+}
+
 static gboolean
 spice_channel_gather_sasl_credentials(SpiceChannel *channel,
-				       sasl_interact_t *interact)
+				      sasl_interact_t *interact)
 {
-    SpiceChannelPrivate *c;
     int ninteract;
 
     g_return_val_if_fail(channel != NULL, FALSE);
     g_return_val_if_fail(channel->priv != NULL, FALSE);
 
-    c = channel->priv;
-
     /* FIXME: we could keep connection open and ask connection details if missing */
 
     for (ninteract = 0 ; interact[ninteract].id != 0 ; ninteract++) {
@@ -1263,14 +1309,17 @@ spice_channel_gather_sasl_credentials(SpiceChannel *channel,
             g_warn_if_reached();
             break;
 
-        case SASL_CB_PASS:
-            if (spice_session_get_password(c->session) == NULL)
+        case SASL_CB_PASS: {
+            char *password;
+            password = spice_channel_get_session_password(channel);
+            if (password == NULL)
                 return FALSE;
 
-            interact[ninteract].result =  spice_session_get_password(c->session);
+            interact[ninteract].result =  password;
             interact[ninteract].len = strlen(interact[ninteract].result);
             break;
         }
+        }
     }
 
     CHANNEL_DEBUG(channel, "Filled SASL interact");
@@ -1631,6 +1680,7 @@ restart:
     }
 
 complete:
+    spice_channel_free_sasl_credentials(interact);
     CHANNEL_DEBUG(channel, "%s", "SASL authentication complete");
     spice_channel_read(channel, &len, sizeof(len));
     if (len != SPICE_LINK_ERR_OK)
@@ -1643,6 +1693,7 @@ complete:
     return ret;
 
 error:
+    spice_channel_free_sasl_credentials(interact);
     g_clear_object(&addr);
     if (saslconn)
         sasl_dispose(&saslconn);
diff --git a/gtk/spice-session-priv.h b/gtk/spice-session-priv.h
index 218f5c3..8423d0f 100644
--- a/gtk/spice-session-priv.h
+++ b/gtk/spice-session-priv.h
@@ -139,6 +139,8 @@ guint spice_session_get_verify(SpiceSession *session);
 const gchar* spice_session_get_password(SpiceSession *session);
 const gchar* spice_session_get_auth_file(SpiceSession *session);
 const gchar* spice_session_get_host(SpiceSession *session);
+const gchar* spice_session_get_port(SpiceSession *session);
+const gchar* spice_session_get_tls_port(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);
diff --git a/gtk/spice-session.c b/gtk/spice-session.c
index 9746051..289d7e7 100644
--- a/gtk/spice-session.c
+++ b/gtk/spice-session.c
@@ -2118,6 +2118,24 @@ const gchar* spice_session_get_host(SpiceSession *session)
 }
 
 G_GNUC_INTERNAL
+const gchar* spice_session_get_port(SpiceSession *session)
+{
+    SpiceSessionPrivate *s = SPICE_SESSION_GET_PRIVATE(session);
+
+    g_return_val_if_fail(s != NULL, NULL);
+    return s->port;
+}
+
+G_GNUC_INTERNAL
+const gchar* spice_session_get_tls_port(SpiceSession *session)
+{
+    SpiceSessionPrivate *s = SPICE_SESSION_GET_PRIVATE(session);
+
+    g_return_val_if_fail(s != NULL, NULL);
+    return s->tls_port;
+}
+
+G_GNUC_INTERNAL
 const gchar* spice_session_get_cert_subject(SpiceSession *session)
 {
     SpiceSessionPrivate *s = SPICE_SESSION_GET_PRIVATE(session);
-- 
1.8.2.1



More information about the Spice-devel mailing list