Add support for testing postgres protocol over TLS/SSL

The Postgres protocol uses STARTTLS with a custom start packet. This
functionality is supported by openssl s_client in the current openssl
master branch but not yet in any released version.

This patch detects whether the given openssl binary supports postgres
and runs the usual tests against a postgres server.

Example of no openssl support:

    ~/bin/testssl$ ./testssl.sh --quiet
    --openssl=/opt/openssl/openssl-1.1.0c/bin/openssl --starttls=postgres
    test.postgres.server.com:5432

     Start 2016-12-07 18:03:24    -->> ip.add.re.ss:5432
    (test.postgres.server.com:5432) <<--

    Fatal error: Your /opt/openssl/openssl-1.1.0c/bin/openssl does not
    support the "-starttls postgres" option

Example of openssl support:

    ~/bin/testssl$ ./testssl.sh --quiet
    --openssl=/opt/openssl/openssl-2016-12-07/bin/openssl --startt ls=postgres
    test.postgres.server.com:5432

     Start 2016-12-07 18:06:03    -->> ip.add.re.ss:5432
    (test.postgres.server.com:5432) <<--

     Service set:            STARTTLS via POSTGRES

     Testing protocols (via openssl, SSLv2 via sockets)

     SSLv2               not offered (OK)
     SSLv3               offered (NOT ok)
     TLS 1               offered
     TLS 1.1             offered
     TLS 1.2             offered (OK)
     SPDY/NPN            (SPDY is an HTTP protocol and thus not tested here)
     HTTP2/ALPN          (HTTP/2 is a HTTP protocol and thus not tested
    here)
    ...
This commit is contained in:
Steven Danneman 2016-12-08 10:54:44 -08:00
parent c985f68533
commit 1f165bcdf4

View File

