These changes are the raw update to qemu-2.6.
[kvmfornfv.git] / qemu / ui / vnc-auth-sasl.c
index 62a5fc4..5ae29c1 100644 (file)
@@ -22,6 +22,8 @@
  * THE SOFTWARE.
  */
 
+#include "qemu/osdep.h"
+#include "qapi/error.h"
 #include "vnc.h"
 
 /* Max amount of data we send/recv for SASL steps to prevent DOS */
@@ -62,7 +64,7 @@ long vnc_client_write_sasl(VncState *vs)
                           (const char **)&vs->sasl.encoded,
                           &vs->sasl.encodedLength);
         if (err != SASL_OK)
-            return vnc_client_io_error(vs, -1, EIO);
+            return vnc_client_io_error(vs, -1, NULL);
 
         vs->sasl.encodedOffset = 0;
     }
@@ -86,7 +88,11 @@ long vnc_client_write_sasl(VncState *vs)
      * SASL encoded output
      */
     if (vs->output.offset == 0) {
-        qemu_set_fd_handler(vs->csock, vnc_client_read, NULL, vs);
+        if (vs->ioc_tag) {
+            g_source_remove(vs->ioc_tag);
+        }
+        vs->ioc_tag = qio_channel_add_watch(
+            vs->ioc, G_IO_IN, vnc_client_io, vs, NULL);
     }
 
     return ret;
@@ -110,7 +116,7 @@ long vnc_client_read_sasl(VncState *vs)
                       &decoded, &decodedLen);
 
     if (err != SASL_OK)
-        return vnc_client_io_error(vs, -1, -EIO);
+        return vnc_client_io_error(vs, -1, NULL);
     VNC_DEBUG("Read SASL Encoded %p size %ld Decoded %p size %d\n",
               encoded, ret, decoded, decodedLen);
     buffer_reserve(&vs->input, decodedLen);
@@ -255,17 +261,17 @@ static int protocol_client_auth_sasl_step(VncState *vs, uint8_t *data, size_t le
         vnc_read_when(vs, protocol_client_auth_sasl_step_len, 4);
     } else {
         if (!vnc_auth_sasl_check_ssf(vs)) {
-            VNC_DEBUG("Authentication rejected for weak SSF %d\n", vs->csock);
+            VNC_DEBUG("Authentication rejected for weak SSF %p\n", vs->ioc);
             goto authreject;
         }
 
         /* Check username whitelist ACL */
         if (vnc_auth_sasl_check_access(vs) < 0) {
-            VNC_DEBUG("Authentication rejected for ACL %d\n", vs->csock);
+            VNC_DEBUG("Authentication rejected for ACL %p\n", vs->ioc);
             goto authreject;
         }
 
-        VNC_DEBUG("Authentication successful %d\n", vs->csock);
+        VNC_DEBUG("Authentication successful %p\n", vs->ioc);
         vnc_write_u32(vs, 0); /* Accept auth */
         /*
          * Delay writing in SSF encoded mode until pending output
@@ -383,17 +389,17 @@ static int protocol_client_auth_sasl_start(VncState *vs, uint8_t *data, size_t l
         vnc_read_when(vs, protocol_client_auth_sasl_step_len, 4);
     } else {
         if (!vnc_auth_sasl_check_ssf(vs)) {
-            VNC_DEBUG("Authentication rejected for weak SSF %d\n", vs->csock);
+            VNC_DEBUG("Authentication rejected for weak SSF %p\n", vs->ioc);
             goto authreject;
         }
 
         /* Check username whitelist ACL */
         if (vnc_auth_sasl_check_access(vs) < 0) {
-            VNC_DEBUG("Authentication rejected for ACL %d\n", vs->csock);
+            VNC_DEBUG("Authentication rejected for ACL %p\n", vs->ioc);
             goto authreject;
         }
 
-        VNC_DEBUG("Authentication successful %d\n", vs->csock);
+        VNC_DEBUG("Authentication successful %p\n", vs->ioc);
         vnc_write_u32(vs, 0); /* Accept auth */
         start_client_init(vs);
     }
@@ -487,6 +493,33 @@ static int protocol_client_auth_sasl_mechname_len(VncState *vs, uint8_t *data, s
     return 0;
 }
 
