Codebase list tlssled / ddb10a4e-41e8-4964-8170-c8c91c32626d/main TLSSLed_v1.3.sh
ddb10a4e-41e8-4964-8170-c8c91c32626d/main

Tree @ddb10a4e-41e8-4964-8170-c8c91c32626d/main (Download .tar.gz)

TLSSLed_v1.3.sh @ddb10a4e-41e8-4964-8170-c8c91c32626d/mainraw · history · blame

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
#!/usr/bin/env bash
#
# Tool:    
#	TLSSLed.sh
#
# Description:
#	Script to extract the most relevant security details from a 
#	target SSL/TLS HTTPS implementation by using sslscan & openssl.
#
# URL:     
#	http://www.taddong.com/en/lab.html#TLSSLED
#
# Author:  
#	Raul Siles (raul _AT_ taddong _DOT_ com)
#	Taddong SL (www.taddong.com)
#
# Date:		2013-01-31
# Version:	1.3
#

#
# /**************************************************************************
# *   Copyright 2011-2013 by Taddong SL (Raul Siles)                        *
# *                                                                         *
# *   This program is free software; you can redistribute it and/or modify  *
# *   it under the terms of the GNU General Public License as published by  *
# *   the Free Software Foundation; either version 3 of the License, or     *
# *   (at your option) any later version.                                   *
# *                                                                         *
# *   This program is distributed in the hope that it will be useful,       *
# *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
# *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
# *   GNU General Public License for more details.                          *
# *                                                                         *
# *   You should have received a copy of the GNU General Public License     *
# *   along with this program. If not, see <http://www.gnu.org/licenses/>.  *
# *                                                                         *
# **************************************************************************/
#

#
# - TODO:
#   - Add a new command line argument to define the specific URL to test in
#   the target server. E.g. $ ./TLSSLed.sh HOSTNAME_or_IP-ADDRESS PORT [URL]"
#
#   By default the URL should be "/".
#   This check should use HTTP/1.1 (instead of 1.0) and a valid Host header.
#   (Right now this only applies to the HTTP header tests at the end)
#
#
# - New in version 1.3:
#   - All file output goes to a single directory (same filenames as in 
#     previous versions) instead of to the working local directory.
#   - Change in the date format used for log files:
#     From: 2011-12-30_105055 - To: 20111230-105055
#   - Test if SSL/TLS renegotiation is enabled (NEW check) and if the target 
#     service supports secure renegotiation (already in previous versions).
#     If secure renegotiation is not supported, we must check renegotiation
#     by usin legacy renegotiation (two new log files are used). 
#   - New test to check for legacy renegotiation even when secure 
#     renegotiation is supported, just in case the target service supports
#     both.
#   - Test if client certificate authentication is required by the target 
#     service. If so, identify the number of CAs accepted and save the
#     list of CAs to a file.
#	- New test to check for HTTP headers using HTTP/1.0 (previous 
#	  versions) as well as HTTP/1.1 and a valid Host header. New log 
#	  files created for this.
#   - New error handling code for the initial SSL/TLS verification.
#   - Optimizations in the openssl delays (sleep timers). 
#   - New DELAY variable to control sleep timers (by default 3 seconds - 
#     it was 5 before).
#   - New output indentation.
#   - New output code set for findings: - (negative), + (positive), . (info),
#     * (group of checks) or ! (error/warning).
#   - LOGFILE changed to SSLSCANLOGFILE & ERRFILE changed to SSLSCANERRFILE.
#   - RENEGLEGACY???FILE(s) included in the final listing and removal 
#     process.
#   - Several changes to the output messages for the different findings.
#   - Duplication of "Prefered Server Cipher" output message removed.
#   - New check to test for RC4 in the prefered chiper(s) regarding BEAST.
#   - Use of openssl "-prexit" option for some weird target scenarios (CSA).
#   - Added the date and time at the beggining of the output.
#
# - New in version 1.2:
#   - Mac OS X support: sed regex switch changed - by [ anonymous ].
#   - Test if target service speaks SSL/TLS - by Abraham Aranguren (AA).
#     For performance reasons, this test has been merged with the SSL/TLS 
#     renegotiation test.
#   - Optimizations by removing cat usage in grepping for findings - by AA.
#   - New initial tests to check for the tool prerequisites: openssl & 
#     sslscan.
#   - Test for TLS v1.1 and v1.2 support (CVE-2011-3389 aka BEAST).
#     The tests also include checking for SSLv3 and TLSv1 support.
#   - Log files names changed from host:port to host_port and ":" removed 
#     from the time portion of the date command, to be able to copy them 
#     to Windows based file systems: 
#     (In Windows ":" is not allowed in a filename, while "_" is).
#
# - New in version 1.1:
#   - Cert public key length, subject, issuer, and validiy period.
#   - Test HTTP(S) secure headers: Strict-Transport-Security (STS), and 
#     cookies with and without the secure flag.
#   - NOTE: openssl output is now saved to files too.
#
# - Current SSL/TLS tests: (version 1.0)
#   SSLv2, NULL cipher, weak ciphers -key length-, strong ciphers -AES-, 
#   MD5 signed cert, and SSL/TLS renegotiation.
#
#
# Requires: 
# - sslscan
# https://sourceforge.net/projects/sslscan/
# - openssl
# http://www.openssl.org
#
# Credits for ideas and feedback: 
# - Version 1.0 based on ssl_test.sh by Aung Khant, http://yehg.net.
# - Abraham Aranguren (AA) - http://securityconscious.blogspot.com  (in v1.2)
# 

