Store VNC auth scheme per-client as well as per-server

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

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
Daniel P. Berrange 2011-06-23 13:31:41 +01:00 committed by Anthony Liguori
parent e69ae5c49a
commit 7e7e2ebc94
4 changed files with 41 additions and 26 deletions

View file

@ -538,8 +538,8 @@ void start_auth_sasl(VncState *vs)
#ifdef CONFIG_VNC_TLS #ifdef CONFIG_VNC_TLS
/* Inform SASL that we've got an external SSF layer from TLS/x509 */ /* Inform SASL that we've got an external SSF layer from TLS/x509 */
if (vs->vd->auth == VNC_AUTH_VENCRYPT && if (vs->auth == VNC_AUTH_VENCRYPT &&
vs->vd->subauth == VNC_AUTH_VENCRYPT_X509SASL) { vs->subauth == VNC_AUTH_VENCRYPT_X509SASL) {
gnutls_cipher_algorithm_t cipher; gnutls_cipher_algorithm_t cipher;
sasl_ssf_t ssf; sasl_ssf_t ssf;
@ -570,8 +570,8 @@ void start_auth_sasl(VncState *vs)
#ifdef CONFIG_VNC_TLS #ifdef CONFIG_VNC_TLS
/* Disable SSF, if using TLS+x509+SASL only. TLS without x509 /* Disable SSF, if using TLS+x509+SASL only. TLS without x509
is not sufficiently strong */ is not sufficiently strong */
|| (vs->vd->auth == VNC_AUTH_VENCRYPT && || (vs->auth == VNC_AUTH_VENCRYPT &&
vs->vd->subauth == VNC_AUTH_VENCRYPT_X509SASL) vs->subauth == VNC_AUTH_VENCRYPT_X509SASL)
#endif /* CONFIG_VNC_TLS */ #endif /* CONFIG_VNC_TLS */
) { ) {
/* If we've got TLS or UNIX domain sock, we don't care about SSF */ /* If we've got TLS or UNIX domain sock, we don't care about SSF */

View file

@ -29,7 +29,7 @@
static void start_auth_vencrypt_subauth(VncState *vs) static void start_auth_vencrypt_subauth(VncState *vs)
{ {
switch (vs->vd->subauth) { switch (vs->subauth) {
case VNC_AUTH_VENCRYPT_TLSNONE: case VNC_AUTH_VENCRYPT_TLSNONE:
case VNC_AUTH_VENCRYPT_X509NONE: case VNC_AUTH_VENCRYPT_X509NONE:
VNC_DEBUG("Accept TLS auth none\n"); VNC_DEBUG("Accept TLS auth none\n");
@ -51,7 +51,7 @@ static void start_auth_vencrypt_subauth(VncState *vs)
#endif /* CONFIG_VNC_SASL */ #endif /* CONFIG_VNC_SASL */
default: /* Should not be possible, but just in case */ 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); vnc_write_u8(vs, 1);
if (vs->minor >= 8) { if (vs->minor >= 8) {
static const char err[] = "Unsupported authentication type"; static const char err[] = "Unsupported authentication type";
@ -110,17 +110,17 @@ static void vnc_tls_handshake_io(void *opaque) {
#define NEED_X509_AUTH(vs) \ #define NEED_X509_AUTH(vs) \
((vs)->vd->subauth == VNC_AUTH_VENCRYPT_X509NONE || \ ((vs)->subauth == VNC_AUTH_VENCRYPT_X509NONE || \
(vs)->vd->subauth == VNC_AUTH_VENCRYPT_X509VNC || \ (vs)->subauth == VNC_AUTH_VENCRYPT_X509VNC || \
(vs)->vd->subauth == VNC_AUTH_VENCRYPT_X509PLAIN || \ (vs)->subauth == VNC_AUTH_VENCRYPT_X509PLAIN || \
(vs)->vd->subauth == VNC_AUTH_VENCRYPT_X509SASL) (vs)->subauth == VNC_AUTH_VENCRYPT_X509SASL)
static int protocol_client_vencrypt_auth(VncState *vs, uint8_t *data, size_t len) static int protocol_client_vencrypt_auth(VncState *vs, uint8_t *data, size_t len)
{ {
int auth = read_u32(data, 0); int auth = read_u32(data, 0);
if (auth != vs->vd->subauth) { if (auth != vs->subauth) {
VNC_DEBUG("Rejecting auth %d\n", auth); VNC_DEBUG("Rejecting auth %d\n", auth);
vnc_write_u8(vs, 0); /* Reject auth */ vnc_write_u8(vs, 0); /* Reject auth */
vnc_flush(vs); 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_flush(vs);
vnc_client_error(vs); vnc_client_error(vs);
} else { } 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, 0); /* Accept version */
vnc_write_u8(vs, 1); /* Number of sub-auths */ 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_flush(vs);
vnc_read_when(vs, protocol_client_vencrypt_auth, 4); vnc_read_when(vs, protocol_client_vencrypt_auth, 4);
} }

View file

@ -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 /* We only advertise 1 auth scheme at a time, so client
* must pick the one we sent. Verify this */ * 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_DEBUG("Reject auth %d because it didn't match advertized\n", (int)data[0]);
vnc_write_u32(vs, 1); vnc_write_u32(vs, 1);
if (vs->minor >= 8) { 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); vnc_client_error(vs);
} else { /* Accept requested auth */ } else { /* Accept requested auth */
VNC_DEBUG("Client requested auth %d\n", (int)data[0]); VNC_DEBUG("Client requested auth %d\n", (int)data[0]);
switch (vs->vd->auth) { switch (vs->auth) {
case VNC_AUTH_NONE: case VNC_AUTH_NONE:
VNC_DEBUG("Accept auth none\n"); VNC_DEBUG("Accept auth none\n");
if (vs->minor >= 8) { 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 */ #endif /* CONFIG_VNC_SASL */
default: /* Should not be possible, but just in case */ 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); vnc_write_u8(vs, 1);
if (vs->minor >= 8) { if (vs->minor >= 8) {
static const char err[] = "Authentication failed"; 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; vs->minor = 3;
if (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_DEBUG("Tell client auth none\n");
vnc_write_u32(vs, vs->vd->auth); vnc_write_u32(vs, vs->auth);
vnc_flush(vs); vnc_flush(vs);
start_client_init(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_DEBUG("Tell client VNC auth\n");
vnc_write_u32(vs, vs->vd->auth); vnc_write_u32(vs, vs->auth);
vnc_flush(vs); vnc_flush(vs);
start_auth_vnc(vs); start_auth_vnc(vs);
} else { } 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_write_u32(vs, VNC_AUTH_INVALID);
vnc_flush(vs); vnc_flush(vs);
vnc_client_error(vs); vnc_client_error(vs);
} }
} else { } 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, 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_read_when(vs, protocol_client_auth, 1);
vnc_flush(vs); 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)); VncState *vs = qemu_mallocz(sizeof(VncState));
int i; int i;
vs->csock = csock; 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)); vs->lossy_rect = qemu_mallocz(VNC_STAT_ROWS * sizeof (*vs->lossy_rect));
for (i = 0; i < VNC_STAT_ROWS; ++i) { for (i = 0; i < VNC_STAT_ROWS; ++i) {
vs->lossy_rect[i] = qemu_mallocz(VNC_STAT_COLS * sizeof (uint8_t)); 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); int csock = qemu_accept(vs->lsock, (struct sockaddr *)&addr, &addrlen);
if (csock != -1) { 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 { } else {
int csock = vs->lsock; int csock = vs->lsock;
vs->lsock = -1; vs->lsock = -1;
vnc_connect(vs, csock); vnc_connect(vs, csock, 0);
} }
return 0; return 0;

View file

@ -256,8 +256,10 @@ struct VncState
int major; int major;
int minor; int minor;
int auth;
char challenge[VNC_AUTH_CHALLENGE_SIZE]; char challenge[VNC_AUTH_CHALLENGE_SIZE];
#ifdef CONFIG_VNC_TLS #ifdef CONFIG_VNC_TLS
int subauth; /* Used by VeNCrypt */
VncStateTLS tls; VncStateTLS tls;
#endif #endif
#ifdef CONFIG_VNC_SASL #ifdef CONFIG_VNC_SASL