Converted tab indents to spaces.

This commit is contained in:
Joe Testa 2020-06-12 21:01:10 -04:00
parent 246a41d46f
commit 22ac41bfb8
16 changed files with 4836 additions and 4915 deletions

File diff suppressed because it is too large Load Diff

View File

@ -8,149 +8,149 @@ import pytest
if sys.version_info[0] == 2:
import StringIO # pylint: disable=import-error
StringIO = StringIO.StringIO
import StringIO # pylint: disable=import-error
StringIO = StringIO.StringIO
else:
StringIO = io.StringIO
StringIO = io.StringIO
@pytest.fixture(scope='module')
def ssh_audit():
__rdir = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..')
sys.path.append(os.path.abspath(__rdir))
return __import__('ssh-audit')
__rdir = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..')
sys.path.append(os.path.abspath(__rdir))
return __import__('ssh-audit')
# pylint: disable=attribute-defined-outside-init
class _OutputSpy(list):
def begin(self):
self.__out = StringIO()
self.__old_stdout = sys.stdout
sys.stdout = self.__out
def begin(self):
self.__out = StringIO()
self.__old_stdout = sys.stdout
sys.stdout = self.__out
def flush(self):
lines = self.__out.getvalue().splitlines()
sys.stdout = self.__old_stdout
self.__out = None
return lines
def flush(self):
lines = self.__out.getvalue().splitlines()
sys.stdout = self.__old_stdout
self.__out = None
return lines
@pytest.fixture(scope='module')
def output_spy():
return _OutputSpy()
return _OutputSpy()
class _VirtualGlobalSocket(object):
def __init__(self, vsocket):
self.vsocket = vsocket
self.addrinfodata = {}
def __init__(self, vsocket):
self.vsocket = vsocket
self.addrinfodata = {}
# pylint: disable=unused-argument
def create_connection(self, address, timeout=0, source_address=None):
# pylint: disable=protected-access
return self.vsocket._connect(address, True)
# pylint: disable=unused-argument
def create_connection(self, address, timeout=0, source_address=None):
# pylint: disable=protected-access
return self.vsocket._connect(address, True)
# pylint: disable=unused-argument
def socket(self,
family=socket.AF_INET,
socktype=socket.SOCK_STREAM,
proto=0,
fileno=None):
return self.vsocket
# pylint: disable=unused-argument
def socket(self,
family=socket.AF_INET,
socktype=socket.SOCK_STREAM,
proto=0,
fileno=None):
return self.vsocket
def getaddrinfo(self, host, port, family=0, socktype=0, proto=0, flags=0):
key = '{0}#{1}'.format(host, port)
if key in self.addrinfodata:
data = self.addrinfodata[key]
if isinstance(data, Exception):
raise data
return data
if host == 'localhost':
r = []
if family in (0, socket.AF_INET):
r.append((socket.AF_INET, 1, 6, '', ('127.0.0.1', port)))
if family in (0, socket.AF_INET6):
r.append((socket.AF_INET6, 1, 6, '', ('::1', port)))
return r
return []
def getaddrinfo(self, host, port, family=0, socktype=0, proto=0, flags=0):
key = '{0}#{1}'.format(host, port)
if key in self.addrinfodata:
data = self.addrinfodata[key]
if isinstance(data, Exception):
raise data
return data
if host == 'localhost':
r = []
if family in (0, socket.AF_INET):
r.append((socket.AF_INET, 1, 6, '', ('127.0.0.1', port)))
if family in (0, socket.AF_INET6):
r.append((socket.AF_INET6, 1, 6, '', ('::1', port)))
return r
return []
class _VirtualSocket(object):
def __init__(self):
self.sock_address = ('127.0.0.1', 0)
self.peer_address = None
self._connected = False
self.timeout = -1.0
self.rdata = []
self.sdata = []
self.errors = {}
self.gsock = _VirtualGlobalSocket(self)
def __init__(self):
self.sock_address = ('127.0.0.1', 0)
self.peer_address = None
self._connected = False
self.timeout = -1.0
self.rdata = []
self.sdata = []
self.errors = {}
self.gsock = _VirtualGlobalSocket(self)
def _check_err(self, method):
method_error = self.errors.get(method)
if method_error:
raise method_error
def _check_err(self, method):
method_error = self.errors.get(method)
if method_error:
raise method_error
def connect(self, address):
return self._connect(address, False)
def connect(self, address):
return self._connect(address, False)
def _connect(self, address, ret=True):
self.peer_address = address
self._connected = True
self._check_err('connect')
return self if ret else None
def _connect(self, address, ret=True):
self.peer_address = address
self._connected = True
self._check_err('connect')
return self if ret else None
def settimeout(self, timeout):
self.timeout = timeout
def settimeout(self, timeout):
self.timeout = timeout
def gettimeout(self):
return self.timeout
def gettimeout(self):
return self.timeout
def getpeername(self):
if self.peer_address is None or not self._connected:
raise socket.error(57, 'Socket is not connected')
return self.peer_address
def getpeername(self):
if self.peer_address is None or not self._connected:
raise socket.error(57, 'Socket is not connected')
return self.peer_address
def getsockname(self):
return self.sock_address
def getsockname(self):
return self.sock_address
def bind(self, address):
self.sock_address = address
def bind(self, address):
self.sock_address = address
def listen(self, backlog):
pass
def listen(self, backlog):
pass
def accept(self):
# pylint: disable=protected-access
conn = _VirtualSocket()
conn.sock_address = self.sock_address
conn.peer_address = ('127.0.0.1', 0)
conn._connected = True
return conn, conn.peer_address
def accept(self):
# pylint: disable=protected-access
conn = _VirtualSocket()
conn.sock_address = self.sock_address
conn.peer_address = ('127.0.0.1', 0)
conn._connected = True
return conn, conn.peer_address
def recv(self, bufsize, flags=0):
# pylint: disable=unused-argument
if not self._connected:
raise socket.error(54, 'Connection reset by peer')
if not len(self.rdata) > 0:
return b''
data = self.rdata.pop(0)
if isinstance(data, Exception):
raise data
return data
def recv(self, bufsize, flags=0):
# pylint: disable=unused-argument
if not self._connected:
raise socket.error(54, 'Connection reset by peer')
if not len(self.rdata) > 0:
return b''
data = self.rdata.pop(0)
if isinstance(data, Exception):
raise data
return data
def send(self, data):
if self.peer_address is None or not self._connected:
raise socket.error(32, 'Broken pipe')
self._check_err('send')
self.sdata.append(data)
def send(self, data):
if self.peer_address is None or not self._connected:
raise socket.error(32, 'Broken pipe')
self._check_err('send')
self.sdata.append(data)
@pytest.fixture()
def virtual_socket(monkeypatch):
vsocket = _VirtualSocket()
gsock = vsocket.gsock
monkeypatch.setattr(socket, 'create_connection', gsock.create_connection)
monkeypatch.setattr(socket, 'socket', gsock.socket)
monkeypatch.setattr(socket, 'getaddrinfo', gsock.getaddrinfo)
return vsocket
vsocket = _VirtualSocket()
gsock = vsocket.gsock
monkeypatch.setattr(socket, 'create_connection', gsock.create_connection)
monkeypatch.setattr(socket, 'socket', gsock.socket)
monkeypatch.setattr(socket, 'getaddrinfo', gsock.getaddrinfo)
return vsocket

View File

@ -5,196 +5,196 @@ import pytest
# pylint: disable=attribute-defined-outside-init
class TestAuditConf(object):
@pytest.fixture(autouse=True)
def init(self, ssh_audit):
self.AuditConf = ssh_audit.AuditConf
self.usage = ssh_audit.usage
@pytest.fixture(autouse=True)
def init(self, ssh_audit):
self.AuditConf = ssh_audit.AuditConf
self.usage = ssh_audit.usage
@staticmethod
def _test_conf(conf, **kwargs):
options = {
'host': None,
'port': 22,
'ssh1': True,
'ssh2': True,
'batch': False,
'colors': True,
'verbose': False,
'level': 'info',
'ipv4': True,
'ipv6': True,
'ipvo': ()
}
for k, v in kwargs.items():
options[k] = v
assert conf.host == options['host']
assert conf.port == options['port']
assert conf.ssh1 is options['ssh1']
assert conf.ssh2 is options['ssh2']
assert conf.batch is options['batch']
assert conf.colors is options['colors']
assert conf.verbose is options['verbose']
assert conf.level == options['level']
assert conf.ipv4 == options['ipv4']
assert conf.ipv6 == options['ipv6']
assert conf.ipvo == options['ipvo']
@staticmethod
def _test_conf(conf, **kwargs):
options = {
'host': None,
'port': 22,
'ssh1': True,
'ssh2': True,
'batch': False,
'colors': True,
'verbose': False,
'level': 'info',
'ipv4': True,
'ipv6': True,
'ipvo': ()
}
for k, v in kwargs.items():
options[k] = v
assert conf.host == options['host']
assert conf.port == options['port']
assert conf.ssh1 is options['ssh1']
assert conf.ssh2 is options['ssh2']
assert conf.batch is options['batch']
assert conf.colors is options['colors']
assert conf.verbose is options['verbose']
assert conf.level == options['level']
assert conf.ipv4 == options['ipv4']
assert conf.ipv6 == options['ipv6']
assert conf.ipvo == options['ipvo']
def test_audit_conf_defaults(self):
conf = self.AuditConf()
self._test_conf(conf)
def test_audit_conf_defaults(self):
conf = self.AuditConf()
self._test_conf(conf)
def test_audit_conf_booleans(self):
conf = self.AuditConf()
for p in ['ssh1', 'ssh2', 'batch', 'colors', 'verbose']:
for v in [True, 1]:
setattr(conf, p, v)
assert getattr(conf, p) is True
for v in [False, 0]:
setattr(conf, p, v)
assert getattr(conf, p) is False
def test_audit_conf_booleans(self):
conf = self.AuditConf()
for p in ['ssh1', 'ssh2', 'batch', 'colors', 'verbose']:
for v in [True, 1]:
setattr(conf, p, v)
assert getattr(conf, p) is True
for v in [False, 0]:
setattr(conf, p, v)
assert getattr(conf, p) is False
def test_audit_conf_port(self):
conf = self.AuditConf()
for port in [22, 2222]:
conf.port = port
assert conf.port == port
for port in [-1, 0, 65536, 99999]:
with pytest.raises(ValueError) as excinfo:
conf.port = port
excinfo.match(r'.*invalid port.*')
def test_audit_conf_port(self):
conf = self.AuditConf()
for port in [22, 2222]:
conf.port = port
assert conf.port == port
for port in [-1, 0, 65536, 99999]:
with pytest.raises(ValueError) as excinfo:
conf.port = port
excinfo.match(r'.*invalid port.*')
def test_audit_conf_ipvo(self):
# ipv4-only
conf = self.AuditConf()
conf.ipv4 = True
assert conf.ipv4 is True
assert conf.ipv6 is False
assert conf.ipvo == (4,)
# ipv6-only
conf = self.AuditConf()
conf.ipv6 = True
assert conf.ipv4 is False
assert conf.ipv6 is True
assert conf.ipvo == (6,)
# ipv4-only (by removing ipv6)
conf = self.AuditConf()
conf.ipv6 = False
assert conf.ipv4 is True
assert conf.ipv6 is False
assert conf.ipvo == (4, )
# ipv6-only (by removing ipv4)
conf = self.AuditConf()
conf.ipv4 = False
assert conf.ipv4 is False
assert conf.ipv6 is True
assert conf.ipvo == (6, )
# ipv4-preferred
conf = self.AuditConf()
conf.ipv4 = True
conf.ipv6 = True
assert conf.ipv4 is True
assert conf.ipv6 is True
assert conf.ipvo == (4, 6)
# ipv6-preferred
conf = self.AuditConf()
conf.ipv6 = True
conf.ipv4 = True
assert conf.ipv4 is True
assert conf.ipv6 is True
assert conf.ipvo == (6, 4)
# ipvo empty
conf = self.AuditConf()
conf.ipvo = ()
assert conf.ipv4 is True
assert conf.ipv6 is True
assert conf.ipvo == ()
# ipvo validation
conf = self.AuditConf()
conf.ipvo = (1, 2, 3, 4, 5, 6)
assert conf.ipvo == (4, 6)
conf.ipvo = (4, 4, 4, 6, 6)
assert conf.ipvo == (4, 6)
def test_audit_conf_ipvo(self):
# ipv4-only
conf = self.AuditConf()
conf.ipv4 = True
assert conf.ipv4 is True
assert conf.ipv6 is False
assert conf.ipvo == (4,)
# ipv6-only
conf = self.AuditConf()
conf.ipv6 = True
assert conf.ipv4 is False
assert conf.ipv6 is True
assert conf.ipvo == (6,)
# ipv4-only (by removing ipv6)
conf = self.AuditConf()
conf.ipv6 = False
assert conf.ipv4 is True
assert conf.ipv6 is False
assert conf.ipvo == (4, )
# ipv6-only (by removing ipv4)
conf = self.AuditConf()
conf.ipv4 = False
assert conf.ipv4 is False
assert conf.ipv6 is True
assert conf.ipvo == (6, )
# ipv4-preferred
conf = self.AuditConf()
conf.ipv4 = True
conf.ipv6 = True
assert conf.ipv4 is True
assert conf.ipv6 is True
assert conf.ipvo == (4, 6)
# ipv6-preferred
conf = self.AuditConf()
conf.ipv6 = True
conf.ipv4 = True
assert conf.ipv4 is True
assert conf.ipv6 is True
assert conf.ipvo == (6, 4)
# ipvo empty
conf = self.AuditConf()
conf.ipvo = ()
assert conf.ipv4 is True
assert conf.ipv6 is True
assert conf.ipvo == ()
# ipvo validation
conf = self.AuditConf()
conf.ipvo = (1, 2, 3, 4, 5, 6)
assert conf.ipvo == (4, 6)
conf.ipvo = (4, 4, 4, 6, 6)
assert conf.ipvo == (4, 6)
def test_audit_conf_level(self):
conf = self.AuditConf()
for level in ['info', 'warn', 'fail']:
conf.level = level
assert conf.level == level
for level in ['head', 'good', 'unknown', None]:
with pytest.raises(ValueError) as excinfo:
conf.level = level
excinfo.match(r'.*invalid level.*')
def test_audit_conf_level(self):
conf = self.AuditConf()
for level in ['info', 'warn', 'fail']:
conf.level = level
assert conf.level == level
for level in ['head', 'good', 'unknown', None]:
with pytest.raises(ValueError) as excinfo:
conf.level = level
excinfo.match(r'.*invalid level.*')
def test_audit_conf_cmdline(self):
# pylint: disable=too-many-statements
c = lambda x: self.AuditConf.from_cmdline(x.split(), self.usage) # noqa
with pytest.raises(SystemExit):
conf = c('')
with pytest.raises(SystemExit):
conf = c('-x')
with pytest.raises(SystemExit):
conf = c('-h')
with pytest.raises(SystemExit):
conf = c('--help')
with pytest.raises(SystemExit):
conf = c(':')
with pytest.raises(SystemExit):
conf = c(':22')
conf = c('localhost')
self._test_conf(conf, host='localhost')
conf = c('github.com')
self._test_conf(conf, host='github.com')
conf = c('localhost:2222')
self._test_conf(conf, host='localhost', port=2222)
conf = c('-p 2222 localhost')
self._test_conf(conf, host='localhost', port=2222)
conf = c('2001:4860:4860::8888')
self._test_conf(conf, host='2001:4860:4860::8888')
conf = c('[2001:4860:4860::8888]:22')
self._test_conf(conf, host='2001:4860:4860::8888')
conf = c('[2001:4860:4860::8888]:2222')
self._test_conf(conf, host='2001:4860:4860::8888', port=2222)
conf = c('-p 2222 2001:4860:4860::8888')
self._test_conf(conf, host='2001:4860:4860::8888', port=2222)
with pytest.raises(SystemExit):
conf = c('localhost:')
with pytest.raises(SystemExit):
conf = c('localhost:abc')
with pytest.raises(SystemExit):
conf = c('-p abc localhost')
with pytest.raises(SystemExit):
conf = c('localhost:-22')
with pytest.raises(SystemExit):
conf = c('-p -22 localhost')
with pytest.raises(SystemExit):
conf = c('localhost:99999')
with pytest.raises(SystemExit):
conf = c('-p 99999 localhost')
conf = c('-1 localhost')
self._test_conf(conf, host='localhost', ssh1=True, ssh2=False)
conf = c('-2 localhost')
self._test_conf(conf, host='localhost', ssh1=False, ssh2=True)
conf = c('-12 localhost')
self._test_conf(conf, host='localhost', ssh1=True, ssh2=True)
conf = c('-4 localhost')
self._test_conf(conf, host='localhost', ipv4=True, ipv6=False, ipvo=(4,))
conf = c('-6 localhost')
self._test_conf(conf, host='localhost', ipv4=False, ipv6=True, ipvo=(6,))
conf = c('-46 localhost')
self._test_conf(conf, host='localhost', ipv4=True, ipv6=True, ipvo=(4, 6))
conf = c('-64 localhost')
self._test_conf(conf, host='localhost', ipv4=True, ipv6=True, ipvo=(6, 4))
conf = c('-b localhost')
self._test_conf(conf, host='localhost', batch=True, verbose=True)
conf = c('-n localhost')
self._test_conf(conf, host='localhost', colors=False)
conf = c('-v localhost')
self._test_conf(conf, host='localhost', verbose=True)
conf = c('-l info localhost')
self._test_conf(conf, host='localhost', level='info')
conf = c('-l warn localhost')
self._test_conf(conf, host='localhost', level='warn')
conf = c('-l fail localhost')
self._test_conf(conf, host='localhost', level='fail')
with pytest.raises(SystemExit):
conf = c('-l something localhost')
def test_audit_conf_cmdline(self):
# pylint: disable=too-many-statements
c = lambda x: self.AuditConf.from_cmdline(x.split(), self.usage) # noqa
with pytest.raises(SystemExit):
conf = c('')
with pytest.raises(SystemExit):
conf = c('-x')
with pytest.raises(SystemExit):
conf = c('-h')
with pytest.raises(SystemExit):
conf = c('--help')
with pytest.raises(SystemExit):
conf = c(':')
with pytest.raises(SystemExit):
conf = c(':22')
conf = c('localhost')
self._test_conf(conf, host='localhost')
conf = c('github.com')
self._test_conf(conf, host='github.com')
conf = c('localhost:2222')
self._test_conf(conf, host='localhost', port=2222)
conf = c('-p 2222 localhost')
self._test_conf(conf, host='localhost', port=2222)
conf = c('2001:4860:4860::8888')
self._test_conf(conf, host='2001:4860:4860::8888')
conf = c('[2001:4860:4860::8888]:22')
self._test_conf(conf, host='2001:4860:4860::8888')
conf = c('[2001:4860:4860::8888]:2222')
self._test_conf(conf, host='2001:4860:4860::8888', port=2222)
conf = c('-p 2222 2001:4860:4860::8888')
self._test_conf(conf, host='2001:4860:4860::8888', port=2222)
with pytest.raises(SystemExit):
conf = c('localhost:')
with pytest.raises(SystemExit):
conf = c('localhost:abc')
with pytest.raises(SystemExit):
conf = c('-p abc localhost')
with pytest.raises(SystemExit):
conf = c('localhost:-22')
with pytest.raises(SystemExit):
conf = c('-p -22 localhost')
with pytest.raises(SystemExit):
conf = c('localhost:99999')
with pytest.raises(SystemExit):
conf = c('-p 99999 localhost')
conf = c('-1 localhost')
self._test_conf(conf, host='localhost', ssh1=True, ssh2=False)
conf = c('-2 localhost')
self._test_conf(conf, host='localhost', ssh1=False, ssh2=True)
conf = c('-12 localhost')
self._test_conf(conf, host='localhost', ssh1=True, ssh2=True)
conf = c('-4 localhost')
self._test_conf(conf, host='localhost', ipv4=True, ipv6=False, ipvo=(4,))
conf = c('-6 localhost')
self._test_conf(conf, host='localhost', ipv4=False, ipv6=True, ipvo=(6,))
conf = c('-46 localhost')
self._test_conf(conf, host='localhost', ipv4=True, ipv6=True, ipvo=(4, 6))
conf = c('-64 localhost')
self._test_conf(conf, host='localhost', ipv4=True, ipv6=True, ipvo=(6, 4))
conf = c('-b localhost')
self._test_conf(conf, host='localhost', batch=True, verbose=True)
conf = c('-n localhost')
self._test_conf(conf, host='localhost', colors=False)
conf = c('-v localhost')
self._test_conf(conf, host='localhost', verbose=True)
conf = c('-l info localhost')
self._test_conf(conf, host='localhost', level='info')
conf = c('-l warn localhost')
self._test_conf(conf, host='localhost', level='warn')
conf = c('-l fail localhost')
self._test_conf(conf, host='localhost', level='fail')
with pytest.raises(SystemExit):
conf = c('-l something localhost')

View File