# New output codeset (between square brackets) for the findings:
# [-] Negative finding (insecure)
# [+] Positive finding (secure)
# [.] Informational finding 
# [*] Group of checks
# [!] Error or warning message

# Variables

# Version
VERSION=1.3

# Manage sleep time for openssl connections (in seconds)
DELAY=3

# DATE (pre v1.3):
# DATE=$(date +%F_%R:%S | sed 's/://g')
# DATE (post v1.3+):
DATE=$(date +%Y%m%d-%H%M%S)

# Some SSL/TLS target services require some extra options to work:
# E.g. -prexit: Print out info even when the SSL/TLS connection fails.
#               http://www.openssl.org/docs/apps/s_client.html
#               For some scenarios where client certificates are required.
OPENSSLOPTIONS="-prexit"

# Default openssl protocol: By default this variable is empty so that the 
# protocol is automatically selected by the openssl version available:
OPENSSLPROTOCOLVERSION=""
# The default backward compatible protocol version in case of errors: TLS1
BACKWARDPROTOCOL="false"
OPENSSLBACKWARDPROTOCOLVERSION="-tls1"
#
# See NOTE (openssl protocol version glitches) below. 
#
# openssl 1.x might require the "-tls1" or "-ssl3" openssl command line 
# arguments on some target sites, as openssl 1.x uses TLS protocol version 
# 1.2 by default in the Client Hello message, and if not supported by the 
# target server, it never sends the Server Hello message back.
#

# *** SECURITY DISCLAIMER ***
# This script does not filter the input for certain commands, hence it 
# might be vulnerable to local input command manipulation, such as in uname.
# *** SECURITY DISCLAIMER ***

# Functions ()

reviewlogfiles () {
	echo
	echo "[.] Review the files within the output directory for more info."
	echo "    [.] Output directory: $DIRECTORY ..." 
	echo
}

