From d041589b58c189e1ba0fc7e42fc2d479d949f3d2 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Thu, 18 Mar 2010 17:25:31 -0300
Subject: [PATCH 05/14] vnc: support password expire

RH-Author: Gerd Hoffmann <kraxel@redhat.com>
Message-id: <1268933140-655-6-git-send-email-kraxel@redhat.com>
Patchwork-id: 7900
O-Subject: [RHEL-6 kvm PATCH v3 05/14] vnc: support password expire
Bugzilla: 525935
RH-Acked-by: Yonit Halperin <yhalperi@redhat.com>
RH-Acked-by: Izik Eidus <ieidus@redhat.com>
RH-Acked-by: Juan Quintela <quintela@redhat.com>
RH-Acked-by: Zachary Amsden <zamsden@redhat.com>
RH-Acked-by: Luiz Capitulino <lcapitulino@redhat.com>

bugzilla: #525935 -- RFE: expire vnc password

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 console.h |    2 +-
 monitor.c |    2 +-
 vnc.c     |   43 ++++++++++++++++++++++++++-----------------
 vnc.h     |    1 +
 4 files changed, 29 insertions(+), 19 deletions(-)

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
 console.h |    2 +-
 monitor.c |    2 +-
 vnc.c     |   43 ++++++++++++++++++++++++++-----------------
 vnc.h     |    1 +
 4 files changed, 29 insertions(+), 19 deletions(-)

diff --git a/console.h b/console.h
index d9027f8..5371beb 100644
--- a/console.h
+++ b/console.h
@@ -337,7 +337,7 @@ void cocoa_display_init(DisplayState *ds, int full_screen);
 void vnc_display_init(DisplayState *ds);
 void vnc_display_close(DisplayState *ds);
 int vnc_display_open(DisplayState *ds, const char *display);
-int vnc_display_password(DisplayState *ds, const char *password);
+int vnc_display_password(DisplayState *ds, const char *password, int lifetime);
 void do_info_vnc_print(Monitor *mon, const QObject *data);
 void do_info_vnc(Monitor *mon, QObject **ret_data);
 char *vnc_display_local_addr(DisplayState *ds);
diff --git a/monitor.c b/monitor.c
index 63848ea..ec6a1a3 100644
--- a/monitor.c
+++ b/monitor.c
@@ -975,7 +975,7 @@ static void do_change_block(Monitor *mon, const char *device,
 
 static void change_vnc_password(const char *password)
 {
-    if (vnc_display_password(NULL, password) < 0)
+    if (vnc_display_password(NULL, password, 0) < 0)
         qemu_error_new(QERR_SET_PASSWD_FAILED);
 
 }
diff --git a/vnc.c b/vnc.c
index 94d0d3b..012738d 100644
--- a/vnc.c
+++ b/vnc.c
@@ -2136,18 +2136,18 @@ static int protocol_client_auth_vnc(VncState *vs, uint8_t *data, size_t len)
     unsigned char response[VNC_AUTH_CHALLENGE_SIZE];
     int i, j, pwlen;
     unsigned char key[8];
+    time_t now;
 
     if (!vs->vd->password || !vs->vd->password[0]) {
         VNC_DEBUG("No password configured on server");
-        vnc_write_u32(vs, 1); /* Reject auth */
-        if (vs->minor >= 8) {
-            static const char err[] = "Authentication failed";
-            vnc_write_u32(vs, sizeof(err));
-            vnc_write(vs, err, sizeof(err));
+        goto reject;
+    }
+    if (vs->vd->expires) {
+        time(&now);
+        if (vs->vd->expires < now) {
+            VNC_DEBUG("Password is expired");
+            goto reject;
         }
-        vnc_flush(vs);
-        vnc_client_error(vs);
-        return 0;
     }
 
     memcpy(response, vs->challenge, VNC_AUTH_CHALLENGE_SIZE);
@@ -2163,14 +2163,7 @@ static int protocol_client_auth_vnc(VncState *vs, uint8_t *data, size_t len)
     /* Compare expected vs actual challenge response */
     if (memcmp(response, data, VNC_AUTH_CHALLENGE_SIZE) != 0) {
         VNC_DEBUG("Client challenge reponse did not match\n");
-        vnc_write_u32(vs, 1); /* Reject auth */
-        if (vs->minor >= 8) {
-            static const char err[] = "Authentication failed";
-            vnc_write_u32(vs, sizeof(err));
-            vnc_write(vs, err, sizeof(err));
-        }
-        vnc_flush(vs);
-        vnc_client_error(vs);
+        goto reject;
     } else {
         VNC_DEBUG("Accepting VNC challenge response\n");
         vnc_write_u32(vs, 0); /* Accept auth */
@@ -2179,6 +2172,17 @@ static int protocol_client_auth_vnc(VncState *vs, uint8_t *data, size_t len)
         start_client_init(vs);
     }
     return 0;
+
+reject:
+    vnc_write_u32(vs, 1); /* Reject auth */
+    if (vs->minor >= 8) {
+        static const char err[] = "Authentication failed";
+        vnc_write_u32(vs, sizeof(err));
+        vnc_write(vs, err, sizeof(err));
+    }
+    vnc_flush(vs);
+    vnc_client_error(vs);
+    return 0;
 }
 
 void start_auth_vnc(VncState *vs)
@@ -2517,7 +2521,7 @@ void vnc_display_close(DisplayState *ds)
 #endif
 }
 
-int vnc_display_password(DisplayState *ds, const char *password)
+int vnc_display_password(DisplayState *ds, const char *password, int lifetime)
 {
     VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
 
@@ -2535,6 +2539,11 @@ int vnc_display_password(DisplayState *ds, const char *password)
         if (vs->auth == VNC_AUTH_NONE) {
             vs->auth = VNC_AUTH_VNC;
         }
+        if (lifetime) {
+            vs->expires = time(NULL) + lifetime;
+        } else {
+            vs->expires = 0;
+        }
     } else {
         vs->auth = VNC_AUTH_NONE;
     }
diff --git a/vnc.h b/vnc.h
index 5b8bd5c..36e6bfc 100644
--- a/vnc.h
+++ b/vnc.h
@@ -104,6 +104,7 @@ struct VncDisplay
 
     char *display;
     char *password;
+    time_t expires;
     int auth;
 #ifdef CONFIG_VNC_TLS
     int subauth; /* Used by VeNCrypt */
-- 
1.6.3.rc4.29.g8146

