Beispiel #1
0
    def test_exception_security_handshake_fails(self, mock_auth):
        """Validate behavior if the security handshake fails for any reason."""
        self.proxy._fail = self.manager.proxy._fail

        self._version_handshake()

        self._expect_compute_recv(1, "\x02")
        self._expect_compute_recv(2, "\x01\x02")

        self._expect_tenant_send("\x01\x01")
        self._expect_tenant_recv(1, "\x01")

        self._expect_compute_send("\x01")

        ex = exception.RFBAuthHandshakeFailed(reason="crackers")
        mock_auth.side_effect = ex

        self.expected_manager_calls.extend([
            mock.call.proxy._fail(self.tenant_sock, None,
                                  'Unable to negotiate security with server')
        ])

        self.assertRaises(exception.SecurityProxyNegotiationFailed,
                          self.proxy.connect, self.tenant_sock,
                          self.compute_sock)

        mock_auth.assert_called_once_with(self.compute_sock)
        self._assert_expected_calls()
Beispiel #2
0
 def recv(sock, num):
     b = sock.recv(num)
     if len(b) != num:
         reason = _("Incorrect read from socket, wanted %(wanted)d "
                    "bytes but got %(got)d. Socket returned "
                    "%(result)r") % {'wanted': num, 'got': len(b),
                                     'result': b}
         raise exception.RFBAuthHandshakeFailed(reason=reason)
     return b
Beispiel #3
0
 def recv(num):
     b = compute_sock.recv(num)
     if len(b) != num:
         reason = _("Short read from compute socket, wanted "
                    "%(wanted)d bytes but got %(got)d") % {
                        'wanted': num,
                        'got': len(b)
                    }
         raise exception.RFBAuthHandshakeFailed(reason=reason)
     return b
Beispiel #4
0
    def security_handshake(self, compute_sock):
        def recv(num):
            b = compute_sock.recv(num)
            if len(b) != num:
                reason = _("Short read from compute socket, wanted "
                           "%(wanted)d bytes but got %(got)d") % {
                               'wanted': num,
                               'got': len(b)
                           }
                raise exception.RFBAuthHandshakeFailed(reason=reason)
            return b

        # get the VeNCrypt version from the server
        maj_ver = ord(recv(1))
        min_ver = ord(recv(1))

        LOG.debug("Server sent VeNCrypt version "
                  "%(maj)s.%(min)s", {
                      'maj': maj_ver,
                      'min': min_ver
                  })

        if maj_ver != 0 or min_ver != 2:
            reason = _("Only VeNCrypt version 0.2 is supported by this "
                       "proxy, but the server wanted to use version "
                       "%(maj)s.%(min)s") % {
                           'maj': maj_ver,
                           'min': min_ver
                       }
            raise exception.RFBAuthHandshakeFailed(reason=reason)

        # use version 0.2
        compute_sock.sendall(b"\x00\x02")

        can_use_version = ord(recv(1))

        if can_use_version > 0:
            reason = _("Server could not use VeNCrypt version 0.2")
            raise exception.RFBAuthHandshakeFailed(reason=reason)

        # get the supported sub-auth types
        sub_types_cnt = ord(recv(1))
        sub_types_raw = recv(sub_types_cnt * auth.SUBTYPE_LENGTH)
        sub_types = struct.unpack('!' + str(sub_types_cnt) + 'I',
                                  sub_types_raw)

        LOG.debug("Server supports VeNCrypt sub-types %s", sub_types)

        # We use X509None as we're only seeking to encrypt the channel (ruling
        # out PLAIN) and prevent MITM (ruling out TLS*, which uses trivially
        # MITM'd Anonymous Diffie Hellmann (DH) cyphers)
        if AuthVeNCryptSubtype.X509NONE not in sub_types:
            reason = _("Server does not support the x509None (%s) VeNCrypt"
                       " sub-auth type") % \
                       AuthVeNCryptSubtype.X509NONE
            raise exception.RFBAuthHandshakeFailed(reason=reason)

        LOG.debug("Attempting to use the x509None (%s) auth sub-type",
                  AuthVeNCryptSubtype.X509NONE)

        compute_sock.sendall(struct.pack('!I', AuthVeNCryptSubtype.X509NONE))

        # NB(sross): the spec is missing a U8 here that's used in
        # multiple implementations (e.g. QEMU, GTK-VNC).  1 means
        # acceptance, 0 means failure (unlike the rest of RFB)
        auth_accepted = ord(recv(1))
        if auth_accepted == 0:
            reason = _("Server didn't accept the requested auth sub-type")
            raise exception.RFBAuthHandshakeFailed(reason=reason)

        LOG.debug("Server accepted the requested sub-auth type")

        if (CONF.vnc.vencrypt_client_key and CONF.vnc.vencrypt_client_cert):
            client_key = CONF.vnc.vencrypt_client_key
            client_cert = CONF.vnc.vencrypt_client_cert
        else:
            client_key = None
            client_cert = None

        try:
            wrapped_sock = ssl.wrap_socket(compute_sock,
                                           keyfile=client_key,
                                           certfile=client_cert,
                                           server_side=False,
                                           cert_reqs=ssl.CERT_REQUIRED,
                                           ca_certs=CONF.vnc.vencrypt_ca_certs)

            LOG.info("VeNCrypt security handshake accepted")
            return wrapped_sock

        except ssl.SSLError as e:
            reason = _("Error establishing TLS connection to server: %s") % (
                str(e))
            raise exception.RFBAuthHandshakeFailed(reason=reason)