This PR is in response to issue #352, where it was noted that Bash does not support binary data in strings.
I replaced all calls to `sockread()` with calls to `sockread_serverhello()`, and then, since is now used everywhere and not just to read ServerHello messages, I renamed `sockread_serverhello()` to `sockread()`.
I tested the revised code against several servers, including one that is vulnerable to CCS and Heartbleed, and got the same results as with the current code (although the hexdumps displayed in debug mode differ).
One concern I have is the code in `run_ccs_injection()`. The current code is:
```
byte6=$(echo "$SOCKREPLY" | "${HEXDUMPPLAIN[@]}" | sed 's/^..........//')
lines=$(echo "$SOCKREPLY" | "${HEXDUMP[@]}" | count_lines )
debugme echo "lines: $lines, byte6: $byte6"
if [[ "$byte6" == "0a" ]] || [[ "$lines" -gt 1 ]]; then
pr_done_best "not vulnerable (OK)"
...
```
I revised this to:
```
if [[ -s "$SOCK_REPLY_FILE" ]]; then
byte6=$(hexdump -ve '1/1 "%.2x"' "$SOCK_REPLY_FILE" | sed 's/^..........//')
lines=$(hexdump -ve '16/1 "%02x " " \n"' "$SOCK_REPLY_FILE" | count_lines )
debugme echo "lines: $lines, byte6: $byte6"
fi
rm "$SOCK_REPLY_FILE"
if [[ "$byte6" == "0a" ]] || [[ "$lines" -gt 1 ]]; then
...
```
In the revised code `byte6` is initialized to `0a` so that the response is `not vulnerable (OK)` if `$SOCK_REPLY_FILE` is empty. This has worked okay since for all of the servers that I tested that weren't vulnerable `$SOCK_REPLY_FILE` was empty. Since I haven't seen any other examples, I don't understand why check for vulnerability was written the way it was. So, I'm a bit concerned that the test in the revised code may produce incorrect results now that `hexdump -ve '1/1 "%.2x"' "$SOCK_REPLY_FILE"` is an accurate hexdump of the reply.
In the check for old versions of OpenSSL, the results of the call to `ignore_no_or_lame()` are ignored, and so the program continues even if the user enters `no`.
This PR makes three changes to `determine_optimal_proto()`:
* It no longer tries an empty string for `$OPTIMAL_PROTO` twice.
* It does not include `-servername` for `-ssl2` or `-ssl3`, since some versions of OpenSSL that support SSLv2 will fail if `s_client` is provided both the `-ssl2` and `-servername` options.
* It displays a warning if `$OPTIMAL_PROTO` is `-ssl2`, since some tests in testssl.sh will not work correctly for SSLv2-only servers.
This PR addresses two issues related to SSLv2 for "--server-preference" checks.
First, some versions of OpenSSL that support SSLv2 will fail if `s_client` is provided both the `-ssl2` and `-servername` options.
Second, the line for extracting the chosen cipher,`cipher=$(awk '/Cipher.*:/ { print $3 }' $TMPFILE)`, fails for SSLv2. For SSLv2, the output from `$OPENSSL s_client` is as shown below, and the `cipher=` line extracts the word `between` from `Ciphers common between both SSL endpoints:` rather than `IDEA-CBC-MD5` from ` Cipher : IDEA-CBC-MD5`.
```
...
Ciphers common between both SSL endpoints:
RC4-MD5 RC2-CBC-MD5 IDEA-CBC-MD5
DES-CBC-MD5 DES-CBC3-MD5
---
SSL handshake has read 1191 bytes and written 373 bytes
---
New, SSLv2, Cipher is IDEA-CBC-MD5
Server public key is 2048 bit
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : SSLv2
Cipher : IDEA-CBC-MD5
...
```
This PR changes test_just_one() to correctly handle SSLv2 ciphers.
As with PR #424, this PR addresses the problem in which servers that do not implement SSLv2, but that implement RC4-MD5, EXP-RC2-CBC-MD5, EXP-RC4-MD5, or NULL-MD5 are shown as implementing both the SSLv2 and SSLv3 versions of the ciphers, and that any SSLv2 ciphers that a server does implement are not shown as being implemented.
This PR changes run_rc4() to correctly handle SSLv2 ciphers.
It addresses the problem in which servers that do not implement SSLv2, but that implement SSLv3 ciphers that share an OpenSSL name with an SSLv2 cipher (RC4-MD5 and EXP-RC4-MD5), are not incorrectly shown as having implemented the SSLv2 cipher.
It also addresses the problem that if a server does implement SSLv2 with an RC4 SSLv2-cipher suite, then that cipher suite it not shown as being implemented.
It is OK for a site to pin a CA that is not part of the chain (like github.com does)
This is a provision against a CA compromise (like diginotar) which could lead to a
briked site in case of CA compromise.
GitHub has built in multiple levels of security they have both backup pins for host
certs and back pins for CAs (and I wouldn;t be surprised if they have a backup
intermediate pin too).