# Function to initially test if the target service speaks SSL/TLS
test_if_service_speaks_SSLTLS () {

	(echo R; sleep $DELAY) | \
	openssl s_client $OPENSSLPROTOCOLVERSION -connect $HOST:$PORT \
	$OPENSSLOPTIONS > $DIRECTORY/$RENEGLOGFILE 2> $DIRECTORY/$RENEGERRFILE &
	pid=$!
	sleep $DELAY

	SSL_HANDSHAKE_LINES=$(cat $DIRECTORY/$RENEGLOGFILE | wc -l)
	#
	# NOTE: openssl protocol version glitches
	#
	# This check does not work with openssl 1.0.1-dev on some target sites, 
	# and it requires the "-tls1" or "-ssl3" openssl command line arguments; 
	# here, and in all openssl instances within this script.
	#
	# The reason is openssl 1.0.1-dev uses TLS protocol version 1.2 in the 
	# Client Hello message, and the server never sends the Server Hello 
	# message. The otput simply shows:
	# CONNECTED
	# 
	# If the -tls1_1 switch is used in these target services, they properly 
	# reply back with a "wrong version number" message.
	#
	# v1.3: Added new code to accommodate this scenario:
	# If (-lt 5) but CONNECTED, then use the -tls1 (backward protocol 
	# version) switch in all openssl executions...
	# ... or (select the right option based on the openssl version, but this
	# might change): if openssl 1.0.1-dev or +, use -tls1...

	#
	# There is a specific case where the target service can refuse the 
	# connection but the port still speaks SSL/TLS. In that case the error 
	# log contains the following messages, although the handshake log is > 
	# than 5 lines:
	# connect: Connection refused
	# connect:errno=22
	#

	ERR_SSL=$(cat $DIRECTORY/$RENEGERRFILE)

	if grep -q "connect: Connection refused" <<<$ERR_SSL; then
		# Target service speaks SSL/TLS but refuses the connection
		echo
		echo "[!] ERROR: The target service $HOST:$PORT might speak SSL/TLS"
		echo "           but refuses the connection."
		reviewlogfiles
		exit
	fi

	if [ $SSL_HANDSHAKE_LINES -lt 5 ] ; then 
		# SSL handshake failed - Non SSL/TLS service or error:
		# - If the target service does not speak SSL/TLS, openssl does not 
		#   terminate, so kill it.
		# - However, if the target speaks SSL/TLS but the connection fails 
		#   (e.g. "sslv3 alert bad certificate") then the connection 
		#   finishes.
		kill -s SIGINT ${pid} 2>/dev/null

		# Check if it failed because of an error or lack of SSL/TLS support
		#ERR_SSL=$(cat $DIRECTORY/$RENEGERRFILE)
		if grep -q "ssl handshake failure" <<<$ERR_SSL; then
		    echo
		    echo "[!] ERROR: The target service $HOST:$PORT speaks SSL/TLS"
			echo "           but returned an error: ssl handshake failure."
			echo "           E.g. Client certificate mandatory?"
		elif [ $BACKWARDPROTOCOL == "true" ]; then
			echo
			echo "[!] ERROR: The target service $HOST:$PORT does not seem"
			echo "           to speak SSL/TLS even when using the SSL/TLS backward"
			echo "           protocol version: $OPENSSLPROTOCOLVERSION"
		elif grep -q "CONNECTED" <<<$ERR_SSL; then
			# The local openssl tool tried by default a protocol version not 
			# supported by the target server. Switching back to a more
			# conservative protocol version (OPENSSLBACKWARDPROTOCOLVERSION).
			OPENSSLPROTOCOLVERSION=$OPENSSLBACKWARDPROTOCOLVERSION
			# Set we already tried a backward option
			BACKWARDPROTOCOL="true"
			echo
			echo "[.] WARNING: Trying connection again with SSL/TLS protocol version:"
			echo "             $OPENSSLPROTOCOLVERSION"
			#echo
			mv $DIRECTORY/$RENEGLOGFILE $DIRECTORY/$RENEGLOGFILE.1st-try
			mv $DIRECTORY/$RENEGERRFILE $DIRECTORY/$RENEGERRFILE.1st-try
		    	# Repeat initial test with a potentially different 
			# $OPENSSLPROTOCOLVERSION
			test_if_service_speaks_SSLTLS
		else
		    echo
		    echo "[!] ERROR: The target service $HOST:$PORT does not seem"
			echo "           to speak SSL/TLS or it is not reachable!!"
		fi
		reviewlogfiles
		exit
	else 
		# Specific case where server returns "reason(1000)" cause it requires a
		# client certificate, and SSLv3 was used by default. Force it to switch
		# to the OPENSLLBACKWARDPROTOCOLVERSION and try again:
		# Error: 
		# 3073591496:error:140773E8:SSL routines:SSL23_GET_SERVER_HELLO:\
		# reason(1000):s23_clnt.c:724:
	        # Another error: (!= openssl version)
		# 13531:error:14094412:SSL routines:SSL3_READ_BYTES:sslv3 alert bad certificate:s3_pkt.c:1093:SSL alert number 42

		if grep -q "SSL23_GET_SERVER_HELLO:reason(1000)\|sslv3 alert bad certificate" <<<$ERR_SSL; then
		    echo
		    echo "[!] ERROR: The target service $HOST:$PORT speaks SSL/TLS"
		    echo "           but returned an error."
		    echo "           Check the output and try manually other SSL/TLS versions."
		    echo "           E.g. Client certificate mandatory?"
		    reviewlogfiles
		    exit
		else	
		    # SSL handshake succeded - Continue...
		    # VERBOSE
		    echo "    [.] The target service $HOST:$PORT seems to speak SSL/TLS..."
		    echo
		    echo "    [.] Using SSL/TLS protocol version: $OPENSSLPROTOCOLVERSION"
		    echo "        (empty means I'm using the default openssl protocol version(s))"
		    echo
		fi
	fi
}


