Fix accumulated nits

Fix nits from the following reviews:

- https://review.openstack.org/#/c/345397/35
- https://review.openstack.org/#/c/345398/36
- https://review.openstack.org/#/c/345399/42

Change-Id: Iafa5b4432a85353a216da4d55e46e1eda30842e3
Blueprint: websocket-proxy-to-host-security
This commit is contained in:
Stephen Finucane
2018-01-16 11:22:39 +00:00
parent 3875eaae73
commit 025d73dbf6
9 changed files with 124 additions and 60 deletions

View File

@@ -40,19 +40,6 @@ class AuthType(enum.IntEnum):
MSLOGON = 0xfffffffa # Used by UltraVNC
class AuthVeNCryptSubtype(enum.IntEnum):
PLAIN = 256
TLSNONE = 257
TLSVNC = 258
TLSPLAIN = 259
X509NONE = 260
X509VNC = 261
X509PLAIN = 262
X509SASL = 263
TLSSASL = 264
@six.add_metaclass(abc.ABCMeta)
class RFBAuthScheme(object):
@@ -74,5 +61,7 @@ class RFBAuthScheme(object):
Should raise exception.RFBAuthHandshakeFailed if
an error occurs
:param compute_sock: socket connected to the compute node instance
"""
pass

View File

@@ -37,6 +37,13 @@ class RFBAuthSchemeList(object):
self.schemes[scheme.security_type()] = scheme
def find_scheme(self, desired_types):
"""Find a suitable authentication scheme to use with compute node.
Identify which of the ``desired_types`` we can accept.
:param desired_types: A list of ints corresponding to the various
authentication types supported.
"""
for security_type in desired_types:
if security_type in self.schemes:
return self.schemes[security_type]

View File

@@ -12,20 +12,39 @@
# License for the specific language governing permissions and limitations
# under the License.
import enum
import ssl
import struct
from oslo_config import cfg
from oslo_log import log as logging
import six
from nova.console.rfb import auth
from nova import exception
from nova.i18n import _, _LI
from nova.i18n import _
LOG = logging.getLogger(__name__)
CONF = cfg.CONF
class AuthVeNCryptSubtype(enum.IntEnum):
"""Possible VeNCrypt subtypes.
From https://github.com/rfbproto/rfbproto/blob/master/rfbproto.rst
"""
PLAIN = 256
TLSNONE = 257
TLSVNC = 258
TLSPLAIN = 259
X509NONE = 260
X509VNC = 261
X509PLAIN = 262
X509SASL = 263
TLSSASL = 264
class RFBAuthSchemeVeNCrypt(auth.RFBAuthScheme):
"""A security proxy helper which uses VeNCrypt.
@@ -81,17 +100,20 @@ class RFBAuthSchemeVeNCrypt(auth.RFBAuthScheme):
LOG.debug("Server supports VeNCrypt sub-types %s", sub_types)
if auth.AuthVeNCryptSubtype.X509NONE not in 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") % \
auth.AuthVeNCryptSubtype.X509NONE
AuthVeNCryptSubtype.X509NONE
raise exception.RFBAuthHandshakeFailed(reason=reason)
LOG.debug("Attempting to use the x509None (%s) auth sub-type",
auth.AuthVeNCryptSubtype.X509NONE)
AuthVeNCryptSubtype.X509NONE)
compute_sock.sendall(struct.pack(
'!I', auth.AuthVeNCryptSubtype.X509NONE))
'!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
@@ -120,9 +142,10 @@ class RFBAuthSchemeVeNCrypt(auth.RFBAuthScheme):
cert_reqs=ssl.CERT_REQUIRED,
ca_certs=CONF.vnc.vencrypt_ca_certs)
LOG.info(_LI("VeNCrypt security handshake accepted"))
LOG.info("VeNCrypt security handshake accepted")
return wrapped_sock
except ssl.SSLError as e:
reason = _("Error establishing TLS connection to server: %s") % e
reason = _("Error establishing TLS connection to server: %s") % (
six.text_type(e))
raise exception.RFBAuthHandshakeFailed(reason=reason)

View File

@@ -23,7 +23,7 @@ from nova.console.rfb import auth
from nova.console.rfb import auths
from nova.console.securityproxy import base
from nova import exception
from nova.i18n import _, _LI
from nova.i18n import _
LOG = logging.getLogger(__name__)
@@ -46,6 +46,10 @@ class RFBSecurityProxy(base.SecurityProxy):
See the general RFB specification at:
https://tools.ietf.org/html/rfc6143
See an updated, maintained RDB specification at:
https://github.com/rfbproto/rfbproto/blob/master/rfbproto.rst
"""
def __init__(self):
@@ -67,7 +71,13 @@ class RFBSecurityProxy(base.SecurityProxy):
# by sending the "Invalid" security type
compute_sock.sendall(auth.AUTH_STATUS_FAIL)
def _parse_version(self, version_str):
@staticmethod
def _parse_version(version_str):
r"""Convert a version string to a float.
>>> RFBSecurityProxy._parse_version('RFB 003.008\n')
0.2
"""
maj_str = version_str[4:7]
min_str = version_str[8:11]
@@ -119,6 +129,7 @@ class RFBSecurityProxy(base.SecurityProxy):
permitted_auth_types_cnt = six.byte2int(recv(compute_sock, 1))
if permitted_auth_types_cnt == 0:
# Decode the reason why the request failed
reason_len_raw = recv(compute_sock, 4)
reason_len = struct.unpack('!I', reason_len_raw)[0]
reason = recv(compute_sock, reason_len)
@@ -148,9 +159,8 @@ class RFBSecurityProxy(base.SecurityProxy):
_("Only the security type None (%d) is supported") %
auth.AuthType.NONE)
reason = _("Client requested a security type other than "
" None (%(none_code)d): "
"%(auth_type)s") % {
reason = _("Client requested a security type other than None "
"(%(none_code)d): %(auth_type)s") % {
'auth_type': client_auth,
'none_code': auth.AuthType.NONE}
raise exception.SecurityProxyNegotiationFailed(reason=reason)
@@ -179,10 +189,10 @@ class RFBSecurityProxy(base.SecurityProxy):
_("Unable to negotiate security with server"))
LOG.debug("Auth failed %s", six.text_type(e))
raise exception.SecurityProxyNegotiationFailed(
reason="Auth handshake failed")
reason=_("Auth handshake failed"))
LOG.info(_LI("Finished security handshake, resuming normal proxy "
"mode using secured socket"))
LOG.info("Finished security handshake, resuming normal proxy "
"mode using secured socket")
# we can just proxy the security result -- if the server security
# negotiation fails, we want the client to think it has failed