Split ssh_audit.py into separate files (#47).

This commit is contained in:
Joe Testa
2020-10-15 14:34:23 -04:00
parent e9df9ee45c
commit 1a5c0e7fad
44 changed files with 4098 additions and 3185 deletions

View File

@ -1,18 +1,22 @@
import pytest
from ssh_audit.algorithm import Algorithm
from ssh_audit.timeframe import Timeframe
# pylint: disable=attribute-defined-outside-init
class TestSSHAlgorithm:
class TestAlgorithm:
@pytest.fixture(autouse=True)
def init(self, ssh_audit):
self.ssh = ssh_audit.SSH
self.algorithm = Algorithm
self.timeframe = Timeframe
def _tf(self, v, s=None):
return self.ssh.Algorithm.Timeframe().update(v, s)
return self.timeframe().update(v, s)
def test_get_ssh_version(self):
def ver(v):
return self.ssh.Algorithm.get_ssh_version(v)
return self.algorithm.get_ssh_version(v)
assert ver('7.5') == ('OpenSSH', '7.5', False)
assert ver('7.5C') == ('OpenSSH', '7.5', True)
@ -22,7 +26,7 @@ class TestSSHAlgorithm:
def test_get_since_text(self):
def gst(v):
return self.ssh.Algorithm.get_since_text(v)
return self.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)'

View File

@ -1,4 +1,5 @@
import pytest
from ssh_audit.ssh_audit import process_commandline
# pylint: disable=attribute-defined-outside-init
@ -7,6 +8,7 @@ class TestAuditConf:
def init(self, ssh_audit):
self.AuditConf = ssh_audit.AuditConf
self.usage = ssh_audit.usage
self.process_commandline = process_commandline
@staticmethod
def _test_conf(conf, **kwargs):
@ -123,9 +125,9 @@ class TestAuditConf:
conf.level = level
excinfo.match(r'.*invalid level.*')
def test_audit_conf_cmdline(self):
def test_audit_conf_process_commandline(self):
# pylint: disable=too-many-statements
c = lambda x: self.AuditConf.from_cmdline(x.split(), self.usage) # noqa
c = lambda x: self.process_commandline(x.split(), self.usage) # noqa
with pytest.raises(SystemExit):
conf = c('')
with pytest.raises(SystemExit):

View File

@ -1,14 +1,16 @@
import pytest
from ssh_audit.banner import Banner
# pylint: disable=line-too-long,attribute-defined-outside-init
class TestBanner:
@pytest.fixture(autouse=True)
def init(self, ssh_audit):
self.ssh = ssh_audit.SSH
self.banner = Banner
def test_simple_banners(self):
banner = lambda x: self.ssh.Banner.parse(x) # noqa
banner = lambda x: self.banner.parse(x) # noqa
b = banner('SSH-2.0-OpenSSH_7.3')
assert b.protocol == (2, 0)
assert b.software == 'OpenSSH_7.3'
@ -26,12 +28,12 @@ class TestBanner:
assert str(b) == 'SSH-1.5-Cisco-1.25'
def test_invalid_banners(self):
b = lambda x: self.ssh.Banner.parse(x) # noqa
b = lambda x: self.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
b = lambda x: self.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
@ -42,7 +44,7 @@ class TestBanner:
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
b = lambda x: self.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
@ -53,13 +55,13 @@ class TestBanner:
assert str(b('SSH-2.0-')) == 'SSH-2.0-'
def test_banners_with_comments(self):
b = lambda x: self.ssh.Banner.parse(x) # noqa
b = lambda x: self.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
b = lambda x: self.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'

View File

@ -1,13 +1,16 @@
import re
import pytest
from ssh_audit.readbuf import ReadBuf
from ssh_audit.writebuf import WriteBuf
# pylint: disable=attribute-defined-outside-init,bad-whitespace
class TestBuffer:
@pytest.fixture(autouse=True)
def init(self, ssh_audit):
self.rbuf = ssh_audit.ReadBuf
self.wbuf = ssh_audit.WriteBuf
self.rbuf = ReadBuf
self.wbuf = WriteBuf
self.utf8rchar = b'\xef\xbf\xbd'
@classmethod

