mirror of
https://github.com/jtesta/ssh-audit.git
synced 2025-07-06 14:02:49 -05:00
Compare commits
194 Commits
Author | SHA1 | Date | |
---|---|---|---|
3606863ebf | |||
cf1e069db4 | |||
1e1220807f | |||
0263769243 | |||
e6c31ee4f5 | |||
14e0ed0e00 | |||
0f21f2131c | |||
b6c64d296b | |||
1ec13c653e | |||
a401afd099 | |||
8a3ae321f1 | |||
e62b548677 | |||
fd85e247e7 | |||
e3a59a3e21 | |||
4ebefdf894 | |||
83544836c9 | |||
4c9b871f5c | |||
1d707276d7 | |||
166c93ace4 | |||
9759480ae4 | |||
fd3a1f7d41 | |||
08677d65b1 | |||
8c5493ae3e | |||
14af53cf04 | |||
bbf6204ce1 | |||
0df63c20ac | |||
209bcab427 | |||
eac81455a9 | |||
bce9e2b152 | |||
f5431559ff | |||
6f60722455 | |||
f7cbe71aba | |||
c185a25af1 | |||
7221413567 | |||
747177c1c7 | |||
6846b1bf29 | |||
af7e2a088c | |||
120f898539 | |||
0b034b8226 | |||
4ebccb8068 | |||
4f138d7f82 | |||
7a06b872f9 | |||
6baff0f8fe | |||
af663da838 | |||
ed11fc135b | |||
afa73d2dd2 | |||
64656b5228 | |||
99ac875542 | |||
f9a51d4108 | |||
8527d13343 | |||
f8fcd119e2 | |||
76a4750934 | |||
7155efeb4a | |||
41d396f551 | |||
a9933f9211 | |||
b35ca6c6f3 | |||
f2e6f1a71c | |||
f44663bfc4 | |||
95ca0bb243 | |||
a9f6b93391 | |||
04973df2af | |||
a3f126a1dd | |||
1bb5490e01 | |||
c1d0540d1e | |||
cd80917c62 | |||
b7bf8ab38a | |||
a3c6d16500 | |||
4f6e23e568 | |||
b2775c9cf9 | |||
ee5dde1cde | |||
33ae2946ea | |||
7c919b093b | |||
d8eb46d766 | |||
96d442ec62 | |||
9c463b4e06 | |||
1d1f842bed | |||
72a6b9eeaf | |||
774d1c1fe4 | |||
6c8173d409 | |||
21a93cbd66 | |||
0d555d43b3 | |||
e4bdabb891 | |||
c132c62b96 | |||
bb122ffe13 | |||
09c2e7b2d5 | |||
464bb154f3 | |||
9fe69841eb | |||
f330608278 | |||
cab83f837a | |||
041805f608 | |||
2f7c64d896 | |||
e91bbb5e30 | |||
95ba7d11ce | |||
0ffb15dd54 | |||
76849540be | |||
57a8744d03 | |||
3ebb59108b | |||
74d1b5c7b5 | |||
6d9f5e6f2a | |||
29d9e4270d | |||
cfae0d020a | |||
8b7659c4d3 | |||
d3ba5a4e6f | |||
65ef250aae | |||
94a74e9cfd | |||
9ac03d368a | |||
54b0960502 | |||
c9443e6e06 | |||
ff500ba84b | |||
9a409e835e | |||
6fde896d77 | |||
6c4b9fcadf | |||
5bb0ae0ceb | |||
11b6155c64 | |||
b3ed4c7715 | |||
44c1d4827c | |||
22b671e15f | |||
dd3ca9688e | |||
e42064b9b9 | |||
8c24fc01e8 | |||
4fbd339c54 | |||
66b9e079a8 | |||
8018209dd1 | |||
7314d780e7 | |||
6a1f5d2d75 | |||
4684ff0113 | |||
84dfdcaf5e | |||
318aab79bc | |||
aa4eabda66 | |||
4bbb1f4d11 | |||
66bd6c3ef0 | |||
182467e0e8 | |||
385c230376 | |||
855d64f5b1 | |||
5b3b630623 | |||
a5f1cd9197 | |||
cdfe06e75d | |||
cbe7ad4ac3 | |||
dfb8c302bf | |||
4120377c0b | |||
5be64a8ad2 | |||
67087fb920 | |||
42be99a2c7 | |||
ca6cfb81a2 | |||
fabb4b5bb2 | |||
8ca6ec591d | |||
6b76e68d0d | |||
f065118959 | |||
63a9c479a7 | |||
c9d58bb827 | |||
76509a1011 | |||
98717198c2 | |||
e50544def9 | |||
4959029c33 | |||
2abbe8f229 | |||
58a943bed9 | |||
e60d4ff809 | |||
93b908f890 | |||
3868b9f45f | |||
5f760fb8f8 | |||
dabbad3afc | |||
c58041b97c | |||
69436b2c77 | |||
f1e8231b67 | |||
4d16a58f22 | |||
07c272f197 | |||
84ac5a30ab | |||
705bedd608 | |||
aec576b57a | |||
4b456dd01e | |||
301a27ae27 | |||
76f49d4016 | |||
d0356564d5 | |||
ec0b4704e9 | |||
a193059bc9 | |||
4b69544d91 | |||
7959c7448a | |||
262c65b7be | |||
407ddbd7ea | |||
aee949a717 | |||
489a24c564 | |||
5269b63e64 | |||
5de7b913fd | |||
0c98bc1397 | |||
f25e6caa2a | |||
29a0bb86fa | |||
1fda7b2a3e | |||
6cb4c88f88 | |||
15d24cde08 | |||
84549b74f2 | |||
758d839d29 | |||
f1003ab195 | |||
954989c3b7 | |||
7d5f74810b |
37
.appveyor.yml
Normal file
37
.appveyor.yml
Normal file
@ -0,0 +1,37 @@
|
||||
version: '1.7.1.dev.{build}'
|
||||
|
||||
build: off
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- develop
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
- PYTHON: "C:\\Python26"
|
||||
- PYTHON: "C:\\Python26-x64"
|
||||
- PYTHON: "C:\\Python27"
|
||||
- PYTHON: "C:\\Python27-x64"
|
||||
- PYTHON: "C:\\Python33"
|
||||
- PYTHON: "C:\\Python33-x64"
|
||||
- PYTHON: "C:\\Python34"
|
||||
- PYTHON: "C:\\Python34-x64"
|
||||
- PYTHON: "C:\\Python35"
|
||||
- PYTHON: "C:\\Python35-x64"
|
||||
- PYTHON: "C:\\Python36"
|
||||
- PYTHON: "C:\\Python36-x64"
|
||||
matrix:
|
||||
fast_finish: true
|
||||
|
||||
cache:
|
||||
- '%LOCALAPPDATA%\pip\Cache'
|
||||
- .downloads -> .appveyor.yml
|
||||
|
||||
install:
|
||||
- "cmd /c .\\test\\tools\\ci-win.cmd install"
|
||||
|
||||
test_script:
|
||||
- "cmd /c .\\test\\tools\\ci-win.cmd test"
|
||||
|
||||
on_failure:
|
||||
- ps: get-content .tox\*\log\*
|
9
.gitignore
vendored
9
.gitignore
vendored
@ -1,2 +1,11 @@
|
||||
*~
|
||||
*.pyc
|
||||
venv*/
|
||||
.cache/
|
||||
.tox
|
||||
.coverage*
|
||||
reports/
|
||||
.scannerwork/
|
||||
pypi/sshaudit/LICENSE
|
||||
pypi/sshaudit/README.md
|
||||
pypi/sshaudit/sshaudit.py
|
||||
|
80
.travis.yml
Normal file
80
.travis.yml
Normal file
@ -0,0 +1,80 @@
|
||||
language: python
|
||||
sudo: false
|
||||
matrix:
|
||||
include:
|
||||
# (default)
|
||||
- os: linux
|
||||
python: 2.6
|
||||
- os: linux
|
||||
python: 2.7
|
||||
env: SQ=1
|
||||
- os: linux
|
||||
python: 3.3
|
||||
- os: linux
|
||||
python: 3.4
|
||||
- os: linux
|
||||
python: 3.5
|
||||
- os: linux
|
||||
python: 3.6
|
||||
- os: linux
|
||||
python: pypy
|
||||
- os: linux
|
||||
python: pypy3
|
||||
- os: linux
|
||||
python: 3.7-dev
|
||||
# Ubuntu 12.04
|
||||
- os: linux
|
||||
dist: precise
|
||||
language: generic
|
||||
env: PY_VER=py26,py27,py33,py34,py35,py36,pypy,pypy3 PY_ORIGIN=pyenv
|
||||
# Ubuntu 14.04
|
||||
- os: linux
|
||||
dist: trusty
|
||||
language: generic
|
||||
env: PY_VER=py26,py27,py33,py34,py35,py36,pypy,pypy3 PY_ORIGIN=pyenv
|
||||
# macOS 10.12 Sierra
|
||||
- os: osx
|
||||
osx_image: xcode8.3
|
||||
language: generic
|
||||
env: PY_VER=py26,py27,py33,py34,py35,py36,pypy,pypy3
|
||||
# Mac OS X 10.11 El Capitan
|
||||
- os: osx
|
||||
osx_image: xcode7.3
|
||||
language: generic
|
||||
env: PY_VER=py26,py27,py33,py34,py35,py36,pypy,pypy3
|
||||
# Mac OS X 10.10 Yosemite
|
||||
- os: osx
|
||||
osx_image: xcode6.4
|
||||
language: generic
|
||||
env: PY_VER=py26,py27,py33,py34,py35,py36,pypy,pypy3
|
||||
allow_failures:
|
||||
# PyPy3 on Travis CI is out of date
|
||||
- python: pypy3
|
||||
# Python nightly could fail
|
||||
- python: 3.7-dev
|
||||
- env: PY_VER=py37
|
||||
- env: PY_VER=py37/pyenv
|
||||
- env: PY_VER=py37 PY_ORIGIN=pyenv
|
||||
fast_finish: true
|
||||
|
||||
cache:
|
||||
- pip
|
||||
- directories:
|
||||
- $HOME/.pyenv.cache
|
||||
- $HOME/.bin
|
||||
|
||||
before_install:
|
||||
- source test/tools/ci-linux.sh
|
||||
- ci_step_before_install
|
||||
|
||||
install:
|
||||
- ci_step_install
|
||||
|
||||
script:
|
||||
- ci_step_script
|
||||
|
||||
after_success:
|
||||
- ci_step_success
|
||||
|
||||
after_failure:
|
||||
- ci_step_failure
|
23
LICENSE
Normal file
23
LICENSE
Normal file
@ -0,0 +1,23 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (C) 2017 Andris Raugulis (moo@arthepsy.eu)
|
||||
Copyright (C) 2017-2019 Joe Testa (jtesta@positronsecurity.com)
|
||||
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
76
README.md
76
README.md
@ -1,35 +1,93 @@
|
||||
# ssh-audit
|
||||
**ssh-audit** is a tool for ssh server auditing.
|
||||
<!--
|
||||
[](https://travis-ci.org/arthepsy/ssh-audit)
|
||||
[](https://ci.appveyor.com/project/arthepsy/ssh-audit)
|
||||
[](https://codecov.io/gh/arthepsy/ssh-audit)
|
||||
[](https://sq.evolutiongaming.com/dashboard?id=arthepsy-github%3Assh-audit%3Adevelop)
|
||||
-->
|
||||
**ssh-audit** is a tool for ssh server & client configuration auditing.
|
||||
|
||||
## Features
|
||||
- SSH1 and SSH2 protocol server support;
|
||||
- analyze SSH client configuration;
|
||||
- grab banner, recognize device or software and operating system, detect compression;
|
||||
- gather key-exchange, host-key, encryption and message authentication code algorithms;
|
||||
- output algorithm information (available since, removed/disabled, unsafe/weak/legacy, etc);
|
||||
- output algorithm recommendations (append or remove based on recognized software version);
|
||||
- output security information (related issues, assigned CVE list, etc);
|
||||
- analyze SSH version compatibility based on algorithm information;
|
||||
- historical information from OpenSSH and Dropbear SSH;
|
||||
- no dependencies, compatible with Python2 and Python3;
|
||||
- historical information from OpenSSH, Dropbear SSH and libssh;
|
||||
- no dependencies
|
||||
|
||||
## Usage
|
||||
```
|
||||
usage: ssh-audit.py [-bnv] [-l <level>] <host[:port]>
|
||||
usage: ssh-audit.py [-1246pbcnjvlt] <host>
|
||||
|
||||
-1, --ssh1 force ssh version 1 only
|
||||
-2, --ssh2 force ssh version 1 only
|
||||
-2, --ssh2 force ssh version 2 only
|
||||
-4, --ipv4 enable IPv4 (order of precedence)
|
||||
-6, --ipv6 enable IPv6 (order of precedence)
|
||||
-p, --port=<port> port to connect
|
||||
-b, --batch batch output
|
||||
-c, --client-audit starts a server on port 2222 to audit client
|
||||
software config (use -p to change port;
|
||||
use -t to change timeout)
|
||||
-n, --no-colors disable colors
|
||||
-j, --json JSON output
|
||||
-v, --verbose verbose output
|
||||
-l, --level=<level> minimum output level (info|warn|fail)
|
||||
|
||||
-t, --timeout=<secs> timeout (in seconds) for connection and reading
|
||||
(default: 5)
|
||||
```
|
||||
* if both IPv4 and IPv6 are used, order of precedence can be set by using either `-46` or `-64`.
|
||||
* batch flag `-b` will output sections without header and without empty lines (implies verbose flag).
|
||||
* verbose flag `-v` will prefix each line with section type and algorithm name.
|
||||
|
||||
### example
|
||||

|
||||
### Server Audit Example
|
||||
Below is a screen shot of the server-auditing output when connecting to an unhardened OpenSSH v5.3 service:
|
||||

|
||||
|
||||
### Client Audit Example
|
||||
Below is a screen shot of the client-auditing output when an unhardened OpenSSH v7.2 client connects:
|
||||

|
||||
|
||||
## ChangeLog
|
||||
### v2.1.0 (2019-11-14)
|
||||
- Added client software auditing functionality (see `-c` / `--client-audit` option).
|
||||
- Added JSON output option (see `-j` / `--json` option; credit [Andreas Jaggi](https://github.com/x-way)).
|
||||
- Fixed crash while scanning Solaris Sun_SSH.
|
||||
- Added 9 new key exchanges: `gss-group1-sha1-toWM5Slw5Ew8Mqkay+al2g==`, `gss-gex-sha1-toWM5Slw5Ew8Mqkay+al2g==`, `gss-group14-sha1-`, `gss-group14-sha1-toWM5Slw5Ew8Mqkay+al2g==`, `gss-group14-sha256-toWM5Slw5Ew8Mqkay+al2g==`, `gss-group15-sha512-toWM5Slw5Ew8Mqkay+al2g==`, `diffie-hellman-group15-sha256`, `ecdh-sha2-1.3.132.0.10`, `curve448-sha512`.
|
||||
- Added 1 new host key type: `ecdsa-sha2-1.3.132.0.10`.
|
||||
- Added 4 new ciphers: `idea-cbc`, `serpent128-cbc`, `serpent192-cbc`, `serpent256-cbc`.
|
||||
- Added 6 new MACs: `hmac-sha2-256-96-etm@openssh.com`, `hmac-sha2-512-96-etm@openssh.com`, `hmac-ripemd`, `hmac-sha256-96@ssh.com`, `umac-32@openssh.com`, `umac-96@openssh.com`.
|
||||
|
||||
### v2.0.0 (2019-08-29)
|
||||
- Forked from https://github.com/arthepsy/ssh-audit (development was stalled, and developer went MIA).
|
||||
- Added RSA host key length test.
|
||||
- Added RSA certificate key length test.
|
||||
- Added Diffie-Hellman modulus size test.
|
||||
- Now outputs host key fingerprints for RSA and ED25519.
|
||||
- Added 5 new key exchanges: `sntrup4591761x25519-sha512@tinyssh.org`, `diffie-hellman-group-exchange-sha256@ssh.com`, `diffie-hellman-group-exchange-sha512@ssh.com`, `diffie-hellman-group16-sha256`, `diffie-hellman-group17-sha512`.
|
||||
- Added 3 new encryption algorithms: `des-cbc-ssh1`, `blowfish-ctr`, `twofish-ctr`.
|
||||
- Added 10 new MACs: `hmac-sha2-56`, `hmac-sha2-224`, `hmac-sha2-384`, `hmac-sha3-256`, `hmac-sha3-384`, `hmac-sha3-512`, `hmac-sha256`, `hmac-sha256@ssh.com`, `hmac-sha512`, `hmac-512@ssh.com`.
|
||||
- Added command line argument (`-t` / `--timeout`) for connection & reading timeouts.
|
||||
- Updated CVEs for libssh & Dropbear.
|
||||
|
||||
### v1.7.0 (2016-10-26)
|
||||
- implement options to allow specify IPv4/IPv6 usage and order of precedence
|
||||
- implement option to specify remote port (old behavior kept for compatibility)
|
||||
- add colors support for Microsoft Windows via optional colorama dependency
|
||||
- fix encoding and decoding issues, add tests, do not crash on encoding errors
|
||||
- use mypy-lang for static type checking and verify all code
|
||||
|
||||
### v1.6.0 (2016-10-14)
|
||||
- implement algorithm recommendations section (based on recognized software)
|
||||
- implement full libssh support (version history, algorithms, security, etc)
|
||||
- fix SSH-1.99 banner recognition and version comparison functionality
|
||||
- do not output empty algorithms (happens for misconfigured servers)
|
||||
- make consistent output for Python 3.x versions
|
||||
- add a lot more tests (conf, banner, software, SSH1/SSH2, output, etc)
|
||||
- use Travis CI to test for multiple Python versions (2.6-3.5, pypy, pypy3)
|
||||
|
||||
### v1.5.0 (2016-09-20)
|
||||
- create security section for related security information
|
||||
@ -37,7 +95,7 @@ usage: ssh-audit.py [-bnv] [-l <level>] <host[:port]>
|
||||
- implement full SSH1 support with fingerprint information
|
||||
- automatically fallback to SSH1 on protocol mismatch
|
||||
- add new options to force SSH1 or SSH2 (both allowed by default)
|
||||
- parse banner information and convert it to specific sofware and OS version
|
||||
- parse banner information and convert it to specific software and OS version
|
||||
- do not use padding in batch mode
|
||||
- several fixes (Cisco sshd, rare hangs, error handling, etc)
|
||||
|
||||
|
511
docker_test.sh
Executable file
511
docker_test.sh
Executable file
@ -0,0 +1,511 @@
|
||||
#!/bin/bash
|
||||
|
||||
#
|
||||
# This script will set up a docker image with multiple versions of OpenSSH, then
|
||||
# use it to run tests.
|
||||
#
|
||||
# For debugging purposes, here is a cheat sheet for manually running the docker image:
|
||||
#
|
||||
# docker run -p 2222:22 -it ssh-audit-test:X /bin/bash
|
||||
# docker run -p 2222:22 --security-opt seccomp:unconfined -it ssh-audit-test /debug.sh
|
||||
# docker run -d -p 2222:22 ssh-audit-test:X /openssh/sshd-5.6p1 -D -f /etc/ssh/sshd_config-5.6p1_test1
|
||||
# docker run -d -p 2222:22 ssh-audit-test:X /openssh/sshd-8.0p1 -D -f /etc/ssh/sshd_config-8.0p1_test1
|
||||
#
|
||||
|
||||
|
||||
# This is the docker tag for the image. If this tag doesn't exist, then we assume the
|
||||
# image is out of date, and generate a new one with this tag.
|
||||
IMAGE_VERSION=3
|
||||
|
||||
# This is the name of our docker image.
|
||||
IMAGE_NAME=ssh-audit-test
|
||||
|
||||
|
||||
# Terminal colors.
|
||||
CLR="\033[0m"
|
||||
RED="\033[0;31m"
|
||||
GREEN="\033[0;32m"
|
||||
REDB="\033[1;31m" # Red + bold
|
||||
GREENB="\033[1;32m" # Green + bold
|
||||
|
||||
|
||||
# Returns 0 if current docker image exists.
|
||||
function check_if_docker_image_exists {
|
||||
images=`docker image ls | egrep "$IMAGE_NAME[[:space:]]+$IMAGE_VERSION"`
|
||||
}
|
||||
|
||||
|
||||
# Uncompresses and compiles the specified version of Dropbear.
|
||||
function compile_dropbear {
|
||||
version=$1
|
||||
compile 'Dropbear' $version
|
||||
}
|
||||
|
||||
|
||||
# Uncompresses and compiles the specified version of OpenSSH.
|
||||
function compile_openssh {
|
||||
version=$1
|
||||
compile 'OpenSSH' $version
|
||||
}
|
||||
|
||||
|
||||
# Uncompresses and compiles the specified version of TinySSH.
|
||||
function compile_tinyssh {
|
||||
version=$1
|
||||
compile 'TinySSH' $version
|
||||
}
|
||||
|
||||
|
||||
function compile {
|
||||
project=$1
|
||||
version=$2
|
||||
|
||||
tarball=
|
||||
uncompress_options=
|
||||
source_dir=
|
||||
server_executable=
|
||||
if [[ $project == 'OpenSSH' ]]; then
|
||||
tarball="openssh-${version}.tar.gz"
|
||||
uncompress_options="xzf"
|
||||
source_dir="openssh-${version}"
|
||||
server_executable=sshd
|
||||
elif [[ $project == 'Dropbear' ]]; then
|
||||
tarball="dropbear-${version}.tar.bz2"
|
||||
uncompress_options="xjf"
|
||||
source_dir="dropbear-${version}"
|
||||
server_executable=dropbear
|
||||
elif [[ $project == 'TinySSH' ]]; then
|
||||
tarball="${version}.tar.gz"
|
||||
uncompress_options="xzf"
|
||||
source_dir="tinyssh-${version}"
|
||||
server_executable='build/bin/tinysshd'
|
||||
fi
|
||||
|
||||
echo "Uncompressing ${project} ${version}..."
|
||||
tar $uncompress_options $tarball
|
||||
|
||||
echo "Compiling ${project} ${version}..."
|
||||
pushd $source_dir > /dev/null
|
||||
|
||||
# TinySSH has no configure script... only a Makefile.
|
||||
if [[ $project == 'TinySSH' ]]; then
|
||||
make -j 10
|
||||
else
|
||||
./configure && make -j 10
|
||||
fi
|
||||
|
||||
if [[ ! -f $server_executable ]]; then
|
||||
echo -e "${REDB}Error: ${server_executable} not built!${CLR}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "\n${GREEN}Successfully built ${project} ${version}${CLR}\n"
|
||||
popd > /dev/null
|
||||
}
|
||||
|
||||
|
||||
# Creates a new docker image.
|
||||
function create_docker_image {
|
||||
# Create a new temporary directory.
|
||||
TMP_DIR=`mktemp -d /tmp/sshaudit-docker-XXXXXXXXXX`
|
||||
|
||||
# Copy the Dockerfile and all files in the test/docker/ dir to our new temp directory.
|
||||
find test/docker/ -maxdepth 1 -type f | xargs cp -t $TMP_DIR
|
||||
|
||||
# Make the temp directory our working directory for the duration of the build
|
||||
# process.
|
||||
pushd $TMP_DIR > /dev/null
|
||||
|
||||
# Get the release keys.
|
||||
get_dropbear_release_key
|
||||
get_openssh_release_key
|
||||
get_tinyssh_release_key
|
||||
|
||||
# Aside from checking the GPG signatures, we also compare against this known-good
|
||||
# SHA-256 hash just in case.
|
||||
get_openssh '4.0p1' '5adb9b2c2002650e15216bf94ed9db9541d9a17c96fcd876784861a8890bc92b'
|
||||
get_openssh '5.6p1' '538af53b2b8162c21a293bb004ae2bdb141abd250f61b4cea55244749f3c6c2b'
|
||||
get_openssh '8.0p1' 'bd943879e69498e8031eb6b7f44d08cdc37d59a7ab689aa0b437320c3481fd68'
|
||||
get_dropbear '2019.78' '525965971272270995364a0eb01f35180d793182e63dd0b0c3eb0292291644a4'
|
||||
get_tinyssh '20190101' '554a9a94e53b370f0cd0c5fbbd322c34d1f695cbcea6a6a32dcb8c9f595b3fea'
|
||||
|
||||
# Compile the versions of OpenSSH.
|
||||
compile_openssh '4.0p1'
|
||||
compile_openssh '5.6p1'
|
||||
compile_openssh '8.0p1'
|
||||
|
||||
# Compile the versions of Dropbear.
|
||||
compile_dropbear '2019.78'
|
||||
|
||||
# Compile the versions of TinySSH.
|
||||
compile_tinyssh '20190101'
|
||||
|
||||
|
||||
# Rename the default config files so we know they are our originals.
|
||||
mv openssh-4.0p1/sshd_config sshd_config-4.0p1_orig
|
||||
mv openssh-5.6p1/sshd_config sshd_config-5.6p1_orig
|
||||
mv openssh-8.0p1/sshd_config sshd_config-8.0p1_orig
|
||||
|
||||
|
||||
# Create the configurations for each test.
|
||||
|
||||
|
||||
#
|
||||
# OpenSSH v4.0p1
|
||||
#
|
||||
|
||||
# Test 1: Basic test.
|
||||
create_openssh_config '4.0p1' 'test1' "HostKey /etc/ssh/ssh1_host_key\nHostKey /etc/ssh/ssh_host_rsa_key_1024\nHostKey /etc/ssh/ssh_host_dsa_key"
|
||||
|
||||
|
||||
#
|
||||
# OpenSSH v5.6p1
|
||||
#
|
||||
|
||||
# Test 1: Basic test.
|
||||
create_openssh_config '5.6p1' 'test1' "HostKey /etc/ssh/ssh_host_rsa_key_1024\nHostKey /etc/ssh/ssh_host_dsa_key"
|
||||
|
||||
# Test 2: RSA 1024 host key with RSA 1024 certificate.
|
||||
create_openssh_config '5.6p1' 'test2' "HostKey /etc/ssh/ssh_host_rsa_key_1024\nHostCertificate /etc/ssh/ssh_host_rsa_key_1024-cert_1024.pub"
|
||||
|
||||
# Test 3: RSA 1024 host key with RSA 3072 certificate.
|
||||
create_openssh_config '5.6p1' 'test3' "HostKey /etc/ssh/ssh_host_rsa_key_1024\nHostCertificate /etc/ssh/ssh_host_rsa_key_1024-cert_3072.pub"
|
||||
|
||||
# Test 4: RSA 3072 host key with RSA 1024 certificate.
|
||||
create_openssh_config '5.6p1' 'test4' "HostKey /etc/ssh/ssh_host_rsa_key_3072\nHostCertificate /etc/ssh/ssh_host_rsa_key_3072-cert_1024.pub"
|
||||
|
||||
# Test 5: RSA 3072 host key with RSA 3072 certificate.
|
||||
create_openssh_config '5.6p1' 'test5' "HostKey /etc/ssh/ssh_host_rsa_key_3072\nHostCertificate /etc/ssh/ssh_host_rsa_key_3072-cert_3072.pub"
|
||||
|
||||
|
||||
#
|
||||
# OpenSSH v8.0p1
|
||||
#
|
||||
|
||||
# Test 1: Basic test.
|
||||
create_openssh_config '8.0p1' 'test1' "HostKey /etc/ssh/ssh_host_rsa_key_3072\nHostKey /etc/ssh/ssh_host_ecdsa_key\nHostKey /etc/ssh/ssh_host_ed25519_key"
|
||||
|
||||
# Test 2: ED25519 certificate test.
|
||||
create_openssh_config '8.0p1' 'test2' "HostKey /etc/ssh/ssh_host_ed25519_key\nHostCertificate /etc/ssh/ssh_host_ed25519_key-cert.pub"
|
||||
|
||||
# Test 3: Hardened installation test.
|
||||
create_openssh_config '8.0p1' 'test3' "HostKey /etc/ssh/ssh_host_ed25519_key\nKexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256\nCiphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr\nMACs hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,umac-128-etm@openssh.com"
|
||||
|
||||
|
||||
# Now build the docker image!
|
||||
docker build --tag $IMAGE_NAME:$IMAGE_VERSION .
|
||||
|
||||
popd > /dev/null
|
||||
rm -rf $TMP_DIR
|
||||
}
|
||||
|
||||
|
||||
# Creates an OpenSSH configuration file for a specific test.
|
||||
function create_openssh_config {
|
||||
openssh_version=$1
|
||||
test_number=$2
|
||||
config_text=$3
|
||||
|
||||
cp sshd_config-${openssh_version}_orig sshd_config-${openssh_version}_${test_number}
|
||||
echo -e "${config_text}" >> sshd_config-${openssh_version}_${test_number}
|
||||
}
|
||||
|
||||
|
||||
# Downloads the Dropbear release key and adds it to the local keyring.
|
||||
function get_dropbear_release_key {
|
||||
get_release_key 'Dropbear' 'https://matt.ucc.asn.au/dropbear/releases/dropbear-key-2015.asc' 'F29C6773' 'F734 7EF2 EE2E 07A2 6762 8CA9 4493 1494 F29C 6773'
|
||||
}
|
||||
|
||||
|
||||
# Downloads the OpenSSH release key and adds it to the local keyring.
|
||||
function get_openssh_release_key {
|
||||
get_release_key 'OpenSSH' 'https://ftp.openbsd.org/pub/OpenBSD/OpenSSH/RELEASE_KEY.asc' '6D920D30' '59C2 118E D206 D927 E667 EBE3 D3E5 F56B 6D92 0D30'
|
||||
}
|
||||
|
||||
|
||||
# Downloads the TinySSH release key and adds it to the local keyring.
|
||||
function get_tinyssh_release_key {
|
||||
get_release_key 'TinySSH' '' '96939FF9' 'AADF 2EDF 5529 F170 2772 C8A2 DEC4 D246 931E F49B'
|
||||
}
|
||||
|
||||
|
||||
function get_release_key {
|
||||
project=$1
|
||||
key_url=$2
|
||||
key_id=$3
|
||||
release_key_fingerprint_expected=$4
|
||||
|
||||
# The TinySSH release key isn't on any website, apparently.
|
||||
if [[ $project == 'TinySSH' ]]; then
|
||||
gpg --recv-key $key_id
|
||||
else
|
||||
echo -e "\nGetting ${project} release key...\n"
|
||||
wget -O key.asc $2
|
||||
|
||||
echo -e "\nImporting ${project} release key...\n"
|
||||
gpg --import key.asc
|
||||
|
||||
rm key.asc
|
||||
fi
|
||||
|
||||
local release_key_fingerprint_actual=`gpg --fingerprint ${key_id}`
|
||||
if [[ $release_key_fingerprint_actual != *"$release_key_fingerprint_expected"* ]]; then
|
||||
echo -e "\n${REDB}Error: ${project} release key fingerprint does not match expected value!\n\tExpected: $release_key_fingerprint_expected\n\tActual: $release_key_fingerprint_actual\n\nTerminating.${CLR}"
|
||||
exit -1
|
||||
fi
|
||||
echo -e "\n\n${GREEN}${project} release key matches expected value.${CLR}\n"
|
||||
}
|
||||
|
||||
|
||||
# Downloads the specified version of Dropbear.
|
||||
function get_dropbear {
|
||||
version=$1
|
||||
tarball_checksum_expected=$2
|
||||
get_source 'Dropbear' $version $tarball_checksum_expected
|
||||
}
|
||||
|
||||
|
||||
# Downloads the specified version of OpenSSH.
|
||||
function get_openssh {
|
||||
version=$1
|
||||
tarball_checksum_expected=$2
|
||||
get_source 'OpenSSH' $version $tarball_checksum_expected
|
||||
}
|
||||
|
||||
|
||||
# Downloads the specified version of TinySSH.
|
||||
function get_tinyssh {
|
||||
version=$1
|
||||
tarball_checksum_expected=$2
|
||||
get_source 'TinySSH' $version $tarball_checksum_expected
|
||||
}
|
||||
|
||||
|
||||
function get_source {
|
||||
project=$1
|
||||
version=$2
|
||||
tarball_checksum_expected=$3
|
||||
|
||||
base_url_source=
|
||||
base_url_sig=
|
||||
tarball=
|
||||
sig=
|
||||
signer=
|
||||
if [[ $project == 'OpenSSH' ]]; then
|
||||
base_url_source='https://cdn.openbsd.org/pub/OpenBSD/OpenSSH/portable/'
|
||||
base_url_sig=$base_url_source
|
||||
tarball="openssh-${version}.tar.gz"
|
||||
sig="${tarball}.asc"
|
||||
signer="Damien Miller "
|
||||
elif [[ $project == 'Dropbear' ]]; then
|
||||
base_url_source='https://matt.ucc.asn.au/dropbear/releases/'
|
||||
base_url_sig=$base_url_source
|
||||
tarball="dropbear-${version}.tar.bz2"
|
||||
sig="${tarball}.asc"
|
||||
signer="Dropbear SSH Release Signing <matt@ucc.asn.au>"
|
||||
elif [[ $project == 'TinySSH' ]]; then
|
||||
base_url_source='https://github.com/janmojzis/tinyssh/archive/'
|
||||
base_url_sig="https://github.com/janmojzis/tinyssh/releases/download/${version}/"
|
||||
tarball="${version}.tar.gz"
|
||||
sig="${tarball}.asc"
|
||||
signer="Jan Mojžíš <jan.mojzis@gmail.com>"
|
||||
fi
|
||||
|
||||
echo -e "\nGetting ${project} ${version} sources...\n"
|
||||
wget "${base_url_source}${tarball}"
|
||||
|
||||
echo -e "\nGetting ${project} ${version} signature...\n"
|
||||
wget "${base_url_sig}${sig}"
|
||||
|
||||
|
||||
# Older OpenSSH releases were .sigs.
|
||||
if [[ ($project == 'OpenSSH') && (! -f $sig) ]]; then
|
||||
wget ${base_url_sig}openssh-${version}.tar.gz.sig
|
||||
sig=openssh-${version}.tar.gz.sig
|
||||
fi
|
||||
|
||||
local gpg_verify=`gpg --verify ${sig} ${tarball} 2>&1`
|
||||
if [[ $gpg_verify != *"Good signature from \"${signer}"* ]]; then
|
||||
echo -e "\n\n${REDB}Error: ${project} signature invalid!\n$gpg_verify\n\nTerminating.${CLR}"
|
||||
exit -1
|
||||
fi
|
||||
|
||||
# Check GPG's return value. 0 denotes a valid signature, and 1 is returned
|
||||
# on invalid signatures.
|
||||
if [[ $? != 0 ]]; then
|
||||
echo -e "\n\n${REDB}Error: ${project} signature invalid! Verification returned code: $?\n\nTerminating.${CLR}"
|
||||
exit -1
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}Signature on ${project} sources verified.${CLR}\n"
|
||||
|
||||
local checksum_actual=`sha256sum ${tarball} | cut -f1 -d" "`
|
||||
if [[ $checksum_actual != $tarball_checksum_expected ]]; then
|
||||
echo -e "${REDB}Error: ${project} checksum is invalid!\n Expected: ${tarball_checksum_expected}\n Actual: ${checksum_actual}\n\n Terminating.${CLR}"
|
||||
exit -1
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
# Runs a Dropbear test. Upon failure, a diff between the expected and actual results
|
||||
# is shown, then the script immediately terminates.
|
||||
function run_dropbear_test {
|
||||
dropbear_version=$1
|
||||
test_number=$2
|
||||
options=$3
|
||||
|
||||
run_test 'Dropbear' $dropbear_version $test_number "$options"
|
||||
}
|
||||
|
||||
|
||||
# Runs an OpenSSH test. Upon failure, a diff between the expected and actual results
|
||||
# is shown, then the script immediately terminates.
|
||||
function run_openssh_test {
|
||||
openssh_version=$1
|
||||
test_number=$2
|
||||
|
||||
run_test 'OpenSSH' $openssh_version $test_number ''
|
||||
}
|
||||
|
||||
|
||||
# Runs a TinySSH test. Upon failure, a diff between the expected and actual results
|
||||
# is shown, then the script immediately terminates.
|
||||
function run_tinyssh_test {
|
||||
tinyssh_version=$1
|
||||
test_number=$2
|
||||
|
||||
run_test 'TinySSH' $tinyssh_version $test_number ''
|
||||
}
|
||||
|
||||
|
||||
function run_test {
|
||||
server_type=$1
|
||||
version=$2
|
||||
test_number=$3
|
||||
options=$4
|
||||
|
||||
server_exec=
|
||||
test_result_stdout=
|
||||
test_result_json=
|
||||
expected_result_stdout=
|
||||
expected_result_json=
|
||||
test_name=
|
||||
if [[ $server_type == 'OpenSSH' ]]; then
|
||||
server_exec="/openssh/sshd-${version} -D -f /etc/ssh/sshd_config-${version}_${test_number}"
|
||||
test_result_stdout="${TEST_RESULT_DIR}/openssh_${version}_${test_number}.txt"
|
||||
test_result_json="${TEST_RESULT_DIR}/openssh_${version}_${test_number}.json"
|
||||
expected_result_stdout="test/docker/expected_results/openssh_${version}_${test_number}.txt"
|
||||
expected_result_json="test/docker/expected_results/openssh_${version}_${test_number}.json"
|
||||
test_name="OpenSSH ${version} ${test_number}"
|
||||
options=
|
||||
elif [[ $server_type == 'Dropbear' ]]; then
|
||||
server_exec="/dropbear/dropbear-${version} -F ${options}"
|
||||
test_result_stdout="${TEST_RESULT_DIR}/dropbear_${version}_${test_number}.txt"
|
||||
test_result_json="${TEST_RESULT_DIR}/dropbear_${version}_${test_number}.json"
|
||||
expected_result_stdout="test/docker/expected_results/dropbear_${version}_${test_number}.txt"
|
||||
expected_result_json="test/docker/expected_results/dropbear_${version}_${test_number}.json"
|
||||
test_name="Dropbear ${version} ${test_number}"
|
||||
elif [[ $server_type == 'TinySSH' ]]; then
|
||||
server_exec="/usr/bin/tcpserver -HRDl0 0.0.0.0 22 /tinysshd/tinyssh-20190101 -v /etc/tinyssh/"
|
||||
test_result_stdout="${TEST_RESULT_DIR}/tinyssh_${version}_${test_number}.txt"
|
||||
test_result_json="${TEST_RESULT_DIR}/tinyssh_${version}_${test_number}.json"
|
||||
expected_result_stdout="test/docker/expected_results/tinyssh_${version}_${test_number}.txt"
|
||||
expected_result_json="test/docker/expected_results/tinyssh_${version}_${test_number}.json"
|
||||
test_name="TinySSH ${version} ${test_number}"
|
||||
fi
|
||||
|
||||
cid=`docker run -d -p 2222:22 ${IMAGE_NAME}:${IMAGE_VERSION} ${server_exec}`
|
||||
if [[ $? != 0 ]]; then
|
||||
echo -e "${REDB}Failed to run docker image! (exit code: $?)${CLR}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
./ssh-audit.py localhost:2222 > $test_result_stdout
|
||||
if [[ $? != 0 ]]; then
|
||||
echo -e "${REDB}Failed to run ssh-audit.py! (exit code: $?)${CLR}"
|
||||
docker container stop $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}"
|
||||
docker container stop $cid > /dev/null
|
||||
exit 1
|
||||
fi
|
||||
|
||||
docker container stop $cid > /dev/null
|
||||
if [[ $? != 0 ]]; then
|
||||
echo -e "${REDB}Failed to stop docker container ${cid}! (exit code: $?)${CLR}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# TinySSH outputs a random string in each banner, which breaks our test. So
|
||||
# we need to filter out the banner part of the output so we get stable, repeatable
|
||||
# results.
|
||||
if [[ $server_type == 'TinySSH' ]]; then
|
||||
grep -v "(gen) banner: " ${test_result_stdout} > "${test_result_stdout}.tmp"
|
||||
mv "${test_result_stdout}.tmp" ${test_result_stdout}
|
||||
cat "${test_result_json}" | perl -pe 's/"comments": ".*?"/"comments": ""/' | perl -pe 's/"raw": ".+?"/"raw": ""/' > "${test_result_json}.tmp"
|
||||
mv "${test_result_json}.tmp" ${test_result_json}
|
||||
fi
|
||||
|
||||
diff=`diff -u ${expected_result_stdout} ${test_result_stdout}`
|
||||
if [[ $? != 0 ]]; then
|
||||
echo -e "${test_name} ${REDB}FAILED${CLR}.\n\n${diff}\n"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
diff=`diff -u ${expected_result_json} ${test_result_json}`
|
||||
if [[ $? != 0 ]]; then
|
||||
echo -e "${test_name} ${REDB}FAILED${CLR}.\n\n${diff}\n"
|
||||
exit 1
|
||||
fi
|
||||
echo -e "${test_name} ${GREEN}passed${CLR}."
|
||||
}
|
||||
|
||||
|
||||
# First check if docker is functional.
|
||||
docker version > /dev/null
|
||||
if [[ $? != 0 ]]; then
|
||||
echo -e "${REDB}Error: 'docker version' command failed (error code: $?). Is docker installed and functioning?${CLR}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if the docker image is the most up-to-date version. If not, create it.
|
||||
check_if_docker_image_exists
|
||||
if [[ $? == 0 ]]; then
|
||||
echo -e "\n${GREEN}Docker image $IMAGE_NAME:$IMAGE_VERSION already exists.${CLR}"
|
||||
else
|
||||
echo -e "\nCreating docker image $IMAGE_NAME:$IMAGE_VERSION..."
|
||||
create_docker_image
|
||||
echo -e "\n${GREEN}Done creating docker image!${CLR}"
|
||||
fi
|
||||
|
||||
# Create a temporary directory to write test results to.
|
||||
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'
|
||||
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'
|
||||
echo
|
||||
run_openssh_test '8.0p1' 'test1'
|
||||
run_openssh_test '8.0p1' 'test2'
|
||||
run_openssh_test '8.0p1' 'test3'
|
||||
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'
|
||||
echo
|
||||
run_tinyssh_test '20190101' 'test1'
|
||||
|
||||
# The test functions above will terminate the script on failure, so if we reached here,
|
||||
# all tests are successful.
|
||||
echo -e "\n${GREENB}ALL TESTS PASS!${CLR}\n"
|
||||
|
||||
rm -rf $TEST_RESULT_DIR
|
||||
exit 0
|
1
pypi/MANIFEST.in
Normal file
1
pypi/MANIFEST.in
Normal file
@ -0,0 +1 @@
|
||||
include sshaudit/LICENSE
|
14
pypi/Makefile
Normal file
14
pypi/Makefile
Normal file
@ -0,0 +1,14 @@
|
||||
all:
|
||||
cp ../ssh-audit.py sshaudit/sshaudit.py
|
||||
cp ../LICENSE sshaudit/LICENSE
|
||||
cp ../README.md sshaudit/README.md
|
||||
python3 setup.py sdist bdist_wheel
|
||||
|
||||
uploadtest:
|
||||
twine upload --repository-url https://test.pypi.org/legacy/ dist/*
|
||||
|
||||
uploadprod:
|
||||
twine upload dist/*
|
||||
|
||||
clean:
|
||||
rm -rf build/ dist/ *.egg-info/ sshaudit/sshaudit.py sshaudit/LICENSE sshaudit/README.md
|
38
pypi/setup.py
Normal file
38
pypi/setup.py
Normal file
@ -0,0 +1,38 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
import re
|
||||
from setuptools import setup
|
||||
|
||||
|
||||
version = re.search('^VERSION\s*=\s*\'v(\d\.\d\.\d)\'', open('sshaudit/sshaudit.py').read(), re.M).group(1)
|
||||
print("\n\nPackaging ssh-audit v%s...\n\n" % version)
|
||||
|
||||
with open("sshaudit/README.md", "rb") as f:
|
||||
long_descr = f.read().decode("utf-8")
|
||||
|
||||
|
||||
setup(
|
||||
name = "ssh-audit",
|
||||
packages = ["sshaudit"],
|
||||
license = 'MIT',
|
||||
entry_points = {
|
||||
"console_scripts": ['ssh-audit = sshaudit.sshaudit:main']
|
||||
},
|
||||
version = version,
|
||||
description = "An SSH server configuration security auditing tool",
|
||||
long_description = long_descr,
|
||||
long_description_content_type = "text/markdown",
|
||||
author = "Joe Testa",
|
||||
author_email = "jtesta@positronsecurity.com",
|
||||
url = "https://github.com/jtesta/ssh-audit",
|
||||
classifiers = [
|
||||
"Development Status :: 5 - Production/Stable",
|
||||
"Intended Audience :: Information Technology",
|
||||
"Intended Audience :: System Administrators",
|
||||
"License :: OSI Approved :: MIT License",
|
||||
"Operating System :: OS Independent",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Topic :: Security",
|
||||
"Topic :: Security :: Cryptography"
|
||||
])
|
0
pypi/sshaudit/__init__.py
Normal file
0
pypi/sshaudit/__init__.py
Normal file
4
pypi/sshaudit/__main__.py
Normal file
4
pypi/sshaudit/__main__.py
Normal file
@ -0,0 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from .sshaudit import main
|
||||
main()
|
3039
ssh-audit.py
3039
ssh-audit.py
File diff suppressed because it is too large
Load Diff
148
test/conftest.py
148
test/conftest.py
@ -1,10 +1,156 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
import os, sys
|
||||
import os
|
||||
import io
|
||||
import sys
|
||||
import socket
|
||||
import pytest
|
||||
|
||||
|
||||
if sys.version_info[0] == 2:
|
||||
import StringIO # pylint: disable=import-error
|
||||
StringIO = StringIO.StringIO
|
||||
else:
|
||||
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')
|
||||
|
||||
|
||||
# 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 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()
|
||||
|
||||
|
||||
class _VirtualGlobalSocket(object):
|
||||
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 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 []
|
||||
|
||||
|
||||
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 _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, 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 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 getsockname(self):
|
||||
return self.sock_address
|
||||
|
||||
def bind(self, address):
|
||||
self.sock_address = address
|
||||
|
||||
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 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)
|
||||
|
||||
|
||||
@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
|
||||
|
1
test/docker/.ed25519.sk
Normal file
1
test/docker/.ed25519.sk
Normal file
@ -0,0 +1 @@
|
||||
iܛ<EFBFBD><EFBFBD><EFBFBD><1C><><EFBFBD>V<EFBFBD>违<EFBFBD>Z/D<><<3C><>|S<>z<EFBFBD>=<3D>:<3A>1vu}<7D><><11>J<EFBFBD>ݷ<EFBFBD><DDB7>"<22>^Bb&U<><03>P<EFBFBD><50>
|
32
test/docker/Dockerfile
Normal file
32
test/docker/Dockerfile
Normal file
@ -0,0 +1,32 @@
|
||||
FROM ubuntu:16.04
|
||||
|
||||
COPY openssh-4.0p1/sshd /openssh/sshd-4.0p1
|
||||
COPY openssh-5.6p1/sshd /openssh/sshd-5.6p1
|
||||
COPY openssh-8.0p1/sshd /openssh/sshd-8.0p1
|
||||
COPY dropbear-2019.78/dropbear /dropbear/dropbear-2019.78
|
||||
COPY tinyssh-20190101/build/bin/tinysshd /tinysshd/tinyssh-20190101
|
||||
|
||||
# Dropbear host keys.
|
||||
COPY dropbear_*_host_key* /etc/dropbear/
|
||||
|
||||
# OpenSSH configs.
|
||||
COPY sshd_config* /etc/ssh/
|
||||
|
||||
# OpenSSH host keys & moduli file.
|
||||
COPY ssh_host_* /etc/ssh/
|
||||
COPY ssh1_host_* /etc/ssh/
|
||||
COPY moduli_1024 /usr/local/etc/moduli
|
||||
|
||||
# TinySSH host keys.
|
||||
COPY ed25519.pk /etc/tinyssh/
|
||||
COPY .ed25519.sk /etc/tinyssh/
|
||||
|
||||
COPY debug.sh /debug.sh
|
||||
|
||||
RUN apt update 2> /dev/null
|
||||
RUN apt install -y libssl-dev strace rsyslog ucspi-tcp 2> /dev/null
|
||||
RUN apt clean 2> /dev/null
|
||||
RUN useradd -s /bin/false sshd
|
||||
RUN mkdir /var/empty
|
||||
|
||||
EXPOSE 22
|
9
test/docker/debug.sh
Executable file
9
test/docker/debug.sh
Executable file
@ -0,0 +1,9 @@
|
||||
#!/bin/bash
|
||||
|
||||
# This script is run on in docker container. It will enable logging for sshd in
|
||||
# /var/log/auth.log.
|
||||
|
||||
/etc/init.d/rsyslog start
|
||||
sleep 1
|
||||
/openssh/sshd-5.6p1 -o LogLevel=DEBUG3 -f /etc/ssh/sshd_config-5.6p1_test1
|
||||
/bin/bash
|
BIN
test/docker/dropbear_dss_host_key
Normal file
BIN
test/docker/dropbear_dss_host_key
Normal file
Binary file not shown.
BIN
test/docker/dropbear_ecdsa_host_key
Normal file
BIN
test/docker/dropbear_ecdsa_host_key
Normal file
Binary file not shown.
BIN
test/docker/dropbear_rsa_host_key_1024
Normal file
BIN
test/docker/dropbear_rsa_host_key_1024
Normal file
Binary file not shown.
BIN
test/docker/dropbear_rsa_host_key_3072
Normal file
BIN
test/docker/dropbear_rsa_host_key_3072
Normal file
Binary file not shown.
1
test/docker/ed25519.pk
Normal file
1
test/docker/ed25519.pk
Normal file
@ -0,0 +1 @@
|
||||
1vu}<7D><><11>J<EFBFBD>ݷ<EFBFBD><DDB7>"<22>^Bb&U<><03>P<EFBFBD><50>
|
1
test/docker/expected_results/dropbear_2019.78_test1.json
Normal file
1
test/docker/expected_results/dropbear_2019.78_test1.json
Normal file
@ -0,0 +1 @@
|
||||
{"banner": {"comments": null, "protocol": [2, 0], "raw": "SSH-2.0-dropbear_2019.78", "software": "dropbear_2019.78"}, "compression": ["zlib@openssh.com", "none"], "enc": ["aes128-ctr", "aes256-ctr", "aes128-cbc", "aes256-cbc", "3des-ctr", "3des-cbc"], "fingerprints": [{"fp": "SHA256:CDfAU12pjQS7/91kg7gYacza0U/6PDbE04Ic3IpYxkM", "type": "ssh-rsa"}], "kex": [{"algorithm": "curve25519-sha256"}, {"algorithm": "curve25519-sha256@libssh.org"}, {"algorithm": "ecdh-sha2-nistp521"}, {"algorithm": "ecdh-sha2-nistp384"}, {"algorithm": "ecdh-sha2-nistp256"}, {"algorithm": "diffie-hellman-group14-sha256"}, {"algorithm": "diffie-hellman-group14-sha1"}, {"algorithm": "kexguess2@matt.ucc.asn.au"}], "key": [{"algorithm": "ecdsa-sha2-nistp256"}, {"algorithm": "ssh-rsa", "keysize": 1024}, {"algorithm": "ssh-dss"}], "mac": ["hmac-sha1-96", "hmac-sha1", "hmac-sha2-256"]}
|
85
test/docker/expected_results/dropbear_2019.78_test1.txt
Normal file
85
test/docker/expected_results/dropbear_2019.78_test1.txt
Normal file
@ -0,0 +1,85 @@
|
||||
[0;36m# general[0m
|
||||
[0;32m(gen) banner: SSH-2.0-dropbear_2019.78[0m
|
||||
[0;32m(gen) software: Dropbear SSH 2019.78[0m
|
||||
[0;32m(gen) compatibility: OpenSSH 7.4+ (some functionality from 6.6), Dropbear SSH 2018.76+[0m
|
||||
[0;32m(gen) compression: enabled (zlib@openssh.com)[0m
|
||||
|
||||
[0;36m# key exchange algorithms[0m
|
||||
[0;32m(kex) curve25519-sha256 -- [info] available since OpenSSH 7.4, Dropbear SSH 2018.76[0m
|
||||
[0;32m(kex) curve25519-sha256@libssh.org -- [info] available since OpenSSH 6.5, Dropbear SSH 2013.62[0m
|
||||
[0;31m(kex) ecdh-sha2-nistp521 -- [fail] using weak elliptic curves[0m
|
||||
`- [info] available since OpenSSH 5.7, Dropbear SSH 2013.62
|
||||
[0;31m(kex) ecdh-sha2-nistp384 -- [fail] using weak elliptic curves[0m
|
||||
`- [info] available since OpenSSH 5.7, Dropbear SSH 2013.62
|
||||
[0;31m(kex) ecdh-sha2-nistp256 -- [fail] using weak elliptic curves[0m
|
||||
`- [info] available since OpenSSH 5.7, Dropbear SSH 2013.62
|
||||
[0;32m(kex) diffie-hellman-group14-sha256 -- [info] available since OpenSSH 7.3, Dropbear SSH 2016.73[0m
|
||||
[0;33m(kex) diffie-hellman-group14-sha1 -- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 3.9, Dropbear SSH 0.53
|
||||
[0;32m(kex) kexguess2@matt.ucc.asn.au -- [info] available since Dropbear SSH 2013.57[0m
|
||||
|
||||
[0;36m# host-key algorithms[0m
|
||||
[0;31m(key) ecdsa-sha2-nistp256 -- [fail] using weak elliptic curves[0m
|
||||
[0;33m `- [warn] using weak random number generator could reveal the key[0m
|
||||
`- [info] available since OpenSSH 5.7, Dropbear SSH 2013.62
|
||||
[0;31m(key) ssh-rsa (1024-bit) -- [fail] using small 1024-bit modulus[0m
|
||||
`- [info] available since OpenSSH 2.5.0, Dropbear SSH 0.28
|
||||
[0;31m(key) ssh-dss -- [fail] removed (in server) and disabled (in client) since OpenSSH 7.0, weak algorithm[0m
|
||||
[0;33m `- [warn] using small 1024-bit modulus[0m
|
||||
[0;33m `- [warn] using weak random number generator could reveal the key[0m
|
||||
`- [info] available since OpenSSH 2.1.0, Dropbear SSH 0.28
|
||||
|
||||
[0;36m# encryption algorithms (ciphers)[0m
|
||||
[0;32m(enc) aes128-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52[0m
|
||||
[0;32m(enc) aes256-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52[0m
|
||||
[0;31m(enc) aes128-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher mode[0m
|
||||
`- [info] available since OpenSSH 2.3.0, Dropbear SSH 0.28
|
||||
[0;31m(enc) aes256-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher mode[0m
|
||||
`- [info] available since OpenSSH 2.3.0, Dropbear SSH 0.47
|
||||
[0;31m(enc) 3des-ctr -- [fail] using weak cipher[0m
|
||||
`- [info] available since Dropbear SSH 0.52
|
||||
[0;31m(enc) 3des-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.4, unsafe algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher[0m
|
||||
[0;33m `- [warn] using weak cipher mode[0m
|
||||
[0;33m `- [warn] using small 64-bit block size[0m
|
||||
`- [info] available since OpenSSH 1.2.2, Dropbear SSH 0.28
|
||||
|
||||
[0;36m# message authentication code algorithms[0m
|
||||
[0;31m(mac) hmac-sha1-96 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using encrypt-and-MAC mode[0m
|
||||
[0;33m `- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 2.5.0, Dropbear SSH 0.47
|
||||
[0;33m(mac) hmac-sha1 -- [warn] using encrypt-and-MAC mode[0m
|
||||
[0;33m `- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 2.1.0, Dropbear SSH 0.28
|
||||
[0;33m(mac) hmac-sha2-256 -- [warn] using encrypt-and-MAC mode[0m
|
||||
`- [info] available since OpenSSH 5.9, Dropbear SSH 2013.56
|
||||
|
||||
[0;36m# fingerprints[0m
|
||||
[0;32m(fin) ssh-rsa: SHA256:CDfAU12pjQS7/91kg7gYacza0U/6PDbE04Ic3IpYxkM[0m
|
||||
|
||||
[0;36m# algorithm recommendations (for Dropbear SSH 2019.78)[0m
|
||||
[0;31m(rec) !ssh-rsa -- key algorithm to change (increase modulus size to 2048 bits or larger) [0m
|
||||
[0;31m(rec) -3des-cbc -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -3des-ctr -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -aes128-cbc -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -aes256-cbc -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -ecdh-sha2-nistp256 -- kex algorithm to remove [0m
|
||||
[0;31m(rec) -ecdh-sha2-nistp384 -- kex algorithm to remove [0m
|
||||
[0;31m(rec) -ecdh-sha2-nistp521 -- kex algorithm to remove [0m
|
||||
[0;31m(rec) -ecdsa-sha2-nistp256 -- key algorithm to remove [0m
|
||||
[0;31m(rec) -hmac-sha1-96 -- mac algorithm to remove [0m
|
||||
[0;31m(rec) -ssh-dss -- key algorithm to remove [0m
|
||||
[0;32m(rec) +diffie-hellman-group16-sha512 -- kex algorithm to append [0m
|
||||
[0;32m(rec) +twofish128-ctr -- enc algorithm to append [0m
|
||||
[0;32m(rec) +twofish256-ctr -- enc algorithm to append [0m
|
||||
[0;33m(rec) -diffie-hellman-group14-sha1 -- kex algorithm to remove [0m
|
||||
[0;33m(rec) -hmac-sha1 -- mac algorithm to remove [0m
|
||||
|
||||
[0;36m# additional info[0m
|
||||
[0;33m(nfo) For hardening guides on common OSes, please see: <https://www.ssh-audit.com/hardening_guides.html>[0m
|
||||
|
1
test/docker/expected_results/openssh_4.0p1_test1.json
Normal file
1
test/docker/expected_results/openssh_4.0p1_test1.json
Normal file
@ -0,0 +1 @@
|
||||
{"banner": {"comments": null, "protocol": [1, 99], "raw": "SSH-1.99-OpenSSH_4.0", "software": "OpenSSH_4.0"}, "compression": ["none", "zlib"], "enc": ["aes128-cbc", "3des-cbc", "blowfish-cbc", "cast128-cbc", "arcfour", "aes192-cbc", "aes256-cbc", "rijndael-cbc@lysator.liu.se", "aes128-ctr", "aes192-ctr", "aes256-ctr"], "fingerprints": [{"fp": "SHA256:YZ457EBcJTSxRKI3yXRgtAj3PBf5B9/F36b1SVooml4", "type": "ssh-rsa"}], "kex": [{"algorithm": "diffie-hellman-group-exchange-sha1", "keysize": 1024}, {"algorithm": "diffie-hellman-group14-sha1"}, {"algorithm": "diffie-hellman-group1-sha1"}], "key": [{"algorithm": "ssh-rsa", "keysize": 1024}, {"algorithm": "ssh-dss"}], "mac": ["hmac-md5", "hmac-sha1", "hmac-ripemd160", "hmac-ripemd160@openssh.com", "hmac-sha1-96", "hmac-md5-96"]}
|
139
test/docker/expected_results/openssh_4.0p1_test1.txt
Normal file
139
test/docker/expected_results/openssh_4.0p1_test1.txt
Normal file
@ -0,0 +1,139 @@
|
||||
[0;36m# general[0m
|
||||
[0;32m(gen) banner: SSH-1.99-OpenSSH_4.0[0m
|
||||
[0;31m(gen) protocol SSH1 enabled[0m
|
||||
[0;32m(gen) software: OpenSSH 4.0[0m
|
||||
[0;32m(gen) compatibility: OpenSSH 3.9-6.6, Dropbear SSH 0.53+ (some functionality from 0.52)[0m
|
||||
[0;32m(gen) compression: enabled (zlib)[0m
|
||||
|
||||
[0;36m# security[0m
|
||||
[0;33m(cve) CVE-2016-3115 -- (CVSSv2: 5.5) bypass command restrictions via crafted X11 forwarding data[0m
|
||||
[0;33m(cve) CVE-2014-1692 -- (CVSSv2: 7.5) cause DoS via triggering error condition (memory corruption)[0m
|
||||
[0;33m(cve) CVE-2012-0814 -- (CVSSv2: 3.5) leak data via debug messages[0m
|
||||
[0;33m(cve) CVE-2011-5000 -- (CVSSv2: 3.5) cause DoS via large value in certain length field (memory consumption)[0m
|
||||
[0;33m(cve) CVE-2010-5107 -- (CVSSv2: 5.0) cause DoS via large number of connections (slot exhaustion)[0m
|
||||
[0;33m(cve) CVE-2010-4755 -- (CVSSv2: 4.0) cause DoS via crafted glob expression (CPU and memory consumption)[0m
|
||||
[0;33m(cve) CVE-2010-4478 -- (CVSSv2: 7.5) bypass authentication check via crafted values[0m
|
||||
[0;33m(cve) CVE-2008-5161 -- (CVSSv2: 2.6) recover plaintext data from ciphertext[0m
|
||||
[0;33m(cve) CVE-2008-4109 -- (CVSSv2: 5.0) cause DoS via multiple login attempts (slot exhaustion)[0m
|
||||
[0;33m(cve) CVE-2008-1657 -- (CVSSv2: 6.5) bypass command restrictions via modifying session file[0m
|
||||
[0;33m(cve) CVE-2008-1483 -- (CVSSv2: 6.9) hijack forwarded X11 connections[0m
|
||||
[0;33m(cve) CVE-2007-4752 -- (CVSSv2: 7.5) privilege escalation via causing an X client to be trusted[0m
|
||||
[0;33m(cve) CVE-2007-2243 -- (CVSSv2: 5.0) discover valid usernames through different responses[0m
|
||||
[0;33m(cve) CVE-2006-5052 -- (CVSSv2: 5.0) discover valid usernames through different responses[0m
|
||||
[0;31m(cve) CVE-2006-5051 -- (CVSSv2: 9.3) cause DoS or execute arbitrary code (double free)[0m
|
||||
[0;33m(cve) CVE-2006-4924 -- (CVSSv2: 7.8) cause DoS via crafted packet (CPU consumption)[0m
|
||||
[0;33m(cve) CVE-2006-0225 -- (CVSSv2: 4.6) execute arbitrary code[0m
|
||||
[0;33m(cve) CVE-2005-2798 -- (CVSSv2: 5.0) leak data about authentication credentials[0m
|
||||
|
||||
[0;36m# key exchange algorithms[0m
|
||||
[0;31m(kex) diffie-hellman-group-exchange-sha1 (1024-bit) -- [fail] using small 1024-bit modulus[0m
|
||||
[0;33m `- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 2.3.0
|
||||
[0;33m(kex) diffie-hellman-group14-sha1 -- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 3.9, Dropbear SSH 0.53
|
||||
[0;31m(kex) diffie-hellman-group1-sha1 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;31m `- [fail] disabled (in client) since OpenSSH 7.0, logjam attack[0m
|
||||
[0;33m `- [warn] using small 1024-bit modulus[0m
|
||||
[0;33m `- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 2.3.0, Dropbear SSH 0.28
|
||||
|
||||
[0;36m# host-key algorithms[0m
|
||||
[0;31m(key) ssh-rsa (1024-bit) -- [fail] using small 1024-bit modulus[0m
|
||||
`- [info] available since OpenSSH 2.5.0, Dropbear SSH 0.28
|
||||
[0;31m(key) ssh-dss -- [fail] removed (in server) and disabled (in client) since OpenSSH 7.0, weak algorithm[0m
|
||||
[0;33m `- [warn] using small 1024-bit modulus[0m
|
||||
[0;33m `- [warn] using weak random number generator could reveal the key[0m
|
||||
`- [info] available since OpenSSH 2.1.0, Dropbear SSH 0.28
|
||||
|
||||
[0;36m# encryption algorithms (ciphers)[0m
|
||||
[0;31m(enc) aes128-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher mode[0m
|
||||
`- [info] available since OpenSSH 2.3.0, Dropbear SSH 0.28
|
||||
[0;31m(enc) 3des-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.4, unsafe algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher[0m
|
||||
[0;33m `- [warn] using weak cipher mode[0m
|
||||
[0;33m `- [warn] using small 64-bit block size[0m
|
||||
`- [info] available since OpenSSH 1.2.2, Dropbear SSH 0.28
|
||||
[0;31m(enc) blowfish-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;31m `- [fail] disabled since Dropbear SSH 0.53[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher mode[0m
|
||||
[0;33m `- [warn] using small 64-bit block size[0m
|
||||
`- [info] available since OpenSSH 1.2.2, Dropbear SSH 0.28
|
||||
[0;31m(enc) cast128-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher mode[0m
|
||||
[0;33m `- [warn] using small 64-bit block size[0m
|
||||
`- [info] available since OpenSSH 2.1.0
|
||||
[0;31m(enc) arcfour -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher[0m
|
||||
`- [info] available since OpenSSH 2.1.0
|
||||
[0;31m(enc) aes192-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher mode[0m
|
||||
`- [info] available since OpenSSH 2.3.0
|
||||
[0;31m(enc) aes256-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher mode[0m
|
||||
`- [info] available since OpenSSH 2.3.0, Dropbear SSH 0.47
|
||||
[0;31m(enc) rijndael-cbc@lysator.liu.se -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher mode[0m
|
||||
`- [info] available since OpenSSH 2.3.0
|
||||
[0;32m(enc) aes128-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52[0m
|
||||
[0;32m(enc) aes192-ctr -- [info] available since OpenSSH 3.7[0m
|
||||
[0;32m(enc) aes256-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52[0m
|
||||
|
||||
[0;36m# message authentication code algorithms[0m
|
||||
[0;31m(mac) hmac-md5 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using encrypt-and-MAC mode[0m
|
||||
[0;33m `- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 2.1.0, Dropbear SSH 0.28
|
||||
[0;33m(mac) hmac-sha1 -- [warn] using encrypt-and-MAC mode[0m
|
||||
[0;33m `- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 2.1.0, Dropbear SSH 0.28
|
||||
[0;31m(mac) hmac-ripemd160 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using encrypt-and-MAC mode[0m
|
||||
`- [info] available since OpenSSH 2.5.0
|
||||
[0;31m(mac) hmac-ripemd160@openssh.com -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using encrypt-and-MAC mode[0m
|
||||
`- [info] available since OpenSSH 2.1.0
|
||||
[0;31m(mac) hmac-sha1-96 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using encrypt-and-MAC mode[0m
|
||||
[0;33m `- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 2.5.0, Dropbear SSH 0.47
|
||||
[0;31m(mac) hmac-md5-96 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using encrypt-and-MAC mode[0m
|
||||
[0;33m `- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 2.5.0
|
||||
|
||||
[0;36m# fingerprints[0m
|
||||
[0;32m(fin) ssh-rsa: SHA256:YZ457EBcJTSxRKI3yXRgtAj3PBf5B9/F36b1SVooml4[0m
|
||||
|
||||
[0;36m# algorithm recommendations (for OpenSSH 4.0)[0m
|
||||
[0;31m(rec) !ssh-rsa -- key algorithm to change (increase modulus size to 2048 bits or larger) [0m
|
||||
[0;31m(rec) -3des-cbc -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -aes128-cbc -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -aes192-cbc -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -aes256-cbc -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -arcfour -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -blowfish-cbc -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -cast128-cbc -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -diffie-hellman-group-exchange-sha1 -- kex algorithm to remove [0m
|
||||
[0;31m(rec) -diffie-hellman-group1-sha1 -- kex algorithm to remove [0m
|
||||
[0;31m(rec) -hmac-md5 -- mac algorithm to remove [0m
|
||||
[0;31m(rec) -hmac-md5-96 -- mac algorithm to remove [0m
|
||||
[0;31m(rec) -hmac-ripemd160 -- mac algorithm to remove [0m
|
||||
[0;31m(rec) -hmac-ripemd160@openssh.com -- mac algorithm to remove [0m
|
||||
[0;31m(rec) -hmac-sha1-96 -- mac algorithm to remove [0m
|
||||
[0;31m(rec) -rijndael-cbc@lysator.liu.se -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -ssh-dss -- key algorithm to remove [0m
|
||||
|
||||
[0;36m# additional info[0m
|
||||
[0;33m(nfo) For hardening guides on common OSes, please see: <https://www.ssh-audit.com/hardening_guides.html>[0m
|
||||
|
1
test/docker/expected_results/openssh_5.6p1_test1.json
Normal file
1
test/docker/expected_results/openssh_5.6p1_test1.json
Normal file
@ -0,0 +1 @@
|
||||
{"banner": {"comments": null, "protocol": [2, 0], "raw": "SSH-2.0-OpenSSH_5.6", "software": "OpenSSH_5.6"}, "compression": ["none", "zlib@openssh.com"], "enc": ["aes128-ctr", "aes192-ctr", "aes256-ctr", "arcfour256", "arcfour128", "aes128-cbc", "3des-cbc", "blowfish-cbc", "cast128-cbc", "aes192-cbc", "aes256-cbc", "arcfour", "rijndael-cbc@lysator.liu.se"], "fingerprints": [{"fp": "SHA256:YZ457EBcJTSxRKI3yXRgtAj3PBf5B9/F36b1SVooml4", "type": "ssh-rsa"}], "kex": [{"algorithm": "diffie-hellman-group-exchange-sha256", "keysize": 1024}, {"algorithm": "diffie-hellman-group-exchange-sha1", "keysize": 1024}, {"algorithm": "diffie-hellman-group14-sha1"}, {"algorithm": "diffie-hellman-group1-sha1"}], "key": [{"algorithm": "ssh-rsa", "keysize": 1024}, {"algorithm": "ssh-dss"}], "mac": ["hmac-md5", "hmac-sha1", "umac-64@openssh.com", "hmac-ripemd160", "hmac-ripemd160@openssh.com", "hmac-sha1-96", "hmac-md5-96"]}
|
148
test/docker/expected_results/openssh_5.6p1_test1.txt
Normal file
148
test/docker/expected_results/openssh_5.6p1_test1.txt
Normal file
@ -0,0 +1,148 @@
|
||||
[0;36m# general[0m
|
||||
[0;32m(gen) banner: SSH-2.0-OpenSSH_5.6[0m
|
||||
[0;32m(gen) software: OpenSSH 5.6[0m
|
||||
[0;32m(gen) compatibility: OpenSSH 4.7-6.6, Dropbear SSH 0.53+ (some functionality from 0.52)[0m
|
||||
[0;32m(gen) compression: enabled (zlib@openssh.com)[0m
|
||||
|
||||
[0;36m# security[0m
|
||||
[0;33m(cve) CVE-2016-3115 -- (CVSSv2: 5.5) bypass command restrictions via crafted X11 forwarding data[0m
|
||||
[0;33m(cve) CVE-2016-1907 -- (CVSSv2: 5.0) cause DoS via crafted network traffic (out of bounds read)[0m
|
||||
[0;33m(cve) CVE-2015-6564 -- (CVSSv2: 6.9) privilege escalation via leveraging sshd uid[0m
|
||||
[0;33m(cve) CVE-2015-6563 -- (CVSSv2: 1.9) conduct impersonation attack[0m
|
||||
[0;33m(cve) CVE-2014-2532 -- (CVSSv2: 5.8) bypass environment restrictions via specific string before wildcard[0m
|
||||
[0;33m(cve) CVE-2014-1692 -- (CVSSv2: 7.5) cause DoS via triggering error condition (memory corruption)[0m
|
||||
[0;33m(cve) CVE-2012-0814 -- (CVSSv2: 3.5) leak data via debug messages[0m
|
||||
[0;33m(cve) CVE-2011-5000 -- (CVSSv2: 3.5) cause DoS via large value in certain length field (memory consumption)[0m
|
||||
[0;33m(cve) CVE-2010-5107 -- (CVSSv2: 5.0) cause DoS via large number of connections (slot exhaustion)[0m
|
||||
[0;33m(cve) CVE-2010-4755 -- (CVSSv2: 4.0) cause DoS via crafted glob expression (CPU and memory consumption)[0m
|
||||
[0;33m(cve) CVE-2010-4478 -- (CVSSv2: 7.5) bypass authentication check via crafted values[0m
|
||||
|
||||
[0;36m# key exchange algorithms[0m
|
||||
[0;31m(kex) diffie-hellman-group-exchange-sha256 (1024-bit) -- [fail] using small 1024-bit modulus[0m
|
||||
`- [info] available since OpenSSH 4.4
|
||||
[0;31m(kex) diffie-hellman-group-exchange-sha1 (1024-bit) -- [fail] using small 1024-bit modulus[0m
|
||||
[0;33m `- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 2.3.0
|
||||
[0;33m(kex) diffie-hellman-group14-sha1 -- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 3.9, Dropbear SSH 0.53
|
||||
[0;31m(kex) diffie-hellman-group1-sha1 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;31m `- [fail] disabled (in client) since OpenSSH 7.0, logjam attack[0m
|
||||
[0;33m `- [warn] using small 1024-bit modulus[0m
|
||||
[0;33m `- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 2.3.0, Dropbear SSH 0.28
|
||||
|
||||
[0;36m# host-key algorithms[0m
|
||||
[0;31m(key) ssh-rsa (1024-bit) -- [fail] using small 1024-bit modulus[0m
|
||||
`- [info] available since OpenSSH 2.5.0, Dropbear SSH 0.28
|
||||
[0;31m(key) ssh-dss -- [fail] removed (in server) and disabled (in client) since OpenSSH 7.0, weak algorithm[0m
|
||||
[0;33m `- [warn] using small 1024-bit modulus[0m
|
||||
[0;33m `- [warn] using weak random number generator could reveal the key[0m
|
||||
`- [info] available since OpenSSH 2.1.0, Dropbear SSH 0.28
|
||||
|
||||
[0;36m# encryption algorithms (ciphers)[0m
|
||||
[0;32m(enc) aes128-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52[0m
|
||||
[0;32m(enc) aes192-ctr -- [info] available since OpenSSH 3.7[0m
|
||||
[0;32m(enc) aes256-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52[0m
|
||||
[0;31m(enc) arcfour256 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher[0m
|
||||
`- [info] available since OpenSSH 4.2
|
||||
[0;31m(enc) arcfour128 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher[0m
|
||||
`- [info] available since OpenSSH 4.2
|
||||
[0;31m(enc) aes128-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher mode[0m
|
||||
`- [info] available since OpenSSH 2.3.0, Dropbear SSH 0.28
|
||||
[0;31m(enc) 3des-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.4, unsafe algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher[0m
|
||||
[0;33m `- [warn] using weak cipher mode[0m
|
||||
[0;33m `- [warn] using small 64-bit block size[0m
|
||||
`- [info] available since OpenSSH 1.2.2, Dropbear SSH 0.28
|
||||
[0;31m(enc) blowfish-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;31m `- [fail] disabled since Dropbear SSH 0.53[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher mode[0m
|
||||
[0;33m `- [warn] using small 64-bit block size[0m
|
||||
`- [info] available since OpenSSH 1.2.2, Dropbear SSH 0.28
|
||||
[0;31m(enc) cast128-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher mode[0m
|
||||
[0;33m `- [warn] using small 64-bit block size[0m
|
||||
`- [info] available since OpenSSH 2.1.0
|
||||
[0;31m(enc) aes192-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher mode[0m
|
||||
`- [info] available since OpenSSH 2.3.0
|
||||
[0;31m(enc) aes256-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher mode[0m
|
||||
`- [info] available since OpenSSH 2.3.0, Dropbear SSH 0.47
|
||||
[0;31m(enc) arcfour -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher[0m
|
||||
`- [info] available since OpenSSH 2.1.0
|
||||
[0;31m(enc) rijndael-cbc@lysator.liu.se -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher mode[0m
|
||||
`- [info] available since OpenSSH 2.3.0
|
||||
|
||||
[0;36m# message authentication code algorithms[0m
|
||||
[0;31m(mac) hmac-md5 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using encrypt-and-MAC mode[0m
|
||||
[0;33m `- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 2.1.0, Dropbear SSH 0.28
|
||||
[0;33m(mac) hmac-sha1 -- [warn] using encrypt-and-MAC mode[0m
|
||||
[0;33m `- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 2.1.0, Dropbear SSH 0.28
|
||||
[0;33m(mac) umac-64@openssh.com -- [warn] using encrypt-and-MAC mode[0m
|
||||
[0;33m `- [warn] using small 64-bit tag size[0m
|
||||
`- [info] available since OpenSSH 4.7
|
||||
[0;31m(mac) hmac-ripemd160 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using encrypt-and-MAC mode[0m
|
||||
`- [info] available since OpenSSH 2.5.0
|
||||
[0;31m(mac) hmac-ripemd160@openssh.com -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using encrypt-and-MAC mode[0m
|
||||
`- [info] available since OpenSSH 2.1.0
|
||||
[0;31m(mac) hmac-sha1-96 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using encrypt-and-MAC mode[0m
|
||||
[0;33m `- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 2.5.0, Dropbear SSH 0.47
|
||||
[0;31m(mac) hmac-md5-96 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using encrypt-and-MAC mode[0m
|
||||
[0;33m `- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 2.5.0
|
||||
|
||||
[0;36m# fingerprints[0m
|
||||
[0;32m(fin) ssh-rsa: SHA256:YZ457EBcJTSxRKI3yXRgtAj3PBf5B9/F36b1SVooml4[0m
|
||||
|
||||
[0;36m# algorithm recommendations (for OpenSSH 5.6)[0m
|
||||
[0;31m(rec) !diffie-hellman-group-exchange-sha256 -- kex algorithm to change (increase modulus size to 2048 bits or larger) [0m
|
||||
[0;31m(rec) !ssh-rsa -- key algorithm to change (increase modulus size to 2048 bits or larger) [0m
|
||||
[0;31m(rec) -3des-cbc -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -aes128-cbc -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -aes192-cbc -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -aes256-cbc -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -arcfour -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -arcfour128 -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -arcfour256 -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -blowfish-cbc -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -cast128-cbc -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -diffie-hellman-group-exchange-sha1 -- kex algorithm to remove [0m
|
||||
[0;31m(rec) -diffie-hellman-group1-sha1 -- kex algorithm to remove [0m
|
||||
[0;31m(rec) -hmac-md5 -- mac algorithm to remove [0m
|
||||
[0;31m(rec) -hmac-md5-96 -- mac algorithm to remove [0m
|
||||
[0;31m(rec) -hmac-ripemd160 -- mac algorithm to remove [0m
|
||||
[0;31m(rec) -hmac-ripemd160@openssh.com -- mac algorithm to remove [0m
|
||||
[0;31m(rec) -hmac-sha1-96 -- mac algorithm to remove [0m
|
||||
[0;31m(rec) -rijndael-cbc@lysator.liu.se -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -ssh-dss -- key algorithm to remove [0m
|
||||
[0;33m(rec) -diffie-hellman-group14-sha1 -- kex algorithm to remove [0m
|
||||
|
||||
[0;36m# additional info[0m
|
||||
[0;33m(nfo) For hardening guides on common OSes, please see: <https://www.ssh-audit.com/hardening_guides.html>[0m
|
||||
|
1
test/docker/expected_results/openssh_5.6p1_test2.json
Normal file
1
test/docker/expected_results/openssh_5.6p1_test2.json
Normal file
@ -0,0 +1 @@
|
||||
{"banner": {"comments": null, "protocol": [2, 0], "raw": "SSH-2.0-OpenSSH_5.6", "software": "OpenSSH_5.6"}, "compression": ["none", "zlib@openssh.com"], "enc": ["aes128-ctr", "aes192-ctr", "aes256-ctr", "arcfour256", "arcfour128", "aes128-cbc", "3des-cbc", "blowfish-cbc", "cast128-cbc", "aes192-cbc", "aes256-cbc", "arcfour", "rijndael-cbc@lysator.liu.se"], "fingerprints": [{"fp": "SHA256:YZ457EBcJTSxRKI3yXRgtAj3PBf5B9/F36b1SVooml4", "type": "ssh-rsa"}], "kex": [{"algorithm": "diffie-hellman-group-exchange-sha256", "keysize": 1024}, {"algorithm": "diffie-hellman-group-exchange-sha1", "keysize": 1024}, {"algorithm": "diffie-hellman-group14-sha1"}, {"algorithm": "diffie-hellman-group1-sha1"}], "key": [{"algorithm": "ssh-rsa", "keysize": 1024}, {"algorithm": "ssh-rsa-cert-v01@openssh.com", "casize": 1024, "keysize": 1024}], "mac": ["hmac-md5", "hmac-sha1", "umac-64@openssh.com", "hmac-ripemd160", "hmac-ripemd160@openssh.com", "hmac-sha1-96", "hmac-md5-96"]}
|
146
test/docker/expected_results/openssh_5.6p1_test2.txt
Normal file
146
test/docker/expected_results/openssh_5.6p1_test2.txt
Normal file
@ -0,0 +1,146 @@
|
||||
[0;36m# general[0m
|
||||
[0;32m(gen) banner: SSH-2.0-OpenSSH_5.6[0m
|
||||
[0;32m(gen) software: OpenSSH 5.6[0m
|
||||
[0;32m(gen) compatibility: OpenSSH 5.6-6.6, Dropbear SSH 0.53+ (some functionality from 0.52)[0m
|
||||
[0;32m(gen) compression: enabled (zlib@openssh.com)[0m
|
||||
|
||||
[0;36m# security[0m
|
||||
[0;33m(cve) CVE-2016-3115 -- (CVSSv2: 5.5) bypass command restrictions via crafted X11 forwarding data[0m
|
||||
[0;33m(cve) CVE-2016-1907 -- (CVSSv2: 5.0) cause DoS via crafted network traffic (out of bounds read)[0m
|
||||
[0;33m(cve) CVE-2015-6564 -- (CVSSv2: 6.9) privilege escalation via leveraging sshd uid[0m
|
||||
[0;33m(cve) CVE-2015-6563 -- (CVSSv2: 1.9) conduct impersonation attack[0m
|
||||
[0;33m(cve) CVE-2014-2532 -- (CVSSv2: 5.8) bypass environment restrictions via specific string before wildcard[0m
|
||||
[0;33m(cve) CVE-2014-1692 -- (CVSSv2: 7.5) cause DoS via triggering error condition (memory corruption)[0m
|
||||
[0;33m(cve) CVE-2012-0814 -- (CVSSv2: 3.5) leak data via debug messages[0m
|
||||
[0;33m(cve) CVE-2011-5000 -- (CVSSv2: 3.5) cause DoS via large value in certain length field (memory consumption)[0m
|
||||
[0;33m(cve) CVE-2010-5107 -- (CVSSv2: 5.0) cause DoS via large number of connections (slot exhaustion)[0m
|
||||
[0;33m(cve) CVE-2010-4755 -- (CVSSv2: 4.0) cause DoS via crafted glob expression (CPU and memory consumption)[0m
|
||||
[0;33m(cve) CVE-2010-4478 -- (CVSSv2: 7.5) bypass authentication check via crafted values[0m
|
||||
|
||||
[0;36m# key exchange algorithms[0m
|
||||
[0;31m(kex) diffie-hellman-group-exchange-sha256 (1024-bit) -- [fail] using small 1024-bit modulus[0m
|
||||
`- [info] available since OpenSSH 4.4
|
||||
[0;31m(kex) diffie-hellman-group-exchange-sha1 (1024-bit) -- [fail] using small 1024-bit modulus[0m
|
||||
[0;33m `- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 2.3.0
|
||||
[0;33m(kex) diffie-hellman-group14-sha1 -- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 3.9, Dropbear SSH 0.53
|
||||
[0;31m(kex) diffie-hellman-group1-sha1 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;31m `- [fail] disabled (in client) since OpenSSH 7.0, logjam attack[0m
|
||||
[0;33m `- [warn] using small 1024-bit modulus[0m
|
||||
[0;33m `- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 2.3.0, Dropbear SSH 0.28
|
||||
|
||||
[0;36m# host-key algorithms[0m
|
||||
[0;31m(key) ssh-rsa (1024-bit) -- [fail] using small 1024-bit modulus[0m
|
||||
`- [info] available since OpenSSH 2.5.0, Dropbear SSH 0.28
|
||||
[0;31m(key) ssh-rsa-cert-v01@openssh.com (1024-bit cert/1024-bit CA) -- [fail] using small 1024-bit modulus[0m
|
||||
`- [info] available since OpenSSH 5.6
|
||||
|
||||
[0;36m# encryption algorithms (ciphers)[0m
|
||||
[0;32m(enc) aes128-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52[0m
|
||||
[0;32m(enc) aes192-ctr -- [info] available since OpenSSH 3.7[0m
|
||||
[0;32m(enc) aes256-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52[0m
|
||||
[0;31m(enc) arcfour256 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher[0m
|
||||
`- [info] available since OpenSSH 4.2
|
||||
[0;31m(enc) arcfour128 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher[0m
|
||||
`- [info] available since OpenSSH 4.2
|
||||
[0;31m(enc) aes128-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher mode[0m
|
||||
`- [info] available since OpenSSH 2.3.0, Dropbear SSH 0.28
|
||||
[0;31m(enc) 3des-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.4, unsafe algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher[0m
|
||||
[0;33m `- [warn] using weak cipher mode[0m
|
||||
[0;33m `- [warn] using small 64-bit block size[0m
|
||||
`- [info] available since OpenSSH 1.2.2, Dropbear SSH 0.28
|
||||
[0;31m(enc) blowfish-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;31m `- [fail] disabled since Dropbear SSH 0.53[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher mode[0m
|
||||
[0;33m `- [warn] using small 64-bit block size[0m
|
||||
`- [info] available since OpenSSH 1.2.2, Dropbear SSH 0.28
|
||||
[0;31m(enc) cast128-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher mode[0m
|
||||
[0;33m `- [warn] using small 64-bit block size[0m
|
||||
`- [info] available since OpenSSH 2.1.0
|
||||
[0;31m(enc) aes192-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher mode[0m
|
||||
`- [info] available since OpenSSH 2.3.0
|
||||
[0;31m(enc) aes256-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher mode[0m
|
||||
`- [info] available since OpenSSH 2.3.0, Dropbear SSH 0.47
|
||||
[0;31m(enc) arcfour -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher[0m
|
||||
`- [info] available since OpenSSH 2.1.0
|
||||
[0;31m(enc) rijndael-cbc@lysator.liu.se -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher mode[0m
|
||||
`- [info] available since OpenSSH 2.3.0
|
||||
|
||||
[0;36m# message authentication code algorithms[0m
|
||||
[0;31m(mac) hmac-md5 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using encrypt-and-MAC mode[0m
|
||||
[0;33m `- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 2.1.0, Dropbear SSH 0.28
|
||||
[0;33m(mac) hmac-sha1 -- [warn] using encrypt-and-MAC mode[0m
|
||||
[0;33m `- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 2.1.0, Dropbear SSH 0.28
|
||||
[0;33m(mac) umac-64@openssh.com -- [warn] using encrypt-and-MAC mode[0m
|
||||
[0;33m `- [warn] using small 64-bit tag size[0m
|
||||
`- [info] available since OpenSSH 4.7
|
||||
[0;31m(mac) hmac-ripemd160 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using encrypt-and-MAC mode[0m
|
||||
`- [info] available since OpenSSH 2.5.0
|
||||
[0;31m(mac) hmac-ripemd160@openssh.com -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using encrypt-and-MAC mode[0m
|
||||
`- [info] available since OpenSSH 2.1.0
|
||||
[0;31m(mac) hmac-sha1-96 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using encrypt-and-MAC mode[0m
|
||||
[0;33m `- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 2.5.0, Dropbear SSH 0.47
|
||||
[0;31m(mac) hmac-md5-96 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using encrypt-and-MAC mode[0m
|
||||
[0;33m `- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 2.5.0
|
||||
|
||||
[0;36m# fingerprints[0m
|
||||
[0;32m(fin) ssh-rsa: SHA256:YZ457EBcJTSxRKI3yXRgtAj3PBf5B9/F36b1SVooml4[0m
|
||||
|
||||
[0;36m# algorithm recommendations (for OpenSSH 5.6)[0m
|
||||
[0;31m(rec) !diffie-hellman-group-exchange-sha256 -- kex algorithm to change (increase modulus size to 2048 bits or larger) [0m
|
||||
[0;31m(rec) !ssh-rsa -- key algorithm to change (increase modulus size to 2048 bits or larger) [0m
|
||||
[0;31m(rec) !ssh-rsa-cert-v01@openssh.com -- key algorithm to change (increase modulus size to 2048 bits or larger) [0m
|
||||
[0;31m(rec) -3des-cbc -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -aes128-cbc -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -aes192-cbc -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -aes256-cbc -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -arcfour -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -arcfour128 -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -arcfour256 -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -blowfish-cbc -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -cast128-cbc -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -diffie-hellman-group-exchange-sha1 -- kex algorithm to remove [0m
|
||||
[0;31m(rec) -diffie-hellman-group1-sha1 -- kex algorithm to remove [0m
|
||||
[0;31m(rec) -hmac-md5 -- mac algorithm to remove [0m
|
||||
[0;31m(rec) -hmac-md5-96 -- mac algorithm to remove [0m
|
||||
[0;31m(rec) -hmac-ripemd160 -- mac algorithm to remove [0m
|
||||
[0;31m(rec) -hmac-ripemd160@openssh.com -- mac algorithm to remove [0m
|
||||
[0;31m(rec) -hmac-sha1-96 -- mac algorithm to remove [0m
|
||||
[0;31m(rec) -rijndael-cbc@lysator.liu.se -- enc algorithm to remove [0m
|
||||
[0;33m(rec) -diffie-hellman-group14-sha1 -- kex algorithm to remove [0m
|
||||
|
||||
[0;36m# additional info[0m
|
||||
[0;33m(nfo) For hardening guides on common OSes, please see: <https://www.ssh-audit.com/hardening_guides.html>[0m
|
||||
|
1
test/docker/expected_results/openssh_5.6p1_test3.json
Normal file
1
test/docker/expected_results/openssh_5.6p1_test3.json
Normal file
@ -0,0 +1 @@
|
||||
{"banner": {"comments": null, "protocol": [2, 0], "raw": "SSH-2.0-OpenSSH_5.6", "software": "OpenSSH_5.6"}, "compression": ["none", "zlib@openssh.com"], "enc": ["aes128-ctr", "aes192-ctr", "aes256-ctr", "arcfour256", "arcfour128", "aes128-cbc", "3des-cbc", "blowfish-cbc", "cast128-cbc", "aes192-cbc", "aes256-cbc", "arcfour", "rijndael-cbc@lysator.liu.se"], "fingerprints": [{"fp": "SHA256:YZ457EBcJTSxRKI3yXRgtAj3PBf5B9/F36b1SVooml4", "type": "ssh-rsa"}], "kex": [{"algorithm": "diffie-hellman-group-exchange-sha256", "keysize": 1024}, {"algorithm": "diffie-hellman-group-exchange-sha1", "keysize": 1024}, {"algorithm": "diffie-hellman-group14-sha1"}, {"algorithm": "diffie-hellman-group1-sha1"}], "key": [{"algorithm": "ssh-rsa", "keysize": 1024}, {"algorithm": "ssh-rsa-cert-v01@openssh.com", "casize": 3072, "keysize": 1024}], "mac": ["hmac-md5", "hmac-sha1", "umac-64@openssh.com", "hmac-ripemd160", "hmac-ripemd160@openssh.com", "hmac-sha1-96", "hmac-md5-96"]}
|
146
test/docker/expected_results/openssh_5.6p1_test3.txt
Normal file
146
test/docker/expected_results/openssh_5.6p1_test3.txt
Normal file
@ -0,0 +1,146 @@
|
||||
[0;36m# general[0m
|
||||
[0;32m(gen) banner: SSH-2.0-OpenSSH_5.6[0m
|
||||
[0;32m(gen) software: OpenSSH 5.6[0m
|
||||
[0;32m(gen) compatibility: OpenSSH 5.6-6.6, Dropbear SSH 0.53+ (some functionality from 0.52)[0m
|
||||
[0;32m(gen) compression: enabled (zlib@openssh.com)[0m
|
||||
|
||||
[0;36m# security[0m
|
||||
[0;33m(cve) CVE-2016-3115 -- (CVSSv2: 5.5) bypass command restrictions via crafted X11 forwarding data[0m
|
||||
[0;33m(cve) CVE-2016-1907 -- (CVSSv2: 5.0) cause DoS via crafted network traffic (out of bounds read)[0m
|
||||
[0;33m(cve) CVE-2015-6564 -- (CVSSv2: 6.9) privilege escalation via leveraging sshd uid[0m
|
||||
[0;33m(cve) CVE-2015-6563 -- (CVSSv2: 1.9) conduct impersonation attack[0m
|
||||
[0;33m(cve) CVE-2014-2532 -- (CVSSv2: 5.8) bypass environment restrictions via specific string before wildcard[0m
|
||||
[0;33m(cve) CVE-2014-1692 -- (CVSSv2: 7.5) cause DoS via triggering error condition (memory corruption)[0m
|
||||
[0;33m(cve) CVE-2012-0814 -- (CVSSv2: 3.5) leak data via debug messages[0m
|
||||
[0;33m(cve) CVE-2011-5000 -- (CVSSv2: 3.5) cause DoS via large value in certain length field (memory consumption)[0m
|
||||
[0;33m(cve) CVE-2010-5107 -- (CVSSv2: 5.0) cause DoS via large number of connections (slot exhaustion)[0m
|
||||
[0;33m(cve) CVE-2010-4755 -- (CVSSv2: 4.0) cause DoS via crafted glob expression (CPU and memory consumption)[0m
|
||||
[0;33m(cve) CVE-2010-4478 -- (CVSSv2: 7.5) bypass authentication check via crafted values[0m
|
||||
|
||||
[0;36m# key exchange algorithms[0m
|
||||
[0;31m(kex) diffie-hellman-group-exchange-sha256 (1024-bit) -- [fail] using small 1024-bit modulus[0m
|
||||
`- [info] available since OpenSSH 4.4
|
||||
[0;31m(kex) diffie-hellman-group-exchange-sha1 (1024-bit) -- [fail] using small 1024-bit modulus[0m
|
||||
[0;33m `- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 2.3.0
|
||||
[0;33m(kex) diffie-hellman-group14-sha1 -- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 3.9, Dropbear SSH 0.53
|
||||
[0;31m(kex) diffie-hellman-group1-sha1 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;31m `- [fail] disabled (in client) since OpenSSH 7.0, logjam attack[0m
|
||||
[0;33m `- [warn] using small 1024-bit modulus[0m
|
||||
[0;33m `- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 2.3.0, Dropbear SSH 0.28
|
||||
|
||||
[0;36m# host-key algorithms[0m
|
||||
[0;31m(key) ssh-rsa (1024-bit) -- [fail] using small 1024-bit modulus[0m
|
||||
`- [info] available since OpenSSH 2.5.0, Dropbear SSH 0.28
|
||||
[0;31m(key) ssh-rsa-cert-v01@openssh.com (1024-bit cert/3072-bit CA) -- [fail] using small 1024-bit modulus[0m
|
||||
`- [info] available since OpenSSH 5.6
|
||||
|
||||
[0;36m# encryption algorithms (ciphers)[0m
|
||||
[0;32m(enc) aes128-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52[0m
|
||||
[0;32m(enc) aes192-ctr -- [info] available since OpenSSH 3.7[0m
|
||||
[0;32m(enc) aes256-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52[0m
|
||||
[0;31m(enc) arcfour256 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher[0m
|
||||
`- [info] available since OpenSSH 4.2
|
||||
[0;31m(enc) arcfour128 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher[0m
|
||||
`- [info] available since OpenSSH 4.2
|
||||
[0;31m(enc) aes128-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher mode[0m
|
||||
`- [info] available since OpenSSH 2.3.0, Dropbear SSH 0.28
|
||||
[0;31m(enc) 3des-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.4, unsafe algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher[0m
|
||||
[0;33m `- [warn] using weak cipher mode[0m
|
||||
[0;33m `- [warn] using small 64-bit block size[0m
|
||||
`- [info] available since OpenSSH 1.2.2, Dropbear SSH 0.28
|
||||
[0;31m(enc) blowfish-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;31m `- [fail] disabled since Dropbear SSH 0.53[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher mode[0m
|
||||
[0;33m `- [warn] using small 64-bit block size[0m
|
||||
`- [info] available since OpenSSH 1.2.2, Dropbear SSH 0.28
|
||||
[0;31m(enc) cast128-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher mode[0m
|
||||
[0;33m `- [warn] using small 64-bit block size[0m
|
||||
`- [info] available since OpenSSH 2.1.0
|
||||
[0;31m(enc) aes192-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher mode[0m
|
||||
`- [info] available since OpenSSH 2.3.0
|
||||
[0;31m(enc) aes256-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher mode[0m
|
||||
`- [info] available since OpenSSH 2.3.0, Dropbear SSH 0.47
|
||||
[0;31m(enc) arcfour -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher[0m
|
||||
`- [info] available since OpenSSH 2.1.0
|
||||
[0;31m(enc) rijndael-cbc@lysator.liu.se -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher mode[0m
|
||||
`- [info] available since OpenSSH 2.3.0
|
||||
|
||||
[0;36m# message authentication code algorithms[0m
|
||||
[0;31m(mac) hmac-md5 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using encrypt-and-MAC mode[0m
|
||||
[0;33m `- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 2.1.0, Dropbear SSH 0.28
|
||||
[0;33m(mac) hmac-sha1 -- [warn] using encrypt-and-MAC mode[0m
|
||||
[0;33m `- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 2.1.0, Dropbear SSH 0.28
|
||||
[0;33m(mac) umac-64@openssh.com -- [warn] using encrypt-and-MAC mode[0m
|
||||
[0;33m `- [warn] using small 64-bit tag size[0m
|
||||
`- [info] available since OpenSSH 4.7
|
||||
[0;31m(mac) hmac-ripemd160 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using encrypt-and-MAC mode[0m
|
||||
`- [info] available since OpenSSH 2.5.0
|
||||
[0;31m(mac) hmac-ripemd160@openssh.com -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using encrypt-and-MAC mode[0m
|
||||
`- [info] available since OpenSSH 2.1.0
|
||||
[0;31m(mac) hmac-sha1-96 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using encrypt-and-MAC mode[0m
|
||||
[0;33m `- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 2.5.0, Dropbear SSH 0.47
|
||||
[0;31m(mac) hmac-md5-96 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using encrypt-and-MAC mode[0m
|
||||
[0;33m `- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 2.5.0
|
||||
|
||||
[0;36m# fingerprints[0m
|
||||
[0;32m(fin) ssh-rsa: SHA256:YZ457EBcJTSxRKI3yXRgtAj3PBf5B9/F36b1SVooml4[0m
|
||||
|
||||
[0;36m# algorithm recommendations (for OpenSSH 5.6)[0m
|
||||
[0;31m(rec) !diffie-hellman-group-exchange-sha256 -- kex algorithm to change (increase modulus size to 2048 bits or larger) [0m
|
||||
[0;31m(rec) !ssh-rsa -- key algorithm to change (increase modulus size to 2048 bits or larger) [0m
|
||||
[0;31m(rec) !ssh-rsa-cert-v01@openssh.com -- key algorithm to change (increase modulus size to 2048 bits or larger) [0m
|
||||
[0;31m(rec) -3des-cbc -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -aes128-cbc -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -aes192-cbc -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -aes256-cbc -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -arcfour -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -arcfour128 -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -arcfour256 -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -blowfish-cbc -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -cast128-cbc -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -diffie-hellman-group-exchange-sha1 -- kex algorithm to remove [0m
|
||||
[0;31m(rec) -diffie-hellman-group1-sha1 -- kex algorithm to remove [0m
|
||||
[0;31m(rec) -hmac-md5 -- mac algorithm to remove [0m
|
||||
[0;31m(rec) -hmac-md5-96 -- mac algorithm to remove [0m
|
||||
[0;31m(rec) -hmac-ripemd160 -- mac algorithm to remove [0m
|
||||
[0;31m(rec) -hmac-ripemd160@openssh.com -- mac algorithm to remove [0m
|
||||
[0;31m(rec) -hmac-sha1-96 -- mac algorithm to remove [0m
|
||||
[0;31m(rec) -rijndael-cbc@lysator.liu.se -- enc algorithm to remove [0m
|
||||
[0;33m(rec) -diffie-hellman-group14-sha1 -- kex algorithm to remove [0m
|
||||
|
||||
[0;36m# additional info[0m
|
||||
[0;33m(nfo) For hardening guides on common OSes, please see: <https://www.ssh-audit.com/hardening_guides.html>[0m
|
||||
|
1
test/docker/expected_results/openssh_5.6p1_test4.json
Normal file
1
test/docker/expected_results/openssh_5.6p1_test4.json
Normal file
@ -0,0 +1 @@
|
||||
{"banner": {"comments": null, "protocol": [2, 0], "raw": "SSH-2.0-OpenSSH_5.6", "software": "OpenSSH_5.6"}, "compression": ["none", "zlib@openssh.com"], "enc": ["aes128-ctr", "aes192-ctr", "aes256-ctr", "arcfour256", "arcfour128", "aes128-cbc", "3des-cbc", "blowfish-cbc", "cast128-cbc", "aes192-cbc", "aes256-cbc", "arcfour", "rijndael-cbc@lysator.liu.se"], "fingerprints": [{"fp": "SHA256:nsWtdJ9Z67Vrf7OsUzQov7esXhsWAfVppArGh25u244", "type": "ssh-rsa"}], "kex": [{"algorithm": "diffie-hellman-group-exchange-sha256", "keysize": 1024}, {"algorithm": "diffie-hellman-group-exchange-sha1", "keysize": 1024}, {"algorithm": "diffie-hellman-group14-sha1"}, {"algorithm": "diffie-hellman-group1-sha1"}], "key": [{"algorithm": "ssh-rsa", "keysize": 3072}, {"algorithm": "ssh-rsa-cert-v01@openssh.com", "casize": 1024, "keysize": 3072}], "mac": ["hmac-md5", "hmac-sha1", "umac-64@openssh.com", "hmac-ripemd160", "hmac-ripemd160@openssh.com", "hmac-sha1-96", "hmac-md5-96"]}
|
144
test/docker/expected_results/openssh_5.6p1_test4.txt
Normal file
144
test/docker/expected_results/openssh_5.6p1_test4.txt
Normal file
@ -0,0 +1,144 @@
|
||||
[0;36m# general[0m
|
||||
[0;32m(gen) banner: SSH-2.0-OpenSSH_5.6[0m
|
||||
[0;32m(gen) software: OpenSSH 5.6[0m
|
||||
[0;32m(gen) compatibility: OpenSSH 5.6-6.6, Dropbear SSH 0.53+ (some functionality from 0.52)[0m
|
||||
[0;32m(gen) compression: enabled (zlib@openssh.com)[0m
|
||||
|
||||
[0;36m# security[0m
|
||||
[0;33m(cve) CVE-2016-3115 -- (CVSSv2: 5.5) bypass command restrictions via crafted X11 forwarding data[0m
|
||||
[0;33m(cve) CVE-2016-1907 -- (CVSSv2: 5.0) cause DoS via crafted network traffic (out of bounds read)[0m
|
||||
[0;33m(cve) CVE-2015-6564 -- (CVSSv2: 6.9) privilege escalation via leveraging sshd uid[0m
|
||||
[0;33m(cve) CVE-2015-6563 -- (CVSSv2: 1.9) conduct impersonation attack[0m
|
||||
[0;33m(cve) CVE-2014-2532 -- (CVSSv2: 5.8) bypass environment restrictions via specific string before wildcard[0m
|
||||
[0;33m(cve) CVE-2014-1692 -- (CVSSv2: 7.5) cause DoS via triggering error condition (memory corruption)[0m
|
||||
[0;33m(cve) CVE-2012-0814 -- (CVSSv2: 3.5) leak data via debug messages[0m
|
||||
[0;33m(cve) CVE-2011-5000 -- (CVSSv2: 3.5) cause DoS via large value in certain length field (memory consumption)[0m
|
||||
[0;33m(cve) CVE-2010-5107 -- (CVSSv2: 5.0) cause DoS via large number of connections (slot exhaustion)[0m
|
||||
[0;33m(cve) CVE-2010-4755 -- (CVSSv2: 4.0) cause DoS via crafted glob expression (CPU and memory consumption)[0m
|
||||
[0;33m(cve) CVE-2010-4478 -- (CVSSv2: 7.5) bypass authentication check via crafted values[0m
|
||||
|
||||
[0;36m# key exchange algorithms[0m
|
||||
[0;31m(kex) diffie-hellman-group-exchange-sha256 (1024-bit) -- [fail] using small 1024-bit modulus[0m
|
||||
`- [info] available since OpenSSH 4.4
|
||||
[0;31m(kex) diffie-hellman-group-exchange-sha1 (1024-bit) -- [fail] using small 1024-bit modulus[0m
|
||||
[0;33m `- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 2.3.0
|
||||
[0;33m(kex) diffie-hellman-group14-sha1 -- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 3.9, Dropbear SSH 0.53
|
||||
[0;31m(kex) diffie-hellman-group1-sha1 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;31m `- [fail] disabled (in client) since OpenSSH 7.0, logjam attack[0m
|
||||
[0;33m `- [warn] using small 1024-bit modulus[0m
|
||||
[0;33m `- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 2.3.0, Dropbear SSH 0.28
|
||||
|
||||
[0;36m# host-key algorithms[0m
|
||||
[0;32m(key) ssh-rsa (3072-bit) -- [info] available since OpenSSH 2.5.0, Dropbear SSH 0.28[0m
|
||||
[0;31m(key) ssh-rsa-cert-v01@openssh.com (3072-bit cert/1024-bit CA) -- [fail] using small 1024-bit modulus[0m
|
||||
`- [info] available since OpenSSH 5.6
|
||||
|
||||
[0;36m# encryption algorithms (ciphers)[0m
|
||||
[0;32m(enc) aes128-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52[0m
|
||||
[0;32m(enc) aes192-ctr -- [info] available since OpenSSH 3.7[0m
|
||||
[0;32m(enc) aes256-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52[0m
|
||||
[0;31m(enc) arcfour256 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher[0m
|
||||
`- [info] available since OpenSSH 4.2
|
||||
[0;31m(enc) arcfour128 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher[0m
|
||||
`- [info] available since OpenSSH 4.2
|
||||
[0;31m(enc) aes128-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher mode[0m
|
||||
`- [info] available since OpenSSH 2.3.0, Dropbear SSH 0.28
|
||||
[0;31m(enc) 3des-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.4, unsafe algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher[0m
|
||||
[0;33m `- [warn] using weak cipher mode[0m
|
||||
[0;33m `- [warn] using small 64-bit block size[0m
|
||||
`- [info] available since OpenSSH 1.2.2, Dropbear SSH 0.28
|
||||
[0;31m(enc) blowfish-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;31m `- [fail] disabled since Dropbear SSH 0.53[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher mode[0m
|
||||
[0;33m `- [warn] using small 64-bit block size[0m
|
||||
`- [info] available since OpenSSH 1.2.2, Dropbear SSH 0.28
|
||||
[0;31m(enc) cast128-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher mode[0m
|
||||
[0;33m `- [warn] using small 64-bit block size[0m
|
||||
`- [info] available since OpenSSH 2.1.0
|
||||
[0;31m(enc) aes192-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher mode[0m
|
||||
`- [info] available since OpenSSH 2.3.0
|
||||
[0;31m(enc) aes256-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher mode[0m
|
||||
`- [info] available since OpenSSH 2.3.0, Dropbear SSH 0.47
|
||||
[0;31m(enc) arcfour -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher[0m
|
||||
`- [info] available since OpenSSH 2.1.0
|
||||
[0;31m(enc) rijndael-cbc@lysator.liu.se -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher mode[0m
|
||||
`- [info] available since OpenSSH 2.3.0
|
||||
|
||||
[0;36m# message authentication code algorithms[0m
|
||||
[0;31m(mac) hmac-md5 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using encrypt-and-MAC mode[0m
|
||||
[0;33m `- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 2.1.0, Dropbear SSH 0.28
|
||||
[0;33m(mac) hmac-sha1 -- [warn] using encrypt-and-MAC mode[0m
|
||||
[0;33m `- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 2.1.0, Dropbear SSH 0.28
|
||||
[0;33m(mac) umac-64@openssh.com -- [warn] using encrypt-and-MAC mode[0m
|
||||
[0;33m `- [warn] using small 64-bit tag size[0m
|
||||
`- [info] available since OpenSSH 4.7
|
||||
[0;31m(mac) hmac-ripemd160 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using encrypt-and-MAC mode[0m
|
||||
`- [info] available since OpenSSH 2.5.0
|
||||
[0;31m(mac) hmac-ripemd160@openssh.com -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using encrypt-and-MAC mode[0m
|
||||
`- [info] available since OpenSSH 2.1.0
|
||||
[0;31m(mac) hmac-sha1-96 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using encrypt-and-MAC mode[0m
|
||||
[0;33m `- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 2.5.0, Dropbear SSH 0.47
|
||||
[0;31m(mac) hmac-md5-96 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using encrypt-and-MAC mode[0m
|
||||
[0;33m `- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 2.5.0
|
||||
|
||||
[0;36m# fingerprints[0m
|
||||
[0;32m(fin) ssh-rsa: SHA256:nsWtdJ9Z67Vrf7OsUzQov7esXhsWAfVppArGh25u244[0m
|
||||
|
||||
[0;36m# algorithm recommendations (for OpenSSH 5.6)[0m
|
||||
[0;31m(rec) !diffie-hellman-group-exchange-sha256 -- kex algorithm to change (increase modulus size to 2048 bits or larger) [0m
|
||||
[0;31m(rec) !ssh-rsa-cert-v01@openssh.com -- key algorithm to change (increase modulus size to 2048 bits or larger) [0m
|
||||
[0;31m(rec) -3des-cbc -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -aes128-cbc -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -aes192-cbc -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -aes256-cbc -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -arcfour -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -arcfour128 -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -arcfour256 -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -blowfish-cbc -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -cast128-cbc -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -diffie-hellman-group-exchange-sha1 -- kex algorithm to remove [0m
|
||||
[0;31m(rec) -diffie-hellman-group1-sha1 -- kex algorithm to remove [0m
|
||||
[0;31m(rec) -hmac-md5 -- mac algorithm to remove [0m
|
||||
[0;31m(rec) -hmac-md5-96 -- mac algorithm to remove [0m
|
||||
[0;31m(rec) -hmac-ripemd160 -- mac algorithm to remove [0m
|
||||
[0;31m(rec) -hmac-ripemd160@openssh.com -- mac algorithm to remove [0m
|
||||
[0;31m(rec) -hmac-sha1-96 -- mac algorithm to remove [0m
|
||||
[0;31m(rec) -rijndael-cbc@lysator.liu.se -- enc algorithm to remove [0m
|
||||
[0;33m(rec) -diffie-hellman-group14-sha1 -- kex algorithm to remove [0m
|
||||
|
||||
[0;36m# additional info[0m
|
||||
[0;33m(nfo) For hardening guides on common OSes, please see: <https://www.ssh-audit.com/hardening_guides.html>[0m
|
||||
|
1
test/docker/expected_results/openssh_5.6p1_test5.json
Normal file
1
test/docker/expected_results/openssh_5.6p1_test5.json
Normal file
@ -0,0 +1 @@
|
||||
{"banner": {"comments": null, "protocol": [2, 0], "raw": "SSH-2.0-OpenSSH_5.6", "software": "OpenSSH_5.6"}, "compression": ["none", "zlib@openssh.com"], "enc": ["aes128-ctr", "aes192-ctr", "aes256-ctr", "arcfour256", "arcfour128", "aes128-cbc", "3des-cbc", "blowfish-cbc", "cast128-cbc", "aes192-cbc", "aes256-cbc", "arcfour", "rijndael-cbc@lysator.liu.se"], "fingerprints": [{"fp": "SHA256:nsWtdJ9Z67Vrf7OsUzQov7esXhsWAfVppArGh25u244", "type": "ssh-rsa"}], "kex": [{"algorithm": "diffie-hellman-group-exchange-sha256", "keysize": 1024}, {"algorithm": "diffie-hellman-group-exchange-sha1", "keysize": 1024}, {"algorithm": "diffie-hellman-group14-sha1"}, {"algorithm": "diffie-hellman-group1-sha1"}], "key": [{"algorithm": "ssh-rsa", "keysize": 3072}, {"algorithm": "ssh-rsa-cert-v01@openssh.com", "casize": 3072, "keysize": 3072}], "mac": ["hmac-md5", "hmac-sha1", "umac-64@openssh.com", "hmac-ripemd160", "hmac-ripemd160@openssh.com", "hmac-sha1-96", "hmac-md5-96"]}
|
142
test/docker/expected_results/openssh_5.6p1_test5.txt
Normal file
142
test/docker/expected_results/openssh_5.6p1_test5.txt
Normal file
@ -0,0 +1,142 @@
|
||||
[0;36m# general[0m
|
||||
[0;32m(gen) banner: SSH-2.0-OpenSSH_5.6[0m
|
||||
[0;32m(gen) software: OpenSSH 5.6[0m
|
||||
[0;32m(gen) compatibility: OpenSSH 5.6-6.6, Dropbear SSH 0.53+ (some functionality from 0.52)[0m
|
||||
[0;32m(gen) compression: enabled (zlib@openssh.com)[0m
|
||||
|
||||
[0;36m# security[0m
|
||||
[0;33m(cve) CVE-2016-3115 -- (CVSSv2: 5.5) bypass command restrictions via crafted X11 forwarding data[0m
|
||||
[0;33m(cve) CVE-2016-1907 -- (CVSSv2: 5.0) cause DoS via crafted network traffic (out of bounds read)[0m
|
||||
[0;33m(cve) CVE-2015-6564 -- (CVSSv2: 6.9) privilege escalation via leveraging sshd uid[0m
|
||||
[0;33m(cve) CVE-2015-6563 -- (CVSSv2: 1.9) conduct impersonation attack[0m
|
||||
[0;33m(cve) CVE-2014-2532 -- (CVSSv2: 5.8) bypass environment restrictions via specific string before wildcard[0m
|
||||
[0;33m(cve) CVE-2014-1692 -- (CVSSv2: 7.5) cause DoS via triggering error condition (memory corruption)[0m
|
||||
[0;33m(cve) CVE-2012-0814 -- (CVSSv2: 3.5) leak data via debug messages[0m
|
||||
[0;33m(cve) CVE-2011-5000 -- (CVSSv2: 3.5) cause DoS via large value in certain length field (memory consumption)[0m
|
||||
[0;33m(cve) CVE-2010-5107 -- (CVSSv2: 5.0) cause DoS via large number of connections (slot exhaustion)[0m
|
||||
[0;33m(cve) CVE-2010-4755 -- (CVSSv2: 4.0) cause DoS via crafted glob expression (CPU and memory consumption)[0m
|
||||
[0;33m(cve) CVE-2010-4478 -- (CVSSv2: 7.5) bypass authentication check via crafted values[0m
|
||||
|
||||
[0;36m# key exchange algorithms[0m
|
||||
[0;31m(kex) diffie-hellman-group-exchange-sha256 (1024-bit) -- [fail] using small 1024-bit modulus[0m
|
||||
`- [info] available since OpenSSH 4.4
|
||||
[0;31m(kex) diffie-hellman-group-exchange-sha1 (1024-bit) -- [fail] using small 1024-bit modulus[0m
|
||||
[0;33m `- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 2.3.0
|
||||
[0;33m(kex) diffie-hellman-group14-sha1 -- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 3.9, Dropbear SSH 0.53
|
||||
[0;31m(kex) diffie-hellman-group1-sha1 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;31m `- [fail] disabled (in client) since OpenSSH 7.0, logjam attack[0m
|
||||
[0;33m `- [warn] using small 1024-bit modulus[0m
|
||||
[0;33m `- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 2.3.0, Dropbear SSH 0.28
|
||||
|
||||
[0;36m# host-key algorithms[0m
|
||||
[0;32m(key) ssh-rsa (3072-bit) -- [info] available since OpenSSH 2.5.0, Dropbear SSH 0.28[0m
|
||||
[0;32m(key) ssh-rsa-cert-v01@openssh.com (3072-bit cert/3072-bit CA) -- [info] available since OpenSSH 5.6[0m
|
||||
|
||||
[0;36m# encryption algorithms (ciphers)[0m
|
||||
[0;32m(enc) aes128-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52[0m
|
||||
[0;32m(enc) aes192-ctr -- [info] available since OpenSSH 3.7[0m
|
||||
[0;32m(enc) aes256-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52[0m
|
||||
[0;31m(enc) arcfour256 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher[0m
|
||||
`- [info] available since OpenSSH 4.2
|
||||
[0;31m(enc) arcfour128 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher[0m
|
||||
`- [info] available since OpenSSH 4.2
|
||||
[0;31m(enc) aes128-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher mode[0m
|
||||
`- [info] available since OpenSSH 2.3.0, Dropbear SSH 0.28
|
||||
[0;31m(enc) 3des-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.4, unsafe algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher[0m
|
||||
[0;33m `- [warn] using weak cipher mode[0m
|
||||
[0;33m `- [warn] using small 64-bit block size[0m
|
||||
`- [info] available since OpenSSH 1.2.2, Dropbear SSH 0.28
|
||||
[0;31m(enc) blowfish-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;31m `- [fail] disabled since Dropbear SSH 0.53[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher mode[0m
|
||||
[0;33m `- [warn] using small 64-bit block size[0m
|
||||
`- [info] available since OpenSSH 1.2.2, Dropbear SSH 0.28
|
||||
[0;31m(enc) cast128-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher mode[0m
|
||||
[0;33m `- [warn] using small 64-bit block size[0m
|
||||
`- [info] available since OpenSSH 2.1.0
|
||||
[0;31m(enc) aes192-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher mode[0m
|
||||
`- [info] available since OpenSSH 2.3.0
|
||||
[0;31m(enc) aes256-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher mode[0m
|
||||
`- [info] available since OpenSSH 2.3.0, Dropbear SSH 0.47
|
||||
[0;31m(enc) arcfour -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher[0m
|
||||
`- [info] available since OpenSSH 2.1.0
|
||||
[0;31m(enc) rijndael-cbc@lysator.liu.se -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using weak cipher mode[0m
|
||||
`- [info] available since OpenSSH 2.3.0
|
||||
|
||||
[0;36m# message authentication code algorithms[0m
|
||||
[0;31m(mac) hmac-md5 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using encrypt-and-MAC mode[0m
|
||||
[0;33m `- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 2.1.0, Dropbear SSH 0.28
|
||||
[0;33m(mac) hmac-sha1 -- [warn] using encrypt-and-MAC mode[0m
|
||||
[0;33m `- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 2.1.0, Dropbear SSH 0.28
|
||||
[0;33m(mac) umac-64@openssh.com -- [warn] using encrypt-and-MAC mode[0m
|
||||
[0;33m `- [warn] using small 64-bit tag size[0m
|
||||
`- [info] available since OpenSSH 4.7
|
||||
[0;31m(mac) hmac-ripemd160 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using encrypt-and-MAC mode[0m
|
||||
`- [info] available since OpenSSH 2.5.0
|
||||
[0;31m(mac) hmac-ripemd160@openssh.com -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using encrypt-and-MAC mode[0m
|
||||
`- [info] available since OpenSSH 2.1.0
|
||||
[0;31m(mac) hmac-sha1-96 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using encrypt-and-MAC mode[0m
|
||||
[0;33m `- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 2.5.0, Dropbear SSH 0.47
|
||||
[0;31m(mac) hmac-md5-96 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m
|
||||
[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m
|
||||
[0;33m `- [warn] using encrypt-and-MAC mode[0m
|
||||
[0;33m `- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 2.5.0
|
||||
|
||||
[0;36m# fingerprints[0m
|
||||
[0;32m(fin) ssh-rsa: SHA256:nsWtdJ9Z67Vrf7OsUzQov7esXhsWAfVppArGh25u244[0m
|
||||
|
||||
[0;36m# algorithm recommendations (for OpenSSH 5.6)[0m
|
||||
[0;31m(rec) !diffie-hellman-group-exchange-sha256 -- kex algorithm to change (increase modulus size to 2048 bits or larger) [0m
|
||||
[0;31m(rec) -3des-cbc -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -aes128-cbc -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -aes192-cbc -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -aes256-cbc -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -arcfour -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -arcfour128 -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -arcfour256 -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -blowfish-cbc -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -cast128-cbc -- enc algorithm to remove [0m
|
||||
[0;31m(rec) -diffie-hellman-group-exchange-sha1 -- kex algorithm to remove [0m
|
||||
[0;31m(rec) -diffie-hellman-group1-sha1 -- kex algorithm to remove [0m
|
||||
[0;31m(rec) -hmac-md5 -- mac algorithm to remove [0m
|
||||
[0;31m(rec) -hmac-md5-96 -- mac algorithm to remove [0m
|
||||
[0;31m(rec) -hmac-ripemd160 -- mac algorithm to remove [0m
|
||||
[0;31m(rec) -hmac-ripemd160@openssh.com -- mac algorithm to remove [0m
|
||||
[0;31m(rec) -hmac-sha1-96 -- mac algorithm to remove [0m
|
||||
[0;31m(rec) -rijndael-cbc@lysator.liu.se -- enc algorithm to remove [0m
|
||||
[0;33m(rec) -diffie-hellman-group14-sha1 -- kex algorithm to remove [0m
|
||||
|
||||
[0;36m# additional info[0m
|
||||
[0;33m(nfo) For hardening guides on common OSes, please see: <https://www.ssh-audit.com/hardening_guides.html>[0m
|
||||
|
1
test/docker/expected_results/openssh_8.0p1_test1.json
Normal file
1
test/docker/expected_results/openssh_8.0p1_test1.json
Normal file
@ -0,0 +1 @@
|
||||
{"banner": {"comments": null, "protocol": [2, 0], "raw": "SSH-2.0-OpenSSH_8.0", "software": "OpenSSH_8.0"}, "compression": ["none", "zlib@openssh.com"], "enc": ["chacha20-poly1305@openssh.com", "aes128-ctr", "aes192-ctr", "aes256-ctr", "aes128-gcm@openssh.com", "aes256-gcm@openssh.com"], "fingerprints": [{"fp": "SHA256:UrnXIVH+7dlw8UqYocl48yUEcKrthGDQG2CPCgp7MxU", "type": "ssh-ed25519"}, {"fp": "SHA256:nsWtdJ9Z67Vrf7OsUzQov7esXhsWAfVppArGh25u244", "type": "ssh-rsa"}], "kex": [{"algorithm": "curve25519-sha256"}, {"algorithm": "curve25519-sha256@libssh.org"}, {"algorithm": "ecdh-sha2-nistp256"}, {"algorithm": "ecdh-sha2-nistp384"}, {"algorithm": "ecdh-sha2-nistp521"}, {"algorithm": "diffie-hellman-group-exchange-sha256", "keysize": 2048}, {"algorithm": "diffie-hellman-group16-sha512"}, {"algorithm": "diffie-hellman-group18-sha512"}, {"algorithm": "diffie-hellman-group14-sha256"}, {"algorithm": "diffie-hellman-group14-sha1"}], "key": [{"algorithm": "rsa-sha2-512", "keysize": 3072}, {"algorithm": "rsa-sha2-256", "keysize": 3072}, {"algorithm": "ssh-rsa", "keysize": 3072}, {"algorithm": "ecdsa-sha2-nistp256"}, {"algorithm": "ssh-ed25519"}], "mac": ["umac-64-etm@openssh.com", "umac-128-etm@openssh.com", "hmac-sha2-256-etm@openssh.com", "hmac-sha2-512-etm@openssh.com", "hmac-sha1-etm@openssh.com", "umac-64@openssh.com", "umac-128@openssh.com", "hmac-sha2-256", "hmac-sha2-512", "hmac-sha1"]}
|
82
test/docker/expected_results/openssh_8.0p1_test1.txt
Normal file
82
test/docker/expected_results/openssh_8.0p1_test1.txt
Normal file
@ -0,0 +1,82 @@
|
||||
[0;36m# general[0m
|
||||
[0;32m(gen) banner: SSH-2.0-OpenSSH_8.0[0m
|
||||
[0;32m(gen) software: OpenSSH 8.0[0m
|
||||
[0;32m(gen) compatibility: OpenSSH 7.4+, Dropbear SSH 2018.76+[0m
|
||||
[0;32m(gen) compression: enabled (zlib@openssh.com)[0m
|
||||
|
||||
[0;36m# key exchange algorithms[0m
|
||||
[0;32m(kex) curve25519-sha256 -- [info] available since OpenSSH 7.4, Dropbear SSH 2018.76[0m
|
||||
[0;32m(kex) curve25519-sha256@libssh.org -- [info] available since OpenSSH 6.5, Dropbear SSH 2013.62[0m
|
||||
[0;31m(kex) ecdh-sha2-nistp256 -- [fail] using weak elliptic curves[0m
|
||||
`- [info] available since OpenSSH 5.7, Dropbear SSH 2013.62
|
||||
[0;31m(kex) ecdh-sha2-nistp384 -- [fail] using weak elliptic curves[0m
|
||||
`- [info] available since OpenSSH 5.7, Dropbear SSH 2013.62
|
||||
[0;31m(kex) ecdh-sha2-nistp521 -- [fail] using weak elliptic curves[0m
|
||||
`- [info] available since OpenSSH 5.7, Dropbear SSH 2013.62
|
||||
[0;32m(kex) diffie-hellman-group-exchange-sha256 (2048-bit) -- [info] available since OpenSSH 4.4[0m
|
||||
[0;32m(kex) diffie-hellman-group16-sha512 -- [info] available since OpenSSH 7.3, Dropbear SSH 2016.73[0m
|
||||
[0;32m(kex) diffie-hellman-group18-sha512 -- [info] available since OpenSSH 7.3[0m
|
||||
[0;32m(kex) diffie-hellman-group14-sha256 -- [info] available since OpenSSH 7.3, Dropbear SSH 2016.73[0m
|
||||
[0;33m(kex) diffie-hellman-group14-sha1 -- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 3.9, Dropbear SSH 0.53
|
||||
|
||||
[0;36m# host-key algorithms[0m
|
||||
[0;32m(key) rsa-sha2-512 (3072-bit) -- [info] available since OpenSSH 7.2[0m
|
||||
[0;32m(key) rsa-sha2-256 (3072-bit) -- [info] available since OpenSSH 7.2[0m
|
||||
[0;32m(key) ssh-rsa (3072-bit) -- [info] available since OpenSSH 2.5.0, Dropbear SSH 0.28[0m
|
||||
[0;31m(key) ecdsa-sha2-nistp256 -- [fail] using weak elliptic curves[0m
|
||||
[0;33m `- [warn] using weak random number generator could reveal the key[0m
|
||||
`- [info] available since OpenSSH 5.7, Dropbear SSH 2013.62
|
||||
[0;32m(key) ssh-ed25519 -- [info] available since OpenSSH 6.5[0m
|
||||
|
||||
[0;36m# encryption algorithms (ciphers)[0m
|
||||
[0;32m(enc) chacha20-poly1305@openssh.com -- [info] available since OpenSSH 6.5[0m
|
||||
`- [info] default cipher since OpenSSH 6.9.
|
||||
[0;32m(enc) aes128-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52[0m
|
||||
[0;32m(enc) aes192-ctr -- [info] available since OpenSSH 3.7[0m
|
||||
[0;32m(enc) aes256-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52[0m
|
||||
[0;32m(enc) aes128-gcm@openssh.com -- [info] available since OpenSSH 6.2[0m
|
||||
[0;32m(enc) aes256-gcm@openssh.com -- [info] available since OpenSSH 6.2[0m
|
||||
|
||||
[0;36m# message authentication code algorithms[0m
|
||||
[0;33m(mac) umac-64-etm@openssh.com -- [warn] using small 64-bit tag size[0m
|
||||
`- [info] available since OpenSSH 6.2
|
||||
[0;32m(mac) umac-128-etm@openssh.com -- [info] available since OpenSSH 6.2[0m
|
||||
[0;32m(mac) hmac-sha2-256-etm@openssh.com -- [info] available since OpenSSH 6.2[0m
|
||||
[0;32m(mac) hmac-sha2-512-etm@openssh.com -- [info] available since OpenSSH 6.2[0m
|
||||
[0;33m(mac) hmac-sha1-etm@openssh.com -- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 6.2
|
||||
[0;33m(mac) umac-64@openssh.com -- [warn] using encrypt-and-MAC mode[0m
|
||||
[0;33m `- [warn] using small 64-bit tag size[0m
|
||||
`- [info] available since OpenSSH 4.7
|
||||
[0;33m(mac) umac-128@openssh.com -- [warn] using encrypt-and-MAC mode[0m
|
||||
`- [info] available since OpenSSH 6.2
|
||||
[0;33m(mac) hmac-sha2-256 -- [warn] using encrypt-and-MAC mode[0m
|
||||
`- [info] available since OpenSSH 5.9, Dropbear SSH 2013.56
|
||||
[0;33m(mac) hmac-sha2-512 -- [warn] using encrypt-and-MAC mode[0m
|
||||
`- [info] available since OpenSSH 5.9, Dropbear SSH 2013.56
|
||||
[0;33m(mac) hmac-sha1 -- [warn] using encrypt-and-MAC mode[0m
|
||||
[0;33m `- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 2.1.0, Dropbear SSH 0.28
|
||||
|
||||
[0;36m# fingerprints[0m
|
||||
[0;32m(fin) ssh-ed25519: SHA256:UrnXIVH+7dlw8UqYocl48yUEcKrthGDQG2CPCgp7MxU[0m
|
||||
[0;32m(fin) ssh-rsa: SHA256:nsWtdJ9Z67Vrf7OsUzQov7esXhsWAfVppArGh25u244[0m
|
||||
|
||||
[0;36m# algorithm recommendations (for OpenSSH 8.0)[0m
|
||||
[0;31m(rec) -ecdh-sha2-nistp256 -- kex algorithm to remove [0m
|
||||
[0;31m(rec) -ecdh-sha2-nistp384 -- kex algorithm to remove [0m
|
||||
[0;31m(rec) -ecdh-sha2-nistp521 -- kex algorithm to remove [0m
|
||||
[0;31m(rec) -ecdsa-sha2-nistp256 -- key algorithm to remove [0m
|
||||
[0;33m(rec) -diffie-hellman-group14-sha1 -- kex algorithm to remove [0m
|
||||
[0;33m(rec) -hmac-sha1 -- mac algorithm to remove [0m
|
||||
[0;33m(rec) -hmac-sha1-etm@openssh.com -- mac algorithm to remove [0m
|
||||
[0;33m(rec) -hmac-sha2-256 -- mac algorithm to remove [0m
|
||||
[0;33m(rec) -hmac-sha2-512 -- mac algorithm to remove [0m
|
||||
[0;33m(rec) -umac-128@openssh.com -- mac algorithm to remove [0m
|
||||
[0;33m(rec) -umac-64-etm@openssh.com -- mac algorithm to remove [0m
|
||||
[0;33m(rec) -umac-64@openssh.com -- mac algorithm to remove [0m
|
||||
|
||||
[0;36m# additional info[0m
|
||||
[0;33m(nfo) For hardening guides on common OSes, please see: <https://www.ssh-audit.com/hardening_guides.html>[0m
|
||||
|
1
test/docker/expected_results/openssh_8.0p1_test2.json
Normal file
1
test/docker/expected_results/openssh_8.0p1_test2.json
Normal file
@ -0,0 +1 @@
|
||||
{"banner": {"comments": null, "protocol": [2, 0], "raw": "SSH-2.0-OpenSSH_8.0", "software": "OpenSSH_8.0"}, "compression": ["none", "zlib@openssh.com"], "enc": ["chacha20-poly1305@openssh.com", "aes128-ctr", "aes192-ctr", "aes256-ctr", "aes128-gcm@openssh.com", "aes256-gcm@openssh.com"], "fingerprints": [{"fp": "SHA256:UrnXIVH+7dlw8UqYocl48yUEcKrthGDQG2CPCgp7MxU", "type": "ssh-ed25519"}], "kex": [{"algorithm": "curve25519-sha256"}, {"algorithm": "curve25519-sha256@libssh.org"}, {"algorithm": "ecdh-sha2-nistp256"}, {"algorithm": "ecdh-sha2-nistp384"}, {"algorithm": "ecdh-sha2-nistp521"}, {"algorithm": "diffie-hellman-group-exchange-sha256", "keysize": 2048}, {"algorithm": "diffie-hellman-group16-sha512"}, {"algorithm": "diffie-hellman-group18-sha512"}, {"algorithm": "diffie-hellman-group14-sha256"}, {"algorithm": "diffie-hellman-group14-sha1"}], "key": [{"algorithm": "ssh-ed25519"}, {"algorithm": "ssh-ed25519-cert-v01@openssh.com"}], "mac": ["umac-64-etm@openssh.com", "umac-128-etm@openssh.com", "hmac-sha2-256-etm@openssh.com", "hmac-sha2-512-etm@openssh.com", "hmac-sha1-etm@openssh.com", "umac-64@openssh.com", "umac-128@openssh.com", "hmac-sha2-256", "hmac-sha2-512", "hmac-sha1"]}
|
78
test/docker/expected_results/openssh_8.0p1_test2.txt
Normal file
78
test/docker/expected_results/openssh_8.0p1_test2.txt
Normal file
@ -0,0 +1,78 @@
|
||||
[0;36m# general[0m
|
||||
[0;32m(gen) banner: SSH-2.0-OpenSSH_8.0[0m
|
||||
[0;32m(gen) software: OpenSSH 8.0[0m
|
||||
[0;32m(gen) compatibility: OpenSSH 7.4+, Dropbear SSH 2018.76+[0m
|
||||
[0;32m(gen) compression: enabled (zlib@openssh.com)[0m
|
||||
|
||||
[0;36m# key exchange algorithms[0m
|
||||
[0;32m(kex) curve25519-sha256 -- [info] available since OpenSSH 7.4, Dropbear SSH 2018.76[0m
|
||||
[0;32m(kex) curve25519-sha256@libssh.org -- [info] available since OpenSSH 6.5, Dropbear SSH 2013.62[0m
|
||||
[0;31m(kex) ecdh-sha2-nistp256 -- [fail] using weak elliptic curves[0m
|
||||
`- [info] available since OpenSSH 5.7, Dropbear SSH 2013.62
|
||||
[0;31m(kex) ecdh-sha2-nistp384 -- [fail] using weak elliptic curves[0m
|
||||
`- [info] available since OpenSSH 5.7, Dropbear SSH 2013.62
|
||||
[0;31m(kex) ecdh-sha2-nistp521 -- [fail] using weak elliptic curves[0m
|
||||
`- [info] available since OpenSSH 5.7, Dropbear SSH 2013.62
|
||||
[0;32m(kex) diffie-hellman-group-exchange-sha256 (2048-bit) -- [info] available since OpenSSH 4.4[0m
|
||||
[0;32m(kex) diffie-hellman-group16-sha512 -- [info] available since OpenSSH 7.3, Dropbear SSH 2016.73[0m
|
||||
[0;32m(kex) diffie-hellman-group18-sha512 -- [info] available since OpenSSH 7.3[0m
|
||||
[0;32m(kex) diffie-hellman-group14-sha256 -- [info] available since OpenSSH 7.3, Dropbear SSH 2016.73[0m
|
||||
[0;33m(kex) diffie-hellman-group14-sha1 -- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 3.9, Dropbear SSH 0.53
|
||||
|
||||
[0;36m# host-key algorithms[0m
|
||||
[0;32m(key) ssh-ed25519 -- [info] available since OpenSSH 6.5[0m
|
||||
[0;32m(key) ssh-ed25519-cert-v01@openssh.com -- [info] available since OpenSSH 6.5[0m
|
||||
|
||||
[0;36m# encryption algorithms (ciphers)[0m
|
||||
[0;32m(enc) chacha20-poly1305@openssh.com -- [info] available since OpenSSH 6.5[0m
|
||||
`- [info] default cipher since OpenSSH 6.9.
|
||||
[0;32m(enc) aes128-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52[0m
|
||||
[0;32m(enc) aes192-ctr -- [info] available since OpenSSH 3.7[0m
|
||||
[0;32m(enc) aes256-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52[0m
|
||||
[0;32m(enc) aes128-gcm@openssh.com -- [info] available since OpenSSH 6.2[0m
|
||||
[0;32m(enc) aes256-gcm@openssh.com -- [info] available since OpenSSH 6.2[0m
|
||||
|
||||
[0;36m# message authentication code algorithms[0m
|
||||
[0;33m(mac) umac-64-etm@openssh.com -- [warn] using small 64-bit tag size[0m
|
||||
`- [info] available since OpenSSH 6.2
|
||||
[0;32m(mac) umac-128-etm@openssh.com -- [info] available since OpenSSH 6.2[0m
|
||||
[0;32m(mac) hmac-sha2-256-etm@openssh.com -- [info] available since OpenSSH 6.2[0m
|
||||
[0;32m(mac) hmac-sha2-512-etm@openssh.com -- [info] available since OpenSSH 6.2[0m
|
||||
[0;33m(mac) hmac-sha1-etm@openssh.com -- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 6.2
|
||||
[0;33m(mac) umac-64@openssh.com -- [warn] using encrypt-and-MAC mode[0m
|
||||
[0;33m `- [warn] using small 64-bit tag size[0m
|
||||
`- [info] available since OpenSSH 4.7
|
||||
[0;33m(mac) umac-128@openssh.com -- [warn] using encrypt-and-MAC mode[0m
|
||||
`- [info] available since OpenSSH 6.2
|
||||
[0;33m(mac) hmac-sha2-256 -- [warn] using encrypt-and-MAC mode[0m
|
||||
`- [info] available since OpenSSH 5.9, Dropbear SSH 2013.56
|
||||
[0;33m(mac) hmac-sha2-512 -- [warn] using encrypt-and-MAC mode[0m
|
||||
`- [info] available since OpenSSH 5.9, Dropbear SSH 2013.56
|
||||
[0;33m(mac) hmac-sha1 -- [warn] using encrypt-and-MAC mode[0m
|
||||
[0;33m `- [warn] using weak hashing algorithm[0m
|
||||
`- [info] available since OpenSSH 2.1.0, Dropbear SSH 0.28
|
||||
|
||||
[0;36m# fingerprints[0m
|
||||
[0;32m(fin) ssh-ed25519: SHA256:UrnXIVH+7dlw8UqYocl48yUEcKrthGDQG2CPCgp7MxU[0m
|
||||
|
||||
[0;36m# algorithm recommendations (for OpenSSH 8.0)[0m
|
||||
[0;31m(rec) -ecdh-sha2-nistp256 -- kex algorithm to remove [0m
|
||||
[0;31m(rec) -ecdh-sha2-nistp384 -- kex algorithm to remove [0m
|
||||
[0;31m(rec) -ecdh-sha2-nistp521 -- kex algorithm to remove [0m
|
||||
[0;32m(rec) +rsa-sha2-256 -- key algorithm to append [0m
|
||||
[0;32m(rec) +rsa-sha2-512 -- key algorithm to append [0m
|
||||
[0;32m(rec) +ssh-rsa -- key algorithm to append [0m
|
||||
[0;33m(rec) -diffie-hellman-group14-sha1 -- kex algorithm to remove [0m
|
||||
[0;33m(rec) -hmac-sha1 -- mac algorithm to remove [0m
|
||||
[0;33m(rec) -hmac-sha1-etm@openssh.com -- mac algorithm to remove [0m
|
||||
[0;33m(rec) -hmac-sha2-256 -- mac algorithm to remove [0m
|
||||
[0;33m(rec) -hmac-sha2-512 -- mac algorithm to remove [0m
|
||||
[0;33m(rec) -umac-128@openssh.com -- mac algorithm to remove [0m
|
||||
[0;33m(rec) -umac-64-etm@openssh.com -- mac algorithm to remove [0m
|
||||
[0;33m(rec) -umac-64@openssh.com -- mac algorithm to remove [0m
|
||||
|
||||
[0;36m# additional info[0m
|
||||
[0;33m(nfo) For hardening guides on common OSes, please see: <https://www.ssh-audit.com/hardening_guides.html>[0m
|
||||
|
1
test/docker/expected_results/openssh_8.0p1_test3.json
Normal file
1
test/docker/expected_results/openssh_8.0p1_test3.json
Normal file
@ -0,0 +1 @@
|
||||
{"banner": {"comments": null, "protocol": [2, 0], "raw": "SSH-2.0-OpenSSH_8.0", "software": "OpenSSH_8.0"}, "compression": ["none", "zlib@openssh.com"], "enc": ["chacha20-poly1305@openssh.com", "aes256-gcm@openssh.com", "aes128-gcm@openssh.com", "aes256-ctr", "aes192-ctr", "aes128-ctr"], "fingerprints": [{"fp": "SHA256:UrnXIVH+7dlw8UqYocl48yUEcKrthGDQG2CPCgp7MxU", "type": "ssh-ed25519"}], "kex": [{"algorithm": "curve25519-sha256"}, {"algorithm": "curve25519-sha256@libssh.org"}, {"algorithm": "diffie-hellman-group-exchange-sha256", "keysize": 2048}], "key": [{"algorithm": "ssh-ed25519"}], "mac": ["hmac-sha2-256-etm@openssh.com", "hmac-sha2-512-etm@openssh.com", "umac-128-etm@openssh.com"]}
|
39
test/docker/expected_results/openssh_8.0p1_test3.txt
Normal file
39
test/docker/expected_results/openssh_8.0p1_test3.txt
Normal file
@ -0,0 +1,39 @@
|
||||
[0;36m# general[0m
|
||||
[0;32m(gen) banner: SSH-2.0-OpenSSH_8.0[0m
|
||||
[0;32m(gen) software: OpenSSH 8.0[0m
|
||||
[0;32m(gen) compatibility: OpenSSH 7.4+, Dropbear SSH 2018.76+[0m
|
||||
[0;32m(gen) compression: enabled (zlib@openssh.com)[0m
|
||||
|
||||
[0;36m# key exchange algorithms[0m
|
||||
[0;32m(kex) curve25519-sha256 -- [info] available since OpenSSH 7.4, Dropbear SSH 2018.76[0m
|
||||
[0;32m(kex) curve25519-sha256@libssh.org -- [info] available since OpenSSH 6.5, Dropbear SSH 2013.62[0m
|
||||
[0;32m(kex) diffie-hellman-group-exchange-sha256 (2048-bit) -- [info] available since OpenSSH 4.4[0m
|
||||
|
||||
[0;36m# host-key algorithms[0m
|
||||
[0;32m(key) ssh-ed25519 -- [info] available since OpenSSH 6.5[0m
|
||||
|
||||
[0;36m# encryption algorithms (ciphers)[0m
|
||||
[0;32m(enc) chacha20-poly1305@openssh.com -- [info] available since OpenSSH 6.5[0m
|
||||
`- [info] default cipher since OpenSSH 6.9.
|
||||
[0;32m(enc) aes256-gcm@openssh.com -- [info] available since OpenSSH 6.2[0m
|
||||
[0;32m(enc) aes128-gcm@openssh.com -- [info] available since OpenSSH 6.2[0m
|
||||
[0;32m(enc) aes256-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52[0m
|
||||
[0;32m(enc) aes192-ctr -- [info] available since OpenSSH 3.7[0m
|
||||
[0;32m(enc) aes128-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52[0m
|
||||
|
||||
[0;36m# message authentication code algorithms[0m
|
||||
[0;32m(mac) hmac-sha2-256-etm@openssh.com -- [info] available since OpenSSH 6.2[0m
|
||||
[0;32m(mac) hmac-sha2-512-etm@openssh.com -- [info] available since OpenSSH 6.2[0m
|
||||
[0;32m(mac) umac-128-etm@openssh.com -- [info] available since OpenSSH 6.2[0m
|
||||
|
||||
[0;36m# fingerprints[0m
|
||||
[0;32m(fin) ssh-ed25519: SHA256:UrnXIVH+7dlw8UqYocl48yUEcKrthGDQG2CPCgp7MxU[0m
|
||||
|
||||
[0;36m# algorithm recommendations (for OpenSSH 8.0)[0m
|
||||
[0;32m(rec) +diffie-hellman-group14-sha256 -- kex algorithm to append [0m
|
||||
[0;32m(rec) +diffie-hellman-group16-sha512 -- kex algorithm to append [0m
|
||||
[0;32m(rec) +diffie-hellman-group18-sha512 -- kex algorithm to append [0m
|
||||
[0;32m(rec) +rsa-sha2-256 -- key algorithm to append [0m
|
||||
[0;32m(rec) +rsa-sha2-512 -- key algorithm to append [0m
|
||||
[0;32m(rec) +ssh-rsa -- key algorithm to append [0m
|
||||
|
1
test/docker/expected_results/tinyssh_20190101_test1.json
Normal file
1
test/docker/expected_results/tinyssh_20190101_test1.json
Normal file
@ -0,0 +1 @@
|
||||
{"banner": {"comments": "", "protocol": [2, 0], "raw": "", "software": "tinyssh_noversion"}, "compression": ["none"], "enc": ["chacha20-poly1305@openssh.com"], "fingerprints": [{"fp": "SHA256:89ocln1x7KNqnMgWffGoYtD70ksJ4FrH7BMJHa7SrwU", "type": "ssh-ed25519"}], "kex": [{"algorithm": "curve25519-sha256"}, {"algorithm": "curve25519-sha256@libssh.org"}, {"algorithm": "sntrup4591761x25519-sha512@tinyssh.org"}], "key": [{"algorithm": "ssh-ed25519"}], "mac": ["hmac-sha2-256"]}
|
25
test/docker/expected_results/tinyssh_20190101_test1.txt
Normal file
25
test/docker/expected_results/tinyssh_20190101_test1.txt
Normal file
@ -0,0 +1,25 @@
|
||||
[0;36m# general[0m
|
||||
[0;32m(gen) software: TinySSH noversion[0m
|
||||
[0;32m(gen) compatibility: OpenSSH 8.0+, Dropbear SSH 2018.76+[0m
|
||||
[0;32m(gen) compression: disabled[0m
|
||||
|
||||
[0;36m# key exchange algorithms[0m
|
||||
[0;32m(kex) curve25519-sha256 -- [info] available since OpenSSH 7.4, Dropbear SSH 2018.76[0m
|
||||
[0;32m(kex) curve25519-sha256@libssh.org -- [info] available since OpenSSH 6.5, Dropbear SSH 2013.62[0m
|
||||
[0;33m(kex) sntrup4591761x25519-sha512@tinyssh.org -- [warn] using experimental algorithm[0m
|
||||
`- [info] available since OpenSSH 8.0
|
||||
|
||||
[0;36m# host-key algorithms[0m
|
||||
[0;32m(key) ssh-ed25519 -- [info] available since OpenSSH 6.5[0m
|
||||
|
||||
[0;36m# encryption algorithms (ciphers)[0m
|
||||
[0;32m(enc) chacha20-poly1305@openssh.com -- [info] available since OpenSSH 6.5[0m
|
||||
`- [info] default cipher since OpenSSH 6.9.
|
||||
|
||||
[0;36m# message authentication code algorithms[0m
|
||||
[0;33m(mac) hmac-sha2-256 -- [warn] using encrypt-and-MAC mode[0m
|
||||
`- [info] available since OpenSSH 5.9, Dropbear SSH 2013.56
|
||||
|
||||
[0;36m# fingerprints[0m
|
||||
[0;32m(fin) ssh-ed25519: SHA256:89ocln1x7KNqnMgWffGoYtD70ksJ4FrH7BMJHa7SrwU[0m
|
||||
|
7
test/docker/host_ca_ed25519
Normal file
7
test/docker/host_ca_ed25519
Normal file
@ -0,0 +1,7 @@
|
||||
-----BEGIN OPENSSH PRIVATE KEY-----
|
||||
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
|
||||
QyNTUxOQAAACAbM9Wp3ZPcC8Ifhu6GjNDJaoMg7KxO0el2+r9J35TltQAAAKAa0zr8GtM6
|
||||
/AAAAAtzc2gtZWQyNTUxOQAAACAbM9Wp3ZPcC8Ifhu6GjNDJaoMg7KxO0el2+r9J35TltQ
|
||||
AAAEC/j/BpfmgaZqNMTkJXO4cKZBr31N5z33IRFjh5m6IDDhsz1andk9wLwh+G7oaM0Mlq
|
||||
gyDsrE7R6Xb6v0nflOW1AAAAHWpkb2dAbG9jYWxob3N0LndvbmRlcmxhbmQubG9s
|
||||
-----END OPENSSH PRIVATE KEY-----
|
1
test/docker/host_ca_ed25519.pub
Normal file
1
test/docker/host_ca_ed25519.pub
Normal file
@ -0,0 +1 @@
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBsz1andk9wLwh+G7oaM0MlqgyDsrE7R6Xb6v0nflOW1 jdog@localhost.wonderland.lol
|
15
test/docker/host_ca_rsa_1024
Normal file
15
test/docker/host_ca_rsa_1024
Normal file
@ -0,0 +1,15 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIICXgIBAAKBgQDnRlN3AFnUe2lFf5XG9UhXLr/9POruNTFbMt0zrjOUSjmAS7hS
|
||||
6pDv5VEToT6DaR1EQUYaqSMpHYzZhuCK52vrydOm5XFbJ7712r9MyZQUhoVZx8Su
|
||||
dBHzVDIVO3jcMMWIlrfWBMnUaUHEqpmy88Y7gKDa2TWxJg1+hg51KqHrUQIDAQAB
|
||||
AoGBANALOUXRcP1tTtOP4+In/709dsONKyDBhPavGMFGsWtyIavBcbxU+bBzrq1j
|
||||
3WJFCmi99xxAjjqMNInxhMgvSaoJtsiY0/FFxqRy6l/ZnRjI6hrVKR8whrPKVgBF
|
||||
pvbjeQIn9txeCYA8kwl/Si762u7byq+qvupE53xMP94J02KBAkEA/Q4+Hn1Rjblw
|
||||
VXynF+oXIq6iZy+8PW+Y/FIL8d31ehzfcssCMdFV6S3/wBoQkWby30oGC/xGmHGR
|
||||
6ffXGilByQJBAOn3NMrBPXNkaPeQtgV3tk4s1dRDQYhbqGNz6tcgThyyPdhJCmCy
|
||||
jgUEhLwAetsDI8/+3avWbo6/csOV+BvpYUkCQQDQyEp6L1z0+FV1QqY99dZmt/yn
|
||||
89t0OLnZG/xc7osU1/OHq3TBE3y1KU2D+j1HKdAiZ9l7VAYOykzf46qmG/n5AkEA
|
||||
2kWjfcjcIIw7lULvXZh6fuI7NwTr3V/Nb8MUA1EDLqhnJCG4SdAqyKmXf6Fe/HYo
|
||||
cgKPIaIykIAxfCCsULXg6QJAOxB0CKYJlopVBdjGMlGqOEneWTmb1A2INQDE2Una
|
||||
LkSd0Rr8OiEzDeemV7j3Ec4BH0HxGMnHDxMybZwoZRnRPw==
|
||||
-----END RSA PRIVATE KEY-----
|
1
test/docker/host_ca_rsa_1024.pub
Normal file
1
test/docker/host_ca_rsa_1024.pub
Normal file
@ -0,0 +1 @@
|
||||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDnRlN3AFnUe2lFf5XG9UhXLr/9POruNTFbMt0zrjOUSjmAS7hS6pDv5VEToT6DaR1EQUYaqSMpHYzZhuCK52vrydOm5XFbJ7712r9MyZQUhoVZx8SudBHzVDIVO3jcMMWIlrfWBMnUaUHEqpmy88Y7gKDa2TWxJg1+hg51KqHrUQ== jdog@localhost.wonderland.lol
|
39
test/docker/host_ca_rsa_3072
Normal file
39
test/docker/host_ca_rsa_3072
Normal file
@ -0,0 +1,39 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIG4wIBAAKCAYEAqxQEIbj8w0TrBY1fDO81curijQrdLOUr8Vl8XECWc5QGd1Lk
|
||||
AG80NgdcCBPvjWxZSmYrKeqA78GUdN+KgycE0ztpxYSXKHZMaIM5Xe94BB+BocH9
|
||||
1vd/2iBzGeed1nV/zfAdq2AEHQj1TpII+a+z25yxv2PuwVTTwwo9I/6JgNq3evH4
|
||||
Hbwgr3SRfEEYZQ+YL8cOpBuNg1YZOR0k1yk23ZqAd92JybxZ4iCtOt7rcj2sFHzN
|
||||
u1U544wWBwIL5yZZKTgBhY4dqfT2Ep7IzR5HdsdrvQV9qC92GM1zDE+U3AwrVKjH
|
||||
s0YZq3jzcq/yvFDCcMMRz4/0pGFFU26oWma+n3vbAxKJoL+rhG8QM9+l2qFlLGsn
|
||||
M0kUXAJXsPKbygpaP8Z3U4eKgTuJ2GuS9eLIFnB7mrwD75V6GgN9q5mY89DfkVSk
|
||||
HaoqpY8pPdRkz9QAmMEuLtHmv29CVOpfX5v/rsm7wASAZqtUlmFu4rFGBLwvZbUl
|
||||
Wu02HmgBT47g6EIfAgMBAAECggGAKVCdKtO03yd+pomcodAHFWiaK7uq7FOwCAo3
|
||||
WUQT0Xe3FAwFmgFBF6cxV5YQ7RN0gN4poGbMmpoiUxNFLSU4KhcYFSZPJutiyn6e
|
||||
VQwm7L/7G2hw+AAvdSsPAPuJh6g6pC5Py/pVI/ns2/uyhTIkem3eEz18BF6LAXgw
|
||||
icfHx0GKu/tBk1TCg/zfwaUq0gUxGKC27XTl+QjK8JsUMY33fQ755Xiv9PMytcR0
|
||||
cVoyfBVewFffi1UqtMQ48ZpR65G743RxrP4/wcwsfD7n5LJLdyxQkh3gIMTJ8dd/
|
||||
R5V4FlueorRgjTbLTjGDxNrCAJ+locezhEEPXsPh2q0KiIXGyz2AMxaOqFmhU8oK
|
||||
aVVt8pWJ+YsrKIgc/A3s18ezO8uO5ZdtjQ+CWguduUGY7YgWezGLO1LPxhJC4d7b
|
||||
Q/xpeKveTRlcScAqOUzKgSuEhcvPgj8paUcRUoiXm4qiJBY5sXJks+YGp8BGksH0
|
||||
O94no+Ns2G58MlL+RyXk3JWrc6zRAoHBANdPplY2sIuIiiEBu95f1Qar1nCBHhB2
|
||||
i+HpnsUOdSlbxwMxoF8ffeN9N+DQqaqPu1RhFa5xbB2EUSujvOnL7b/RWqe1X9Po
|
||||
UIt5UjXctNP/HYcQDyjXY+rV5SZhHDyv6TBYurNZlvlBivliDz82THPRtqVxed3B
|
||||
w2MeaSkKAQ8rA7PE+0j3TG+YtIij0mHOhNPJgEZ/XZ9MIQOGMycRJhwOlclBI5NP
|
||||
Ak6p30ArnU2fX4qMkU3i+wqUfXS1hhDihwKBwQDLaHWPIWPVbWdcCbYQTcUmFC3i
|
||||
xkxd0UuLcfS9csk61nvdFj7m8tMExX+3fIo/fHEtzDd98Alc1i6/f6ePl0CX6NDu
|
||||
QIWLryI1QQRQidHCdw0wQ3N3VD4ZXJHDeqBxogVAkA7A/1QeXwcXE/Xj2ZgyDwhL
|
||||
3+myjmvWtw9zJsXL0F3tpPzn+Mrf0KRkWOaluOw7hMMjVjrgu6g24HMWbHHVLRTx
|
||||
dlAI7tgxCAPe2SEi+1mzaVUZ8cfgqYqC3X66UakCgcEAopxtK7+yJi/A4pzEnnYS
|
||||
FS/CjMV3R0fA7aXbW0hIBCxkaW0Zib3m/eCcSxZMjZxwBpIsJctTtBcylprbGlgB
|
||||
/1TF+tNoxEo4Sp4eEL/XciTC0Da4vEewFrPklM/S26KfovvgRYPsGeP+aco9aahA
|
||||
pVhFcT36pBiq0DkvgucjValO6n5iqgDboYzbDDdttKCcgLc2Qgf/VUfRxy+bgm3Z
|
||||
MmdxiMXBcIfDXlW9XmGSNAWhyqnPM9uxbZQoC/Tsg+QRAoHANHMcFSsz9f2+8DGk
|
||||
27FiC76aUmZ1nJ9yTmO1CwDFOMHDsK+iyqSEmy9eDm8zqsko2flVuciicWjdJw4A
|
||||
o/sJceJbtYO3q9weAwNf3HCdQPq30OEjrfpwBNQk1fYR1xtDJXHADC4Kf8ZbKq0/
|
||||
81/Rad8McZwsQ5mL3xLXDgdKa5KwFa48dIhnr6y6JxHxb3wule5W7w62Ierhpjzc
|
||||
EEUoWSLFyrmKS7Ni1cnOTbFJZR7Q831Or2Dz/E9bYwFAQ0T5AoHAM4/zU+8rsbdD
|
||||
FvvhWsj7Ivfh6pxx1Tl1Wccaauea9AJayHht0FOzkycpJrH1E+6F5MzhkFFU1SUY
|
||||
60NZxzSZgbU0HBrJRcRFyo510iMcnctdTdyh8p7nweGoD0oqXzf6cHqrUep8Y8rQ
|
||||
gkSVhPE31+NGlPbwz+NOflcaaAWYiDC6wjVt1asaZq292SJD4DF1fAUkbQ2hxgyQ
|
||||
+G/6y5ovrcGnh7q63RLhW1TRf8dD2D2Av9UgXDmWZAZ5n838FS+X
|
||||
-----END RSA PRIVATE KEY-----
|
1
test/docker/host_ca_rsa_3072.pub
Normal file
1
test/docker/host_ca_rsa_3072.pub
Normal file
@ -0,0 +1 @@
|
||||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCrFAQhuPzDROsFjV8M7zVy6uKNCt0s5SvxWXxcQJZzlAZ3UuQAbzQ2B1wIE++NbFlKZisp6oDvwZR034qDJwTTO2nFhJcodkxogzld73gEH4Ghwf3W93/aIHMZ553WdX/N8B2rYAQdCPVOkgj5r7PbnLG/Y+7BVNPDCj0j/omA2rd68fgdvCCvdJF8QRhlD5gvxw6kG42DVhk5HSTXKTbdmoB33YnJvFniIK063utyPawUfM27VTnjjBYHAgvnJlkpOAGFjh2p9PYSnsjNHkd2x2u9BX2oL3YYzXMMT5TcDCtUqMezRhmrePNyr/K8UMJwwxHPj/SkYUVTbqhaZr6fe9sDEomgv6uEbxAz36XaoWUsayczSRRcAlew8pvKClo/xndTh4qBO4nYa5L14sgWcHuavAPvlXoaA32rmZjz0N+RVKQdqiqljyk91GTP1ACYwS4u0ea/b0JU6l9fm/+uybvABIBmq1SWYW7isUYEvC9ltSVa7TYeaAFPjuDoQh8= jdog@localhost.wonderland.lol
|
44
test/docker/moduli_1024
Normal file
44
test/docker/moduli_1024
Normal file
@ -0,0 +1,44 @@
|
||||
20190821035337 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC08BE313B
|
||||
20190821035338 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC08C0B443
|
||||
20190821035338 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC08D1AF8B
|
||||
20190821035338 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC08E76DDB
|
||||
20190821035338 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC08E8F5D3
|
||||
20190821035338 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC08EE3F1B
|
||||
20190821035338 2 6 100 1023 5 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC08F28387
|
||||
20190821035339 2 6 100 1023 5 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC08F69A57
|
||||
20190821035339 2 6 100 1023 5 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC0903B157
|
||||
20190821035339 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC0905C973
|
||||
20190821035339 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC0909BCD3
|
||||
20190821035339 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC090F4A2B
|
||||
20190821035340 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC0933BC13
|
||||
20190821035340 2 6 100 1023 5 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC09395757
|
||||
20190821035340 2 6 100 1023 5 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC093F40D7
|
||||
20190821035340 2 6 100 1023 5 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC09478D4F
|
||||
20190821035340 2 6 100 1023 5 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC0953A4D7
|
||||
20190821035340 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC095B5C7B
|
||||
20190821035341 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC09696573
|
||||
20190821035341 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC096BA243
|
||||
20190821035341 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC096F3903
|
||||
20190821035341 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC09850E4B
|
||||
20190821035341 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC098A1C23
|
||||
20190821035341 2 6 100 1023 5 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC098E08E7
|
||||
20190821035342 2 6 100 1023 5 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC09A4FF7F
|
||||
20190821035342 2 6 100 1023 5 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC09AE4707
|
||||
20190821035342 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC09B4CE73
|
||||
20190821035342 2 6 100 1023 5 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC09C60C6F
|
||||
20190821035342 2 6 100 1023 5 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC09D2588F
|
||||
20190821035343 2 6 100 1023 5 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC0A025067
|
||||
20190821035343 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC0A0E38EB
|
||||
20190821035343 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC0A213923
|
||||
20190821035344 2 6 100 1023 5 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC0A390CA7
|
||||
20190821035344 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC0A3C7ADB
|
||||
20190821035344 2 6 100 1023 5 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC0A44D497
|
||||
20190821035344 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC0A479B13
|
||||
20190821035345 2 6 100 1023 5 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC0A5EF01F
|
||||
20190821035345 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC0A615D43
|
||||
20190821035345 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC0A6BEADB
|
||||
20190821035345 2 6 100 1023 5 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC0A86309F
|
||||
20190821035345 2 6 100 1023 5 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC0A991E8F
|
||||
20190821035346 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC0AA32C53
|
||||
20190821035346 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC0AA9FAAB
|
||||
20190821035346 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC0AAC42BB
|
BIN
test/docker/ssh1_host_key
Normal file
BIN
test/docker/ssh1_host_key
Normal file
Binary file not shown.
1
test/docker/ssh1_host_key.pub
Normal file
1
test/docker/ssh1_host_key.pub
Normal file
@ -0,0 +1 @@
|
||||
1024 35 150823875409720459951648542224727752099073441604930026287525797402159071426070997897033651155038337251362080634963146983947007228274330777134724953282680928153520263171933106732090266742784258910450489054624715996015082463159338507115031336180486071622718809324273851629938883104520608180885444242395900180011 root@ubuntu1604server
|
12
test/docker/ssh_host_dsa_key
Normal file
12
test/docker/ssh_host_dsa_key
Normal file
@ -0,0 +1,12 @@
|
||||
-----BEGIN DSA PRIVATE KEY-----
|
||||
MIIBugIBAAKBgQDth1eV+A8j191R0ey0dVXL2LGNGYM+a+PomSa7suK8xNCeVLKC
|
||||
YpQ6VSWpAf6FbRWev1UVo8IpbglwFZPcyFPK2G1H7p45ows2SN4CleszDD56e6W0
|
||||
3Plc+qMqSJ6LTjr4M5+HqTDOM3CS72d7MXUkfHQiagyrWQhXyc0kFsNJLwIVAKg7
|
||||
b5+NiIZzpg5IEH0tlYFQpuhBAoGAGcbq79QqNNZRuPCE/F05sCoTRGCmFnDjCuCg
|
||||
WN7wNRotjMz/S3pHtCCeuTT1jT6Hy0ZFHftv0t/GF8GBRgeokUbS4ytHpOkFWcTz
|
||||
8oFguDL44nq8eNfSY6bzEl84qsgEe4HP93mB4FR1ZUUgI4b7gCBOYEFl3yPiH7H1
|
||||
p7Z9E1oCgYAl1UPQkeRhElz+AgEbNsnMKu1+6O3/z95D1Wvv4OEwAImbytlBaC7p
|
||||
kwJElJNsMMfGqCC8OHdJ0e4VQQUwk/GOhD0MFhVQHBtVZYbiWmVkpfHf1ouUQg3f
|
||||
1IZmz2SSt6cPPEu+BEQ/Sn3mFRJ5XSTHLtnI0HJeDND5u1+6p1nXawIURv3Maige
|
||||
oxmfqC24VoROJEq+sew=
|
||||
-----END DSA PRIVATE KEY-----
|
1
test/docker/ssh_host_dsa_key.pub
Normal file
1
test/docker/ssh_host_dsa_key.pub
Normal file
@ -0,0 +1 @@
|
||||
ssh-dss AAAAB3NzaC1kc3MAAACBAO2HV5X4DyPX3VHR7LR1VcvYsY0Zgz5r4+iZJruy4rzE0J5UsoJilDpVJakB/oVtFZ6/VRWjwiluCXAVk9zIU8rYbUfunjmjCzZI3gKV6zMMPnp7pbTc+Vz6oypInotOOvgzn4epMM4zcJLvZ3sxdSR8dCJqDKtZCFfJzSQWw0kvAAAAFQCoO2+fjYiGc6YOSBB9LZWBUKboQQAAAIAZxurv1Co01lG48IT8XTmwKhNEYKYWcOMK4KBY3vA1Gi2MzP9Leke0IJ65NPWNPofLRkUd+2/S38YXwYFGB6iRRtLjK0ek6QVZxPPygWC4Mvjierx419JjpvMSXziqyAR7gc/3eYHgVHVlRSAjhvuAIE5gQWXfI+IfsfWntn0TWgAAAIAl1UPQkeRhElz+AgEbNsnMKu1+6O3/z95D1Wvv4OEwAImbytlBaC7pkwJElJNsMMfGqCC8OHdJ0e4VQQUwk/GOhD0MFhVQHBtVZYbiWmVkpfHf1ouUQg3f1IZmz2SSt6cPPEu+BEQ/Sn3mFRJ5XSTHLtnI0HJeDND5u1+6p1nXaw==
|
5
test/docker/ssh_host_ecdsa_key
Normal file
5
test/docker/ssh_host_ecdsa_key
Normal file
@ -0,0 +1,5 @@
|
||||
-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEICq/YV5QenL0uW5g5tCjY3EWs+UBFmskY+Jjt2vd2aEmoAoGCCqGSM49
|
||||
AwEHoUQDQgAEdYSxDVUjOpW479L/nRDiAdxRB5Kuy2bgkP/LA2pnWPcGIWmFa4QU
|
||||
YN2U3JsFKcLIcx5cvTehQfgrHDnaSKVdKA==
|
||||
-----END EC PRIVATE KEY-----
|
1
test/docker/ssh_host_ecdsa_key.pub
Normal file
1
test/docker/ssh_host_ecdsa_key.pub
Normal file
@ -0,0 +1 @@
|
||||
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHWEsQ1VIzqVuO/S/50Q4gHcUQeSrstm4JD/ywNqZ1j3BiFphWuEFGDdlNybBSnCyHMeXL03oUH4Kxw52kilXSg=
|
7
test/docker/ssh_host_ed25519_key
Normal file
7
test/docker/ssh_host_ed25519_key
Normal file
@ -0,0 +1,7 @@
|
||||
-----BEGIN OPENSSH PRIVATE KEY-----
|
||||
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
|
||||
QyNTUxOQAAACC/9RD2Ao95ODDIH8i11ekTALut8AUNqWoQx0jHlP4xygAAAKDiqVOs4qlT
|
||||
rAAAAAtzc2gtZWQyNTUxOQAAACC/9RD2Ao95ODDIH8i11ekTALut8AUNqWoQx0jHlP4xyg
|
||||
AAAECTmHGkq0Qea0QqTJYMXL0bpxVU7mhgwYninfVWxrA017/1EPYCj3k4MMgfyLXV6RMA
|
||||
u63wBQ2pahDHSMeU/jHKAAAAHWpkb2dAbG9jYWxob3N0LndvbmRlcmxhbmQubG9s
|
||||
-----END OPENSSH PRIVATE KEY-----
|
1
test/docker/ssh_host_ed25519_key-cert.pub
Normal file
1
test/docker/ssh_host_ed25519_key-cert.pub
Normal file
@ -0,0 +1 @@
|
||||
ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIO1W0I8tD0c4LypvHY1XNch3BQCw9Yy28/4KmAYql80DAAAAIL/1EPYCj3k4MMgfyLXV6RMAu63wBQ2pahDHSMeU/jHKAAAAAAAAAAAAAAACAAAABHRlc3QAAAAIAAAABHRlc3QAAAAAXV7hvAAAAACBa2YhAAAAAAAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACAbM9Wp3ZPcC8Ifhu6GjNDJaoMg7KxO0el2+r9J35TltQAAAFMAAAALc3NoLWVkMjU1MTkAAABAW60bCSeIG4Ta+57zgkSbW4LIGCxtOuJJ+pP3i3S0xJJfHGnOtXbg0NQm7pulNl/wd01kgJO9A7RjbhTh7TV1AA== ssh_host_ed25519_key.pub
|
1
test/docker/ssh_host_ed25519_key.pub
Normal file
1
test/docker/ssh_host_ed25519_key.pub
Normal file
@ -0,0 +1 @@
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL/1EPYCj3k4MMgfyLXV6RMAu63wBQ2pahDHSMeU/jHK
|
15
test/docker/ssh_host_rsa_key_1024
Normal file
15
test/docker/ssh_host_rsa_key_1024
Normal file
@ -0,0 +1,15 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIICXgIBAAKBgQDeCC1U7VqVg9AfrfWrXACiW6pzYOuP8tim68z+YN/dUU7JhFZ4
|
||||
0toteQkLcJBAD2miQ6ZJYkjVfhQ4FRFeOW5vcN0UYHn8ttb2mKdGJdt24ZYY5Z6J
|
||||
WHQhPOpSgtWyUv6RnxU2ligEeaoPaiepUUOhoyLf4WcF7voVCAKZNqeTtQIDAQAB
|
||||
AoGATGZ16s5NqDsWJ4B9k3xx/2wZZ+BGzl6a7D0habq97XLn8HGoK6UqTBFk6lnO
|
||||
WSy0hZBPrNq0AzqCDJY7RrfuZqgVAu/+HEFuXencgt8Z//ueYBaGK8yAC+OrMnDG
|
||||
LbSoIGRq8saaFtCzt47c+uSVsrhJ4TvK5gbceZuD/2uw10ECQQD79T0j+YWsLISK
|
||||
PKvYHqEXSMPN6b+lK9hRPLoF9NMksNLSjuxxhkYHz+hJPVNT+wPtRMAYmMdPXfKa
|
||||
FjuErXVFAkEA4ZgJIOeJ7OHfqGEgd29m36yFy0UaUJ+cmYuJzHAYWgW3TOanqpZm
|
||||
A8EENuXvH0DtYRVytv4m/cIRVVPxWtXzsQJBALXlQUOEc0VuSi1GScVXr3KQ3JL+
|
||||
ipWixqM3VRDRw9D8Ouc5uWbnygz/wrGFLXA2ioozlP7s5Q7eQzOMk2FgnIUCQQCz
|
||||
j5QUgLcjuVWQbF6vMhisCGImPUaIzcKT5KE1/DMl1E7mAuGJwlRIwKVeHP6L3d4T
|
||||
3EKGrRzT9lhdlocRSiLBAkEAi3xI0MOZp4xGviPc1C1TKuqdJSr8fHwbtLozwNQO
|
||||
nnF6m5S72JzZEThDBZS9zcdBp9EFpTvUGzx/O0GI454eoA==
|
||||
-----END RSA PRIVATE KEY-----
|
1
test/docker/ssh_host_rsa_key_1024-cert_1024.pub
Normal file
1
test/docker/ssh_host_rsa_key_1024-cert_1024.pub
Normal file
@ -0,0 +1 @@
|
||||
ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgFqxXSa9HTqCw5YW3DdIwVREPGxI+i56w32RnHWRg0NoAAAADAQABAAAAgQDeCC1U7VqVg9AfrfWrXACiW6pzYOuP8tim68z+YN/dUU7JhFZ40toteQkLcJBAD2miQ6ZJYkjVfhQ4FRFeOW5vcN0UYHn8ttb2mKdGJdt24ZYY5Z6JWHQhPOpSgtWyUv6RnxU2ligEeaoPaiepUUOhoyLf4WcF7voVCAKZNqeTtQAAAAAAAAAAAAAAAgAAAAR0ZXN0AAAACAAAAAR0ZXN0AAAAAF1evHgAAAAAgWtAtQAAAAAAAAAAAAAAAAAAAJcAAAAHc3NoLXJzYQAAAAMBAAEAAACBAOdGU3cAWdR7aUV/lcb1SFcuv/086u41MVsy3TOuM5RKOYBLuFLqkO/lUROhPoNpHURBRhqpIykdjNmG4Irna+vJ06blcVsnvvXav0zJlBSGhVnHxK50EfNUMhU7eNwwxYiWt9YEydRpQcSqmbLzxjuAoNrZNbEmDX6GDnUqoetRAAAAjwAAAAdzc2gtcnNhAAAAgFRc2g0eWXGmqSa6Z8rcMPHf4rNMornEHSnTzZ8Rdh4YBhDa9xMRRy6puaWPDzXxOfZh7eSjCwrzUMEXTgCIO4oX62xm/6kUnAmKhXle0+inR/hdPg03daE0SBJ4spBT49lJ4WIW38RKFNzjmYg70rTPAnP8oM/F3CC1GV117/Vv ssh_host_rsa_key_1024.pub
|
1
test/docker/ssh_host_rsa_key_1024-cert_3072.pub
Normal file
1
test/docker/ssh_host_rsa_key_1024-cert_3072.pub
Normal file
@ -0,0 +1 @@
|
||||
ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgrJGcfyW8V6VWGT7lD1ardj2RtTP8TOjmLRNbuoGkyZQAAAADAQABAAAAgQDeCC1U7VqVg9AfrfWrXACiW6pzYOuP8tim68z+YN/dUU7JhFZ40toteQkLcJBAD2miQ6ZJYkjVfhQ4FRFeOW5vcN0UYHn8ttb2mKdGJdt24ZYY5Z6JWHQhPOpSgtWyUv6RnxU2ligEeaoPaiepUUOhoyLf4WcF7voVCAKZNqeTtQAAAAAAAAAAAAAAAgAAAAR0ZXN0AAAACAAAAAR0ZXN0AAAAAF1evHgAAAAAgWtA7gAAAAAAAAAAAAAAAAAAAZcAAAAHc3NoLXJzYQAAAAMBAAEAAAGBAKsUBCG4/MNE6wWNXwzvNXLq4o0K3SzlK/FZfFxAlnOUBndS5ABvNDYHXAgT741sWUpmKynqgO/BlHTfioMnBNM7acWElyh2TGiDOV3veAQfgaHB/db3f9ogcxnnndZ1f83wHatgBB0I9U6SCPmvs9ucsb9j7sFU08MKPSP+iYDat3rx+B28IK90kXxBGGUPmC/HDqQbjYNWGTkdJNcpNt2agHfdicm8WeIgrTre63I9rBR8zbtVOeOMFgcCC+cmWSk4AYWOHan09hKeyM0eR3bHa70FfagvdhjNcwxPlNwMK1Sox7NGGat483Kv8rxQwnDDEc+P9KRhRVNuqFpmvp972wMSiaC/q4RvEDPfpdqhZSxrJzNJFFwCV7Dym8oKWj/Gd1OHioE7idhrkvXiyBZwe5q8A++VehoDfauZmPPQ35FUpB2qKqWPKT3UZM/UAJjBLi7R5r9vQlTqX1+b/67Ju8AEgGarVJZhbuKxRgS8L2W1JVrtNh5oAU+O4OhCHwAAAY8AAAAHc3NoLXJzYQAAAYCO78ONpHp+EGWDqDLb/GPFDH32o6oaRRrIH/Bhvg1FOi5XngnHTdU7xWdnJqNE2Sl6VOrg0sTCMYcX9fZ8tVREnCo3aF7Iwow5Br67QYKayRzHANQqHaVK46lpI1gz81V00u54tX1F8oEUqm6sRmFKFuklt6CjfbR+tnpj7DrfeOTKEBOGJP2uU0jMsJr2DrBeXrzONjIJtIJ1AxWjXd2LeIWO2C6yTkcN5ggThMMaeu6QuuBPpC2PN2COfu+Mgto9g103+/SS4Wa8CzinZZn2Xe1isUxI8QRNrShy4Hl/bIZQL7mi/0rxkfw+fA7IzMk462V99gPVSp+/jK0sbUJoC3QeeglS5hWodjW+VGZfgweGQ+AE/OxkNSv+kDPMYEkjfOf4qhxS5QFvButLt6zp2UNbE5+OWvYpdjO9/DOa0ro+wCw07+dVKIcDpU2csiCcJvQ/HmKAmhch7jOHa0WaxSX0tt0xTPJWTvr6E4WZOgEnk9AvWmrKjF5tEzGYwTU= ssh_host_rsa_key_1024.pub
|
1
test/docker/ssh_host_rsa_key_1024.pub
Normal file
1
test/docker/ssh_host_rsa_key_1024.pub
Normal file
@ -0,0 +1 @@
|
||||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDeCC1U7VqVg9AfrfWrXACiW6pzYOuP8tim68z+YN/dUU7JhFZ40toteQkLcJBAD2miQ6ZJYkjVfhQ4FRFeOW5vcN0UYHn8ttb2mKdGJdt24ZYY5Z6JWHQhPOpSgtWyUv6RnxU2ligEeaoPaiepUUOhoyLf4WcF7voVCAKZNqeTtQ==
|
39
test/docker/ssh_host_rsa_key_3072
Normal file
39
test/docker/ssh_host_rsa_key_3072
Normal file
@ -0,0 +1,39 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIG5AIBAAKCAYEAzhHp7eFnrQAJqOd7aihyQyIDKgxCF7H51Q3Ft3+8af+lX3Ol
|
||||
Ie77Gi5GNNM+eRB4OzG+CBslxN5I3pM//sZ+gyylA1VuWZZkOlgtbOHutIkO2ldk
|
||||
XtoGidla0VAxLcUcUK6cCmqwBTT31Hp4Qimp2zyeg/l5q0DhWKguY13lrm5b3YZY
|
||||
rj7CW3Ktzxf8SbYz6du8KF0dHCWilzq+FLeGzXr7Yul5njVF5njkGvZ9duQ0qiVR
|
||||
zqZkrkLEWgQlCM0T+PyUbvedL1MfDZPHGh7ZhU0snOvJRsxAr31tlknq+WwauZYd
|
||||
DzJf1g1URcM65UwEsPlfgOW3ZoZogR1v57Im+KdsKhq2B3snEtJgdQh06JyO0ur4
|
||||
uUXo1mMtvBFhiptUtwP4g9v/IN4neeK+wBRom46m2Q1bMUBPneBOa8r2SY/3ynrz
|
||||
XuVIWFOQtF60aJ+BNqvgUVCKOmz1KzoJwTqGm+EFaKM5z+UQWjIbSE3Ge4X5hXtk
|
||||
Ou52v+tyDUk6boZLAgMBAAECggGAdrhxWmA7N7tG1W2Pd6iXs7+brRTk2vvpYGqP
|
||||
11kbNsJXBzf8EiG5vuqb/gEaA+uOKSRORCNHzjT2LG0POHwpFO+aneIRMkHnuolk
|
||||
mk9ME+zGhtpEdDUOAUsc/GxD+QePeZgvQ/0VLdrHUT3BnPSd7DXvaT9IbnZxnX8/
|
||||
QnYtRiJEgMrOuoxjswXNxvsdmWYEYJ38uBB1Hes80f3A1vSpECbjP6gdLh2pCM/r
|
||||
MvGBdQaipMfdar4IUTEcKHQs1fY3mlAxnWRjYCqJPmq10d3NrdUrHb2zBE1HCC4h
|
||||
aj2ycTxFhDJqGV6Y2AboHqh2c7lPJ+R2UjI9mIpALZSviHB1POcpWCAGA3NKjri9
|
||||
8jgxl3bj03ikJNfCuvlqRTa8at63W2zZTMRsxamoiO023uUOEMNBPwWXP/rVhQ8g
|
||||
ufih0SY44j0EMPIuu2PoQV4ZSOtDw8xdPrchVCa078/pP5cRa4uV0bl2K4as+cYC
|
||||
BhjEq2Org3ulDW2n6Mz5ZS7NbAkxAoHBAP/bgPGKX7rfrHa5MRHIgbLSmZtUoF51
|
||||
YGelc8ytRx6UT6wriJ1jQRXiI5mZlIXyVxMpIz9s4+h59kF+LpZuNLc3vTYpPOQn
|
||||
RUDBVY6+SPC5MancL7bfBoHahpWEJuJB/WUE7eWvQM03/LsBtU6Nq+R632t5KdqF
|
||||
A4y86qgD1vIjcBWvySLFJZGOCoNbj7ZinoBUO3ueYK6SUj8xH6TAqOJsTPvquRT3
|
||||
AFBpFBmrVc24wW7wTiLkQOhkIQs1J/ZhYwKBwQDOL07qF8wsoQBBTTXkZ59BCauz
|
||||
R8kfqe5oUBwsmGJdiIHX6gutBA07sSwzVekIvCCkJFXk3TxLoBSMHEZEIdnS+HVt
|
||||
gMIacYuhbh+XztdY0kadH/SMbVQD/2LZcL99vcZPq1QF3cHb0Buip5+fyAYjoEc7
|
||||
oVgvewD/TwdNcMjos/kMNh6l04kLi6vQG3WhoSBPWaoB669ppBNXSrWKe43nXVi6
|
||||
EvjGEiL+HCCnmD6LiD6p797Owu9AChP6fXInD/kCgcEAiLP3SRbt3yLzOtvn4+CF
|
||||
q83qVJv6s31zbO1x2cIbZbNIfm0kKTOG6vJQoxjzyj2ZWJt6QcEkZGoFsSiCK83m
|
||||
TJ5zciTGbACvd9HUrNfukO/iISeMNuEi0O65Sdm6DNnFUdw4X6grr3pihmh7PuVj
|
||||
GkisZvft7Nt08hVeKzch+W4FzRCHHxTG5eZGp7icKI64sUhQH9SXQ67aUvkkNxrZ
|
||||
IWFMIK1hBlqSyGPcYXqx9aDpeSTcGrhqFcCqBxr3pySRAoHAfJNO3delEC3yxoHN
|
||||
FwSYzyX1rOuplE0K89G7RCKKBDNPKFKL3Wx+Rluk9htpIlLwcdxWXWJiZNsCrykC
|
||||
N3YwcuyVnqTWIj4KfG3Z/tIFgPADpDnDevkvcv7iDbi2qlV4NXix2p2C3LnfiKY4
|
||||
psSnGO1lPJ0eeAmcr6VjJyIG8bqTthIY8F5gBi7Mj3+X0iFVMTxeoKxzHqP435wP
|
||||
Fe3S7kCTNFH0J1Cb/eamwDwXRhz6p5h7iXd0MMAmFAmpZ/qZAoHBAPDSIvk2ocf1
|
||||
FVW8pKtKOJFIs8iQVIaOLKwPJVP8/JsB1+7mQx5KMoROb5pNpX2edN4vvG0CgqpJ
|
||||
KekleqpH6nQCqYGFZ1BDhORElNILxeJHcNl0eAG++IJ2PfIpTZV30edDqMm0x7EI
|
||||
8POZWAx809VzcYbE2jsgpN/EuiaG30EAI5yNvyzmZRCyQykH+eltHlCx17MWBxRQ
|
||||
bb2UUfpdInTMS2vyrvkeUACkC1DGYdBVVBqqPTkHZg+Kcbs8ntQqEQ==
|
||||
-----END RSA PRIVATE KEY-----
|
1
test/docker/ssh_host_rsa_key_3072-cert_1024.pub
Normal file
1
test/docker/ssh_host_rsa_key_3072-cert_1024.pub
Normal file
@ -0,0 +1 @@
|
||||
ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgGHz1JwF/1IcxW3pdQtpqbUjIHaFuk0cR/+l50vG+9hIAAAADAQABAAABgQDOEent4WetAAmo53tqKHJDIgMqDEIXsfnVDcW3f7xp/6Vfc6Uh7vsaLkY00z55EHg7Mb4IGyXE3kjekz/+xn6DLKUDVW5ZlmQ6WC1s4e60iQ7aV2Re2gaJ2VrRUDEtxRxQrpwKarAFNPfUenhCKanbPJ6D+XmrQOFYqC5jXeWublvdhliuPsJbcq3PF/xJtjPp27woXR0cJaKXOr4Ut4bNevti6XmeNUXmeOQa9n125DSqJVHOpmSuQsRaBCUIzRP4/JRu950vUx8Nk8caHtmFTSyc68lGzECvfW2WSer5bBq5lh0PMl/WDVRFwzrlTASw+V+A5bdmhmiBHW/nsib4p2wqGrYHeycS0mB1CHTonI7S6vi5RejWYy28EWGKm1S3A/iD2/8g3id54r7AFGibjqbZDVsxQE+d4E5ryvZJj/fKevNe5UhYU5C0XrRon4E2q+BRUIo6bPUrOgnBOoab4QVooznP5RBaMhtITcZ7hfmFe2Q67na/63INSTpuhksAAAAAAAAAAAAAAAIAAAAEdGVzdAAAAAgAAAAEdGVzdAAAAABdXry0AAAAAIFrQR8AAAAAAAAAAAAAAAAAAACXAAAAB3NzaC1yc2EAAAADAQABAAAAgQDnRlN3AFnUe2lFf5XG9UhXLr/9POruNTFbMt0zrjOUSjmAS7hS6pDv5VEToT6DaR1EQUYaqSMpHYzZhuCK52vrydOm5XFbJ7712r9MyZQUhoVZx8SudBHzVDIVO3jcMMWIlrfWBMnUaUHEqpmy88Y7gKDa2TWxJg1+hg51KqHrUQAAAI8AAAAHc3NoLXJzYQAAAIB4HaEexgQ9T6rScEbiHZx+suCaYXI7ywLYyoSEO48K8o+MmO83UTLtpPa3DXlT8hSYL8Aq6Bb5AMkDawsgsC484owPqObT/5ndLG/fctNBFcCTSL0ftte+A8xH0pZaGRoKbdxxgMqX4ubrCXpbMLGF9aAeh7MRa756XzqGlsCiSA== ssh_host_rsa_key_3072.pub
|
1
test/docker/ssh_host_rsa_key_3072-cert_3072.pub
Normal file
1
test/docker/ssh_host_rsa_key_3072-cert_3072.pub
Normal file
@ -0,0 +1 @@
|
||||
ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAg9MVX4OlkEy3p9eC+JJp8h7j76EmI46EY/RXxCGSWTC0AAAADAQABAAABgQDOEent4WetAAmo53tqKHJDIgMqDEIXsfnVDcW3f7xp/6Vfc6Uh7vsaLkY00z55EHg7Mb4IGyXE3kjekz/+xn6DLKUDVW5ZlmQ6WC1s4e60iQ7aV2Re2gaJ2VrRUDEtxRxQrpwKarAFNPfUenhCKanbPJ6D+XmrQOFYqC5jXeWublvdhliuPsJbcq3PF/xJtjPp27woXR0cJaKXOr4Ut4bNevti6XmeNUXmeOQa9n125DSqJVHOpmSuQsRaBCUIzRP4/JRu950vUx8Nk8caHtmFTSyc68lGzECvfW2WSer5bBq5lh0PMl/WDVRFwzrlTASw+V+A5bdmhmiBHW/nsib4p2wqGrYHeycS0mB1CHTonI7S6vi5RejWYy28EWGKm1S3A/iD2/8g3id54r7AFGibjqbZDVsxQE+d4E5ryvZJj/fKevNe5UhYU5C0XrRon4E2q+BRUIo6bPUrOgnBOoab4QVooznP5RBaMhtITcZ7hfmFe2Q67na/63INSTpuhksAAAAAAAAAAAAAAAIAAAAEdGVzdAAAAAgAAAAEdGVzdAAAAABdXr0sAAAAAIFrQWwAAAAAAAAAAAAAAAAAAAGXAAAAB3NzaC1yc2EAAAADAQABAAABgQCrFAQhuPzDROsFjV8M7zVy6uKNCt0s5SvxWXxcQJZzlAZ3UuQAbzQ2B1wIE++NbFlKZisp6oDvwZR034qDJwTTO2nFhJcodkxogzld73gEH4Ghwf3W93/aIHMZ553WdX/N8B2rYAQdCPVOkgj5r7PbnLG/Y+7BVNPDCj0j/omA2rd68fgdvCCvdJF8QRhlD5gvxw6kG42DVhk5HSTXKTbdmoB33YnJvFniIK063utyPawUfM27VTnjjBYHAgvnJlkpOAGFjh2p9PYSnsjNHkd2x2u9BX2oL3YYzXMMT5TcDCtUqMezRhmrePNyr/K8UMJwwxHPj/SkYUVTbqhaZr6fe9sDEomgv6uEbxAz36XaoWUsayczSRRcAlew8pvKClo/xndTh4qBO4nYa5L14sgWcHuavAPvlXoaA32rmZjz0N+RVKQdqiqljyk91GTP1ACYwS4u0ea/b0JU6l9fm/+uybvABIBmq1SWYW7isUYEvC9ltSVa7TYeaAFPjuDoQh8AAAGPAAAAB3NzaC1yc2EAAAGAG8tCiBMSq3Of3Gmcrid2IfPmaaemYivgEEuK8ubq1rznF0vtR07/NUQ7WVzfJhUSeG0gtJ3A1ey60NjcBn0DHao4Q3ATIXnkSOIKjNolZ2urqYv9fT1LAC4I5XWGzK2aKK0NEqAYr06YPtcGOBQk5+3GPAWSJ4eQycKRz5BSuMYbKaVxU0kGSvbavG07ZntMQhia/lILyq84PjXh/JlRVpIqY+LAS0qwqkUR3gWMTmvYvYI7fXU84ReVB1ut75bY7Xx0DXHPl1Zc2MNDLGcKsByZtoO9ueZRyOlZMUJcVP5fK+OUuZKjMbCaaJnV55BQ78/rftIPYsTEEO2Sf9WT86ADa3k4S0pyWqlTxBzZcDWNt+fZFNm9wcqcYS32nDKtfixcDN8E/IJIWY7aoabPqoYnKUVQBOcIEnZf1HqsKUVmF44Dp9mKhefUs3BtcdK63j/lNXzzMrPwZQAreJqH/uV3TgYBLjMPl++ctX6tCe6Hv5zFKNhnOCSBSzcsCgIU ssh_host_rsa_key_3072.pub
|
1
test/docker/ssh_host_rsa_key_3072.pub
Normal file
1
test/docker/ssh_host_rsa_key_3072.pub
Normal file
@ -0,0 +1 @@
|
||||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDOEent4WetAAmo53tqKHJDIgMqDEIXsfnVDcW3f7xp/6Vfc6Uh7vsaLkY00z55EHg7Mb4IGyXE3kjekz/+xn6DLKUDVW5ZlmQ6WC1s4e60iQ7aV2Re2gaJ2VrRUDEtxRxQrpwKarAFNPfUenhCKanbPJ6D+XmrQOFYqC5jXeWublvdhliuPsJbcq3PF/xJtjPp27woXR0cJaKXOr4Ut4bNevti6XmeNUXmeOQa9n125DSqJVHOpmSuQsRaBCUIzRP4/JRu950vUx8Nk8caHtmFTSyc68lGzECvfW2WSer5bBq5lh0PMl/WDVRFwzrlTASw+V+A5bdmhmiBHW/nsib4p2wqGrYHeycS0mB1CHTonI7S6vi5RejWYy28EWGKm1S3A/iD2/8g3id54r7AFGibjqbZDVsxQE+d4E5ryvZJj/fKevNe5UhYU5C0XrRon4E2q+BRUIo6bPUrOgnBOoab4QVooznP5RBaMhtITcZ7hfmFe2Q67na/63INSTpuhks=
|
@ -1,8 +0,0 @@
|
||||
#!/bin/sh
|
||||
_cdir=$(cd -- "$(dirname "$0")" && pwd)
|
||||
type prospector > /dev/null 2>&1
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "err: prospector (Python Static Analysis) not found."
|
||||
exit 1
|
||||
fi
|
||||
prospector --profile-path "${_cdir}" -P prospector "${_cdir}/../ssh-audit.py"
|
@ -1,9 +0,0 @@
|
||||
inherits:
|
||||
- strictness_veryhigh
|
||||
|
||||
pep8:
|
||||
disable:
|
||||
- W191
|
||||
- W293
|
||||
- E501
|
||||
- E221
|
6
test/stubs/colorama.pyi
Normal file
6
test/stubs/colorama.pyi
Normal file
@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
from typing import Optional
|
||||
|
||||
def init(autoreset: bool = False, convert: Optional[bool] = None, strip: Optional[bool] = None, wrap: bool = True) -> None: ...
|
||||
|
200
test/test_auditconf.py
Normal file
200
test/test_auditconf.py
Normal file
@ -0,0 +1,200 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
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
|
||||
|
||||
@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_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_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_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')
|
69
test/test_banner.py
Normal file
69
test/test_banner.py
Normal file
@ -0,0 +1,69 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
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
|
||||
|
||||
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_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_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'
|
133
test/test_buffer.py
Normal file
133
test/test_buffer.py
Normal file
@ -0,0 +1,133 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
import re
|
||||
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'
|
||||
|
||||
@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_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_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_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_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_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_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
|
162
test/test_errors.py
Normal file
162
test/test_errors.py
Normal file
@ -0,0 +1,162 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
import socket
|
||||
import errno
|
||||
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
|
||||
|
||||
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 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_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):
|
||||
vsocket = 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_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_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_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_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_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]
|
175
test/test_output.py
Normal file
175
test/test_output.py
Normal file
@ -0,0 +1,175 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import print_function
|
||||
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
|
||||
|
||||
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_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_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_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(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
|
@ -1,42 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
import pytest
|
||||
import re
|
||||
|
||||
|
||||
class TestProtocol(object):
|
||||
@pytest.fixture(autouse=True)
|
||||
def init(self, ssh_audit):
|
||||
self.rbuf = ssh_audit.ReadBuf
|
||||
self.wbuf = ssh_audit.WriteBuf
|
||||
|
||||
def _b(self, 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_mpint1(self):
|
||||
mpint1w = lambda x: self.wbuf().write_mpint1(x).write_flush()
|
||||
mpint1r = lambda x: self.rbuf(x).read_mpint1()
|
||||
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()
|
||||
mpint2r = lambda x: self.rbuf(x).read_mpint2()
|
||||
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
|
85
test/test_resolve.py
Normal file
85
test/test_resolve.py
Normal file
@ -0,0 +1,85 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
import socket
|
||||
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
|
||||
|
||||
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):
|
||||
r = 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_ipv4(self, virtual_socket):
|
||||
vsocket = 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):
|
||||
vsocket = 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):
|
||||
vsocket = 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):
|
||||
vsocket = 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))
|
41
test/test_socket.py
Normal file
41
test/test_socket.py
Normal file
@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
import socket
|
||||
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
|
||||
|
||||
def test_invalid_host(self, virtual_socket):
|
||||
with pytest.raises(ValueError):
|
||||
s = self.ssh.Socket(None, 22)
|
||||
|
||||
def test_invalid_port(self, virtual_socket):
|
||||
with pytest.raises(ValueError):
|
||||
s = self.ssh.Socket('localhost', 'abc')
|
||||
with pytest.raises(ValueError):
|
||||
s = self.ssh.Socket('localhost', -1)
|
||||
with pytest.raises(ValueError):
|
||||
s = self.ssh.Socket('localhost', 0)
|
||||
with pytest.raises(ValueError):
|
||||
s = 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'
|
287
test/test_software.py
Normal file
287
test/test_software.py
Normal file
@ -0,0 +1,287 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
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
|
||||
|
||||
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_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_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_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))>'
|
156
test/test_ssh1.py
Normal file
156
test/test_ssh1.py
Normal file
@ -0,0 +1,156 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
import struct
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
@classmethod
|
||||
def _server_key(cls):
|
||||
return (1024, 0x10001, 0xee6552da432e0ac2c422df1a51287507748bfe3b5e3e4fa989a8f49fdc163a17754939ef18ef8a667ea3b71036a151fcd7f5e01ceef1e4439864baf3ac569047582c69d6c128212e0980dcb3168f00d371004039983f6033cd785b8b8f85096c7d9405cbfdc664e27c966356a6b4eb6ee20ad43414b50de18b22829c1880b551)
|
||||
|
||||
@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 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 _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 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_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_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]
|
155
test/test_ssh2.py
Normal file
155
test/test_ssh2.py
Normal file
@ -0,0 +1,155 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
import struct, os
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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 _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 test_key_payload(self):
|
||||
kex1 = self._get_kex_variat1()
|
||||
kex2 = self.ssh2.Kex.parse(self._kex_payload())
|
||||
assert kex1.payload == kex2.payload
|
||||
|
||||
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]
|
164
test/test_ssh_algorithm.py
Normal file
164
test/test_ssh_algorithm.py
Normal file
@ -0,0 +1,164 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
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
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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], 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']})
|
||||
|
||||
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'
|
||||
|
||||
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)
|
218
test/test_utils.py
Normal file
218
test/test_utils.py
Normal file
@ -0,0 +1,218 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
import sys
|
||||
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,)
|
||||
|
||||
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_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_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_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_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_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_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_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_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]
|
@ -2,6 +2,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import pytest
|
||||
|
||||
|
||||
# pylint: disable=attribute-defined-outside-init
|
||||
class TestVersionCompare(object):
|
||||
@pytest.fixture(autouse=True)
|
||||
def init(self, ssh_audit):
|
||||
@ -15,34 +17,69 @@ class TestVersionCompare(object):
|
||||
b = self.ssh.Banner.parse('SSH-2.0-OpenSSH_{0}'.format(v))
|
||||
return self.ssh.Software.parse(b)
|
||||
|
||||
def get_libssh_software(self, v):
|
||||
b = self.ssh.Banner.parse('SSH-2.0-libssh-{0}'.format(v))
|
||||
return self.ssh.Software.parse(b)
|
||||
|
||||
def test_dropbear_compare_version_pre_years(self):
|
||||
s = self.get_dropbear_software('0.44')
|
||||
assert s.compare_version(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') == True
|
||||
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('2014.67') > 0
|
||||
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.67', '2016.74') == True
|
||||
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') == True
|
||||
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_sequential(self):
|
||||
versions = []
|
||||
@ -82,20 +119,28 @@ class TestVersionCompare(object):
|
||||
|
||||
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') == True
|
||||
|
||||
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_openbsd_compare_version_sequential(self):
|
||||
versions = []
|
||||
@ -130,3 +175,41 @@ class TestVersionCompare(object):
|
||||
if i + 1 < l:
|
||||
vnext = versions[i + 1]
|
||||
assert s.compare_version(vnext) < 0
|
||||
|
||||
def test_libssh_compare_version_simple(self):
|
||||
s = self.get_libssh_software('0.3')
|
||||
assert s.compare_version(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))
|
||||
l = len(versions)
|
||||
for i in range(l):
|
||||
v = versions[i]
|
||||
s = self.get_libssh_software(v)
|
||||
assert s.compare_version(v) == 0
|
||||
if i - 1 >= 0:
|
||||
vbefore = versions[i - 1]
|
||||
assert s.compare_version(vbefore) > 0
|
||||
if i + 1 < l:
|
||||
vnext = versions[i + 1]
|
||||
assert s.compare_version(vnext) < 0
|
||||
|
412
test/tools/ci-linux.sh
Executable file
412
test/tools/ci-linux.sh
Executable file
@ -0,0 +1,412 @@
|
||||
#!/bin/sh
|
||||
|
||||
CI_VERBOSE=1
|
||||
|
||||
ci_err_msg() { echo "[ci] error: $1" >&2; }
|
||||
ci_err() { [ $1 -ne 0 ] && ci_err_msg "$2" && exit 1; }
|
||||
ci_is_osx() { [ X"$(uname -s)" == X"Darwin" ]; }
|
||||
|
||||
ci_get_pypy_ver() {
|
||||
local _v="$1"
|
||||
[ -z "$_v" ] && _v=$(python -V 2>&1)
|
||||
case "$_v" in
|
||||
pypy-*|pypy2-*|pypy3-*|pypy3.*) echo "$_v"; return 0 ;;
|
||||
pypy|pypy2|pypy3) echo "$_v-unknown"; return 0 ;;
|
||||
esac
|
||||
echo "$_v" | tail -1 | grep -qi pypy
|
||||
if [ $? -eq 0 ]; then
|
||||
local _py_ver=$(echo "$_v" | head -1 | cut -d ' ' -sf 2)
|
||||
local _pypy_ver=$(echo "$_v" | tail -1 | cut -d ' ' -sf 2)
|
||||
[ -z "${_py_ver} " ] && _py_ver=2
|
||||
[ -z "${_pypy_ver}" ] && _pypy_ver="unknown"
|
||||
case "${_py_ver}" in
|
||||
2*) echo "pypy-${_pypy_ver}" ;;
|
||||
3.3*) echo "pypy3.3-${_pypy_ver}" ;;
|
||||
3.5*) echo "pypy3.5-${_pypy_ver}" ;;
|
||||
*) echo "pypy3-${_pypy_ver}" ;;
|
||||
esac
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
ci_get_py_ver() {
|
||||
local _v
|
||||
case "$1" in
|
||||
py26) _v=2.6.9 ;;
|
||||
py27) _v=2.7.13 ;;
|
||||
py33) _v=3.3.6 ;;
|
||||
py34) _v=3.4.6 ;;
|
||||
py35) _v=3.5.3 ;;
|
||||
py36) _v=3.6.1 ;;
|
||||
py37) _v=3.7-dev ;;
|
||||
pypy) ci_is_osx && _v=pypy2-5.7.0 || _v=pypy-portable-5.7.0 ;;
|
||||
pypy3) ci_is_osx && _v=pypy3.3-5.5-alpha || _v=pypy3-portable-5.7.0 ;;
|
||||
*)
|
||||
[ -z "$1" ] && set -- "$(python -V 2>&1)"
|
||||
_v=$(ci_get_pypy_ver "$1")
|
||||
[ -z "$_v" ] && _v=$(echo "$_v" | head -1 | cut -d ' ' -sf 2)
|
||||
;;
|
||||
esac
|
||||
echo "${_v}"
|
||||
return 0
|
||||
}
|
||||
|
||||
ci_get_py_env() {
|
||||
[ -z "$1" ] && set -- "$(python -V 2>&1)"
|
||||
case "$(ci_get_pypy_ver "$1")" in
|
||||
pypy|pypy2|pypy-*|pypy2-*) echo "pypy" ;;
|
||||
pypy3|pypy3*) echo "pypy3" ;;
|
||||
*)
|
||||
local _v=$(echo "$1" | head -1 | sed -e 's/[^0-9]//g' | cut -c1-2)
|
||||
echo "py${_v}"
|
||||
esac
|
||||
return 0
|
||||
}
|
||||
|
||||
ci_pyenv_setup() {
|
||||
[ ${CI_VERBOSE} -gt 0 ] && echo "[ci] install pyenv"
|
||||
rm -rf ~/.pyenv
|
||||
git clone --depth 1 https://github.com/yyuu/pyenv.git ~/.pyenv
|
||||
PYENV_ROOT=$HOME/.pyenv
|
||||
PATH="$HOME/.pyenv/bin:$PATH"
|
||||
eval "$(pyenv init -)"
|
||||
ci_err $? "failed to init pyenv"
|
||||
[ ${CI_VERBOSE} -gt 0 ] && echo "[ci] pyenv init: $(pyenv -v 2>&1)"
|
||||
return 0
|
||||
}
|
||||
|
||||
ci_pyenv_install() {
|
||||
CI_PYENV_CACHE=~/.pyenv.cache
|
||||
type pyenv > /dev/null 2>&1
|
||||
ci_err $? "pyenv not found"
|
||||
local _py_ver=$(ci_get_py_ver "$1")
|
||||
local _py_env=$(ci_get_py_env "${_py_ver}")
|
||||
local _nocache
|
||||
case "${_py_env}" in
|
||||
py37) _nocache=1 ;;
|
||||
esac
|
||||
[ ${CI_VERBOSE} -gt 0 ] && echo "[ci] pyenv install: ${_py_env}/${_py_ver}"
|
||||
[ -z "${PYENV_ROOT}" ] && PYENV_ROOT="$HOME/.pyenv"
|
||||
local _py_ver_dir="${PYENV_ROOT}/versions/${_py_ver}"
|
||||
local _py_ver_cached_dir="${CI_PYENV_CACHE}/${_py_ver}"
|
||||
if [ -z "${_nocache}" ]; then
|
||||
if [ ! -d "${_py_ver_dir}" ]; then
|
||||
if [ -d "${_py_ver_cached_dir}" ]; then
|
||||
[ ${CI_VERBOSE} -gt 0 ] && echo "[ci] pyenv reuse ${_py_ver}"
|
||||
ln -s "${_py_ver_cached_dir}" "${_py_ver_dir}"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if [ ! -d "${_py_ver_dir}" ]; then
|
||||
pyenv install -s "${_py_ver}"
|
||||
ci_err $? "pyenv failed to install ${_py_ver}"
|
||||
if [ -z "${_nocache}" ]; then
|
||||
[ ${CI_VERBOSE} -gt 0 ] && echo "[ci] pyenv cache ${_py_ver}"
|
||||
rm -rf -- "${_py_ver_cached_dir}"
|
||||
mkdir -p -- "${CI_PYENV_CACHE}"
|
||||
mv "${_py_ver_dir}" "${_py_ver_cached_dir}"
|
||||
ln -s "${_py_ver_cached_dir}" "${_py_ver_dir}"
|
||||
fi
|
||||
fi
|
||||
pyenv rehash
|
||||
return 0
|
||||
}
|
||||
|
||||
ci_pyenv_use() {
|
||||
type pyenv > /dev/null 2>&1
|
||||
ci_err $? "pyenv not found"
|
||||
local _py_ver=$(ci_get_py_ver "$1")
|
||||
pyenv shell "${_py_ver}"
|
||||
ci_err $? "pyenv could not use ${_py_ver}"
|
||||
[ ${CI_VERBOSE} -gt 0 ] && echo "[ci] pyenv using python: $(python -V 2>&1)"
|
||||
return 0
|
||||
}
|
||||
|
||||
ci_pip_setup() {
|
||||
local _py_ver=$(ci_get_py_ver "$1")
|
||||
local _py_env=$(ci_get_py_env "${_py_ver}")
|
||||
[ ${CI_VERBOSE} -gt 0 ] && echo "[ci] install pip/venv for ${_py_env}/${_py_ver}"
|
||||
PIPOPT=$(python -c 'import sys; print("" if hasattr(sys, "real_prefix") else "--user")')
|
||||
if [ -z "${_py_env##py2*}" ]; then
|
||||
curl -O https://bootstrap.pypa.io/get-pip.py
|
||||
python get-pip.py ${PIPOPT}
|
||||
ci_err $? "failed to install pip"
|
||||
fi
|
||||
if [ X"${_py_env}" == X"py26" ]; then
|
||||
python -c 'import pip; pip.main();' install ${PIPOPT} -U pip virtualenv
|
||||
else
|
||||
python -m pip install ${PIPOPT} -U pip virtualenv
|
||||
fi
|
||||
ci_err $? "failed to upgrade pip/venv" || return 0
|
||||
}
|
||||
|
||||
ci_venv_setup() {
|
||||
local _py_ver=$(ci_get_py_ver "$1")
|
||||
local _py_env=$(ci_get_py_env "${_py_ver}")
|
||||
[ ${CI_VERBOSE} -gt 0 ] && echo "[ci] create venv for ${_py_env}/${_py_ver}"
|
||||
local VENV_DIR=~/.venv/${_py_ver}
|
||||
mkdir -p -- ~/.venv
|
||||
rm -rf -- "${VENV_DIR}"
|
||||
if [ X"${_py_env}" == X"py26" ]; then
|
||||
python -c 'import virtualenv; virtualenv.main();' "${VENV_DIR}"
|
||||
else
|
||||
python -m virtualenv "${VENV_DIR}"
|
||||
fi
|
||||
ci_err $? "failed to create venv" || return 0
|
||||
}
|
||||
|
||||
ci_venv_use() {
|
||||
local _py_ver=$(ci_get_py_ver "$1")
|
||||
local _py_env=$(ci_get_py_env "${_py_ver}")
|
||||
local VENV_DIR=~/.venv/${_py_ver}
|
||||
. "${VENV_DIR}/bin/activate"
|
||||
ci_err $? "could not actiavte virtualenv"
|
||||
[ ${CI_VERBOSE} -gt 0 ] && echo "[ci] venv using python: $(python -V 2>&1)"
|
||||
return 0
|
||||
}
|
||||
|
||||
ci_get_filedir() {
|
||||
local _sdir=$(cd -- "$(dirname "$0")" && pwd)
|
||||
local _pdir=$(pwd)
|
||||
if [ -z "${_pdir##${_sdir}*}" ]; then
|
||||
_sdir="${_pdir}"
|
||||
fi
|
||||
local _first=1
|
||||
while [ X"${_sdir}" != X"/" ]; do
|
||||
if [ ${_first} -eq 1 ]; then
|
||||
_first=0
|
||||
local _f=$(find "${_sdir}" -name "$1" | head -1)
|
||||
if [ -n "${_f}" ]; then
|
||||
echo $(dirname -- "${_f}")
|
||||
return 0
|
||||
fi
|
||||
else
|
||||
_f=$(find "${_sdir}" -mindepth 1 -maxdepth 1 -name "$1" | head -1)
|
||||
fi
|
||||
[ -n "${_f}" ] && echo "${_sdir}" && return 0
|
||||
_sdir=$(cd -- "${_sdir}/.." && pwd)
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
ci_sq_ensure_java() {
|
||||
type java >/dev/null 2>&1
|
||||
if [ $? -ne 0 ]; then
|
||||
ci_err_msg "java not found"
|
||||
return 1
|
||||
fi
|
||||
local _java_ver=$(java -version 2>&1 | head -1 | sed -e 's/[^0-9\._]//g')
|
||||
if [ -z "${_java_ver##1.8*}" ]; then
|
||||
return 0
|
||||
fi
|
||||
ci_err_msg "unsupported java version: ${_java_ver}"
|
||||
return 1
|
||||
}
|
||||
|
||||
ci_sq_ensure_scanner() {
|
||||
local _cli_version="3.0.0.702"
|
||||
local _cli_basedir="$HOME/.bin"
|
||||
local _cli_postfix=""
|
||||
case "$(uname -s)" in
|
||||
Linux)
|
||||
[ X"$(uname -m)" = X"x86_64" ] && _cli_postfix="-linux"
|
||||
[ X"$(uname -m)" = X"amd64" ] && _cli_postfix="-linux"
|
||||
;;
|
||||
Darwin) _cli_postfix="-macosx" ;;
|
||||
esac
|
||||
if [ X"${_cli_postfix}" = X"" ]; then
|
||||
ci_sq_ensure_java || return 1
|
||||
fi
|
||||
if [ X"${SONAR_SCANNER_PATH}" != X"" ]; then
|
||||
if [ -e "${SONAR_SCANNER_PATH}" ]; then
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
local _cli_fname="sonar-scanner-cli-${_cli_version}${_cli_postfix}"
|
||||
[ ${CI_VERBOSE} -gt 0 ] && echo "[ci] ensure scanner ${_cli_fname}"
|
||||
local _cli_dname="sonar-scanner-${_cli_version}${_cli_postfix}"
|
||||
local _cli_archive="${_cli_basedir}/${_cli_fname}.zip"
|
||||
local _cli_dir="${_cli_basedir}/${_cli_dname}"
|
||||
local _cli_url="https://sonarsource.bintray.com/Distribution/sonar-scanner-cli/${_cli_fname}.zip"
|
||||
if [ ! -e "${_cli_archive}" ]; then
|
||||
mkdir -p -- "${_cli_basedir}" > /dev/null 2>&1
|
||||
if [ $? -ne 0 ]; then
|
||||
ci_err_msg "could not create ${_cli_basedir}"
|
||||
return 1
|
||||
fi
|
||||
[ ${CI_VERBOSE} -gt 0 ] && echo "[ci] downloading ${_cli_fname}"
|
||||
curl -kL -o "${_cli_archive}" "${_cli_url}"
|
||||
[ $? -ne 0 ] && ci_err_msg "download failed" && return 1
|
||||
[ ! -e "${_cli_archive}" ] && ci_err_msg "download verify" && return 1
|
||||
fi
|
||||
if [ ! -d "${_cli_dir}" ]; then
|
||||
[ ${CI_VERBOSE} -gt 0 ] && echo "[ci] extracting ${_cli_fname}"
|
||||
unzip -od "${_cli_basedir}" "${_cli_archive}"
|
||||
[ $? -ne 0 ] && ci_err_msg "extract failed" && return 1
|
||||
[ ! -d "${_cli_dir}" ] && ci_err_msg "extract verify" && return 1
|
||||
fi
|
||||
if [ ! -e "${_cli_dir}/bin/sonar-scanner" ]; then
|
||||
ci_err_msg "sonar-scanner binary not found."
|
||||
return 1
|
||||
fi
|
||||
SONAR_SCANNER_PATH="${_cli_dir}/bin/sonar-scanner"
|
||||
return 0
|
||||
}
|
||||
|
||||
ci_sq_run() {
|
||||
if [ X"${SONAR_SCANNER_PATH}" = X"" ]; then
|
||||
ci_err_msg "environment variable SONAR_SCANNER_PATH not set"
|
||||
return 1
|
||||
fi
|
||||
if [ X"${SONAR_HOST_URL}" = X"" ]; then
|
||||
ci_err_msg "environment variable SONAR_HOST_URL not set"
|
||||
return 1
|
||||
fi
|
||||
if [ X"${SONAR_AUTH_TOKEN}" = X"" ]; then
|
||||
ci_err_msg "environment variable SONAR_AUTH_TOKEN not set"
|
||||
return 1
|
||||
fi
|
||||
local _pdir=$(ci_get_filedir "ssh-audit.py")
|
||||
if [ -z "${_pdir}" ]; then
|
||||
ci_err_msg "failed to find project directory"
|
||||
return 1
|
||||
fi
|
||||
local _odir=$(pwd)
|
||||
cd -- "${_pdir}"
|
||||
local _branch=$(git name-rev --name-only HEAD | cut -d '~' -f 1)
|
||||
case "${_branch}" in
|
||||
master) ;;
|
||||
develop) ;;
|
||||
*) ci_err_msg "unknown branch: ${_branch}"; return 1 ;;
|
||||
esac
|
||||
local _junit=$(cd -- "${_pdir}" && ls -1 reports/junit.*.xml | sort -r | head -1)
|
||||
if [ X"${_junit}" = X"" ]; then
|
||||
ci_err_msg "no junit.xml found"
|
||||
return 1
|
||||
fi
|
||||
local _project_ver=$(grep VERSION ssh-audit.py | head -1 | cut -d "'" -f 2)
|
||||
if [ -z "${_project_ver}" ]; then
|
||||
ci_err_msg "failed to get project version"
|
||||
return 1
|
||||
fi
|
||||
if [ -z "${_project_ver##*dev}" ]; then
|
||||
local _git_commit=$(git rev-parse --short=8 HEAD)
|
||||
_project_ver="${_project_ver}.${_git_commit}"
|
||||
fi
|
||||
[ ${CI_VERBOSE} -gt 0 ] && echo "[ci] run sonar-scanner for ${_project_ver}"
|
||||
"${SONAR_SCANNER_PATH}" -X \
|
||||
-Dsonar.projectKey=arthepsy-github:ssh-audit \
|
||||
-Dsonar.sources=ssh-audit.py \
|
||||
-Dsonar.tests=test \
|
||||
-Dsonar.test.inclusions=test/*.py \
|
||||
-Dsonar.host.url="${SONAR_HOST_URL}" \
|
||||
-Dsonar.projectName=ssh-audit \
|
||||
-Dsonar.projectVersion="${_project_ver}" \
|
||||
-Dsonar.branch="${_branch}" \
|
||||
-Dsonar.python.coverage.overallReportPath=reports/coverage.xml \
|
||||
-Dsonar.python.xunit.reportPath="${_junit}" \
|
||||
-Dsonar.organization=arthepsy-github \
|
||||
-Dsonar.login="${SONAR_AUTH_TOKEN}"
|
||||
cd -- "${_odir}"
|
||||
return 0
|
||||
}
|
||||
|
||||
ci_run_wrapped() {
|
||||
local _versions=$(echo "${PY_VER}" | sed -e 's/,/ /g')
|
||||
[ -z "${_versions}" ] && eval "$1"
|
||||
for _i in ${_versions}; do
|
||||
local _v=$(echo "$_i" | cut -d '/' -f 1)
|
||||
local _o=$(echo "$_i" | cut -d '/' -sf 2)
|
||||
[ -z "${_o}" ] && _o="${PY_ORIGIN}"
|
||||
eval "$1" "${_v}" "${_o}" || return 1
|
||||
done
|
||||
return 0
|
||||
}
|
||||
|
||||
ci_step_before_install_wrapped() {
|
||||
local _py_ver="$1"
|
||||
local _py_ori="$2"
|
||||
case "${_py_ori}" in
|
||||
pyenv)
|
||||
if [ "${CI_PYENV_SETUP}" -eq 0 ]; then
|
||||
ci_pyenv_setup
|
||||
CI_PYENV_SETUP=1
|
||||
fi
|
||||
ci_pyenv_install "${_py_ver}" || return 1
|
||||
ci_pyenv_use "${_py_ver}" || return 1
|
||||
;;
|
||||
esac
|
||||
ci_pip_setup "${_py_ver}" || return 1
|
||||
ci_venv_setup "${_py_ver}" || return 1
|
||||
return 0
|
||||
}
|
||||
|
||||
ci_step_before_install() {
|
||||
if ci_is_osx; then
|
||||
[ ${CI_VERBOSE} -gt 0 ] && sw_vers
|
||||
brew update || brew update
|
||||
brew install autoconf pkg-config openssl readline xz
|
||||
brew upgrade autoconf pkg-config openssl readline xz
|
||||
PY_ORIGIN=pyenv
|
||||
fi
|
||||
CI_PYENV_SETUP=0
|
||||
ci_run_wrapped "ci_step_before_install_wrapped" || return 1
|
||||
if [ "${CI_PYENV_SETUP}" -eq 1 ]; then
|
||||
pyenv shell --unset
|
||||
[ ${CI_VERBOSE} -gt 0 ] && pyenv versions
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
ci_step_install_wrapped() {
|
||||
local _py_ver="$1"
|
||||
ci_venv_use "${_py_ver}"
|
||||
pip install -U tox coveralls codecov
|
||||
ci_err $? "failed to install dependencies" || return 0
|
||||
}
|
||||
|
||||
ci_step_script_wrapped() {
|
||||
local _py_ver="$1"
|
||||
local _py_ori="$2"
|
||||
local _py_env=$(ci_get_py_env "${_py_ver}")
|
||||
ci_venv_use "${_py_ver}" || return 1
|
||||
if [ -z "${_py_env##*py3*}" ]; then
|
||||
if [ -z "${_py_env##*pypy3*}" ]; then
|
||||
# NOTE: workaround for travis environment
|
||||
_pydir=$(dirname $(which python))
|
||||
ln -s -- "${_pydir}/python" "${_pydir}/pypy3"
|
||||
# NOTE: do not lint, as it hangs when flake8 is run
|
||||
# NOTE: do not type, as it can't install dependencies
|
||||
TOXENV=${_py_env}-test
|
||||
else
|
||||
TOXENV=${_py_env}-test,${_py_env}-type,${_py_env}-lint
|
||||
fi
|
||||
else
|
||||
# NOTE: do not type, as it isn't supported on py2x
|
||||
TOXENV=${_py_env}-test,${_py_env}-lint
|
||||
fi
|
||||
tox -e $TOXENV,cov
|
||||
ci_err $? "tox failed" || return 0
|
||||
}
|
||||
|
||||
ci_step_success_wrapped() {
|
||||
local _py_ver="$1"
|
||||
local _py_ori="$2"
|
||||
if [ X"${SQ}" = X"1" ]; then
|
||||
ci_sq_ensure_scanner && ci_sq_run
|
||||
fi
|
||||
ci_venv_use "${_py_ver}" || return 1
|
||||
coveralls
|
||||
codecov
|
||||
}
|
||||
|
||||
ci_step_failure() {
|
||||
cat .tox/log/*
|
||||
cat .tox/*/log/*
|
||||
}
|
||||
|
||||
ci_step_install() { ci_run_wrapped "ci_step_install_wrapped"; }
|
||||
ci_step_script() { ci_run_wrapped "ci_step_script_wrapped"; }
|
||||
ci_step_success() { ci_run_wrapped "ci_step_success_wrapped"; }
|
131
test/tools/ci-win.cmd
Normal file
131
test/tools/ci-win.cmd
Normal file
@ -0,0 +1,131 @@
|
||||
@ECHO OFF
|
||||
|
||||
IF "%PYTHON%" == "" (
|
||||
ECHO PYTHON environment variable not set
|
||||
EXIT 1
|
||||
)
|
||||
SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%"
|
||||
FOR /F %%i IN ('python -c "import platform; print(platform.python_version());"') DO (
|
||||
SET PYTHON_VERSION=%%i
|
||||
)
|
||||
SET PYTHON_VERSION_MAJOR=%PYTHON_VERSION:~0,1%
|
||||
IF "%PYTHON_VERSION:~3,1%" == "." (
|
||||
SET PYTHON_VERSION_MINOR=%PYTHON_VERSION:~2,1%
|
||||
) ELSE (
|
||||
SET PYTHON_VERSION_MINOR=%PYTHON_VERSION:~2,2%
|
||||
)
|
||||
FOR /F %%i IN ('python -c "import struct; print(struct.calcsize(\"P\")*8)"') DO (
|
||||
SET PYTHON_ARCH=%%i
|
||||
)
|
||||
CALL :devenv
|
||||
|
||||
IF /I "%1"=="" (
|
||||
SET target=test
|
||||
) ELSE (
|
||||
SET target=%1
|
||||
)
|
||||
|
||||
echo [CI] TARGET=%target%
|
||||
GOTO %target%
|
||||
|
||||
:devenv
|
||||
SET WIN_SDK_ROOT=C:\Program Files\Microsoft SDKs\Windows
|
||||
SET VS2015_ROOT=C:\Program Files (x86)\Microsoft Visual Studio 14.0
|
||||
IF %PYTHON_VERSION_MAJOR% == 2 (
|
||||
SET WINDOWS_SDK_VERSION="v7.0"
|
||||
) ELSE IF %PYTHON_VERSION_MAJOR% == 3 (
|
||||
IF %PYTHON_VERSION_MAJOR% LEQ 4 (
|
||||
SET WINDOWS_SDK_VERSION="v7.1"
|
||||
) ELSE (
|
||||
SET WINDOWS_SDK_VERSION="2015"
|
||||
)
|
||||
) ELSE (
|
||||
ECHO Unsupported Python version: "%PYTHON_VERSION%"
|
||||
EXIT 1
|
||||
)
|
||||
SETLOCAL ENABLEDELAYEDEXPANSION
|
||||
IF %PYTHON_ARCH% == 32 (SET PYTHON_ARCHX=x86) ELSE (SET PYTHON_ARCHX=x64)
|
||||
IF %WINDOWS_SDK_VERSION% == "2015" (
|
||||
"%VS2015_ROOT%\VC\vcvarsall.bat" %PYTHON_ARCHX%
|
||||
) ELSE (
|
||||
SET DISTUTILS_USE_SDK=1
|
||||
SET MSSdk=1
|
||||
"%WIN_SDK_ROOT%\%WINDOWS_SDK_VERSION%\Setup\WindowsSdkVer.exe" -q -version:%WINDOWS_SDK_VERSION%
|
||||
"%WIN_SDK_ROOT%\%WINDOWS_SDK_VERSION%\Bin\SetEnv.cmd" /%PYTHON_ARCHX% /release
|
||||
)
|
||||
GOTO :eof
|
||||
|
||||
:install
|
||||
pip install --user --upgrade pip virtualenv
|
||||
SET VENV_DIR=.venv\%PYTHON_VERSION%
|
||||
rmdir /s /q %VENV_DIR% > nul 2>nul
|
||||
mkdir .venv > nul 2>nul
|
||||
IF "%PYTHON_VERSION_MAJOR%%PYTHON_VERSION_MINOR%" == "26" (
|
||||
python -c "import virtualenv; virtualenv.main();" %VENV_DIR%
|
||||
) ELSE (
|
||||
python -m virtualenv %VENV_DIR%
|
||||
)
|
||||
CALL %VENV_DIR%\Scripts\activate
|
||||
python -V
|
||||
pip install tox
|
||||
deactivate
|
||||
GOTO :eof
|
||||
|
||||
:install_deps
|
||||
SET LXML_FILE=
|
||||
SET LXML_URL=
|
||||
IF %PYTHON_VERSION_MAJOR% == 3 (
|
||||
IF %PYTHON_VERSION_MINOR% == 3 (
|
||||
IF %PYTHON_ARCH% == 32 (
|
||||
SET LXML_FILE=lxml-3.7.3.win32-py3.3.exe
|
||||
SET LXML_URL=https://pypi.python.org/packages/66/fd/b82a54e7a15e91184efeef4b659379d0581a73cf78239d70feb0f0877841/lxml-3.7.3.win32-py3.3.exe
|
||||
) ELSE (
|
||||
SET LXML_FILE=lxml-3.7.3.win-amd64-py3.3.exe
|
||||
SET LXML_URL=https://pypi.python.org/packages/dc/bc/4742b84793fa1fd991b5d2c6f2e5d32695659d6cfedf5c66aef9274a8723/lxml-3.7.3.win-amd64-py3.3.exe
|
||||
)
|
||||
) ELSE IF %PYTHON_VERSION_MINOR% == 4 (
|
||||
IF %PYTHON_ARCH% == 32 (
|
||||
SET LXML_FILE=lxml-3.7.3.win32-py3.4.exe
|
||||
SET LXML_URL=https://pypi.python.org/packages/88/33/265459d68d465ddc707621e6471989f5c2cb0d43f230f516800ffd629af7/lxml-3.7.3.win32-py3.4.exe
|
||||
) ELSE (
|
||||
SET LXML_FILE=lxml-3.7.3.win-amd64-py3.4.exe
|
||||
SET LXML_URL=https://pypi.python.org/packages/2d/65/e47db7f36a69a1b59b4f661e42d699d6c43e663b8fd91035e6f7681d017e/lxml-3.7.3.win-amd64-py3.4.exe
|
||||
)
|
||||
)
|
||||
)
|
||||
IF NOT "%LXML_FILE%" == "" (
|
||||
CALL :download %LXML_URL% .downloads\%LXML_FILE%
|
||||
easy_install --user .downloads\%LXML_FILE%
|
||||
)
|
||||
GOTO :eof
|
||||
|
||||
:test
|
||||
SET VENV_DIR=.venv\%PYTHON_VERSION%
|
||||
CALL %VENV_DIR%\Scripts\activate
|
||||
IF "%TOXENV%" == "" (
|
||||
SET TOXENV=py%PYTHON_VERSION_MAJOR%%PYTHON_VERSION_MINOR%
|
||||
)
|
||||
IF "%PYTHON_VERSION_MAJOR%%PYTHON_VERSION_MINOR%" == "26" (
|
||||
SET TOX=python -c "from tox import cmdline; cmdline()"
|
||||
) ELSE (
|
||||
SET TOX=python -m tox
|
||||
)
|
||||
IF %PYTHON_VERSION_MAJOR% == 3 (
|
||||
IF %PYTHON_VERSION_MINOR% LEQ 4 (
|
||||
:: Python 3.3 and 3.4 does not support typed-ast (mypy dependency)
|
||||
%TOX% --sitepackages -e %TOXENV%-test,%TOXENV%-lint,cov || EXIT 1
|
||||
) ELSE (
|
||||
%TOX% --sitepackages -e %TOXENV%-test,%TOXENV%-type,%TOXENV%-lint,cov || EXIT 1
|
||||
)
|
||||
) ELSE (
|
||||
%TOX% --sitepackages -e %TOXENV%-test,%TOXENV%-lint,cov || EXIT 1
|
||||
)
|
||||
GOTO :eof
|
||||
|
||||
:download
|
||||
IF NOT EXIST %2 (
|
||||
IF NOT EXIST .downloads\ mkdir .downloads
|
||||
powershell -command "(new-object net.webclient).DownloadFile('%1', '%2')" || EXIT 1
|
||||
|
||||
)
|
||||
GOTO :eof
|
158
tox.ini
Normal file
158
tox.ini
Normal file
@ -0,0 +1,158 @@
|
||||
[tox]
|
||||
envlist =
|
||||
py26-{test,vulture}
|
||||
py{27,py,py3}-{test,pylint,flake8,vulture}
|
||||
py{33,34,35,36,37}-{test,mypy,pylint,flake8,vulture}
|
||||
cov
|
||||
skipsdist = true
|
||||
skip_missing_interpreters = true
|
||||
|
||||
[testenv]
|
||||
deps =
|
||||
test: pytest==3.0.7
|
||||
test,cov: {[testenv:cov]deps}
|
||||
test,py{33,34,35,36,37}-{type,mypy}: colorama==0.3.7
|
||||
py{33,34,35,36,37}-{type,mypy}: {[testenv:mypy]deps}
|
||||
py{27,py,py3,33,34,35,36,37}-{lint,pylint},lint: {[testenv:pylint]deps}
|
||||
py{27,py,py3,33,34,35,36,37}-{lint,flake8},lint: {[testenv:flake8]deps}
|
||||
py{27,py,py3,33,34,35,36,37}-{lint,vulture},lint: {[testenv:vulture]deps}
|
||||
setenv =
|
||||
SSHAUDIT = {toxinidir}/ssh-audit.py
|
||||
test: COVERAGE_FILE = {toxinidir}/.coverage.{envname}
|
||||
type,mypy: MYPYPATH = {toxinidir}/test/stubs
|
||||
type,mypy: MYPYHTML = {toxinidir}/reports/html/mypy
|
||||
commands =
|
||||
test: coverage run --source ssh-audit -m -- \
|
||||
test: pytest -v --junitxml={toxinidir}/reports/junit.{envname}.xml {posargs:test}
|
||||
test: coverage report --show-missing
|
||||
test: coverage html -d {toxinidir}/reports/html/coverage.{envname}
|
||||
py{33,34,35,36,37}-{type,mypy}: {[testenv:mypy]commands}
|
||||
py{27,py,py3,33,34,35,36,37}-{lint,pylint},lint: {[testenv:pylint]commands}
|
||||
py{27,py,py3,33,34,35,36,37}-{lint,flake8},lint: {[testenv:flake8]commands}
|
||||
py{27,py,py3,33,34,35,36,37}-{lint,vulture},lint: {[testenv:vulture]commands}
|
||||
ignore_outcome =
|
||||
type: true
|
||||
lint: true
|
||||
|
||||
[testenv:cov]
|
||||
deps =
|
||||
coverage==4.3.4
|
||||
setenv =
|
||||
COVERAGE_FILE = {toxinidir}/.coverage
|
||||
commands =
|
||||
coverage erase
|
||||
coverage combine
|
||||
coverage report --show-missing
|
||||
coverage xml -i -o {toxinidir}/reports/coverage.xml
|
||||
coverage html -d {toxinidir}/reports/html/coverage
|
||||
|
||||
[testenv:mypy]
|
||||
deps =
|
||||
colorama==0.3.7
|
||||
lxml==3.7.3
|
||||
mypy==0.501
|
||||
commands =
|
||||
mypy \
|
||||
--show-error-context \
|
||||
--config-file {toxinidir}/tox.ini \
|
||||
--html-report {env:MYPYHTML}.py3.{envname} \
|
||||
{posargs:{env:SSHAUDIT}}
|
||||
mypy \
|
||||
-2 \
|
||||
--no-warn-incomplete-stub \
|
||||
--show-error-context \
|
||||
--config-file {toxinidir}/tox.ini \
|
||||
--html-report {env:MYPYHTML}.py2.{envname} \
|
||||
{posargs:{env:SSHAUDIT}}
|
||||
|
||||
[testenv:pylint]
|
||||
deps =
|
||||
mccabe
|
||||
pylint
|
||||
commands =
|
||||
pylint \
|
||||
--rcfile tox.ini \
|
||||
--load-plugins=pylint.extensions.bad_builtin \
|
||||
--load-plugins=pylint.extensions.check_elif \
|
||||
--load-plugins=pylint.extensions.mccabe \
|
||||
{posargs:{env:SSHAUDIT}}
|
||||
|
||||
[testenv:flake8]
|
||||
deps =
|
||||
flake8
|
||||
commands =
|
||||
flake8 {posargs:{env:SSHAUDIT}}
|
||||
|
||||
[testenv:vulture]
|
||||
deps =
|
||||
vulture
|
||||
commands =
|
||||
python -c "import sys; from subprocess import Popen, PIPE; \
|
||||
a = ['vulture'] + r'{posargs:{env:SSHAUDIT}}'.split(' '); \
|
||||
o = Popen(a, shell=False, stdout=PIPE).communicate()[0]; \
|
||||
l = [x for x in o.split(b'\n') if x and b'Unused import' not in x]; \
|
||||
print(b'\n'.join(l).decode('utf-8')); \
|
||||
sys.exit(1 if len(l) > 0 else 0)"
|
||||
|
||||
|
||||
[mypy]
|
||||
ignore_missing_imports = False
|
||||
follow_imports = error
|
||||
disallow_untyped_calls = True
|
||||
disallow_untyped_defs = True
|
||||
check_untyped_defs = True
|
||||
disallow_subclassing_any = True
|
||||
warn_incomplete_stub = True
|
||||
warn_redundant_casts = True
|
||||
warn_return_any = True
|
||||
warn_unused_ignores = True
|
||||
strict_optional = True
|
||||
strict_boolean = True
|
||||
|
||||
[pylint]
|
||||
reports = no
|
||||
#output-format = colorized
|
||||
indent-string = \t
|
||||
disable =
|
||||
locally-disabled,
|
||||
bad-continuation,
|
||||
multiple-imports,
|
||||
invalid-name,
|
||||
trailing-whitespace,
|
||||
missing-docstring
|
||||
max-complexity = 15
|
||||
max-args = 8
|
||||
max-locals = 20
|
||||
max-returns = 6
|
||||
max-branches = 15
|
||||
max-statements = 60
|
||||
max-parents = 7
|
||||
max-attributes = 8
|
||||
min-public-methods = 1
|
||||
max-public-methods = 20
|
||||
max-bool-expr = 5
|
||||
max-nested-blocks = 6
|
||||
max-line-length = 80
|
||||
ignore-long-lines = ^\s*(#\s+type:\s+.*|[A-Z0-9_]+\s+=\s+.*|('.*':\s+)?\[.*\],?|assert\s+.*)$
|
||||
max-module-lines = 2500
|
||||
|
||||
[flake8]
|
||||
ignore =
|
||||
# indentation contains tabs
|
||||
W191,
|
||||
# blank line contains whitespace
|
||||
W293,
|
||||
# indentation contains mixed spaces and tabs
|
||||
E101,
|
||||
# multiple spaces before operator
|
||||
E221,
|
||||
# multiple spaces after operator
|
||||
E241,
|
||||
# multiple imports on one line
|
||||
E401,
|
||||
# line too long
|
||||
E501,
|
||||
# module imported but unused
|
||||
F401,
|
||||
# undefined name
|
||||
F821
|
Reference in New Issue
Block a user