Patchwork [1/3] Store VNC auth scheme per-client as well as per-server

login
register
mail settings
Submitter Daniel P. Berrange
Date June 23, 2011, 12:31 p.m.
Message ID <1308832303-24205-2-git-send-email-berrange@redhat.com>
Download mbox | patch
Permalink /patch/101628/
State New
Headers show

Comments

Daniel P. Berrange - June 23, 2011, 12:31 p.m.
A future patch will introduce a situation where different
clients may have different authentication schemes set.
When a new client arrives, copy the 'auth' and 'subauth'
fields from VncDisplay into the client's VncState, and
use the latter in all authentication functions.

* ui/vnc.h: Add 'auth' and 'subauth' to VncState
* ui/vnc-auth-sasl.c, ui/vnc-auth-vencrypt.c,
  ui/vnc.c: Make auth functions pull auth scheme
  from VncState instead of VncDisplay
---
 ui/vnc-auth-sasl.c     |    8 ++++----
 ui/vnc-auth-vencrypt.c |   18 +++++++++---------
 ui/vnc.c               |   39 ++++++++++++++++++++++++++-------------
 ui/vnc.h               |    2 ++
 4 files changed, 41 insertions(+), 26 deletions(-)
Anthony Liguori - July 23, 2011, 4:53 p.m.
On 06/23/2011 07:31 AM, Daniel P. Berrange wrote:
> A future patch will introduce a situation where different
> clients may have different authentication schemes set.
> When a new client arrives, copy the 'auth' and 'subauth'
> fields from VncDisplay into the client's VncState, and
> use the latter in all authentication functions.
>
> * ui/vnc.h: Add 'auth' and 'subauth' to VncState
> * ui/vnc-auth-sasl.c, ui/vnc-auth-vencrypt.c,
>    ui/vnc.c: Make auth functions pull auth scheme
>    from VncState instead of VncDisplay
> ---
>   ui/vnc-auth-sasl.c     |    8 ++++----
>   ui/vnc-auth-vencrypt.c |   18 +++++++++---------
>   ui/vnc.c               |   39 ++++++++++++++++++++++++++-------------
>   ui/vnc.h               |    2 ++
>   4 files changed, 41 insertions(+), 26 deletions(-)

Applied.  Thanks.

Regards,

Anthony Liguori