View File

@ -1,17 +1,19 @@
import os
import pytest
from ssh_audit.ssh2_kex import SSH2_Kex
from ssh_audit.ssh2_kexparty import SSH2_KexParty
@pytest.fixture
def kex(ssh_audit):
kex_algs, key_algs = [], []
enc, mac, compression, languages = [], [], ['none'], []
cli = ssh_audit.SSH2.KexParty(enc, mac, compression, languages)
cli = SSH2_KexParty(enc, mac, compression, languages)
enc, mac, compression, languages = [], [], ['none'], []
srv = ssh_audit.SSH2.KexParty(enc, mac, compression, languages)
srv = SSH2_KexParty(enc, mac, compression, languages)
cookie = os.urandom(16)
kex = ssh_audit.SSH2.Kex(cookie, kex_algs, key_algs, cli, srv, 0)
kex = SSH2_Kex(cookie, kex_algs, key_algs, cli, srv, 0)
return kex

View File

@ -2,13 +2,17 @@ import hashlib
import pytest
from datetime import date
from ssh_audit.policy import Policy
from ssh_audit.ssh2_kex import SSH2_Kex
from ssh_audit.writebuf import WriteBuf
class TestPolicy:
@pytest.fixture(autouse=True)
def init(self, ssh_audit):
self.Policy = ssh_audit.Policy
self.wbuf = ssh_audit.WriteBuf
self.ssh2 = ssh_audit.SSH2
self.Policy = Policy
self.wbuf = WriteBuf
self.ssh2_kex = SSH2_Kex
def _get_kex(self):
@ -28,7 +32,7 @@ class TestPolicy:
w.write_list([''])
w.write_byte(False)
w.write_int(0)
return self.ssh2.Kex.parse(w.write_flush())
return self.ssh2_kex.parse(w.write_flush())
def test_policy_basic(self):

View File

@ -8,7 +8,7 @@ class TestResolve:
def init(self, ssh_audit):
self.AuditConf = ssh_audit.AuditConf
self.audit = ssh_audit.audit
self.ssh = ssh_audit.SSH
self.ssh_socket = ssh_audit.SSH_Socket
def _conf(self):
conf = self.AuditConf('localhost', 22)
@ -19,7 +19,7 @@ class TestResolve:
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)
s = self.ssh_socket('localhost', 22)
conf = self._conf()
output_spy.begin()
with pytest.raises(SystemExit):
@ -31,7 +31,7 @@ class TestResolve:
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)
s = self.ssh_socket('localhost', 22)
conf = self._conf()
output_spy.begin()
r = list(s._resolve(conf.ipvo))
@ -40,13 +40,13 @@ class TestResolve:
def test_resolve_ipv4(self, virtual_socket):
conf = self._conf()
conf.ipv4 = True
s = self.ssh.Socket('localhost', 22)
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)
s = self.ssh_socket('localhost', 22)
conf = self._conf()
conf.ipv6 = True
r = list(s._resolve(conf.ipvo))
@ -54,7 +54,7 @@ class TestResolve:
assert r[0] == (socket.AF_INET6, ('::1', 22))
def test_resolve_ipv46_both(self, virtual_socket):
s = self.ssh.Socket('localhost', 22)
s = self.ssh_socket('localhost', 22)
conf = self._conf()
r = list(s._resolve(conf.ipvo))
assert len(r) == 2
@ -62,7 +62,7 @@ class TestResolve:
assert r[1] == (socket.AF_INET6, ('::1', 22))
def test_resolve_ipv46_order(self, virtual_socket):
s = self.ssh.Socket('localhost', 22)
s = self.ssh_socket('localhost', 22)
conf = self._conf()
conf.ipv4 = True
conf.ipv6 = True

View File

