Authentication with SASL needs username and password.

Signed-off-by: Dietmar Maurer <dietmar@proxmox.com>

Index: new/gtk/spice-session.c
===================================================================
--- new.orig/gtk/spice-session.c	2013-10-23 12:25:12.000000000 +0200
+++ new/gtk/spice-session.c	2013-10-23 12:25:12.000000000 +0200
@@ -108,7 +108,8 @@
     PROP_NAME,
     PROP_CA,
     PROP_PROXY,
-    PROP_SECURE_CHANNELS
+    PROP_SECURE_CHANNELS,
+    PROP_USERNAME
 };
 
 /* signals */
@@ -229,6 +230,7 @@
     g_free(s->port);
     g_free(s->tls_port);
     g_free(s->password);
+    g_free(s->username);
     g_free(s->ca_file);
     g_free(s->ciphers);
     g_free(s->cert_subject);
@@ -272,7 +274,7 @@
 static int spice_uri_parse(SpiceSession *session, const char *original_uri)
 {
     SpiceSessionPrivate *s = SPICE_SESSION_GET_PRIVATE(session);
-    gchar *host = NULL, *port = NULL, *tls_port = NULL, *uri = NULL, *password = NULL;
+    gchar *host = NULL, *port = NULL, *tls_port = NULL, *uri = NULL, *password = NULL, *username = NULL;
     gchar *path = NULL;
     gchar *unescaped_path = NULL;
     gchar *authority = NULL;
@@ -358,6 +360,8 @@
             target_key = &port;
         } else if (g_str_equal(key, "tls-port")) {
             target_key = &tls_port;
+        } else if (g_str_equal(key, "username")) {
+            target_key = &username;
         } else if (g_str_equal(key, "password")) {
             target_key = &password;
             g_warning("password may be visible in process listings");
@@ -386,10 +390,12 @@
     g_free(s->port);
     g_free(s->tls_port);
     g_free(s->password);
+    g_free(s->username);
     s->host = host;
     s->port = port;
     s->tls_port = tls_port;
     s->password = password;
+    s->username = username;
     return 0;
 
 fail:
@@ -399,6 +405,7 @@
     g_free(port);
     g_free(tls_port);
     g_free(password);
+    g_free(username);
     return -1;
 }
 
@@ -422,6 +429,9 @@
     case PROP_TLS_PORT:
         g_value_set_string(value, s->tls_port);
 	break;
+    case PROP_USERNAME:
+        g_value_set_string(value, s->username);
+	break;
     case PROP_PASSWORD:
         g_value_set_string(value, s->password);
 	break;
@@ -529,7 +539,11 @@
         g_free(s->tls_port);
         s->tls_port = g_value_dup_string(value);
         break;
-    case PROP_PASSWORD:
+    case PROP_USERNAME:
+        g_free(s->username);
+        s->username = g_value_dup_string(value);
+        break;
+     case PROP_PASSWORD:
         g_free(s->password);
         s->password = g_value_dup_string(value);
         break;
@@ -688,6 +702,21 @@
                              G_PARAM_READWRITE |
                              G_PARAM_STATIC_STRINGS));
 
+   /**
+     * SpiceSession:username:
+     *
+     * username to use
+     *
+     **/
+    g_object_class_install_property
+        (gobject_class, PROP_USERNAME,
+         g_param_spec_string("username",
+                             "Username",
+                             "",
+                             NULL,
+                             G_PARAM_READWRITE |
+                             G_PARAM_STATIC_STRINGS));
+
     /**
      * SpiceSession:password:
      *
@@ -1199,6 +1228,7 @@
     g_warn_if_fail(c->host == NULL);
     g_warn_if_fail(c->tls_port == NULL);
     g_warn_if_fail(c->password == NULL);
+    g_warn_if_fail(c->username == NULL);
     g_warn_if_fail(c->ca_file == NULL);
     g_warn_if_fail(c->ciphers == NULL);
     g_warn_if_fail(c->cert_subject == NULL);
@@ -1210,6 +1240,7 @@
                  "host", &c->host,
                  "tls-port", &c->tls_port,
                  "password", &c->password,
+                 "username", &c->username,
                  "ca-file", &c->ca_file,
                  "ciphers", &c->ciphers,
                  "cert-subject", &c->cert_subject,
@@ -2037,6 +2068,15 @@
 }
 
 G_GNUC_INTERNAL
+const gchar* spice_session_get_username(SpiceSession *session)
+{
+    SpiceSessionPrivate *s = SPICE_SESSION_GET_PRIVATE(session);
+
+    g_return_val_if_fail(s != NULL, NULL);
+    return s->username;
+}
+
+G_GNUC_INTERNAL
 const gchar* spice_session_get_password(SpiceSession *session)
 {
     SpiceSessionPrivate *s = SPICE_SESSION_GET_PRIVATE(session);
Index: new/gtk/spice-session-priv.h
===================================================================
--- new.orig/gtk/spice-session-priv.h	2013-10-03 11:11:56.000000000 +0200
+++ new/gtk/spice-session-priv.h	2013-10-23 12:25:12.000000000 +0200
@@ -37,6 +37,7 @@
     char              *host;
     char              *port;
     char              *tls_port;
+    char              *username;
     char              *password;
     char              *ca_file;
     char              *ciphers;
@@ -135,6 +136,7 @@
 void spice_session_set_port(SpiceSession *session, int port, gboolean tls);
 void spice_session_get_pubkey(SpiceSession *session, guint8 **pubkey, guint *size);
 guint spice_session_get_verify(SpiceSession *session);
+const gchar* spice_session_get_username(SpiceSession *session);
 const gchar* spice_session_get_password(SpiceSession *session);
 const gchar* spice_session_get_host(SpiceSession *session);
 const gchar* spice_session_get_cert_subject(SpiceSession *session);
Index: new/gtk/spice-channel.c
===================================================================
--- new.orig/gtk/spice-channel.c	2013-10-23 12:25:12.000000000 +0200
+++ new/gtk/spice-channel.c	2013-10-23 12:29:28.000000000 +0200
@@ -1282,7 +1282,11 @@
         switch (interact[ninteract].id) {
         case SASL_CB_AUTHNAME:
         case SASL_CB_USER:
-            g_warn_if_reached();
+            if (spice_session_get_username(c->session) == NULL)
+                return FALSE;
+
+            interact[ninteract].result = spice_session_get_username(c->session);
+            interact[ninteract].len = strlen(interact[ninteract].result);
             break;
 
         case SASL_CB_PASS:
@@ -1351,6 +1355,8 @@
     const void *val;
     sasl_ssf_t ssf;
     sasl_callback_t saslcb[] = {
+        { .id = SASL_CB_USER },
+        { .id = SASL_CB_AUTHNAME },
         { .id = SASL_CB_PASS },
         { .id = 0 },
     };

