mirror of
				https://github.com/jtesta/ssh-audit.git
				synced 2025-10-30 21:15:27 +01:00 
			
		
		
		
	Recognize libssh (software, history, compatibility, security, etc). Closes #8.
This commit is contained in:
		
							
								
								
									
										102
									
								
								ssh-audit.py
									
									
									
									
									
								
							
							
						
						
									
										102
									
								
								ssh-audit.py
									
									
									
									
									
								
							| @@ -472,6 +472,7 @@ class SSH(object): | ||||
| 	class Product(object): | ||||
| 		OpenSSH = 'OpenSSH' | ||||
| 		DropbearSSH = 'Dropbear SSH' | ||||
| 		LibSSH = 'libssh' | ||||
| 	 | ||||
| 	class Software(object): | ||||
| 		def __init__(self, vendor, product, version, patch, os): | ||||
| @@ -632,6 +633,12 @@ class SSH(object): | ||||
| 				v = None | ||||
| 				os = cls._extract_os(banner.comments) | ||||
| 				return cls(v, p, mx.group(1), patch, os) | ||||
| 			mx = re.match(r'^libssh-([\d\.]+\d+)(.*)', software) | ||||
| 			if mx: | ||||
| 				patch = cls._fix_patch(mx.group(2)) | ||||
| 				v, p = None, SSH.Product.LibSSH | ||||
| 				os = cls._extract_os(banner.comments) | ||||
| 				return cls(v, p, mx.group(1), patch, os) | ||||
| 			mx = re.match(r'^RomSShell_([\d\.]+\d+)(.*)', software) | ||||
| 			if mx: | ||||
| 				patch = cls._fix_patch(mx.group(2)) | ||||
| @@ -718,21 +725,34 @@ class SSH(object): | ||||
| 	class Security(object): | ||||
| 		CVE = { | ||||
| 			'Dropbear SSH': [ | ||||
| 				['0.44', '2015.71', 1, 'CVE-2016-3116', 5.5, 'bypass command restrictions via xauth command injection.'], | ||||
| 				['0.28', '2013.58', 1, 'CVE-2013-4434', 5.0, 'discover valid usernames through different time delays.'], | ||||
| 				['0.28', '2013.58', 1, 'CVE-2013-4421', 5.0, 'cause DoS (memory consumption) via a compressed packet.'], | ||||
| 				['0.52', '2011.54', 1, 'CVE-2012-0920', 7.1, 'execute arbitrary code or bypass command restrictions.'], | ||||
| 				['0.40', '0.48.1',  1, 'CVE-2007-1099', 7.5, 'conduct a MitM attack (no warning for hostkey mismatch).'], | ||||
| 				['0.28', '0.47',    1, 'CVE-2006-1206', 7.5, 'cause DoS (slot exhaustion) via large number of connections.'], | ||||
| 				['0.39', '0.47',    1, 'CVE-2006-0225', 4.6, 'execute arbitrary commands via scp with crafted filenames.'], | ||||
| 				['0.28', '0.46',    1, 'CVE-2005-4178', 6.5, 'execute arbitrary code via buffer overflow vulnerability.'], | ||||
| 				['0.28', '0.42',    1, 'CVE-2004-2486', 7.5, 'execute arbitrary code via DSS verification code.'], | ||||
| 			] | ||||
| 				['0.44', '2015.71', 1, 'CVE-2016-3116', 5.5, 'bypass command restrictions via xauth command injection'], | ||||
| 				['0.28', '2013.58', 1, 'CVE-2013-4434', 5.0, 'discover valid usernames through different time delays'], | ||||
| 				['0.28', '2013.58', 1, 'CVE-2013-4421', 5.0, 'cause DoS (memory consumption) via a compressed packet'], | ||||
| 				['0.52', '2011.54', 1, 'CVE-2012-0920', 7.1, 'execute arbitrary code or bypass command restrictions'], | ||||
| 				['0.40', '0.48.1',  1, 'CVE-2007-1099', 7.5, 'conduct a MitM attack (no warning for hostkey mismatch)'], | ||||
| 				['0.28', '0.47',    1, 'CVE-2006-1206', 7.5, 'cause DoS (slot exhaustion) via large number of connections'], | ||||
| 				['0.39', '0.47',    1, 'CVE-2006-0225', 4.6, 'execute arbitrary commands via scp with crafted filenames'], | ||||
| 				['0.28', '0.46',    1, 'CVE-2005-4178', 6.5, 'execute arbitrary code via buffer overflow vulnerability'], | ||||
| 				['0.28', '0.42',    1, 'CVE-2004-2486', 7.5, 'execute arbitrary code via DSS verification code']], | ||||
| 			'libssh': [ | ||||
| 				['0.1',   '0.7.2',  1, 'CVE-2016-0739', 4.3, 'conduct a MitM attack (weakness in DH key generation)'], | ||||
| 				['0.5.1', '0.6.4',  1, 'CVE-2015-3146', 5.0, 'cause DoS via kex packets (null pointer dereference)'], | ||||
| 				['0.5.1', '0.6.3',  1, 'CVE-2014-8132', 5.0, 'cause DoS via kex init packet (dangling pointer)'], | ||||
| 				['0.4.7', '0.6.2',  1, 'CVE-2014-0017', 1.9, 'leak data via PRNG state reuse on forking servers'], | ||||
| 				['0.4.7', '0.5.3',  1, 'CVE-2013-0176', 4.3, 'cause DoS via kex packet (null pointer dereference)'], | ||||
| 				['0.4.7', '0.5.2',  1, 'CVE-2012-6063', 7.5, 'cause DoS or execute arbitrary code via sftp (double free)'], | ||||
| 				['0.4.7', '0.5.2',  1, 'CVE-2012-4562', 7.5, 'cause DoS or execute arbitrary code (overflow check)'], | ||||
| 				['0.4.7', '0.5.2',  1, 'CVE-2012-4561', 5.0, 'cause DoS via unspecified vectors (invalid pointer)'], | ||||
| 				['0.4.7', '0.5.2',  1, 'CVE-2012-4560', 7.5, 'cause DoS or execute arbitrary code (buffer overflow)'], | ||||
| 				['0.4.7', '0.5.2',  1, 'CVE-2012-4559', 6.8, 'cause DoS or execute arbitrary code (double free)']] | ||||
| 		} | ||||
| 		TXT = { | ||||
| 			'Dropbear SSH': [ | ||||
| 				['0.28', '0.34', 1, 'remote root exploit', 'remote format string buffer overflow exploit (exploit-db#387).'], | ||||
| 			] | ||||
| 				['0.28', '0.34', 1, 'remote root exploit', 'remote format string buffer overflow exploit (exploit-db#387)']], | ||||
| 			'libssh': [ | ||||
| 				['0.3.3', '0.3.3', 1, 'null pointer check', 'missing null pointer check in "crypt_set_algorithms_server"'], | ||||
| 				['0.3.3', '0.3.3', 1, 'integer overflow',   'integer overflow in "buffer_get_data"'], | ||||
| 				['0.3.3', '0.3.3', 3, 'heap overflow',      'heap overflow in "packet_decrypt"']] | ||||
| 		} | ||||
| 	 | ||||
| 	class Socket(ReadBuf, WriteBuf): | ||||
| @@ -964,29 +984,29 @@ class KexDB(object): | ||||
|  | ||||
| 	ALGORITHMS = { | ||||
| 		'kex': { | ||||
| 			'diffie-hellman-group1-sha1': [['2.3.0,d0.28', '6.6', '6.9'], [FAIL_OPENSSH67_UNSAFE, FAIL_OPENSSH70_LOGJAM], [WARN_MODULUS_SIZE, WARN_HASH_WEAK]], | ||||
| 			'diffie-hellman-group14-sha1': [['3.9,d0.53'], [], [WARN_HASH_WEAK]], | ||||
| 			'diffie-hellman-group1-sha1': [['2.3.0,d0.28,l10.2', '6.6', '6.9'], [FAIL_OPENSSH67_UNSAFE, FAIL_OPENSSH70_LOGJAM], [WARN_MODULUS_SIZE, WARN_HASH_WEAK]], | ||||
| 			'diffie-hellman-group14-sha1': [['3.9,d0.53,l10.6.0'], [], [WARN_HASH_WEAK]], | ||||
| 			'diffie-hellman-group14-sha256': [['7.3,d2016.73']], | ||||
| 			'diffie-hellman-group16-sha512': [['7.3,d2016.73']], | ||||
| 			'diffie-hellman-group18-sha512': [['7.3']], | ||||
| 			'diffie-hellman-group-exchange-sha1': [['2.3.0', '6.6', None], [FAIL_OPENSSH67_UNSAFE], [WARN_HASH_WEAK]], | ||||
| 			'diffie-hellman-group-exchange-sha256': [['4.4'], [], [WARN_MODULUS_CUSTOM]], | ||||
| 			'ecdh-sha2-nistp256': [['5.7,d2013.62'], [WARN_CURVES_WEAK]], | ||||
| 			'ecdh-sha2-nistp256': [['5.7,d2013.62,l10.6.0'], [WARN_CURVES_WEAK]], | ||||
| 			'ecdh-sha2-nistp384': [['5.7,d2013.62'], [WARN_CURVES_WEAK]], | ||||
| 			'ecdh-sha2-nistp521': [['5.7,d2013.62'], [WARN_CURVES_WEAK]], | ||||
| 			'curve25519-sha256@libssh.org': [['6.5,d2013.62']], | ||||
| 			'curve25519-sha256@libssh.org': [['6.5,d2013.62,l10.6.0']], | ||||
| 			'kexguess2@matt.ucc.asn.au': [['d2013.57']], | ||||
| 		}, | ||||
| 		'key': { | ||||
| 			'rsa-sha2-256': [['7.2']], | ||||
| 			'rsa-sha2-512': [['7.2']], | ||||
| 			'ssh-ed25519': [['6.5']], | ||||
| 			'ssh-ed25519': [['6.5,l10.7.0']], | ||||
| 			'ssh-ed25519-cert-v01@openssh.com': [['6.5']], | ||||
| 			'ssh-rsa': [['2.5.0,d0.28']], | ||||
| 			'ssh-dss': [['2.1.0,d0.28', '6.9'], [FAIL_OPENSSH70_WEAK], [WARN_MODULUS_SIZE, WARN_RNDSIG_KEY]], | ||||
| 			'ecdsa-sha2-nistp256': [['5.7,d2013.62'], [WARN_CURVES_WEAK], [WARN_RNDSIG_KEY]], | ||||
| 			'ecdsa-sha2-nistp384': [['5.7,d2013.62'], [WARN_CURVES_WEAK], [WARN_RNDSIG_KEY]], | ||||
| 			'ecdsa-sha2-nistp521': [['5.7,d2013.62'], [WARN_CURVES_WEAK], [WARN_RNDSIG_KEY]], | ||||
| 			'ssh-rsa': [['2.5.0,d0.28,l10.2']], | ||||
| 			'ssh-dss': [['2.1.0,d0.28,l10.2', '6.9'], [FAIL_OPENSSH70_WEAK], [WARN_MODULUS_SIZE, WARN_RNDSIG_KEY]], | ||||
| 			'ecdsa-sha2-nistp256': [['5.7,d2013.62,l10.6.4'], [WARN_CURVES_WEAK], [WARN_RNDSIG_KEY]], | ||||
| 			'ecdsa-sha2-nistp384': [['5.7,d2013.62,l10.6.4'], [WARN_CURVES_WEAK], [WARN_RNDSIG_KEY]], | ||||
| 			'ecdsa-sha2-nistp521': [['5.7,d2013.62,l10.6.4'], [WARN_CURVES_WEAK], [WARN_RNDSIG_KEY]], | ||||
| 			'ssh-rsa-cert-v00@openssh.com': [['5.4', '6.9'], [FAIL_OPENSSH70_LEGACY], []], | ||||
| 			'ssh-dss-cert-v00@openssh.com': [['5.4', '6.9'], [FAIL_OPENSSH70_LEGACY], [WARN_MODULUS_SIZE, WARN_RNDSIG_KEY]], | ||||
| 			'ssh-rsa-cert-v01@openssh.com': [['5.6']], | ||||
| @@ -996,10 +1016,10 @@ class KexDB(object): | ||||
| 			'ecdsa-sha2-nistp521-cert-v01@openssh.com': [['5.7'], [WARN_CURVES_WEAK], [WARN_RNDSIG_KEY]], | ||||
| 		}, | ||||
| 		'enc': { | ||||
| 			'none': [['1.2.2,d2013.56'], [FAIL_PLAINTEXT]], | ||||
| 			'3des-cbc': [['1.2.2,d0.28', '6.6', None], [FAIL_OPENSSH67_UNSAFE], [WARN_CIPHER_WEAK, WARN_CIPHER_MODE, WARN_BLOCK_SIZE]], | ||||
| 			'none': [['1.2.2,d2013.56,l10.2'], [FAIL_PLAINTEXT]], | ||||
| 			'3des-cbc': [['1.2.2,d0.28,l10.2', '6.6', None], [FAIL_OPENSSH67_UNSAFE], [WARN_CIPHER_WEAK, WARN_CIPHER_MODE, WARN_BLOCK_SIZE]], | ||||
| 			'3des-ctr': [['d0.52']], | ||||
| 			'blowfish-cbc': [['1.2.2,d0.28', '6.6,d0.52', '7.1,d0.52'], [FAIL_OPENSSH67_UNSAFE, FAIL_DBEAR53_DISABLED], [WARN_OPENSSH72_LEGACY, WARN_CIPHER_MODE, WARN_BLOCK_SIZE]], | ||||
| 			'blowfish-cbc': [['1.2.2,d0.28,l10.2', '6.6,d0.52', '7.1,d0.52'], [FAIL_OPENSSH67_UNSAFE, FAIL_DBEAR53_DISABLED], [WARN_OPENSSH72_LEGACY, WARN_CIPHER_MODE, WARN_BLOCK_SIZE]], | ||||
| 			'twofish-cbc': [['d0.28', 'd2014.66'], [FAIL_DBEAR67_DISABLED], [WARN_CIPHER_MODE]], | ||||
| 			'twofish128-cbc': [['d0.47', 'd2014.66'], [FAIL_DBEAR67_DISABLED], [WARN_CIPHER_MODE]], | ||||
| 			'twofish256-cbc': [['d0.47', 'd2014.66'], [FAIL_DBEAR67_DISABLED], [WARN_CIPHER_MODE]], | ||||
| @@ -1009,27 +1029,27 @@ class KexDB(object): | ||||
| 			'arcfour': [['2.1.0', '6.6', '7.1'], [FAIL_OPENSSH67_UNSAFE], [WARN_OPENSSH72_LEGACY, WARN_CIPHER_WEAK]], | ||||
| 			'arcfour128': [['4.2', '6.6', '7.1'], [FAIL_OPENSSH67_UNSAFE], [WARN_OPENSSH72_LEGACY, WARN_CIPHER_WEAK]], | ||||
| 			'arcfour256': [['4.2', '6.6', '7.1'], [FAIL_OPENSSH67_UNSAFE], [WARN_OPENSSH72_LEGACY, WARN_CIPHER_WEAK]], | ||||
| 			'aes128-cbc': [['2.3.0,d0.28', '6.6', None], [FAIL_OPENSSH67_UNSAFE], [WARN_CIPHER_MODE]], | ||||
| 			'aes192-cbc': [['2.3.0', '6.6', None], [FAIL_OPENSSH67_UNSAFE], [WARN_CIPHER_MODE]], | ||||
| 			'aes256-cbc': [['2.3.0,d0.47', '6.6', None], [FAIL_OPENSSH67_UNSAFE], [WARN_CIPHER_MODE]], | ||||
| 			'aes128-cbc': [['2.3.0,d0.28,l10.2', '6.6', None], [FAIL_OPENSSH67_UNSAFE], [WARN_CIPHER_MODE]], | ||||
| 			'aes192-cbc': [['2.3.0,l10.2', '6.6', None], [FAIL_OPENSSH67_UNSAFE], [WARN_CIPHER_MODE]], | ||||
| 			'aes256-cbc': [['2.3.0,d0.47,l10.2', '6.6', None], [FAIL_OPENSSH67_UNSAFE], [WARN_CIPHER_MODE]], | ||||
| 			'rijndael128-cbc': [['2.3.0', '3.0.2'], [FAIL_OPENSSH31_REMOVE], [WARN_CIPHER_MODE]], | ||||
| 			'rijndael192-cbc': [['2.3.0', '3.0.2'], [FAIL_OPENSSH31_REMOVE], [WARN_CIPHER_MODE]], | ||||
| 			'rijndael256-cbc': [['2.3.0', '3.0.2'], [FAIL_OPENSSH31_REMOVE], [WARN_CIPHER_MODE]], | ||||
| 			'rijndael-cbc@lysator.liu.se': [['2.3.0', '6.6', '7.1'], [FAIL_OPENSSH67_UNSAFE], [WARN_OPENSSH72_LEGACY, WARN_CIPHER_MODE]], | ||||
| 			'aes128-ctr': [['3.7,d0.52']], | ||||
| 			'aes192-ctr': [['3.7']], | ||||
| 			'aes256-ctr': [['3.7,d0.52']], | ||||
| 			'aes128-ctr': [['3.7,d0.52,l10.4.1']], | ||||
| 			'aes192-ctr': [['3.7,l10.4.1']], | ||||
| 			'aes256-ctr': [['3.7,d0.52,l10.4.1']], | ||||
| 			'aes128-gcm@openssh.com': [['6.2']], | ||||
| 			'aes256-gcm@openssh.com': [['6.2']], | ||||
| 			'chacha20-poly1305@openssh.com': [['6.5'], [], [], [INFO_OPENSSH69_CHACHA]], | ||||
| 		}, | ||||
| 		'mac': { | ||||
| 			'none': [['d2013.56'], [FAIL_PLAINTEXT]], | ||||
| 			'hmac-sha1': [['2.1.0,d0.28'], [], [WARN_ENCRYPT_AND_MAC, WARN_HASH_WEAK]], | ||||
| 			'hmac-sha1': [['2.1.0,d0.28,l10.2'], [], [WARN_ENCRYPT_AND_MAC, WARN_HASH_WEAK]], | ||||
| 			'hmac-sha1-96': [['2.5.0,d0.47', '6.6', '7.1'], [FAIL_OPENSSH67_UNSAFE], [WARN_OPENSSH72_LEGACY, WARN_ENCRYPT_AND_MAC, WARN_HASH_WEAK]], | ||||
| 			'hmac-sha2-256': [['5.9,d2013.56'], [], [WARN_ENCRYPT_AND_MAC]], | ||||
| 			'hmac-sha2-256': [['5.9,d2013.56,l10.7.0'], [], [WARN_ENCRYPT_AND_MAC]], | ||||
| 			'hmac-sha2-256-96': [['5.9', '6.0'], [FAIL_OPENSSH61_REMOVE], [WARN_ENCRYPT_AND_MAC]], | ||||
| 			'hmac-sha2-512': [['5.9,d2013.56'], [], [WARN_ENCRYPT_AND_MAC]], | ||||
| 			'hmac-sha2-512': [['5.9,d2013.56,l10.7.0'], [], [WARN_ENCRYPT_AND_MAC]], | ||||
| 			'hmac-sha2-512-96': [['5.9', '6.0'], [FAIL_OPENSSH61_REMOVE], [WARN_ENCRYPT_AND_MAC]], | ||||
| 			'hmac-md5': [['2.1.0,d0.28', '6.6', '7.1'], [FAIL_OPENSSH67_UNSAFE], [WARN_OPENSSH72_LEGACY, WARN_ENCRYPT_AND_MAC, WARN_HASH_WEAK]], | ||||
| 			'hmac-md5-96': [['2.5.0', '6.6', '7.1'], [FAIL_OPENSSH67_UNSAFE], [WARN_OPENSSH72_LEGACY, WARN_ENCRYPT_AND_MAC, WARN_HASH_WEAK]], | ||||
| @@ -1053,6 +1073,8 @@ class KexDB(object): | ||||
| def get_ssh_version(version_desc): | ||||
| 	if version_desc.startswith('d'): | ||||
| 		return (SSH.Product.DropbearSSH, version_desc[1:]) | ||||
| 	elif version_desc.startswith('l1'): | ||||
| 		return (SSH.Product.LibSSH, version_desc[2:]) | ||||
| 	else: | ||||
| 		return (SSH.Product.OpenSSH, version_desc) | ||||
|  | ||||
| @@ -1116,6 +1138,8 @@ def get_alg_since_text(alg_desc): | ||||
| 		ssh_prefix, ssh_version = get_ssh_version(v) | ||||
| 		if not ssh_version: | ||||
| 			continue | ||||
| 		if ssh_prefix in [SSH.Product.LibSSH]: | ||||
| 			continue | ||||
| 		if ssh_version.endswith('C'): | ||||
| 			ssh_version = '{0} (client only)'.format(ssh_version[:-1]) | ||||
| 		tv.append('{0} {1}'.format(ssh_prefix, ssh_version)) | ||||
| @@ -1142,12 +1166,15 @@ def get_alg_pairs(kex, pkm): | ||||
|  | ||||
| def get_alg_recommendations(software, kex, pkm, for_server=True): | ||||
| 	alg_pairs = get_alg_pairs(kex, pkm) | ||||
| 	vproducts = [SSH.Product.OpenSSH, | ||||
| 	             SSH.Product.DropbearSSH, | ||||
| 	             SSH.Product.LibSSH] | ||||
| 	if software is not None: | ||||
| 		if software.product not in [SSH.Product.OpenSSH, SSH.Product.DropbearSSH]: | ||||
| 		if software.product not in vproducts: | ||||
| 			software = None | ||||
| 	if software is None: | ||||
| 		ssh_timeframe = get_ssh_timeframe(alg_pairs, for_server) | ||||
| 		for product in [SSH.Product.OpenSSH, SSH.Product.DropbearSSH]: | ||||
| 		for product in vproducts: | ||||
| 			if product not in ssh_timeframe: | ||||
| 				continue | ||||
| 			version = ssh_timeframe[product][0] | ||||
| @@ -1302,7 +1329,8 @@ def output_security_sub(sub, software, padlen): | ||||
| 			continue | ||||
| 		target, name = line[2:4] | ||||
| 		is_server, is_client = target & 1 == 1, target & 2 == 2 | ||||
| 		if is_client: | ||||
| 		is_local = target & 4 == 4 | ||||
| 		if not is_server: | ||||
| 			continue | ||||
| 		p = '' if out.batch else ' ' * (padlen - len(name)) | ||||
| 		if sub == 'cve': | ||||
|   | ||||
| @@ -2,10 +2,11 @@ | ||||
| # -*- coding: utf-8 -*- | ||||
| import pytest | ||||
|  | ||||
|  | ||||
| class TestVersionCompare(object): | ||||
| 	@pytest.fixture(autouse=True) | ||||
| 	def init(self, ssh_audit): | ||||
| 		self.ssh = ssh_audit.SSH  | ||||
| 		self.ssh = ssh_audit.SSH | ||||
| 	 | ||||
| 	def get_dropbear_software(self, v): | ||||
| 		b = self.ssh.Banner.parse('SSH-2.0-dropbear_{0}'.format(v)) | ||||
| @@ -15,26 +16,30 @@ class TestVersionCompare(object): | ||||
| 		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 test_dropbear_compare_version_pre_years(self): | ||||
| 		s = self.get_dropbear_software('0.44') | ||||
| 		assert s.compare_version('0.43') > 0 | ||||
| 		assert s.compare_version('0.44') == 0 | ||||
| 		assert s.compare_version('0.45') < 0 | ||||
| 		assert s.between_versions('0.43', '0.45') == True | ||||
| 		assert s.between_versions('0.43', '0.45') | ||||
| 	 | ||||
| 	def test_dropbear_compare_version_with_years(self): | ||||
| 		s = self.get_dropbear_software('2015.71') | ||||
| 		assert s.compare_version('2014.67') > 0 | ||||
| 		assert s.compare_version('2015.71') == 0 | ||||
| 		assert s.compare_version('2016.74') < 0 | ||||
| 		assert s.between_versions('2014.67', '2016.74') == True | ||||
| 		assert s.between_versions('2014.67', '2016.74') | ||||
| 	 | ||||
| 	def test_dropbear_compare_version_mixed(self): | ||||
| 		s = self.get_dropbear_software('0.53.1') | ||||
| 		assert s.compare_version('0.53') > 0 | ||||
| 		assert s.compare_version('0.53.1') == 0 | ||||
| 		assert s.compare_version('2011.54') < 0 | ||||
| 		assert s.between_versions('0.53', '2011.54') == True | ||||
| 		assert s.between_versions('0.53', '2011.54') | ||||
| 	 | ||||
| 	def test_dropbear_compare_version_patchlevel(self): | ||||
| 		s1 = self.get_dropbear_software('0.44') | ||||
| @@ -85,9 +90,8 @@ class TestVersionCompare(object): | ||||
| 		assert s.compare_version('3.7') > 0 | ||||
| 		assert s.compare_version('3.7.1') == 0 | ||||
| 		assert s.compare_version('3.8') < 0 | ||||
| 		assert s.between_versions('3.7', '3.8') == True | ||||
| 		 | ||||
| 		 | ||||
| 		assert s.between_versions('3.7', '3.8') | ||||
| 	 | ||||
| 	def test_openssh_compare_version_patchlevel(self): | ||||
| 		s1 = self.get_openssh_software('2.1.1') | ||||
| 		s2 = self.get_openssh_software('2.1.1p2') | ||||
| @@ -130,3 +134,36 @@ class TestVersionCompare(object): | ||||
| 			if i + 1 < l: | ||||
| 				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('0.2') > 0 | ||||
| 		assert s.compare_version('0.3') == 0 | ||||
| 		assert s.compare_version('0.3.1') < 0 | ||||
| 		assert s.between_versions('0.2', '0.3.1') | ||||
| 	 | ||||
| 	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, 4): | ||||
| 			versions.append('0.7.{0}'.format(i)) | ||||
| 		l = len(versions) | ||||
| 		for i in range(l): | ||||
| 			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 < l: | ||||
| 				vnext = versions[i + 1] | ||||
| 				assert s.compare_version(vnext) < 0 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Andris Raugulis
					Andris Raugulis