@ -1,28 +1,30 @@
import pytest
from ssh_audit.ssh_socket import SSH_Socket
# pylint: disable=attribute-defined-outside-init
class TestSocket:
@pytest.fixture(autouse=True)
def init(self, ssh_audit):
self.ssh = ssh_audit.SSH
self.ssh_socket = SSH_Socket
def test_invalid_host(self, virtual_socket):
with pytest.raises(ValueError):
self.ssh.Socket(None, 22)
self.ssh_socket(None, 22)
def test_invalid_port(self, virtual_socket):
with pytest.raises(ValueError):
self.ssh.Socket('localhost', 'abc')
self.ssh_socket('localhost', 'abc')
with pytest.raises(ValueError):
self.ssh.Socket('localhost', -1)
self.ssh_socket('localhost', -1)
with pytest.raises(ValueError):
self.ssh.Socket('localhost', 0)
self.ssh_socket('localhost', 0)
with pytest.raises(ValueError):
self.ssh.Socket('localhost', 65536)
self.ssh_socket('localhost', 65536)
def test_not_connected_socket(self, virtual_socket):
sock = self.ssh.Socket('localhost', 22)
sock = self.ssh_socket('localhost', 22)
banner, header, err = sock.get_banner()
assert banner is None
assert len(header) == 0

View File

@ -1,21 +1,25 @@
import pytest
from ssh_audit.banner import Banner
from ssh_audit.software import Software
# pylint: disable=line-too-long,attribute-defined-outside-init
class TestSoftware:
@pytest.fixture(autouse=True)
def init(self, ssh_audit):
self.ssh = ssh_audit.SSH
self.software = Software
self.banner = Banner
def test_unknown_software(self):
ps = lambda x: self.ssh.Software.parse(self.ssh.Banner.parse(x)) # noqa
ps = lambda x: self.software.parse(self.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
ps = lambda x: self.software.parse(self.banner.parse(x)) # noqa
# common
s = ps('SSH-2.0-OpenSSH_7.3')
assert s.vendor is None
@ -102,7 +106,7 @@ class TestSoftware:
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
ps = lambda x: self.software.parse(self.banner.parse(x)) # noqa
# common
s = ps('SSH-2.0-dropbear_2016.74')
assert s.vendor is None
@ -153,7 +157,7 @@ class TestSoftware:
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
ps = lambda x: self.software.parse(self.banner.parse(x)) # noqa
# common
s = ps('SSH-2.0-libssh-0.2')
assert s.vendor is None
@ -179,7 +183,7 @@ class TestSoftware:
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
ps = lambda x: self.software.parse(self.banner.parse(x)) # noqa
# common
s = ps('SSH-2.0-RomSShell_5.40')
assert s.vendor == 'Allegro Software'
@ -194,7 +198,7 @@ class TestSoftware:
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
ps = lambda x: self.software.parse(self.banner.parse(x)) # noqa
# common
s = ps('SSH-2.0-mpSSH_0.2.1')
assert s.vendor == 'HP'
@ -209,7 +213,7 @@ class TestSoftware:
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
ps = lambda x: self.software.parse(self.banner.parse(x)) # noqa
# common
s = ps('SSH-1.5-Cisco-1.25')
assert s.vendor == 'Cisco'
@ -224,7 +228,7 @@ class TestSoftware:
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
ps = lambda x: self.software.parse(self.banner.parse(x)) # noqa
# unknown
s = ps('SSH-2.0-OpenSSH_3.7.1 MegaOperatingSystem 123')
assert s.os is None

View File

@ -1,17 +1,28 @@
import struct
import pytest
from ssh_audit.auditconf import AuditConf
from ssh_audit.fingerprint import Fingerprint
from ssh_audit.protocol import Protocol
from ssh_audit.readbuf import ReadBuf
from ssh_audit.ssh1 import SSH1
from ssh_audit.ssh1_publickeymessage import SSH1_PublicKeyMessage
from ssh_audit.ssh_audit import audit
from ssh_audit.writebuf import WriteBuf
# pylint: disable=line-too-long,attribute-defined-outside-init
class TestSSH1:
@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
self.protocol = Protocol
self.ssh1 = SSH1
self.PublicKeyMessage = SSH1_PublicKeyMessage
self.rbuf = ReadBuf
self.wbuf = WriteBuf
self.audit = audit
self.AuditConf = AuditConf
self.fingerprint = Fingerprint
def _conf(self):
conf = self.AuditConf('localhost', 22)
@ -59,7 +70,7 @@ class TestSSH1:
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)
fp = self.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'
@ -83,7 +94,7 @@ class TestSSH1:
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)
fp = self.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'
@ -91,32 +102,32 @@ class TestSSH1:
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)
pkm = self.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)
pkm = self.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)
pkm = self.PublicKeyMessage(cookie, skey, hkey2, pflags, cmask, amask)
def test_pkm_read(self):
pkm = self.ssh1.PublicKeyMessage.parse(self._pkm_payload())
pkm = self.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())
pkm1 = self.PublicKeyMessage(cookie, skey, hkey, pflags, cmask, amask)
pkm2 = self.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_byte(self.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()))
@ -128,7 +139,7 @@ class TestSSH1:
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_byte(self.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()))
@ -142,7 +153,7 @@ class TestSSH1:
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_byte(self.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))