@ -223,6 +223,7 @@ HAS_SPDY=false
HAS_FALLBACK_SCSV=false HAS_FALLBACK_SCSV=false
HAS_PROXY=false HAS_PROXY=false
HAS_XMPP=false HAS_XMPP=false
HAS_POSTGRES=false
ADD_RFC_STR="rfc" # display RFC ciphernames ADD_RFC_STR="rfc" # display RFC ciphernames
PORT=443 # unless otherwise auto-determined, see below PORT=443 # unless otherwise auto-determined, see below
NODE="" NODE=""
@ -5571,6 +5572,10 @@ EOF
starttls_line "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>" "proceed" starttls_line "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>" "proceed"
# BTW: https://xmpp.net ! # BTW: https://xmpp.net !
;; ;;
postgres|postgress) # Postgres SQL, see http://www.postgresql.org/docs/devel/static/protocol-message-formats.html
$FAST_STARTTLS || starttls_just_read
starttls_line "\x00\x00\x00\x08\x04\xD2\x16\x2F" "S"
;;
*) # we need to throw an error here -- otherwise testssl.sh treats the STARTTLS protocol as plain SSL/TLS which leads to FP *) # we need to throw an error here -- otherwise testssl.sh treats the STARTTLS protocol as plain SSL/TLS which leads to FP
fatal "FIXME: STARTTLS protocol $STARTTLS_PROTOCOL is not yet supported" -4 fatal "FIXME: STARTTLS protocol $STARTTLS_PROTOCOL is not yet supported" -4
esac esac
@ -7426,6 +7431,7 @@ test_openssl_suffix() {
find_openssl_binary() { find_openssl_binary() {
local s_client_has=$TEMPDIR/s_client_has.txt local s_client_has=$TEMPDIR/s_client_has.txt
local s_client_starttls_has=$TEMPDIR/s_client_starttls_has.txt
# 0. check environment variable whether it's executable # 0. check environment variable whether it's executable
if [[ -n "$OPENSSL" ]] && [[ ! -x "$OPENSSL" ]]; then if [[ -n "$OPENSSL" ]] && [[ ! -x "$OPENSSL" ]]; then
@ -7482,6 +7488,8 @@ find_openssl_binary() {
$OPENSSL s_client -help 2>$s_client_has $OPENSSL s_client -help 2>$s_client_has
$OPENSSL s_client -starttls foo 2>$s_client_starttls_has
grep -qw '\-alpn' $s_client_has && \ grep -qw '\-alpn' $s_client_has && \
HAS_ALPN=true HAS_ALPN=true
@ -7497,6 +7505,9 @@ find_openssl_binary() {
grep -q '\-xmpp' $s_client_has && \ grep -q '\-xmpp' $s_client_has && \
HAS_XMPP=true HAS_XMPP=true
grep -q 'postgres' $s_client_starttls_has && \
HAS_POSTGRES=true
return 0 return 0
} }
@ -7592,8 +7603,8 @@ special invocations:
partly mandatory parameters: partly mandatory parameters:
URI host|host:port|URL|URL:port (port 443 is assumed unless otherwise specified) URI host|host:port|URL|URL:port (port 443 is assumed unless otherwise specified)
pattern an ignore case word pattern of cipher hexcode or any other string in the name, kx or bits pattern an ignore case word pattern of cipher hexcode or any other string in the name, kx or bits
protocol is one of the STARTTLS protocols ftp,smtp,pop3,imap,xmpp,telnet,ldap protocol is one of the STARTTLS protocols ftp,smtp,pop3,imap,xmpp,telnet,ldap,postgres
(for the latter two you need e.g. the supplied openssl) (for telnet and ldap you need e.g. the supplied openssl)
tuning options (can also be preset via environment variables): tuning options (can also be preset via environment variables):
--bugs enables the "-bugs" option of s_client, needed e.g. for some buggy F5s --bugs enables the "-bugs" option of s_client, needed e.g. for some buggy F5s
@ -7681,6 +7692,7 @@ HAS_ALPN: $HAS_ALPN
HAS_FALLBACK_SCSV: $HAS_FALLBACK_SCSV HAS_FALLBACK_SCSV: $HAS_FALLBACK_SCSV
HAS_PROXY: $HAS_PROXY HAS_PROXY: $HAS_PROXY
HAS_XMPP: $HAS_XMPP HAS_XMPP: $HAS_XMPP
HAS_POSTGRES: $HAS_POSTGRES
PATH: $PATH PATH: $PATH
PROG_NAME: $PROG_NAME PROG_NAME: $PROG_NAME
@ -8284,7 +8296,7 @@ determine_optimal_proto() {
} }
# arg1: ftp smtp, pop3, imap, xmpp, telnet, ldap (maybe with trailing s) # arg1: ftp smtp, pop3, imap, xmpp, telnet, ldap, postgres (maybe with trailing s)
determine_service() { determine_service() {
local ua local ua
local protocol local protocol
@ -8311,9 +8323,13 @@ determine_service() {
service_detection $OPTIMAL_PROTO service_detection $OPTIMAL_PROTO
else else
# STARTTLS # STARTTLS
protocol=${1%s} # strip trailing 's' in ftp(s), smtp(s), pop3(s), etc if [[ "$1" == postgres ]]; then
protocol="postgres"
else
protocol=${1%s} # strip trailing 's' in ftp(s), smtp(s), pop3(s), etc
fi
case "$protocol" in case "$protocol" in
ftp|smtp|pop3|imap|xmpp|telnet|ldap) ftp|smtp|pop3|imap|xmpp|telnet|ldap|postgres)
STARTTLS="-starttls $protocol" STARTTLS="-starttls $protocol"
SNI="" SNI=""
if [[ "$protocol" == xmpp ]]; then if [[ "$protocol" == xmpp ]]; then
@ -8327,6 +8343,12 @@ determine_service() {
# see http://xmpp.org/rfcs/rfc3920.html # see http://xmpp.org/rfcs/rfc3920.html
fi fi
fi fi
if [[ "$protocol" == postgres ]]; then
# Check if openssl version supports postgres.
if ! "$HAS_POSTGRES"; then
fatal "Your $OPENSSL does not support the \"-starttls postgres\" option" -5
fi
fi
$OPENSSL s_client -connect $NODEIP:$PORT $PROXY $BUGS $STARTTLS 2>$ERRFILE >$TMPFILE </dev/null $OPENSSL s_client -connect $NODEIP:$PORT $PROXY $BUGS $STARTTLS 2>$ERRFILE >$TMPFILE </dev/null
if [[ $? -ne 0 ]]; then if [[ $? -ne 0 ]]; then
debugme cat $TMPFILE debugme cat $TMPFILE
@ -8340,7 +8362,7 @@ determine_service() {
outln outln
;; ;;
*) outln *) outln
fatal "momentarily only ftp, smtp, pop3, imap, xmpp, telnet and ldap allowed" -4 fatal "momentarily only ftp, smtp, pop3, imap, xmpp, telnet, ldap and postgres allowed" -4
;; ;;
esac esac
fi fi
@ -8648,8 +8670,8 @@ parse_cmd_line() {
STARTTLS_PROTOCOL=$(parse_opt_equal_sign "$1" "$2") STARTTLS_PROTOCOL=$(parse_opt_equal_sign "$1" "$2")
[[ $? -eq 0 ]] && shift [[ $? -eq 0 ]] && shift
case $STARTTLS_PROTOCOL in case $STARTTLS_PROTOCOL in
ftp|smtp|pop3|imap|xmpp|telnet|ldap|nntp) ;; ftp|smtp|pop3|imap|xmpp|telnet|ldap|nntp|postgres) ;;
ftps|smtps|pop3s|imaps|xmpps|telnets|ldaps|nntps) ;; ftps|smtps|pop3s|imaps|xmpps|telnets|ldaps|nntps|postgress) ;;
*) pr_magentaln "\nunrecognized STARTTLS protocol \"$1\", see help" 1>&2 *) pr_magentaln "\nunrecognized STARTTLS protocol \"$1\", see help" 1>&2
help 1 ;; help 1 ;;
esac esac