>
> diff --git a/ui/vnc-auth-sasl.c b/ui/vnc-auth-sasl.c
> index 17a621a..8aac5ec 100644
> --- a/ui/vnc-auth-sasl.c
> +++ b/ui/vnc-auth-sasl.c
> @@ -538,8 +538,8 @@ void start_auth_sasl(VncState *vs)
>
>   #ifdef CONFIG_VNC_TLS
>       /* Inform SASL that we've got an external SSF layer from TLS/x509 */
> -    if (vs->vd->auth == VNC_AUTH_VENCRYPT&&
> -        vs->vd->subauth == VNC_AUTH_VENCRYPT_X509SASL) {
> +    if (vs->auth == VNC_AUTH_VENCRYPT&&
> +        vs->subauth == VNC_AUTH_VENCRYPT_X509SASL) {
>           gnutls_cipher_algorithm_t cipher;
>           sasl_ssf_t ssf;
>
> @@ -570,8 +570,8 @@ void start_auth_sasl(VncState *vs)
>   #ifdef CONFIG_VNC_TLS
>           /* Disable SSF, if using TLS+x509+SASL only. TLS without x509
>              is not sufficiently strong */
> -        || (vs->vd->auth == VNC_AUTH_VENCRYPT&&
> -            vs->vd->subauth == VNC_AUTH_VENCRYPT_X509SASL)
> +        || (vs->auth == VNC_AUTH_VENCRYPT&&
> +            vs->subauth == VNC_AUTH_VENCRYPT_X509SASL)
>   #endif /* CONFIG_VNC_TLS */
>           ) {
>           /* If we've got TLS or UNIX domain sock, we don't care about SSF */
> diff --git a/ui/vnc-auth-vencrypt.c b/ui/vnc-auth-vencrypt.c
> index 07c1691..674ba97 100644
> --- a/ui/vnc-auth-vencrypt.c
> +++ b/ui/vnc-auth-vencrypt.c
> @@ -29,7 +29,7 @@
>
>   static void start_auth_vencrypt_subauth(VncState *vs)
>   {
> -    switch (vs->vd->subauth) {
> +    switch (vs->subauth) {
>       case VNC_AUTH_VENCRYPT_TLSNONE:
>       case VNC_AUTH_VENCRYPT_X509NONE:
>          VNC_DEBUG("Accept TLS auth none\n");
> @@ -51,7 +51,7 @@ static void start_auth_vencrypt_subauth(VncState *vs)
>   #endif /* CONFIG_VNC_SASL */
>
>       default: /* Should not be possible, but just in case */
> -       VNC_DEBUG("Reject subauth %d server bug\n", vs->vd->auth);
> +       VNC_DEBUG("Reject subauth %d server bug\n", vs->auth);
>          vnc_write_u8(vs, 1);
>          if (vs->minor>= 8) {
>              static const char err[] = "Unsupported authentication type";
> @@ -110,17 +110,17 @@ static void vnc_tls_handshake_io(void *opaque) {
>
>
>   #define NEED_X509_AUTH(vs)                              \
> -    ((vs)->vd->subauth == VNC_AUTH_VENCRYPT_X509NONE ||   \
> -     (vs)->vd->subauth == VNC_AUTH_VENCRYPT_X509VNC ||    \
> -     (vs)->vd->subauth == VNC_AUTH_VENCRYPT_X509PLAIN ||  \
> -     (vs)->vd->subauth == VNC_AUTH_VENCRYPT_X509SASL)
> +    ((vs)->subauth == VNC_AUTH_VENCRYPT_X509NONE ||   \
> +     (vs)->subauth == VNC_AUTH_VENCRYPT_X509VNC ||    \
> +     (vs)->subauth == VNC_AUTH_VENCRYPT_X509PLAIN ||  \
> +     (vs)->subauth == VNC_AUTH_VENCRYPT_X509SASL)
>
>
>   static int protocol_client_vencrypt_auth(VncState *vs, uint8_t *data, size_t len)
>   {
>       int auth = read_u32(data, 0);
>
> -    if (auth != vs->vd->subauth) {
> +    if (auth != vs->subauth) {
>           VNC_DEBUG("Rejecting auth %d\n", auth);
>           vnc_write_u8(vs, 0); /* Reject auth */
>           vnc_flush(vs);
> @@ -153,10 +153,10 @@ static int protocol_client_vencrypt_init(VncState *vs, uint8_t *data, size_t len
>           vnc_flush(vs);
>           vnc_client_error(vs);
>       } else {
> -        VNC_DEBUG("Sending allowed auth %d\n", vs->vd->subauth);
> +        VNC_DEBUG("Sending allowed auth %d\n", vs->subauth);
>           vnc_write_u8(vs, 0); /* Accept version */
>           vnc_write_u8(vs, 1); /* Number of sub-auths */
> -        vnc_write_u32(vs, vs->vd->subauth); /* The supported auth */
> +        vnc_write_u32(vs, vs->subauth); /* The supported auth */
>           vnc_flush(vs);
>           vnc_read_when(vs, protocol_client_vencrypt_auth, 4);
>       }
> diff --git a/ui/vnc.c b/ui/vnc.c
> index 14f2930..39b5b51 100644
> --- a/ui/vnc.c
> +++ b/ui/vnc.c
> @@ -2124,7 +2124,7 @@ static int protocol_client_auth(VncState *vs, uint8_t *data, size_t len)
>   {
>       /* We only advertise 1 auth scheme at a time, so client
>        * must pick the one we sent. Verify this */
> -    if (data[0] != vs->vd->auth) { /* Reject auth */
> +    if (data[0] != vs->auth) { /* Reject auth */
>          VNC_DEBUG("Reject auth %d because it didn't match advertized\n", (int)data[0]);
>          vnc_write_u32(vs, 1);
>          if (vs->minor>= 8) {
> @@ -2135,7 +2135,7 @@ static int protocol_client_auth(VncState *vs, uint8_t *data, size_t len)
>          vnc_client_error(vs);
>       } else { /* Accept requested auth */
>          VNC_DEBUG("Client requested auth %d\n", (int)data[0]);
> -       switch (vs->vd->auth) {
> +       switch (vs->auth) {
>          case VNC_AUTH_NONE:
>              VNC_DEBUG("Accept auth none\n");
>              if (vs->minor>= 8) {
> @@ -2165,7 +2165,7 @@ static int protocol_client_auth(VncState *vs, uint8_t *data, size_t len)
>   #endif /* CONFIG_VNC_SASL */
>
>          default: /* Should not be possible, but just in case */
> -           VNC_DEBUG("Reject auth %d server code bug\n", vs->vd->auth);
> +           VNC_DEBUG("Reject auth %d server code bug\n", vs->auth);
>              vnc_write_u8(vs, 1);
>              if (vs->minor>= 8) {
>                  static const char err[] = "Authentication failed";
> @@ -2210,26 +2210,26 @@ static int protocol_version(VncState *vs, uint8_t *version, size_t len)
>           vs->minor = 3;
>
>       if (vs->minor == 3) {
> -        if (vs->vd->auth == VNC_AUTH_NONE) {
> +        if (vs->auth == VNC_AUTH_NONE) {
>               VNC_DEBUG("Tell client auth none\n");
> -            vnc_write_u32(vs, vs->vd->auth);
> +            vnc_write_u32(vs, vs->auth);
>               vnc_flush(vs);
>               start_client_init(vs);
> -       } else if (vs->vd->auth == VNC_AUTH_VNC) {
> +       } else if (vs->auth == VNC_AUTH_VNC) {
>               VNC_DEBUG("Tell client VNC auth\n");
> -            vnc_write_u32(vs, vs->vd->auth);
> +            vnc_write_u32(vs, vs->auth);
>               vnc_flush(vs);
>               start_auth_vnc(vs);
>          } else {
> -            VNC_DEBUG("Unsupported auth %d for protocol 3.3\n", vs->vd->auth);
> +            VNC_DEBUG("Unsupported auth %d for protocol 3.3\n", vs->auth);
>               vnc_write_u32(vs, VNC_AUTH_INVALID);
>               vnc_flush(vs);
>               vnc_client_error(vs);
>          }
>       } else {
> -        VNC_DEBUG("Telling client we support auth %d\n", vs->vd->auth);
> +        VNC_DEBUG("Telling client we support auth %d\n", vs->auth);
>           vnc_write_u8(vs, 1); /* num auth */
> -        vnc_write_u8(vs, vs->vd->auth);
> +        vnc_write_u8(vs, vs->auth);
>           vnc_read_when(vs, protocol_client_auth, 1);
>           vnc_flush(vs);
>       }
> @@ -2494,12 +2494,25 @@ static void vnc_remove_timer(VncDisplay *vd)
>       }
>   }
>
> -static void vnc_connect(VncDisplay *vd, int csock)
> +static void vnc_connect(VncDisplay *vd, int csock, int skipauth)
>   {
>       VncState *vs = qemu_mallocz(sizeof(VncState));
>       int i;
>
>       vs->csock = csock;
> +
> +    if (skipauth) {
> +	vs->auth = VNC_AUTH_NONE;
> +#ifdef CONFIG_VNC_TLS
> +	vs->subauth = VNC_AUTH_INVALID;
> +#endif
> +    } else {
> +	vs->auth = vd->auth;
> +#ifdef CONFIG_VNC_TLS
> +	vs->subauth = vd->subauth;
> +#endif
> +    }
> +
>       vs->lossy_rect = qemu_mallocz(VNC_STAT_ROWS * sizeof (*vs->lossy_rect));
>       for (i = 0; i<  VNC_STAT_ROWS; ++i) {
>           vs->lossy_rect[i] = qemu_mallocz(VNC_STAT_COLS * sizeof (uint8_t));
> @@ -2557,7 +2570,7 @@ static void vnc_listen_read(void *opaque)
>
>       int csock = qemu_accept(vs->lsock, (struct sockaddr *)&addr,&addrlen);
>       if (csock != -1) {
> -        vnc_connect(vs, csock);
> +        vnc_connect(vs, csock, 0);
>       }
>   }
>
> @@ -2887,7 +2900,7 @@ int vnc_display_open(DisplayState *ds, const char *display)
>           } else {
>               int csock = vs->lsock;
>               vs->lsock = -1;
> -            vnc_connect(vs, csock);
> +            vnc_connect(vs, csock, 0);
>           }
>           return 0;
>
> diff --git a/ui/vnc.h b/ui/vnc.h
> index f10c5dc..66689f1 100644
> --- a/ui/vnc.h
> +++ b/ui/vnc.h
> @@ -256,8 +256,10 @@ struct VncState
>       int major;
>       int minor;
>
> +    int auth;
>       char challenge[VNC_AUTH_CHALLENGE_SIZE];
>   #ifdef CONFIG_VNC_TLS
> +    int subauth; /* Used by VeNCrypt */
>       VncStateTLS tls;
>   #endif
>   #ifdef CONFIG_VNC_SASL

Patch

diff --git a/ui/vnc-auth-sasl.c b/ui/vnc-auth-sasl.c
index 17a621a..8aac5ec 100644
--- a/ui/vnc-auth-sasl.c
+++ b/ui/vnc-auth-sasl.c
@@ -538,8 +538,8 @@  void start_auth_sasl(VncState *vs)
 
 #ifdef CONFIG_VNC_TLS
     /* Inform SASL that we've got an external SSF layer from TLS/x509 */
-    if (vs->vd->auth == VNC_AUTH_VENCRYPT &&
-        vs->vd->subauth == VNC_AUTH_VENCRYPT_X509SASL) {
+    if (vs->auth == VNC_AUTH_VENCRYPT &&
+        vs->subauth == VNC_AUTH_VENCRYPT_X509SASL) {
         gnutls_cipher_algorithm_t cipher;
         sasl_ssf_t ssf;
 
@@ -570,8 +570,8 @@  void start_auth_sasl(VncState *vs)
 #ifdef CONFIG_VNC_TLS
         /* Disable SSF, if using TLS+x509+SASL only. TLS without x509
            is not sufficiently strong */
-        || (vs->vd->auth == VNC_AUTH_VENCRYPT &&
-            vs->vd->subauth == VNC_AUTH_VENCRYPT_X509SASL)
+        || (vs->auth == VNC_AUTH_VENCRYPT &&
+            vs->subauth == VNC_AUTH_VENCRYPT_X509SASL)
 #endif /* CONFIG_VNC_TLS */
         ) {
         /* If we've got TLS or UNIX domain sock, we don't care about SSF */
diff --git a/ui/vnc-auth-vencrypt.c b/ui/vnc-auth-vencrypt.c
index 07c1691..674ba97 100644
--- a/ui/vnc-auth-vencrypt.c
+++ b/ui/vnc-auth-vencrypt.c
@@ -29,7 +29,7 @@ 
 
 static void start_auth_vencrypt_subauth(VncState *vs)
 {
-    switch (vs->vd->subauth) {
+    switch (vs->subauth) {
     case VNC_AUTH_VENCRYPT_TLSNONE:
     case VNC_AUTH_VENCRYPT_X509NONE:
        VNC_DEBUG("Accept TLS auth none\n");
@@ -51,7 +51,7 @@  static void start_auth_vencrypt_subauth(VncState *vs)
 #endif /* CONFIG_VNC_SASL */
 
     default: /* Should not be possible, but just in case */
-       VNC_DEBUG("Reject subauth %d server bug\n", vs->vd->auth);
+       VNC_DEBUG("Reject subauth %d server bug\n", vs->auth);
        vnc_write_u8(vs, 1);
        if (vs->minor >= 8) {
            static const char err[] = "Unsupported authentication type";
@@ -110,17 +110,17 @@  static void vnc_tls_handshake_io(void *opaque) {
 
 
 #define NEED_X509_AUTH(vs)                              \
-    ((vs)->vd->subauth == VNC_AUTH_VENCRYPT_X509NONE ||   \
-     (vs)->vd->subauth == VNC_AUTH_VENCRYPT_X509VNC ||    \
-     (vs)->vd->subauth == VNC_AUTH_VENCRYPT_X509PLAIN ||  \
-     (vs)->vd->subauth == VNC_AUTH_VENCRYPT_X509SASL)
+    ((vs)->subauth == VNC_AUTH_VENCRYPT_X509NONE ||   \
+     (vs)->subauth == VNC_AUTH_VENCRYPT_X509VNC ||    \
+     (vs)->subauth == VNC_AUTH_VENCRYPT_X509PLAIN ||  \
+     (vs)->subauth == VNC_AUTH_VENCRYPT_X509SASL)
 
 
 static int protocol_client_vencrypt_auth(VncState *vs, uint8_t *data, size_t len)
 {
     int auth = read_u32(data, 0);
 
-    if (auth != vs->vd->subauth) {
+    if (auth != vs->subauth) {
         VNC_DEBUG("Rejecting auth %d\n", auth);
         vnc_write_u8(vs, 0); /* Reject auth */
         vnc_flush(vs);
@@ -153,10 +153,10 @@  static int protocol_client_vencrypt_init(VncState *vs, uint8_t *data, size_t len
         vnc_flush(vs);
         vnc_client_error(vs);
     } else {
-        VNC_DEBUG("Sending allowed auth %d\n", vs->vd->subauth);
+        VNC_DEBUG("Sending allowed auth %d\n", vs->subauth);
         vnc_write_u8(vs, 0); /* Accept version */
         vnc_write_u8(vs, 1); /* Number of sub-auths */
-        vnc_write_u32(vs, vs->vd->subauth); /* The supported auth */
+        vnc_write_u32(vs, vs->subauth); /* The supported auth */
         vnc_flush(vs);
         vnc_read_when(vs, protocol_client_vencrypt_auth, 4);
     }
diff --git a/ui/vnc.c b/ui/vnc.c
index 14f2930..39b5b51 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -2124,7 +2124,7 @@  static int protocol_client_auth(VncState *vs, uint8_t *data, size_t len)
 {
     /* We only advertise 1 auth scheme at a time, so client
      * must pick the one we sent. Verify this */
-    if (data[0] != vs->vd->auth) { /* Reject auth */
+    if (data[0] != vs->auth) { /* Reject auth */
        VNC_DEBUG("Reject auth %d because it didn't match advertized\n", (int)data[0]);
        vnc_write_u32(vs, 1);
        if (vs->minor >= 8) {
@@ -2135,7 +2135,7 @@  static int protocol_client_auth(VncState *vs, uint8_t *data, size_t len)
        vnc_client_error(vs);
     } else { /* Accept requested auth */
        VNC_DEBUG("Client requested auth %d\n", (int)data[0]);
-       switch (vs->vd->auth) {
+       switch (vs->auth) {
        case VNC_AUTH_NONE:
            VNC_DEBUG("Accept auth none\n");
            if (vs->minor >= 8) {
@@ -2165,7 +2165,7 @@  static int protocol_client_auth(VncState *vs, uint8_t *data, size_t len)
 #endif /* CONFIG_VNC_SASL */
 
        default: /* Should not be possible, but just in case */
-           VNC_DEBUG("Reject auth %d server code bug\n", vs->vd->auth);
+           VNC_DEBUG("Reject auth %d server code bug\n", vs->auth);
            vnc_write_u8(vs, 1);
            if (vs->minor >= 8) {
                static const char err[] = "Authentication failed";
@@ -2210,26 +2210,26 @@  static int protocol_version(VncState *vs, uint8_t *version, size_t len)
         vs->minor = 3;
 
     if (vs->minor == 3) {
-        if (vs->vd->auth == VNC_AUTH_NONE) {
+        if (vs->auth == VNC_AUTH_NONE) {
             VNC_DEBUG("Tell client auth none\n");
-            vnc_write_u32(vs, vs->vd->auth);
+            vnc_write_u32(vs, vs->auth);
             vnc_flush(vs);
             start_client_init(vs);
-       } else if (vs->vd->auth == VNC_AUTH_VNC) {
+       } else if (vs->auth == VNC_AUTH_VNC) {
             VNC_DEBUG("Tell client VNC auth\n");
-            vnc_write_u32(vs, vs->vd->auth);
+            vnc_write_u32(vs, vs->auth);
             vnc_flush(vs);
             start_auth_vnc(vs);
        } else {
-            VNC_DEBUG("Unsupported auth %d for protocol 3.3\n", vs->vd->auth);
+            VNC_DEBUG("Unsupported auth %d for protocol 3.3\n", vs->auth);
             vnc_write_u32(vs, VNC_AUTH_INVALID);
             vnc_flush(vs);
             vnc_client_error(vs);
        }
     } else {
-        VNC_DEBUG("Telling client we support auth %d\n", vs->vd->auth);
+        VNC_DEBUG("Telling client we support auth %d\n", vs->auth);
         vnc_write_u8(vs, 1); /* num auth */
-        vnc_write_u8(vs, vs->vd->auth);
+        vnc_write_u8(vs, vs->auth);
         vnc_read_when(vs, protocol_client_auth, 1);
         vnc_flush(vs);
     }
@@ -2494,12 +2494,25 @@  static void vnc_remove_timer(VncDisplay *vd)
     }
 }
 
-static void vnc_connect(VncDisplay *vd, int csock)
+static void vnc_connect(VncDisplay *vd, int csock, int skipauth)
 {
     VncState *vs = qemu_mallocz(sizeof(VncState));
     int i;
 
     vs->csock = csock;
+
+    if (skipauth) {
+	vs->auth = VNC_AUTH_NONE;
+#ifdef CONFIG_VNC_TLS
+	vs->subauth = VNC_AUTH_INVALID;
+#endif
+    } else {
+	vs->auth = vd->auth;
+#ifdef CONFIG_VNC_TLS
+	vs->subauth = vd->subauth;
+#endif
+    }
+
     vs->lossy_rect = qemu_mallocz(VNC_STAT_ROWS * sizeof (*vs->lossy_rect));
     for (i = 0; i < VNC_STAT_ROWS; ++i) {
         vs->lossy_rect[i] = qemu_mallocz(VNC_STAT_COLS * sizeof (uint8_t));
@@ -2557,7 +2570,7 @@  static void vnc_listen_read(void *opaque)
 
     int csock = qemu_accept(vs->lsock, (struct sockaddr *)&addr, &addrlen);
     if (csock != -1) {
-        vnc_connect(vs, csock);
+        vnc_connect(vs, csock, 0);
     }
 }
 
@@ -2887,7 +2900,7 @@  int vnc_display_open(DisplayState *ds, const char *display)
         } else {
             int csock = vs->lsock;
             vs->lsock = -1;
-            vnc_connect(vs, csock);
+            vnc_connect(vs, csock, 0);
         }
         return 0;
 
diff --git a/ui/vnc.h b/ui/vnc.h
index f10c5dc..66689f1 100644
--- a/ui/vnc.h
+++ b/ui/vnc.h
@@ -256,8 +256,10 @@  struct VncState
     int major;
     int minor;
 
+    int auth;
     char challenge[VNC_AUTH_CHALLENGE_SIZE];
 #ifdef CONFIG_VNC_TLS
+    int subauth; /* Used by VeNCrypt */
     VncStateTLS tls;
 #endif
 #ifdef CONFIG_VNC_SASL