mirror of
				https://github.com/jtesta/ssh-audit.git
				synced 2025-10-30 13:05:26 +01:00 
			
		
		
		
	Converted tab indents to spaces.
This commit is contained in:
		
							
								
								
									
										5893
									
								
								ssh-audit.py
									
									
									
									
									
								
							
							
						
						
									
										5893
									
								
								ssh-audit.py
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										214
									
								
								test/conftest.py
									
									
									
									
									
								
							
							
						
						
									
										214
									
								
								test/conftest.py
									
									
									
									
									
								
							| @@ -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 | ||||
|   | ||||
| @@ -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') | ||||
|   | ||||
| @@ -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' | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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] | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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)) | ||||
|   | ||||
| @@ -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' | ||||
|   | ||||
| @@ -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))>' | ||||
|   | ||||
| @@ -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] | ||||
|   | ||||
| @@ -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] | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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] | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
							
								
								
									
										8
									
								
								tox.ini
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								tox.ini
									
									
									
									
									
								
							| @@ -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 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Joe Testa
					Joe Testa