+static char *
+vnc_socket_ip_addr_string(QIOChannelSocket *ioc,
+                          bool local,
+                          Error **errp)
+{
+    SocketAddress *addr;
+    char *ret;
+
+    if (local) {
+        addr = qio_channel_socket_get_local_address(ioc, errp);
+    } else {
+        addr = qio_channel_socket_get_remote_address(ioc, errp);
+    }
+    if (!addr) {
+        return NULL;
+    }
+
+    if (addr->type != SOCKET_ADDRESS_KIND_INET) {
+        error_setg(errp, "Not an inet socket type");
+        return NULL;
+    }
+    ret = g_strdup_printf("%s;%s", addr->u.inet.data->host,
+                          addr->u.inet.data->port);
+    qapi_free_SocketAddress(addr);
+    return ret;
+}
+
 void start_auth_sasl(VncState *vs)
 {
     const char *mechlist = NULL;
@@ -495,13 +528,16 @@ void start_auth_sasl(VncState *vs)
     char *localAddr, *remoteAddr;
     int mechlistlen;
 
-    VNC_DEBUG("Initialize SASL auth %d\n", vs->csock);
+    VNC_DEBUG("Initialize SASL auth %p\n", vs->ioc);
 
     /* Get local & remote client addresses in form  IPADDR;PORT */
-    if (!(localAddr = vnc_socket_local_addr("%s;%s", vs->csock)))
+    localAddr = vnc_socket_ip_addr_string(vs->sioc, true, NULL);
+    if (!localAddr) {
         goto authabort;
+    }
 
-    if (!(remoteAddr = vnc_socket_remote_addr("%s;%s", vs->csock))) {
+    remoteAddr = vnc_socket_ip_addr_string(vs->sioc, false, NULL);
+    if (!remoteAddr) {
         g_free(localAddr);
         goto authabort;
     }
@@ -525,21 +561,24 @@ void start_auth_sasl(VncState *vs)
         goto authabort;
     }
 
-#ifdef CONFIG_VNC_TLS
     /* Inform SASL that we've got an external SSF layer from TLS/x509 */
     if (vs->auth == VNC_AUTH_VENCRYPT &&
         vs->subauth == VNC_AUTH_VENCRYPT_X509SASL) {
-        gnutls_cipher_algorithm_t cipher;
+        Error *local_err = NULL;
+        int keysize;
         sasl_ssf_t ssf;
 
-        cipher = gnutls_cipher_get(vs->tls.session);
-        if (!(ssf = (sasl_ssf_t)gnutls_cipher_get_key_size(cipher))) {
-            VNC_DEBUG("%s", "cannot TLS get cipher size\n");
+        keysize = qcrypto_tls_session_get_key_size(vs->tls,
+                                                   &local_err);
+        if (keysize < 0) {
+            VNC_DEBUG("cannot TLS get cipher size: %s\n",
+                      error_get_pretty(local_err));
+            error_free(local_err);
             sasl_dispose(&vs->sasl.conn);
             vs->sasl.conn = NULL;
             goto authabort;
         }
-        ssf *= 8; /* tls key size is bytes, sasl wants bits */
+        ssf = keysize * CHAR_BIT; /* tls key size is bytes, sasl wants bits */
 
         err = sasl_setprop(vs->sasl.conn, SASL_SSF_EXTERNAL, &ssf);
         if (err != SASL_OK) {
@@ -549,20 +588,19 @@ void start_auth_sasl(VncState *vs)
             vs->sasl.conn = NULL;
             goto authabort;
         }
-    } else
-#endif /* CONFIG_VNC_TLS */
+    } else {
         vs->sasl.wantSSF = 1;
+    }
 
     memset (&secprops, 0, sizeof secprops);
-    /* Inform SASL that we've got an external SSF layer from TLS */
-    if (vs->vd->is_unix
-#ifdef CONFIG_VNC_TLS
-        /* Disable SSF, if using TLS+x509+SASL only. TLS without x509
-           is not sufficiently strong */
-        || (vs->auth == VNC_AUTH_VENCRYPT &&
-            vs->subauth == VNC_AUTH_VENCRYPT_X509SASL)
-#endif /* CONFIG_VNC_TLS */
-        ) {
+    /* Inform SASL that we've got an external SSF layer from TLS.
+     *
+     * Disable SSF, if using TLS+x509+SASL only. TLS without x509
+     * is not sufficiently strong
+     */
+    if (vs->vd->is_unix ||
+        (vs->auth == VNC_AUTH_VENCRYPT &&
+         vs->subauth == VNC_AUTH_VENCRYPT_X509SASL)) {
         /* If we've got TLS or UNIX domain sock, we don't care about SSF */
         secprops.min_ssf = 0;
         secprops.max_ssf = 0;