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

Function output_fingerprints

src/ssh_audit/ssh_audit.py:288–332  ·  view source on GitHub ↗
(out: OutputBuffer, algs: Algorithms, is_json_output: bool)

Source from the content-addressed store, hash-verified

286
287
288def output_fingerprints(out: OutputBuffer, algs: Algorithms, is_json_output: bool) -> None:
289 with out:
290 fps = {}
291 if algs.ssh1kex is not None:
292 name = 'ssh-rsa1'
293 fp = Fingerprint(algs.ssh1kex.host_key_fingerprint_data)
294 # bits = algs.ssh1kex.host_key_bits
295 fps[name] = fp
296 if algs.ssh2kex is not None:
297 host_keys = algs.ssh2kex.host_keys()
298 for host_key_type in algs.ssh2kex.host_keys():
299 if host_keys[host_key_type] is None:
300 continue
301
302 fp = Fingerprint(cast(bytes, host_keys[host_key_type]['raw_hostkey_bytes']))
303
304 # Workaround for Python's order-indifference in dicts. We might get a random RSA type (ssh-rsa, rsa-sha2-256, or rsa-sha2-512), so running the tool against the same server three times may give three different host key types here. So if we have any RSA type, we will simply hard-code it to 'ssh-rsa'.
305 if host_key_type in HostKeyTest.RSA_FAMILY:
306 host_key_type = 'ssh-rsa'
307
308 # Skip over certificate host types (or we would return invalid fingerprints), and only add one fingerprint in the RSA family.
309 if '-cert-' not in host_key_type:
310 fps[host_key_type] = fp
311 # Similarly, the host keys can be processed in random order due to Python's order-indifference in dicts. So we sort this list before printing; this makes automated testing possible.
312 fp_types = sorted(fps.keys())
313 for fp_type in fp_types:
314 fp = fps[fp_type]
315
316 # Don't output any ECDSA or DSS fingerprints unless verbose mode is enabled.
317 if fp_type.startswith("ecdsa-") or (fp_type == "ssh-dss"):
318 if out.verbose:
319 out.warn('(fin) {}: {} -- [info] this fingerprint type is insecure and should not be relied upon'.format(fp_type, fp.sha256))
320 else:
321 continue # If verbose mode is not enabled, skip this type entirely.
322 else:
323 out.good('(fin) {}: {}'.format(fp_type, fp.sha256))
324
325 # Output the MD5 hash too if verbose mode is enabled.
326 if out.verbose:
327 out.warn('(fin) {}: {} -- [info] do not rely on MD5 fingerprints for server identification; it is insecure for this use case'.format(fp_type, fp.md5))
328
329 if not out.is_section_empty() and not is_json_output:
330 out.head('# fingerprints')
331 out.flush_section()
332 out.sep()
333
334
335# Returns True if no warnings or failures encountered in configuration.

Callers 1

outputFunction · 0.85

Calls 8

FingerprintClass · 0.90
host_keysMethod · 0.80
warnMethod · 0.80
goodMethod · 0.80
is_section_emptyMethod · 0.80
headMethod · 0.80
flush_sectionMethod · 0.80
sepMethod · 0.80

Tested by

no test coverage detected