mirror of
https://github.com/jtesta/ssh-audit.git
synced 2024-12-22 09:05:10 +01:00
Added return values for standard scans.
This commit is contained in:
parent
103b8fb934
commit
49bd2c96a8
@ -28,6 +28,12 @@ GREEN="\033[0;32m"
|
||||
REDB="\033[1;31m" # Red + bold
|
||||
GREENB="\033[1;32m" # Green + bold
|
||||
|
||||
# Program return values.
|
||||
PROGRAM_RETVAL_FAILURE=3
|
||||
PROGRAM_RETVAL_WARNING=2
|
||||
PROGRAM_RETVAL_CONNECTION_ERROR=1
|
||||
PROGRAM_RETVAL_GOOD=0
|
||||
|
||||
|
||||
# Returns 0 if current docker image exists.
|
||||
function check_if_docker_image_exists {
|
||||
@ -353,8 +359,9 @@ function run_dropbear_test {
|
||||
dropbear_version=$1
|
||||
test_number=$2
|
||||
options=$3
|
||||
expected_retval=$4
|
||||
|
||||
run_test 'Dropbear' $dropbear_version $test_number "$options"
|
||||
run_test 'Dropbear' $dropbear_version $test_number "$options" $expected_retval
|
||||
}
|
||||
|
||||
|
||||
@ -363,8 +370,9 @@ function run_dropbear_test {
|
||||
function run_openssh_test {
|
||||
openssh_version=$1
|
||||
test_number=$2
|
||||
expected_retval=$3
|
||||
|
||||
run_test 'OpenSSH' $openssh_version $test_number ''
|
||||
run_test 'OpenSSH' $openssh_version $test_number '' $expected_retval
|
||||
}
|
||||
|
||||
|
||||
@ -373,8 +381,9 @@ function run_openssh_test {
|
||||
function run_tinyssh_test {
|
||||
tinyssh_version=$1
|
||||
test_number=$2
|
||||
expected_retval=$3
|
||||
|
||||
run_test 'TinySSH' $tinyssh_version $test_number ''
|
||||
run_test 'TinySSH' $tinyssh_version $test_number '' $expected_retval
|
||||
}
|
||||
|
||||
|
||||
@ -383,6 +392,7 @@ function run_test {
|
||||
version=$2
|
||||
test_number=$3
|
||||
options=$4
|
||||
expected_retval=$5
|
||||
|
||||
server_exec=
|
||||
test_result_stdout=
|
||||
@ -421,15 +431,17 @@ function run_test {
|
||||
fi
|
||||
|
||||
./ssh-audit.py localhost:2222 > $test_result_stdout
|
||||
if [[ $? != 0 ]]; then
|
||||
echo -e "${REDB}Failed to run ssh-audit.py! (exit code: $?)${CLR}"
|
||||
actual_retval=$?
|
||||
if [[ $actual_retval != $expected_retval ]]; then
|
||||
echo -e "${REDB}Unexpected return value. Expected: ${expected_retval}; Actual: ${actual_retval}${CLR}"
|
||||
docker container stop -t 0 $cid > /dev/null
|
||||
exit 1
|
||||
fi
|
||||
|
||||
./ssh-audit.py -j localhost:2222 > $test_result_json
|
||||
if [[ $? != 0 ]]; then
|
||||
echo -e "${REDB}Failed to run ssh-audit.py! (exit code: $?)${CLR}"
|
||||
actual_retval=$?
|
||||
if [[ $actual_retval != $expected_retval ]]; then
|
||||
echo -e "${REDB}Unexpected return value. Expected: ${expected_retval}; Actual: ${actual_retval}${CLR}"
|
||||
docker container stop -t 0 $cid > /dev/null
|
||||
exit 1
|
||||
fi
|
||||
@ -560,53 +572,53 @@ TEST_RESULT_DIR=`mktemp -d /tmp/ssh-audit_test-results_XXXXXXXXXX`
|
||||
|
||||
# Now run all the tests.
|
||||
echo -e "\nRunning tests..."
|
||||
run_openssh_test '4.0p1' 'test1'
|
||||
run_openssh_test '4.0p1' 'test1' $PROGRAM_RETVAL_FAILURE
|
||||
echo
|
||||
run_openssh_test '5.6p1' 'test1'
|
||||
run_openssh_test '5.6p1' 'test2'
|
||||
run_openssh_test '5.6p1' 'test3'
|
||||
run_openssh_test '5.6p1' 'test4'
|
||||
run_openssh_test '5.6p1' 'test5'
|
||||
run_openssh_test '5.6p1' 'test1' $PROGRAM_RETVAL_FAILURE
|
||||
run_openssh_test '5.6p1' 'test2' $PROGRAM_RETVAL_FAILURE
|
||||
run_openssh_test '5.6p1' 'test3' $PROGRAM_RETVAL_FAILURE
|
||||
run_openssh_test '5.6p1' 'test4' $PROGRAM_RETVAL_FAILURE
|
||||
run_openssh_test '5.6p1' 'test5' $PROGRAM_RETVAL_FAILURE
|
||||
echo
|
||||
run_openssh_test '8.0p1' 'test1'
|
||||
run_openssh_test '8.0p1' 'test2'
|
||||
run_openssh_test '8.0p1' 'test3'
|
||||
run_openssh_test '8.0p1' 'test1' $PROGRAM_RETVAL_FAILURE
|
||||
run_openssh_test '8.0p1' 'test2' $PROGRAM_RETVAL_FAILURE
|
||||
run_openssh_test '8.0p1' 'test3' $PROGRAM_RETVAL_GOOD
|
||||
echo
|
||||
run_dropbear_test '2019.78' 'test1' '-r /etc/dropbear/dropbear_rsa_host_key_1024 -r /etc/dropbear/dropbear_dss_host_key -r /etc/dropbear/dropbear_ecdsa_host_key'
|
||||
run_dropbear_test '2019.78' 'test1' '-r /etc/dropbear/dropbear_rsa_host_key_1024 -r /etc/dropbear/dropbear_dss_host_key -r /etc/dropbear/dropbear_ecdsa_host_key' 3
|
||||
echo
|
||||
run_tinyssh_test '20190101' 'test1'
|
||||
run_tinyssh_test '20190101' 'test1' $PROGRAM_RETVAL_WARNING
|
||||
echo
|
||||
echo
|
||||
run_policy_test 'config1' 'test1' '0'
|
||||
run_policy_test 'config1' 'test2' '1'
|
||||
run_policy_test 'config1' 'test3' '1'
|
||||
run_policy_test 'config1' 'test4' '1'
|
||||
run_policy_test 'config1' 'test5' '1'
|
||||
run_policy_test 'config2' 'test6' '0'
|
||||
run_policy_test 'config1' 'test1' $PROGRAM_RETVAL_GOOD
|
||||
run_policy_test 'config1' 'test2' $PROGRAM_RETVAL_FAILURE
|
||||
run_policy_test 'config1' 'test3' $PROGRAM_RETVAL_FAILURE
|
||||
run_policy_test 'config1' 'test4' $PROGRAM_RETVAL_FAILURE
|
||||
run_policy_test 'config1' 'test5' $PROGRAM_RETVAL_FAILURE
|
||||
run_policy_test 'config2' 'test6' $PROGRAM_RETVAL_GOOD
|
||||
|
||||
# Passing test with host key certificate and CA key certificates.
|
||||
run_policy_test 'config3' 'test7' '0'
|
||||
run_policy_test 'config3' 'test7' $PROGRAM_RETVAL_GOOD
|
||||
|
||||
# Failing test with host key certificate and non-compliant CA key length.
|
||||
run_policy_test 'config3' 'test8' '1'
|
||||
run_policy_test 'config3' 'test8' $PROGRAM_RETVAL_FAILURE
|
||||
|
||||
# Failing test with non-compliant host key certificate and CA key certificate.
|
||||
run_policy_test 'config3' 'test9' '1'
|
||||
run_policy_test 'config3' 'test9' $PROGRAM_RETVAL_FAILURE
|
||||
|
||||
# Failing test with non-compliant host key certificate and non-compliant CA key certificate.
|
||||
run_policy_test 'config3' 'test10' '1'
|
||||
run_policy_test 'config3' 'test10' $PROGRAM_RETVAL_FAILURE
|
||||
|
||||
# Passing test with host key size check.
|
||||
run_policy_test 'config2' 'test11' '0'
|
||||
run_policy_test 'config2' 'test11' $PROGRAM_RETVAL_GOOD
|
||||
|
||||
# Failing test with non-compliant host key size check.
|
||||
run_policy_test 'config2' 'test12' '1'
|
||||
run_policy_test 'config2' 'test12' $PROGRAM_RETVAL_FAILURE
|
||||
|
||||
# Passing test with DH modulus test.
|
||||
run_policy_test 'config2' 'test13' '0'
|
||||
run_policy_test 'config2' 'test13' $PROGRAM_RETVAL_GOOD
|
||||
|
||||
# Failing test with DH modulus test.
|
||||
run_policy_test 'config2' 'test14' '1'
|
||||
run_policy_test 'config2' 'test14' $PROGRAM_RETVAL_FAILURE
|
||||
|
||||
|
||||
# The test functions above will terminate the script on failure, so if we reached here,
|
||||
|
98
ssh-audit.py
98
ssh-audit.py
@ -46,6 +46,12 @@ from typing import Callable, Optional, Union, Any
|
||||
VERSION = 'v2.2.1-dev'
|
||||
SSH_HEADER = 'SSH-{0}-OpenSSH_8.0' # SSH software to impersonate
|
||||
|
||||
# The program return values corresponding to failure(s) encountered, warning(s) encountered, connection errors, and no problems found, respectively.
|
||||
PROGRAM_RETVAL_FAILURE = 3
|
||||
PROGRAM_RETVAL_WARNING = 2
|
||||
PROGRAM_RETVAL_CONNECTION_ERROR = 1
|
||||
PROGRAM_RETVAL_GOOD = 0
|
||||
|
||||
try: # pragma: nocover
|
||||
from colorama import init as colorama_init
|
||||
colorama_init(strip=False) # pragma: nocover
|
||||
@ -2831,17 +2837,19 @@ class KexGroupExchange_SHA256(KexGroupExchange):
|
||||
super(KexGroupExchange_SHA256, self).__init__('KexGroupExchange_SHA256', 'sha256')
|
||||
|
||||
|
||||
def output_algorithms(title: str, alg_db: Dict[str, Dict[str, List[List[Optional[str]]]]], alg_type: str, algorithms: List[str], unknown_algs: List[str], maxlen: int = 0, alg_sizes: Optional[Dict[str, Tuple[int, int]]] = None) -> None:
|
||||
def output_algorithms(title: str, alg_db: Dict[str, Dict[str, List[List[Optional[str]]]]], alg_type: str, algorithms: List[str], unknown_algs: List[str], is_json_output: bool, program_retval: int, maxlen: int = 0, alg_sizes: Optional[Dict[str, Tuple[int, int]]] = None) -> int: # pylint: disable=too-many-arguments
|
||||
with OutputBuffer() as obuf:
|
||||
for algorithm in algorithms:
|
||||
output_algorithm(alg_db, alg_type, algorithm, unknown_algs, maxlen, alg_sizes)
|
||||
if len(obuf) > 0:
|
||||
program_retval = output_algorithm(alg_db, alg_type, algorithm, unknown_algs, program_retval, maxlen, alg_sizes)
|
||||
if len(obuf) > 0 and not is_json_output:
|
||||
out.head('# ' + title)
|
||||
obuf.flush()
|
||||
out.sep()
|
||||
|
||||
return program_retval
|
||||
|
||||
def output_algorithm(alg_db: Dict[str, Dict[str, List[List[Optional[str]]]]], alg_type: str, alg_name: str, unknown_algs: List[str], alg_max_len: int = 0, alg_sizes: Optional[Dict[str, Tuple[int, int]]] = None) -> None:
|
||||
|
||||
def output_algorithm(alg_db: Dict[str, Dict[str, List[List[Optional[str]]]]], alg_type: str, alg_name: str, unknown_algs: List[str], program_retval: int, alg_max_len: int = 0, alg_sizes: Optional[Dict[str, Tuple[int, int]]] = None) -> int:
|
||||
prefix = '(' + alg_type + ') '
|
||||
if alg_max_len == 0:
|
||||
alg_max_len = len(alg_name)
|
||||
@ -2861,7 +2869,7 @@ def output_algorithm(alg_db: Dict[str, Dict[str, List[List[Optional[str]]]]], al
|
||||
|
||||
texts = []
|
||||
if len(alg_name.strip()) == 0:
|
||||
return
|
||||
return program_retval
|
||||
alg_name_native = utils.to_text(alg_name)
|
||||
if alg_name_native in alg_db[alg_type]:
|
||||
alg_desc = alg_db[alg_type][alg_name_native]
|
||||
@ -2887,6 +2895,11 @@ def output_algorithm(alg_db: Dict[str, Dict[str, List[List[Optional[str]]]]], al
|
||||
alg_name = alg_name_with_size if alg_name_with_size is not None else alg_name
|
||||
first = True
|
||||
for level, text in texts:
|
||||
if level == 'fail':
|
||||
program_retval = PROGRAM_RETVAL_FAILURE
|
||||
elif level == 'warn' and program_retval != PROGRAM_RETVAL_FAILURE: # If a failure was found previously, don't downgrade to warning.
|
||||
program_retval = PROGRAM_RETVAL_WARNING
|
||||
|
||||
f = getattr(out, level)
|
||||
comment = (padding + ' -- [' + level + '] ' + text) if text != '' else ''
|
||||
if first:
|
||||
@ -2901,6 +2914,8 @@ def output_algorithm(alg_db: Dict[str, Dict[str, List[List[Optional[str]]]]], al
|
||||
comment = (padding + ' `- [' + level + '] ' + text)
|
||||
f(' ' * len(prefix + alg_name) + comment)
|
||||
|
||||
return program_retval
|
||||
|
||||
|
||||
def output_compatibility(algs: SSH.Algorithms, client_audit: bool, for_server: bool = True) -> None:
|
||||
|
||||
@ -2968,19 +2983,19 @@ def output_security_sub(sub: str, software: Optional[SSH.Software], client_audit
|
||||
out.fail('(sec) {}{} -- {}'.format(name, p, descr))
|
||||
|
||||
|
||||
def output_security(banner: Optional[SSH.Banner], client_audit: bool, padlen: int) -> None:
|
||||
def output_security(banner: Optional[SSH.Banner], client_audit: bool, padlen: int, is_json_output: bool) -> None:
|
||||
with OutputBuffer() as obuf:
|
||||
if banner is not None:
|
||||
software = SSH.Software.parse(banner)
|
||||
output_security_sub('cve', software, client_audit, padlen)
|
||||
output_security_sub('txt', software, client_audit, padlen)
|
||||
if len(obuf) > 0:
|
||||
if len(obuf) > 0 and not is_json_output:
|
||||
out.head('# security')
|
||||
obuf.flush()
|
||||
out.sep()
|
||||
|
||||
|
||||
def output_fingerprints(algs: SSH.Algorithms, sha256: bool = True) -> None:
|
||||
def output_fingerprints(algs: SSH.Algorithms, is_json_output: bool, sha256: bool = True) -> None:
|
||||
with OutputBuffer() as obuf:
|
||||
fps = []
|
||||
if algs.ssh1kex is not None:
|
||||
@ -3011,14 +3026,14 @@ def output_fingerprints(algs: SSH.Algorithms, sha256: bool = True) -> None:
|
||||
# p = '' if out.batch else ' ' * (padlen - len(name))
|
||||
# out.good('(fin) {0}{1} -- {2} {3}'.format(name, p, bits, fpo))
|
||||
out.good('(fin) {}: {}'.format(name, fpo))
|
||||
if len(obuf) > 0:
|
||||
if len(obuf) > 0 and not is_json_output:
|
||||
out.head('# fingerprints')
|
||||
obuf.flush()
|
||||
out.sep()
|
||||
|
||||
|
||||
# Returns True if no warnings or failures encountered in configuration.
|
||||
def output_recommendations(algs: SSH.Algorithms, software: Optional[SSH.Software], padlen: int = 0) -> bool:
|
||||
def output_recommendations(algs: SSH.Algorithms, software: Optional[SSH.Software], is_json_output: bool, padlen: int = 0) -> bool:
|
||||
|
||||
ret = True
|
||||
# PuTTY's algorithms cannot be modified, so there's no point in issuing recommendations.
|
||||
@ -3078,7 +3093,7 @@ def output_recommendations(algs: SSH.Algorithms, software: Optional[SSH.Software
|
||||
b = '(SSH{})'.format(sshv) if sshv == 1 else ''
|
||||
fm = '(rec) {0}{1}{2}-- {3} algorithm to {4}{5} {6}'
|
||||
fn(fm.format(sg, name, p, alg_type, an, chg_additional_info, b))
|
||||
if len(obuf) > 0:
|
||||
if len(obuf) > 0 and not is_json_output:
|
||||
if software is not None:
|
||||
title = '(for {})'.format(software.display(False))
|
||||
else:
|
||||
@ -3090,7 +3105,7 @@ def output_recommendations(algs: SSH.Algorithms, software: Optional[SSH.Software
|
||||
|
||||
|
||||
# Output additional information & notes.
|
||||
def output_info(software: Optional['SSH.Software'], client_audit: bool, any_problems: bool) -> None:
|
||||
def output_info(software: Optional['SSH.Software'], client_audit: bool, any_problems: bool, is_json_output: bool) -> None:
|
||||
with OutputBuffer() as obuf:
|
||||
# Tell user that PuTTY cannot be hardened at the protocol-level.
|
||||
if client_audit and (software is not None) and (software.product == SSH.Product.PuTTY):
|
||||
@ -3100,19 +3115,16 @@ def output_info(software: Optional['SSH.Software'], client_audit: bool, any_prob
|
||||
if any_problems:
|
||||
out.warn('(nfo) For hardening guides on common OSes, please see: <https://www.ssh-audit.com/hardening_guides.html>')
|
||||
|
||||
if len(obuf) > 0:
|
||||
if len(obuf) > 0 and not is_json_output:
|
||||
out.head('# additional info')
|
||||
obuf.flush()
|
||||
out.sep()
|
||||
|
||||
|
||||
def output(aconf: AuditConf, banner: Optional[SSH.Banner], header: List[str], client_host: Optional[str] = None, kex: Optional[SSH2.Kex] = None, pkm: Optional[SSH1.PublicKeyMessage] = None) -> None:
|
||||
|
||||
# If the user requested JSON output, output that and return immediately.
|
||||
if aconf.json:
|
||||
print(json.dumps(build_struct(banner, kex=kex, client_host=client_host), sort_keys=True))
|
||||
return
|
||||
# Returns a PROGRAM_RETVAL_* flag to denote if any failures or warnings were encountered.
|
||||
def output(aconf: AuditConf, banner: Optional[SSH.Banner], header: List[str], client_host: Optional[str] = None, kex: Optional[SSH2.Kex] = None, pkm: Optional[SSH1.PublicKeyMessage] = None) -> int:
|
||||
|
||||
program_retval = PROGRAM_RETVAL_GOOD
|
||||
client_audit = client_host is not None # If set, this is a client audit.
|
||||
sshv = 1 if pkm is not None else 2
|
||||
algs = SSH.Algorithms(pkm, kex)
|
||||
@ -3141,12 +3153,12 @@ def output(aconf: AuditConf, banner: Optional[SSH.Banner], header: List[str], cl
|
||||
else:
|
||||
cmptxt = 'disabled'
|
||||
out.good('(gen) compression: {}'.format(cmptxt))
|
||||
if len(obuf) > 0:
|
||||
if len(obuf) > 0 and not aconf.json: # Print output when it exists and JSON output isn't requested.
|
||||
out.head('# general')
|
||||
obuf.flush()
|
||||
out.sep()
|
||||
maxlen = algs.maxlen + 1
|
||||
output_security(banner, client_audit, maxlen)
|
||||
output_security(banner, client_audit, maxlen, aconf.json)
|
||||
# Filled in by output_algorithms() with unidentified algs.
|
||||
unknown_algorithms = [] # type: List[str]
|
||||
if pkm is not None:
|
||||
@ -3154,29 +3166,33 @@ def output(aconf: AuditConf, banner: Optional[SSH.Banner], header: List[str], cl
|
||||
ciphers = pkm.supported_ciphers
|
||||
auths = pkm.supported_authentications
|
||||
title, atype = 'SSH1 host-key algorithms', 'key'
|
||||
output_algorithms(title, adb, atype, ['ssh-rsa1'], unknown_algorithms, maxlen)
|
||||
program_retval = output_algorithms(title, adb, atype, ['ssh-rsa1'], unknown_algorithms, aconf.json, program_retval, maxlen)
|
||||
title, atype = 'SSH1 encryption algorithms (ciphers)', 'enc'
|
||||
output_algorithms(title, adb, atype, ciphers, unknown_algorithms, maxlen)
|
||||
program_retval = output_algorithms(title, adb, atype, ciphers, unknown_algorithms, aconf.json, program_retval, maxlen)
|
||||
title, atype = 'SSH1 authentication types', 'aut'
|
||||
output_algorithms(title, adb, atype, auths, unknown_algorithms, maxlen)
|
||||
program_retval = output_algorithms(title, adb, atype, auths, unknown_algorithms, aconf.json, program_retval, maxlen)
|
||||
if kex is not None:
|
||||
adb = SSH2.KexDB.ALGORITHMS
|
||||
title, atype = 'key exchange algorithms', 'kex'
|
||||
output_algorithms(title, adb, atype, kex.kex_algorithms, unknown_algorithms, maxlen, kex.dh_modulus_sizes())
|
||||
program_retval = output_algorithms(title, adb, atype, kex.kex_algorithms, unknown_algorithms, aconf.json, program_retval, maxlen, kex.dh_modulus_sizes())
|
||||
title, atype = 'host-key algorithms', 'key'
|
||||
output_algorithms(title, adb, atype, kex.key_algorithms, unknown_algorithms, maxlen, kex.rsa_key_sizes())
|
||||
program_retval = output_algorithms(title, adb, atype, kex.key_algorithms, unknown_algorithms, aconf.json, program_retval, maxlen, kex.rsa_key_sizes())
|
||||
title, atype = 'encryption algorithms (ciphers)', 'enc'
|
||||
output_algorithms(title, adb, atype, kex.server.encryption, unknown_algorithms, maxlen)
|
||||
program_retval = output_algorithms(title, adb, atype, kex.server.encryption, unknown_algorithms, aconf.json, program_retval, maxlen)
|
||||
title, atype = 'message authentication code algorithms', 'mac'
|
||||
output_algorithms(title, adb, atype, kex.server.mac, unknown_algorithms, maxlen)
|
||||
output_fingerprints(algs, True)
|
||||
perfect_config = output_recommendations(algs, software, maxlen)
|
||||
output_info(software, client_audit, not perfect_config)
|
||||
program_retval = output_algorithms(title, adb, atype, kex.server.mac, unknown_algorithms, aconf.json, program_retval, maxlen)
|
||||
output_fingerprints(algs, aconf.json, True)
|
||||
perfect_config = output_recommendations(algs, software, aconf.json, maxlen)
|
||||
output_info(software, client_audit, not perfect_config, aconf.json)
|
||||
|
||||
# If we encountered any unknown algorithms, ask the user to report them.
|
||||
if len(unknown_algorithms) > 0:
|
||||
# If the user requested JSON output, output that and return immediately.
|
||||
if aconf.json:
|
||||
print(json.dumps(build_struct(banner, kex=kex, client_host=client_host), sort_keys=True))
|
||||
elif len(unknown_algorithms) > 0: # If we encountered any unknown algorithms, ask the user to report them.
|
||||
out.warn("\n\n!!! WARNING: unknown algorithm(s) found!: %s. Please email the full output above to the maintainer (jtesta@positronsecurity.com), or create a Github issue at <https://github.com/jtesta/ssh-audit/issues>.\n" % ','.join(unknown_algorithms))
|
||||
|
||||
return program_retval
|
||||
|
||||
|
||||
def evaluate_policy(aconf: AuditConf, banner: Optional['SSH.Banner'], kex: Optional['SSH2.Kex'] = None) -> bool:
|
||||
|
||||
@ -3415,7 +3431,9 @@ def build_struct(banner: Optional['SSH.Banner'], kex: Optional['SSH2.Kex'] = Non
|
||||
return res
|
||||
|
||||
|
||||
# Returns one of the PROGRAM_RETVAL_* flags.
|
||||
def audit(aconf: AuditConf, sshv: Optional[int] = None) -> int:
|
||||
program_retval = PROGRAM_RETVAL_GOOD
|
||||
out.batch = aconf.batch
|
||||
out.verbose = aconf.verbose
|
||||
out.level = aconf.level
|
||||
@ -3461,13 +3479,9 @@ def audit(aconf: AuditConf, sshv: Optional[int] = None) -> int:
|
||||
if err is not None:
|
||||
output(aconf, banner, header)
|
||||
out.fail(err)
|
||||
return 1
|
||||
return PROGRAM_RETVAL_CONNECTION_ERROR
|
||||
if sshv == 1:
|
||||
pkm = SSH1.PublicKeyMessage.parse(payload)
|
||||
if aconf.json:
|
||||
print(json.dumps(build_struct(banner, pkm=pkm), sort_keys=True))
|
||||
else:
|
||||
output(aconf, banner, header, pkm=pkm)
|
||||
program_retval = output(aconf, banner, header, pkm=SSH1.PublicKeyMessage.parse(payload))
|
||||
elif sshv == 2:
|
||||
kex = SSH2.Kex.parse(payload)
|
||||
if aconf.client_audit is False:
|
||||
@ -3476,11 +3490,11 @@ def audit(aconf: AuditConf, sshv: Optional[int] = None) -> int:
|
||||
|
||||
# This is a standard audit scan.
|
||||
if (aconf.policy is None) and (aconf.make_policy is False):
|
||||
output(aconf, banner, header, client_host=s.client_host, kex=kex)
|
||||
program_retval = output(aconf, banner, header, client_host=s.client_host, kex=kex)
|
||||
|
||||
# This is a policy test.
|
||||
elif (aconf.policy is not None) and (aconf.make_policy is False):
|
||||
return 0 if evaluate_policy(aconf, banner, kex=kex) else 1
|
||||
program_retval = PROGRAM_RETVAL_GOOD if evaluate_policy(aconf, banner, kex=kex) else PROGRAM_RETVAL_FAILURE
|
||||
|
||||
# A new policy should be made from this scan.
|
||||
elif (aconf.policy is None) and (aconf.make_policy is True):
|
||||
@ -3489,7 +3503,7 @@ def audit(aconf: AuditConf, sshv: Optional[int] = None) -> int:
|
||||
else:
|
||||
raise RuntimeError('Internal error while handling output: %r %r' % (aconf.policy is None, aconf.make_policy))
|
||||
|
||||
return 0
|
||||
return program_retval
|
||||
|
||||
|
||||
utils = Utils()
|
||||
|
Loading…
Reference in New Issue
Block a user