# MAIN:

# v1.2: 
# Mac OS X (Darwin) support:
# sed regexes in Linux use the -r switch, while in non-GNU systems (like
# Mac OS X) they use the -E switch.
#SED_ARG_REGEX=-r
#if [ "$(uname)" == "Darwin" ] ; then
#   SED_ARG_REGEX=-E
#fi
#
# Used for the old check below required to remove terminal output formatting

echo ------------------------------------------------------
echo " TLSSLed - ($VERSION) based on sslscan and openssl"
echo "                 by Raul Siles (www.taddong.com)"
echo ------------------------------------------------------

if [ -z `which openssl` ] ;then echo; echo "[!] ERROR: openssl command not found!"; echo; exit; fi
if [ -z `which sslscan` ] ;then echo; echo "[!] ERROR: sslscan command not found!"; echo; exit; fi

OPENSSLVERSION=$(openssl version)
#SSLSCANVERSION=$(sslscan --version | grep version | \
#sed ${SED_ARG_REGEX} "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g")
# v1.3:
# Works with the old sslscan 1.8.2 and the new 1.8.3rc3 fork
SSLSCANVERSION=$(sslscan --version | grep version | \
sed "s/^.*sslscan/sslscan/")

echo "    openssl version: $OPENSSLVERSION"
echo "    $SSLSCANVERSION"
echo ------------------------------------------------------
echo "    Date: $DATE" 
echo ------------------------------------------------------
echo