View File

@ -2,17 +2,26 @@ import os
import struct
import pytest
from ssh_audit.auditconf import AuditConf
from ssh_audit.protocol import Protocol
from ssh_audit.readbuf import ReadBuf
from ssh_audit.ssh2_kex import SSH2_Kex
from ssh_audit.ssh2_kexparty import SSH2_KexParty
from ssh_audit.ssh_audit import audit
from ssh_audit.writebuf import WriteBuf
# pylint: disable=line-too-long,attribute-defined-outside-init
class TestSSH2:
@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
self.protocol = Protocol
self.ssh2_kex = SSH2_Kex
self.ssh2_kexparty = SSH2_KexParty
self.rbuf = ReadBuf
self.wbuf = WriteBuf
self.audit = audit
self.AuditConf = AuditConf
def _conf(self):
conf = self.AuditConf('localhost', 22)
@ -51,7 +60,7 @@ class TestSSH2:
return w.write_flush()
def test_kex_read(self):
kex = self.ssh2.Kex.parse(self._kex_payload())
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 == ['bogus_kex1', 'bogus_kex2']
@ -72,12 +81,12 @@ class TestSSH2:
def _get_empty_kex(self, cookie=None):
kex_algs, key_algs = [], []
enc, mac, compression, languages = [], [], ['none'], []
cli = self.ssh2.KexParty(enc, mac, compression, languages)
cli = self.ssh2_kexparty(enc, mac, compression, languages)
enc, mac, compression, languages = [], [], ['none'], []
srv = self.ssh2.KexParty(enc, mac, compression, languages)
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)
kex = self.ssh2_kex(cookie, kex_algs, key_algs, cli, srv, 0)
return kex
def _get_kex_variat1(self):
@ -121,13 +130,13 @@ class TestSSH2:
def test_key_payload(self):
kex1 = self._get_kex_variat1()
kex2 = self.ssh2.Kex.parse(self._kex_payload())
kex2 = self.ssh2_kex.parse(self._kex_payload())
assert kex1.payload == kex2.payload
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_byte(self.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()))
@ -139,7 +148,7 @@ class TestSSH2:
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)
w.write_byte(self.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()

View File

@ -1,23 +1,27 @@
import pytest
from ssh_audit.banner import Banner
from ssh_audit.software import Software
# pylint: disable=attribute-defined-outside-init
class TestVersionCompare:
@pytest.fixture(autouse=True)
def init(self, ssh_audit):
self.ssh = ssh_audit.SSH
self.software = Software
self.banner = Banner
def get_dropbear_software(self, v):
b = self.ssh.Banner.parse('SSH-2.0-dropbear_{}'.format(v))
return self.ssh.Software.parse(b)
b = self.banner.parse('SSH-2.0-dropbear_{}'.format(v))
return self.software.parse(b)
def get_openssh_software(self, v):
b = self.ssh.Banner.parse('SSH-2.0-OpenSSH_{}'.format(v))
return self.ssh.Software.parse(b)
b = self.banner.parse('SSH-2.0-OpenSSH_{}'.format(v))
return self.software.parse(b)
def get_libssh_software(self, v):
b = self.ssh.Banner.parse('SSH-2.0-libssh-{}'.format(v))
return self.ssh.Software.parse(b)
b = self.banner.parse('SSH-2.0-libssh-{}'.format(v))
return self.software.parse(b)
def test_dropbear_compare_version_pre_years(self):
s = self.get_dropbear_software('0.44')