@ -5,65 +5,65 @@ import pytest
# pylint: disable=line-too-long,attribute-defined-outside-init
class TestBanner(object):
@pytest.fixture(autouse=True)
def init(self, ssh_audit):
self.ssh = ssh_audit.SSH
@pytest.fixture(autouse=True)
def init(self, ssh_audit):
self.ssh = ssh_audit.SSH
def test_simple_banners(self):
banner = lambda x: self.ssh.Banner.parse(x) # noqa
b = banner('SSH-2.0-OpenSSH_7.3')
assert b.protocol == (2, 0)
assert b.software == 'OpenSSH_7.3'
assert b.comments is None
assert str(b) == 'SSH-2.0-OpenSSH_7.3'
b = banner('SSH-1.99-Sun_SSH_1.1.3')
assert b.protocol == (1, 99)
assert b.software == 'Sun_SSH_1.1.3'
assert b.comments is None
assert str(b) == 'SSH-1.99-Sun_SSH_1.1.3'
b = banner('SSH-1.5-Cisco-1.25')
assert b.protocol == (1, 5)
assert b.software == 'Cisco-1.25'
assert b.comments is None
assert str(b) == 'SSH-1.5-Cisco-1.25'
def test_simple_banners(self):
banner = lambda x: self.ssh.Banner.parse(x) # noqa
b = banner('SSH-2.0-OpenSSH_7.3')
assert b.protocol == (2, 0)
assert b.software == 'OpenSSH_7.3'
assert b.comments is None
assert str(b) == 'SSH-2.0-OpenSSH_7.3'
b = banner('SSH-1.99-Sun_SSH_1.1.3')
assert b.protocol == (1, 99)
assert b.software == 'Sun_SSH_1.1.3'
assert b.comments is None
assert str(b) == 'SSH-1.99-Sun_SSH_1.1.3'
b = banner('SSH-1.5-Cisco-1.25')
assert b.protocol == (1, 5)
assert b.software == 'Cisco-1.25'
assert b.comments is None
assert str(b) == 'SSH-1.5-Cisco-1.25'
def test_invalid_banners(self):
b = lambda x: self.ssh.Banner.parse(x) # noqa
assert b('Something') is None
assert b('SSH-XXX-OpenSSH_7.3') is None
def test_invalid_banners(self):
b = lambda x: self.ssh.Banner.parse(x) # noqa
assert b('Something') is None
assert b('SSH-XXX-OpenSSH_7.3') is None
def test_banners_with_spaces(self):
b = lambda x: self.ssh.Banner.parse(x) # noqa
s = 'SSH-2.0-OpenSSH_4.3p2'
assert str(b('SSH-2.0-OpenSSH_4.3p2 ')) == s
assert str(b('SSH-2.0- OpenSSH_4.3p2')) == s
assert str(b('SSH-2.0- OpenSSH_4.3p2 ')) == s
s = 'SSH-2.0-OpenSSH_4.3p2 Debian-9etch3 on i686-pc-linux-gnu'
assert str(b('SSH-2.0- OpenSSH_4.3p2 Debian-9etch3 on i686-pc-linux-gnu')) == s
assert str(b('SSH-2.0-OpenSSH_4.3p2 Debian-9etch3 on i686-pc-linux-gnu ')) == s
assert str(b('SSH-2.0- OpenSSH_4.3p2 Debian-9etch3 on i686-pc-linux-gnu ')) == s
def test_banners_with_spaces(self):
b = lambda x: self.ssh.Banner.parse(x) # noqa
s = 'SSH-2.0-OpenSSH_4.3p2'
assert str(b('SSH-2.0-OpenSSH_4.3p2 ')) == s
assert str(b('SSH-2.0- OpenSSH_4.3p2')) == s
assert str(b('SSH-2.0- OpenSSH_4.3p2 ')) == s
s = 'SSH-2.0-OpenSSH_4.3p2 Debian-9etch3 on i686-pc-linux-gnu'
assert str(b('SSH-2.0- OpenSSH_4.3p2 Debian-9etch3 on i686-pc-linux-gnu')) == s
assert str(b('SSH-2.0-OpenSSH_4.3p2 Debian-9etch3 on i686-pc-linux-gnu ')) == s
assert str(b('SSH-2.0- OpenSSH_4.3p2 Debian-9etch3 on i686-pc-linux-gnu ')) == s
def test_banners_without_software(self):
b = lambda x: self.ssh.Banner.parse(x) # noqa
assert b('SSH-2.0').protocol == (2, 0)
assert b('SSH-2.0').software is None
assert b('SSH-2.0').comments is None
assert str(b('SSH-2.0')) == 'SSH-2.0'
assert b('SSH-2.0-').protocol == (2, 0)
assert b('SSH-2.0-').software == ''
assert b('SSH-2.0-').comments is None
assert str(b('SSH-2.0-')) == 'SSH-2.0-'
def test_banners_without_software(self):
b = lambda x: self.ssh.Banner.parse(x) # noqa
assert b('SSH-2.0').protocol == (2, 0)
assert b('SSH-2.0').software is None
assert b('SSH-2.0').comments is None
assert str(b('SSH-2.0')) == 'SSH-2.0'
assert b('SSH-2.0-').protocol == (2, 0)
assert b('SSH-2.0-').software == ''
assert b('SSH-2.0-').comments is None
assert str(b('SSH-2.0-')) == 'SSH-2.0-'
def test_banners_with_comments(self):
b = lambda x: self.ssh.Banner.parse(x) # noqa
assert repr(b('SSH-2.0-OpenSSH_7.2p2 Ubuntu-1')) == '<Banner(protocol=2.0, software=OpenSSH_7.2p2, comments=Ubuntu-1)>'
assert repr(b('SSH-1.99-OpenSSH_3.4p1 Debian 1:3.4p1-1.woody.3')) == '<Banner(protocol=1.99, software=OpenSSH_3.4p1, comments=Debian 1:3.4p1-1.woody.3)>'
assert repr(b('SSH-1.5-1.3.7 F-SECURE SSH')) == '<Banner(protocol=1.5, software=1.3.7, comments=F-SECURE SSH)>'
def test_banners_with_comments(self):
b = lambda x: self.ssh.Banner.parse(x) # noqa
assert repr(b('SSH-2.0-OpenSSH_7.2p2 Ubuntu-1')) == '<Banner(protocol=2.0, software=OpenSSH_7.2p2, comments=Ubuntu-1)>'
assert repr(b('SSH-1.99-OpenSSH_3.4p1 Debian 1:3.4p1-1.woody.3')) == '<Banner(protocol=1.99, software=OpenSSH_3.4p1, comments=Debian 1:3.4p1-1.woody.3)>'
assert repr(b('SSH-1.5-1.3.7 F-SECURE SSH')) == '<Banner(protocol=1.5, software=1.3.7, comments=F-SECURE SSH)>'
def test_banners_with_multiple_protocols(self):
b = lambda x: self.ssh.Banner.parse(x) # noqa
assert str(b('SSH-1.99-SSH-1.99-OpenSSH_3.6.1p2')) == 'SSH-1.99-OpenSSH_3.6.1p2'
assert str(b('SSH-2.0-SSH-2.0-OpenSSH_4.3p2 Debian-9')) == 'SSH-2.0-OpenSSH_4.3p2 Debian-9'
assert str(b('SSH-1.99-SSH-2.0-dropbear_0.5')) == 'SSH-1.99-dropbear_0.5'
assert str(b('SSH-2.0-SSH-1.99-OpenSSH_4.2p1 SSH Secure Shell (non-commercial)')) == 'SSH-1.99-OpenSSH_4.2p1 SSH Secure Shell (non-commercial)'
assert str(b('SSH-1.99-SSH-1.99-SSH-1.99-OpenSSH_3.9p1')) == 'SSH-1.99-OpenSSH_3.9p1'
def test_banners_with_multiple_protocols(self):
b = lambda x: self.ssh.Banner.parse(x) # noqa
assert str(b('SSH-1.99-SSH-1.99-OpenSSH_3.6.1p2')) == 'SSH-1.99-OpenSSH_3.6.1p2'
assert str(b('SSH-2.0-SSH-2.0-OpenSSH_4.3p2 Debian-9')) == 'SSH-2.0-OpenSSH_4.3p2 Debian-9'
assert str(b('SSH-1.99-SSH-2.0-dropbear_0.5')) == 'SSH-1.99-dropbear_0.5'
assert str(b('SSH-2.0-SSH-1.99-OpenSSH_4.2p1 SSH Secure Shell (non-commercial)')) == 'SSH-1.99-OpenSSH_4.2p1 SSH Secure Shell (non-commercial)'
assert str(b('SSH-1.99-SSH-1.99-SSH-1.99-OpenSSH_3.9p1')) == 'SSH-1.99-OpenSSH_3.9p1'

View File

