diff --git a/testssl.sh b/testssl.sh index 9a0f39a..f7aba0a 100755 --- a/testssl.sh +++ b/testssl.sh @@ -853,6 +853,7 @@ fileout() { # ID, SEVERITY, FINDING debugme() { [[ "$DEBUG" -ge 2 ]] && "$@" + return 0 } hex2dec() { @@ -6073,8 +6074,8 @@ starttls_line() { } starttls_just_send(){ - debugme echo -e "\n=== sending \"$1\" ..." - echo -e "$1" >&5 + debugme echo -e "C: $1" + echo -ne "$1\r\n" >&5 } starttls_just_read(){ @@ -6090,6 +6091,108 @@ starttls_just_read(){ return 0 } +starttls_full_read(){ + starttls_read_data=() + local one_line="" + local ret=0 + local cont_pattern="$1" + local end_pattern="$2" + local ret_found=0 + if [[ $# -ge 3 ]]; then + debugme echo "=== we have to search for $3 pattern ===" + ret_found=3 + fi + debugme echo "=== full read banner ===" + + local oldIFS="$IFS" + IFS='' + while read -r -t $STARTTLS_SLEEP one_line; do + debugme echo "S: ${one_line}" + if [[ $# -ge 3 ]]; then + if [[ ${one_line} =~ $3 ]]; then + ret_found=0 + debugme echo "^^^^^^^ that's what we were looking for ===" + fi + fi + starttls_read_data+=("${one_line}") + if [[ ${one_line} =~ ${end_pattern} ]]; then + debugme echo "=== full read finished ===" + IFS="${oldIFS}" + return ${ret_found} + fi + if [[ ! ${one_line} =~ ${cont_pattern} ]]; then + debugme echo "=== full read syntax error, expected regex pattern ${cont_pattern} (cont) or ${end_pattern} (end) ===" + IFS="${oldIFS}" + return 2 + fi + done <&5 + ret=$? + debugme echo "=== full read error/timeout ===" + IFS="${oldIFS}" + return $ret +} + +starttls_ftp_dialog(){ + debugme echo "=== starting ftp STARTTLS dialog ===" + local reAUTHTLS='^ AUTH TLS' + starttls_full_read '^220-' '^220 ' && debugme echo "received server greeting" && + starttls_just_send 'FEAT' && debugme echo "sent FEAT" && + starttls_full_read '^(211-| )' '^211 ' "${reAUTHTLS}" && debugme echo "received server features and checked STARTTLS availability" && + starttls_just_send 'AUTH TLS' && debugme echo "initiated STARTTLS" && + starttls_full_read '^234-' '^234 ' && debugme echo "received ack for STARTTLS" + local ret=$? + debugme echo "=== finished ftp STARTTLS dialog with ${ret} ===" + return $ret +} + +starttls_smtp_dialog(){ + debugme echo "=== starting smtp STARTTLS dialog ===" + local re250STARTTLS='^250[ -]STARTTLS' + starttls_full_read '^220-' '^220 ' && debugme echo "received server greeting" && + starttls_just_send 'EHLO testssl.sh' && debugme echo "sent EHLO" && + starttls_full_read '^250-' '^250 ' "${re250STARTTLS}" && debugme echo "received server capabilities and checked STARTTLS availability" && + starttls_just_send 'STARTTLS' && debugme echo "initiated STARTTLS" && + starttls_full_read '^220-' '^220 ' && debugme echo "received ack for STARTTLS" + local ret=$? + debugme echo "=== finished smtp STARTTLS dialog with ${ret} ===" + return $ret +} + +starttls_pop3_dialog() { + debugme echo "=== starting pop3 STARTTLS dialog ===" + starttls_full_read '$^' '^+OK' && debugme echo "received server greeting" && + starttls_just_send 'STLS' && debugme echo "initiated STARTTLS" && + starttls_full_read '$^' '^+OK' && debugme echo "received ack for STARTTLS" + local ret=$? + debugme echo "=== finished pop3 STARTTLS dialog with ${ret} ===" + return $ret +} + +starttls_imap_dialog() { + debugme echo "=== starting imap STARTTLS dialog ===" + local reSTARTTLS='^\* CAPABILITY(( .*)? IMAP4rev1( .*)? STARTTLS( .*)?|( .*)? STARTTLS( .*)? IMAP4rev1( .*)?)$' + starttls_full_read '^\* ' '^\* OK ' && debugme echo "received server greeting" && + starttls_just_send 'a001 CAPABILITY' && debugme echo "sent CAPABILITY" && + starttls_full_read '^\* ' '^a001 OK ' "${reSTARTTLS}" && debugme echo "received server capabilities and checked STARTTLS availability" && + starttls_just_send 'a002 STARTTLS' && debugme echo "initiated STARTTLS" && + starttls_full_read '^\* ' '^a002 OK ' && debugme echo "received ack for STARTTLS" + local ret=$? + debugme echo "=== finished imap STARTTLS dialog with ${ret} ===" + return $ret +} + +starttls_nntp_dialog() { + debugme echo "=== starting nntp STARTTLS dialog ===" + starttls_full_read '$^' '^20[01] ' && debugme echo "received server greeting" && + starttls_just_send 'CAPABILITIES' && debugme echo "sent CAPABILITIES" && + starttls_full_read '$^' '^101 ' && + starttls_full_read '' '^\.$' "^STARTTLS$" && debugme echo "received server capabilities and checked STARTTLS availability" && + starttls_just_send 'STARTTLS' && debugme echo "initiated STARTTLS" && + starttls_full_read '$^' '^382 ' && debugme echo "received ack for STARTTLS" + local ret=$? + debugme echo "=== finished nntp STARTTLS dialog with ${ret} ===" + return $ret +} # arg for a fd doesn't work here fd_socket() { @@ -6127,29 +6230,20 @@ fd_socket() { if [[ -n "$STARTTLS" ]]; then case "$STARTTLS_PROTOCOL" in # port - ftp|ftps) # https://tools.ietf.org/html/rfc4217 - $FAST_STARTTLS || starttls_just_read - $FAST_STARTTLS || starttls_line "FEAT" "211" && starttls_just_send "FEAT" - starttls_line "AUTH TLS" "successful|234" + ftp|ftps) # https://tools.ietf.org/html/rfc4217, https://tools.ietf.org/html/rfc959 + starttls_ftp_dialog ;; - smtp|smtps) # SMTP, see https://tools.ietf.org/html/rfc4217 - $FAST_STARTTLS || starttls_just_read - $FAST_STARTTLS || starttls_line "EHLO testssl.sh" "220|250" && starttls_just_send "EHLO testssl.sh" - starttls_line "STARTTLS" "220" + smtp|smtps) # SMTP, see https://tools.ietf.org/html/rfc5321, https://tools.ietf.org/html/rfc3207 + starttls_smtp_dialog ;; pop3|pop3s) # POP, see https://tools.ietf.org/html/rfc2595 - $FAST_STARTTLS || starttls_just_read - starttls_line "STLS" "OK" + starttls_pop3_dialog ;; nntp|nntps) # NNTP, see https://tools.ietf.org/html/rfc4642 - $FAST_STARTTLS || starttls_just_read - $FAST_STARTTLS || starttls_line "CAPABILITIES" "101|200" && starttls_just_send "CAPABILITIES" - starttls_line "STARTTLS" "382" + starttls_nntp_dialog ;; - imap|imaps) # IMAP, https://tools.ietf.org/html/rfc2595 - $FAST_STARTTLS || starttls_just_read - $FAST_STARTTLS || starttls_line "a001 CAPABILITY" "OK" && starttls_just_send "a001 CAPABILITY" - starttls_line "a002 STARTTLS" "OK" + imap|imaps) # IMAP, https://tools.ietf.org/html/rfc2595, https://tools.ietf.org/html/rfc3501 + starttls_imap_dialog ;; ldap|ldaps) # LDAP, https://tools.ietf.org/html/rfc2830, https://tools.ietf.org/html/rfc4511 fatal "FIXME: LDAP+STARTTLS over sockets not yet supported (try \"--ssl-native\")" -4