MCPcopy
hub / github.com/jtesta/ssh-audit / evaluate

Method evaluate

src/ssh_audit/policy.py:334–464  ·  view source on GitHub ↗

Evaluates a server configuration against this policy. Returns a tuple of a boolean (True if server adheres to policy) and an array of strings that holds error messages.

(self, banner: Optional['Banner'], kex: Optional['SSH2_Kex'])

Source from the content-addressed store, hash-verified

332
333
334 def evaluate(self, banner: Optional['Banner'], kex: Optional['SSH2_Kex']) -> Tuple[bool, List[Dict[str, str]], str]:
335 '''Evaluates a server configuration against this policy. Returns a tuple of a boolean (True if server adheres to policy) and an array of strings that holds error messages.'''
336
337 ret = True
338
339 banner_str = str(banner)
340 if (self._banner is not None) and (banner_str != self._banner):
341 ret = False
342 self._append_error('Banner', [self._banner], None, [banner_str])
343
344 # All subsequent tests require a valid kex, so end here if we don't have one.
345 if kex is None:
346 error_list, error_str = self._get_errors()
347 return ret, error_list, error_str
348
349 if (self._compressions is not None) and (kex.server.compression != self._compressions):
350 ret = False
351 self._append_error('Compression', self._compressions, None, kex.server.compression)
352
353 # If a list of optional host keys was given in the policy, remove any of its entries from the list retrieved from the server. This allows us to do an exact comparison with the expected list below.
354 pruned_host_keys = kex.key_algorithms
355 if self._optional_host_keys is not None:
356 pruned_host_keys = [x for x in kex.key_algorithms if x not in self._optional_host_keys]
357
358 # Check host keys.
359 if self._host_keys is not None:
360 # If the policy allows subsets and re-ordered algorithms...
361 if self._allow_algorithm_subset_and_reordering:
362 for hostkey_t in kex.key_algorithms:
363 if hostkey_t not in self._host_keys:
364 ret = False
365 self._append_error('Host keys', self._host_keys, self._optional_host_keys, kex.key_algorithms)
366 break
367 # The policy requires exact matching of algorithms.
368 elif pruned_host_keys != self._host_keys:
369 ret = False
370 self._append_error('Host keys', self._host_keys, self._optional_host_keys, kex.key_algorithms)
371
372 # Check host key sizes.
373 if self._hostkey_sizes is not None:
374 hostkey_types = list(self._hostkey_sizes.keys())
375 hostkey_types.sort() # Sorted to make testing output repeatable.
376 for hostkey_type in hostkey_types:
377 expected_hostkey_size = cast(int, self._hostkey_sizes[hostkey_type]['hostkey_size'])
378 server_host_keys = kex.host_keys()
379 if hostkey_type in server_host_keys:
380 actual_hostkey_size = cast(int, server_host_keys[hostkey_type]['hostkey_size'])
381 if (self._allow_larger_keys and actual_hostkey_size < expected_hostkey_size) or \
382 (not self._allow_larger_keys and actual_hostkey_size != expected_hostkey_size):
383 ret = False
384 self._append_error('Host key (%s) sizes' % hostkey_type, [str(expected_hostkey_size)], None, [str(actual_hostkey_size)])
385
386 # If we have expected CA signatures set, check them against what the server returned.
387 if self._hostkey_sizes is not None and len(cast(str, self._hostkey_sizes[hostkey_type]['ca_key_type'])) > 0 and cast(int, self._hostkey_sizes[hostkey_type]['ca_key_size']) > 0:
388 expected_ca_key_type = cast(str, self._hostkey_sizes[hostkey_type]['ca_key_type'])
389 expected_ca_key_size = cast(int, self._hostkey_sizes[hostkey_type]['ca_key_size'])
390 actual_ca_key_type = cast(str, server_host_keys[hostkey_type]['ca_key_type'])
391 actual_ca_key_size = cast(int, server_host_keys[hostkey_type]['ca_key_size'])

Calls 4

_append_errorMethod · 0.95
_get_errorsMethod · 0.95
host_keysMethod · 0.80
dh_modulus_sizesMethod · 0.80