@ -6,128 +6,128 @@ import pytest
# pylint: disable=attribute-defined-outside-init,bad-whitespace
class TestBuffer(object):
@pytest.fixture(autouse=True)
def init(self, ssh_audit):
self.rbuf = ssh_audit.ReadBuf
self.wbuf = ssh_audit.WriteBuf
self.utf8rchar = b'\xef\xbf\xbd'
@pytest.fixture(autouse=True)
def init(self, ssh_audit):
self.rbuf = ssh_audit.ReadBuf
self.wbuf = ssh_audit.WriteBuf
self.utf8rchar = b'\xef\xbf\xbd'
@classmethod
def _b(cls, v):
v = re.sub(r'\s', '', v)
data = [int(v[i * 2:i * 2 + 2], 16) for i in range(len(v) // 2)]
return bytes(bytearray(data))
@classmethod
def _b(cls, v):
v = re.sub(r'\s', '', v)
data = [int(v[i * 2:i * 2 + 2], 16) for i in range(len(v) // 2)]
return bytes(bytearray(data))
def test_unread(self):
w = self.wbuf().write_byte(1).write_int(2).write_flush()
r = self.rbuf(w)
assert r.unread_len == 5
r.read_byte()
assert r.unread_len == 4
r.read_int()
assert r.unread_len == 0
def test_unread(self):
w = self.wbuf().write_byte(1).write_int(2).write_flush()
r = self.rbuf(w)
assert r.unread_len == 5
r.read_byte()
assert r.unread_len == 4
r.read_int()
assert r.unread_len == 0
def test_byte(self):
w = lambda x: self.wbuf().write_byte(x).write_flush() # noqa
r = lambda x: self.rbuf(x).read_byte() # noqa
tc = [(0x00, '00'),
(0x01, '01'),
(0x10, '10'),
(0xff, 'ff')]
for p in tc:
assert w(p[0]) == self._b(p[1])
assert r(self._b(p[1])) == p[0]
def test_byte(self):
w = lambda x: self.wbuf().write_byte(x).write_flush() # noqa
r = lambda x: self.rbuf(x).read_byte() # noqa
tc = [(0x00, '00'),
(0x01, '01'),
(0x10, '10'),
(0xff, 'ff')]
for p in tc:
assert w(p[0]) == self._b(p[1])
assert r(self._b(p[1])) == p[0]
def test_bool(self):
w = lambda x: self.wbuf().write_bool(x).write_flush() # noqa
r = lambda x: self.rbuf(x).read_bool() # noqa
tc = [(True, '01'),
(False, '00')]
for p in tc:
assert w(p[0]) == self._b(p[1])
assert r(self._b(p[1])) == p[0]
def test_bool(self):
w = lambda x: self.wbuf().write_bool(x).write_flush() # noqa
r = lambda x: self.rbuf(x).read_bool() # noqa
tc = [(True, '01'),
(False, '00')]
for p in tc:
assert w(p[0]) == self._b(p[1])
assert r(self._b(p[1])) == p[0]
def test_int(self):
w = lambda x: self.wbuf().write_int(x).write_flush() # noqa
r = lambda x: self.rbuf(x).read_int() # noqa
tc = [(0x00, '00 00 00 00'),
(0x01, '00 00 00 01'),
(0xabcd, '00 00 ab cd'),
(0xffffffff, 'ff ff ff ff')]
for p in tc:
assert w(p[0]) == self._b(p[1])
assert r(self._b(p[1])) == p[0]
def test_int(self):
w = lambda x: self.wbuf().write_int(x).write_flush() # noqa
r = lambda x: self.rbuf(x).read_int() # noqa
tc = [(0x00, '00 00 00 00'),
(0x01, '00 00 00 01'),
(0xabcd, '00 00 ab cd'),
(0xffffffff, 'ff ff ff ff')]
for p in tc:
assert w(p[0]) == self._b(p[1])
assert r(self._b(p[1])) == p[0]
def test_string(self):
w = lambda x: self.wbuf().write_string(x).write_flush() # noqa
r = lambda x: self.rbuf(x).read_string() # noqa
tc = [(u'abc1', '00 00 00 04 61 62 63 31'),
(b'abc2', '00 00 00 04 61 62 63 32')]
for p in tc:
v = p[0]
assert w(v) == self._b(p[1])
if not isinstance(v, bytes):
v = bytes(bytearray(v, 'utf-8'))
assert r(self._b(p[1])) == v
def test_string(self):
w = lambda x: self.wbuf().write_string(x).write_flush() # noqa
r = lambda x: self.rbuf(x).read_string() # noqa
tc = [(u'abc1', '00 00 00 04 61 62 63 31'),
(b'abc2', '00 00 00 04 61 62 63 32')]
for p in tc:
v = p[0]
assert w(v) == self._b(p[1])
if not isinstance(v, bytes):
v = bytes(bytearray(v, 'utf-8'))
assert r(self._b(p[1])) == v
def test_list(self):
w = lambda x: self.wbuf().write_list(x).write_flush() # noqa
r = lambda x: self.rbuf(x).read_list() # noqa
tc = [(['d', 'ef', 'ault'], '00 00 00 09 64 2c 65 66 2c 61 75 6c 74')]
for p in tc:
assert w(p[0]) == self._b(p[1])
assert r(self._b(p[1])) == p[0]
def test_list(self):
w = lambda x: self.wbuf().write_list(x).write_flush() # noqa
r = lambda x: self.rbuf(x).read_list() # noqa
tc = [(['d', 'ef', 'ault'], '00 00 00 09 64 2c 65 66 2c 61 75 6c 74')]
for p in tc:
assert w(p[0]) == self._b(p[1])
assert r(self._b(p[1])) == p[0]
def test_list_nonutf8(self):
r = lambda x: self.rbuf(x).read_list() # noqa
src = self._b('00 00 00 04 de ad be ef')
dst = [(b'\xde\xad' + self.utf8rchar + self.utf8rchar).decode('utf-8')]
assert r(src) == dst
def test_list_nonutf8(self):
r = lambda x: self.rbuf(x).read_list() # noqa
src = self._b('00 00 00 04 de ad be ef')
dst = [(b'\xde\xad' + self.utf8rchar + self.utf8rchar).decode('utf-8')]
assert r(src) == dst
def test_line(self):
w = lambda x: self.wbuf().write_line(x).write_flush() # noqa
r = lambda x: self.rbuf(x).read_line() # noqa
tc = [(u'example line', '65 78 61 6d 70 6c 65 20 6c 69 6e 65 0d 0a')]
for p in tc:
assert w(p[0]) == self._b(p[1])
assert r(self._b(p[1])) == p[0]
def test_line(self):
w = lambda x: self.wbuf().write_line(x).write_flush() # noqa
r = lambda x: self.rbuf(x).read_line() # noqa
tc = [(u'example line', '65 78 61 6d 70 6c 65 20 6c 69 6e 65 0d 0a')]
for p in tc:
assert w(p[0]) == self._b(p[1])
assert r(self._b(p[1])) == p[0]
def test_line_nonutf8(self):
r = lambda x: self.rbuf(x).read_line() # noqa
src = self._b('de ad be af')
dst = (b'\xde\xad' + self.utf8rchar + self.utf8rchar).decode('utf-8')
assert r(src) == dst
def test_line_nonutf8(self):
r = lambda x: self.rbuf(x).read_line() # noqa
src = self._b('de ad be af')
dst = (b'\xde\xad' + self.utf8rchar + self.utf8rchar).decode('utf-8')
assert r(src) == dst
def test_bitlen(self):
# pylint: disable=protected-access
class Py26Int(int):
def bit_length(self):
raise AttributeError
assert self.wbuf._bitlength(42) == 6
assert self.wbuf._bitlength(Py26Int(42)) == 6
def test_bitlen(self):
# pylint: disable=protected-access
class Py26Int(int):
def bit_length(self):
raise AttributeError
assert self.wbuf._bitlength(42) == 6
assert self.wbuf._bitlength(Py26Int(42)) == 6
def test_mpint1(self):
mpint1w = lambda x: self.wbuf().write_mpint1(x).write_flush() # noqa
mpint1r = lambda x: self.rbuf(x).read_mpint1() # noqa
tc = [(0x0, '00 00'),
(0x1234, '00 0d 12 34'),
(0x12345, '00 11 01 23 45'),
(0xdeadbeef, '00 20 de ad be ef')]
for p in tc:
assert mpint1w(p[0]) == self._b(p[1])
assert mpint1r(self._b(p[1])) == p[0]
def test_mpint1(self):
mpint1w = lambda x: self.wbuf().write_mpint1(x).write_flush() # noqa
mpint1r = lambda x: self.rbuf(x).read_mpint1() # noqa
tc = [(0x0, '00 00'),
(0x1234, '00 0d 12 34'),
(0x12345, '00 11 01 23 45'),
(0xdeadbeef, '00 20 de ad be ef')]
for p in tc:
assert mpint1w(p[0]) == self._b(p[1])
assert mpint1r(self._b(p[1])) == p[0]
def test_mpint2(self):
mpint2w = lambda x: self.wbuf().write_mpint2(x).write_flush() # noqa
mpint2r = lambda x: self.rbuf(x).read_mpint2() # noqa
tc = [(0x0, '00 00 00 00'),
(0x80, '00 00 00 02 00 80'),
(0x9a378f9b2e332a7, '00 00 00 08 09 a3 78 f9 b2 e3 32 a7'),
(-0x1234, '00 00 00 02 ed cc'),
(-0xdeadbeef, '00 00 00 05 ff 21 52 41 11'),
(-0x8000, '00 00 00 02 80 00'),
(-0x80, '00 00 00 01 80')]
for p in tc:
assert mpint2w(p[0]) == self._b(p[1])
assert mpint2r(self._b(p[1])) == p[0]
assert mpint2r(self._b('00 00 00 02 ff 80')) == -0x80
def test_mpint2(self):
mpint2w = lambda x: self.wbuf().write_mpint2(x).write_flush() # noqa
mpint2r = lambda x: self.rbuf(x).read_mpint2() # noqa
tc = [(0x0, '00 00 00 00'),
(0x80, '00 00 00 02 00 80'),
(0x9a378f9b2e332a7, '00 00 00 08 09 a3 78 f9 b2 e3 32 a7'),
(-0x1234, '00 00 00 02 ed cc'),
(-0xdeadbeef, '00 00 00 05 ff 21 52 41 11'),
(-0x8000, '00 00 00 02 80 00'),
(-0x80, '00 00 00 01 80')]
for p in tc:
assert mpint2w(p[0]) == self._b(p[1])
assert mpint2r(self._b(p[1])) == p[0]
assert mpint2r(self._b('00 00 00 02 ff 80')) == -0x80

View File

@ -7,155 +7,155 @@ import pytest
# pylint: disable=attribute-defined-outside-init
class TestErrors(object):
@pytest.fixture(autouse=True)
def init(self, ssh_audit):
self.AuditConf = ssh_audit.AuditConf
self.audit = ssh_audit.audit
@pytest.fixture(autouse=True)
def init(self, ssh_audit):
self.AuditConf = ssh_audit.AuditConf
self.audit = ssh_audit.audit
def _conf(self):
conf = self.AuditConf('localhost', 22)
conf.colors = False
conf.batch = True
return conf
def _conf(self):
conf = self.AuditConf('localhost', 22)
conf.colors = False
conf.batch = True
return conf
def _audit(self, spy, conf=None, sysexit=True):
if conf is None:
conf = self._conf()
spy.begin()
if sysexit:
with pytest.raises(SystemExit):
self.audit(conf)
else:
self.audit(conf)
lines = spy.flush()
return lines
def _audit(self, spy, conf=None, sysexit=True):
if conf is None:
conf = self._conf()
spy.begin()
if sysexit:
with pytest.raises(SystemExit):
self.audit(conf)
else:
self.audit(conf)
lines = spy.flush()
return lines
def test_connection_unresolved(self, output_spy, virtual_socket):
vsocket = virtual_socket
vsocket.gsock.addrinfodata['localhost#22'] = []
lines = self._audit(output_spy)
assert len(lines) == 1
assert 'has no DNS records' in lines[-1]
def test_connection_unresolved(self, output_spy, virtual_socket):
vsocket = virtual_socket
vsocket.gsock.addrinfodata['localhost#22'] = []
lines = self._audit(output_spy)
assert len(lines) == 1
assert 'has no DNS records' in lines[-1]
def test_connection_refused(self, output_spy, virtual_socket):
vsocket = virtual_socket
vsocket.errors['connect'] = socket.error(errno.ECONNREFUSED, 'Connection refused')
lines = self._audit(output_spy)
assert len(lines) == 1
assert 'Connection refused' in lines[-1]
def test_connection_refused(self, output_spy, virtual_socket):
vsocket = virtual_socket
vsocket.errors['connect'] = socket.error(errno.ECONNREFUSED, 'Connection refused')
lines = self._audit(output_spy)
assert len(lines) == 1
assert 'Connection refused' in lines[-1]
def test_connection_timeout(self, output_spy, virtual_socket):
vsocket = virtual_socket
vsocket.errors['connect'] = socket.timeout('timed out')
lines = self._audit(output_spy)
assert len(lines) == 1
assert 'timed out' in lines[-1]
def test_connection_timeout(self, output_spy, virtual_socket):
vsocket = virtual_socket
vsocket.errors['connect'] = socket.timeout('timed out')
lines = self._audit(output_spy)
assert len(lines) == 1
assert 'timed out' in lines[-1]
def test_recv_empty(self, output_spy, virtual_socket):
lines = self._audit(output_spy)
assert len(lines) == 1
assert 'did not receive banner' in lines[-1]
def test_recv_empty(self, output_spy, virtual_socket):
lines = self._audit(output_spy)
assert len(lines) == 1
assert 'did not receive banner' in lines[-1]
def test_recv_timeout(self, output_spy, virtual_socket):
vsocket = virtual_socket
vsocket.rdata.append(socket.timeout('timed out'))
lines = self._audit(output_spy)
assert len(lines) == 1
assert 'did not receive banner' in lines[-1]
assert 'timed out' in lines[-1]
def test_recv_timeout(self, output_spy, virtual_socket):
vsocket = virtual_socket
vsocket.rdata.append(socket.timeout('timed out'))
lines = self._audit(output_spy)
assert len(lines) == 1
assert 'did not receive banner' in lines[-1]
assert 'timed out' in lines[-1]
def test_recv_retry_till_timeout(self, output_spy, virtual_socket):
vsocket = virtual_socket
vsocket.rdata.append(socket.error(errno.EAGAIN, 'Resource temporarily unavailable'))
vsocket.rdata.append(socket.error(errno.EWOULDBLOCK, 'Resource temporarily unavailable'))
vsocket.rdata.append(socket.error(errno.EAGAIN, 'Resource temporarily unavailable'))
vsocket.rdata.append(socket.timeout('timed out'))
lines = self._audit(output_spy)
assert len(lines) == 1
assert 'did not receive banner' in lines[-1]
assert 'timed out' in lines[-1]
def test_recv_retry_till_timeout(self, output_spy, virtual_socket):
vsocket = virtual_socket
vsocket.rdata.append(socket.error(errno.EAGAIN, 'Resource temporarily unavailable'))
vsocket.rdata.append(socket.error(errno.EWOULDBLOCK, 'Resource temporarily unavailable'))
vsocket.rdata.append(socket.error(errno.EAGAIN, 'Resource temporarily unavailable'))
vsocket.rdata.append(socket.timeout('timed out'))
lines = self._audit(output_spy)
assert len(lines) == 1
assert 'did not receive banner' in lines[-1]
assert 'timed out' in lines[-1]
def test_recv_retry_till_reset(self, output_spy, virtual_socket):
vsocket = virtual_socket
vsocket.rdata.append(socket.error(errno.EAGAIN, 'Resource temporarily unavailable'))
vsocket.rdata.append(socket.error(errno.EWOULDBLOCK, 'Resource temporarily unavailable'))
vsocket.rdata.append(socket.error(errno.EAGAIN, 'Resource temporarily unavailable'))
vsocket.rdata.append(socket.error(errno.ECONNRESET, 'Connection reset by peer'))
lines = self._audit(output_spy)
assert len(lines) == 1
assert 'did not receive banner' in lines[-1]
assert 'reset by peer' in lines[-1]
def test_recv_retry_till_reset(self, output_spy, virtual_socket):
vsocket = virtual_socket
vsocket.rdata.append(socket.error(errno.EAGAIN, 'Resource temporarily unavailable'))
vsocket.rdata.append(socket.error(errno.EWOULDBLOCK, 'Resource temporarily unavailable'))
vsocket.rdata.append(socket.error(errno.EAGAIN, 'Resource temporarily unavailable'))
vsocket.rdata.append(socket.error(errno.ECONNRESET, 'Connection reset by peer'))
lines = self._audit(output_spy)
assert len(lines) == 1
assert 'did not receive banner' in lines[-1]
assert 'reset by peer' in lines[-1]
def test_connection_closed_before_banner(self, output_spy, virtual_socket):
vsocket = virtual_socket
vsocket.rdata.append(socket.error(errno.ECONNRESET, 'Connection reset by peer'))
lines = self._audit(output_spy)
assert len(lines) == 1
assert 'did not receive banner' in lines[-1]
assert 'reset by peer' in lines[-1]
def test_connection_closed_before_banner(self, output_spy, virtual_socket):
vsocket = virtual_socket
vsocket.rdata.append(socket.error(errno.ECONNRESET, 'Connection reset by peer'))
lines = self._audit(output_spy)
assert len(lines) == 1
assert 'did not receive banner' in lines[-1]
assert 'reset by peer' in lines[-1]
def test_connection_closed_after_header(self, output_spy, virtual_socket):
vsocket = virtual_socket
vsocket.rdata.append(b'header line 1\n')
vsocket.rdata.append(b'\n')
vsocket.rdata.append(b'header line 2\n')
vsocket.rdata.append(socket.error(errno.ECONNRESET, 'Connection reset by peer'))
lines = self._audit(output_spy)
assert len(lines) == 3
assert 'did not receive banner' in lines[-1]
assert 'reset by peer' in lines[-1]
def test_connection_closed_after_header(self, output_spy, virtual_socket):
vsocket = virtual_socket
vsocket.rdata.append(b'header line 1\n')
vsocket.rdata.append(b'\n')
vsocket.rdata.append(b'header line 2\n')
vsocket.rdata.append(socket.error(errno.ECONNRESET, 'Connection reset by peer'))
lines = self._audit(output_spy)
assert len(lines) == 3
assert 'did not receive banner' in lines[-1]
assert 'reset by peer' in lines[-1]
def test_connection_closed_after_banner(self, output_spy, virtual_socket):
vsocket = virtual_socket
vsocket.rdata.append(b'SSH-2.0-ssh-audit-test\r\n')
vsocket.rdata.append(socket.error(54, 'Connection reset by peer'))
lines = self._audit(output_spy)
assert len(lines) == 2
assert 'error reading packet' in lines[-1]
assert 'reset by peer' in lines[-1]
def test_connection_closed_after_banner(self, output_spy, virtual_socket):
vsocket = virtual_socket
vsocket.rdata.append(b'SSH-2.0-ssh-audit-test\r\n')
vsocket.rdata.append(socket.error(54, 'Connection reset by peer'))
lines = self._audit(output_spy)
assert len(lines) == 2
assert 'error reading packet' in lines[-1]
assert 'reset by peer' in lines[-1]
def test_empty_data_after_banner(self, output_spy, virtual_socket):
vsocket = virtual_socket
vsocket.rdata.append(b'SSH-2.0-ssh-audit-test\r\n')
lines = self._audit(output_spy)
assert len(lines) == 2
assert 'error reading packet' in lines[-1]
assert 'empty' in lines[-1]
def test_empty_data_after_banner(self, output_spy, virtual_socket):
vsocket = virtual_socket
vsocket.rdata.append(b'SSH-2.0-ssh-audit-test\r\n')
lines = self._audit(output_spy)
assert len(lines) == 2
assert 'error reading packet' in lines[-1]
assert 'empty' in lines[-1]
def test_wrong_data_after_banner(self, output_spy, virtual_socket):
vsocket = virtual_socket
vsocket.rdata.append(b'SSH-2.0-ssh-audit-test\r\n')
vsocket.rdata.append(b'xxx\n')
lines = self._audit(output_spy)
assert len(lines) == 2
assert 'error reading packet' in lines[-1]
assert 'xxx' in lines[-1]
def test_wrong_data_after_banner(self, output_spy, virtual_socket):
vsocket = virtual_socket
vsocket.rdata.append(b'SSH-2.0-ssh-audit-test\r\n')
vsocket.rdata.append(b'xxx\n')
lines = self._audit(output_spy)
assert len(lines) == 2
assert 'error reading packet' in lines[-1]
assert 'xxx' in lines[-1]
def test_non_ascii_banner(self, output_spy, virtual_socket):
vsocket = virtual_socket
vsocket.rdata.append(b'SSH-2.0-ssh-audit-test\xc3\xbc\r\n')
lines = self._audit(output_spy)
assert len(lines) == 3
assert 'error reading packet' in lines[-1]
assert 'ASCII' in lines[-2]
assert lines[-3].endswith('SSH-2.0-ssh-audit-test?')
def test_non_ascii_banner(self, output_spy, virtual_socket):
vsocket = virtual_socket
vsocket.rdata.append(b'SSH-2.0-ssh-audit-test\xc3\xbc\r\n')
lines = self._audit(output_spy)
assert len(lines) == 3
assert 'error reading packet' in lines[-1]
assert 'ASCII' in lines[-2]
assert lines[-3].endswith('SSH-2.0-ssh-audit-test?')
def test_nonutf8_data_after_banner(self, output_spy, virtual_socket):
vsocket = virtual_socket
vsocket.rdata.append(b'SSH-2.0-ssh-audit-test\r\n')
vsocket.rdata.append(b'\x81\xff\n')
lines = self._audit(output_spy)
assert len(lines) == 2
assert 'error reading packet' in lines[-1]
assert '\\x81\\xff' in lines[-1]
def test_nonutf8_data_after_banner(self, output_spy, virtual_socket):
vsocket = virtual_socket
vsocket.rdata.append(b'SSH-2.0-ssh-audit-test\r\n')
vsocket.rdata.append(b'\x81\xff\n')
lines = self._audit(output_spy)
assert len(lines) == 2
assert 'error reading packet' in lines[-1]
assert '\\x81\\xff' in lines[-1]
def test_protocol_mismatch_by_conf(self, output_spy, virtual_socket):
vsocket = virtual_socket
vsocket.rdata.append(b'SSH-1.3-ssh-audit-test\r\n')
vsocket.rdata.append(b'Protocol major versions differ.\n')
conf = self._conf()
conf.ssh1, conf.ssh2 = True, False
lines = self._audit(output_spy, conf)
assert len(lines) == 3
assert 'error reading packet' in lines[-1]
assert 'major versions differ' in lines[-1]
def test_protocol_mismatch_by_conf(self, output_spy, virtual_socket):
vsocket = virtual_socket
vsocket.rdata.append(b'SSH-1.3-ssh-audit-test\r\n')
vsocket.rdata.append(b'Protocol major versions differ.\n')
conf = self._conf()
conf.ssh1, conf.ssh2 = True, False
lines = self._audit(output_spy, conf)
assert len(lines) == 3
assert 'error reading packet' in lines[-1]
assert 'major versions differ' in lines[-1]

View File

@ -6,170 +6,170 @@ import pytest
# pylint: disable=attribute-defined-outside-init
class TestOutput(object):
@pytest.fixture(autouse=True)
def init(self, ssh_audit):
self.Output = ssh_audit.Output
self.OutputBuffer = ssh_audit.OutputBuffer
@pytest.fixture(autouse=True)
def init(self, ssh_audit):
self.Output = ssh_audit.Output
self.OutputBuffer = ssh_audit.OutputBuffer
def test_output_buffer_no_lines(self, output_spy):
output_spy.begin()
with self.OutputBuffer() as obuf:
pass
assert output_spy.flush() == []
output_spy.begin()
with self.OutputBuffer() as obuf:
pass
obuf.flush()
assert output_spy.flush() == []
def test_output_buffer_no_lines(self, output_spy):
output_spy.begin()
with self.OutputBuffer() as obuf:
pass
assert output_spy.flush() == []
output_spy.begin()
with self.OutputBuffer() as obuf:
pass
obuf.flush()
assert output_spy.flush() == []
def test_output_buffer_no_flush(self, output_spy):
output_spy.begin()
with self.OutputBuffer():
print(u'abc')
assert output_spy.flush() == []
def test_output_buffer_no_flush(self, output_spy):
output_spy.begin()
with self.OutputBuffer():
print(u'abc')
assert output_spy.flush() == []
def test_output_buffer_flush(self, output_spy):
output_spy.begin()
with self.OutputBuffer() as obuf:
print(u'abc')
print()
print(u'def')
obuf.flush()
assert output_spy.flush() == [u'abc', u'', u'def']
def test_output_buffer_flush(self, output_spy):
output_spy.begin()
with self.OutputBuffer() as obuf:
print(u'abc')
print()
print(u'def')
obuf.flush()
assert output_spy.flush() == [u'abc', u'', u'def']
def test_output_defaults(self):
out = self.Output()
# default: on
assert out.batch is False
assert out.use_colors is True
assert out.level == 'info'
def test_output_defaults(self):
out = self.Output()
# default: on
assert out.batch is False
assert out.use_colors is True
assert out.level == 'info'
def test_output_colors(self, output_spy):
out = self.Output()
# test without colors
out.use_colors = False
output_spy.begin()
out.info('info color')
assert output_spy.flush() == [u'info color']
output_spy.begin()
out.head('head color')
assert output_spy.flush() == [u'head color']
output_spy.begin()
out.good('good color')
assert output_spy.flush() == [u'good color']
output_spy.begin()
out.warn('warn color')
assert output_spy.flush() == [u'warn color']
output_spy.begin()
out.fail('fail color')
assert output_spy.flush() == [u'fail color']
if not out.colors_supported:
return
# test with colors
out.use_colors = True
output_spy.begin()
out.info('info color')
assert output_spy.flush() == [u'info color']
output_spy.begin()
out.head('head color')
assert output_spy.flush() == [u'\x1b[0;36mhead color\x1b[0m']
output_spy.begin()
out.good('good color')
assert output_spy.flush() == [u'\x1b[0;32mgood color\x1b[0m']
output_spy.begin()
out.warn('warn color')
assert output_spy.flush() == [u'\x1b[0;33mwarn color\x1b[0m']
output_spy.begin()
out.fail('fail color')
assert output_spy.flush() == [u'\x1b[0;31mfail color\x1b[0m']
def test_output_colors(self, output_spy):
out = self.Output()
# test without colors
out.use_colors = False
output_spy.begin()
out.info('info color')
assert output_spy.flush() == [u'info color']
output_spy.begin()
out.head('head color')
assert output_spy.flush() == [u'head color']
output_spy.begin()
out.good('good color')
assert output_spy.flush() == [u'good color']
output_spy.begin()
out.warn('warn color')
assert output_spy.flush() == [u'warn color']
output_spy.begin()
out.fail('fail color')
assert output_spy.flush() == [u'fail color']
if not out.colors_supported:
return
# test with colors
out.use_colors = True
output_spy.begin()
out.info('info color')
assert output_spy.flush() == [u'info color']
output_spy.begin()
out.head('head color')
assert output_spy.flush() == [u'\x1b[0;36mhead color\x1b[0m']
output_spy.begin()
out.good('good color')
assert output_spy.flush() == [u'\x1b[0;32mgood color\x1b[0m']
output_spy.begin()
out.warn('warn color')
assert output_spy.flush() == [u'\x1b[0;33mwarn color\x1b[0m']
output_spy.begin()
out.fail('fail color')
assert output_spy.flush() == [u'\x1b[0;31mfail color\x1b[0m']
def test_output_sep(self, output_spy):
out = self.Output()
output_spy.begin()
out.sep()
out.sep()
out.sep()
assert output_spy.flush() == [u'', u'', u'']
def test_output_sep(self, output_spy):
out = self.Output()
output_spy.begin()
out.sep()
out.sep()
out.sep()
assert output_spy.flush() == [u'', u'', u'']
def test_output_levels(self):
out = self.Output()
assert out.get_level('info') == 0
assert out.get_level('good') == 0
assert out.get_level('warn') == 1
assert out.get_level('fail') == 2
assert out.get_level('unknown') > 2
def test_output_levels(self):
out = self.Output()
assert out.get_level('info') == 0
assert out.get_level('good') == 0
assert out.get_level('warn') == 1
assert out.get_level('fail') == 2
assert out.get_level('unknown') > 2
def test_output_level_property(self):
out = self.Output()
out.level = 'info'
assert out.level == 'info'
out.level = 'good'
assert out.level == 'info'
out.level = 'warn'
assert out.level == 'warn'
out.level = 'fail'
assert out.level == 'fail'
out.level = 'invalid level'
assert out.level == 'unknown'
def test_output_level_property(self):
out = self.Output()
out.level = 'info'
assert out.level == 'info'
out.level = 'good'
assert out.level == 'info'
out.level = 'warn'
assert out.level == 'warn'
out.level = 'fail'
assert out.level == 'fail'
out.level = 'invalid level'
assert out.level == 'unknown'
def test_output_level(self, output_spy):
out = self.Output()
# visible: all
out.level = 'info'
output_spy.begin()
out.info('info color')
out.head('head color')
out.good('good color')
out.warn('warn color')
out.fail('fail color')
assert len(output_spy.flush()) == 5
# visible: head, warn, fail
out.level = 'warn'
output_spy.begin()
out.info('info color')
out.head('head color')
out.good('good color')
out.warn('warn color')
out.fail('fail color')
assert len(output_spy.flush()) == 3
# visible: head, fail
out.level = 'fail'
output_spy.begin()
out.info('info color')
out.head('head color')
out.good('good color')
out.warn('warn color')
out.fail('fail color')
assert len(output_spy.flush()) == 2
# visible: head
out.level = 'invalid level'
output_spy.begin()
out.info('info color')
out.head('head color')
out.good('good color')
out.warn('warn color')
out.fail('fail color')
assert len(output_spy.flush()) == 1
def test_output_level(self, output_spy):
out = self.Output()
# visible: all
out.level = 'info'
output_spy.begin()
out.info('info color')
out.head('head color')
out.good('good color')
out.warn('warn color')
out.fail('fail color')
assert len(output_spy.flush()) == 5
# visible: head, warn, fail
out.level = 'warn'
output_spy.begin()
out.info('info color')
out.head('head color')
out.good('good color')
out.warn('warn color')
out.fail('fail color')
assert len(output_spy.flush()) == 3
# visible: head, fail
out.level = 'fail'
output_spy.begin()
out.info('info color')
out.head('head color')
out.good('good color')
out.warn('warn color')
out.fail('fail color')
assert len(output_spy.flush()) == 2
# visible: head
out.level = 'invalid level'
output_spy.begin()
out.info('info color')
out.head('head color')
out.good('good color')
out.warn('warn color')
out.fail('fail color')
assert len(output_spy.flush()) == 1
def test_output_batch(self, output_spy):
out = self.Output()
# visible: all
output_spy.begin()
out.level = 'info'
out.batch = False
out.info('info color')
out.head('head color')
out.good('good color')
out.warn('warn color')
out.fail('fail color')
assert len(output_spy.flush()) == 5
# visible: all except head
output_spy.begin()
out.level = 'info'
out.batch = True
out.info('info color')
out.head('head color')
out.good('good color')
out.warn('warn color')
out.fail('fail color')
assert len(output_spy.flush()) == 4
def test_output_batch(self, output_spy):
out = self.Output()
# visible: all
output_spy.begin()
out.level = 'info'
out.batch = False
out.info('info color')
out.head('head color')
out.good('good color')
out.warn('warn color')
out.fail('fail color')
assert len(output_spy.flush()) == 5
# visible: all except head
output_spy.begin()
out.level = 'info'
out.batch = True
out.info('info color')
out.head('head color')
out.good('good color')
out.warn('warn color')
out.fail('fail color')
assert len(output_spy.flush()) == 4

View File

@ -6,76 +6,76 @@ import pytest
# pylint: disable=attribute-defined-outside-init,protected-access
class TestResolve(object):
@pytest.fixture(autouse=True)
def init(self, ssh_audit):
self.AuditConf = ssh_audit.AuditConf
self.audit = ssh_audit.audit
self.ssh = ssh_audit.SSH
@pytest.fixture(autouse=True)
def init(self, ssh_audit):
self.AuditConf = ssh_audit.AuditConf
self.audit = ssh_audit.audit
self.ssh = ssh_audit.SSH
def _conf(self):
conf = self.AuditConf('localhost', 22)
conf.colors = False
conf.batch = True
return conf
def _conf(self):
conf = self.AuditConf('localhost', 22)
conf.colors = False
conf.batch = True
return conf
def test_resolve_error(self, output_spy, virtual_socket):
vsocket = virtual_socket
vsocket.gsock.addrinfodata['localhost#22'] = socket.gaierror(8, 'hostname nor servname provided, or not known')
s = self.ssh.Socket('localhost', 22)
conf = self._conf()
output_spy.begin()
with pytest.raises(SystemExit):
list(s._resolve(conf.ipvo))
lines = output_spy.flush()
assert len(lines) == 1
assert 'hostname nor servname provided' in lines[-1]
def test_resolve_error(self, output_spy, virtual_socket):
vsocket = virtual_socket
vsocket.gsock.addrinfodata['localhost#22'] = socket.gaierror(8, 'hostname nor servname provided, or not known')
s = self.ssh.Socket('localhost', 22)
conf = self._conf()
output_spy.begin()
with pytest.raises(SystemExit):
list(s._resolve(conf.ipvo))
lines = output_spy.flush()
assert len(lines) == 1
assert 'hostname nor servname provided' in lines[-1]
def test_resolve_hostname_without_records(self, output_spy, virtual_socket):
vsocket = virtual_socket
vsocket.gsock.addrinfodata['localhost#22'] = []
s = self.ssh.Socket('localhost', 22)
conf = self._conf()
output_spy.begin()
r = list(s._resolve(conf.ipvo))
assert len(r) == 0
def test_resolve_hostname_without_records(self, output_spy, virtual_socket):
vsocket = virtual_socket
vsocket.gsock.addrinfodata['localhost#22'] = []
s = self.ssh.Socket('localhost', 22)
conf = self._conf()
output_spy.begin()
r = list(s._resolve(conf.ipvo))
assert len(r) == 0
def test_resolve_ipv4(self, virtual_socket):
conf = self._conf()
conf.ipv4 = True
s = self.ssh.Socket('localhost', 22)
r = list(s._resolve(conf.ipvo))
assert len(r) == 1
assert r[0] == (socket.AF_INET, ('127.0.0.1', 22))
def test_resolve_ipv4(self, virtual_socket):
conf = self._conf()
conf.ipv4 = True
s = self.ssh.Socket('localhost', 22)
r = list(s._resolve(conf.ipvo))
assert len(r) == 1
assert r[0] == (socket.AF_INET, ('127.0.0.1', 22))
def test_resolve_ipv6(self, virtual_socket):
s = self.ssh.Socket('localhost', 22)
conf = self._conf()
conf.ipv6 = True
r = list(s._resolve(conf.ipvo))
assert len(r) == 1
assert r[0] == (socket.AF_INET6, ('::1', 22))
def test_resolve_ipv6(self, virtual_socket):
s = self.ssh.Socket('localhost', 22)
conf = self._conf()
conf.ipv6 = True
r = list(s._resolve(conf.ipvo))
assert len(r) == 1
assert r[0] == (socket.AF_INET6, ('::1', 22))
def test_resolve_ipv46_both(self, virtual_socket):
s = self.ssh.Socket('localhost', 22)
conf = self._conf()
r = list(s._resolve(conf.ipvo))
assert len(r) == 2
assert r[0] == (socket.AF_INET, ('127.0.0.1', 22))
assert r[1] == (socket.AF_INET6, ('::1', 22))
def test_resolve_ipv46_both(self, virtual_socket):
s = self.ssh.Socket('localhost', 22)
conf = self._conf()
r = list(s._resolve(conf.ipvo))
assert len(r) == 2
assert r[0] == (socket.AF_INET, ('127.0.0.1', 22))
assert r[1] == (socket.AF_INET6, ('::1', 22))
def test_resolve_ipv46_order(self, virtual_socket):
s = self.ssh.Socket('localhost', 22)
conf = self._conf()
conf.ipv4 = True
conf.ipv6 = True
r = list(s._resolve(conf.ipvo))
assert len(r) == 2
assert r[0] == (socket.AF_INET, ('127.0.0.1', 22))
assert r[1] == (socket.AF_INET6, ('::1', 22))
conf = self._conf()
conf.ipv6 = True
conf.ipv4 = True
r = list(s._resolve(conf.ipvo))
assert len(r) == 2
assert r[0] == (socket.AF_INET6, ('::1', 22))
assert r[1] == (socket.AF_INET, ('127.0.0.1', 22))
def test_resolve_ipv46_order(self, virtual_socket):
s = self.ssh.Socket('localhost', 22)
conf = self._conf()
conf.ipv4 = True
conf.ipv6 = True
r = list(s._resolve(conf.ipvo))
assert len(r) == 2
assert r[0] == (socket.AF_INET, ('127.0.0.1', 22))
assert r[1] == (socket.AF_INET6, ('::1', 22))
conf = self._conf()
conf.ipv6 = True
conf.ipv4 = True
r = list(s._resolve(conf.ipvo))
assert len(r) == 2
assert r[0] == (socket.AF_INET6, ('::1', 22))
assert r[1] == (socket.AF_INET, ('127.0.0.1', 22))

View File

@ -5,36 +5,36 @@ import pytest
# pylint: disable=attribute-defined-outside-init
class TestSocket(object):
@pytest.fixture(autouse=True)
def init(self, ssh_audit):
self.ssh = ssh_audit.SSH
@pytest.fixture(autouse=True)
def init(self, ssh_audit):
self.ssh = ssh_audit.SSH
def test_invalid_host(self, virtual_socket):
with pytest.raises(ValueError):
self.ssh.Socket(None, 22)
def test_invalid_host(self, virtual_socket):
with pytest.raises(ValueError):
self.ssh.Socket(None, 22)
def test_invalid_port(self, virtual_socket):
with pytest.raises(ValueError):
self.ssh.Socket('localhost', 'abc')
with pytest.raises(ValueError):
self.ssh.Socket('localhost', -1)
with pytest.raises(ValueError):
self.ssh.Socket('localhost', 0)
with pytest.raises(ValueError):
self.ssh.Socket('localhost', 65536)
def test_invalid_port(self, virtual_socket):
with pytest.raises(ValueError):
self.ssh.Socket('localhost', 'abc')
with pytest.raises(ValueError):
self.ssh.Socket('localhost', -1)
with pytest.raises(ValueError):
self.ssh.Socket('localhost', 0)
with pytest.raises(ValueError):
self.ssh.Socket('localhost', 65536)
def test_not_connected_socket(self, virtual_socket):
sock = self.ssh.Socket('localhost', 22)
banner, header, err = sock.get_banner()
assert banner is None
assert len(header) == 0
assert err == 'not connected'
s, e = sock.recv()
assert s == -1
assert e == 'not connected'
s, e = sock.send('nothing')
assert s == -1
assert e == 'not connected'
s, e = sock.send_packet()
assert s == -1
assert e == 'not connected'
def test_not_connected_socket(self, virtual_socket):
sock = self.ssh.Socket('localhost', 22)
banner, header, err = sock.get_banner()
assert banner is None
assert len(header) == 0
assert err == 'not connected'
s, e = sock.recv()
assert s == -1
assert e == 'not connected'
s, e = sock.send('nothing')
assert s == -1
assert e == 'not connected'
s, e = sock.send_packet()
assert s == -1
assert e == 'not connected'

View File

@ -5,283 +5,283 @@ import pytest
# pylint: disable=line-too-long,attribute-defined-outside-init
class TestSoftware(object):
@pytest.fixture(autouse=True)
def init(self, ssh_audit):
self.ssh = ssh_audit.SSH
@pytest.fixture(autouse=True)
def init(self, ssh_audit):
self.ssh = ssh_audit.SSH
def test_unknown_software(self):
ps = lambda x: self.ssh.Software.parse(self.ssh.Banner.parse(x)) # noqa
assert ps('SSH-1.5') is None
assert ps('SSH-1.99-AlfaMegaServer') is None
assert ps('SSH-2.0-BetaMegaServer 0.0.1') is None
def test_unknown_software(self):
ps = lambda x: self.ssh.Software.parse(self.ssh.Banner.parse(x)) # noqa
assert ps('SSH-1.5') is None
assert ps('SSH-1.99-AlfaMegaServer') is None
assert ps('SSH-2.0-BetaMegaServer 0.0.1') is None
def test_openssh_software(self):
# pylint: disable=too-many-statements
ps = lambda x: self.ssh.Software.parse(self.ssh.Banner.parse(x)) # noqa
# common
s = ps('SSH-2.0-OpenSSH_7.3')
assert s.vendor is None
assert s.product == 'OpenSSH'
assert s.version == '7.3'
assert s.patch is None
assert s.os is None
assert str(s) == 'OpenSSH 7.3'
assert str(s) == s.display()
assert s.display(True) == str(s)
assert s.display(False) == str(s)
assert repr(s) == '<Software(product=OpenSSH, version=7.3)>'
# common, portable
s = ps('SSH-2.0-OpenSSH_7.2p1')
assert s.vendor is None
assert s.product == 'OpenSSH'
assert s.version == '7.2'
assert s.patch == 'p1'
assert s.os is None
assert str(s) == 'OpenSSH 7.2p1'
assert str(s) == s.display()
assert s.display(True) == str(s)
assert s.display(False) == 'OpenSSH 7.2'
assert repr(s) == '<Software(product=OpenSSH, version=7.2, patch=p1)>'
# dot instead of underline
s = ps('SSH-2.0-OpenSSH.6.6')
assert s.vendor is None
assert s.product == 'OpenSSH'
assert s.version == '6.6'
assert s.patch is None
assert s.os is None
assert str(s) == 'OpenSSH 6.6'
assert str(s) == s.display()
assert s.display(True) == str(s)
assert s.display(False) == str(s)
assert repr(s) == '<Software(product=OpenSSH, version=6.6)>'
# dash instead of underline
s = ps('SSH-2.0-OpenSSH-3.9p1')
assert s.vendor is None
assert s.product == 'OpenSSH'
assert s.version == '3.9'
assert s.patch == 'p1'
assert s.os is None
assert str(s) == 'OpenSSH 3.9p1'
assert str(s) == s.display()
assert s.display(True) == str(s)
assert s.display(False) == 'OpenSSH 3.9'
assert repr(s) == '<Software(product=OpenSSH, version=3.9, patch=p1)>'
# patch prefix with dash
s = ps('SSH-2.0-OpenSSH_7.2-hpn14v5')
assert s.vendor is None
assert s.product == 'OpenSSH'
assert s.version == '7.2'
assert s.patch == 'hpn14v5'
assert s.os is None
assert str(s) == 'OpenSSH 7.2 (hpn14v5)'
assert str(s) == s.display()
assert s.display(True) == str(s)
assert s.display(False) == 'OpenSSH 7.2'
assert repr(s) == '<Software(product=OpenSSH, version=7.2, patch=hpn14v5)>'
# patch prefix with underline
s = ps('SSH-1.5-OpenSSH_6.6.1_hpn13v11')
assert s.vendor is None
assert s.product == 'OpenSSH'
assert s.version == '6.6.1'
assert s.patch == 'hpn13v11'
assert s.os is None
assert str(s) == 'OpenSSH 6.6.1 (hpn13v11)'
assert str(s) == s.display()
assert s.display(True) == str(s)
assert s.display(False) == 'OpenSSH 6.6.1'
assert repr(s) == '<Software(product=OpenSSH, version=6.6.1, patch=hpn13v11)>'
# patch prefix with dot
s = ps('SSH-2.0-OpenSSH_5.9.CASPUR')
assert s.vendor is None
assert s.product == 'OpenSSH'
assert s.version == '5.9'
assert s.patch == 'CASPUR'
assert s.os is None
assert str(s) == 'OpenSSH 5.9 (CASPUR)'
assert str(s) == s.display()
assert s.display(True) == str(s)
assert s.display(False) == 'OpenSSH 5.9'
assert repr(s) == '<Software(product=OpenSSH, version=5.9, patch=CASPUR)>'
def test_openssh_software(self):
# pylint: disable=too-many-statements
ps = lambda x: self.ssh.Software.parse(self.ssh.Banner.parse(x)) # noqa
# common
s = ps('SSH-2.0-OpenSSH_7.3')
assert s.vendor is None
assert s.product == 'OpenSSH'
assert s.version == '7.3'
assert s.patch is None
assert s.os is None
assert str(s) == 'OpenSSH 7.3'
assert str(s) == s.display()
assert s.display(True) == str(s)
assert s.display(False) == str(s)
assert repr(s) == '<Software(product=OpenSSH, version=7.3)>'
# common, portable
s = ps('SSH-2.0-OpenSSH_7.2p1')
assert s.vendor is None
assert s.product == 'OpenSSH'
assert s.version == '7.2'
assert s.patch == 'p1'
assert s.os is None
assert str(s) == 'OpenSSH 7.2p1'
assert str(s) == s.display()
assert s.display(True) == str(s)
assert s.display(False) == 'OpenSSH 7.2'
assert repr(s) == '<Software(product=OpenSSH, version=7.2, patch=p1)>'
# dot instead of underline
s = ps('SSH-2.0-OpenSSH.6.6')
assert s.vendor is None
assert s.product == 'OpenSSH'
assert s.version == '6.6'
assert s.patch is None
assert s.os is None
assert str(s) == 'OpenSSH 6.6'
assert str(s) == s.display()
assert s.display(True) == str(s)
assert s.display(False) == str(s)
assert repr(s) == '<Software(product=OpenSSH, version=6.6)>'
# dash instead of underline
s = ps('SSH-2.0-OpenSSH-3.9p1')
assert s.vendor is None
assert s.product == 'OpenSSH'
assert s.version == '3.9'
assert s.patch == 'p1'
assert s.os is None
assert str(s) == 'OpenSSH 3.9p1'
assert str(s) == s.display()
assert s.display(True) == str(s)
assert s.display(False) == 'OpenSSH 3.9'
assert repr(s) == '<Software(product=OpenSSH, version=3.9, patch=p1)>'
# patch prefix with dash
s = ps('SSH-2.0-OpenSSH_7.2-hpn14v5')
assert s.vendor is None
assert s.product == 'OpenSSH'
assert s.version == '7.2'
assert s.patch == 'hpn14v5'
assert s.os is None
assert str(s) == 'OpenSSH 7.2 (hpn14v5)'
assert str(s) == s.display()
assert s.display(True) == str(s)
assert s.display(False) == 'OpenSSH 7.2'
assert repr(s) == '<Software(product=OpenSSH, version=7.2, patch=hpn14v5)>'
# patch prefix with underline
s = ps('SSH-1.5-OpenSSH_6.6.1_hpn13v11')
assert s.vendor is None
assert s.product == 'OpenSSH'
assert s.version == '6.6.1'
assert s.patch == 'hpn13v11'
assert s.os is None
assert str(s) == 'OpenSSH 6.6.1 (hpn13v11)'
assert str(s) == s.display()
assert s.display(True) == str(s)
assert s.display(False) == 'OpenSSH 6.6.1'
assert repr(s) == '<Software(product=OpenSSH, version=6.6.1, patch=hpn13v11)>'
# patch prefix with dot
s = ps('SSH-2.0-OpenSSH_5.9.CASPUR')
assert s.vendor is None
assert s.product == 'OpenSSH'
assert s.version == '5.9'
assert s.patch == 'CASPUR'
assert s.os is None
assert str(s) == 'OpenSSH 5.9 (CASPUR)'
assert str(s) == s.display()
assert s.display(True) == str(s)
assert s.display(False) == 'OpenSSH 5.9'
assert repr(s) == '<Software(product=OpenSSH, version=5.9, patch=CASPUR)>'
def test_dropbear_software(self):
ps = lambda x: self.ssh.Software.parse(self.ssh.Banner.parse(x)) # noqa
# common
s = ps('SSH-2.0-dropbear_2016.74')
assert s.vendor is None
assert s.product == 'Dropbear SSH'
assert s.version == '2016.74'
assert s.patch is None
assert s.os is None
assert str(s) == 'Dropbear SSH 2016.74'
assert str(s) == s.display()
assert s.display(True) == str(s)
assert s.display(False) == str(s)
assert repr(s) == '<Software(product=Dropbear SSH, version=2016.74)>'
# common, patch
s = ps('SSH-2.0-dropbear_0.44test4')
assert s.vendor is None
assert s.product == 'Dropbear SSH'
assert s.version == '0.44'
assert s.patch == 'test4'
assert s.os is None
assert str(s) == 'Dropbear SSH 0.44 (test4)'
assert str(s) == s.display()
assert s.display(True) == str(s)
assert s.display(False) == 'Dropbear SSH 0.44'
assert repr(s) == '<Software(product=Dropbear SSH, version=0.44, patch=test4)>'
# patch prefix with dash
s = ps('SSH-2.0-dropbear_0.44-Freesco-p49')
assert s.vendor is None
assert s.product == 'Dropbear SSH'
assert s.version == '0.44'
assert s.patch == 'Freesco-p49'
assert s.os is None
assert str(s) == 'Dropbear SSH 0.44 (Freesco-p49)'
assert str(s) == s.display()
assert s.display(True) == str(s)
assert s.display(False) == 'Dropbear SSH 0.44'
assert repr(s) == '<Software(product=Dropbear SSH, version=0.44, patch=Freesco-p49)>'
# patch prefix with underline
s = ps('SSH-2.0-dropbear_2014.66_agbn_1')
assert s.vendor is None
assert s.product == 'Dropbear SSH'
assert s.version == '2014.66'
assert s.patch == 'agbn_1'
assert s.os is None
assert str(s) == 'Dropbear SSH 2014.66 (agbn_1)'
assert str(s) == s.display()
assert s.display(True) == str(s)
assert s.display(False) == 'Dropbear SSH 2014.66'
assert repr(s) == '<Software(product=Dropbear SSH, version=2014.66, patch=agbn_1)>'
def test_dropbear_software(self):
ps = lambda x: self.ssh.Software.parse(self.ssh.Banner.parse(x)) # noqa
# common
s = ps('SSH-2.0-dropbear_2016.74')
assert s.vendor is None
assert s.product == 'Dropbear SSH'
assert s.version == '2016.74'
assert s.patch is None
assert s.os is None
assert str(s) == 'Dropbear SSH 2016.74'
assert str(s) == s.display()
assert s.display(True) == str(s)
assert s.display(False) == str(s)
assert repr(s) == '<Software(product=Dropbear SSH, version=2016.74)>'
# common, patch
s = ps('SSH-2.0-dropbear_0.44test4')
assert s.vendor is None
assert s.product == 'Dropbear SSH'
assert s.version == '0.44'
assert s.patch == 'test4'
assert s.os is None
assert str(s) == 'Dropbear SSH 0.44 (test4)'
assert str(s) == s.display()
assert s.display(True) == str(s)
assert s.display(False) == 'Dropbear SSH 0.44'
assert repr(s) == '<Software(product=Dropbear SSH, version=0.44, patch=test4)>'
# patch prefix with dash
s = ps('SSH-2.0-dropbear_0.44-Freesco-p49')
assert s.vendor is None
assert s.product == 'Dropbear SSH'
assert s.version == '0.44'
assert s.patch == 'Freesco-p49'
assert s.os is None
assert str(s) == 'Dropbear SSH 0.44 (Freesco-p49)'
assert str(s) == s.display()
assert s.display(True) == str(s)
assert s.display(False) == 'Dropbear SSH 0.44'
assert repr(s) == '<Software(product=Dropbear SSH, version=0.44, patch=Freesco-p49)>'
# patch prefix with underline
s = ps('SSH-2.0-dropbear_2014.66_agbn_1')
assert s.vendor is None
assert s.product == 'Dropbear SSH'
assert s.version == '2014.66'
assert s.patch == 'agbn_1'
assert s.os is None
assert str(s) == 'Dropbear SSH 2014.66 (agbn_1)'
assert str(s) == s.display()
assert s.display(True) == str(s)
assert s.display(False) == 'Dropbear SSH 2014.66'
assert repr(s) == '<Software(product=Dropbear SSH, version=2014.66, patch=agbn_1)>'
def test_libssh_software(self):
ps = lambda x: self.ssh.Software.parse(self.ssh.Banner.parse(x)) # noqa
# common
s = ps('SSH-2.0-libssh-0.2')
assert s.vendor is None
assert s.product == 'libssh'
assert s.version == '0.2'
assert s.patch is None
assert s.os is None
assert str(s) == 'libssh 0.2'
assert str(s) == s.display()
assert s.display(True) == str(s)
assert s.display(False) == str(s)
assert repr(s) == '<Software(product=libssh, version=0.2)>'
s = ps('SSH-2.0-libssh-0.7.4')
assert s.vendor is None
assert s.product == 'libssh'
assert s.version == '0.7.4'
assert s.patch is None
assert s.os is None
assert str(s) == 'libssh 0.7.4'
assert str(s) == s.display()
assert s.display(True) == str(s)
assert s.display(False) == str(s)
assert repr(s) == '<Software(product=libssh, version=0.7.4)>'
def test_libssh_software(self):
ps = lambda x: self.ssh.Software.parse(self.ssh.Banner.parse(x)) # noqa
# common
s = ps('SSH-2.0-libssh-0.2')
assert s.vendor is None
assert s.product == 'libssh'
assert s.version == '0.2'
assert s.patch is None
assert s.os is None
assert str(s) == 'libssh 0.2'
assert str(s) == s.display()
assert s.display(True) == str(s)
assert s.display(False) == str(s)
assert repr(s) == '<Software(product=libssh, version=0.2)>'
s = ps('SSH-2.0-libssh-0.7.4')
assert s.vendor is None
assert s.product == 'libssh'
assert s.version == '0.7.4'
assert s.patch is None
assert s.os is None
assert str(s) == 'libssh 0.7.4'
assert str(s) == s.display()
assert s.display(True) == str(s)
assert s.display(False) == str(s)
assert repr(s) == '<Software(product=libssh, version=0.7.4)>'
def test_romsshell_software(self):
ps = lambda x: self.ssh.Software.parse(self.ssh.Banner.parse(x)) # noqa
# common
s = ps('SSH-2.0-RomSShell_5.40')
assert s.vendor == 'Allegro Software'
assert s.product == 'RomSShell'
assert s.version == '5.40'
assert s.patch is None
assert s.os is None
assert str(s) == 'Allegro Software RomSShell 5.40'
assert str(s) == s.display()
assert s.display(True) == str(s)
assert s.display(False) == str(s)
assert repr(s) == '<Software(vendor=Allegro Software, product=RomSShell, version=5.40)>'
def test_romsshell_software(self):
ps = lambda x: self.ssh.Software.parse(self.ssh.Banner.parse(x)) # noqa
# common
s = ps('SSH-2.0-RomSShell_5.40')
assert s.vendor == 'Allegro Software'
assert s.product == 'RomSShell'
assert s.version == '5.40'
assert s.patch is None
assert s.os is None
assert str(s) == 'Allegro Software RomSShell 5.40'
assert str(s) == s.display()
assert s.display(True) == str(s)
assert s.display(False) == str(s)
assert repr(s) == '<Software(vendor=Allegro Software, product=RomSShell, version=5.40)>'
def test_hp_ilo_software(self):
ps = lambda x: self.ssh.Software.parse(self.ssh.Banner.parse(x)) # noqa
# common
s = ps('SSH-2.0-mpSSH_0.2.1')
assert s.vendor == 'HP'
assert s.product == 'iLO (Integrated Lights-Out) sshd'
assert s.version == '0.2.1'
assert s.patch is None
assert s.os is None
assert str(s) == 'HP iLO (Integrated Lights-Out) sshd 0.2.1'
assert str(s) == s.display()
assert s.display(True) == str(s)
assert s.display(False) == str(s)
assert repr(s) == '<Software(vendor=HP, product=iLO (Integrated Lights-Out) sshd, version=0.2.1)>'
def test_hp_ilo_software(self):
ps = lambda x: self.ssh.Software.parse(self.ssh.Banner.parse(x)) # noqa
# common
s = ps('SSH-2.0-mpSSH_0.2.1')
assert s.vendor == 'HP'
assert s.product == 'iLO (Integrated Lights-Out) sshd'
assert s.version == '0.2.1'
assert s.patch is None
assert s.os is None
assert str(s) == 'HP iLO (Integrated Lights-Out) sshd 0.2.1'
assert str(s) == s.display()
assert s.display(True) == str(s)
assert s.display(False) == str(s)
assert repr(s) == '<Software(vendor=HP, product=iLO (Integrated Lights-Out) sshd, version=0.2.1)>'
def test_cisco_software(self):
ps = lambda x: self.ssh.Software.parse(self.ssh.Banner.parse(x)) # noqa
# common
s = ps('SSH-1.5-Cisco-1.25')
assert s.vendor == 'Cisco'
assert s.product == 'IOS/PIX sshd'
assert s.version == '1.25'
assert s.patch is None
assert s.os is None
assert str(s) == 'Cisco IOS/PIX sshd 1.25'
assert str(s) == s.display()
assert s.display(True) == str(s)
assert s.display(False) == str(s)
assert repr(s) == '<Software(vendor=Cisco, product=IOS/PIX sshd, version=1.25)>'
def test_cisco_software(self):
ps = lambda x: self.ssh.Software.parse(self.ssh.Banner.parse(x)) # noqa
# common
s = ps('SSH-1.5-Cisco-1.25')
assert s.vendor == 'Cisco'
assert s.product == 'IOS/PIX sshd'
assert s.version == '1.25'
assert s.patch is None
assert s.os is None
assert str(s) == 'Cisco IOS/PIX sshd 1.25'
assert str(s) == s.display()
assert s.display(True) == str(s)
assert s.display(False) == str(s)
assert repr(s) == '<Software(vendor=Cisco, product=IOS/PIX sshd, version=1.25)>'
def test_software_os(self):
ps = lambda x: self.ssh.Software.parse(self.ssh.Banner.parse(x)) # noqa
# unknown
s = ps('SSH-2.0-OpenSSH_3.7.1 MegaOperatingSystem 123')
assert s.os is None
# NetBSD
s = ps('SSH-1.99-OpenSSH_2.5.1 NetBSD_Secure_Shell-20010614')
assert s.os == 'NetBSD (2001-06-14)'
assert str(s) == 'OpenSSH 2.5.1 running on NetBSD (2001-06-14)'
assert repr(s) == '<Software(product=OpenSSH, version=2.5.1, os=NetBSD (2001-06-14))>'
s = ps('SSH-1.99-OpenSSH_5.0 NetBSD_Secure_Shell-20080403+-hpn13v1')
assert s.os == 'NetBSD (2008-04-03)'
assert str(s) == 'OpenSSH 5.0 running on NetBSD (2008-04-03)'
assert repr(s) == '<Software(product=OpenSSH, version=5.0, os=NetBSD (2008-04-03))>'
s = ps('SSH-2.0-OpenSSH_6.6.1_hpn13v11 NetBSD-20100308')
assert s.os == 'NetBSD (2010-03-08)'
assert str(s) == 'OpenSSH 6.6.1 (hpn13v11) running on NetBSD (2010-03-08)'
assert repr(s) == '<Software(product=OpenSSH, version=6.6.1, patch=hpn13v11, os=NetBSD (2010-03-08))>'
s = ps('SSH-2.0-OpenSSH_4.4 NetBSD')
assert s.os == 'NetBSD'
assert str(s) == 'OpenSSH 4.4 running on NetBSD'
assert repr(s) == '<Software(product=OpenSSH, version=4.4, os=NetBSD)>'
s = ps('SSH-2.0-OpenSSH_3.0.2 NetBSD Secure Shell')
assert s.os == 'NetBSD'
assert str(s) == 'OpenSSH 3.0.2 running on NetBSD'
assert repr(s) == '<Software(product=OpenSSH, version=3.0.2, os=NetBSD)>'
# FreeBSD
s = ps('SSH-2.0-OpenSSH_7.2 FreeBSD-20160310')
assert s.os == 'FreeBSD (2016-03-10)'
assert str(s) == 'OpenSSH 7.2 running on FreeBSD (2016-03-10)'
assert repr(s) == '<Software(product=OpenSSH, version=7.2, os=FreeBSD (2016-03-10))>'
s = ps('SSH-1.99-OpenSSH_2.9 FreeBSD localisations 20020307')
assert s.os == 'FreeBSD (2002-03-07)'
assert str(s) == 'OpenSSH 2.9 running on FreeBSD (2002-03-07)'
assert repr(s) == '<Software(product=OpenSSH, version=2.9, os=FreeBSD (2002-03-07))>'
s = ps('SSH-2.0-OpenSSH_2.3.0 green@FreeBSD.org 20010321')
assert s.os == 'FreeBSD (2001-03-21)'
assert str(s) == 'OpenSSH 2.3.0 running on FreeBSD (2001-03-21)'
assert repr(s) == '<Software(product=OpenSSH, version=2.3.0, os=FreeBSD (2001-03-21))>'
s = ps('SSH-1.99-OpenSSH_4.4p1 FreeBSD-openssh-portable-overwrite-base-4.4.p1_1,1')
assert s.os == 'FreeBSD'
assert str(s) == 'OpenSSH 4.4p1 running on FreeBSD'
assert repr(s) == '<Software(product=OpenSSH, version=4.4, patch=p1, os=FreeBSD)>'
s = ps('SSH-2.0-OpenSSH_7.2-OVH-rescue FreeBSD')
assert s.os == 'FreeBSD'
assert str(s) == 'OpenSSH 7.2 (OVH-rescue) running on FreeBSD'
assert repr(s) == '<Software(product=OpenSSH, version=7.2, patch=OVH-rescue, os=FreeBSD)>'
# Windows
s = ps('SSH-2.0-OpenSSH_3.7.1 in RemotelyAnywhere 5.21.422')
assert s.os == 'Microsoft Windows (RemotelyAnywhere 5.21.422)'
assert str(s) == 'OpenSSH 3.7.1 running on Microsoft Windows (RemotelyAnywhere 5.21.422)'
assert repr(s) == '<Software(product=OpenSSH, version=3.7.1, os=Microsoft Windows (RemotelyAnywhere 5.21.422))>'
s = ps('SSH-2.0-OpenSSH_3.8 in DesktopAuthority 7.1.091')
assert s.os == 'Microsoft Windows (DesktopAuthority 7.1.091)'
assert str(s) == 'OpenSSH 3.8 running on Microsoft Windows (DesktopAuthority 7.1.091)'
assert repr(s) == '<Software(product=OpenSSH, version=3.8, os=Microsoft Windows (DesktopAuthority 7.1.091))>'
s = ps('SSH-2.0-OpenSSH_3.8 in RemoteSupportManager 1.0.023')
assert s.os == 'Microsoft Windows (RemoteSupportManager 1.0.023)'
assert str(s) == 'OpenSSH 3.8 running on Microsoft Windows (RemoteSupportManager 1.0.023)'
assert repr(s) == '<Software(product=OpenSSH, version=3.8, os=Microsoft Windows (RemoteSupportManager 1.0.023))>'
def test_software_os(self):
ps = lambda x: self.ssh.Software.parse(self.ssh.Banner.parse(x)) # noqa
# unknown
s = ps('SSH-2.0-OpenSSH_3.7.1 MegaOperatingSystem 123')
assert s.os is None
# NetBSD
s = ps('SSH-1.99-OpenSSH_2.5.1 NetBSD_Secure_Shell-20010614')
assert s.os == 'NetBSD (2001-06-14)'
assert str(s) == 'OpenSSH 2.5.1 running on NetBSD (2001-06-14)'
assert repr(s) == '<Software(product=OpenSSH, version=2.5.1, os=NetBSD (2001-06-14))>'
s = ps('SSH-1.99-OpenSSH_5.0 NetBSD_Secure_Shell-20080403+-hpn13v1')
assert s.os == 'NetBSD (2008-04-03)'
assert str(s) == 'OpenSSH 5.0 running on NetBSD (2008-04-03)'
assert repr(s) == '<Software(product=OpenSSH, version=5.0, os=NetBSD (2008-04-03))>'
s = ps('SSH-2.0-OpenSSH_6.6.1_hpn13v11 NetBSD-20100308')
assert s.os == 'NetBSD (2010-03-08)'
assert str(s) == 'OpenSSH 6.6.1 (hpn13v11) running on NetBSD (2010-03-08)'
assert repr(s) == '<Software(product=OpenSSH, version=6.6.1, patch=hpn13v11, os=NetBSD (2010-03-08))>'
s = ps('SSH-2.0-OpenSSH_4.4 NetBSD')
assert s.os == 'NetBSD'
assert str(s) == 'OpenSSH 4.4 running on NetBSD'
assert repr(s) == '<Software(product=OpenSSH, version=4.4, os=NetBSD)>'
s = ps('SSH-2.0-OpenSSH_3.0.2 NetBSD Secure Shell')
assert s.os == 'NetBSD'
assert str(s) == 'OpenSSH 3.0.2 running on NetBSD'
assert repr(s) == '<Software(product=OpenSSH, version=3.0.2, os=NetBSD)>'
# FreeBSD
s = ps('SSH-2.0-OpenSSH_7.2 FreeBSD-20160310')
assert s.os == 'FreeBSD (2016-03-10)'
assert str(s) == 'OpenSSH 7.2 running on FreeBSD (2016-03-10)'
assert repr(s) == '<Software(product=OpenSSH, version=7.2, os=FreeBSD (2016-03-10))>'
s = ps('SSH-1.99-OpenSSH_2.9 FreeBSD localisations 20020307')
assert s.os == 'FreeBSD (2002-03-07)'
assert str(s) == 'OpenSSH 2.9 running on FreeBSD (2002-03-07)'
assert repr(s) == '<Software(product=OpenSSH, version=2.9, os=FreeBSD (2002-03-07))>'
s = ps('SSH-2.0-OpenSSH_2.3.0 green@FreeBSD.org 20010321')
assert s.os == 'FreeBSD (2001-03-21)'
assert str(s) == 'OpenSSH 2.3.0 running on FreeBSD (2001-03-21)'
assert repr(s) == '<Software(product=OpenSSH, version=2.3.0, os=FreeBSD (2001-03-21))>'
s = ps('SSH-1.99-OpenSSH_4.4p1 FreeBSD-openssh-portable-overwrite-base-4.4.p1_1,1')
assert s.os == 'FreeBSD'
assert str(s) == 'OpenSSH 4.4p1 running on FreeBSD'
assert repr(s) == '<Software(product=OpenSSH, version=4.4, patch=p1, os=FreeBSD)>'
s = ps('SSH-2.0-OpenSSH_7.2-OVH-rescue FreeBSD')
assert s.os == 'FreeBSD'
assert str(s) == 'OpenSSH 7.2 (OVH-rescue) running on FreeBSD'
assert repr(s) == '<Software(product=OpenSSH, version=7.2, patch=OVH-rescue, os=FreeBSD)>'
# Windows
s = ps('SSH-2.0-OpenSSH_3.7.1 in RemotelyAnywhere 5.21.422')
assert s.os == 'Microsoft Windows (RemotelyAnywhere 5.21.422)'
assert str(s) == 'OpenSSH 3.7.1 running on Microsoft Windows (RemotelyAnywhere 5.21.422)'
assert repr(s) == '<Software(product=OpenSSH, version=3.7.1, os=Microsoft Windows (RemotelyAnywhere 5.21.422))>'
s = ps('SSH-2.0-OpenSSH_3.8 in DesktopAuthority 7.1.091')
assert s.os == 'Microsoft Windows (DesktopAuthority 7.1.091)'
assert str(s) == 'OpenSSH 3.8 running on Microsoft Windows (DesktopAuthority 7.1.091)'
assert repr(s) == '<Software(product=OpenSSH, version=3.8, os=Microsoft Windows (DesktopAuthority 7.1.091))>'
s = ps('SSH-2.0-OpenSSH_3.8 in RemoteSupportManager 1.0.023')
assert s.os == 'Microsoft Windows (RemoteSupportManager 1.0.023)'
assert str(s) == 'OpenSSH 3.8 running on Microsoft Windows (RemoteSupportManager 1.0.023)'
assert repr(s) == '<Software(product=OpenSSH, version=3.8, os=Microsoft Windows (RemoteSupportManager 1.0.023))>'

View File

@ -6,151 +6,151 @@ import pytest
# pylint: disable=line-too-long,attribute-defined-outside-init
class TestSSH1(object):
@pytest.fixture(autouse=True)
def init(self, ssh_audit):
self.ssh = ssh_audit.SSH
self.ssh1 = ssh_audit.SSH1
self.rbuf = ssh_audit.ReadBuf
self.wbuf = ssh_audit.WriteBuf
self.audit = ssh_audit.audit
self.AuditConf = ssh_audit.AuditConf
@pytest.fixture(autouse=True)
def init(self, ssh_audit):
self.ssh = ssh_audit.SSH
self.ssh1 = ssh_audit.SSH1
self.rbuf = ssh_audit.ReadBuf
self.wbuf = ssh_audit.WriteBuf
self.audit = ssh_audit.audit
self.AuditConf = ssh_audit.AuditConf
def _conf(self):
conf = self.AuditConf('localhost', 22)
conf.colors = False
conf.batch = True
conf.verbose = True
conf.ssh1 = True
conf.ssh2 = False
return conf
def _conf(self):
conf = self.AuditConf('localhost', 22)
conf.colors = False
conf.batch = True
conf.verbose = True
conf.ssh1 = True
conf.ssh2 = False
return conf
def _create_ssh1_packet(self, payload, valid_crc=True):
padding = -(len(payload) + 4) % 8
plen = len(payload) + 4
pad_bytes = b'\x00' * padding
cksum = self.ssh1.crc32(pad_bytes + payload) if valid_crc else 0
data = struct.pack('>I', plen) + pad_bytes + payload + struct.pack('>I', cksum)
return data
def _create_ssh1_packet(self, payload, valid_crc=True):
padding = -(len(payload) + 4) % 8
plen = len(payload) + 4
pad_bytes = b'\x00' * padding
cksum = self.ssh1.crc32(pad_bytes + payload) if valid_crc else 0
data = struct.pack('>I', plen) + pad_bytes + payload + struct.pack('>I', cksum)
return data
@classmethod
def _server_key(cls):
return (1024, 0x10001, 0xee6552da432e0ac2c422df1a51287507748bfe3b5e3e4fa989a8f49fdc163a17754939ef18ef8a667ea3b71036a151fcd7f5e01ceef1e4439864baf3ac569047582c69d6c128212e0980dcb3168f00d371004039983f6033cd785b8b8f85096c7d9405cbfdc664e27c966356a6b4eb6ee20ad43414b50de18b22829c1880b551)
@classmethod
def _server_key(cls):
return (1024, 0x10001, 0xee6552da432e0ac2c422df1a51287507748bfe3b5e3e4fa989a8f49fdc163a17754939ef18ef8a667ea3b71036a151fcd7f5e01ceef1e4439864baf3ac569047582c69d6c128212e0980dcb3168f00d371004039983f6033cd785b8b8f85096c7d9405cbfdc664e27c966356a6b4eb6ee20ad43414b50de18b22829c1880b551)
@classmethod
def _host_key(cls):
return (2048, 0x10001, 0xdfa20cd2a530ccc8c870aa60d9feb3b35deeab81c3215a96557abbd683d21f4600f38e475d87100da9a4404220eeb3bb5584e5a2b5b48ffda58530ea19104a32577d7459d91e76aa711b241050f4cc6d5327ccce254f371acad3be56d46eb5919b73f20dbdb1177b700f00891c5bf4ed128bb90ed541b778288285bcfa28432ab5cbcb8321b6e24760e998e0daa519f093a631e44276d7dd252ce0c08c75e2ab28a7349ead779f97d0f20a6d413bf3623cd216dc35375f6366690bcc41e3b2d5465840ec7ee0dc7e3f1c101d674a0c7dbccbc3942788b111396add2f8153b46a0e4b50d66e57ee92958f1c860dd97cc0e40e32febff915343ed53573142bdf4b)
@classmethod
def _host_key(cls):
return (2048, 0x10001, 0xdfa20cd2a530ccc8c870aa60d9feb3b35deeab81c3215a96557abbd683d21f4600f38e475d87100da9a4404220eeb3bb5584e5a2b5b48ffda58530ea19104a32577d7459d91e76aa711b241050f4cc6d5327ccce254f371acad3be56d46eb5919b73f20dbdb1177b700f00891c5bf4ed128bb90ed541b778288285bcfa28432ab5cbcb8321b6e24760e998e0daa519f093a631e44276d7dd252ce0c08c75e2ab28a7349ead779f97d0f20a6d413bf3623cd216dc35375f6366690bcc41e3b2d5465840ec7ee0dc7e3f1c101d674a0c7dbccbc3942788b111396add2f8153b46a0e4b50d66e57ee92958f1c860dd97cc0e40e32febff915343ed53573142bdf4b)
def _pkm_payload(self):
w = self.wbuf()
w.write(b'\x88\x99\xaa\xbb\xcc\xdd\xee\xff')
b, e, m = self._server_key()
w.write_int(b).write_mpint1(e).write_mpint1(m)
b, e, m = self._host_key()
w.write_int(b).write_mpint1(e).write_mpint1(m)
w.write_int(2)
w.write_int(72)
w.write_int(36)
return w.write_flush()
def _pkm_payload(self):
w = self.wbuf()
w.write(b'\x88\x99\xaa\xbb\xcc\xdd\xee\xff')
b, e, m = self._server_key()
w.write_int(b).write_mpint1(e).write_mpint1(m)
b, e, m = self._host_key()
w.write_int(b).write_mpint1(e).write_mpint1(m)
w.write_int(2)
w.write_int(72)
w.write_int(36)
return w.write_flush()
def test_crc32(self):
assert self.ssh1.crc32(b'') == 0x00
assert self.ssh1.crc32(b'The quick brown fox jumps over the lazy dog') == 0xb9c60808
def test_crc32(self):
assert self.ssh1.crc32(b'') == 0x00
assert self.ssh1.crc32(b'The quick brown fox jumps over the lazy dog') == 0xb9c60808
def test_fingerprint(self):
# pylint: disable=protected-access
b, e, m = self._host_key()
fpd = self.wbuf._create_mpint(m, False)
fpd += self.wbuf._create_mpint(e, False)
fp = self.ssh.Fingerprint(fpd)
assert b == 2048
assert fp.md5 == 'MD5:9d:26:f8:39:fc:20:9d:9b:ca:cc:4a:0f:e1:93:f5:96'
assert fp.sha256 == 'SHA256:vZdx3mhzbvVJmn08t/ruv8WDhJ9jfKYsCTuSzot+QIs'
def test_fingerprint(self):
# pylint: disable=protected-access
b, e, m = self._host_key()
fpd = self.wbuf._create_mpint(m, False)
fpd += self.wbuf._create_mpint(e, False)
fp = self.ssh.Fingerprint(fpd)
assert b == 2048
assert fp.md5 == 'MD5:9d:26:f8:39:fc:20:9d:9b:ca:cc:4a:0f:e1:93:f5:96'
assert fp.sha256 == 'SHA256:vZdx3mhzbvVJmn08t/ruv8WDhJ9jfKYsCTuSzot+QIs'
def _assert_pkm_keys(self, pkm, skey, hkey):
b, e, m = skey
assert pkm.server_key_bits == b
assert pkm.server_key_public_exponent == e
assert pkm.server_key_public_modulus == m
b, e, m = hkey
assert pkm.host_key_bits == b
assert pkm.host_key_public_exponent == e
assert pkm.host_key_public_modulus == m
def _assert_pkm_keys(self, pkm, skey, hkey):
b, e, m = skey
assert pkm.server_key_bits == b
assert pkm.server_key_public_exponent == e
assert pkm.server_key_public_modulus == m
b, e, m = hkey
assert pkm.host_key_bits == b
assert pkm.host_key_public_exponent == e
assert pkm.host_key_public_modulus == m
def _assert_pkm_fields(self, pkm, skey, hkey):
assert pkm is not None
assert pkm.cookie == b'\x88\x99\xaa\xbb\xcc\xdd\xee\xff'
self._assert_pkm_keys(pkm, skey, hkey)
assert pkm.protocol_flags == 2
assert pkm.supported_ciphers_mask == 72
assert pkm.supported_ciphers == ['3des', 'blowfish']
assert pkm.supported_authentications_mask == 36
assert pkm.supported_authentications == ['rsa', 'tis']
fp = self.ssh.Fingerprint(pkm.host_key_fingerprint_data)
assert fp.md5 == 'MD5:9d:26:f8:39:fc:20:9d:9b:ca:cc:4a:0f:e1:93:f5:96'
assert fp.sha256 == 'SHA256:vZdx3mhzbvVJmn08t/ruv8WDhJ9jfKYsCTuSzot+QIs'
def _assert_pkm_fields(self, pkm, skey, hkey):
assert pkm is not None
assert pkm.cookie == b'\x88\x99\xaa\xbb\xcc\xdd\xee\xff'
self._assert_pkm_keys(pkm, skey, hkey)
assert pkm.protocol_flags == 2
assert pkm.supported_ciphers_mask == 72
assert pkm.supported_ciphers == ['3des', 'blowfish']
assert pkm.supported_authentications_mask == 36
assert pkm.supported_authentications == ['rsa', 'tis']
fp = self.ssh.Fingerprint(pkm.host_key_fingerprint_data)
assert fp.md5 == 'MD5:9d:26:f8:39:fc:20:9d:9b:ca:cc:4a:0f:e1:93:f5:96'
assert fp.sha256 == 'SHA256:vZdx3mhzbvVJmn08t/ruv8WDhJ9jfKYsCTuSzot+QIs'
def test_pkm_init(self):
cookie = b'\x88\x99\xaa\xbb\xcc\xdd\xee\xff'
pflags, cmask, amask = 2, 72, 36
skey, hkey = self._server_key(), self._host_key()
pkm = self.ssh1.PublicKeyMessage(cookie, skey, hkey, pflags, cmask, amask)
self._assert_pkm_fields(pkm, skey, hkey)
for skey2 in ([], [0], [0, 1], [0, 1, 2, 3]):
with pytest.raises(ValueError):
pkm = self.ssh1.PublicKeyMessage(cookie, skey2, hkey, pflags, cmask, amask)
for hkey2 in ([], [0], [0, 1], [0, 1, 2, 3]):
with pytest.raises(ValueError):
print(hkey2)
pkm = self.ssh1.PublicKeyMessage(cookie, skey, hkey2, pflags, cmask, amask)
def test_pkm_init(self):
cookie = b'\x88\x99\xaa\xbb\xcc\xdd\xee\xff'
pflags, cmask, amask = 2, 72, 36
skey, hkey = self._server_key(), self._host_key()
pkm = self.ssh1.PublicKeyMessage(cookie, skey, hkey, pflags, cmask, amask)
self._assert_pkm_fields(pkm, skey, hkey)
for skey2 in ([], [0], [0, 1], [0, 1, 2, 3]):
with pytest.raises(ValueError):
pkm = self.ssh1.PublicKeyMessage(cookie, skey2, hkey, pflags, cmask, amask)
for hkey2 in ([], [0], [0, 1], [0, 1, 2, 3]):
with pytest.raises(ValueError):
print(hkey2)
pkm = self.ssh1.PublicKeyMessage(cookie, skey, hkey2, pflags, cmask, amask)
def test_pkm_read(self):
pkm = self.ssh1.PublicKeyMessage.parse(self._pkm_payload())
self._assert_pkm_fields(pkm, self._server_key(), self._host_key())
def test_pkm_read(self):
pkm = self.ssh1.PublicKeyMessage.parse(self._pkm_payload())
self._assert_pkm_fields(pkm, self._server_key(), self._host_key())
def test_pkm_payload(self):
cookie = b'\x88\x99\xaa\xbb\xcc\xdd\xee\xff'
skey, hkey = self._server_key(), self._host_key()
pflags, cmask, amask = 2, 72, 36
pkm1 = self.ssh1.PublicKeyMessage(cookie, skey, hkey, pflags, cmask, amask)
pkm2 = self.ssh1.PublicKeyMessage.parse(self._pkm_payload())
assert pkm1.payload == pkm2.payload
def test_pkm_payload(self):
cookie = b'\x88\x99\xaa\xbb\xcc\xdd\xee\xff'
skey, hkey = self._server_key(), self._host_key()
pflags, cmask, amask = 2, 72, 36
pkm1 = self.ssh1.PublicKeyMessage(cookie, skey, hkey, pflags, cmask, amask)
pkm2 = self.ssh1.PublicKeyMessage.parse(self._pkm_payload())
assert pkm1.payload == pkm2.payload
def test_ssh1_server_simple(self, output_spy, virtual_socket):
vsocket = virtual_socket
w = self.wbuf()
w.write_byte(self.ssh.Protocol.SMSG_PUBLIC_KEY)
w.write(self._pkm_payload())
vsocket.rdata.append(b'SSH-1.5-OpenSSH_7.2 ssh-audit-test\r\n')
vsocket.rdata.append(self._create_ssh1_packet(w.write_flush()))
output_spy.begin()
self.audit(self._conf())
lines = output_spy.flush()
assert len(lines) == 13
def test_ssh1_server_simple(self, output_spy, virtual_socket):
vsocket = virtual_socket
w = self.wbuf()
w.write_byte(self.ssh.Protocol.SMSG_PUBLIC_KEY)
w.write(self._pkm_payload())
vsocket.rdata.append(b'SSH-1.5-OpenSSH_7.2 ssh-audit-test\r\n')
vsocket.rdata.append(self._create_ssh1_packet(w.write_flush()))
output_spy.begin()
self.audit(self._conf())
lines = output_spy.flush()
assert len(lines) == 13
def test_ssh1_server_invalid_first_packet(self, output_spy, virtual_socket):
vsocket = virtual_socket
w = self.wbuf()
w.write_byte(self.ssh.Protocol.SMSG_PUBLIC_KEY + 1)
w.write(self._pkm_payload())
vsocket.rdata.append(b'SSH-1.5-OpenSSH_7.2 ssh-audit-test\r\n')
vsocket.rdata.append(self._create_ssh1_packet(w.write_flush()))
output_spy.begin()
with pytest.raises(SystemExit):
self.audit(self._conf())
lines = output_spy.flush()
assert len(lines) == 7
assert 'unknown message' in lines[-1]
def test_ssh1_server_invalid_first_packet(self, output_spy, virtual_socket):
vsocket = virtual_socket
w = self.wbuf()
w.write_byte(self.ssh.Protocol.SMSG_PUBLIC_KEY + 1)
w.write(self._pkm_payload())
vsocket.rdata.append(b'SSH-1.5-OpenSSH_7.2 ssh-audit-test\r\n')
vsocket.rdata.append(self._create_ssh1_packet(w.write_flush()))
output_spy.begin()
with pytest.raises(SystemExit):
self.audit(self._conf())
lines = output_spy.flush()
assert len(lines) == 7
assert 'unknown message' in lines[-1]
def test_ssh1_server_invalid_checksum(self, output_spy, virtual_socket):
vsocket = virtual_socket
w = self.wbuf()
w.write_byte(self.ssh.Protocol.SMSG_PUBLIC_KEY + 1)
w.write(self._pkm_payload())
vsocket.rdata.append(b'SSH-1.5-OpenSSH_7.2 ssh-audit-test\r\n')
vsocket.rdata.append(self._create_ssh1_packet(w.write_flush(), False))
output_spy.begin()
with pytest.raises(SystemExit):
self.audit(self._conf())
lines = output_spy.flush()
assert len(lines) == 1
assert 'checksum' in lines[-1]
def test_ssh1_server_invalid_checksum(self, output_spy, virtual_socket):
vsocket = virtual_socket
w = self.wbuf()
w.write_byte(self.ssh.Protocol.SMSG_PUBLIC_KEY + 1)
w.write(self._pkm_payload())
vsocket.rdata.append(b'SSH-1.5-OpenSSH_7.2 ssh-audit-test\r\n')
vsocket.rdata.append(self._create_ssh1_packet(w.write_flush(), False))
output_spy.begin()
with pytest.raises(SystemExit):
self.audit(self._conf())
lines = output_spy.flush()
assert len(lines) == 1
assert 'checksum' in lines[-1]

View File

@ -7,151 +7,151 @@ import pytest
# pylint: disable=line-too-long,attribute-defined-outside-init
class TestSSH2(object):
@pytest.fixture(autouse=True)
def init(self, ssh_audit):
self.ssh = ssh_audit.SSH
self.ssh2 = ssh_audit.SSH2
self.rbuf = ssh_audit.ReadBuf
self.wbuf = ssh_audit.WriteBuf
self.audit = ssh_audit.audit
self.AuditConf = ssh_audit.AuditConf
@pytest.fixture(autouse=True)
def init(self, ssh_audit):
self.ssh = ssh_audit.SSH
self.ssh2 = ssh_audit.SSH2
self.rbuf = ssh_audit.ReadBuf
self.wbuf = ssh_audit.WriteBuf
self.audit = ssh_audit.audit
self.AuditConf = ssh_audit.AuditConf
def _conf(self):
conf = self.AuditConf('localhost', 22)
conf.colors = False
conf.batch = True
conf.verbose = True
conf.ssh1 = False
conf.ssh2 = True
return conf
def _conf(self):
conf = self.AuditConf('localhost', 22)
conf.colors = False
conf.batch = True
conf.verbose = True
conf.ssh1 = False
conf.ssh2 = True
return conf
@classmethod
def _create_ssh2_packet(cls, payload):
padding = -(len(payload) + 5) % 8
if padding < 4:
padding += 8
plen = len(payload) + padding + 1
pad_bytes = b'\x00' * padding
data = struct.pack('>Ib', plen, padding) + payload + pad_bytes
return data
@classmethod
def _create_ssh2_packet(cls, payload):
padding = -(len(payload) + 5) % 8
if padding < 4:
padding += 8
plen = len(payload) + padding + 1
pad_bytes = b'\x00' * padding
data = struct.pack('>Ib', plen, padding) + payload + pad_bytes
return data
def _kex_payload(self):
w = self.wbuf()
w.write(b'\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff')
w.write_list([u'curve25519-sha256@libssh.org', u'ecdh-sha2-nistp256', u'ecdh-sha2-nistp384', u'ecdh-sha2-nistp521', u'diffie-hellman-group-exchange-sha256', u'diffie-hellman-group14-sha1'])
w.write_list([u'ssh-rsa', u'rsa-sha2-512', u'rsa-sha2-256', u'ssh-ed25519'])
w.write_list([u'chacha20-poly1305@openssh.com', u'aes128-ctr', u'aes192-ctr', u'aes256-ctr', u'aes128-gcm@openssh.com', u'aes256-gcm@openssh.com', u'aes128-cbc', u'aes192-cbc', u'aes256-cbc'])
w.write_list([u'chacha20-poly1305@openssh.com', u'aes128-ctr', u'aes192-ctr', u'aes256-ctr', u'aes128-gcm@openssh.com', u'aes256-gcm@openssh.com', u'aes128-cbc', u'aes192-cbc', u'aes256-cbc'])
w.write_list([u'umac-64-etm@openssh.com', u'umac-128-etm@openssh.com', u'hmac-sha2-256-etm@openssh.com', u'hmac-sha2-512-etm@openssh.com', u'hmac-sha1-etm@openssh.com', u'umac-64@openssh.com', u'umac-128@openssh.com', u'hmac-sha2-256', u'hmac-sha2-512', u'hmac-sha1'])
w.write_list([u'umac-64-etm@openssh.com', u'umac-128-etm@openssh.com', u'hmac-sha2-256-etm@openssh.com', u'hmac-sha2-512-etm@openssh.com', u'hmac-sha1-etm@openssh.com', u'umac-64@openssh.com', u'umac-128@openssh.com', u'hmac-sha2-256', u'hmac-sha2-512', u'hmac-sha1'])
w.write_list([u'none', u'zlib@openssh.com'])
w.write_list([u'none', u'zlib@openssh.com'])
w.write_list([u''])
w.write_list([u''])
w.write_byte(False)
w.write_int(0)
return w.write_flush()
def _kex_payload(self):
w = self.wbuf()
w.write(b'\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff')
w.write_list([u'curve25519-sha256@libssh.org', u'ecdh-sha2-nistp256', u'ecdh-sha2-nistp384', u'ecdh-sha2-nistp521', u'diffie-hellman-group-exchange-sha256', u'diffie-hellman-group14-sha1'])
w.write_list([u'ssh-rsa', u'rsa-sha2-512', u'rsa-sha2-256', u'ssh-ed25519'])
w.write_list([u'chacha20-poly1305@openssh.com', u'aes128-ctr', u'aes192-ctr', u'aes256-ctr', u'aes128-gcm@openssh.com', u'aes256-gcm@openssh.com', u'aes128-cbc', u'aes192-cbc', u'aes256-cbc'])
w.write_list([u'chacha20-poly1305@openssh.com', u'aes128-ctr', u'aes192-ctr', u'aes256-ctr', u'aes128-gcm@openssh.com', u'aes256-gcm@openssh.com', u'aes128-cbc', u'aes192-cbc', u'aes256-cbc'])
w.write_list([u'umac-64-etm@openssh.com', u'umac-128-etm@openssh.com', u'hmac-sha2-256-etm@openssh.com', u'hmac-sha2-512-etm@openssh.com', u'hmac-sha1-etm@openssh.com', u'umac-64@openssh.com', u'umac-128@openssh.com', u'hmac-sha2-256', u'hmac-sha2-512', u'hmac-sha1'])
w.write_list([u'umac-64-etm@openssh.com', u'umac-128-etm@openssh.com', u'hmac-sha2-256-etm@openssh.com', u'hmac-sha2-512-etm@openssh.com', u'hmac-sha1-etm@openssh.com', u'umac-64@openssh.com', u'umac-128@openssh.com', u'hmac-sha2-256', u'hmac-sha2-512', u'hmac-sha1'])
w.write_list([u'none', u'zlib@openssh.com'])
w.write_list([u'none', u'zlib@openssh.com'])
w.write_list([u''])
w.write_list([u''])
w.write_byte(False)
w.write_int(0)
return w.write_flush()
def test_kex_read(self):
kex = self.ssh2.Kex.parse(self._kex_payload())
assert kex is not None
assert kex.cookie == b'\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff'
assert kex.kex_algorithms == [u'curve25519-sha256@libssh.org', u'ecdh-sha2-nistp256', u'ecdh-sha2-nistp384', u'ecdh-sha2-nistp521', u'diffie-hellman-group-exchange-sha256', u'diffie-hellman-group14-sha1']
assert kex.key_algorithms == [u'ssh-rsa', u'rsa-sha2-512', u'rsa-sha2-256', u'ssh-ed25519']
assert kex.client is not None
assert kex.server is not None
assert kex.client.encryption == [u'chacha20-poly1305@openssh.com', u'aes128-ctr', u'aes192-ctr', u'aes256-ctr', u'aes128-gcm@openssh.com', u'aes256-gcm@openssh.com', u'aes128-cbc', u'aes192-cbc', u'aes256-cbc']
assert kex.server.encryption == [u'chacha20-poly1305@openssh.com', u'aes128-ctr', u'aes192-ctr', u'aes256-ctr', u'aes128-gcm@openssh.com', u'aes256-gcm@openssh.com', u'aes128-cbc', u'aes192-cbc', u'aes256-cbc']
assert kex.client.mac == [u'umac-64-etm@openssh.com', u'umac-128-etm@openssh.com', u'hmac-sha2-256-etm@openssh.com', u'hmac-sha2-512-etm@openssh.com', u'hmac-sha1-etm@openssh.com', u'umac-64@openssh.com', u'umac-128@openssh.com', u'hmac-sha2-256', u'hmac-sha2-512', u'hmac-sha1']
assert kex.server.mac == [u'umac-64-etm@openssh.com', u'umac-128-etm@openssh.com', u'hmac-sha2-256-etm@openssh.com', u'hmac-sha2-512-etm@openssh.com', u'hmac-sha1-etm@openssh.com', u'umac-64@openssh.com', u'umac-128@openssh.com', u'hmac-sha2-256', u'hmac-sha2-512', u'hmac-sha1']
assert kex.client.compression == [u'none', u'zlib@openssh.com']
assert kex.server.compression == [u'none', u'zlib@openssh.com']
assert kex.client.languages == [u'']
assert kex.server.languages == [u'']
assert kex.follows is False
assert kex.unused == 0
def test_kex_read(self):
kex = self.ssh2.Kex.parse(self._kex_payload())
assert kex is not None
assert kex.cookie == b'\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff'
assert kex.kex_algorithms == [u'curve25519-sha256@libssh.org', u'ecdh-sha2-nistp256', u'ecdh-sha2-nistp384', u'ecdh-sha2-nistp521', u'diffie-hellman-group-exchange-sha256', u'diffie-hellman-group14-sha1']
assert kex.key_algorithms == [u'ssh-rsa', u'rsa-sha2-512', u'rsa-sha2-256', u'ssh-ed25519']
assert kex.client is not None
assert kex.server is not None
assert kex.client.encryption == [u'chacha20-poly1305@openssh.com', u'aes128-ctr', u'aes192-ctr', u'aes256-ctr', u'aes128-gcm@openssh.com', u'aes256-gcm@openssh.com', u'aes128-cbc', u'aes192-cbc', u'aes256-cbc']
assert kex.server.encryption == [u'chacha20-poly1305@openssh.com', u'aes128-ctr', u'aes192-ctr', u'aes256-ctr', u'aes128-gcm@openssh.com', u'aes256-gcm@openssh.com', u'aes128-cbc', u'aes192-cbc', u'aes256-cbc']
assert kex.client.mac == [u'umac-64-etm@openssh.com', u'umac-128-etm@openssh.com', u'hmac-sha2-256-etm@openssh.com', u'hmac-sha2-512-etm@openssh.com', u'hmac-sha1-etm@openssh.com', u'umac-64@openssh.com', u'umac-128@openssh.com', u'hmac-sha2-256', u'hmac-sha2-512', u'hmac-sha1']
assert kex.server.mac == [u'umac-64-etm@openssh.com', u'umac-128-etm@openssh.com', u'hmac-sha2-256-etm@openssh.com', u'hmac-sha2-512-etm@openssh.com', u'hmac-sha1-etm@openssh.com', u'umac-64@openssh.com', u'umac-128@openssh.com', u'hmac-sha2-256', u'hmac-sha2-512', u'hmac-sha1']
assert kex.client.compression == [u'none', u'zlib@openssh.com']
assert kex.server.compression == [u'none', u'zlib@openssh.com']
assert kex.client.languages == [u'']
assert kex.server.languages == [u'']
assert kex.follows is False
assert kex.unused == 0
def _get_empty_kex(self, cookie=None):
kex_algs, key_algs = [], []
enc, mac, compression, languages = [], [], ['none'], []
cli = self.ssh2.KexParty(enc, mac, compression, languages)
enc, mac, compression, languages = [], [], ['none'], []
srv = self.ssh2.KexParty(enc, mac, compression, languages)
if cookie is None:
cookie = os.urandom(16)
kex = self.ssh2.Kex(cookie, kex_algs, key_algs, cli, srv, 0)
return kex
def _get_empty_kex(self, cookie=None):
kex_algs, key_algs = [], []
enc, mac, compression, languages = [], [], ['none'], []
cli = self.ssh2.KexParty(enc, mac, compression, languages)
enc, mac, compression, languages = [], [], ['none'], []
srv = self.ssh2.KexParty(enc, mac, compression, languages)
if cookie is None:
cookie = os.urandom(16)
kex = self.ssh2.Kex(cookie, kex_algs, key_algs, cli, srv, 0)
return kex
def _get_kex_variat1(self):
cookie = b'\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff'
kex = self._get_empty_kex(cookie)
kex.kex_algorithms.append('curve25519-sha256@libssh.org')
kex.kex_algorithms.append('ecdh-sha2-nistp256')
kex.kex_algorithms.append('ecdh-sha2-nistp384')
kex.kex_algorithms.append('ecdh-sha2-nistp521')
kex.kex_algorithms.append('diffie-hellman-group-exchange-sha256')
kex.kex_algorithms.append('diffie-hellman-group14-sha1')
kex.key_algorithms.append('ssh-rsa')
kex.key_algorithms.append('rsa-sha2-512')
kex.key_algorithms.append('rsa-sha2-256')
kex.key_algorithms.append('ssh-ed25519')
kex.server.encryption.append('chacha20-poly1305@openssh.com')
kex.server.encryption.append('aes128-ctr')
kex.server.encryption.append('aes192-ctr')
kex.server.encryption.append('aes256-ctr')
kex.server.encryption.append('aes128-gcm@openssh.com')
kex.server.encryption.append('aes256-gcm@openssh.com')
kex.server.encryption.append('aes128-cbc')
kex.server.encryption.append('aes192-cbc')
kex.server.encryption.append('aes256-cbc')
kex.server.mac.append('umac-64-etm@openssh.com')
kex.server.mac.append('umac-128-etm@openssh.com')
kex.server.mac.append('hmac-sha2-256-etm@openssh.com')
kex.server.mac.append('hmac-sha2-512-etm@openssh.com')
kex.server.mac.append('hmac-sha1-etm@openssh.com')
kex.server.mac.append('umac-64@openssh.com')
kex.server.mac.append('umac-128@openssh.com')
kex.server.mac.append('hmac-sha2-256')
kex.server.mac.append('hmac-sha2-512')
kex.server.mac.append('hmac-sha1')
kex.server.compression.append('zlib@openssh.com')
for a in kex.server.encryption:
kex.client.encryption.append(a)
for a in kex.server.mac:
kex.client.mac.append(a)
for a in kex.server.compression:
if a == 'none':
continue
kex.client.compression.append(a)
return kex
def _get_kex_variat1(self):
cookie = b'\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff'
kex = self._get_empty_kex(cookie)
kex.kex_algorithms.append('curve25519-sha256@libssh.org')
kex.kex_algorithms.append('ecdh-sha2-nistp256')
kex.kex_algorithms.append('ecdh-sha2-nistp384')
kex.kex_algorithms.append('ecdh-sha2-nistp521')
kex.kex_algorithms.append('diffie-hellman-group-exchange-sha256')
kex.kex_algorithms.append('diffie-hellman-group14-sha1')
kex.key_algorithms.append('ssh-rsa')
kex.key_algorithms.append('rsa-sha2-512')
kex.key_algorithms.append('rsa-sha2-256')
kex.key_algorithms.append('ssh-ed25519')
kex.server.encryption.append('chacha20-poly1305@openssh.com')
kex.server.encryption.append('aes128-ctr')
kex.server.encryption.append('aes192-ctr')
kex.server.encryption.append('aes256-ctr')
kex.server.encryption.append('aes128-gcm@openssh.com')
kex.server.encryption.append('aes256-gcm@openssh.com')
kex.server.encryption.append('aes128-cbc')
kex.server.encryption.append('aes192-cbc')
kex.server.encryption.append('aes256-cbc')
kex.server.mac.append('umac-64-etm@openssh.com')
kex.server.mac.append('umac-128-etm@openssh.com')
kex.server.mac.append('hmac-sha2-256-etm@openssh.com')
kex.server.mac.append('hmac-sha2-512-etm@openssh.com')
kex.server.mac.append('hmac-sha1-etm@openssh.com')
kex.server.mac.append('umac-64@openssh.com')
kex.server.mac.append('umac-128@openssh.com')
kex.server.mac.append('hmac-sha2-256')
kex.server.mac.append('hmac-sha2-512')
kex.server.mac.append('hmac-sha1')
kex.server.compression.append('zlib@openssh.com')
for a in kex.server.encryption:
kex.client.encryption.append(a)
for a in kex.server.mac:
kex.client.mac.append(a)
for a in kex.server.compression:
if a == 'none':
continue
kex.client.compression.append(a)
return kex
def test_key_payload(self):
kex1 = self._get_kex_variat1()
kex2 = self.ssh2.Kex.parse(self._kex_payload())
assert kex1.payload == kex2.payload
def test_key_payload(self):
kex1 = self._get_kex_variat1()
kex2 = self.ssh2.Kex.parse(self._kex_payload())
assert kex1.payload == kex2.payload
@pytest.mark.skip(reason="Temporarily skip this test to have a working test suite!")
def test_ssh2_server_simple(self, output_spy, virtual_socket):
vsocket = virtual_socket
w = self.wbuf()
w.write_byte(self.ssh.Protocol.MSG_KEXINIT)
w.write(self._kex_payload())
vsocket.rdata.append(b'SSH-2.0-OpenSSH_7.3 ssh-audit-test\r\n')
vsocket.rdata.append(self._create_ssh2_packet(w.write_flush()))
output_spy.begin()
self.audit(self._conf())
lines = output_spy.flush()
assert len(lines) == 72
@pytest.mark.skip(reason="Temporarily skip this test to have a working test suite!")
def test_ssh2_server_simple(self, output_spy, virtual_socket):
vsocket = virtual_socket
w = self.wbuf()
w.write_byte(self.ssh.Protocol.MSG_KEXINIT)
w.write(self._kex_payload())
vsocket.rdata.append(b'SSH-2.0-OpenSSH_7.3 ssh-audit-test\r\n')
vsocket.rdata.append(self._create_ssh2_packet(w.write_flush()))
output_spy.begin()
self.audit(self._conf())
lines = output_spy.flush()
assert len(lines) == 72
def test_ssh2_server_invalid_first_packet(self, output_spy, virtual_socket):
vsocket = virtual_socket
w = self.wbuf()
w.write_byte(self.ssh.Protocol.MSG_KEXINIT + 1)
vsocket.rdata.append(b'SSH-2.0-OpenSSH_7.3 ssh-audit-test\r\n')
vsocket.rdata.append(self._create_ssh2_packet(w.write_flush()))
output_spy.begin()
with pytest.raises(SystemExit):
self.audit(self._conf())
lines = output_spy.flush()
assert len(lines) == 3
assert 'unknown message' in lines[-1]
def test_ssh2_server_invalid_first_packet(self, output_spy, virtual_socket):
vsocket = virtual_socket
w = self.wbuf()
w.write_byte(self.ssh.Protocol.MSG_KEXINIT + 1)
vsocket.rdata.append(b'SSH-2.0-OpenSSH_7.3 ssh-audit-test\r\n')
vsocket.rdata.append(self._create_ssh2_packet(w.write_flush()))
output_spy.begin()
with pytest.raises(SystemExit):
self.audit(self._conf())
lines = output_spy.flush()
assert len(lines) == 3
assert 'unknown message' in lines[-1]

View File

@ -5,160 +5,160 @@ import pytest
# pylint: disable=attribute-defined-outside-init
class TestSSHAlgorithm(object):
@pytest.fixture(autouse=True)
def init(self, ssh_audit):
self.ssh = ssh_audit.SSH
@pytest.fixture(autouse=True)
def init(self, ssh_audit):
self.ssh = ssh_audit.SSH
def _tf(self, v, s=None):
return self.ssh.Algorithm.Timeframe().update(v, s)
def _tf(self, v, s=None):
return self.ssh.Algorithm.Timeframe().update(v, s)
def test_get_ssh_version(self):
def ver(v):
return self.ssh.Algorithm.get_ssh_version(v)
def test_get_ssh_version(self):
def ver(v):
return self.ssh.Algorithm.get_ssh_version(v)
assert ver('7.5') == ('OpenSSH', '7.5', False)
assert ver('7.5C') == ('OpenSSH', '7.5', True)
assert ver('d2016.74') == ('Dropbear SSH', '2016.74', False)
assert ver('l10.7.4') == ('libssh', '0.7.4', False)
assert ver('')[1] == ''
assert ver('7.5') == ('OpenSSH', '7.5', False)
assert ver('7.5C') == ('OpenSSH', '7.5', True)
assert ver('d2016.74') == ('Dropbear SSH', '2016.74', False)
assert ver('l10.7.4') == ('libssh', '0.7.4', False)
assert ver('')[1] == ''
def test_get_since_text(self):
def gst(v):
return self.ssh.Algorithm.get_since_text(v)
def test_get_since_text(self):
def gst(v):
return self.ssh.Algorithm.get_since_text(v)
assert gst(['7.5']) == 'available since OpenSSH 7.5'
assert gst(['7.5C']) == 'available since OpenSSH 7.5 (client only)'
assert gst(['7.5,']) == 'available since OpenSSH 7.5'
assert gst(['d2016.73']) == 'available since Dropbear SSH 2016.73'
assert gst(['7.5,d2016.73']) == 'available since OpenSSH 7.5, Dropbear SSH 2016.73'
assert gst(['l10.7.4']) is None
assert gst([]) is None
assert gst(['7.5']) == 'available since OpenSSH 7.5'
assert gst(['7.5C']) == 'available since OpenSSH 7.5 (client only)'
assert gst(['7.5,']) == 'available since OpenSSH 7.5'
assert gst(['d2016.73']) == 'available since Dropbear SSH 2016.73'
assert gst(['7.5,d2016.73']) == 'available since OpenSSH 7.5, Dropbear SSH 2016.73'
assert gst(['l10.7.4']) is None
assert gst([]) is None
def test_timeframe_creation(self):
# pylint: disable=line-too-long,too-many-statements
def cmp_tf(v, s, r):
assert str(self._tf(v, s)) == str(r)
def test_timeframe_creation(self):
# pylint: disable=line-too-long,too-many-statements
def cmp_tf(v, s, r):
assert str(self._tf(v, s)) == str(r)
cmp_tf(['6.2'], None, {'OpenSSH': ['6.2', None, '6.2', None]})
cmp_tf(['6.2'], True, {'OpenSSH': ['6.2', None, None, None]})
cmp_tf(['6.2'], False, {'OpenSSH': [None, None, '6.2', None]})
cmp_tf(['6.2C'], None, {'OpenSSH': [None, None, '6.2', None]})
cmp_tf(['6.2C'], True, {})
cmp_tf(['6.2C'], False, {'OpenSSH': [None, None, '6.2', None]})
cmp_tf(['6.1,6.2C'], None, {'OpenSSH': ['6.1', None, '6.2', None]})
cmp_tf(['6.1,6.2C'], True, {'OpenSSH': ['6.1', None, None, None]})
cmp_tf(['6.1,6.2C'], False, {'OpenSSH': [None, None, '6.2', None]})
cmp_tf(['6.2C,6.1'], None, {'OpenSSH': ['6.1', None, '6.2', None]})
cmp_tf(['6.2C,6.1'], True, {'OpenSSH': ['6.1', None, None, None]})
cmp_tf(['6.2C,6.1'], False, {'OpenSSH': [None, None, '6.2', None]})
cmp_tf(['6.3,6.2C'], None, {'OpenSSH': ['6.3', None, '6.2', None]})
cmp_tf(['6.3,6.2C'], True, {'OpenSSH': ['6.3', None, None, None]})
cmp_tf(['6.3,6.2C'], False, {'OpenSSH': [None, None, '6.2', None]})
cmp_tf(['6.2C,6.3'], None, {'OpenSSH': ['6.3', None, '6.2', None]})
cmp_tf(['6.2C,6.3'], True, {'OpenSSH': ['6.3', None, None, None]})
cmp_tf(['6.2C,6.3'], False, {'OpenSSH': [None, None, '6.2', None]})
cmp_tf(['6.2'], None, {'OpenSSH': ['6.2', None, '6.2', None]})
cmp_tf(['6.2'], True, {'OpenSSH': ['6.2', None, None, None]})
cmp_tf(['6.2'], False, {'OpenSSH': [None, None, '6.2', None]})
cmp_tf(['6.2C'], None, {'OpenSSH': [None, None, '6.2', None]})
cmp_tf(['6.2C'], True, {})
cmp_tf(['6.2C'], False, {'OpenSSH': [None, None, '6.2', None]})
cmp_tf(['6.1,6.2C'], None, {'OpenSSH': ['6.1', None, '6.2', None]})
cmp_tf(['6.1,6.2C'], True, {'OpenSSH': ['6.1', None, None, None]})
cmp_tf(['6.1,6.2C'], False, {'OpenSSH': [None, None, '6.2', None]})
cmp_tf(['6.2C,6.1'], None, {'OpenSSH': ['6.1', None, '6.2', None]})
cmp_tf(['6.2C,6.1'], True, {'OpenSSH': ['6.1', None, None, None]})
cmp_tf(['6.2C,6.1'], False, {'OpenSSH': [None, None, '6.2', None]})
cmp_tf(['6.3,6.2C'], None, {'OpenSSH': ['6.3', None, '6.2', None]})
cmp_tf(['6.3,6.2C'], True, {'OpenSSH': ['6.3', None, None, None]})
cmp_tf(['6.3,6.2C'], False, {'OpenSSH': [None, None, '6.2', None]})
cmp_tf(['6.2C,6.3'], None, {'OpenSSH': ['6.3', None, '6.2', None]})
cmp_tf(['6.2C,6.3'], True, {'OpenSSH': ['6.3', None, None, None]})
cmp_tf(['6.2C,6.3'], False, {'OpenSSH': [None, None, '6.2', None]})
cmp_tf(['6.2', '6.6'], None, {'OpenSSH': ['6.2', '6.6', '6.2', '6.6']})
cmp_tf(['6.2', '6.6'], True, {'OpenSSH': ['6.2', '6.6', None, None]})
cmp_tf(['6.2', '6.6'], False, {'OpenSSH': [None, None, '6.2', '6.6']})
cmp_tf(['6.2C', '6.6'], None, {'OpenSSH': [None, '6.6', '6.2', '6.6']})
cmp_tf(['6.2C', '6.6'], True, {'OpenSSH': [None, '6.6', None, None]})
cmp_tf(['6.2C', '6.6'], False, {'OpenSSH': [None, None, '6.2', '6.6']})
cmp_tf(['6.1,6.2C', '6.6'], None, {'OpenSSH': ['6.1', '6.6', '6.2', '6.6']})
cmp_tf(['6.1,6.2C', '6.6'], True, {'OpenSSH': ['6.1', '6.6', None, None]})
cmp_tf(['6.1,6.2C', '6.6'], False, {'OpenSSH': [None, None, '6.2', '6.6']})
cmp_tf(['6.2C,6.1', '6.6'], None, {'OpenSSH': ['6.1', '6.6', '6.2', '6.6']})
cmp_tf(['6.2C,6.1', '6.6'], True, {'OpenSSH': ['6.1', '6.6', None, None]})
cmp_tf(['6.2C,6.1', '6.6'], False, {'OpenSSH': [None, None, '6.2', '6.6']})
cmp_tf(['6.3,6.2C', '6.6'], None, {'OpenSSH': ['6.3', '6.6', '6.2', '6.6']})
cmp_tf(['6.3,6.2C', '6.6'], True, {'OpenSSH': ['6.3', '6.6', None, None]})
cmp_tf(['6.3,6.2C', '6.6'], False, {'OpenSSH': [None, None, '6.2', '6.6']})
cmp_tf(['6.2C,6.3', '6.6'], None, {'OpenSSH': ['6.3', '6.6', '6.2', '6.6']})
cmp_tf(['6.2C,6.3', '6.6'], True, {'OpenSSH': ['6.3', '6.6', None, None]})
cmp_tf(['6.2C,6.3', '6.6'], False, {'OpenSSH': [None, None, '6.2', '6.6']})
cmp_tf(['6.2', '6.6'], None, {'OpenSSH': ['6.2', '6.6', '6.2', '6.6']})
cmp_tf(['6.2', '6.6'], True, {'OpenSSH': ['6.2', '6.6', None, None]})
cmp_tf(['6.2', '6.6'], False, {'OpenSSH': [None, None, '6.2', '6.6']})
cmp_tf(['6.2C', '6.6'], None, {'OpenSSH': [None, '6.6', '6.2', '6.6']})
cmp_tf(['6.2C', '6.6'], True, {'OpenSSH': [None, '6.6', None, None]})
cmp_tf(['6.2C', '6.6'], False, {'OpenSSH': [None, None, '6.2', '6.6']})
cmp_tf(['6.1,6.2C', '6.6'], None, {'OpenSSH': ['6.1', '6.6', '6.2', '6.6']})
cmp_tf(['6.1,6.2C', '6.6'], True, {'OpenSSH': ['6.1', '6.6', None, None]})
cmp_tf(['6.1,6.2C', '6.6'], False, {'OpenSSH': [None, None, '6.2', '6.6']})
cmp_tf(['6.2C,6.1', '6.6'], None, {'OpenSSH': ['6.1', '6.6', '6.2', '6.6']})
cmp_tf(['6.2C,6.1', '6.6'], True, {'OpenSSH': ['6.1', '6.6', None, None]})
cmp_tf(['6.2C,6.1', '6.6'], False, {'OpenSSH': [None, None, '6.2', '6.6']})
cmp_tf(['6.3,6.2C', '6.6'], None, {'OpenSSH': ['6.3', '6.6', '6.2', '6.6']})
cmp_tf(['6.3,6.2C', '6.6'], True, {'OpenSSH': ['6.3', '6.6', None, None]})
cmp_tf(['6.3,6.2C', '6.6'], False, {'OpenSSH': [None, None, '6.2', '6.6']})
cmp_tf(['6.2C,6.3', '6.6'], None, {'OpenSSH': ['6.3', '6.6', '6.2', '6.6']})
cmp_tf(['6.2C,6.3', '6.6'], True, {'OpenSSH': ['6.3', '6.6', None, None]})
cmp_tf(['6.2C,6.3', '6.6'], False, {'OpenSSH': [None, None, '6.2', '6.6']})
cmp_tf(['6.2', '6.6', None], None, {'OpenSSH': ['6.2', '6.6', '6.2', None]})
cmp_tf(['6.2', '6.6', None], True, {'OpenSSH': ['6.2', '6.6', None, None]})
cmp_tf(['6.2', '6.6', None], False, {'OpenSSH': [None, None, '6.2', None]})
cmp_tf(['6.2C', '6.6', None], None, {'OpenSSH': [None, '6.6', '6.2', None]})
cmp_tf(['6.2C', '6.6', None], True, {'OpenSSH': [None, '6.6', None, None]})
cmp_tf(['6.2C', '6.6', None], False, {'OpenSSH': [None, None, '6.2', None]})
cmp_tf(['6.1,6.2C', '6.6', None], None, {'OpenSSH': ['6.1', '6.6', '6.2', None]})
cmp_tf(['6.1,6.2C', '6.6', None], True, {'OpenSSH': ['6.1', '6.6', None, None]})
cmp_tf(['6.1,6.2C', '6.6', None], False, {'OpenSSH': [None, None, '6.2', None]})
cmp_tf(['6.2C,6.1', '6.6', None], None, {'OpenSSH': ['6.1', '6.6', '6.2', None]})
cmp_tf(['6.2C,6.1', '6.6', None], True, {'OpenSSH': ['6.1', '6.6', None, None]})
cmp_tf(['6.2C,6.1', '6.6', None], False, {'OpenSSH': [None, None, '6.2', None]})
cmp_tf(['6.2,6.3C', '6.6', None], None, {'OpenSSH': ['6.2', '6.6', '6.3', None]})
cmp_tf(['6.2,6.3C', '6.6', None], True, {'OpenSSH': ['6.2', '6.6', None, None]})
cmp_tf(['6.2,6.3C', '6.6', None], False, {'OpenSSH': [None, None, '6.3', None]})
cmp_tf(['6.3C,6.2', '6.6', None], None, {'OpenSSH': ['6.2', '6.6', '6.3', None]})
cmp_tf(['6.3C,6.2', '6.6', None], True, {'OpenSSH': ['6.2', '6.6', None, None]})
cmp_tf(['6.3C,6.2', '6.6', None], False, {'OpenSSH': [None, None, '6.3', None]})
cmp_tf(['6.2', '6.6', None], None, {'OpenSSH': ['6.2', '6.6', '6.2', None]})
cmp_tf(['6.2', '6.6', None], True, {'OpenSSH': ['6.2', '6.6', None, None]})
cmp_tf(['6.2', '6.6', None], False, {'OpenSSH': [None, None, '6.2', None]})
cmp_tf(['6.2C', '6.6', None], None, {'OpenSSH': [None, '6.6', '6.2', None]})
cmp_tf(['6.2C', '6.6', None], True, {'OpenSSH': [None, '6.6', None, None]})
cmp_tf(['6.2C', '6.6', None], False, {'OpenSSH': [None, None, '6.2', None]})
cmp_tf(['6.1,6.2C', '6.6', None], None, {'OpenSSH': ['6.1', '6.6', '6.2', None]})
cmp_tf(['6.1,6.2C', '6.6', None], True, {'OpenSSH': ['6.1', '6.6', None, None]})
cmp_tf(['6.1,6.2C', '6.6', None], False, {'OpenSSH': [None, None, '6.2', None]})
cmp_tf(['6.2C,6.1', '6.6', None], None, {'OpenSSH': ['6.1', '6.6', '6.2', None]})
cmp_tf(['6.2C,6.1', '6.6', None], True, {'OpenSSH': ['6.1', '6.6', None, None]})
cmp_tf(['6.2C,6.1', '6.6', None], False, {'OpenSSH': [None, None, '6.2', None]})
cmp_tf(['6.2,6.3C', '6.6', None], None, {'OpenSSH': ['6.2', '6.6', '6.3', None]})
cmp_tf(['6.2,6.3C', '6.6', None], True, {'OpenSSH': ['6.2', '6.6', None, None]})
cmp_tf(['6.2,6.3C', '6.6', None], False, {'OpenSSH': [None, None, '6.3', None]})
cmp_tf(['6.3C,6.2', '6.6', None], None, {'OpenSSH': ['6.2', '6.6', '6.3', None]})
cmp_tf(['6.3C,6.2', '6.6', None], True, {'OpenSSH': ['6.2', '6.6', None, None]})
cmp_tf(['6.3C,6.2', '6.6', None], False, {'OpenSSH': [None, None, '6.3', None]})
cmp_tf(['6.2', '6.6', '7.1'], None, {'OpenSSH': ['6.2', '6.6', '6.2', '7.1']})
cmp_tf(['6.2', '6.6', '7.1'], True, {'OpenSSH': ['6.2', '6.6', None, None]})
cmp_tf(['6.2', '6.6', '7.1'], False, {'OpenSSH': [None, None, '6.2', '7.1']})
cmp_tf(['6.1,6.2C', '6.6', '7.1'], None, {'OpenSSH': ['6.1', '6.6', '6.2', '7.1']})
cmp_tf(['6.1,6.2C', '6.6', '7.1'], True, {'OpenSSH': ['6.1', '6.6', None, None]})
cmp_tf(['6.1,6.2C', '6.6', '7.1'], False, {'OpenSSH': [None, None, '6.2', '7.1']})
cmp_tf(['6.2C,6.1', '6.6', '7.1'], None, {'OpenSSH': ['6.1', '6.6', '6.2', '7.1']})
cmp_tf(['6.2C,6.1', '6.6', '7.1'], True, {'OpenSSH': ['6.1', '6.6', None, None]})
cmp_tf(['6.2C,6.1', '6.6', '7.1'], False, {'OpenSSH': [None, None, '6.2', '7.1']})
cmp_tf(['6.2,6.3C', '6.6', '7.1'], None, {'OpenSSH': ['6.2', '6.6', '6.3', '7.1']})
cmp_tf(['6.2,6.3C', '6.6', '7.1'], True, {'OpenSSH': ['6.2', '6.6', None, None]})
cmp_tf(['6.2,6.3C', '6.6', '7.1'], False, {'OpenSSH': [None, None, '6.3', '7.1']})
cmp_tf(['6.3C,6.2', '6.6', '7.1'], None, {'OpenSSH': ['6.2', '6.6', '6.3', '7.1']})
cmp_tf(['6.3C,6.2', '6.6', '7.1'], True, {'OpenSSH': ['6.2', '6.6', None, None]})
cmp_tf(['6.3C,6.2', '6.6', '7.1'], False, {'OpenSSH': [None, None, '6.3', '7.1']})
cmp_tf(['6.2', '6.6', '7.1'], None, {'OpenSSH': ['6.2', '6.6', '6.2', '7.1']})
cmp_tf(['6.2', '6.6', '7.1'], True, {'OpenSSH': ['6.2', '6.6', None, None]})
cmp_tf(['6.2', '6.6', '7.1'], False, {'OpenSSH': [None, None, '6.2', '7.1']})
cmp_tf(['6.1,6.2C', '6.6', '7.1'], None, {'OpenSSH': ['6.1', '6.6', '6.2', '7.1']})
cmp_tf(['6.1,6.2C', '6.6', '7.1'], True, {'OpenSSH': ['6.1', '6.6', None, None]})
cmp_tf(['6.1,6.2C', '6.6', '7.1'], False, {'OpenSSH': [None, None, '6.2', '7.1']})
cmp_tf(['6.2C,6.1', '6.6', '7.1'], None, {'OpenSSH': ['6.1', '6.6', '6.2', '7.1']})
cmp_tf(['6.2C,6.1', '6.6', '7.1'], True, {'OpenSSH': ['6.1', '6.6', None, None]})
cmp_tf(['6.2C,6.1', '6.6', '7.1'], False, {'OpenSSH': [None, None, '6.2', '7.1']})
cmp_tf(['6.2,6.3C', '6.6', '7.1'], None, {'OpenSSH': ['6.2', '6.6', '6.3', '7.1']})
cmp_tf(['6.2,6.3C', '6.6', '7.1'], True, {'OpenSSH': ['6.2', '6.6', None, None]})
cmp_tf(['6.2,6.3C', '6.6', '7.1'], False, {'OpenSSH': [None, None, '6.3', '7.1']})
cmp_tf(['6.3C,6.2', '6.6', '7.1'], None, {'OpenSSH': ['6.2', '6.6', '6.3', '7.1']})
cmp_tf(['6.3C,6.2', '6.6', '7.1'], True, {'OpenSSH': ['6.2', '6.6', None, None]})
cmp_tf(['6.3C,6.2', '6.6', '7.1'], False, {'OpenSSH': [None, None, '6.3', '7.1']})
tf1 = self._tf(['6.1,d2016.72,6.2C', '6.6,d2016.73', '7.1,d2016.74'])
tf2 = self._tf(['d2016.72,6.2C,6.1', 'd2016.73,6.6', 'd2016.74,7.1'])
tf3 = self._tf(['d2016.72,6.2C,6.1', '6.6,d2016.73', '7.1,d2016.74'])
# check without caring for output order
ov = "'OpenSSH': ['6.1', '6.6', '6.2', '7.1']"
dv = "'Dropbear SSH': ['2016.72', '2016.73', '2016.72', '2016.74']"
assert len(str(tf1)) == len(str(tf2)) == len(str(tf3))
assert ov in str(tf1) and ov in str(tf2) and ov in str(tf3)
assert dv in str(tf1) and dv in str(tf2) and dv in str(tf3)
assert ov in repr(tf1) and ov in repr(tf2) and ov in repr(tf3)
assert dv in repr(tf1) and dv in repr(tf2) and dv in repr(tf3)
tf1 = self._tf(['6.1,d2016.72,6.2C', '6.6,d2016.73', '7.1,d2016.74'])
tf2 = self._tf(['d2016.72,6.2C,6.1', 'd2016.73,6.6', 'd2016.74,7.1'])
tf3 = self._tf(['d2016.72,6.2C,6.1', '6.6,d2016.73', '7.1,d2016.74'])
# check without caring for output order
ov = "'OpenSSH': ['6.1', '6.6', '6.2', '7.1']"
dv = "'Dropbear SSH': ['2016.72', '2016.73', '2016.72', '2016.74']"
assert len(str(tf1)) == len(str(tf2)) == len(str(tf3))
assert ov in str(tf1) and ov in str(tf2) and ov in str(tf3)
assert dv in str(tf1) and dv in str(tf2) and dv in str(tf3)
assert ov in repr(tf1) and ov in repr(tf2) and ov in repr(tf3)
assert dv in repr(tf1) and dv in repr(tf2) and dv in repr(tf3)
def test_timeframe_object(self):
tf = self._tf(['6.1,6.2C', '6.6', '7.1'])
assert 'OpenSSH' in tf
assert 'Dropbear SSH' not in tf
assert 'libssh' not in tf
assert 'unknown' not in tf
assert tf['OpenSSH'] == ('6.1', '6.6', '6.2', '7.1')
assert tf['Dropbear SSH'] == (None, None, None, None)
assert tf['libssh'] == (None, None, None, None)
assert tf['unknown'] == (None, None, None, None)
assert tf.get_from('OpenSSH', True) == '6.1'
assert tf.get_till('OpenSSH', True) == '6.6'
assert tf.get_from('OpenSSH', False) == '6.2'
assert tf.get_till('OpenSSH', False) == '7.1'
def test_timeframe_object(self):
tf = self._tf(['6.1,6.2C', '6.6', '7.1'])
assert 'OpenSSH' in tf
assert 'Dropbear SSH' not in tf
assert 'libssh' not in tf
assert 'unknown' not in tf
assert tf['OpenSSH'] == ('6.1', '6.6', '6.2', '7.1')
assert tf['Dropbear SSH'] == (None, None, None, None)
assert tf['libssh'] == (None, None, None, None)
assert tf['unknown'] == (None, None, None, None)
assert tf.get_from('OpenSSH', True) == '6.1'
assert tf.get_till('OpenSSH', True) == '6.6'
assert tf.get_from('OpenSSH', False) == '6.2'
assert tf.get_till('OpenSSH', False) == '7.1'
tf = self._tf(['6.1,d2016.72,6.2C', '6.6,d2016.73', '7.1,d2016.74'])
assert 'OpenSSH' in tf
assert 'Dropbear SSH' in tf
assert 'libssh' not in tf
assert 'unknown' not in tf
assert tf['OpenSSH'] == ('6.1', '6.6', '6.2', '7.1')
assert tf['Dropbear SSH'] == ('2016.72', '2016.73', '2016.72', '2016.74')
assert tf['libssh'] == (None, None, None, None)
assert tf['unknown'] == (None, None, None, None)
assert tf.get_from('OpenSSH', True) == '6.1'
assert tf.get_till('OpenSSH', True) == '6.6'
assert tf.get_from('OpenSSH', False) == '6.2'
assert tf.get_till('OpenSSH', False) == '7.1'
assert tf.get_from('Dropbear SSH', True) == '2016.72'
assert tf.get_till('Dropbear SSH', True) == '2016.73'
assert tf.get_from('Dropbear SSH', False) == '2016.72'
assert tf.get_till('Dropbear SSH', False) == '2016.74'
ov = "'OpenSSH': ['6.1', '6.6', '6.2', '7.1']"
dv = "'Dropbear SSH': ['2016.72', '2016.73', '2016.72', '2016.74']"
assert ov in str(tf)
assert dv in str(tf)
assert ov in repr(tf)
assert dv in repr(tf)
tf = self._tf(['6.1,d2016.72,6.2C', '6.6,d2016.73', '7.1,d2016.74'])
assert 'OpenSSH' in tf
assert 'Dropbear SSH' in tf
assert 'libssh' not in tf
assert 'unknown' not in tf
assert tf['OpenSSH'] == ('6.1', '6.6', '6.2', '7.1')
assert tf['Dropbear SSH'] == ('2016.72', '2016.73', '2016.72', '2016.74')
assert tf['libssh'] == (None, None, None, None)
assert tf['unknown'] == (None, None, None, None)
assert tf.get_from('OpenSSH', True) == '6.1'
assert tf.get_till('OpenSSH', True) == '6.6'
assert tf.get_from('OpenSSH', False) == '6.2'
assert tf.get_till('OpenSSH', False) == '7.1'
assert tf.get_from('Dropbear SSH', True) == '2016.72'
assert tf.get_till('Dropbear SSH', True) == '2016.73'
assert tf.get_from('Dropbear SSH', False) == '2016.72'
assert tf.get_till('Dropbear SSH', False) == '2016.74'
ov = "'OpenSSH': ['6.1', '6.6', '6.2', '7.1']"
dv = "'Dropbear SSH': ['2016.72', '2016.73', '2016.72', '2016.74']"
assert ov in str(tf)
assert dv in str(tf)
assert ov in repr(tf)
assert dv in repr(tf)

View File

@ -6,213 +6,213 @@ import pytest
# pylint: disable=attribute-defined-outside-init
class TestUtils(object):
@pytest.fixture(autouse=True)
def init(self, ssh_audit):
self.utils = ssh_audit.Utils
self.PY3 = sys.version_info >= (3,)
@pytest.fixture(autouse=True)
def init(self, ssh_audit):
self.utils = ssh_audit.Utils
self.PY3 = sys.version_info >= (3,)
def test_to_bytes_py2(self):
if self.PY3:
return
# binary_type (native str, bytes as str)
assert self.utils.to_bytes('fran\xc3\xa7ais') == 'fran\xc3\xa7ais'
assert self.utils.to_bytes(b'fran\xc3\xa7ais') == 'fran\xc3\xa7ais'
# text_type (unicode)
assert self.utils.to_bytes(u'fran\xe7ais') == 'fran\xc3\xa7ais'
# other
with pytest.raises(TypeError):
self.utils.to_bytes(123)
def test_to_bytes_py2(self):
if self.PY3:
return
# binary_type (native str, bytes as str)
assert self.utils.to_bytes('fran\xc3\xa7ais') == 'fran\xc3\xa7ais'
assert self.utils.to_bytes(b'fran\xc3\xa7ais') == 'fran\xc3\xa7ais'
# text_type (unicode)
assert self.utils.to_bytes(u'fran\xe7ais') == 'fran\xc3\xa7ais'
# other
with pytest.raises(TypeError):
self.utils.to_bytes(123)
def test_to_bytes_py3(self):
if not self.PY3:
return
# binary_type (bytes)
assert self.utils.to_bytes(b'fran\xc3\xa7ais') == b'fran\xc3\xa7ais'
# text_type (native str as unicode, unicode)
assert self.utils.to_bytes('fran\xe7ais') == b'fran\xc3\xa7ais'
assert self.utils.to_bytes(u'fran\xe7ais') == b'fran\xc3\xa7ais'
# other
with pytest.raises(TypeError):
self.utils.to_bytes(123)
def test_to_bytes_py3(self):
if not self.PY3:
return
# binary_type (bytes)
assert self.utils.to_bytes(b'fran\xc3\xa7ais') == b'fran\xc3\xa7ais'
# text_type (native str as unicode, unicode)
assert self.utils.to_bytes('fran\xe7ais') == b'fran\xc3\xa7ais'
assert self.utils.to_bytes(u'fran\xe7ais') == b'fran\xc3\xa7ais'
# other
with pytest.raises(TypeError):
self.utils.to_bytes(123)
def test_to_utext_py2(self):
if self.PY3:
return
# binary_type (native str, bytes as str)
assert self.utils.to_utext('fran\xc3\xa7ais') == u'fran\xe7ais'
assert self.utils.to_utext(b'fran\xc3\xa7ais') == u'fran\xe7ais'
# text_type (unicode)
assert self.utils.to_utext(u'fran\xe7ais') == u'fran\xe7ais'
# other
with pytest.raises(TypeError):
self.utils.to_utext(123)
def test_to_utext_py2(self):
if self.PY3:
return
# binary_type (native str, bytes as str)
assert self.utils.to_utext('fran\xc3\xa7ais') == u'fran\xe7ais'
assert self.utils.to_utext(b'fran\xc3\xa7ais') == u'fran\xe7ais'
# text_type (unicode)
assert self.utils.to_utext(u'fran\xe7ais') == u'fran\xe7ais'
# other
with pytest.raises(TypeError):
self.utils.to_utext(123)
def test_to_utext_py3(self):
if not self.PY3:
return
# binary_type (bytes)
assert self.utils.to_utext(b'fran\xc3\xa7ais') == u'fran\xe7ais'
# text_type (native str as unicode, unicode)
assert self.utils.to_utext('fran\xe7ais') == 'fran\xe7ais'
assert self.utils.to_utext(u'fran\xe7ais') == u'fran\xe7ais'
# other
with pytest.raises(TypeError):
self.utils.to_utext(123)
def test_to_utext_py3(self):
if not self.PY3:
return
# binary_type (bytes)
assert self.utils.to_utext(b'fran\xc3\xa7ais') == u'fran\xe7ais'
# text_type (native str as unicode, unicode)
assert self.utils.to_utext('fran\xe7ais') == 'fran\xe7ais'
assert self.utils.to_utext(u'fran\xe7ais') == u'fran\xe7ais'
# other
with pytest.raises(TypeError):
self.utils.to_utext(123)
def test_to_ntext_py2(self):
if self.PY3:
return
# str (native str, bytes as str)
assert self.utils.to_ntext('fran\xc3\xa7ais') == 'fran\xc3\xa7ais'
assert self.utils.to_ntext(b'fran\xc3\xa7ais') == 'fran\xc3\xa7ais'
# text_type (unicode)
assert self.utils.to_ntext(u'fran\xe7ais') == 'fran\xc3\xa7ais'
# other
with pytest.raises(TypeError):
self.utils.to_ntext(123)
def test_to_ntext_py2(self):
if self.PY3:
return
# str (native str, bytes as str)
assert self.utils.to_ntext('fran\xc3\xa7ais') == 'fran\xc3\xa7ais'
assert self.utils.to_ntext(b'fran\xc3\xa7ais') == 'fran\xc3\xa7ais'
# text_type (unicode)
assert self.utils.to_ntext(u'fran\xe7ais') == 'fran\xc3\xa7ais'
# other
with pytest.raises(TypeError):
self.utils.to_ntext(123)
def test_to_ntext_py3(self):
if not self.PY3:
return
# str (native str)
assert self.utils.to_ntext('fran\xc3\xa7ais') == 'fran\xc3\xa7ais'
assert self.utils.to_ntext(u'fran\xe7ais') == 'fran\xe7ais'
# binary_type (bytes)
assert self.utils.to_ntext(b'fran\xc3\xa7ais') == 'fran\xe7ais'
# other
with pytest.raises(TypeError):
self.utils.to_ntext(123)
def test_to_ntext_py3(self):
if not self.PY3:
return
# str (native str)
assert self.utils.to_ntext('fran\xc3\xa7ais') == 'fran\xc3\xa7ais'
assert self.utils.to_ntext(u'fran\xe7ais') == 'fran\xe7ais'
# binary_type (bytes)
assert self.utils.to_ntext(b'fran\xc3\xa7ais') == 'fran\xe7ais'
# other
with pytest.raises(TypeError):
self.utils.to_ntext(123)
def test_is_ascii_py2(self):
if self.PY3:
return
# text_type (unicode)
assert self.utils.is_ascii(u'francais') is True
assert self.utils.is_ascii(u'fran\xe7ais') is False
# str
assert self.utils.is_ascii('francais') is True
assert self.utils.is_ascii('fran\xc3\xa7ais') is False
# other
assert self.utils.is_ascii(123) is False
def test_is_ascii_py2(self):
if self.PY3:
return
# text_type (unicode)
assert self.utils.is_ascii(u'francais') is True
assert self.utils.is_ascii(u'fran\xe7ais') is False
# str
assert self.utils.is_ascii('francais') is True
assert self.utils.is_ascii('fran\xc3\xa7ais') is False
# other
assert self.utils.is_ascii(123) is False
def test_is_ascii_py3(self):
if not self.PY3:
return
# text_type (str)
assert self.utils.is_ascii('francais') is True
assert self.utils.is_ascii(u'francais') is True
assert self.utils.is_ascii('fran\xe7ais') is False
assert self.utils.is_ascii(u'fran\xe7ais') is False
# other
assert self.utils.is_ascii(123) is False
def test_is_ascii_py3(self):
if not self.PY3:
return
# text_type (str)
assert self.utils.is_ascii('francais') is True
assert self.utils.is_ascii(u'francais') is True
assert self.utils.is_ascii('fran\xe7ais') is False
assert self.utils.is_ascii(u'fran\xe7ais') is False
# other
assert self.utils.is_ascii(123) is False
def test_to_ascii_py2(self):
if self.PY3:
return
# text_type (unicode)
assert self.utils.to_ascii(u'francais') == 'francais'
assert self.utils.to_ascii(u'fran\xe7ais') == 'fran?ais'
assert self.utils.to_ascii(u'fran\xe7ais', 'ignore') == 'franais'
# str
assert self.utils.to_ascii('francais') == 'francais'
assert self.utils.to_ascii('fran\xc3\xa7ais') == 'fran??ais'
assert self.utils.to_ascii('fran\xc3\xa7ais', 'ignore') == 'franais'
with pytest.raises(TypeError):
self.utils.to_ascii(123)
def test_to_ascii_py2(self):
if self.PY3:
return
# text_type (unicode)
assert self.utils.to_ascii(u'francais') == 'francais'
assert self.utils.to_ascii(u'fran\xe7ais') == 'fran?ais'
assert self.utils.to_ascii(u'fran\xe7ais', 'ignore') == 'franais'
# str
assert self.utils.to_ascii('francais') == 'francais'
assert self.utils.to_ascii('fran\xc3\xa7ais') == 'fran??ais'
assert self.utils.to_ascii('fran\xc3\xa7ais', 'ignore') == 'franais'
with pytest.raises(TypeError):
self.utils.to_ascii(123)
def test_to_ascii_py3(self):
if not self.PY3:
return
# text_type (str)
assert self.utils.to_ascii('francais') == 'francais'
assert self.utils.to_ascii(u'francais') == 'francais'
assert self.utils.to_ascii('fran\xe7ais') == 'fran?ais'
assert self.utils.to_ascii('fran\xe7ais', 'ignore') == 'franais'
assert self.utils.to_ascii(u'fran\xe7ais') == 'fran?ais'
assert self.utils.to_ascii(u'fran\xe7ais', 'ignore') == 'franais'
with pytest.raises(TypeError):
self.utils.to_ascii(123)
def test_to_ascii_py3(self):
if not self.PY3:
return
# text_type (str)
assert self.utils.to_ascii('francais') == 'francais'
assert self.utils.to_ascii(u'francais') == 'francais'
assert self.utils.to_ascii('fran\xe7ais') == 'fran?ais'
assert self.utils.to_ascii('fran\xe7ais', 'ignore') == 'franais'
assert self.utils.to_ascii(u'fran\xe7ais') == 'fran?ais'
assert self.utils.to_ascii(u'fran\xe7ais', 'ignore') == 'franais'
with pytest.raises(TypeError):
self.utils.to_ascii(123)
def test_is_print_ascii_py2(self):
if self.PY3:
return
# text_type (unicode)
assert self.utils.is_print_ascii(u'francais') is True
assert self.utils.is_print_ascii(u'francais\n') is False
assert self.utils.is_print_ascii(u'fran\xe7ais') is False
assert self.utils.is_print_ascii(u'fran\xe7ais\n') is False
# str
assert self.utils.is_print_ascii('francais') is True
assert self.utils.is_print_ascii('francais\n') is False
assert self.utils.is_print_ascii('fran\xc3\xa7ais') is False
# other
assert self.utils.is_print_ascii(123) is False
def test_is_print_ascii_py2(self):
if self.PY3:
return
# text_type (unicode)
assert self.utils.is_print_ascii(u'francais') is True
assert self.utils.is_print_ascii(u'francais\n') is False
assert self.utils.is_print_ascii(u'fran\xe7ais') is False
assert self.utils.is_print_ascii(u'fran\xe7ais\n') is False
# str
assert self.utils.is_print_ascii('francais') is True
assert self.utils.is_print_ascii('francais\n') is False
assert self.utils.is_print_ascii('fran\xc3\xa7ais') is False
# other
assert self.utils.is_print_ascii(123) is False
def test_is_print_ascii_py3(self):
if not self.PY3:
return
# text_type (str)
assert self.utils.is_print_ascii('francais') is True
assert self.utils.is_print_ascii('francais\n') is False
assert self.utils.is_print_ascii(u'francais') is True
assert self.utils.is_print_ascii(u'francais\n') is False
assert self.utils.is_print_ascii('fran\xe7ais') is False
assert self.utils.is_print_ascii(u'fran\xe7ais') is False
# other
assert self.utils.is_print_ascii(123) is False
def test_is_print_ascii_py3(self):
if not self.PY3:
return
# text_type (str)
assert self.utils.is_print_ascii('francais') is True
assert self.utils.is_print_ascii('francais\n') is False
assert self.utils.is_print_ascii(u'francais') is True
assert self.utils.is_print_ascii(u'francais\n') is False
assert self.utils.is_print_ascii('fran\xe7ais') is False
assert self.utils.is_print_ascii(u'fran\xe7ais') is False
# other
assert self.utils.is_print_ascii(123) is False
def test_to_print_ascii_py2(self):
if self.PY3:
return
# text_type (unicode)
assert self.utils.to_print_ascii(u'francais') == 'francais'
assert self.utils.to_print_ascii(u'francais\n') == 'francais?'
assert self.utils.to_print_ascii(u'fran\xe7ais') == 'fran?ais'
assert self.utils.to_print_ascii(u'fran\xe7ais\n') == 'fran?ais?'
assert self.utils.to_print_ascii(u'fran\xe7ais', 'ignore') == 'franais'
assert self.utils.to_print_ascii(u'fran\xe7ais\n', 'ignore') == 'franais'
# str
assert self.utils.to_print_ascii('francais') == 'francais'
assert self.utils.to_print_ascii('francais\n') == 'francais?'
assert self.utils.to_print_ascii('fran\xc3\xa7ais') == 'fran??ais'
assert self.utils.to_print_ascii('fran\xc3\xa7ais\n') == 'fran??ais?'
assert self.utils.to_print_ascii('fran\xc3\xa7ais', 'ignore') == 'franais'
assert self.utils.to_print_ascii('fran\xc3\xa7ais\n', 'ignore') == 'franais'
with pytest.raises(TypeError):
self.utils.to_print_ascii(123)
def test_to_print_ascii_py2(self):
if self.PY3:
return
# text_type (unicode)
assert self.utils.to_print_ascii(u'francais') == 'francais'
assert self.utils.to_print_ascii(u'francais\n') == 'francais?'
assert self.utils.to_print_ascii(u'fran\xe7ais') == 'fran?ais'
assert self.utils.to_print_ascii(u'fran\xe7ais\n') == 'fran?ais?'
assert self.utils.to_print_ascii(u'fran\xe7ais', 'ignore') == 'franais'
assert self.utils.to_print_ascii(u'fran\xe7ais\n', 'ignore') == 'franais'
# str
assert self.utils.to_print_ascii('francais') == 'francais'
assert self.utils.to_print_ascii('francais\n') == 'francais?'
assert self.utils.to_print_ascii('fran\xc3\xa7ais') == 'fran??ais'
assert self.utils.to_print_ascii('fran\xc3\xa7ais\n') == 'fran??ais?'
assert self.utils.to_print_ascii('fran\xc3\xa7ais', 'ignore') == 'franais'
assert self.utils.to_print_ascii('fran\xc3\xa7ais\n', 'ignore') == 'franais'
with pytest.raises(TypeError):
self.utils.to_print_ascii(123)
def test_to_print_ascii_py3(self):
if not self.PY3:
return
# text_type (str)
assert self.utils.to_print_ascii('francais') == 'francais'
assert self.utils.to_print_ascii('francais\n') == 'francais?'
assert self.utils.to_print_ascii(u'francais') == 'francais'
assert self.utils.to_print_ascii(u'francais\n') == 'francais?'
assert self.utils.to_print_ascii('fran\xe7ais') == 'fran?ais'
assert self.utils.to_print_ascii('fran\xe7ais\n') == 'fran?ais?'
assert self.utils.to_print_ascii('fran\xe7ais', 'ignore') == 'franais'
assert self.utils.to_print_ascii('fran\xe7ais\n', 'ignore') == 'franais'
assert self.utils.to_print_ascii(u'fran\xe7ais') == 'fran?ais'
assert self.utils.to_print_ascii(u'fran\xe7ais\n') == 'fran?ais?'
assert self.utils.to_print_ascii(u'fran\xe7ais', 'ignore') == 'franais'
assert self.utils.to_print_ascii(u'fran\xe7ais\n', 'ignore') == 'franais'
with pytest.raises(TypeError):
self.utils.to_print_ascii(123)
def test_to_print_ascii_py3(self):
if not self.PY3:
return
# text_type (str)
assert self.utils.to_print_ascii('francais') == 'francais'
assert self.utils.to_print_ascii('francais\n') == 'francais?'
assert self.utils.to_print_ascii(u'francais') == 'francais'
assert self.utils.to_print_ascii(u'francais\n') == 'francais?'
assert self.utils.to_print_ascii('fran\xe7ais') == 'fran?ais'
assert self.utils.to_print_ascii('fran\xe7ais\n') == 'fran?ais?'
assert self.utils.to_print_ascii('fran\xe7ais', 'ignore') == 'franais'
assert self.utils.to_print_ascii('fran\xe7ais\n', 'ignore') == 'franais'
assert self.utils.to_print_ascii(u'fran\xe7ais') == 'fran?ais'
assert self.utils.to_print_ascii(u'fran\xe7ais\n') == 'fran?ais?'
assert self.utils.to_print_ascii(u'fran\xe7ais', 'ignore') == 'franais'
assert self.utils.to_print_ascii(u'fran\xe7ais\n', 'ignore') == 'franais'
with pytest.raises(TypeError):
self.utils.to_print_ascii(123)
def test_ctoi(self):
assert self.utils.ctoi(123) == 123
assert self.utils.ctoi('ABC') == 65
def test_ctoi(self):
assert self.utils.ctoi(123) == 123
assert self.utils.ctoi('ABC') == 65
def test_parse_int(self):
assert self.utils.parse_int(123) == 123
assert self.utils.parse_int('123') == 123
assert self.utils.parse_int(-123) == -123
assert self.utils.parse_int('-123') == -123
assert self.utils.parse_int('abc') == 0
def test_parse_int(self):
assert self.utils.parse_int(123) == 123
assert self.utils.parse_int('123') == 123
assert self.utils.parse_int(-123) == -123
assert self.utils.parse_int('-123') == -123
assert self.utils.parse_int('abc') == 0
def test_unique_seq(self):
assert self.utils.unique_seq((1, 2, 2, 3, 3, 3)) == (1, 2, 3)
assert self.utils.unique_seq((3, 3, 3, 2, 2, 1)) == (3, 2, 1)
assert self.utils.unique_seq([1, 2, 2, 3, 3, 3]) == [1, 2, 3]
assert self.utils.unique_seq([3, 3, 3, 2, 2, 1]) == [3, 2, 1]
def test_unique_seq(self):
assert self.utils.unique_seq((1, 2, 2, 3, 3, 3)) == (1, 2, 3)
assert self.utils.unique_seq((3, 3, 3, 2, 2, 1)) == (3, 2, 1)
assert self.utils.unique_seq([1, 2, 2, 3, 3, 3]) == [1, 2, 3]
assert self.utils.unique_seq([3, 3, 3, 2, 2, 1]) == [3, 2, 1]

View File

@ -5,211 +5,211 @@ import pytest
# pylint: disable=attribute-defined-outside-init
class TestVersionCompare(object):
@pytest.fixture(autouse=True)
def init(self, ssh_audit):
self.ssh = ssh_audit.SSH
@pytest.fixture(autouse=True)
def init(self, ssh_audit):
self.ssh = ssh_audit.SSH
def get_dropbear_software(self, v):
b = self.ssh.Banner.parse('SSH-2.0-dropbear_{0}'.format(v))
return self.ssh.Software.parse(b)
def get_dropbear_software(self, v):
b = self.ssh.Banner.parse('SSH-2.0-dropbear_{0}'.format(v))
return self.ssh.Software.parse(b)
def get_openssh_software(self, v):
b = self.ssh.Banner.parse('SSH-2.0-OpenSSH_{0}'.format(v))
return self.ssh.Software.parse(b)
def get_openssh_software(self, v):
b = self.ssh.Banner.parse('SSH-2.0-OpenSSH_{0}'.format(v))
return self.ssh.Software.parse(b)
def get_libssh_software(self, v):
b = self.ssh.Banner.parse('SSH-2.0-libssh-{0}'.format(v))
return self.ssh.Software.parse(b)
def get_libssh_software(self, v):
b = self.ssh.Banner.parse('SSH-2.0-libssh-{0}'.format(v))
return self.ssh.Software.parse(b)
def test_dropbear_compare_version_pre_years(self):
s = self.get_dropbear_software('0.44')
assert s.compare_version(None) == 1
assert s.compare_version('') == 1
assert s.compare_version('0.43') > 0
assert s.compare_version('0.44') == 0
assert s.compare_version(s) == 0
assert s.compare_version('0.45') < 0
assert s.between_versions('0.43', '0.45')
assert s.between_versions('0.43', '0.43') is False
assert s.between_versions('0.45', '0.43') is False
def test_dropbear_compare_version_pre_years(self):
s = self.get_dropbear_software('0.44')
assert s.compare_version(None) == 1
assert s.compare_version('') == 1
assert s.compare_version('0.43') > 0
assert s.compare_version('0.44') == 0
assert s.compare_version(s) == 0
assert s.compare_version('0.45') < 0
assert s.between_versions('0.43', '0.45')
assert s.between_versions('0.43', '0.43') is False
assert s.between_versions('0.45', '0.43') is False
def test_dropbear_compare_version_with_years(self):
s = self.get_dropbear_software('2015.71')
assert s.compare_version(None) == 1
assert s.compare_version('') == 1
assert s.compare_version('2014.66') > 0
assert s.compare_version('2015.71') == 0
assert s.compare_version(s) == 0
assert s.compare_version('2016.74') < 0
assert s.between_versions('2014.66', '2016.74')
assert s.between_versions('2014.66', '2015.69') is False
assert s.between_versions('2016.74', '2014.66') is False
def test_dropbear_compare_version_with_years(self):
s = self.get_dropbear_software('2015.71')
assert s.compare_version(None) == 1
assert s.compare_version('') == 1
assert s.compare_version('2014.66') > 0
assert s.compare_version('2015.71') == 0
assert s.compare_version(s) == 0
assert s.compare_version('2016.74') < 0
assert s.between_versions('2014.66', '2016.74')
assert s.between_versions('2014.66', '2015.69') is False
assert s.between_versions('2016.74', '2014.66') is False
def test_dropbear_compare_version_mixed(self):
s = self.get_dropbear_software('0.53.1')
assert s.compare_version(None) == 1
assert s.compare_version('') == 1
assert s.compare_version('0.53') > 0
assert s.compare_version('0.53.1') == 0
assert s.compare_version(s) == 0
assert s.compare_version('2011.54') < 0
assert s.between_versions('0.53', '2011.54')
assert s.between_versions('0.53', '0.53') is False
assert s.between_versions('2011.54', '0.53') is False
def test_dropbear_compare_version_mixed(self):
s = self.get_dropbear_software('0.53.1')
assert s.compare_version(None) == 1
assert s.compare_version('') == 1
assert s.compare_version('0.53') > 0
assert s.compare_version('0.53.1') == 0
assert s.compare_version(s) == 0
assert s.compare_version('2011.54') < 0
assert s.between_versions('0.53', '2011.54')
assert s.between_versions('0.53', '0.53') is False
assert s.between_versions('2011.54', '0.53') is False
def test_dropbear_compare_version_patchlevel(self):
s1 = self.get_dropbear_software('0.44')
s2 = self.get_dropbear_software('0.44test3')
assert s1.compare_version(None) == 1
assert s1.compare_version('') == 1
assert s1.compare_version('0.44') == 0
assert s1.compare_version(s1) == 0
assert s1.compare_version('0.43') > 0
assert s1.compare_version('0.44test4') > 0
assert s1.between_versions('0.44test4', '0.45')
assert s1.between_versions('0.43', '0.44test4') is False
assert s1.between_versions('0.45', '0.44test4') is False
assert s2.compare_version(None) == 1
assert s2.compare_version('') == 1
assert s2.compare_version('0.44test3') == 0
assert s2.compare_version(s2) == 0
assert s2.compare_version('0.44') < 0
assert s2.compare_version('0.44test4') < 0
assert s2.between_versions('0.43', '0.44')
assert s2.between_versions('0.43', '0.44test2') is False
assert s2.between_versions('0.44', '0.43') is False
assert s1.compare_version(s2) > 0
assert s2.compare_version(s1) < 0
def test_dropbear_compare_version_patchlevel(self):
s1 = self.get_dropbear_software('0.44')
s2 = self.get_dropbear_software('0.44test3')
assert s1.compare_version(None) == 1
assert s1.compare_version('') == 1
assert s1.compare_version('0.44') == 0
assert s1.compare_version(s1) == 0
assert s1.compare_version('0.43') > 0
assert s1.compare_version('0.44test4') > 0
assert s1.between_versions('0.44test4', '0.45')
assert s1.between_versions('0.43', '0.44test4') is False
assert s1.between_versions('0.45', '0.44test4') is False
assert s2.compare_version(None) == 1
assert s2.compare_version('') == 1
assert s2.compare_version('0.44test3') == 0
assert s2.compare_version(s2) == 0
assert s2.compare_version('0.44') < 0
assert s2.compare_version('0.44test4') < 0
assert s2.between_versions('0.43', '0.44')
assert s2.between_versions('0.43', '0.44test2') is False
assert s2.between_versions('0.44', '0.43') is False
assert s1.compare_version(s2) > 0
assert s2.compare_version(s1) < 0
def test_dropbear_compare_version_sequential(self):
versions = []
for i in range(28, 44):
versions.append('0.{0}'.format(i))
for i in range(1, 5):
versions.append('0.44test{0}'.format(i))
for i in range(44, 49):
versions.append('0.{0}'.format(i))
versions.append('0.48.1')
for i in range(49, 54):
versions.append('0.{0}'.format(i))
versions.append('0.53.1')
for v in ['2011.54', '2012.55']:
versions.append(v)
for i in range(56, 61):
versions.append('2013.{0}'.format(i))
for v in ['2013.61test', '2013.62']:
versions.append(v)
for i in range(63, 67):
versions.append('2014.{0}'.format(i))
for i in range(67, 72):
versions.append('2015.{0}'.format(i))
for i in range(72, 75):
versions.append('2016.{0}'.format(i))
length = len(versions)
for i in range(length):
v = versions[i]
s = self.get_dropbear_software(v)
assert s.compare_version(v) == 0
if i - 1 >= 0:
vbefore = versions[i - 1]
assert s.compare_version(vbefore) > 0
if i + 1 < length:
vnext = versions[i + 1]
assert s.compare_version(vnext) < 0
def test_dropbear_compare_version_sequential(self):
versions = []
for i in range(28, 44):
versions.append('0.{0}'.format(i))
for i in range(1, 5):
versions.append('0.44test{0}'.format(i))
for i in range(44, 49):
versions.append('0.{0}'.format(i))
versions.append('0.48.1')
for i in range(49, 54):
versions.append('0.{0}'.format(i))
versions.append('0.53.1')
for v in ['2011.54', '2012.55']:
versions.append(v)
for i in range(56, 61):
versions.append('2013.{0}'.format(i))
for v in ['2013.61test', '2013.62']:
versions.append(v)
for i in range(63, 67):
versions.append('2014.{0}'.format(i))
for i in range(67, 72):
versions.append('2015.{0}'.format(i))
for i in range(72, 75):
versions.append('2016.{0}'.format(i))
length = len(versions)
for i in range(length):
v = versions[i]
s = self.get_dropbear_software(v)
assert s.compare_version(v) == 0
if i - 1 >= 0:
vbefore = versions[i - 1]
assert s.compare_version(vbefore) > 0
if i + 1 < length:
vnext = versions[i + 1]
assert s.compare_version(vnext) < 0
def test_openssh_compare_version_simple(self):
s = self.get_openssh_software('3.7.1')
assert s.compare_version(None) == 1
assert s.compare_version('') == 1
assert s.compare_version('3.7') > 0
assert s.compare_version('3.7.1') == 0
assert s.compare_version(s) == 0
assert s.compare_version('3.8') < 0
assert s.between_versions('3.7', '3.8')
assert s.between_versions('3.6', '3.7') is False
assert s.between_versions('3.8', '3.7') is False
def test_openssh_compare_version_simple(self):
s = self.get_openssh_software('3.7.1')
assert s.compare_version(None) == 1
assert s.compare_version('') == 1
assert s.compare_version('3.7') > 0
assert s.compare_version('3.7.1') == 0
assert s.compare_version(s) == 0
assert s.compare_version('3.8') < 0
assert s.between_versions('3.7', '3.8')
assert s.between_versions('3.6', '3.7') is False
assert s.between_versions('3.8', '3.7') is False
def test_openssh_compare_version_patchlevel(self):
s1 = self.get_openssh_software('2.1.1')
s2 = self.get_openssh_software('2.1.1p2')
assert s1.compare_version(s1) == 0
assert s2.compare_version(s2) == 0
assert s1.compare_version('2.1.1p1') == 0
assert s1.compare_version('2.1.1p2') == 0
assert s2.compare_version('2.1.1') == 0
assert s2.compare_version('2.1.1p1') > 0
assert s2.compare_version('2.1.1p3') < 0
assert s1.compare_version(s2) == 0
assert s2.compare_version(s1) == 0
def test_openssh_compare_version_patchlevel(self):
s1 = self.get_openssh_software('2.1.1')
s2 = self.get_openssh_software('2.1.1p2')
assert s1.compare_version(s1) == 0
assert s2.compare_version(s2) == 0
assert s1.compare_version('2.1.1p1') == 0
assert s1.compare_version('2.1.1p2') == 0
assert s2.compare_version('2.1.1') == 0
assert s2.compare_version('2.1.1p1') > 0
assert s2.compare_version('2.1.1p3') < 0
assert s1.compare_version(s2) == 0
assert s2.compare_version(s1) == 0
def test_openbsd_compare_version_sequential(self):
versions = []
for v in ['1.2.3', '2.1.0', '2.1.1', '2.2.0', '2.3.0']:
versions.append(v)
for v in ['2.5.0', '2.5.1', '2.5.2', '2.9', '2.9.9']:
versions.append(v)
for v in ['3.0', '3.0.1', '3.0.2', '3.1', '3.2.2', '3.2.3']:
versions.append(v)
for i in range(3, 7):
versions.append('3.{0}'.format(i))
for v in ['3.6.1', '3.7.0', '3.7.1']:
versions.append(v)
for i in range(8, 10):
versions.append('3.{0}'.format(i))
for i in range(0, 10):
versions.append('4.{0}'.format(i))
for i in range(0, 10):
versions.append('5.{0}'.format(i))
for i in range(0, 10):
versions.append('6.{0}'.format(i))
for i in range(0, 4):
versions.append('7.{0}'.format(i))
length = len(versions)
for i in range(length):
v = versions[i]
s = self.get_openssh_software(v)
assert s.compare_version(v) == 0
if i - 1 >= 0:
vbefore = versions[i - 1]
assert s.compare_version(vbefore) > 0
if i + 1 < length:
vnext = versions[i + 1]
assert s.compare_version(vnext) < 0
def test_openbsd_compare_version_sequential(self):
versions = []
for v in ['1.2.3', '2.1.0', '2.1.1', '2.2.0', '2.3.0']:
versions.append(v)
for v in ['2.5.0', '2.5.1', '2.5.2', '2.9', '2.9.9']:
versions.append(v)
for v in ['3.0', '3.0.1', '3.0.2', '3.1', '3.2.2', '3.2.3']:
versions.append(v)
for i in range(3, 7):
versions.append('3.{0}'.format(i))
for v in ['3.6.1', '3.7.0', '3.7.1']:
versions.append(v)
for i in range(8, 10):
versions.append('3.{0}'.format(i))
for i in range(0, 10):
versions.append('4.{0}'.format(i))
for i in range(0, 10):
versions.append('5.{0}'.format(i))
for i in range(0, 10):
versions.append('6.{0}'.format(i))
for i in range(0, 4):
versions.append('7.{0}'.format(i))
length = len(versions)
for i in range(length):
v = versions[i]
s = self.get_openssh_software(v)
assert s.compare_version(v) == 0
if i - 1 >= 0:
vbefore = versions[i - 1]
assert s.compare_version(vbefore) > 0
if i + 1 < length:
vnext = versions[i + 1]
assert s.compare_version(vnext) < 0
def test_libssh_compare_version_simple(self):
s = self.get_libssh_software('0.3')
assert s.compare_version(None) == 1
assert s.compare_version('') == 1
assert s.compare_version('0.2') > 0
assert s.compare_version('0.3') == 0
assert s.compare_version(s) == 0
assert s.compare_version('0.3.1') < 0
assert s.between_versions('0.2', '0.3.1')
assert s.between_versions('0.1', '0.2') is False
assert s.between_versions('0.3.1', '0.2') is False
def test_libssh_compare_version_simple(self):
s = self.get_libssh_software('0.3')
assert s.compare_version(None) == 1
assert s.compare_version('') == 1
assert s.compare_version('0.2') > 0
assert s.compare_version('0.3') == 0
assert s.compare_version(s) == 0
assert s.compare_version('0.3.1') < 0
assert s.between_versions('0.2', '0.3.1')
assert s.between_versions('0.1', '0.2') is False
assert s.between_versions('0.3.1', '0.2') is False
def test_libssh_compare_version_sequential(self):
versions = []
for v in ['0.2', '0.3']:
versions.append(v)
for i in range(1, 5):
versions.append('0.3.{0}'.format(i))
for i in range(0, 9):
versions.append('0.4.{0}'.format(i))
for i in range(0, 6):
versions.append('0.5.{0}'.format(i))
for i in range(0, 6):
versions.append('0.6.{0}'.format(i))
for i in range(0, 5):
versions.append('0.7.{0}'.format(i))
length = len(versions)
for i in range(length):
v = versions[i]
s = self.get_libssh_software(v)
assert s.compare_version(v) == 0
if i - 1 >= 0:
vbefore = versions[i - 1]
assert s.compare_version(vbefore) > 0
if i + 1 < length:
vnext = versions[i + 1]
assert s.compare_version(vnext) < 0
def test_libssh_compare_version_sequential(self):
versions = []
for v in ['0.2', '0.3']:
versions.append(v)
for i in range(1, 5):
versions.append('0.3.{0}'.format(i))
for i in range(0, 9):
versions.append('0.4.{0}'.format(i))
for i in range(0, 6):
versions.append('0.5.{0}'.format(i))
for i in range(0, 6):
versions.append('0.6.{0}'.format(i))
for i in range(0, 5):
versions.append('0.7.{0}'.format(i))
length = len(versions)
for i in range(length):
v = versions[i]
s = self.get_libssh_software(v)
assert s.compare_version(v) == 0
if i - 1 >= 0:
vbefore = versions[i - 1]
assert s.compare_version(vbefore) > 0
if i + 1 < length:
vnext = versions[i + 1]
assert s.compare_version(vnext) < 0

View File

@ -137,13 +137,5 @@ max-module-lines = 2500
[flake8]
ignore =
W191, # indentation contains tabs
E101, # indentation contains mixed spaces and tabs
E241, # multiple spaces after operator; should be kept for tabular data
E501, # line too long
E117, # over-indented
E126, # continuation line over-indented for hanging indent
E128, # continuation line under-indented for visual indent
E722, # do not use bare 'except'
F601, # dictionary key 'ecdsa-sha2-1.3.132.0.10' repeated with different values
W504, # line break after binary operator; this (or W503) has to stay