From 1bb261f222d543cdc95f5167c80eba2d558ba2c4 Mon Sep 17 00:00:00 2001
From: Alexander Graf <agraf@suse.de>
Date: Wed, 12 Dec 2012 19:19:27 +0100
Subject: [PATCH] Legacy Patch kvm-studio-vnc.patch

---
 ui/vnc.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 72 insertions(+)

diff --git a/ui/vnc.c b/ui/vnc.c
index 9ba379436f..d0128ef700 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -45,6 +45,7 @@ static const struct timeval VNC_REFRESH_LOSSY = { 2, 0 };
 
 static VncDisplay *vnc_display; /* needed for info vnc */
 static DisplayChangeListener *dcl;
+static int allowed_connections = 0;
 
 static int vnc_cursor_define(VncState *vs);
 static void vnc_release_modifiers(VncState *vs);
@@ -1025,6 +1026,7 @@ static void vnc_disconnect_start(VncState *vs)
 void vnc_disconnect_finish(VncState *vs)
 {
     int i;
+    static int num_disconnects = 0;
 
     vnc_jobs_join(vs); /* Wait encoding jobs */
 
@@ -1078,6 +1080,13 @@ void vnc_disconnect_finish(VncState *vs)
     }
     g_free(vs->lossy_rect);
     g_free(vs);
+
+    num_disconnects++;
+    if (allowed_connections > 0 && allowed_connections <= num_disconnects) {
+        VNC_DEBUG("Maximum number of disconnects (%d) reached:"
+                  " Session terminating\n", allowed_connections);
+        exit(0);
+    }
 }
 
 int vnc_client_io_error(VncState *vs, int ret, int last_errno)
@@ -2958,6 +2967,39 @@ char *vnc_display_local_addr(DisplayState *ds)
     return vnc_socket_local_addr("%s:%s", vs->lsock);
 }
 
+static void read_file_password(DisplayState *ds, char *filename, Error **errp)
+{
+    FILE *pfile = NULL;
+    char *passwd = NULL;
+    int start = 0, length = 0, rc = 0;
+
+    if(strlen(filename) == 0) {
+	error_setg(errp, "No file supplied");
+	return;
+    }
+
+    pfile = fopen(filename, "r");
+    if(pfile == NULL) {
+	error_setg(errp, "Could not read from %s", filename);
+	return;
+    }
+
+    start  = ftell(pfile);
+    fseek(pfile, 0L, SEEK_END);
+    length = ftell(pfile);
+    fseek(pfile, 0L, start);
+
+    passwd = g_malloc(length+1);
+    rc = fread(passwd, 1, length, pfile);
+    fclose(pfile);
+
+    if(rc == length && rc > 0) {
+	vnc_display_password(ds, passwd);
+    }
+
+    g_free(passwd);
+}
+
 void vnc_display_open(DisplayState *ds, const char *display, Error **errp)
 {
     VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
@@ -2991,6 +3033,9 @@ void vnc_display_open(DisplayState *ds, const char *display, Error **errp)
     while ((options = strchr(options, ','))) {
         options++;
         if (strncmp(options, "password", 8) == 0) {
+            char *start, *end;
+            start = strchr(options, '=');
+            end = strchr(options, ',');
             if (fips_get_state()) {
                 error_setg(errp,
                            "VNC password auth disabled due to FIPS mode, "
@@ -2999,6 +3044,33 @@ void vnc_display_open(DisplayState *ds, const char *display, Error **errp)
                 goto fail;
             }
             password = 1; /* Require password auth */
+            if (start && (!end || (start < end))) {
+                int len = end ? end-(start+1) : strlen(start+1);
+                char *text = g_malloc(len+1);
+                strncpy(text, start+1, len);
+                text[len] = '\0';
+
+                if (strncmp(options, "password-file=", 14) == 0) {
+                    read_file_password(ds, text, errp);
+                } else {
+                    vnc_display_password(ds, text);
+                }
+
+                g_free(text);
+            }
+        } else if (strncmp(options, "allowed-connections=", 20) == 0) {
+            char *start, *end;
+            start = strchr(options, '=');
+            end = strchr(options, ',');
+            if (start && (!end || (start < end))) {
+                int len = end ? end-(start+1) : strlen(start+1);
+                char *text = g_malloc(len+1);
+                strncpy(text, start+1, len);
+                text[len] = '\0';
+                VNC_DEBUG("Maximum number of disconnects: %s\n", text);
+                allowed_connections = atoi(text);
+                g_free(text);
+            }
         } else if (strncmp(options, "reverse", 7) == 0) {
             reverse = 1;
         } else if (strncmp(options, "no-lock-key-sync", 16) == 0) {