if [ $# -ne 2 ]; then 
   echo "[!] Usage: $0 <hostname or IP_address> <port>"
   echo
   exit
fi

HOST=$1
PORT=$2

echo "[*] Analyzing SSL/TLS on $HOST:$PORT ..."

# Run sslcan once, store the results to a log file and
# analyze that file for all the different tests:
TARGET=$HOST\_$PORT
DIRECTORY=TLSSLed\_$VERSION\_$TARGET\_$DATE
SSLSCANLOGFILE=sslscan\_$TARGET\_$DATE.log
SSLSCANERRFILE=sslscan\_$TARGET\_$DATE.err
# Same idea for openssl - save results to files and analyze
# them to verify different tests:
RENEGLOGFILE=openssl\_RENEG\_$TARGET\_$DATE.log
RENEGERRFILE=openssl\_RENEG\_$TARGET\_$DATE.err
RENEGLEGACYLOGFILE=openssl\_RENEG\_LEGACY\_$TARGET\_$DATE.log
RENEGLEGACYERRFILE=openssl\_RENEG\_LEGACY\_$TARGET\_$DATE.err
HEADLOGFILE=openssl\_HEAD\_$TARGET\_$DATE.log
HEADERRFILE=openssl\_HEAD\_$TARGET\_$DATE.err
HEAD1LOGFILE=openssl\_HEAD\_1.0\_$TARGET\_$DATE.log
HEAD1ERRFILE=openssl\_HEAD\_1.0\_$TARGET\_$DATE.err
CASFILE=CAs-client-cert\_$TARGET\_$DATE.txt


# Just in case...
if [ -z "$DIRECTORY" ]; then
    echo
    echo "[!] ERROR: Output directory is not defined! Aborting execution!"
    echo
    exit 
fi

# VERBOSE
echo "    [.] Output directory: $DIRECTORY ..." 
if [ -d "$DIRECTORY" ]; then
    echo
    echo "[!] ERROR: Output directory already exist! Aborting execution!"
    echo
    exit 
fi
echo
mkdir -p $DIRECTORY

# Check if the target service speaks SSL/TLS (& check renegotiation)
echo "[*] Checking if the target service speaks SSL/TLS..." 

test_if_service_speaks_SSLTLS

# This initial check is required because sslscan works pretty slow & badly
# on non-SSL/TLS services, such as HTTP (without S):

echo "[*] Running sslscan on $HOST:$PORT ..."
sslscan $HOST:$PORT > $DIRECTORY/$SSLSCANLOGFILE \
2> $DIRECTORY/$SSLSCANERRFILE

echo
echo "    [-] Testing for SSLv2 ..."
grep "Accepted  SSLv2" $DIRECTORY/$SSLSCANLOGFILE
echo
echo "    [-] Testing for the NULL cipher ..."
grep "NULL" $DIRECTORY/$SSLSCANLOGFILE | grep Accepted
echo
echo "    [-] Testing for weak ciphers (based on key length - 40 or 56 bits) ..."
grep " 40 bits" $DIRECTORY/$SSLSCANLOGFILE | grep Accepted
grep " 56 bits" $DIRECTORY/$SSLSCANLOGFILE | grep Accepted
echo
echo "    [+] Testing for strong ciphers (based on AES) ..."
grep "AES" $DIRECTORY/$SSLSCANLOGFILE | grep Accepted

echo 
echo "    [-] Testing for MD5 signed certificate ..."
#cat $DIRECTORY/$SSLSCANLOGFILE | grep -E 'MD5WithRSAEncryption|md5WithRSAEncryption'
grep -i 'MD5WithRSAEncryption' $DIRECTORY/$SSLSCANLOGFILE

echo 
echo "    [.] Testing for the certificate public key length ..."
grep -i 'RSA Public Key' $DIRECTORY/$SSLSCANLOGFILE

echo 
echo "    [.] Testing for the certificate subject ..."
grep -i 'Subject:' $DIRECTORY/$SSLSCANLOGFILE

echo 
echo "    [.] Testing for the certificate CA issuer ..."
grep -i 'Issuer:' $DIRECTORY/$SSLSCANLOGFILE

echo 
echo "    [.] Testing for the certificate validity period ..."
NOW=$(date -u)
echo "    Today: $NOW"
grep -i 'Not valid' $DIRECTORY/$SSLSCANLOGFILE

echo 
echo "    [.] Checking preferred server ciphers ..."
# v1.1:
# cat $DIRECTORY/$SSLSCANLOGFILE | sed '/Prefered Server Cipher(s):/,/^$/!d' | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g"
#
PREFERED_CIPHERS=$(cat $DIRECTORY/$SSLSCANLOGFILE | \
sed '/Prefered Server Cipher(s):/,/^$/!d' | \
sed ${SED_ARG_REGEX} "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g" | \
grep -v "Prefered Server Cipher" | grep -v "^$")
echo "$PREFERED_CIPHERS"

# Extra empty line above removed with the last grep

#
# SSL/TLS RENEGOTIATION TESTS:
# -----------------------------
#
# Before testing for client initiated renegotiation, we need to check if
# we must use the secure (RFC5746) or the insecure (legacy) mode.
#
# Renegotiation details will go to stderr (2>).
#
# If $OPENSSLVERSION is updated (0.9.8m+) it supports RFC5746 and will print
# the details based on the analysis of the new RI extension:
# - Secure Renegotiation IS NOT supported
# - Secure Renegotiation IS supported
#
# Command executed initially to check if target service supports SSL/TLS:
#
# (echo R; sleep $DELAY) | openssl s_client $OPENSSLPROTOCOLVERSION -connect $HOST:$PORT > \
# $DIRECTORY/$RENEGLOGFILE 2> $DIRECTORY/$RENEGERRFILE
#
# v1.3: 
# First of all, check if secure renegotiation is supported. Based on the 
# results, check if client initiated renegotiation is enabled by using 
# openssl defaults (secure) or the use the "-legacy_renegotiation" flag 
# (insecure).
#
# It is important to differentiate between having client initiated 
# renegotiation enabled, and having support for secure renegotiation.
# There are four possible options or combinations.
#
# If secure renegotiation is NOT supported, we need to use the legacy flag
# to test for SSL/TLS legacy renegotiation. If it IS supported, the default 
# command (initially executed) works fine.
# 
# Additionally, even if secure renegotiation IS supported, we can check if
# the target service also accepts insecure renegotiations (legacy). 
# Therefore, in any case we test for SSL/TLS renegotiation using the legacy 
# mode.
#

# The text can appear two times, hence we use "uniq":
SECURE_RENEG=$(grep -E "Secure Renegotiation IS" $DIRECTORY/$RENEGLOGFILE | \
uniq)

echo
echo "[*] Testing for SSL/TLS renegotiation MitM vuln. (CVE-2009-3555) ..."
echo
echo "    [+] Testing for secure renegotiation support (RFC 5746) ..."
echo "    $SECURE_RENEG"

# Check for SSL/TLS renegotiation using legacy mode in any case
LEGACY_RENEG="-legacy_renegotiation"
(echo R; sleep $DELAY) | \
openssl s_client $LEGACY_RENEG $OPENSSLPROTOCOLVERSION -connect $HOST:$PORT \
> $DIRECTORY/$RENEGLEGACYLOGFILE 2> $DIRECTORY/$RENEGLEGACYERRFILE 

echo
echo "[*] Testing for SSL/TLS renegotiation DoS vuln. (CVE-2011-1473) ..."
echo

if grep -q NOT <<<$SECURE_RENEG; then
    # Secure renegotiation IS NOT supported: show legacy mode results
    SECURE_RENEG_STATE="No"
    ERR_RENEG=$(cat $DIRECTORY/$RENEGLEGACYERRFILE)
    echo "    [.] Testing for client initiated (CI) SSL/TLS renegotiation (insecure)..."
else
    # Secure renegotiation IS supported: RFC5746
    # The default option in openssl (assuming 0.9.8m+) is not to use any 
    # special flag, that is, use secure renegotiation by default
    SECURE_RENEG_STATE="Yes"
    ERR_RENEG=$(cat $DIRECTORY/$RENEGERRFILE)
    echo "    [.] Testing for client initiated (CI) SSL/TLS renegotiation (secure)..."
fi

# - If SSL/TLS renegotiation is enabled you will get:
# ...
# verify return:0
# DONE
#
# The DONE message is on the error output, not on the standard output, and
# only when the "echo R & sleep" method is used (not in interactive mode).

if grep -q DONE <<<$ERR_RENEG; then
    echo "    (CI) SSL/TLS renegotiation IS enabled"
# Client certificate might be required: 
elif grep -q "sslv3 alert bad certificate" <<<$ERR_RENEG; then
    echo "    UNKNOWN: Client certificate might be required (sslv3 alert bad certificate)"
# Client certificate might be required: 
# "sslv3 alert unexpected message" in openssl-1.0.1-dev
elif grep -q "sslv3 alert unexpected message" <<<$ERR_RENEG; then
    echo "    UNKNOWN: Client certificate might be required (sslv3 alert unexpected message)"
# Different error behaviors when reneg. is not enabled:
elif grep -q "no renegotiation" <<<$ERR_RENEG; then
    echo "    (CI) SSL/TLS renegotiation IS NOT enabled (no renegotiation)"
elif grep -q "ssl handshake failure" <<<$ERR_RENEG; then
    echo "    (CI) SSL/TLS renegotiation IS NOT enabled (ssl handshake failure)"
else
    echo "    UNKNOWN"
fi

# Additionally, if secure renegotiation is supported, check if it still
# allows renegotiation using legacy mode (insecure):
if [ "$SECURE_RENEG_STATE" == "Yes" ]; then
    echo
    echo "    [.] Testing for client initiated (CI) SSL/TLS renegotiation (insecure)..."
    ERR_RENEG=$(cat $DIRECTORY/$RENEGLEGACYERRFILE)

    # REPEAT:
    if grep -q DONE <<<$ERR_RENEG; then
        echo "    (CI) SSL/TLS renegotiation IS enabled"
    # Client certificate might be required: 
    elif grep -q "sslv3 alert bad certificate" <<<$ERR_RENEG; then
        echo "    UNKNOWN: Client certificate might be required (sslv3 alert bad certificate)"
    # Client certificate might be required: 
    # "sslv3 alert unexpected message" in openssl-1.0.1-dev
    elif grep -q "sslv3 alert unexpected message" <<<$ERR_RENEG; then
        echo "    UNKNOWN: Client certificate might be required (sslv3 alert unexpected message)"
    # Different error behaviors when reneg. is not enabled:
    elif grep -q "no renegotiation" <<<$ERR_RENEG; then
        echo "    (CI) SSL/TLS renegotiation IS NOT enabled (no renegotiation)"
    elif grep -q "ssl handshake failure" <<<$ERR_RENEG; then
        echo "    (CI) SSL/TLS renegotiation IS NOT enabled (ssl handshake failure)"
    else
        echo "    UNKNOWN"
    fi
fi

# Check if client certificate autentication is required by the target 
# service.
#
# NOTE: If client certificate authentication is being requested, it would be
# possible to test for it using a client digital certificate using openssl:
# $ openssl s_client $OPENSSLPROTOCOLVERSION -connect www.example.com:443 \
#   -cert client.pem -key client.key
#

LOG_RENEG=$(cat $DIRECTORY/$RENEGLOGFILE)

echo
echo "[*] Testing for client authentication using digital certificates ..."
echo
if grep -q "Acceptable client certificate CA names" <<<$LOG_RENEG; then
    echo "    SSL/TLS client certificate authentication IS required"

    # Check the list and number of accepted CAs
    # Save CAs list to file
    # The LOG_RENEG variable does not have the original break lines to parse
    # the output properly, so read the file again
    cat $DIRECTORY/$RENEGLOGFILE | \
	sed '/Acceptable client certificate CA names/,/^---$/!d' | \
	grep -v "\-\-\-" | grep -v "Acceptable client certificate CA names" | \
	grep -v "^$" > $DIRECTORY/$CASFILE
    
    # Number of CAs
    CAS=$(cat $DIRECTORY/$CASFILE | wc -l)
    echo "    The target service accepts $CAS Certification Authorities (CAs)"

elif grep -q "No client certificate CA names sent" <<<$LOG_RENEG; then
    echo "    SSL/TLS client certificate authentication IS NOT required"
else
    echo "    UNKNOWN"
fi


echo
echo "[*] Testing for TLS v1.1 and v1.2 (CVE-2011-3389 vuln. aka BEAST) ..."

# Test for SSLv3 and TLSv1 support first (from sslscan)
echo
echo "    [-] Testing for SSLv3 and TLSv1 support ..."
grep "Accepted  SSLv3" $DIRECTORY/$SSLSCANLOGFILE
grep "Accepted  TLSv1" $DIRECTORY/$SSLSCANLOGFILE

# Test for RC4 in the list of prefered ciphers (from sslscan previously)
echo
echo "    [+] Testing for RC4 in the prefered cipher(s) list ..."
echo "$PREFERED_CIPHERS" | grep "RC4"

#
# Connection details go to stderr (2>) and, in this case, to a variable:
#
# If $OPENSSLVERSION is updated (version >= 1.0.1-stable) it supports 
# TLS v1.1 & v1.2, if not, the openssl help is displayed in the command 
# output.
#
OUTPUT_TLS1_1=$((echo Q; sleep $DELAY) | \
openssl s_client -tls1_1 -connect $HOST:$PORT 2>&1)
OUTPUT_TLS1_2=$((echo Q; sleep $DELAY) | \
openssl s_client -tls1_2 -connect $HOST:$PORT 2>&1)

#      if "DONE":                   TLS v1.x supported
# else if "wrong version number":   TLS v1.x not supported
# else if "unknown option":         OpenSSL does not support TLS v1.1 or v1.2

echo
echo "    [.] Testing for TLS v1.1 support ..."

if grep -q DONE <<<$OUTPUT_TLS1_1; then
    echo "    TLS v1.1 IS supported"
elif grep -q "wrong version number" <<<$OUTPUT_TLS1_1; then
    echo "    TLS v1.1 IS NOT supported"
elif grep -q "ssl handshake failure" <<<$OUTPUT_TLS1_1; then
    echo "    TLS v1.1 IS NOT supported (ssl handshake failure)"
elif grep -q "unknown option" <<<$OUTPUT_TLS1_1; then
    echo "    The local openssl version does NOT support TLS v1.1"
else
    echo "    UNKNOWN"
fi

echo
echo "    [.] Testing for TLS v1.2 support ..."

if grep -q DONE <<<$OUTPUT_TLS1_2; then
    echo "    TLS v1.2 IS supported"
elif grep -q "wrong version number" <<<$OUTPUT_TLS1_2; then
    echo "    TLS v1.2 IS NOT supported"
elif grep -q "ssl handshake failure" <<<$OUTPUT_TLS1_2; then
    echo "    TLS v1.2 IS NOT supported (ssl handshake failure)"
elif grep -q "unknown option" <<<$OUTPUT_TLS1_2; then
    echo "    The local openssl version does NOT support TLS v1.2"
else
    echo "    UNKNOWN"
fi

echo
echo "[*] Testing for HTTPS (SSL/TLS) security headers using HTTP/1.0 ..."

(echo -e "HEAD / HTTP/1.0\n\n"; sleep $DELAY) | \
openssl s_client $OPENSSLPROTOCOLVERSION -connect $HOST:$PORT \
> $DIRECTORY/$HEAD1LOGFILE 2> $DIRECTORY/$HEAD1ERRFILE

echo
echo "    [+] Testing for HTTP Strict-Transport-Security (HSTS) header ..."
grep -i 'Strict-Transport-Security' $DIRECTORY/$HEAD1LOGFILE

echo
echo "    [+] Testing for cookies with the secure flag ..."
grep -i 'Set-Cookie' $DIRECTORY/$HEAD1LOGFILE | grep -i 'secure'

echo
echo "    [-] Testing for cookies without the secure flag ..."
grep -i 'Set-Cookie' $DIRECTORY/$HEAD1LOGFILE | grep -v -i 'secure'


echo
echo "[*] Testing for HTTPS (SSL/TLS) security headers using HTTP/1.1 & Host ..."

(echo -e "HEAD / HTTP/1.1\nHost: $HOST\n\n"; sleep $DELAY) | \
openssl s_client $OPENSSLPROTOCOLVERSION -connect $HOST:$PORT \
> $DIRECTORY/$HEADLOGFILE 2> $DIRECTORY/$HEADERRFILE

echo
echo "    [+] Testing for HTTP Strict-Transport-Security (HSTS) header ..."
grep -i 'Strict-Transport-Security' $DIRECTORY/$HEADLOGFILE

echo
echo "    [+] Testing for cookies with the secure flag ..."
grep -i 'Set-Cookie' $DIRECTORY/$HEADLOGFILE | grep -i 'secure'

echo
echo "    [-] Testing for cookies without the secure flag ..."
grep -i 'Set-Cookie' $DIRECTORY/$HEADLOGFILE | grep -v -i 'secure'


echo
echo "[*] New files created:"
echo "    [.] Output directory: $DIRECTORY ..." 
echo

# Moved to bottom:
#ls -l $DIRECTORY/$SSLSCANLOGFILE
#ls -l $DIRECTORY/$RENEGLOGFILE
#ls -l $DIRECTORY/$RENEGLEGACYLOGFILE
#ls -l $DIRECTORY/$HEAD1LOGFILE
#ls -l $DIRECTORY/$HEADLOGFILE

# Delete all empty error files:
# $ find . -size 0 -name '*.err' -delete 
# This could potentially delete other .err zero-size files not created by 
# TLSSLed.


if [ ! -s "$DIRECTORY/$SSLSCANERRFILE" ]; then
	# SSLscan error file is empty
	rm "$DIRECTORY/$SSLSCANERRFILE"
fi
if [ ! -s "$DIRECTORY/$RENEGERRFILE" ]; then
	# Renegotiation error file is empty
	rm "$DIRECTORY/$RENEGERRFILE"
fi
if [ ! -s "$DIRECTORY/$RENEGLEGACYERRFILE" ]; then
	# Legacy renegotiation error file is empty
	rm "$DIRECTORY/$RENEGLEGACYERRFILE"
fi
if [ ! -s "$DIRECTORY/$HEAD1ERRFILE" ]; then
	# Openssl HEAD 1.0 error file is empty
	rm "$DIRECTORY/$HEAD1ERRFILE"
fi
if [ ! -s "$DIRECTORY/$HEADERRFILE" ]; then
	# Openssl HEAD 1.1 error file is empty
	rm "$DIRECTORY/$HEADERRFILE"
fi

ls $DIRECTORY

echo 
echo [*] done
echo