mirror of
https://github.com/jtesta/ssh-audit.git
synced 2025-06-22 02:33:40 +02:00
Split ssh_audit.py into separate files (#47).
This commit is contained in:
@ -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)'
|
@ -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):
|
||||
|
@ -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'
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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):
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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))
|
||||
|
@ -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()
|
||||
|
@ -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')
|
||||
|
Reference in New Issue
Block a user