URI: 
       tinitial commit - scripts - random scripts
  HTML git clone git://parazyd.org/scripts.git
   DIR Log
   DIR Files
   DIR Refs
       ---
   DIR commit b52b934adf0622975d5a61dcf938e4f80ce1e9d2
  HTML Author: parazyd <parazyd@dyne.org>
       Date:   Wed, 15 Jun 2016 13:14:34 +0200
       
       initial commit
       
       Diffstat:
         A aliens.sh                           |       7 +++++++
         A autoup                              |      12 ++++++++++++
         A backup.sh                           |       1 +
         A cdmenu                              |      21 +++++++++++++++++++++
         A cdump                               |       3 +++
         A chrono                              |      16 ++++++++++++++++
         A ddg                                 |       2 ++
         A disco                               |      12 ++++++++++++
         A dmenuwindows                        |      35 +++++++++++++++++++++++++++++++
         A dn                                  |      41 +++++++++++++++++++++++++++++++
         A extmon                              |      35 +++++++++++++++++++++++++++++++
         A find-https-debian-archives.py       |     136 +++++++++++++++++++++++++++++++
         A genhtpasswd                         |      13 +++++++++++++
         A img                                 |       2 ++
         A ix                                  |       3 +++
         A lock                                |      31 +++++++++++++++++++++++++++++++
         A macspoof.sh                         |      24 ++++++++++++++++++++++++
         A nx-termcast                         |      29 +++++++++++++++++++++++++++++
         A obsolete/dmenu.sh                   |       2 ++
         A obsolete/scream.sh                  |      12 ++++++++++++
         A obsolete/startcups.sh               |       3 +++
         A obsolete/startvbox.sh               |       2 ++
         A obsolete/torrentnotif.sh            |       2 ++
         A obsolete/updatepw.sh                |      37 +++++++++++++++++++++++++++++++
         A open                                |     295 ++++++++++++++++++++++++++++++
         A p                                   |      16 ++++++++++++++++
         A pacmans.sh                          |      45 +++++++++++++++++++++++++++++++
         A pio                                 |       3 +++
         A pipesx                              |     194 ++++++++++++++++++++++++++++++
         A popup                               |       5 +++++
         A powertoptune.sh                     |      34 +++++++++++++++++++++++++++++++
         A rain                                |     100 +++++++++++++++++++++++++++++++
         A rainbow                             |      15 +++++++++++++++
         A randcolor                           |       9 +++++++++
         A record                              |      23 +++++++++++++++++++++++
         A refan                               |       2 ++
         A retor                               |       2 ++
         A rot13                               |       3 +++
         A signrelease                         |      55 +++++++++++++++++++++++++++++++
         A skrot                               |       7 +++++++
         A square                              |       8 ++++++++
         A sslget                              |      12 ++++++++++++
         A startdwm                            |       8 ++++++++
         A supadd                              |      75 +++++++++++++++++++++++++++++++
         A susp                                |       2 ++
         A takeoffdir                          |      10 ++++++++++
         A testssl.sh                          |    4892 +++++++++++++++++++++++++++++++
         A tone                                |       6 ++++++
         A translate                           |      30 ++++++++++++++++++++++++++++++
         A utf8.sh                             |      51 +++++++++++++++++++++++++++++++
         A volume                              |      39 +++++++++++++++++++++++++++++++
         A weepop.sh                           |       5 +++++
         A xkcd.py                             |      10 ++++++++++
         A xurls                               |     115 +++++++++++++++++++++++++++++++
         A ydl                                 |      56 +++++++++++++++++++++++++++++++
         A ys                                  |      37 +++++++++++++++++++++++++++++++
       
       56 files changed, 6645 insertions(+), 0 deletions(-)
       ---
   DIR diff --git a/aliens.sh b/aliens.sh
       t@@ -0,0 +1,7 @@
       +#!/bin/sh
       +#
       +# parazyd - (c) wtfpl 2016
       +# some disco
       +
       +x="if(t%2)else"
       +python3 -c"[print(t>>15&(t>>(2$x 4))%(3+(t>>(8$x 11))%4)+(t>>10)|42&t>>7&t<<9,end='')for t in range(2**20)]" | aplay -c2 -r4"
   DIR diff --git a/autoup b/autoup
       t@@ -0,0 +1,12 @@
       +#!/bin/sh
       +
       +sshuser=parazyd
       +sshkey="$HOME/.ssh/id_ed25519"
       +server=pub.parazyd.cf
       +webroot=/home/parazyd/public_html/pub
       +webdir=tmp
       +
       +test -z "$1" && exit 1 || filename=$(basename $1)
       +scp -i "$sshkey" "$1" "${sshuser}@${server}:${webroot}/${webdir}/${filename}"
       +echo "https://$server/$webdir/$filename" | xsel -i
       +rm $1
   DIR diff --git a/backup.sh b/backup.sh
       t@@ -0,0 +1 @@
       +rsync -aAXv --exclude={"/dev/*","/proc/*","/sys/*","/tmp/*","/run/*","/mnt/*","/media/*","/lost+found","/home/parazyd/mnt"} / /home/parazyd/mnt/backup/
   DIR diff --git a/cdmenu b/cdmenu
       t@@ -0,0 +1,21 @@
       +#!/bin/sh
       +
       +normfg="#939393"
       +normbg="#000000"
       +selbg="#800000"
       +selfg="#ffffff"
       +font="Terminus:size=9"
       +
       +list="$(ls -d */ \
       +        | dmenu -p 'cd' \
       +                -l 20 \
       +                -fn $font \
       +                -nb $normbg \
       +                -nf $normfg \
       +                -sb $selbg \
       +                -sf $selfg \
       +                $@)"
       +
       +if [ ! -z "$list" ]; then
       +        echo $list
       +fi
   DIR diff --git a/cdump b/cdump
       t@@ -0,0 +1,3 @@
       +#!/bin/sh
       +
       +xrdb -query | grep -P '^\*color[0-9]*:' | tr -d '\t' | cut -d: -f2 #| hex2col
   DIR diff --git a/chrono b/chrono
       t@@ -0,0 +1,16 @@
       +#!/bin/sh
       +#
       +# parazyd - (c) wtfpl 2016
       +# fonts: xsansb future smblock univers
       +
       +FONT=$1
       +: ${FONT:="future"}
       +
       +for m in $(seq 0 59); do
       +    for s in $(seq 0 59); do
       +        clear
       +        echo
       +        printf ' %02d : %02d' $m $s | toilet -f $FONT
       +        sleep 1
       +    done
       +done
   DIR diff --git a/ddg b/ddg
       t@@ -0,0 +1,2 @@
       +#!/bin/sh
       +palemoon -new-tab "https://duckduckgo.com/html/?q=$*"
   DIR diff --git a/disco b/disco
       t@@ -0,0 +1,12 @@
       +#!/bin/sh
       +#
       +# parazyd - (c) wtfpl 2016
       +# party mode
       +
       +timeout=0.2
       +while true; do
       +    echo 255 > /sys/devices/platform/thinkpad_acpi/leds/tpacpi::thinklight/brightness
       +    sleep $timeout
       +    echo 0 > /sys/devices/platform/thinkpad_acpi/leds/tpacpi::thinklight/brightness
       +    sleep $timeout
       +done
   DIR diff --git a/dmenuwindows b/dmenuwindows
       t@@ -0,0 +1,35 @@
       +#!/bin/sh
       +#
       +# parayzd - (c) wtfpl 2016
       +# list open windows in a dmenu
       +
       +normfg="#939393"
       +normbg="#000000"
       +selbg="#800000"
       +selfg="#ffffff"
       +font="Terminus:size=9"
       +
       +height=$(wmctrl -l | wc -l)
       +if [[ $height -gt 30 ]]; then
       +        heightfit=30
       +else
       +        heightfit=$height
       +fi
       +
       +num=$(wmctrl -l \
       +        | sed 's/ hansolo/ /' \
       +        | cut -d " " -f 4- \
       +        | nl -w 3 -n rn \
       +        | sed -r 's/^([ 0-9]+)[ \t]*(.*)$/\1 - \2/' \
       +        | dmenu -i \
       +                -fn $font \
       +                -nb $normbg \
       +                -nf $normfg \
       +                -sb $selbg \
       +                -sf $selfg \
       +                -l $heightfit \
       +        | cut -d '-' -f -1 \
       +)
       +
       +[[ -z "$num" ]] && exit
       +wmctrl -l | sed -n "$num p" | cut -c -10 | xargs wmctrl -i -a
   DIR diff --git a/dn b/dn
       t@@ -0,0 +1,41 @@
       +#!/bin/sh
       +#
       +# parazyd - (c) wtfpl 2016
       +# manage resolv.conf
       +
       +chattr() {
       +        case $1 in
       +                on)  /usr/bin/chattr -V +i /etc/resolv.conf;;
       +                off) /usr/bin/chattr -V -i /etc/resolv.conf;;
       +        esac
       +}
       +
       +stopd() {
       +        /etc/init.d/unbound stop
       +        /etc/init.d/dnscrypt-proxy stop
       +}
       +
       +startd() {
       +        /etc/init.d/unbound start
       +        /etc/init.d/dnscrypt-proxy start
       +}
       +
       +case $1 in
       +        out|o)
       +                startd
       +                chattr off && echo "nameserver 127.0.0.1 # $1" > /etc/resolv.conf && chattr on
       +                exit 0;;
       +        home|h)
       +                stopd
       +                chattr off && echo "nameserver 10.0.1.1 # $1" > /etc/resolv.conf && chattr on
       +                exit 0;;
       +        bridge)
       +                stopd
       +                chattr off && echo "nameserver 172.16.17.1 # $1" > /etc/resolv.conf && chattr on
       +                exit 0;;
       +        *)
       +                echo "current set as: `awk '{print $4}' /etc/resolv.conf`"
       +                echo "usage: `basename $0` {home|out}";;
       +esac
       +
       +exit 1
   DIR diff --git a/extmon b/extmon
       t@@ -0,0 +1,35 @@
       +#!/bin/sh
       +#
       +# parazyd - (c) wtfpl 2016
       +# skreenz
       +
       +IN="LVDS1"
       +EXT="VGA1"
       +
       +case "$1" in
       +        left|l)
       +                xrandr --output $IN --auto --primary --output $EXT --auto --left-of $IN
       +                nitrogen --restore
       +                ;;
       +        right|r)
       +                xrandr --output $IN --auto --primary --output $EXT --auto --right-of $IN
       +                nitrogen --restore
       +                ;;
       +        above|a)
       +                xrandr --output $IN --auto --primary --output $EXT --auto --above $IN
       +                nitrogen --restore
       +                ;;
       +        dup|d)
       +                xrandr --output $EXT --same-as $IN --output $IN --primary
       +                ;;
       +        off|o)
       +                xrandr --output $IN --auto --output $EXT --off
       +                nitrogen --restore
       +                ;;
       +        list)
       +                xrandr | grep \<connected\> | cut -d\  -f1
       +                ;;
       +        *)
       +                echo `basename $0` '{left|right|above|dup|off|list}'
       +                ;;
       +esac
   DIR diff --git a/find-https-debian-archives.py b/find-https-debian-archives.py
       t@@ -0,0 +1,136 @@
       +#!/usr/bin/python2
       +#
       +# tries to find debian mirrors with https enabled
       +
       +import urllib2
       +import re
       +import ssl
       +import sys
       +
       +# # find generic mirrors
       +mirrors = urllib2.urlopen('http://www.debian.org/mirror/list')
       +https = []
       +for line in mirrors.readlines():
       +    m = re.match('.*<td valign="top"><a rel="nofollow" href="http(.*)">.*', line)
       +    if m:
       +        url = 'https' + m.group(1)
       +        print 'trying: ',
       +        print url,
       +        print '...',
       +        sys.stdout.flush()
       +        try:
       +            response=urllib2.urlopen(url, timeout=1)
       +            https.append(url)
       +            print 'success!'
       +        except urllib2.URLError as err:
       +            print 'fail!'
       +        except ssl.SSLError as err:
       +            print 'bad SSL!'
       +
       +# print 'HTTPS apt repos:'
       +#for url in https:
       +#    print url
       +
       +
       +# # find security mirrors
       +mirrors = urllib2.urlopen('http://www.debian.org/mirror/list-full')
       +securitys = []
       +for line in mirrors.readlines():
       +    m = re.match('.*</tt><br>Security updates over HTTP: <tt><a rel="nofollow" href="http(.*)">.*/debian-security/</a>.*', line)
       +    if m:
       +        url = 'https' + m.group(1)
       +        print 'trying: ',
       +        print url,
       +        print '...',
       +        sys.stdout.flush()
       +        try:
       +            response=urllib2.urlopen(url, timeout=1)
       +            securitys.append(url)
       +            print 'success!'
       +        except urllib2.URLError as err:
       +            print 'fail!'
       +        except ssl.SSLError as err:
       +            print 'bad SSL!'
       +
       +# print 'HTTPS security repos:'
       +# for url in securitys:
       +#     print url
       +
       +
       +# now find the backports mirrors
       +mirrors = urllib2.urlopen('http://backports-master.debian.org/Mirrors/')
       +backports = []
       +for line in mirrors.readlines():
       +#<td><a href="http://be.mirror.eurid.eu/debian-backports/">/debian-backports/</a>
       +    m = re.match('.*<td><a href="http(.*)">.*/debian-backports/</a>.*', line)
       +    if m:
       +        url = 'https' + m.group(1)
       +        print 'trying: ',
       +        print url,
       +        print '...',
       +        sys.stdout.flush()
       +        try:
       +            response=urllib2.urlopen(url, timeout=1)
       +            backports.append(url)
       +            print 'success!'
       +        except urllib2.URLError as err:
       +            print 'fail!'
       +        except ssl.SSLError as err:
       +            print 'bad SSL!'
       +
       +#print 'HTTPS backports repos:'
       +#for url in backports:
       +#    print url
       +
       +
       +# now find the CD image mirrors
       +mirrors = urllib2.urlopen('http://www.debian.org/CD/http-ftp/')
       +cds = []
       +for line in mirrors.readlines():
       +# <a rel="nofollow" href="http://mirror.easyspeedy.com/debian-cd/">HTTP</a></li>
       +    m = re.match('.*<a rel="nofollow" href="http(:.*)">HTTP</a></li>.*', line)
       +    if m:
       +        url = 'https' + m.group(1)
       +        print 'trying: ',
       +        print url,
       +        print '...',
       +        sys.stdout.flush()
       +        try:
       +            response=urllib2.urlopen(url, timeout=1)
       +            cds.append(url)
       +            print 'success!'
       +        except urllib2.URLError as err:
       +            print 'fail!'
       +        except ssl.SSLError as err:
       +            print 'bad SSL!'
       +
       +print 'HTTPS CD image repos:'
       +for url in cds:
       +    print url
       +
       +
       +# now write everything to a file
       +f = open('/tmp/https-debian-archives.txt', 'w')
       +
       +f.write('HTTPS apt repos\n')
       +f.write('---------------\n')
       +for url in https:
       +    f.write(url + '\n')
       +
       +f.write('\n\nHTTPS security repos\n')
       +f.write('---------------\n')
       +for url in securitys:
       +    f.write(url + '\n')
       +
       +f.write('\n\nHTTPS backports repos\n')
       +f.write('--------------------\n')
       +for url in backports:
       +    f.write(url + '\n')
       +
       +f.write('\n\nHTTPS CD image repos\n')
       +f.write('--------------------\n')
       +for url in cds:
       +    f.write(url + '\n')
       +
       +
       +f.close()
   DIR diff --git a/genhtpasswd b/genhtpasswd
       t@@ -0,0 +1,13 @@
       +#!/bin/sh
       +
       +user="$1"
       +realm="$2"
       +password="$3"
       +
       +if ! [[ -n $user ]] || ! [[ -n $realm ]] || ! [[ -n $password ]]; then
       +        echo "usage: `basename $0` [user] [realm] [password]"
       +else
       +        echo -n "${user}:${realm}:" \
       +                && echo -n "${user}:${realm}:${password}" \
       +                | md5sum | awk '{print $1}'
       +fi
   DIR diff --git a/img b/img
       t@@ -0,0 +1,2 @@
       +#!/bin/sh
       +curl -s "$1" | 2ff | lel -a -w 640 -h 480
   DIR diff --git a/ix b/ix
       t@@ -0,0 +1,3 @@
       +#!/bin/sh
       +
       +torsocks curl -sF "f:1=<-" ix.io
   DIR diff --git a/lock b/lock
       t@@ -0,0 +1,31 @@
       +#!/bin/bash
       +#
       +# parazyd - (c) wtfpl 2016
       +# make screenshot, pixelize and use as i3lock image
       +
       +scrot -z /tmp/screen.png
       +convert /tmp/screen.png -scale 10% -scale 1000% /tmp/screen.png
       +
       +if [ -f $HOME/.icons/lock.png ]; then
       +    # placement x/y
       +    PX=0
       +    PY=0
       +    # lockscreen image info
       +    R=$(file ~/.icons/lock.png | grep -o '[0-9]* x [0-9]*')
       +    RX=$(echo $R | cut -d' ' -f 1)
       +    RY=$(echo $R | cut -d' ' -f 3)
       +
       +    SR=$(xrandr --query | grep ' connected' | cut -f4 -d' ')
       +    for RES in $SR; do
       +        # monitor position/offset
       +        SRX=$(echo $RES | cut -d'x' -f 1)                   # x pos
       +        SRY=$(echo $RES | cut -d'x' -f 2 | cut -d'+' -f 1)  # y pos
       +        SROX=$(echo $RES | cut -d'x' -f 2 | cut -d'+' -f 2) # x offset
       +        SROY=$(echo $RES | cut -d'x' -f 2 | cut -d'+' -f 3) # y offset
       +        PX=$(($SROX + $SRX/2 - $RX/2))
       +        PY=$(($SROY + $SRY/2 - $RY/2))
       +
       +        convert /tmp/screen.png $HOME/.icons/lock.png -geometry +$PX+$PY -composite -matte /tmp/screen.png
       +    done
       +fi
       +i3lock -e -i /tmp/screen.png
   DIR diff --git a/macspoof.sh b/macspoof.sh
       t@@ -0,0 +1,24 @@
       +#!/bin/sh
       +#
       +# parazyd - (c) wtfpl 2016
       +# spoof or restore mac
       +
       +case "$1" in
       +        random|rand|r)
       +                echo "(*) randomizing $2's MAC"
       +                ip link set dev $2 down
       +                macchanger -r $2
       +                ip link set dev $2 up
       +                echo "(*) done!"
       +                ;;
       +        permanent|orig)
       +                echo "(*) restoring $2's MAC"
       +                ip link set dev $2 down
       +                macchanger -p $2
       +                ip link set dev $2 up
       +                echo "(*) done!"
       +                ;;
       +        *)
       +                echo `basename $0` '{random|orig} {device}'
       +                ;;
       +esac
   DIR diff --git a/nx-termcast b/nx-termcast
       t@@ -0,0 +1,29 @@
       +#!/bin/sh
       +#
       +# parazyd - (c) wtfpl 2016
       +#
       +# start recording a script and upload it in base64
       +# usage: nx-termcast [url]
       +
       +nx_upload() {
       +        curl -sLT${1:--} https://p.iotek.org
       +}
       +
       +nx_record() {
       +        script --timing=timing typescript
       +        # make a motherfucking tarbomb
       +        tar cz . | base64 | nx_upload
       +}
       +
       +nx_replay() {
       +        curl -s "$*" | base64 -d | tar xz
       +        scriptreplay timing typescript
       +}
       +
       +# that's to prevent the motherfucking tarbombs
       +cd $(mktemp -d)
       +
       +# give the impression of a clean session
       +
       +# either record or play, your choice
       +test -n "$1" && nx_replay "$*" || nx_record
   DIR diff --git a/obsolete/dmenu.sh b/obsolete/dmenu.sh
       t@@ -0,0 +1,2 @@
       +#!/bin/bash
       +dmenu_run
   DIR diff --git a/obsolete/scream.sh b/obsolete/scream.sh
       t@@ -0,0 +1,12 @@
       +#!/bin/zsh
       +
       +POSIT=/sys/devices/platform/hdaps/position
       +
       +while true; do
       +    val1=`cat $POSIT | awk -F, '{print $1}' | sed 's/(//'`
       +    val2=`cat $POSIT | awk -F, '{print $2}' | sed 's/)//'`
       +
       +    while [[ $val1 -lt '-370' && $val1 -gt '-375' ]]; do
       +        echo "AHAHHAHAA!!"
       +    done
       +done
   DIR diff --git a/obsolete/startcups.sh b/obsolete/startcups.sh
       t@@ -0,0 +1,3 @@
       +#!/bin/sh
       +sudo /etc/init.d/avahi-dnsconfd start
       +sudo /etc/init.d/cupsd start
   DIR diff --git a/obsolete/startvbox.sh b/obsolete/startvbox.sh
       t@@ -0,0 +1,2 @@
       +#!/bin/bash
       +sudo modprobe vboxdrv vboxnetadp vboxnetflt vboxpci; virtualbox
   DIR diff --git a/obsolete/torrentnotif.sh b/obsolete/torrentnotif.sh
       t@@ -0,0 +1,2 @@
       +#!/bin/bash
       +notify-send 'Transmission' 'Torrent Complete!\n$1 $2 $3'
   DIR diff --git a/obsolete/updatepw.sh b/obsolete/updatepw.sh
       t@@ -0,0 +1,37 @@
       +#!/usr/bin/env zsh
       +
       +for i in `find -name "*.xz"`; do
       +        rm ${i}.sha
       +        xz -d $i
       +done
       +
       +for i in `find -name "*.img"`; do
       +        loopdev=`sudo losetup -f --show ${i}`
       +        mappdev=`sudo kpartx -va $loopdev | sed -E 's/.*(loop[0-9])p.*/\1/g' | head -1`
       +
       +        mappdev="/dev/mapper/${mappdev}"
       +        rootpart="${mappdev}p2"
       +
       +        [[ -d "mountdir" ]] || mkdir mountdir
       +
       +        mount ${rootpart} mountdir
       +
       +        cat << EOF | sudo tee mountdir/changepw
       +#!/bin/sh
       +echo "root:devuan" | chpasswd
       +EOF
       +
       +        sudo cp /usr/bin/qemu-arm-static mountdir/usr/bin/qemu-arm-static
       +
       +        sudo chroot mountdir /changepw
       +        sudo rm mountdir/changepw
       +        sudo rm mountdir/usr/bin/qemu-arm-static
       +
       +        sudo umount ${rootpart}
       +
       +        sudo kpartx -dv ${loopdev}
       +        sudo losetup -d ${loopdev}
       +
       +        xz -zv ${i}
       +        sha256sum ${i}.xz > ${i}.xz.sha
       +done
   DIR diff --git a/open b/open
       t@@ -0,0 +1,295 @@
       +#!/usr/bin/perl
       +use strict;
       +use warnings;
       +
       +use constant
       +{
       +        PROG_REVEAL => 'rox',
       +        PROG_EDIT   => 'vim',
       +};
       +
       +sub open_smart;
       +sub edit;
       +sub stdin_to_editor;
       +sub reveal;
       +sub header_edit;
       +sub wait_or_not;
       +
       +sub usage
       +{
       +        print STDERR <<"!";
       +Usage: $0 -[efWwRh]
       +-e: edit
       +-f: stdin-edit
       +-W: wait for exit (true by default for editing)
       +-w: don't wait for exit
       +-R: reveal
       +-h: header search
       +!
       +        exit 1;
       +}
       +
       +my $cmd = \&open_smart;
       +my(@files, @args);
       +
       +my %opts = (
       +        'e'    => 0,
       +        'f'    => 0,
       +        'W'    => 0,
       +        'R'    => 0,
       +        'h'    => 0,
       +);
       +
       +my $wait_set = 0;
       +
       +usage() unless @ARGV;
       +
       +for(my $i = 0; $i < @ARGV; ++$i){
       +        $_ = $ARGV[$i];
       +
       +        if($_ eq '--'){
       +                push @files, @ARGV[$i + 1 .. $#ARGV];
       +                last;
       +        }
       +
       +        if(/^-([a-z])$/i){
       +                my $k = $1;
       +
       +                if(exists $opts{$k}){
       +                        $opts{$k} = 1;
       +                        $wait_set = 1 if $k eq 'W';
       +                }elsif($k eq 'w'){
       +                        $opts{W} = 0;
       +                        $wait_set = 1;
       +                }else{
       +                        usage();
       +                }
       +
       +        }elsif($_ eq '--args'){
       +                push @args, @ARGV[$i + 1 .. $#ARGV];
       +                last;
       +
       +        }elsif(/^-/){
       +                usage();
       +
       +        }else{
       +                push @files, $_;
       +
       +        }
       +}
       +
       +if($opts{e} + $opts{f} + $opts{R} + $opts{h} > 1){
       +        print STDERR "Can't combine -e, -f, -R and -h\n";
       +        usage();
       +}
       +
       +my $should_wait = 1;
       +if($opts{e}){
       +        $cmd = \&edit;
       +
       +}elsif($opts{f}){
       +        # <STDIN> | $EDITOR -
       +        $cmd = \&stdin_to_editor;
       +
       +}elsif($opts{R}){
       +        # open with rox
       +        $cmd = \&reveal;
       +        $should_wait = 0;
       +
       +}elsif($opts{h}){
       +        # search /usr/include/$_ for @files
       +        $cmd = \&header_edit;
       +
       +}
       +
       +$opts{W} = 1 if $should_wait and not $wait_set;
       +
       +exit(&{$cmd}((
       +                wait  => !!$opts{W},
       +                args  => [@args],
       +                files => [@files])));
       +
       +# end ---
       +
       +sub open_smart
       +{
       +        sub read_maps
       +        {
       +                my $rc = "$ENV{HOME}/.openrc";
       +                open F, '<', $rc or die "open $rc: $!\n";
       +
       +                my %maps;
       +
       +                my $suffix = 0;
       +                while(<F>){
       +                        chomp;
       +                        s/#.*//;
       +
       +                        if(/^\[(.*)\]$/){
       +                                if($1 eq 'full'){
       +                                        $suffix = 0;
       +                                }elsif($1 eq 'suffix'){
       +                                        $suffix = 1;
       +                                }else{
       +                                        die "invalid section \"$1\" in $rc\n";
       +                                }
       +
       +                        }elsif(my($prog, $matches) = /^([^:]+): *(.*)/){
       +                                sub getenv
       +                                {
       +                                        my $k = shift;
       +                                        return $ENV{$k} if $ENV{$k};
       +                                        my %backup = (
       +                                                "TERM" => "urxvt",
       +                                                "VISUAL" => "vim",
       +                                        );
       +                                        return $backup{$k} if $backup{$k};
       +                                        return "\$$k";
       +                                }
       +
       +                                my @matches = split / *, */, $matches;
       +
       +                                $prog =~ s/\$([A-Z_]+)/getenv($1)/e;
       +
       +                                push @{$maps{$prog}}, [ $_, $suffix ] for @matches;
       +
       +                        }elsif(length){
       +                                die "invalid confiuration line: \"$1\" in $rc\n";
       +                        }
       +                }
       +
       +                close F;
       +
       +                return %maps;
       +        }
       +
       +        my %maps = read_maps();
       +        my $ec = 0;
       +        my %h = @_;
       +
       +        my @to_open;
       +
       +file:
       +        for my $fnam (@{$h{files}}){
       +                #print "maps:\n";
       +
       +                if(-d $fnam){
       +                        push @to_open, [($h{wait}, PROG_REVEAL, @{$h{args}}, $fnam)];
       +                        next file;
       +                }
       +
       +                for my $prog (keys %maps){
       +                        #print "  $_:\n";
       +                        for(@{$maps{$prog}}){
       +                                my($reg, $suffix) = ($_->[0], $_->[1]);
       +                                if($suffix){
       +                                        $reg = "\\.$reg\$";
       +                                }
       +                                #print "    $reg\n"
       +
       +                                if($fnam =~ /$reg/){
       +                                        push @to_open, [($h{wait}, $prog, @{$h{args}}, $fnam)];
       +                                        next file;
       +                                }
       +                        }
       +                }
       +
       +                die "no program found for $fnam\n";
       +        }
       +
       +        wait_or_not(@{$_}) for @to_open;
       +
       +        return 0;
       +}
       +
       +sub wait_or_not
       +{
       +        my($wait, @rest) = @_;
       +        my $pid = fork();
       +
       +        die "fork(): $!\n" unless defined $pid;
       +
       +        if($pid == 0){
       +                if($rest[0] =~ / /){
       +                        my $a = shift @rest;
       +                        unshift @rest, split / +/, $a;
       +                }
       +
       +                exec @rest;
       +                die;
       +        }else{
       +                # parent
       +                if($wait){
       +                        my $reaped = wait();
       +                        my $ret = $?;
       +
       +                        die "wait(): $!\n" if $reaped == -1;
       +                        warn "unexpected dead child $reaped (expected $pid)\n" if $reaped != $pid;
       +
       +                        return $ret;
       +                }
       +        }
       +}
       +
       +sub edit
       +{
       +        my %h = @_;
       +        my $e = $ENV{VISUAL} || $ENV{EDITOR} || PROG_EDIT;
       +        return wait_or_not($h{wait}, $e, @{$h{args}}, @{$h{files}});
       +}
       +
       +sub stdin_to_editor
       +{
       +        my $tmp = "/tmp/stdin_$$";
       +
       +        open F, '>', $tmp or die "open $tmp: $!\n";
       +        print F $_ while <STDIN>;
       +        close F;
       +
       +        my %h = @_;
       +        push @{$h{files}}, $tmp;
       +        my $r = edit(%h);
       +        unlink $tmp;
       +        return $r;
       +}
       +
       +sub reveal
       +{
       +        my %h = @_;
       +        return wait_or_not($h{wait}, PROG_REVEAL, @{$h{args}}, @{$h{files}});
       +}
       +
       +sub header_edit
       +{
       +        my %h = @_;
       +        my @files = @{$h{files}};
       +        @{$h{files}} = ();
       +
       +        for my $name (@files){
       +                sub find_header
       +                {
       +                        my @inc = ("", "arpa", "net", "sys");
       +                        my $r = shift;
       +                        my @matches;
       +
       +                        for(my @tmp = @inc){
       +                                push @inc, "x86_64-linux-gnu/$_";
       +                        }
       +
       +                        for my $inc (@inc){
       +                                $inc = "/usr/include/$inc";
       +
       +                                opendir D, $inc or next;
       +                                push @matches, map { "$inc/$_" } grep /$r/, readdir D;
       +                                closedir D;
       +                        }
       +
       +                        return @matches;
       +                }
       +
       +                my @paths = find_header($name);
       +                push @{$h{files}}, @paths if @paths;
       +        }
       +
       +        return edit(%h);
       +}
   DIR diff --git a/p b/p
       t@@ -0,0 +1,16 @@
       +#!/bin/sh
       +
       +palemoon=/usr/bin/palemoon
       +profile="$1"
       +
       +ps ax | grep '[p]alemoon' > /dev/null
       +[[ $? = 0 ]] && {
       +    # one is already running, run next with -no-remote
       +    opts=" -no-remote "
       +}
       +case $profile in
       +    obi)          $palemoon ${opts} -P def;;
       +    soc)          $palemoon ${opts} -P soc;;
       +    profile*)     $palemoon -ProfileManager;;
       +    *)            $palemoon $*;;
       +esac
   DIR diff --git a/pacmans.sh b/pacmans.sh
       t@@ -0,0 +1,45 @@
       +#!/bin/sh
       +initializeANSI()
       +{
       + esc="$(echo -en '\e')"
       +
       +  blackf="${esc}[30m";   redf="${esc}[31m";    greenf="${esc}[32m"
       +  yellowf="${esc}[33m"   bluef="${esc}[34m";   purplef="${esc}[35m"
       +  cyanf="${esc}[36m";    whitef="${esc}[37m"
       +
       +  blackb="${esc}[40m";   redb="${esc}[41m";    greenb="${esc}[42m"
       +  yellowb="${esc}[43m"   blueb="${esc}[44m";   purpleb="${esc}[45m"
       +  cyanb="${esc}[46m";    whiteb="${esc}[47m"
       +
       +  boldon="${esc}[1m";    boldoff="${esc}[22m"
       +  italicson="${esc}[3m"; italicsoff="${esc}[23m"
       +  ulon="${esc}[4m";      uloff="${esc}[24m"
       +  invon="${esc}[7m";     invoff="${esc}[27m"
       +
       +  reset="${esc}[0m"
       +}
       +
       +# note in this first use that switching colors doesn't require a reset
       +# first - the new color overrides the old one.
       +
       +#clear
       +
       +initializeANSI
       +
       +cat << EOF
       +
       + ${yellowf}  ▄███████▄${reset}   ${redf}  ▄██████▄${reset}    ${greenf}  ▄██████▄${reset}    ${bluef}  ▄██████▄${reset}    ${purplef}  ▄██████▄${reset}    ${cyanf}  ▄██████▄${reset}
       + ${yellowf}▄█████████▀▀${reset}  ${redf}▄${whitef}█▀█${redf}██${whitef}█▀█${redf}██▄${reset}  ${greenf}▄${whitef}█▀█${greenf}██${whitef}█▀█${greenf}██▄${reset}  ${bluef}▄${whitef}█▀█${bluef}██${whitef}█▀█${bluef}██▄${reset}  ${purplef}▄${whitef}█▀█${purplef}██${whitef}█▀█${purplef}██▄${reset}  ${cyanf}▄${whitef}█▀█${cyanf}██${whitef}█▀█${cyanf}██▄${reset}
       + ${yellowf}███████▀${reset}      ${redf}█${whitef}▄▄█${redf}██${whitef}▄▄█${redf}███${reset}  ${greenf}█${whitef}▄▄█${greenf}██${whitef}▄▄█${greenf}███${reset}  ${bluef}█${whitef}▄▄█${bluef}██${whitef}▄▄█${bluef}███${reset}  ${purplef}█${whitef}▄▄█${purplef}██${whitef}▄▄█${purplef}███${reset}  ${cyanf}█${whitef}▄▄█${cyanf}██${whitef}▄▄█${cyanf}███${reset}
       + ${yellowf}███████▄${reset}      ${redf}████████████${reset}  ${greenf}████████████${reset}  ${bluef}████████████${reset}  ${purplef}████████████${reset}  ${cyanf}████████████${reset}
       + ${yellowf}▀█████████▄▄${reset}  ${redf}██▀██▀▀██▀██${reset}  ${greenf}██▀██▀▀██▀██${reset}  ${bluef}██▀██▀▀██▀██${reset}  ${purplef}██▀██▀▀██▀██${reset}  ${cyanf}██▀██▀▀██▀██${reset}
       + ${yellowf}  ▀███████▀${reset}   ${redf}▀   ▀  ▀   ▀${reset}  ${greenf}▀   ▀  ▀   ▀${reset}  ${bluef}▀   ▀  ▀   ▀${reset}  ${purplef}▀   ▀  ▀   ▀${reset}  ${cyanf}▀   ▀  ▀   ▀${reset}
       +
       + ${boldon}${yellowf}  ▄███████▄   ${redf}  ▄██████▄    ${greenf}  ▄██████▄    ${bluef}  ▄██████▄    ${purplef}  ▄██████▄    ${cyanf}  ▄██████▄${reset}
       + ${boldon}${yellowf}▄█████████▀▀  ${redf}▄${whitef}█▀█${redf}██${whitef}█▀█${redf}██▄  ${greenf}▄${whitef}█▀█${greenf}██${whitef}█▀█${greenf}██▄  ${bluef}▄${whitef}█▀█${bluef}██${whitef}█▀█${bluef}██▄  ${purplef}▄${whitef}█▀█${purplef}██${whitef}█▀█${purplef}██▄  ${cyanf}▄${whitef}█▀█${cyanf}██${whitef}█▀█${cyanf}██▄${reset}
       + ${boldon}${yellowf}███████▀      ${redf}█${whitef}▄▄█${redf}██${whitef}▄▄█${redf}███  ${greenf}█${whitef}▄▄█${greenf}██${whitef}▄▄█${greenf}███  ${bluef}█${whitef}▄▄█${bluef}██${whitef}▄▄█${bluef}███  ${purplef}█${whitef}▄▄█${purplef}██${whitef}▄▄█${purplef}███  ${cyanf}█${whitef}▄▄█${cyanf}██${whitef}▄▄█${cyanf}███${reset}
       + ${boldon}${yellowf}███████▄      ${redf}████████████  ${greenf}████████████  ${bluef}████████████  ${purplef}████████████  ${cyanf}████████████${reset}
       + ${boldon}${yellowf}▀█████████▄▄  ${redf}██▀██▀▀██▀██  ${greenf}██▀██▀▀██▀██  ${bluef}██▀██▀▀██▀██  ${purplef}██▀██▀▀██▀██  ${cyanf}██▀██▀▀██▀██${reset}
       + ${boldon}${yellowf}  ▀███████▀   ${redf}▀   ▀  ▀   ▀  ${greenf}▀   ▀  ▀   ▀  ${bluef}▀   ▀  ▀   ▀  ${purplef}▀   ▀  ▀   ▀  ${cyanf}▀   ▀  ▀   ▀${reset}
       +
       +EOF
   DIR diff --git a/pio b/pio
       t@@ -0,0 +1,3 @@
       +#!/bin/sh
       +
       +curl -sLT${1:--} https://p.iotek.org
   DIR diff --git a/pipesx b/pipesx
       t@@ -0,0 +1,193 @@
       +#!/bin/bash
       +# Animated pipes.sh terminal screensaver at an angle.
       +# Copyright (C) 2013, 2014 by Yu-Jie Lin
       +#
       +# Permission is hereby granted, free of charge, to any person obtaining a copy
       +# of this software and associated documentation files (the "Software"), to deal
       +# in the Software without restriction, including without limitation the rights
       +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       +# copies of the Software, and to permit persons to whom the Software is
       +# furnished to do so, subject to the following conditions:
       +#
       +# The above copyright notice and this permission notice shall be included in
       +# all copies or substantial portions of the Software.
       +#
       +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
       +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
       +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
       +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
       +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
       +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
       +# THE SOFTWARE.
       +#
       +# Website: https://github.com/livibetter/pipesX.sh
       +
       +VERSION=0.1.0
       +
       +W=$(tput cols) H=$(tput lines)
       +# maximal random value + 1
       +M=32768
       +
       +SETS=('╱╲' '/\')
       +COLORS=(31 32 33 34 35 36 37)
       +
       +# default values
       +N=1
       +T=()
       +I=0.05
       +P=25
       +R=$((W * H / 4))
       +
       +HELP="Usage: $(basename $0) [OPTIONS]
       +Animated pipes.sh terminal screensaver at an angle.
       +
       +Options:
       +
       +  -n [1-]     number of pipes. (Default: $N)
       +  -t [0-$((${#SETS[@]} - 1))]    types of pipes, can be used more than once. (Default: $T)
       +  -i [float]  piping interval or maze generation interval. (Default: $I)
       +  -P [0-100]  probability of a turning pipe or of \\ in maze generation. (Default: $P)
       +  -r [LIMIT]  reset after x characters, 0 if no limit. (Default: $R)
       +  -R          random starting point.
       +  -C          no color.
       +  -X          maze generation.
       +  -h          this help message.
       +  -v          print version number.
       +"
       +
       +while getopts "n:t:i:P:r:RCXhv" arg; do
       +  case $arg in
       +    n)
       +      ((N = OPTARG > 0 ? OPTARG : N))
       +      ;;
       +    t)
       +      T+=($(((OPTARG >= 0 && OPTARG < ${#SETS[@]}) ? OPTARG : T)))
       +      ;;
       +    i)
       +      I=$OPTARG
       +      ;;
       +    P)
       +      ((P = (OPTARG >= 0 && OPTARG <= 100) ? OPTARG : P))
       +      ;;
       +    r)
       +      ((R = OPTARG >= 0 ? OPTARG : R))
       +      ;;
       +    R)
       +      RNDSTART=1
       +      ;;
       +    C)
       +      NOCOLOR=1
       +      ;;
       +    X)
       +      MAZE=1
       +      ;;
       +    h)
       +      echo -e "$HELP"
       +      exit 0
       +      ;;
       +    v)
       +      echo "$(basename -- "$0") $VERSION"
       +      exit 0
       +  esac
       +done
       +
       +# set to default values if not by options
       +((${#T[@]})) || T=(0)
       +
       +do_exit() {
       +  # Show cursor and echo stdin
       +  echo -ne "\e[?25h"
       +  stty echo
       +  clear
       +  exit 0
       +  }
       +trap do_exit INT TERM
       +
       +# No echo stdin and hide the cursor
       +stty -echo
       +echo -ne "\e[?25l"
       +
       +# maze geneartion
       +while [[ $MAZE ]] && clear; do
       +  [[ $NOCOLOR ]] || echo -ne "\e[1;${COLORS[${#COLORS[@]} * RANDOM / M]}m"
       +  for ((i = 0; i < W * H; i++ )); do
       +    echo -ne ${SETS[T]:100 * RANDOM / M < P:1}
       +  done
       +  read -t $I -n 1 && [[ $REPLY =~ q|Q ]] && do_exit
       +done
       +
       +# initialze values
       +for ((n = 0; n < N; n++)); do
       +  ((X[n] = RNDSTART ? (W + 2) * RANDOM / M : W / 2))
       +  ((Y[n] = RNDSTART ? (H + 2) * RANDOM / M : H / 2))
       +  D[n]=$((4 * RANDOM / M))
       +  C[n]=${COLORS[${#COLORS[@]} * RANDOM / M]}
       +  t[n]=${T[${#T[@]} * RANDOM / M]}
       +done
       +
       +clear
       +while :; do
       +  for ((n = 0; n < N; n++, CC = 0)); do
       +    x=${X[n]} y=${Y[n]}
       +    d=${D[n]} c=${C[n]}
       +
       +    # calculate new direction `d`
       +    # 1  0
       +    #  \/  4 directions 0 to 3
       +    #  /\
       +    # 2  3
       +    # valid directions: d: dd', d' is the new direction
       +    # d
       +    # 0:  / 00 \  01          03
       +    #    /     /           /\
       +    # 1:  / 10 \  11    12
       +    #     \     \    /\
       +    # 2:       \/ 21  / 22  / 23
       +    #                /      \
       +    # 3: \/ 30       \  32 \  33
       +    #                /      \
       +    ((d = (100 * RANDOM / M) < P ? ((d + 1) + 2 * (RANDOM % 2)) % 4 : d))
       +    ((e = (d + 1) % 4))
       +
       +    # calculate new position
       +    # d'  x'  y'
       +    # 0: x+1 y-1
       +    # 1: x-1 y-1
       +    # 2: x-1 y+1
       +    # 3: x+1 y+1
       +    ((xn = e < 2 ? x + 1 : x - 1))
       +    ((yn = d < 2 ? y - 1 : y + 1))
       +    
       +    # adjust position and change color?
       +    ((d < 2 && y == 0)) && ((yn--, CC=1))
       +    ((e > 1 && x == 0)) && ((xn--, CC=1))
       +    ((d > 1 && y == H)) && ((yn++, CC=1))
       +    ((e < 2 && x == W)) && ((xn++, CC=1))
       +    ((CC)) && c=${COLORS[${#COLORS[@]} * RANDOM / M]}
       +    ((CC)) && t[n]=${T[${#T[@]} * RANDOM / M]}
       +
       +    # warp pipe
       +    ((xn = (xn + W + 1) % (W + 1)))
       +    ((yn = (yn + H + 1) % (H + 1)))
       +
       +    # calculate position in terminal
       +    # d'  xt   yt
       +    # 0: x'   y'+1
       +    # 1: x'+1 y'+1
       +    # 2: x'+1 y'
       +    # 3: x'   y'
       +    ((xt = e < 2 ? xn : xn + 1))
       +    ((yt = d < 2 ? yn + 1 : yn))
       +
       +    echo -ne "\e[${yt};${xt}H"
       +    [[ $NOCOLOR ]] || echo -ne "\e[1;${c}m"
       +    echo -n "${SETS[t[n]]:d%2:1}"
       +
       +    X[n]=$xn Y[n]=$yn
       +    D[n]=$d C[n]=$c
       +  done
       +  read -t $I -n 1 && [[ $REPLY =~ q|Q ]] && do_exit
       +  ((R)) && ((r += N, r >= R)) && r=0 && clear
       +done
       +
       +do_exit
       +\ No newline at end of file
   DIR diff --git a/popup b/popup
       t@@ -0,0 +1,5 @@
       +#!/bin/sh
       +
       +duration=3
       +
       +(echo " $@"; sleep ${duration}) | lemonbar -g '120x20+10+10' -B '#ff333333' -n 'popuplemonbar'
   DIR diff --git a/powertoptune.sh b/powertoptune.sh
       t@@ -0,0 +1,34 @@
       +#!/bin/sh
       +echo '1500' > '/proc/sys/vm/dirty_writeback_centisecs';
       +echo 'auto' > '/sys/bus/i2c/devices/i2c-0/device/power/control';
       +echo 'auto' > '/sys/bus/usb/devices/1-1.3/power/control';
       +echo 'auto' > '/sys/bus/usb/devices/2-1.3/power/control';
       +echo 'auto' > '/sys/bus/i2c/devices/i2c-3/device/power/control';
       +echo 'auto' > '/sys/bus/i2c/devices/i2c-5/device/power/control';
       +echo 'auto' > '/sys/bus/i2c/devices/i2c-1/device/power/control';
       +echo 'auto' > '/sys/bus/i2c/devices/i2c-2/device/power/control';
       +echo 'auto' > '/sys/bus/i2c/devices/i2c-4/device/power/control';
       +echo 'auto' > '/sys/bus/i2c/devices/i2c-6/device/power/control';
       +echo 'auto' > '/sys/bus/i2c/devices/i2c-7/device/power/control';
       +echo 'auto' > '/sys/bus/pci/devices/0000:00:1d.0/power/control';
       +echo 'auto' > '/sys/bus/pci/devices/0000:00:1c.3/power/control';
       +echo 'auto' > '/sys/bus/pci/devices/0000:00:1c.4/power/control';
       +echo 'auto' > '/sys/bus/pci/devices/0000:00:1c.0/power/control';
       +echo 'auto' > '/sys/bus/pci/devices/0000:00:1b.0/power/control';
       +echo 'auto' > '/sys/bus/pci/devices/0000:00:1a.0/power/control';
       +echo 'auto' > '/sys/bus/pci/devices/0000:00:19.0/power/control';
       +echo 'auto' > '/sys/bus/pci/devices/0000:00:16.0/power/control';
       +echo 'auto' > '/sys/bus/pci/devices/0000:00:1f.0/power/control';
       +echo 'auto' > '/sys/bus/pci/devices/0000:00:02.0/power/control';
       +echo 'auto' > '/sys/bus/pci/devices/0000:ff:00.0/power/control';
       +echo 'auto' > '/sys/bus/pci/devices/0000:00:1f.2/power/control';
       +echo 'auto' > '/sys/bus/pci/devices/0000:00:00.0/power/control';
       +echo 'auto' > '/sys/bus/pci/devices/0000:ff:02.1/power/control';
       +echo 'auto' > '/sys/bus/pci/devices/0000:ff:02.3/power/control';
       +echo 'auto' > '/sys/bus/pci/devices/0000:ff:02.2/power/control';
       +echo 'auto' > '/sys/bus/pci/devices/0000:ff:02.0/power/control';
       +echo 'auto' > '/sys/bus/pci/devices/0000:ff:00.1/power/control';
       +echo 'auto' > '/sys/bus/pci/devices/0000:02:00.0/power/control';
       +echo 'auto' > '/sys/bus/pci/devices/0000:00:1f.3/power/control';
       +echo 'auto' > '/sys/bus/pci/devices/0000:00:1f.6/power/control';
       +echo 'auto' > '/sys/bus/pci/devices/0000:00:1e.0/power/control';
   DIR diff --git a/rain b/rain
       t@@ -0,0 +1,100 @@
       +#!/bin/bash
       +RAINS=("|" "│" "┃" "┆" "┇" "┊" "┋" "╽" "╿")
       +COLORS=("\e[37m" "\e[37;1m")
       +# More from 256 color mode
       +for i in {244..255}; do
       +  COLORS=("${COLORS[@]}" "\e[38;5;${i}m")
       +done
       +NRAINS=${#RAINS[@]}
       +NCOLORS=${#COLORS[@]}
       +NUM_RAIN_METADATA=5
       +
       +
       +sigwinch() {
       +  TERM_WIDTH=$(tput cols)
       +  TERM_HEIGHT=$(tput lines)
       +  STEP_DURATION=0.025
       +  ((MAX_RAINS = TERM_WIDTH * TERM_HEIGHT / 4))
       +  ((MAX_RAIN_LENGTH = TERM_HEIGHT < 10 ? 1 : TERM_HEIGHT / 10))
       +  # In percentage
       +  ((NEW_RAIN_ODD = TERM_HEIGHT > 50 ? 100 : TERM_HEIGHT * 2))
       +  ((NEW_RAIN_ODD = NEW_RAIN_ODD * 75 / 100))
       +  ((FALLING_ODD = TERM_HEIGHT > 25 ? 100 : TERM_HEIGHT * 4))
       +  ((FALLING_ODD = FALLING_ODD * 90 / 100))
       +  }
       +
       +do_exit() {
       +  echo -ne "\e[${TERM_HEIGHT};1H\e[0K"
       +
       +  # Show cursor and echo stdin
       +  echo -ne "\e[?25h"
       +  stty echo
       +  exit 0
       +  }
       +
       +do_render() {
       +  # Clean screen first
       +  for ((idx = 0; idx < num_rains * NUM_RAIN_METADATA; idx += NUM_RAIN_METADATA)); do
       +    X=${rains[idx]}
       +    Y=${rains[idx + 1]}
       +    LENGTH=${rains[idx + 4]}
       +    for ((y = Y; y < Y + LENGTH; y++)); do
       +      (( y < 1 || y > TERM_HEIGHT )) && continue
       +      echo -ne "\e[${y};${X}H "
       +    done
       +  done
       +
       +  for ((idx = 0; idx < num_rains * NUM_RAIN_METADATA; idx += NUM_RAIN_METADATA)); do
       +    if ((100 * RANDOM / 32768 < FALLING_ODD)); then
       +      # Falling
       +      if ((++rains[idx + 1] > TERM_HEIGHT)); then
       +        # Out of screen, bye sweet <3
       +        rains=("${rains[@]:0:idx}"
       +               "${rains[@]:idx+NUM_RAIN_METADATA:num_rains*NUM_RAIN_METADATA}")
       +        ((num_rains--))
       +        continue
       +      fi
       +    fi
       +    X=${rains[idx]}
       +    Y=${rains[idx + 1]}
       +    RAIN=${rains[idx + 2]}
       +    COLOR=${rains[idx + 3]}
       +    LENGTH=${rains[idx + 4]}
       +    for ((y = Y; y < Y + LENGTH; y++)); do
       +      (( y < 1 || y > TERM_HEIGHT )) && continue
       +      echo -ne "\e[${y};${X}H${COLOR}${RAIN}"
       +    done
       +  done
       +  }
       +
       +trap do_exit TERM INT
       +trap sigwinch WINCH
       +# no echo stdin and hide the cursor
       +stty -echo
       +echo -ne "\e[?25l"
       +
       +echo -ne "\e[2J"
       +rains=()
       +sigwinch
       +while :; do
       +  read -n 1 -t $STEP_DURATION ch
       +  case "$ch" in
       +    q|Q)
       +      do_exit
       +      ;;
       +  esac
       +
       +  if ((num_rains < MAX_RAINS)) && ((100 * RANDOM / 32768 < NEW_RAIN_ODD)); then
       +    # Need new |, 1-based
       +    RAIN="${RAINS[NRAINS * RANDOM / 32768]}"
       +    COLOR="${COLORS[NCOLORS * RANDOM / 32768]}"
       +    LENGTH=$((MAX_RAIN_LENGTH * RANDOM / 32768 + 1))
       +    X=$((TERM_WIDTH * RANDOM / 32768 + 1))
       +    Y=$((1 - LENGTH))
       +    rains=("${rains[@]}" "$X" "$Y" "$RAIN" "$COLOR" "$LENGTH")
       +    ((num_rains++))
       +  fi
       +
       +  # let rain fall!
       +  do_render
       +done
   DIR diff --git a/rainbow b/rainbow
       t@@ -0,0 +1,15 @@
       +#!/bin/sh
       +#
       +# z3bra - 2015 (c) wtfpl
       +# make the current window "rainbowish"... Awesome idea from xero@nixers.net !
       +
       +FREQ=${FREQ:-0.1}
       +COLORS="888888 8064cc 6480cc 64cccc 80cc64 cccc64 cc6464"
       +CUR=$(pfw)
       +
       +while :; do
       +    for c in $COLORS; do
       +        chwb -c $c $(pfw)
       +        sleep $FREQ
       +    done
       +done
   DIR diff --git a/randcolor b/randcolor
       t@@ -0,0 +1,9 @@
       +#!/bin/sh
       +#
       +# parazyd - (c) wtfpl 2016
       +# print a random terminal colorscheme
       +
       +for i in `seq 0 15`; do
       +    c=$(tr -cd "0-9a-f" < /dev/urandom | fold -bw 6 | sed 1q)
       +    printf "*color%d: #%s\n" "$i" "$c"
       +done
   DIR diff --git a/record b/record
       t@@ -0,0 +1,23 @@
       +#!/bin/sh
       +#
       +# parazyd - (c) wtfpl 2016
       +# screencast time
       +
       +PIDNAME=recorder
       +FRAMERATE=25
       +RES=$(wattr wh `lsw -r` | tr \  x)
       +
       +usage() {
       +        echo "usage: $(basename $0) [-fk] <filename>" >&2
       +        exit 1
       +}
       +
       +case $1 in
       +        -f) FRAMERATE=50; shift 1 ;;
       +        -k) kill $(pidof -s $PIDNAME); exit 0 ;;
       +esac
       +
       +test -n "$1" && WEBM=$1 || usage
       +
       +echo Framerate: $FRAMERATE
       +exec -a $PIDNAME ffmpeg -f x11grab -s $RES -an -r $FRAMERATE -i :0.0 -c:v libvpx -b:v 5M -crf 10 -quality realtime -y -loglevel quiet $1
   DIR diff --git a/refan b/refan
       t@@ -0,0 +1,2 @@
       +#!/bin/sh
       +/etc/init.d/thinkfan restart
   DIR diff --git a/retor b/retor
       t@@ -0,0 +1,2 @@
       +#!/bin/sh
       +/etc/init.d/tor restart
   DIR diff --git a/rot13 b/rot13
       t@@ -0,0 +1,3 @@
       +#!/bin/sh
       +
       +tr 'A-Za-z' 'N-ZA-Mn-za-m'
   DIR diff --git a/signrelease b/signrelease
       t@@ -0,0 +1,55 @@
       +#!/bin/zsh
       +#
       +# shasum and sign release
       +
       +KEY=B876CB44FA1B0274
       +SUM=sha256sum
       +
       +{ test -r "$1" } || { print "usage: signrelease [directory|tarball]"; return 0 }
       +
       +target="$1"
       +
       +{ test -d "$target" } && {
       +
       +    pushd "$target"
       +    for i in README.md INSTALL.md ChangeLog.md AUTHORS.md KNOWN_BUGS.md TODO.md; do
       +        { test -r $i } && {
       +            print "converting $i to .txt"
       +            mv $i ${i%%.md}.txt }
       +        # cat $i | markdown > ${i%%.md}.html
       +    done
       +    for i in COPYING LICENSE TODO README INSTALL ChangeLog AUTHORS KNOWN_BUGS; do
       +        [[ -r $i ]] && {
       +            print "converting $i to .txt"
       +            mv $i ${i}.txt
       +        }
       +    done
       +
       +    # remove git dirs
       +    { test -r .gitignore } && { rm -f .gitignore }
       +    { test -d .git } && { rm -rf .git }
       +
       +    # generate configure
       +    [[ -r configure.in ]] && autoreconf -i
       +    [[ -r configure.ac ]] && autoreconf -i
       +
       +    # remove configure artifacts
       +    [[ -r autom4te.cache ]] && rm -rf autom4te.cache
       +
       +    popd
       +
       +    print "packing tarball from dir $target"
       +    tar cfz ${target}.tar.gz ${target}
       +    target="$1.tar.gz"
       +}
       +
       +{ test -r "$target" } && {
       +    print "making checksum of $target"
       +    ${=SUM} "$target" > "$target.sha"
       +    print "signing tarball with GnuPG key id $KEY"
       +    gpg -b -a -u $KEY "$target"
       +}
       +
       +print "Release done:"
       +ls -lh ${target}
       +cat ${target}.sha
   DIR diff --git a/skrot b/skrot
       t@@ -0,0 +1,7 @@
       +#!/bin/sh
       +
       +if [ $1 == "-s" ]; then
       +    scrot -s '%Y-%m-%d_%H-%M-%S_$wx$h.png' -e 'mv $f ~/screenshots/'
       +else
       +    scrot '%Y-%m-%d_%H-%M-%S_$wx$h.png' -e 'mv $f ~/screenshots/'
       +fi
   DIR diff --git a/square b/square
       t@@ -0,0 +1,8 @@
       +#!/bin/sh
       +
       +CHAR=${1:-██}
       +
       +echo
       +for i in `seq 0 7`; do printf " [0;3${i}m${CHAR}"; done; echo
       +for i in `seq 0 7`; do printf " [1;3${i}m${CHAR}"; done; echo
       +echo
   DIR diff --git a/sslget b/sslget
       t@@ -0,0 +1,12 @@
       +#!/bin/sh
       +#
       +# retrieve SSL certificate of a website
       +# it assumes 443 to be the default SSL port
       +
       +if [[ -n $2 ]]; then
       +        portnum=$2
       +else
       +        portnum=443
       +fi
       +
       +echo | openssl s_client -connect $1:$portnum 2>&1| sed '/BEGIN CERT/,/END CERT/p;d'
   DIR diff --git a/startdwm b/startdwm
       t@@ -0,0 +1,8 @@
       +#!/bin/sh
       +
       +while true; do
       +        # Log stderror to a file
       +        dwm 2> ~/.dwm.log
       +        # No error logging
       +        #dwm >/dev/null 2>&1
       +done
   DIR diff --git a/supadd b/supadd
       t@@ -0,0 +1,75 @@
       +#!/bin/sh
       +#
       +# parazyd - (c) wtfpl 2016
       +# edit sup's bins
       +
       +supsrc="/home/parazyd/src/INSTALLED/sup"
       +
       +printsettings() {
       +        cat <<EOF
       +/* sup's configuration file */
       +
       +/* (un)comment flags below to remove functionalities */
       +#define HASH 1
       +#define DAEMON 0
       +/* #define DEBUG 0 */
       +
       +#ifndef FLAGSONLY
       +
       +#define USER 1000
       +#define GROUP -1
       +
       +#define SETUID 0
       +#define SETGID 0
       +
       +#define CHROOT ""
       +#define CHRDIR ""
       +
       +static struct rule_t rules[] = {
       +        /* allow user to run these programs when found in path location */
       +EOF
       +}
       +
       +printentry() {
       +        cat <<EOF
       +        { USER, GROUP, "$bin", "$binpath", "$shasum" },
       +EOF
       +}
       +
       +printrest() {
       +        cat <<EOF
       +
       +        { 0 },
       +};
       +
       +#endif
       +EOF
       +}
       +
       +getsha() {
       +        shasum=`sha256sum $binpath | awk '{print $1}'`
       +        [[ -n $shasum ]] || exit 1
       +}
       +case $1 in
       +        -l) grep -v -i -e '//' -e '^#' $supsrc/allowed.txt ;;
       +        *)
       +                binpath="$1"
       +                bin=`echo $binpath | awk -F"/" '{print $NF}'`
       +                if ! [[ $binpath == /* ]]; then
       +                        binpath=`pwd`/$bin
       +                fi
       +                getsha || exit 1
       +
       +                if [[ `grep $binpath $supsrc/allowed.txt` ]]; then
       +                        grep -v $binpath $supsrc/allowed.txt > /tmp/allowed.txt
       +                        mv /tmp/allowed.txt $supsrc/allowed.txt
       +                fi
       +                printentry >> $supsrc/allowed.txt
       +                printsettings | cat - $supsrc/allowed.txt > $supsrc/config.h
       +                printrest >> $supsrc/config.h
       +
       +                `basename $0` -l
       +                ;;
       +esac
       +
       +cd $supsrc
   DIR diff --git a/susp b/susp
       t@@ -0,0 +1,2 @@
       +#!/bin/sh
       +echo mem > /sys/power/state
   DIR diff --git a/takeoffdir b/takeoffdir
       t@@ -0,0 +1,10 @@
       +#!/bin/sh
       +
       +TAKEOFF_DIR=/tmp/takeoff
       +
       +mkdir -p $TAKEOFF_DIR
       +
       +# file either created or modified
       +wendy -m 136 -f $TAKEOFF_DIR -v | while read ev file; do
       +    $HOME/bin/autoup "$file"
       +done
   DIR diff --git a/testssl.sh b/testssl.sh
       t@@ -0,0 +1,4892 @@
       +#!/usr/bin/env bash
       +#
       +# vim:ts=5:sw=5
       +# use vim and you will see everything beautifully indented with a 5 char tab
       +
       +[ -z "$BASH_VERSINFO" ] && printf "\n\033[1;35m Please make sure you're using \"bash\"! Bye...\033[m\n\n" >&2 && exit 245 
       +[ $(kill -l | grep -c SIG) -eq 0 ] && printf "\n\033[1;35m Please make sure you're calling me without leading \"sh\"! Bye...\033[m\n\n"  >&2 && exit 245
       +
       +# testssl.sh is a program for spotting weak SSL encryption, ciphers, version and some
       +# vulnerabilities or features
       +#
       +# Devel version is available from    https://github.com/drwetter/testssl.sh
       +# Stable version from                https://testssl.sh
       +# Please file bugs at github!        https://github.com/drwetter/testssl.sh/issues
       +
       +# Main author: Dirk Wetter, copyleft: 2007-today, contributions so far see CREDIT.md
       +#
       +# 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. Do not violate the license!
       +#
       +# USAGE WITHOUT ANY WARRANTY, THE SOFTWARE IS PROVIDED "AS IS". USE IT AT
       +# your OWN RISK!
       +
       +# HISTORY: 
       +# Back in 2006 it all started with a few openssl commands...
       +# That's because openssl is a such a good swiss army knife (see e.g.  
       +# wiki.openssl.org/index.php/Command_Line_Utilities) that it was difficult to resist 
       +# wrapping some shell commands around it, which I used for my pen tests. This is how 
       +# everything started.
       +# Now it has grown up, it has bash socket support for some features which basically replacing
       +# more and more functions of OpenSSL and will serve as some kind of library in the future.
       +# The socket checks in bash may sound cool and unique -- they are -- but probably you
       +# can achieve e.g. the same result with my favorite interactive shell: zsh (zmodload zsh/net/socket
       +# -- checkout zsh/net/tcp) too! 
       +# /bin/bash though is way more often used within Linux and it's perfect
       +# for cross platform support, see MacOS X and also under Windows the MSYS2 extension or Cygwin.
       +# Cross-platform is one of the three main goals of this script. Second: Ease of installation.
       +# No compiling, install gems, go to CPAN, use pip etc. Third: Easy to use and to interpret
       +# the results.
       +
       +# Did I mention it's open source?
       +
       +# Q: So what's the difference to www.ssllabs.com/ssltest/ or sslcheck.globalsign.com/ ?
       +# A: As of now ssllabs only check 1) webservers 2) on standard ports, 3) reachable from the
       +#    internet. And those examples above 4) are 3rd parties. If these restrictions are all fine
       +#    with you and you need a management compatible rating -- go ahead and use those.
       +
       +# But also if your fine with those restrictions: testssl.sh is meant as a tool in your hand 
       +# and it's way more flexible.        
       +#
       +# Oh, and did I mention testssl.sh is open source?
       +
       +# Note that up to today there were a lot changes for "standard" openssl
       +# binaries: a lot of features (ciphers, protocols, vulnerabilities)
       +# are disabled as they'll impact security otherwise. For security
       +# testing though we need  all broken features. testssl.sh will
       +# over time replace those checks with bash sockets -- however it's
       +# still recommended to use the supplied binaries or cook your own, see 
       +# https://github.com/drwetter/testssl.sh/blob/master/bin/Readme.md .
       +# Don't worry if feature X is not available you'll get a warning about
       +# this missing feature!  The idea is if this script can't tell something
       +# for sure it speaks up so that you have clear picture.
       +
       +
       +# debugging help:
       +readonly PS4='${LINENO}> ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
       +
       +# make sure that temporary files are cleaned up after use in ANY case
       +trap "cleanup" QUIT EXIT
       +
       +readonly VERSION="2.6"
       +readonly SWCONTACT="dirk aet testssl dot sh"
       +egrep -q "dev|rc" <<< "$VERSION" && \
       +        SWURL="https://testssl.sh/dev/" ||
       +        SWURL="https://testssl.sh/    "
       +
       +readonly PROG_NAME=$(basename "$0")
       +readonly RUN_DIR=$(dirname "$0")
       +INSTALL_DIR=""
       +MAPPING_FILE_RFC=""
       +
       +which git &>/dev/null && readonly GIT_REL=$(git log --format='%h %ci' -1 2>/dev/null | awk '{ print $1" "$2" "$3 }')
       +readonly CVS_REL=$(tail -5 "$0" | awk '/dirkw Exp/ { print $4" "$5" "$6}')
       +readonly CVS_REL_SHORT=$(tail -5 "$0" | awk '/dirkw Exp/ { print $4 }')
       +readonly SYSTEM=$(uname -s)                        
       +date --help >/dev/null 2>&1 && \
       +        readonly HAS_GNUDATE=true || \
       +        readonly HAS_GNUDATE=false
       +echo A | sed -E 's/A//' >/dev/null 2>&1 && \
       +        readonly HAS_SED_E=true || \
       +        readonly HAS_SED_E=false 
       +TERM_DWITH=${COLUMNS:-$(tput cols)}         # for future custom line wrapping
       +TERM_CURRPOS=0                                                # ^^^ we also need to find out the length or current pos in the line
       +
       +
       +# following variables make use of $ENV, e.g. OPENSSL=<myprivate_path_to_openssl> ./testssl.sh <host>
       +# 0 means (normally) true here. Some of the variables are also accessible with a command line switch
       +
       +declare -x OPENSSL
       +COLOR=${COLOR:-2}                                        # 2: Full color, 1: b/w+positioning, 0: no ESC at all
       +SHOW_EACH_C=${SHOW_EACH_C:-0}                        # where individual ciphers are tested show just the positively ones tested #FIXME: upside down value
       +SNEAKY=${SNEAKY:-false}                                # is the referer and useragent we leave behind just usual? 
       +QUIET=${QUIET:-false}                                # don't output the banner. By doing this yiu acknowledge usage term appearing in the banner
       +SSL_NATIVE=${SSL_NATIVE:-false}                # we do per default bash sockets where possible "true": switch back to "openssl native"
       +ASSUMING_HTTP=${ASSUMING_HTTP:-false}        # in seldom cases (WAF, old servers, grumpy SSL) service detection fails. "True" enforces HTTP checks
       +DEBUG=${DEBUG:-0}                                        # 1.: the temp files won't be erased. 
       +                                                                # 2: list more what's going on (formerly: eq VERBOSE=1, VERBERR=true), lists some errors of connections
       +                                                                # 3: slight hexdumps + other info, 
       +                                                                # 4: display bytes sent via sockets, 5: display bytes received via sockets, 6: whole 9 yards
       +WIDE=${WIDE:-false}                                        # whether to display for some options the cipher or the table with hexcode/KX,Enc,strength etc.
       +HEADER_MAXSLEEP=${HEADER_MAXSLEEP:-5}        # we wait this long before killing the process to retrieve a service banner / http header
       +readonly MAX_WAITSOCK=10                                # waiting at max 10 seconds for socket reply
       +readonly CCS_MAX_WAITSOCK=5                        # for the two CCS payload (each)
       +readonly HEARTBLEED_MAX_WAITSOCK=8                # for the heartbleed payload
       +STARTTLS_SLEEP=${STARTTLS_SLEEP:-1}        # max time to wait on a socket replay for STARTTLS
       +FAST_STARTTLS=${FAST_STARTTLS:-true}        #at the cost of reliabilty decrease the handshakes for STARTTLS
       +USLEEP_SND=${USLEEP_SND:-0.1}                        # sleep time for general socket send
       +USLEEP_REC=${USLEEP_REC:-0.2}                 # sleep time for general socket receive
       +
       +CAPATH="${CAPATH:-/etc/ssl/certs/}"        # Does nothing yet (FC has only a CA bundle per default, ==> openssl version -d)
       +FNAME=${FNAME:-""}                                        # file name to read commands from
       +IKNOW_FNAME=false
       +HSTS_MIN=${HSTS_MIN:-179}               # >179 days is ok for HSTS
       +HPKP_MIN=${HPKP_MIN:-30}                # >=30 days should be ok for HPKP_MIN, practical hints?
       +readonly CLIENT_MIN_PFS=5                        # number of ciphers needed to run a test for PFS
       +DAYS2WARN1=${DAYS2WARN1:-60}            # days to warn before cert expires, threshold 1
       +DAYS2WARN2=${DAYS2WARN2:-30}            # days to warn before cert expires, threshold 2
       +
       +# further vars needed to follow
       +readonly NPN_PROTOs="spdy/4a2,spdy/3,spdy/3.1,spdy/2,spdy/1,http/1.1"
       +TEMPDIR=""
       +TMPFILE=""
       +ERRFILE=""
       +HOSTCERT=""
       +HEADERFILE=""
       +HEADERFILE_BREACH=""
       +LOGFILE=""
       +PROTOS_OFFERED=""
       +DETECTED_TLS_VERSION=""
       +SOCKREPLY=""
       +SOCK_REPLY_FILE=""
       +HEXC=""
       +NW_STR=""
       +LEN_STR=""
       +SNI=""
       +OSSL_VER=""                                                # openssl version, will be auto-determined
       +OSSL_VER_MAJOR=0
       +OSSL_VER_MINOR=0
       +OSSL_VER_APPENDIX="none"
       +HAS_DH_BITS=true
       +HAS_SSL2=true                                                #TODO: in the future we'll do the fastest possible test (openssl s_client -ssl2 is currently faster than sockets)
       +HAS_SSL3=true
       +PORT=443                                                        # unless otherwise auto-determined, see below
       +NODE=""
       +NODEIP=""
       +IPADDRs=""
       +IP46ADDRs=""
       +LOCAL_A=false                                                # does the $NODEIP ceom from /etc/hosts?
       +LOCAL_AAAA=false                                        # does the IPv6 IP come from /etc/hosts?
       +XMPP_HOST=""
       +PROXY=""
       +PROXYIP=""
       +PROXYPORT=""
       +VULN_COUNT=0
       +readonly VULN_THRESHLD=1                                # if bigger than this no we show a separate header in blue
       +IPS=""
       +SERVICE=""                                                # is the server running an HTTP server, SMTP, POP or IMAP?
       +URI=""
       +STARTTLS_PROTOCOL=""
       +OPTIMAL_PROTO=""                                        # we need this for IIS6 (sigh) and OpenSSL 1.02, otherwise some handshakes
       +                                                                # will fail, see https://github.com/PeterMosmans/openssl/issues/19#issuecomment-100897892
       +STARTTLS_OPTIMAL_PROTO=""                        # same for STARTTLS, see https://github.com/drwetter/testssl.sh/issues/188
       +TLS_TIME=""
       +TLS_NOW=""
       +HTTP_TIME=""
       +GET_REQ11=""
       +HEAD_REQ10=""
       +readonly UA_SNEAKY="Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"
       +readonly UA_STD="Mozilla/5.0 (X11; Linux x86_64; rv:42.0) Gecko/19700101 Firefox/42.0"
       +
       +# Devel stuff, see -q below
       +TLS_LOW_BYTE=""
       +HEX_CIPHER=""
       +
       +                                                                        # The various hexdump commands we need to replace xxd (BSD compatibility))
       +HEXDUMPVIEW=(hexdump -C)                                 # This is used in verbose mode to see what's going on
       +HEXDUMP=(hexdump -ve '16/1 "%02x " " \n"')         # This is used to analyze the reply
       +HEXDUMPPLAIN=(hexdump -ve '1/1 "%.2x"')         # Replaces both xxd -p and tr -cd '[:print:]'
       +
       +
       +
       +###### some hexbytes for bash network sockets follow ######
       +
       +# 133 standard cipher + 4x GOST for TLS 1.2 and SPDY/NPN
       +readonly TLS12_CIPHER="
       +cc,14, cc,13, cc,15, c0,30, c0,2c, c0,28, c0,24, c0,14,
       +c0,0a, c0,22, c0,21, c0,20, 00,a5, 00,a3, 00,a1, 00,9f,
       +00,6b, 00,6a, 00,69, 00,68, 00,39, 00,38, 00,37, 00,36, 00,80, 00,81, 00,82, 00,83,
       +c0,77, c0,73, 00,c4, 00,c3, 00,c2, 00,c1, 00,88, 00,87,
       +00,86, 00,85, c0,32, c0,2e, c0,2a, c0,26, c0,0f, c0,05,
       +c0,79, c0,75, 00,9d, 00,3d, 00,35, 00,c0, 00,84, c0,2f,
       +c0,2b, c0,27, c0,23, c0,13, c0,09, c0,1f, c0,1e, c0,1d,
       +00,a4, 00,a2, 00,a0, 00,9e, 00,67, 00,40, 00,3f, 00,3e,
       +00,33, 00,32, 00,31, 00,30, c0,76, c0,72, 00,be, 00,bd,
       +00,bc, 00,bb, 00,9a, 00,99, 00,98, 00,97, 00,45, 00,44,
       +00,43, 00,42, c0,31, c0,2d, c0,29, c0,25, c0,0e, c0,04,
       +c0,78, c0,74, 00,9c, 00,3c, 00,2f, 00,ba, 00,96, 00,41,
       +00,07, c0,11, c0,07, 00,66, c0,0c, c0,02, 00,05, 00,04,
       +c0,12, c0,08, c0,1c, c0,1b, c0,1a, 00,16, 00,13, 00,10,
       +00,0d, c0,0d, c0,03, 00,0a, 00,63, 00,15, 00,12, 00,0f,
       +00,0c, 00,62, 00,09, 00,65, 00,64, 00,14, 00,11, 00,0e,
       +00,0b, 00,08, 00,06, 00,03, 00,ff"
       +
       +# 76 standard cipher +4x GOST for SSLv3, TLS 1, TLS 1.1
       +readonly TLS_CIPHER="
       +c0,14, c0,0a, c0,22, c0,21, c0,20, 00,39, 00,38, 00,37,
       +00,36, 00,88, 00,87, 00,86, 00,85, c0,0f, c0,05, 00,35,
       +00,84, c0,13, c0,09, c0,1f, c0,1e, c0,1d, 00,33, 00,32, 00,80, 00,81, 00,82, 00,83,
       +00,31, 00,30, 00,9a, 00,99, 00,98, 00,97, 00,45, 00,44,
       +00,43, 00,42, c0,0e, c0,04, 00,2f, 00,96, 00,41, 00,07,
       +c0,11, c0,07, 00,66, c0,0c, c0,02, 00,05, 00,04, c0,12,
       +c0,08, c0,1c, c0,1b, c0,1a, 00,16, 00,13, 00,10, 00,0d,
       +c0,0d, c0,03, 00,0a, 00,63, 00,15, 00,12, 00,0f, 00,0c,
       +00,62, 00,09, 00,65, 00,64, 00,14, 00,11, 00,0e, 00,0b,
       +00,08, 00,06, 00,03, 00,ff"
       +
       +readonly SSLv2_CLIENT_HELLO="
       +,80,34    # length (here: 52)
       +,01       # Client Hello
       +,00,02    # SSLv2
       +,00,1b    # cipher spec length (here: 27 )
       +,00,00    # session ID length
       +,00,10    # challenge length
       +,05,00,80 # 1st cipher        9 cipher specs, only classical V2 ciphers are used here, see  FIXME below
       +,03,00,80 # 2nd          there are v3 in v2!!! : https://tools.ietf.org/html/rfc6101#appendix-E
       +,01,00,80 # 3rd          Cipher specifications introduced in version 3.0 can be included in version 2.0 client hello messages using
       +,07,00,c0 # 4th          the syntax below. [..] # V2CipherSpec (see Version 3.0 name) = { 0x00, CipherSuite }; !!!!
       +,08,00,80 # 5th
       +,06,00,40 # 6th
       +,04,00,80 # 7th
       +,02,00,80 # 8th
       +,00,00,00 # 9th
       +,29,22,be,b3,5a,01,8b,04,fe,5f,80,03,a0,13,eb,c4" # Challenge
       +# https://idea.popcount.org/2012-06-16-dissecting-ssl-handshake/ (client)
       +# FIXME: http://max.euston.net/d/tip_sslciphers.html
       +
       +
       +###### output functions ######
       +# a little bit of sanitzing with bash internal search&replace -- otherwise printf will hiccup at '%' and '--' does the rest. 
       +out()   { /usr/bin/printf -- "${1//%/%%}"; }
       +outln() { out "$1\n"; }
       +#TODO: Still no shell injection safe but if just run it from the cmd line: that's fine
       +
       +# color print functions, see also http://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/x329.html
       +pr_liteblue()   { [[ "$COLOR" -eq 2 ]] && out "\033[0;34m$1" || out "$1"; pr_off; }                                # not yet used
       +pr_liteblueln() { pr_liteblue "$1"; outln; }
       +pr_blue()       { [[ "$COLOR" -eq 2 ]] && out "\033[1;34m$1" || out "$1"; pr_off; }                                # used for head lines of single tests
       +pr_blueln()     { pr_blue "$1"; outln; }
       +
       +pr_litered()   { [[ "$COLOR" -eq 2 ]] && out "\033[0;31m$1" || pr_bold "$1"; pr_off; }                        # this is bad
       +pr_literedln() { pr_litered "$1"; outln; }
       +pr_red()       { [[ "$COLOR" -eq 2 ]] && out "\033[1;31m$1" || pr_bold "$1"; pr_off; }                        # oh, this is really bad
       +pr_redln()     { pr_red "$1"; outln; }
       +
       +pr_litemagenta()   { [[ "$COLOR" -eq 2 ]] && out "\033[0;35m$1" || pr_underline "$1"; pr_off; }        # local problem: one test cannot be done
       +pr_litemagentaln() { pr_litemagenta "$1"; outln; }
       +pr_magenta()       { [[ "$COLOR" -eq 2 ]] && out "\033[1;35m$1" || pr_underline "$1"; pr_off; }        # Fatal error: quitting because of this!
       +pr_magentaln()     { pr_magenta "$1"; outln; }
       +
       +pr_litecyan()   { [[ "$COLOR" -eq 2 ]] && out "\033[0;36m$1" || out "$1"; pr_off; }                                # not yet used
       +pr_litecyanln() { pr_litecyan "$1"; outln; }
       +pr_cyan()       { [[ "$COLOR" -eq 2 ]] && out "\033[1;36m$1" || out "$1"; pr_off; }                                # additional hint
       +pr_cyanln()     { pr_cyan "$1"; outln; }
       +
       +pr_litegreyln() { pr_litegrey "$1"; outln; }
       +pr_litegrey()   { [[ "$COLOR" -eq 2 ]] && out "\033[0;37m$1" || out "$1"; pr_off; }
       +pr_grey()       { [[ "$COLOR" -eq 2 ]] && out "\033[1;30m$1" || out "$1"; pr_off; }
       +pr_greyln()     { pr_grey "$1"; outln; }
       +
       +pr_litegreen()   { [[ "$COLOR" -eq 2 ]] && out "\033[0;32m$1" || out "$1"; pr_off; }                                # This is good
       +pr_litegreenln() { pr_litegreen "$1"; outln; }
       +pr_green()       { [[ "$COLOR" -eq 2 ]] && out "\033[1;32m$1" || out "$1"; pr_off; }                                # This is the best 
       +pr_greenln()     { pr_green "$1"; outln; }
       +
       +pr_yellow()   { [[ "$COLOR" -eq 2 ]] && out "\033[1;33m$1" || out "$1"; pr_off; }                                # academic or minor problem 
       +pr_yellowln() { pr_yellow "$1"; outln; }
       +pr_brown()    { [[ "$COLOR" -eq 2 ]] && out "\033[0;33m$1" || out "$1"; pr_off; }                                # it is not a bad problem but you shouldn't do this
       +pr_brownln()  { pr_brown "$1"; outln; }
       +
       +
       +# color=1 functions
       +pr_off()          { [[ "$COLOR" -ne 0 ]] && out "\033[m\c"; }
       +pr_bold()         { [[ "$COLOR" -ne 0 ]] && out "\033[1m$1" || out "$1"; pr_off; }
       +pr_boldln()       { pr_bold "$1" ; outln; }
       +pr_underline()    { [[ "$COLOR" -ne 0 ]] && out "\033[4m$1" || out "$1"; pr_off; }
       +pr_reverse()      { [[ "$COLOR" -ne 0 ]] && out "\033[7m$1" || out "$1"; pr_off; }
       +
       +
       +### colorswitcher (see e.g. https://linuxtidbits.wordpress.com/2008/08/11/output-color-on-bash-scripts/
       +###                         http://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/x405.html
       +set_color_functions() {
       +        local linux_tput=true
       +
       +        # empty vars if we have no color:
       +        red=""
       +        green=""
       +        brown=""
       +        blue=""
       +        magenta=""
       +        cyan=""
       +        grey=""
       +        yellow=""
       +        off=""
       +        bold=""
       +        underline=""
       +
       +        tput sgr0 &>/dev/null || linux_tput=false
       +        if [[ "$COLOR" -eq 2 ]]; then
       +                if $linux_tput; then
       +                        red=$(tput setaf 1)
       +                        green=$(tput setaf 2)
       +                        brown=$(tput setaf 3)
       +                        blue=$(tput setaf 4)
       +                        magenta=$(tput setaf 5)
       +                        cyan=$(tput setaf 6)
       +                        grey=$(tput setaf 7)
       +                        yellow=$(tput setaf 3; tput bold)
       +                else         # this is a try for old BSD, see terminfo(5)
       +                        red=$(tput AF 1)
       +                        green=$(tput AF 2)
       +                        brown=$(tput AF 3)
       +                        blue=$(tput AF 4)
       +                        magenta=$(tput AF 5)
       +                        cyan=$(tput AF 6)
       +                        grey=$(tput AF 7)
       +                        yellow=$(tput AF 3; tput md)
       +                fi
       +        fi
       +
       +        if [[ "$COLOR" -ge 1 ]]; then
       +                if $linux_tput; then
       +                        bold=$(tput bold)
       +                        underline=$(tput sgr 0 1)
       +                        off=$(tput sgr0)
       +                else         # this is a try for old BSD, see terminfo(5)
       +                        bold=$(tput md)
       +                        underline=$(tput us)
       +                        reverse=$(tput mr)
       +                        off=$(tput me)
       +                fi
       +        fi
       +}
       +
       +
       +###### helper function definitions ######
       +
       +debugme() {
       +        [[ $DEBUG -ge 2 ]] && "$@"
       +}
       +
       +hex2dec() {
       +        #/usr/bin/printf -- "%d" 0x"$1"
       +        echo $((16#$1))
       +}
       +
       +dec2hex() {
       +        /usr/bin/printf -- "%x" "$1"
       +        #echo $((0x$1))
       +}
       +
       +# trim spaces for BSD and old sed
       +count_lines() {
       +        echo "$1" | wc -l | sed 's/ //g'
       +}
       +count_words() {
       +        echo "$1" | wc -w | sed 's/ //g'
       +}
       +
       +count_ciphers() {
       +        echo -n "$1" | sed 's/:/ /g' | wc -w | sed 's/ //g'
       +}
       +
       +actually_supported_ciphers() {
       +        $OPENSSL ciphers "$1" 2>/dev/null || echo ""
       +}
       +
       +newline_to_spaces() {
       +        echo "$1" | tr '\n' ' ' | sed 's/ $//'
       +}
       +
       +strip_lf() {
       +        echo "$1" | tr -d '\n' | tr -d '\r'
       +}
       +
       +toupper() {
       +        echo -n "$1" | tr 'a-z' 'A-Z'
       +}
       +
       +# prints out multiple lines in $1, left aligned by spaces in $2
       +out_row_aligned() {
       +        local first=true
       +
       +        echo "$1" | while read line; do
       +                if $first; then
       +                        first=false
       +                else
       +                        out "$2"
       +                fi
       +                outln "$line"
       +        done
       +}
       +
       +
       +tmpfile_handle() {
       +        if [[ "$DEBUG" -eq 0 ]]; then
       +                rm $TMPFILE 2>/dev/null
       +                [[ $ERRFILE =~ dev.null ]] || rm $ERRFILE
       +        else
       +                mv $TMPFILE "$TEMPDIR/$NODEIP.$1" 2>/dev/null
       +                mv $ERRFILE "$TEMPDIR/$NODEIP.$(sed 's/\.txt//g' <<<"$1").errorlog" 2>/dev/null
       +        fi
       +}
       +
       +# arg1: line with comment sign, tabs and so on
       +filter_input() {
       +        echo "$1" | sed -e 's/#.*$//' -e '/^$/d' | tr -d '\n' | tr -d '\t'
       +}
       +
       +
       +wait_kill(){
       +        local pid=$1                        # pid we wait for or kill
       +        local maxsleep=$2                # how long we wait before killing
       +
       +        while true; do
       +                [[ "$DEBUG" -ge 6 ]] && ps $pid
       +                if ! ps $pid >/dev/null ; then
       +                        return 0                 # process terminated before didn't reach $maxsleep
       +                fi
       +                sleep 1
       +                maxsleep=$((maxsleep - 1))
       +                test $maxsleep -le 0 && break
       +        done                                 # needs to be killed:
       +        kill $pid >&2 2>/dev/null
       +        wait $pid 2>/dev/null        # make sure pid terminated, see wait(1p)
       +        return 3                           # means killed
       +}
       +
       +
       +###### check code starts here ######
       +
       +# determines whether the port has an HTTP service running or not (plain TLS, no STARTTLS)
       +# arg1 could be the protocol determined as "working". IIS6 needs that
       +runs_HTTP() {
       +        # SNI is nonsense for !HTTPS but fortunately other protocols don't seem to care
       +        printf "$GET_REQ11" | $OPENSSL s_client $1 -quiet -connect $NODEIP:$PORT $PROXY $SNI >$TMPFILE 2>$ERRFILE &
       +        wait_kill $! $HEADER_MAXSLEEP
       +        head $TMPFILE | grep -aq ^HTTP && SERVICE=HTTP
       +        head $TMPFILE | grep -aq SMTP && SERVICE=SMTP
       +        head $TMPFILE | grep -aq POP && SERVICE=POP
       +        head $TMPFILE | grep -aq IMAP && SERVICE=IMAP
       +        head $TMPFILE | egrep -aqw "Jive News|InterNetNews|NNRP|INN" && SERVICE=NNTP
       +        debugme head -50 $TMPFILE
       +# $TMPFILE contains also a banner which we could use if there's a need for it
       +
       +        out " Service detected:      "
       +        case $SERVICE in
       +                HTTP)
       +                        out " $SERVICE"
       +                        ret=0 ;;
       +                IMAP|POP|SMTP|NNTP)
       +                        out " $SERVICE, thus skipping HTTP specific checks"
       +                        ret=0 ;;
       +                *)   out " Couldn't determine what's running on port $PORT"
       +                        if $ASSUMING_HTTP; then
       +                                SERVICE=HTTP
       +                                out " -- ASSUMING_HTTP set though"
       +                                ret=0
       +                        else
       +                                out ", assuming no HTTP service => skipping HTTP checks"
       +                                ret=1
       +                        fi
       +                        ;;
       +        esac
       +
       +        outln
       +        tmpfile_handle $FUNCNAME.txt
       +        return $ret
       +}
       +
       +#problems not handled: chunked
       +run_http_header() {
       +        local header
       +        local -i ret
       +        local referer useragent
       +        local url
       +
       +        outln; pr_blue "--> Testing HTTP header response"; outln " @ \"$URL_PATH\"\n"
       +
       +        [[ -z "$1" ]] && url="/" || url="$1"
       +        if $SNEAKY; then
       +                referer="http://google.com/"
       +                useragent="$UA_SNEAKY"
       +        else
       +                referer="TLS/SSL-Tester from $SWURL"
       +                useragent="$UA_STD"
       +        fi
       +        (
       +        $OPENSSL s_client $OPTIMAL_PROTO -quiet -connect $NODEIP:$PORT $PROXY $SNI << EOF
       +GET $url HTTP/1.1
       +Host: $NODE
       +Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
       +Accept-Language: en-us,en;q=0.7,de-de;q=0.3
       +User-Agent: $useragent
       +Referer: $referer
       +Connection: close
       +
       +EOF
       +) >$HEADERFILE 2>$ERRFILE &
       +        if wait_kill $! $HEADER_MAXSLEEP; then
       +                if ! egrep -iaq "XML|HTML|DOCTYPE|HTTP|Connection" $HEADERFILE; then
       +                        pr_litemagenta " likely HTTP header requests failed (#lines: $(wc -l < $HEADERFILE | sed 's/ //g'))."
       +                        outln "Rerun with DEBUG=1 and inspect \"run_http_header.txt\"\n"
       +                        debugme cat $HEADERFILE
       +                        ret=7
       +                fi
       +                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
       +                ret=0
       +        else
       +                #TODO: attention: if this runs into a timeout, we're dead. Try again differently:
       +                printf "$GET_REQ11" | $OPENSSL s_client $OPTIMAL_PROTO -quiet -ign_eof -connect $NODEIP:$PORT $PROXY $SNI 1>$HEADERFILE 2>$ERRFILE
       +                if [[ $? -ne 0 ]]; then
       +                        pr_litemagentaln " failed (1st request stalled, 2nd erroneous)"
       +                        return 3
       +                        #ret=3
       +                fi
       +        fi
       +        status_code=$(awk '/^HTTP\// { print $2 }' $HEADERFILE 2>>$ERRFILE)
       +        msg_thereafter=$(awk -F"$status_code" '/^HTTP\// { print $2 }' $HEADERFILE 2>>$ERRFILE)         # dirty trick to use the status code as a
       +        msg_thereafter=$(strip_lf "$msg_thereafter")                                                                # field separator, otherwise we need a loop with awk
       +        debugme echo "Status/MSG: $status_code $msg_thereafter"
       +
       +        pr_bold " HTTP Status Code           "
       +        [[ -z "$status_code" ]] && pr_litemagentaln "No status code" && return 3
       +
       +        out "  $status_code$msg_thereafter" 
       +        case $status_code in
       +                301|302|307|308)        out ", redirecting to \"$(grep -a '^Location' $HEADERFILE | sed 's/Location: //' | tr -d '\r\n')\"" ;;
       +                200) ;;
       +                206) out " -- WTF?" ;;
       +                400) pr_litemagenta " (Hint: better try another URL)" ;;
       +                401) grep -aq "^WWW-Authenticate" $HEADERFILE && out "  "; strip_lf "$(grep -a "^WWW-Authenticate" $HEADERFILE)"
       +                        ;;
       +                403)  ;;
       +                404) out " (Hint: supply a path which doesn't give a \"$status_code$msg_thereafter\")" ;; 
       +                405) ;;
       +                *) pr_litemagenta ". Oh, didn't expect a $status_code$msg_thereafter";;
       +        esac
       +        outln
       +
       +        # we don't call "tmpfile_handle $FUNCNAME.txt" as we need the header file in other functions!
       +        return $ret
       +}
       +
       +# Borrowed from Glenn Jackman, see https://unix.stackexchange.com/users/4667/glenn-jackman
       +detect_ipv4() {
       +        local octet="(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])"
       +        local ipv4address="$octet\\.$octet\\.$octet\\.$octet"
       +        local your_ip_msg="(check if it's your IP address or e.g. a cluster IP)"
       +        local result
       +        local first=true
       +        local spaces="                              "
       +        
       +        if [[ ! -s $HEADERFILE ]]; then
       +                run_http_header "$1" || return 3
       +        fi
       +
       +        # remove pagespeed header as it is mistakenly identified as ipv4 address https://github.com/drwetter/testssl.sh/issues/158
       +        # also facebook has a CSP rule for 127.0.0.1
       +        if egrep -vi "pagespeed|page-speed|Content-Security-Policy" $HEADERFILE | grep -iqE "$ipv4address"; then
       +                pr_bold " IPv4 address in header       " 
       +                while read line; do
       +                        result="$(grep -E "$ipv4address" <<< "$line")"
       +                        result=$(strip_lf "$result")
       +                        if [[ -n "$result" ]]; then
       +                                if ! $first; then
       +                                        out "$spaces"
       +                                        your_ip_msg=""
       +                                else
       +                                        first=false
       +                                fi
       +                                pr_litered "$result"
       +                                outln "\n$spaces$your_ip_msg"
       +                        fi
       +                done < $HEADERFILE
       +        fi
       +}        
       +
       +
       +run_http_date() {
       +        local now difftime
       +
       +        if [[ ! -s $HEADERFILE ]]; then
       +                run_http_header "$1" || return 3                # this is just for the line "Testing HTTP header response"
       +        fi
       +        pr_bold " HTTP clock skew              "
       +        if [[ $SERVICE != "HTTP" ]]; then
       +                out "not tested as we're not targeting HTTP"
       +        else
       +                printf "$GET_REQ11" | $OPENSSL s_client $OPTIMAL_PROTO -ign_eof -connect $NODEIP:$PORT $PROXY $SNI &>$TMPFILE
       +                now=$(date "+%s")                                # we need an ACCURATE date here and cannot rely on the headerfile!
       +                HTTP_TIME=$(awk -F': ' '/^date:/ { print $2 }  /^Date:/ { print $2 }' $TMPFILE)
       +                if [[ -n "$HTTP_TIME" ]]; then
       +                        if $HAS_GNUDATE ; then
       +                                HTTP_TIME=$(date --date="$HTTP_TIME" "+%s")
       +                        else
       +                                HTTP_TIME=$(date -j -f "%a, %d %b %Y %T %Z" "$HTTP_TIME" "+%s" 2>>$ERRFILE) # the trailing \r confuses BSD flavors otherwise
       +                        fi
       +
       +                        difftime=$((HTTP_TIME - $now))
       +                        [[ $difftime != "-"* ]] && [[ $difftime != "0" ]] && difftime="+$difftime"
       +                        out "$difftime sec from localtime";
       +                else
       +                        out "Got no HTTP time, maybe try different URL?";
       +                fi
       +                debugme out " epoch: $HTTP_TIME"
       +        fi
       +        outln
       +        detect_ipv4
       +}
       +
       +includeSubDomains() {
       +        if grep -aiqw includeSubDomains "$1"; then
       +                pr_litegreen ", includeSubDomains"
       +        else
       +                pr_litecyan ", just this domain"
       +        fi
       +}
       +
       +preload() {
       +        grep -aiqw preload "$1" && pr_litegreen ", preload"
       +}
       +
       +
       +run_hsts() {
       +        local hsts_age_sec
       +        local hsts_age_days
       +
       +        if [[ ! -s $HEADERFILE ]]; then
       +                run_http_header "$1" || return 3
       +        fi
       +        #pr_bold " HSTS                         "
       +        pr_bold " Strict Transport Security    "
       +        grep -iaw '^Strict-Transport-Security' $HEADERFILE >$TMPFILE
       +        if [[ $? -eq 0 ]]; then
       +                grep -aciw '^Strict-Transport-Security' $HEADERFILE | egrep -waq "1" || out "(two HSTS header, using 1st one) "
       +                hsts_age_sec=$(sed -e 's/[^0-9]*//g' $TMPFILE | head -1)
       +#FIXME: test for number!
       +                hsts_age_days=$(( hsts_age_sec / 86400))
       +                if [[ $hsts_age_days -gt $HSTS_MIN ]]; then
       +                        pr_litegreen "$hsts_age_days days" ; out "=$hsts_age_sec s"
       +                else
       +                        out "$hsts_age_sec s = "
       +                        pr_brown "$hsts_age_days days, <$HSTS_MIN days is too short"
       +                fi
       +                includeSubDomains "$TMPFILE"
       +                preload "$TMPFILE"
       +                #FIXME: To be checked against e.g. https://dxr.mozilla.org/mozilla-central/source/security/manager/boot/src/nsSTSPreloadList.inc
       +                #                                                  and https://chromium.googlesource.com/chromium/src/+/master/net/http/transport_security_state_static.json
       +        else
       +                out "--"
       +        fi
       +        outln
       +
       +        tmpfile_handle $FUNCNAME.txt
       +        return $?
       +}
       +
       +
       +run_hpkp() {
       +        local -i hpkp_age_sec
       +        local -i hpkp_age_days
       +        local -i hpkp_nr_keys
       +        local hpkp_key hpkp_key_hostcert
       +        local spaces="                             "
       +        local key_found=false
       +        local i
       +
       +        if [[ ! -s $HEADERFILE ]]; then
       +                run_http_header "$1" || return 3
       +        fi
       +        #pr_bold " HPKP                         "
       +        pr_bold " Public Key Pinning           "
       +        egrep -aiw '^Public-Key-Pins|Public-Key-Pins-Report-Only' $HEADERFILE >$TMPFILE
       +        if [[ $? -eq 0 ]]; then
       +                if egrep -aciw '^Public-Key-Pins|Public-Key-Pins-Report-Only' $HEADERFILE | egrep -waq "1" ; then
       +                        :
       +                else
       +                        pr_brown "two HPKP headers: "
       +                        for i in $(newline_to_spaces "$(egrep -ai '^Public-Key-Pins' $HEADERFILE | awk -F':' '/Public-Key-Pins/ { print $1 }')"); do
       +                                pr_underline $i
       +                                out " "
       +                        done
       +                        out "\n$spaces using first "
       +                        pr_underline "$(awk -F':' '/Public-Key-Pins/ { print $1 }' $HEADERFILE | head -1), "
       +                fi
       +
       +                # remove leading Public-Key-Pins*, any colons, double quotes and trailing spaces and taking the first -- whatever that is
       +                sed -e 's/Public-Key-Pins://g' -e s'/Public-Key-Pins-Report-Only://' $TMPFILE | \
       +                        sed -e 's/;//g' -e 's/\"//g' -e 's/^ //' | head -1 > $TMPFILE.2
       +                # BSD lacks -i, otherwise we would have done it inline
       +                # now separate key value and other stuff per line:
       +                tr ' ' '\n' < $TMPFILE.2 >$TMPFILE
       +
       +                hpkp_nr_keys=$(grep -ac pin-sha $TMPFILE)
       +                out "# of keys: "
       +                if [[ $hpkp_nr_keys -eq 1 ]]; then
       +                        pr_litered "1 (NOT ok), "
       +                else
       +                        out "$hpkp_nr_keys, "
       +                fi
       +
       +                # print key=value pair with awk, then strip non-numbers, to be improved with proper parsing of key-value with awk
       +                hpkp_age_sec=$(awk -F= '/max-age/{max_age=$2; print max_age}' $TMPFILE | sed -E 's/[^[:digit:]]//g')
       +                hpkp_age_days=$((hpkp_age_sec / 86400))
       +                if [[ $hpkp_age_days -ge $HPKP_MIN ]]; then
       +                        pr_litegreen "$hpkp_age_days days" ; out "=$hpkp_age_sec s"
       +                else
       +                        out "$hpkp_age_sec s = "
       +                        pr_brown "$hpkp_age_days days (<$HPKP_MIN days is not good enough)"
       +                fi
       +
       +                includeSubDomains "$TMPFILE"
       +                preload "$TMPFILE"
       +
       +                [[ -s "$HOSTCERT" ]] || get_host_cert
       +                # get the key fingerprints
       +                hpkp_key_hostcert="$($OPENSSL x509 -in $HOSTCERT -pubkey -noout | grep -v PUBLIC | \
       +                        $OPENSSL base64 -d | $OPENSSL dgst -sha256 -binary | $OPENSSL base64)"
       +                while read hpkp_key; do
       +                        if [[ "$hpkp_key_hostcert" == "$hpkp_key" ]] || [[ "$hpkp_key_hostcert" == "$hpkp_key=" ]]; then
       +                                out "\n$spaces matching host key: "
       +                                pr_litegreen "$hpkp_key"
       +                                key_found=true
       +                        fi
       +                        debugme out "\n  $hpkp_key | $hpkp_key_hostcert"
       +                done < <(tr ';' '\n' < $TMPFILE | tr -d ' ' | tr -d '\"' | awk -F'=' '/pin.*=/ { print $2 }')
       +                if ! $key_found ; then
       +                        out "\n$spaces"
       +                        pr_litered " No matching key for pins found "
       +                        out "(CAs pinned? -- not yet checked)"
       +                fi
       +        else
       +                out "--"
       +        fi
       +        outln
       +
       +        tmpfile_handle $FUNCNAME.txt
       +        return $?
       +}
       +
       +emphasize_stuff_in_headers(){
       +# see http://www.grymoire.com/Unix/Sed.html#uh-3
       +#        outln "$1" | sed "s/[0-9]*/$brown&$off/g"
       +        outln "$1" | sed -e "s/\([0-9]\)/$brown\1$off/g" \
       +                -e "s/Debian/"$yellow"\Debian$off/g" \
       +                -e "s/Win32/"$yellow"\Win32$off/g" \
       +                -e "s/Win64/"$yellow"\Win64$off/g" \
       +                -e "s/Ubuntu/"$yellow"Ubuntu$off/g" \
       +                -e "s/ubuntu/"$yellow"ubuntu$off/g" \
       +                -e "s/jessie/"$yellow"jessie$off/g" \
       +                -e "s/squeeze/"$yellow"squeeze$off/g" \
       +                -e "s/wheezy/"$yellow"wheezy$off/g" \
       +                -e "s/lenny/"$yellow"lenny$off/g" \
       +                -e "s/SUSE/"$yellow"SUSE$off/g" \
       +                -e "s/Red Hat Enterprise Linux/"$yellow"Red Hat Enterprise Linux$off/g" \
       +                -e "s/Red Hat/"$yellow"Red Hat$off/g" \
       +                -e "s/CentOS/"$yellow"CentOS$off/g" \
       +                -e "s/Via/"$yellow"Via$off/g" \
       +                -e "s/X-Forwarded/"$yellow"X-Forwarded$off/g" \
       +                -e "s/Liferay-Portal/"$yellow"Liferay-Portal$off/g" \
       +                -e "s/X-Cache-Lookup/"$yellow"X-Cache-Lookup$off/g" \
       +                -e "s/X-Cache/"$yellow"X-Cache$off/g" \
       +                -e "s/X-Squid/"$yellow"X-Squid$off/g" \
       +                -e "s/X-Server/"$yellow"X-Server$off/g" \
       +                -e "s/X-Varnish/"$yellow"X-Varnish$off/g" \
       +                -e "s/X-OWA-Version/"$yellow"X-OWA-Version$off/g" \
       +                -e "s/X-Version/"$yellow"X-Version$off/g" \
       +                -e "s/X-Powered-By/"$yellow"X-Powered-By$off/g" \
       +                -e "s/X-UA-Compatible/"$yellow"X-UA-Compatible$off/g" \
       +                -e "s/X-AspNet-Version/"$yellow"X-AspNet-Version$off/g"
       +}
       +
       +run_server_banner() {
       +        local serverbanner
       +
       +        if [[ ! -s $HEADERFILE ]]; then
       +                run_http_header "$1" || return 3
       +        fi
       +        pr_bold " Server banner                "
       +        grep -ai '^Server' $HEADERFILE >$TMPFILE
       +        if [[ $? -eq 0 ]]; then
       +                serverbanner=$(sed -e 's/^Server: //' -e 's/^server: //' $TMPFILE)
       +                if [[ x"$serverbanner" == "x\n" ]] || [[ x"$serverbanner" == "x\n\r" ]] || [[ x"$serverbanner" == "x" ]]; then
       +                        outln "banner exists but empty string"
       +                else
       +                        emphasize_stuff_in_headers "$serverbanner"
       +                        [[ "$serverbanner" = *Microsoft-IIS/6.* ]] && [[ $OSSL_VER == 1.0.2* ]] && \
       +                                pr_litemagentaln "                              It's recommended to run another test w/ OpenSSL 1.01 !"
       +                                # see https://github.com/PeterMosmans/openssl/issues/19#issuecomment-100897892
       +                fi
       +                # mozilla.github.io/server-side-tls/ssl-config-generator/
       +          # https://support.microsoft.com/en-us/kb/245030
       +        else
       +                outln "(no \"Server\" line in header, interesting!)"
       +        fi
       +
       +        tmpfile_handle $FUNCNAME.txt
       +        return 0
       +}
       +
       +run_rp_banner() {
       +        local line
       +        local first=true
       +        local spaces="                              "
       +
       +        if [[ ! -s $HEADERFILE ]]; then
       +                run_http_header "$1" || return 3
       +        fi
       +        pr_bold " Reverse Proxy banner         "
       +        egrep -ai '^Via:|^X-Cache|^X-Squid|^X-Varnish:|^X-Server-Name:|^X-Server-Port:|^x-forwarded' $HEADERFILE >$TMPFILE 
       +        if [[ $? -ne 0 ]]; then
       +                outln "--"
       +        else
       +                while read line; do
       +                        line=$(strip_lf "$line")
       +                        if ! $first; then
       +                                out "$spaces"
       +                        else
       +                                first=false
       +                        fi
       +               emphasize_stuff_in_headers "$line"
       +          done < $TMPFILE
       +        fi
       +        outln
       +
       +        tmpfile_handle $FUNCNAME.txt
       +        return 0
       +#                emphasize_stuff_in_headers "$(sed 's/^/ /g' $TMPFILE | tr '\n\r' '  ')" || \
       +}
       +
       +run_application_banner() {
       +        local line
       +        local first=true
       +        local spaces="                              "
       +
       +        if [[ ! -s $HEADERFILE ]]; then
       +                run_http_header "$1" || return 3
       +        fi
       +        pr_bold " Application banner           "
       +        egrep -ai '^X-Powered-By|^X-AspNet-Version|^X-Version|^Liferay-Portal|^X-OWA-Version' $HEADERFILE >$TMPFILE
       +        if [[ $? -ne 0 ]]; then
       +                outln "--"
       +        else
       +                cat $TMPFILE | while read line; do
       +                        line=$(strip_lf "$line")
       +                        if ! $first; then
       +                                out "$spaces"
       +                        else
       +                                first=false
       +                        fi
       +               emphasize_stuff_in_headers "$line"
       +          done
       +        fi
       +        tmpfile_handle $FUNCNAME.txt
       +        return 0
       +}
       +
       +run_cookie_flags() {        # ARG1: Path, ARG2: path
       +        local -i nr_cookies
       +        local nr_httponly nr_secure
       +        local negative_word 
       +
       +        if [[ ! -s $HEADERFILE ]]; then
       +                run_http_header "$1" || return 3
       +        fi
       +        pr_bold " Cookie(s)                    "
       +        grep -ai '^Set-Cookie' $HEADERFILE >$TMPFILE
       +        if [[ $? -eq 0 ]]; then
       +                nr_cookies=$(wc -l < $TMPFILE | sed 's/ //g')
       +                out "$nr_cookies issued: "
       +                if [[ $nr_cookies -gt 1 ]]; then
       +                        negative_word="NONE"
       +                else
       +                        negative_word="NOT"
       +                fi
       +                nr_secure=$(grep -iac secure $TMPFILE)
       +                case $nr_secure in
       +                        0) pr_brown "$negative_word" ;;
       +                        [123456789]) pr_litegreen "$nr_secure/$nr_cookies";;
       +                esac
       +                 out " secure, "
       +                nr_httponly=$(grep -cai httponly $TMPFILE)
       +                case $nr_httponly in
       +                        0) pr_brown "$negative_word" ;;
       +                        [123456789]) pr_litegreen "$nr_httponly/$nr_cookies";;
       +                esac
       +                out " HttpOnly"
       +        else
       +                out "(none issued at \"$1\")"
       +        fi
       +        outln
       +
       +        tmpfile_handle $FUNCNAME.txt
       +        return 0
       +}
       +
       +
       +run_more_flags() {
       +        local good_flags2test="X-Frame-Options X-XSS-Protection X-Content-Type-Options Content-Security-Policy X-Content-Security-Policy X-WebKit-CSP Content-Security-Policy-Report-Only"
       +        local other_flags2test="Access-Control-Allow-Origin Upgrade X-Served-By X-UA-Compatible"
       +        local egrep_pattern=""
       +        local f2t result_str
       +        local first=true
       +        local spaces="                              "
       +
       +        if [[ ! -s $HEADERFILE ]]; then
       +                run_http_header "$1" || return 3
       +        fi
       +        pr_bold " Security headers             "
       +        # convert spaces to | (for egrep)
       +        egrep_pattern=$(echo "$good_flags2test $other_flags2test"| sed -e 's/ /|\^/g' -e 's/^/\^/g') 
       +        egrep -ai "$egrep_pattern" $HEADERFILE >$TMPFILE
       +        if [[ $? -ne 0 ]]; then
       +                outln "--"
       +                ret=1
       +        else
       +                #set -x
       +                ret=0
       +                for f2t in $good_flags2test; do
       +                        debugme echo "---> $f2t"
       +                        result_str=$(grep -wi "^$f2t" $TMPFILE | grep -vi "$f2t"-)
       +                        result_str=$(strip_lf "$result_str")
       +                        [[ -z "$result_str" ]] && continue
       +                        if ! $first; then
       +                                out "$spaces"        # output leading spaces if the first header
       +                        else
       +                                first=false
       +                        fi
       +                        # extract and print key(=flag) in green:
       +                        pr_litegreen "${result_str%%:*}:"
       +                        #pr_litegreen "$(sed 's/:.*$/:/' <<< "$result_str")"
       +                        # print value in plain text:
       +                        outln "${result_str#*:}"
       +
       +                done
       +                # now the same with other flags
       +                for f2t in $other_flags2test; do
       +                        result_str=$(grep -i "^$f2t" $TMPFILE)
       +                        [[ -z "$result_str" ]] && continue
       +                        if ! $first; then
       +                                out "$spaces"  # output leading spaces if the first header
       +                        else
       +                                first=false
       +                        fi
       +                        # extract and print key(=flag) underlined
       +                        pr_underline "${result_str%%:*}:"
       +                        # print value in plain text:
       +                        outln "${result_str#*:}"
       +                done
       +        fi
       +#TODO: I am not testing for the correctness or anything stupid yet, e.g. "X-Frame-Options: allowall"
       +
       +        tmpfile_handle $FUNCNAME.txt
       +        return $ret
       +}
       +
       +
       +# #1: string with 2 opensssl codes, HEXC= same in NSS/ssllabs 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')
       +                part2=${part2//0x/}
       +                if [[ -n "$part3" ]]; then    # a SSLv2 cipher has three parts
       +                        #part3=$(echo $part3 | sed 's/0x//g')
       +                        part3=${part3//0x/}
       +                fi
       +                HEXC="$part1$part2$part3"
       +        fi
       +#TODO: we should just echo this and avoid the global var HEXC
       +        HEXC=$(echo $HEXC | tr 'A-Z' 'a-z' | sed 's/0x/x/') #tolower + strip leading 0
       +        return 0
       +}
       +
       +prettyprint_local() {
       +        local arg
       +        local hexcode dash ciph sslvers kx auth enc mac export
       +        local re='^[0-9A-Fa-f]+$'
       +
       +        pr_blue "--> Displaying all local ciphers ";
       +        if [[ -n "$1" ]]; then
       +                [[ $1 =~ $re ]] && \
       +                        pr_blue "matching number pattern \"$1\" " || \
       +                        pr_blue "matching word pattern "\"$1\"" (ignore case)"
       +        fi
       +        outln "\n"
       +        neat_header
       +
       +        if [[ -z "$1" ]]; then
       +                $OPENSSL ciphers -V 'ALL:COMPLEMENTOFALL:@STRENGTH' 2>$ERRFILE | while read hexcode dash ciph sslvers kx auth enc mac export ; do       # -V doesn't work with openssl < 1.0
       +                        normalize_ciphercode $hexcode
       +                        neat_list $HEXC $ciph $kx $enc
       +                        outln
       +                done
       +        else
       +                #for arg in $(echo $@ | sed 's/,/ /g'); do
       +                for arg in ${*//,/ /}; do
       +                        $OPENSSL ciphers -V 'ALL:COMPLEMENTOFALL:@STRENGTH' 2>$ERRFILE | while read hexcode dash ciph sslvers kx auth enc mac export ; do        # -V doesn't work with openssl < 1.0
       +                                normalize_ciphercode $hexcode
       +                                # for numbers we don't do word matching:
       +                                [[ $arg =~ $re ]] && \
       +                                        neat_list $HEXC $ciph $kx $enc | grep -ai "$arg" || \
       +                                        neat_list $HEXC $ciph $kx $enc | grep -wai "$arg"
       +                        done
       +             done
       +        fi
       +        outln
       +        return 0
       +}
       +
       +
       +# list ciphers (and makes sure you have them locally configured)
       +# arg[1]: cipher list (or anything else)
       +listciphers() {
       +        local -i ret
       +        local debugname="$(sed -e s'/\!/not/g' -e 's/\:/_/g' <<< "$1")"
       +
       +        $OPENSSL ciphers "$1" &>$TMPFILE
       +        ret=$?
       +        debugme cat $TMPFILE
       +
       +     tmpfile_handle $FUNCNAME.$debugname.txt
       +        return $ret
       +}
       +
       +
       +# argv[1]: cipher list to test
       +# argv[2]: string on console
       +# argv[3]: ok to offer? 0: yes, 1: no
       +std_cipherlists() {
       +        local -i ret
       +        local singlespaces
       +        local debugname="$(sed -e s'/\!/not/g' -e 's/\:/_/g' <<< "$1")"
       +
       +        pr_bold "$2    "         # indent in order to be in the same row as server preferences
       +        if listciphers "$1"; then  # is that locally available??
       +                $OPENSSL s_client -cipher "$1" $STARTTLS -connect $NODEIP:$PORT $PROXY $SNI 2>$ERRFILE >$TMPFILE </dev/null
       +                ret=$?
       +                debugme cat $ERRFILE
       +                case $3 in
       +                        0)        # ok to offer
       +                                [[ $ret -eq 0 ]] && \
       +                                        pr_greenln "offered (OK)" || \
       +                                        pr_brownln "not offered (NOT ok)" ;;
       +                        1) # the ugly ones
       +                                [[ $ret -eq 0 ]] && \
       +                                        pr_redln "offered (NOT ok)" || \
       +                                        pr_greenln "not offered (OK)" ;;
       +                        2)         # bad but not worst
       +                                [[ $ret -eq 0 ]] && \
       +                                        pr_literedln "offered (NOT ok)" || \
       +                                        pr_litegreenln "not offered (OK)" ;;
       +                        3) # not totally bad 
       +                                [[ $ret -eq 0 ]] && \
       +                                        pr_brownln "offered (NOT ok)" || \
       +                                        outln "not offered (OK)" ;;
       +                        *) # we shouldn't reach this
       +                                pr_litemagenta "? (please report this)" ;;
       +                esac
       +                tmpfile_handle $FUNCNAME.$debugname.txt
       +        else
       +                singlespaces=$(echo "$2" | sed -e 's/ \+/ /g' -e 's/^ //' -e 's/ $//g' -e 's/  //g')
       +                local_problem "No $singlespaces configured in $OPENSSL"
       +        fi
       +        # we need lf in those cases:
       +        [[ $DEBUG -ge 2 ]] && echo
       +}
       +
       +
       +# sockets inspired by http://blog.chris007.de/?p=238
       +# ARG1: hexbyte with a leading comma (!!), separated by commas
       +# ARG2: sleep
       +socksend() {
       +        # the following works under BSD and Linux, which is quite tricky. So don't mess with it unless you're really sure what you do
       +        if $HAS_SED_E; then
       +                data=$(echo "$1" | sed -e 's/# .*$//g' -e 's/ //g' | sed -E 's/^[[:space:]]+//; s/[[:space:]]+$//; /^$/d' | sed 's/,/\\/g' | tr -d '\n')
       +        else
       +                data=$(echo "$1" | sed -e 's/# .*$//g' -e 's/ //g' | sed -r 's/^[[:space:]]+//; s/[[:space:]]+$//; /^$/d' | sed 's/,/\\/g' | tr -d '\n')
       +        fi
       +        [[ $DEBUG -ge 4 ]] && echo "\"$data\""
       +        printf -- "$data" >&5 2>/dev/null &
       +        sleep $2
       +}
       +
       +
       +#FIXME: This is only for HB and CCS, others use still sockread_serverhello()
       +sockread() {
       +        local -i ret=0
       +        local ddreply
       +
       +        [[ "x$2" == "x" ]] && maxsleep=$MAX_WAITSOCK || maxsleep=$2
       +
       +        ddreply=$(mktemp $TEMPDIR/ddreply.XXXXXX) || return 7
       +        dd bs=$1 of=$ddreply count=1 <&5 2>/dev/null &
       +        wait_kill $! $maxsleep
       +        ret=$?
       +        SOCKREPLY=$(cat $ddreply)
       +        rm $ddreply
       +        return $ret
       +}
       +
       +
       +show_rfc_style(){
       +        local rfcname
       +
       +        [[ -z "$MAPPING_FILE_RFC" ]] && return 1
       +        rfcname=$(grep -iw "$1" "$MAPPING_FILE_RFC" | sed -e 's/^.*TLS/TLS/' -e 's/^.*SSL/SSL/')
       +        [[ -n "$rfcname" ]] && out "$rfcname"
       +        return 0
       +}
       +
       +neat_header(){
       +        printf -- "Hexcode  Cipher Suite Name (OpenSSL)    KeyExch.   Encryption Bits${MAPPING_FILE_RFC:+        Cipher Suite Name (RFC)}\n"
       +        printf -- "%s-------------------------------------------------------------------------${MAPPING_FILE_RFC:+----------------------------------------------}\n"
       +}
       +
       +
       +# arg1: hexcode
       +# arg2: cipher in openssl notation
       +# arg3: keyexchange
       +# arg4: encryption (maybe included "export")
       +neat_list(){
       +        local hexcode="$1"
       +        local ossl_cipher="$2"
       +        local kx enc strength
       +
       +        kx=$(sed 's/Kx=//g' <<< "$3")
       +        enc=$(sed 's/Enc=//g' <<< "$4")
       +        strength=$(sed -e 's/.*(//' -e 's/)//' <<< "$enc")                                                # strength = encryption bits
       +        strength=$(sed -e 's/ChaCha20-Poly1305/ly1305/g' <<< "$strength")                         # workaround for empty bits ChaCha20-Poly1305
       +        enc=$(sed -e 's/(.*)//g' -e 's/ChaCha20-Poly1305/ChaCha20-Po/g' <<< "$enc")        # workaround for empty bits ChaCha20-Poly1305
       +        echo "$export" | grep -iq export && strength="$strength,export"
       +        # workaround for color escape codes:
       +        if printf -- "$kx" | "${HEXDUMPVIEW[@]}" | grep -q 33 ; then         # here's a color code
       +                kx="$kx "                                                    # one for color code if ECDH and three digits
       +                [[ "${#kx}" -eq 18 ]] && kx="$kx  "        # 18 means DH, colored < 1000. Add another space
       +                [[ "${#kx}" -eq 19 ]] && kx="$kx "                # 19 means DH, colored >=1000. Add another space
       +                #echo ${#kx}                                                # should be always 20
       +        fi
       +        #if [[ -r "$MAPPING_FILE_RFC" ]]; then
       +                printf -- " %-7s %-30s %-10s %-11s%-11s${MAPPING_FILE_RFC:+ %-48s}${SHOW_EACH_C:+  }" "$hexcode" "$ossl_cipher" "$kx" "$enc" "$strength" "$(show_rfc_style $HEXC)"
       +        #else
       +        #        printf -- " %-7s %-30s %-10s %-11s%-11s${SHOW_EACH_C:+  }" "$1" "$2" "$kx" "$enc" "$strength"
       +        #fi
       +}
       +
       +test_just_one(){
       +        local hexcode n ciph sslvers kx auth enc mac export
       +        local dhlen
       +        local ret
       +        local re='^[0-9A-Fa-f]+$'
       +
       +        pr_blue "--> Testing single cipher with "
       +        [[ $1 =~ $re ]] && \
       +                pr_blue "matching number pattern \"$1\" " || \
       +                pr_blue "word pattern "\"$1\"" (ignore case)"
       +        outln
       +        ! $HAS_DH_BITS && pr_litemagentaln "    (Your $OPENSSL cannot show DH/ECDH bits)"
       +        outln
       +        neat_header
       +        #for arg in $(echo $@ | sed 's/,/ /g'); do
       +        for arg in ${*//, /}; do
       +                # 1st check whether openssl has cipher or not
       +                $OPENSSL ciphers -V 'ALL:COMPLEMENTOFALL:@STRENGTH' 2>$ERRFILE | while read hexcode dash ciph sslvers kx auth enc mac export ; do
       +                # FIXME: e.g. OpenSSL < 1.0 doesn't understand "-V" --> we can't do anything about it!
       +                        normalize_ciphercode $hexcode
       +                        # is argument a number?
       +                        if [[ $arg =~ $re ]]; then
       +                                neat_list $HEXC $ciph $kx $enc | grep -qai "$arg" 
       +                        else
       +                                neat_list $HEXC $ciph $kx $enc | grep -qwai "$arg"
       +                        fi
       +                        if [[ $? -eq 0 ]]; then    # string matches, so we can ssl to it:
       +                                $OPENSSL s_client -cipher $ciph $STARTTLS -connect $NODEIP:$PORT $PROXY $SNI &>$TMPFILE </dev/null
       +                                ret=$?
       +                                if [[ $kx == "Kx=ECDH" ]] || [[ $kx == "Kx=DH" ]] || [[ $kx == "Kx=EDH" ]]; then
       +                                        if [[ $ret -eq 0 ]]; then
       +                                                dhlen=$(read_dhbits_from_file $TMPFILE quiet)
       +                                                kx="$kx $dhlen"
       +                                        else
       +                                                kx="$kx$grey TBD  $off "
       +                                        fi
       +                                fi
       +                                neat_list $HEXC $ciph "$kx" $enc
       +                                if [[ $ret -eq 0 ]]; then
       +                                        pr_cyan "  available"
       +                                else
       +                                        out "  not a/v"
       +                                fi
       +                                outln
       +                        fi
       +                done
       +        done
       +        outln
       +
       +        tmpfile_handle $FUNCNAME.txt
       +        return 0                # this is a single test for a cipher
       +}
       +
       +
       +# test for all ciphers locally configured (w/o distinguishing whether they are good or bad
       +run_allciphers(){
       +        local tmpfile
       +        local nr_ciphers
       +        local -i ret=0
       +        local hexcode n ciph sslvers kx auth enc mac export
       +        local dhlen
       +
       +        nr_ciphers=$(count_ciphers "$($OPENSSL ciphers 'ALL:COMPLEMENTOFALL:@STRENGTH' 2>$ERRFILE)")
       +        outln
       +        pr_blue "--> Testing all locally available $nr_ciphers ciphers against the server"; outln ", ordered by encryption strength"
       +        ! $HAS_DH_BITS && pr_litemagentaln "    (Your $OPENSSL cannot show DH/ECDH bits)"
       +        outln
       +        neat_header
       +
       +        $OPENSSL ciphers -V 'ALL:COMPLEMENTOFALL:@STRENGTH' 2>>$ERRFILE | while read hexcode n ciph sslvers kx auth enc mac export; do
       +        # FIXME: e.g. OpenSSL < 1.0 doesn't understand "-V" --> we can't do anything about it!
       +                $OPENSSL s_client -cipher $ciph $STARTTLS -connect $NODEIP:$PORT $PROXY $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
       +                if [[ $kx == "Kx=ECDH" ]] || [[ $kx == "Kx=DH" ]] || [[ $kx == "Kx=EDH" ]]; then
       +                        dhlen=$(read_dhbits_from_file $TMPFILE quiet)
       +                        kx="$kx $dhlen"
       +                fi
       +                neat_list $HEXC $ciph "$kx" $enc
       +                if [[ "$SHOW_EACH_C" -ne 0 ]]; then
       +                        if [[ $ret -eq 0 ]]; then
       +                                pr_cyan "  available"
       +                        else
       +                                out "  not a/v"
       +                        fi
       +                fi
       +                outln
       +                tmpfile_handle $FUNCNAME.txt
       +        done
       +        outln
       +        return 0
       +}
       +
       +# test for all ciphers per protocol locally configured (w/o distinguishing whether they are good or bad
       +run_cipher_per_proto(){
       +        local proto proto_text
       +        local hexcode n ciph sslvers kx auth enc mac export
       +        local -i ret=0
       +        local dhlen
       +
       +        pr_blue "--> Testing all locally available ciphers per protocol against the server"; outln ", ordered by encryption strength"
       +        ! $HAS_DH_BITS && pr_litemagentaln "    (Your $OPENSSL cannot show DH/ECDH bits)"
       +        outln
       +        neat_header
       +        outln " -ssl2 SSLv2\n -ssl3 SSLv3\n -tls1 TLS 1\n -tls1_1 TLS 1.1\n -tls1_2 TLS 1.2"| while read proto proto_text; do
       +                locally_supported "$proto" "$proto_text" || continue
       +                outln
       +                $OPENSSL ciphers $proto -V 'ALL:COMPLEMENTOFALL:@STRENGTH' 2>$ERRFILE | while read hexcode n ciph sslvers kx auth enc mac export; do        # -V doesn't work with openssl < 1.0
       +                        $OPENSSL s_client -cipher $ciph $proto $STARTTLS -connect $NODEIP:$PORT $PROXY $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
       +                        if [[ $kx == "Kx=ECDH" ]] || [[ $kx == "Kx=DH" ]] || [[ $kx == "Kx=EDH" ]]; then
       +                                dhlen=$(read_dhbits_from_file $TMPFILE quiet)
       +                                kx="$kx $dhlen"
       +                        fi
       +                        neat_list $HEXC $ciph "$kx" $enc
       +                        if [[ "$SHOW_EACH_C" -ne 0 ]]; then
       +                                if [[ $ret -eq 0 ]]; then
       +                                        pr_cyan "  available"
       +                                else
       +                                        out "  not a/v"
       +                                fi
       +                        fi
       +                        outln
       +                        tmpfile_handle $FUNCNAME.txt
       +                done
       +        done
       +        return 0
       +}
       +
       +locally_supported() {
       +        local -i ret=0
       +
       +        [[ -n "$2" ]] && out "$2 "
       +        $OPENSSL s_client "$1" 2>&1 | grep -aq "unknown option"
       +        if [[ $? -eq 0 ]]; then
       +                local_problem "$OPENSSL doesn't support \"s_client $1\""
       +                ret=7
       +        fi
       +        return $ret
       +}
       +
       +
       +run_prototest_openssl() {
       +        local sni="$SNI"
       +        local -i ret=0
       +
       +        $OPENSSL s_client -state $1 $STARTTLS -connect $NODEIP:$PORT $PROXY $sni &>$TMPFILE </dev/null
       +        ret=$?
       +# FIXME: here FreeBSD9/openssl 0.9.8 returns always 0 --> need to read the error but for now we DO NOT SUPPORT this platform.
       +# that's where the binaries are for!
       +        [[ $DEBUG -eq 2 ]] && egrep "error|failure" $TMPFILE | egrep -av "unable to get local|verify error"
       +
       +        if ! locally_supported "$1" "$2" ; then
       +                ret=7
       +        else                                                                # we remove SNI for SSLv2 and v3:
       +                [[ "$1" =~ ssl ]] && sni=""                # newer openssl throw an error if SNI is supplied with SSLv2,
       +                                                                        # SSLv3 doesn't have SNI (openssl doesn't complain though -- yet)
       +                $OPENSSL s_client -state $1 $STARTTLS -connect $NODEIP:$PORT $sni &>$TMPFILE </dev/null
       +                ret=$?                                                  #TODO (maybe): here FreeBSD9 returns always 0 --> need to read the error
       +                [[ $DEBUG -eq 2 ]] && egrep "error|failure" $TMPFILE | egrep -av "unable to get local|verify error"
       +                grep -aq "no cipher list" $TMPFILE && ret=5
       +        fi
       +
       +        tmpfile_handle $FUNCNAME$1.txt
       +        return $ret
       +
       +        # 0: offered
       +        # 1: not offered
       +        # 5: protocol ok, but no cipher
       +        # 7: no local support
       +}
       +
       +
       +run_protocols() {
       +        local using_sockets=true
       +        local supported_no_ciph1="supported but couldn't detect a cipher (may need debugging)" 
       +        local supported_no_ciph2="supported but couldn't detect a cipher" 
       +
       +        outln; pr_blue "--> Testing protocols ";
       +
       +        #FIXME: use PROTOS_OFFERED here
       +
       +        if $SSL_NATIVE; then
       +                using_sockets=false
       +                outln "(via native openssl)\n"
       +        else
       +                if [[ -n "$STARTTLS" ]]; then
       +                        outln "(via openssl, SSLv2 via sockets)\n"
       +                        using_sockets=false
       +                else
       +                        using_sockets=true
       +                        outln "(via sockets except TLS 1.2 and SPDY/NPN)\n"
       +                fi
       +        fi
       +
       +        pr_bold " SSLv2      ";
       +        if ! $SSL_NATIVE; then
       +                sslv2_sockets                                                                                         #FIXME: messages need to be moved to this higher level
       +        else
       +                run_prototest_openssl "-ssl2"
       +                case $? in
       +                        0) pr_redln   "offered (NOT ok)" ;;
       +                        1) pr_greenln "not offered (OK)" ;;
       +                        5) pr_litered "$supported_no_ciph2"; 
       +                                outln " (may need further attention)"  ;;                        # protocol ok, but no cipher
       +                        7) ;;                                                                                        # no local support
       +                esac
       +        fi
       +
       +        pr_bold " SSLv3      ";
       +        if $using_sockets; then
       +                tls_sockets "00" "$TLS_CIPHER"
       +        else
       +                run_prototest_openssl "-ssl3"
       +        fi
       +        case $? in
       +                0) pr_literedln "offered (NOT ok)" ;;
       +                1) pr_greenln "not offered (OK)"   ;;
       +                2) pr_litemagentaln "#FIXME: downgraded. still missing a test case here" ;;
       +                5) pr_litered "$supported_no_ciph2"; 
       +                                outln "(may need debugging)"  ;;                                        # protocol ok, but no cipher
       +                7) ;;                                                                                                # no local support
       +        esac
       +
       +        pr_bold " TLS 1      ";
       +        if $using_sockets; then
       +                tls_sockets "01" "$TLS_CIPHER"
       +        else
       +                run_prototest_openssl "-tls1"
       +        fi
       +        case $? in
       +                0) outln "offered" ;;                                                                      # nothing wrong with it -- per se
       +                1) outln "not offered" ;;                                                                  # neither good or bad
       +                2) pr_brown "not offered (NOT ok)"
       +                        [[ $DEBUG -eq 1 ]] && out " -- downgraded"
       +                        outln ;;
       +                5) outln "$supported_no_ciph1"  ;;                                                        # protocol ok, but no cipher
       +                7) ;;                                                                                                # no local support
       +        esac
       +
       +        pr_bold " TLS 1.1    ";
       +        if $using_sockets; then
       +                tls_sockets "02" "$TLS_CIPHER"
       +        else
       +                run_prototest_openssl "-tls1_1"
       +        fi        
       +        case $? in
       +                0) outln "offered" ;;                                                                           # nothing wrong with it
       +                1) outln "not offered" ;;                                                                  # neither good or bad
       +                2) out "not offered" 
       +                        [[ $DEBUG -eq 1 ]] && out " -- downgraded" 
       +                        outln ;;
       +                5) outln "$supported_no_ciph1" ;;                                                        # protocol ok, but no cipher
       +                7) ;;                                                                                                # no local support
       +        esac
       +
       +        pr_bold " TLS 1.2    ";
       +        if $using_sockets && [[ $EXPERIMENTAL == "yes" ]]; then                        #TODO: IIS servers do have a problem here with our handshake
       +                tls_sockets "03" "$TLS12_CIPHER"
       +        else
       +                run_prototest_openssl "-tls1_2"
       +        fi        
       +        case $? in
       +                0) pr_greenln "offered (OK)" ;;                                                         # GCM cipher in TLS 1.2: very good!
       +                1) pr_brownln "not offered (NOT ok)" ;;                                                # no GCM, penalty
       +                2) pr_brown "not offered (NOT ok)"
       +                        [[ $DEBUG -eq 1 ]] && out " -- downgraded"
       +                        outln ;;
       +                5) outln "$supported_no_ciph1" ;;                                                        # protocol ok, but no cipher
       +                7) ;;                                                                                                # no local support
       +        esac
       +
       +        return 0
       +}
       +
       +#TODO: work with a fixed list here
       +run_std_cipherlists() {
       +        outln
       +        pr_blue "--> Testing ~standard cipher lists"; outln "\n"
       +# see ciphers(1ssl)
       +        std_cipherlists 'NULL:eNULL'                       " Null Ciphers             " 1
       +        std_cipherlists 'aNULL'                            " Anonymous NULL Ciphers   " 1
       +        std_cipherlists 'ADH'                              " Anonymous DH Ciphers     " 1
       +        std_cipherlists 'EXPORT40'                         " 40 Bit encryption        " 1
       +        std_cipherlists 'EXPORT56'                         " 56 Bit encryption        " 1
       +        std_cipherlists 'EXPORT'                           " Export Ciphers (general) " 1
       +        std_cipherlists 'LOW:!ADH'                         " Low (<=64 Bit)           " 1
       +        std_cipherlists 'DES:!ADH:!EXPORT:!aNULL'          " DES Ciphers              " 1
       +        std_cipherlists 'MEDIUM:!NULL:!aNULL:!SSLv2'       " Medium grade encryption  " 2
       +        std_cipherlists '3DES:!ADH:!aNULL'                 " Triple DES Ciphers       " 3
       +        std_cipherlists 'HIGH:!NULL:!aNULL:!DES:!3DES'     " High grade encryption    " 0
       +        return 0
       +}
       +
       +
       +# arg1: file with input for grepping the bit length for ECDH/DHE
       +# arg2: whether to print sparse or not (empty: no)
       +read_dhbits_from_file() {
       +        local bits what_dh
       +        local add=""
       +        local old_fart=" (openssl cannot show DH bits)"
       +
       +        bits=$(awk -F': ' '/^Server Temp Key/ { print $2 }' "$1")                                        # extract line
       +        bits=$(echo "$bits" | sed -e 's/, P-...//' -e 's/,//g' -e 's/bits//' -e 's/ //g') # now: ??DH [number]    K??
       +        what_dh=$(echo "$bits" | tr -d '0-9')
       +        bits=$(echo $bits | tr -d 'DHEC')
       +
       +        debugme echo ">$what_dh|$bits<"
       +
       +        if ! $HAS_DH_BITS && [[ -z "what_dh" ]]; then
       +                if [[ -z "$2" ]]; then
       +                        pr_litemagenta "$old_fart"
       +                fi
       +                return 0
       +        fi
       +
       +        [[ -n "$bits" ]] && [[ -z "$2" ]] && out ", "
       +        if [[ $what_dh == "DH" ]] || [[ $what_dh == "EDH" ]]; then
       +                [[ -z "$2" ]] && add="bit DH"
       +                if [[ "$bits" -le 600 ]]; then
       +                        pr_red "$bits $add"
       +                elif [[ "$bits" -le 800 ]]; then
       +                        pr_litered "$bits $add"
       +                elif [[ "$bits" -le 1280 ]]; then
       +                        pr_brown "$bits $add"
       +                elif [[ "$bits" -ge 2048 ]]; then
       +                        pr_litegreen "$bits $add"
       +                else
       +                        out "$bits $add"
       +                fi
       +        # https://wiki.openssl.org/index.php/Elliptic_Curve_Cryptography, http://www.keylength.com/en/compare/
       +        elif [[ $what_dh == "ECDH" ]]; then
       +                [[ -z "$2" ]] && add="bit ECDH"
       +                if [[ "$bits" -le 128 ]]; then         # has that ever existed?
       +                        pr_red "$bits $add"
       +                elif [[ "$bits" -le 163 ]]; then
       +                        pr_litered "$bits $add"
       +                elif [[ "$bits" -ge 224 ]]; then
       +                        pr_litegreen "$bits $add"
       +                else
       +                        out "$bits $add"
       +                fi
       +        fi
       +
       +        return 0
       +}
       +
       +
       +run_server_preference() {
       +        local cipher1 cipher2
       +        local default_cipher default_proto
       +        local remark4default_cipher 
       +        local -a cipher proto
       +        local p i
       +        local -i ret=0
       +        local list_fwd="DES-CBC3-SHA:RC4-MD5:DES-CBC-SHA:RC4-SHA:AES128-SHA:AES128-SHA256:AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:ECDH-RSA-DES-CBC3-SHA:ECDH-RSA-AES128-SHA:ECDH-RSA-AES256-SHA:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:DHE-DSS-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:AES256-SHA256"
       +        # now reversed offline via tac, see https://github.com/thomassa/testssl.sh/commit/7a4106e839b8c3033259d66697893765fc468393 :
       +        local list_reverse="AES256-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384DHE-DSS-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDH-RSA-AES256-SHA:ECDH-RSA-AES128-SHA:ECDH-RSA-DES-CBC3-SHA:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-AES128-SHA:AES256-SHA:AES128-SHA256:AES128-SHA:RC4-SHA:DES-CBC-SHA:RC4-MD5:DES-CBC3-SHA"
       +        local has_cipher_order=true
       +        
       +        outln;
       +        pr_blue "--> Testing server preferences"; outln "\n"
       +
       +        pr_bold " Has server cipher order?     "
       +        $OPENSSL s_client $STARTTLS -cipher $list_fwd -connect $NODEIP:$PORT $PROXY $SNI </dev/null 2>$ERRFILE >$TMPFILE
       +        if [[ $? -ne 0 ]] && [[ -z "$STARTTLS_PROTOCOL" ]]; then
       +                pr_litemagenta "no matching cipher in this list found (pls report this): "
       +                outln "$list_fwd  . "
       +          has_cipher_order=false
       +          ret=6
       +        elif [[ -n "$STARTTLS_PROTOCOL" ]]; then
       +                # now it still could be that we hit this bug: https://github.com/drwetter/testssl.sh/issues/188
       +                # workaround is to connect with a protocol
       +                debugme out "(workaround #188) "
       +                determine_optimal_proto $STARTTLS_PROTOCOL                        
       +                $OPENSSL s_client $STARTTLS $STARTTLS_OPTIMAL_PROTO -cipher $list_fwd -connect $NODEIP:$PORT $PROXY $SNI </dev/null 2>$ERRFILE >$TMPFILE
       +                if [[ $? -ne 0 ]]; then
       +                        pr_litemagenta "no matching cipher in this list found (pls report this): "
       +                        outln "$list_fwd  . "
       +                        has_cipher_order=false
       +                  ret=6
       +                fi
       +        fi
       +
       +        if $has_cipher_order; then
       +                cipher1=$(grep -wa Cipher $TMPFILE | egrep -avw "New|is" | sed -e 's/^ \+Cipher \+://' -e 's/ //g')
       +                $OPENSSL s_client $STARTTLS $STARTTLS_OPTIMAL_PROTO -cipher $list_reverse -connect $NODEIP:$PORT $PROXY $SNI </dev/null 2>>$ERRFILE >$TMPFILE
       +                # that worked above so no error handling here
       +                cipher2=$(grep -wa Cipher $TMPFILE | egrep -avw "New|is" | sed -e 's/^ \+Cipher \+://' -e 's/ //g')
       +
       +                if [[ "$cipher1" != "$cipher2" ]]; then
       +                        pr_litered "nope (NOT ok)"
       +                        remark4default_cipher=" (limited sense as client will pick)"
       +                else
       +                        pr_green "yes (OK)"
       +                        remark4default_cipher=""
       +                fi
       +                [[ $DEBUG -ge 2 ]] && out "  $cipher1 | $cipher2"
       +                outln
       +
       +                pr_bold " Negotiated protocol          "
       +                $OPENSSL s_client $STARTTLS -connect $NODEIP:$PORT $PROXY $SNI </dev/null 2>>$ERRFILE >$TMPFILE
       +                if [[ $? -ne 0 ]]; then
       +                        # 2 second try with $OPTIMAL_PROTO especially for intolerant IIS6 servers:
       +                        $OPENSSL s_client $STARTTLS $OPTIMAL_PROTO -connect $NODEIP:$PORT $PROXY $SNI </dev/null 2>>$ERRFILE >$TMPFILE
       +                        [[ $? -ne 0 ]] && pr_litemagenta "Handshake error!"
       +                fi
       +                default_proto=$(grep -aw "Protocol" $TMPFILE | sed -e 's/^.*Protocol.*://' -e 's/ //g')
       +                case "$default_proto" in
       +                        *TLSv1.2)                pr_greenln $default_proto ;;
       +                        *TLSv1.1)                pr_litegreenln $default_proto ;;
       +                        *TLSv1)                outln $default_proto ;;
       +                        *SSLv2)                pr_redln $default_proto ;;
       +                        *SSLv3)                pr_redln $default_proto ;;
       +                        "")                        pr_litemagenta "default proto empty";  [[ $OSSL_VER == 1.0.2* ]] && outln " (Hint: if IIS6 give OpenSSL 1.01 a try)" ;; 
       +                        *)                        pr_litemagenta "FIXME line $LINENO: $default_proto" ;;
       +                esac
       +
       +                pr_bold " Negotiated cipher            "
       +                default_cipher=$(grep -aw "Cipher" $TMPFILE | egrep -avw "New|is" | sed -e 's/^.*Cipher.*://' -e 's/ //g')
       +                case "$default_cipher" in
       +                        *NULL*|*EXP*)        pr_red "$default_cipher" ;;
       +                        *RC4*)                pr_litered "$default_cipher" ;;
       +                        *CBC*)                pr_brown "$default_cipher" ;;   # FIXME BEAST: We miss some CBC ciphers here, need to work w/ a list
       +                        *GCM*)                pr_green "$default_cipher" ;;   # best ones
       +                        *CHACHA20*)        pr_green "$default_cipher" ;;   # best ones
       +                        ECDHE*AES*)    pr_yellow "$default_cipher" ;;  # it's CBC. --> lucky13
       +                        "")                        pr_litemagenta "default cipher empty" ;  [[ $OSSL_VER == 1.0.2* ]] && out " (Hint: if IIS6 give OpenSSL 1.01 a try)" ;;
       +                        *)                        out "$default_cipher" ;;
       +                esac
       +                read_dhbits_from_file "$TMPFILE"
       +                outln "$remark4default_cipher"
       +
       +                if [[ ! -z "$remark4default_cipher" ]]; then
       +                        pr_bold " Negotiated cipher per proto"; outln " $remark4default_cipher"
       +                        i=1
       +                        for p in ssl2 ssl3 tls1 tls1_1 tls1_2; do
       +                        #locally_supported -"$p" "    " || continue
       +                        locally_supported -"$p" || continue
       +                                $OPENSSL s_client  $STARTTLS -"$p" -connect $NODEIP:$PORT $PROXY $SNI </dev/null 2>>$ERRFILE >$TMPFILE
       +                                if [[ $? -eq 0 ]]; then
       +                                        proto[i]=$(grep -aw "Protocol" $TMPFILE | sed -e 's/^.*Protocol.*://' -e 's/ //g')
       +                                        cipher[i]=$(grep -aw "Cipher" $TMPFILE | egrep -avw "New|is" | sed -e 's/^.*Cipher.*://' -e 's/ //g')
       +                                        [[ ${cipher[i]} == "0000" ]] && cipher[i]=""                                  # Hack!
       +                                        [[ $DEBUG -ge 2 ]] && outln "Default cipher for ${proto[i]}: ${cipher[i]}"
       +                                else
       +                                         proto[i]=""
       +                                         cipher[i]=""
       +                                fi
       +                                i=$(($i + 1))
       +                        done
       +
       +                        [[ -n "$PROXY" ]] && arg="   SPDY/NPN is"
       +                        [[ -n "$STARTTLS" ]] && arg="    "
       +                        if spdy_pre " $arg"; then                                                                                # is NPN/SPDY supported and is this no STARTTLS? / no PROXY
       +                                $OPENSSL s_client -host $NODE -port $PORT -nextprotoneg "$NPN_PROTOs" </dev/null 2>>$ERRFILE >$TMPFILE
       +                                if [[ $? -eq 0 ]]; then
       +                                        proto[i]=$(grep -aw "Next protocol" $TMPFILE | sed -e 's/^Next protocol://' -e 's/(.)//' -e 's/ //g')
       +                                        if [[ -z "${proto[i]}" ]]; then
       +                                                cipher[i]=""
       +                                        else
       +                                                cipher[i]=$(grep -aw "Cipher" $TMPFILE | egrep -avw "New|is" | sed -e 's/^.*Cipher.*://' -e 's/ //g')
       +                                                [[ $DEBUG -ge 2 ]] && outln "Default cipher for ${proto[i]}: ${cipher[i]}"
       +                                        fi
       +                                fi
       +                        else
       +                                outln        # we miss for STARTTLS 1x LF otherwise
       +                        fi
       +
       +                        for i in 1 2 3 4 5 6; do
       +                                if [[ -n "${cipher[i]}" ]]; then                                              # cipher not empty
       +                                         if [[ -z "${cipher[i-1]}" ]]; then                                      # previous one empty
       +                                                #outln
       +                                                printf -- "     %-30s %s" "${cipher[i]}:" "${proto[i]}"        # print out both
       +                                         else                                                                    # previous NOT empty
       +                                                if [[ "${cipher[i-1]}" == "${cipher[i]}" ]]; then                   # and previous protocol same cipher
       +                                                        out ", ${proto[i]}"                                                   # same cipher --> only print out protocol behind it
       +                                                else
       +                                                        outln
       +                                                        printf -- "     %-30s %s" "${cipher[i]}:" "${proto[i]}"        # print out both
       +                                            fi
       +                                         fi
       +                                fi
       +                        done
       +                fi
       +        fi
       +
       +        tmpfile_handle $FUNCNAME.txt
       +        if [[ -z "$remark4default_cipher" ]]; then
       +                cipher_pref_check
       +        else
       +                outln "\n No further cipher order check has been done as order is determined by the client"
       +        fi
       +        return 0
       +}
       +
       +cipher_pref_check() {
       +        local p proto protos
       +        local tested_cipher cipher
       +
       +        pr_bold " Cipher order"
       +
       +        for p in ssl2 ssl3 tls1 tls1_1 tls1_2; do
       +                $OPENSSL s_client $STARTTLS -"$p" -connect $NODEIP:$PORT $PROXY $SNI </dev/null 2>$ERRFILE >$TMPFILE
       +                if [[ $? -eq 0 ]]; then
       +                        tested_cipher=""
       +                        proto=$(grep -aw "Protocol" $TMPFILE | sed -e 's/^.*Protocol.*://' -e 's/ //g')
       +                        cipher=$(grep -aw "Cipher" $TMPFILE | egrep -avw "New|is" | sed -e 's/^.*Cipher.*://' -e 's/ //g')
       +                        [[ -z "$proto" ]] && continue        # for early openssl versions sometimes needed
       +                        outln
       +                        printf "     %-10s %s " "$proto:" "$cipher"
       +                        tested_cipher="-"$cipher
       +                        while true; do
       +                                $OPENSSL s_client $STARTTLS -"$p" -cipher "ALL:$tested_cipher" -connect $NODEIP:$PORT $PROXY $SNI </dev/null 2>>$ERRFILE >$TMPFILE
       +                                [[ $? -ne 0 ]] && break
       +                                cipher=$(grep -aw "Cipher" $TMPFILE | egrep -avw "New|is" | sed -e 's/^.*Cipher.*://' -e 's/ //g')
       +                                out "$cipher "
       +                                tested_cipher="$tested_cipher:-$cipher"
       +                        done
       +                fi
       +        done
       +        outln
       +
       +        if ! spdy_pre "     SPDY/NPN: " ; then                # is NPN/SPDY supported and is this no STARTTLS?
       +                outln
       +        else
       +                protos=$($OPENSSL s_client -host $NODE -port $PORT -nextprotoneg  \"\" </dev/null 2>>$ERRFILE | grep -a "^Protocols " | sed -e 's/^Protocols.*server: //' -e 's/,//g')
       +                for p in $protos; do
       +                        $OPENSSL s_client -host $NODE -port $PORT -nextprotoneg "$p" $PROXY </dev/null 2>>$ERRFILE >$TMPFILE
       +                        cipher=$(grep -aw "Cipher" $TMPFILE | egrep -avw "New|is" | sed -e 's/^.*Cipher.*://' -e 's/ //g')
       +                        printf "     %-10s %s " "$p:" "$cipher"
       +                        tested_cipher="-"$cipher
       +                        while true; do
       +                                $OPENSSL s_client -cipher "ALL:$tested_cipher" -host $NODE -port $PORT -nextprotoneg "$p" $PROXY </dev/null 2>>$ERRFILE >$TMPFILE
       +                                [[ $? -ne 0 ]] && break
       +                                cipher=$(grep -aw "Cipher" $TMPFILE | egrep -avw "New|is" | sed -e 's/^.*Cipher.*://' -e 's/ //g')
       +                                out "$cipher "
       +                                tested_cipher="$tested_cipher:-$cipher"
       +                        done
       +                outln
       +                done
       +        fi
       +
       +        tmpfile_handle $FUNCNAME.txt
       +        return 0
       +}
       +
       +
       +get_host_cert() {
       +                # arg1 is proto or empty
       +                $OPENSSL s_client $STARTTLS -connect $NODEIP:$PORT $PROXY $SNI $1 2>/dev/null </dev/null | \
       +                        awk '/-----BEGIN/,/-----END/ { print $0 }'  >$HOSTCERT
       +                return $((${PIPESTATUS[0]} + ${PIPESTATUS[1]}))
       +}
       +
       +get_all_certs() {
       +        local savedir
       +        local nrsaved
       +        local -i ret
       +
       +        $OPENSSL s_client -showcerts $STARTTLS -connect $NODEIP:$PORT $PROXY $SNI 2>$ERRFILE </dev/null >$TEMPDIR/allcerts.txt
       +        ret=$?
       +        savedir=$(pwd); cd $TEMPDIR
       +        # http://backreference.org/2010/05/09/ocsp-verification-with-openssl/
       +        awk -v n=-1 '/-----BEGIN CERTIFICATE-----/{ inc=1; n++ } 
       +             inc { print > ("level" n ".crt") }
       +             /---END CERTIFICATE-----/{ inc=0 }' $TEMPDIR/allcerts.txt
       +        nrsaved=$(count_words "$(echo level?.crt 2>/dev/null)")
       +        cd "$savedir"
       +
       +        echo $nrsaved
       +        return $ret
       +}
       +
       +
       +tls_time() {
       +        local now difftime
       +
       +        tls_sockets "01" "$TLS_CIPHER"                                                # try first TLS 1.0 (mostfrequently used protocol)
       +        [[ -z "$TLS_TIME" ]] && tls_sockets "03" "$TLS12_CIPHER"        #           TLS 1.2
       +        [[ -z "$TLS_TIME" ]] && tls_sockets "02" "$TLS_CIPHER"                #           TLS 1.1
       +        [[ -z "$TLS_TIME" ]] && tls_sockets "00" "$TLS_CIPHER"                #           SSL 3
       +
       +        if [[ -n "$TLS_TIME" ]]; then                                                        # nothing returned a time!
       +                difftime=$(($TLS_TIME - $TLS_NOW))                                        # TLS_NOW is being set in tls_sockets()
       +                if [[ "${#difftime}" -gt 5 ]]; then
       +                        # openssl >= 1.0.1f fills this field with random values! --> good for possible fingerprint
       +                        pr_bold " TLS timestamp" ; outln "                random values, no fingerprinting possible "
       +                else
       +                        [[ $difftime != "-"* ]] && [[ $difftime != "0" ]] && difftime="+$difftime"
       +                        pr_bold " TLS clock skew" ; outln "               $difftime sec from localtime";
       +                fi
       +                debugme out "$TLS_TIME"
       +                outln
       +        else
       +                pr_bold " TLS timestamp" ; outln "                "; pr_litemagentaln "SSLv3 through TLS 1.2 didn't return a timestamp"
       +        fi
       +}
       +
       +run_server_defaults() {
       +        local proto
       +        local gost_status_problem=false
       +        local extensions
       +        local sessticket_str lifetime unit keysize sig_algo key_algo
       +        local expire secs2warn ocsp_uri crl startdate enddate issuer_c issuer_o issuer sans san cn cn_nosni
       +        local policy_oid
       +        local spaces="                              "
       +        local wildcard=false
       +
       +        outln
       +        pr_blue "--> Testing server defaults (Server Hello)"; outln "\n"
       +
       +        #TLS extensions follow now
       +        # throwing 1st every cipher/protocol at the server to know what works
       +        for proto in tls1_2 tls1_1 tls1 ssl3; do
       +                $OPENSSL s_client $STARTTLS -connect $NODEIP:$PORT $PROXY $SNI -$proto -tlsextdebug -status </dev/null 2>$ERRFILE >$TMPFILE
       +                ret=$?
       +                get_host_cert "-$proto"
       +                [[ $? -eq 0 ]] && [[ $ret -eq 0 ]] && break
       +                ret=7
       +        done                                # this loop is needed for IIS/6
       +        if [[ $ret -eq 7 ]]; then
       +                # "-status" above doesn't work for GOST only servers, so we do another test without it and see whether that works then:
       +                if ! $OPENSSL s_client $STARTTLS -connect $NODEIP:$PORT $PROXY $SNI -$proto -tlsextdebug </dev/null 2>>$ERRFILE >$TMPFILE; then
       +                        pr_litemagentaln "Strange, no SSL/TLS protocol seems to be supported (error around line $((LINENO - 6)))"
       +                        tmpfile_handle tlsextdebug+status.txt
       +                        return 7        # this is ugly, I know
       +                else
       +                        gost_status_problem=true
       +                fi
       +        fi
       +        $OPENSSL s_client $STARTTLS -connect $NODEIP:$PORT $PROXY -$proto 2>>$ERRFILE </dev/null | awk '/-----BEGIN/,/-----END/ { print $0 }'  >$HOSTCERT.nosni
       +        pr_bold " TLS server extensions        "
       +        extensions=$(grep -aw "^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
       +
       +        pr_bold " Session Tickets RFC 5077     "
       +        sessticket_str=$(grep -aw "session ticket" $TMPFILE | grep -a lifetime)
       +        if [[ -z "$sessticket_str" ]]; then
       +                outln "(none)"
       +        else
       +                lifetime=$(echo $sessticket_str | grep -a lifetime | sed 's/[A-Za-z:() ]//g')
       +                unit=$(echo $sessticket_str | grep -a lifetime | sed -e 's/^.*'"$lifetime"'//' -e 's/[ ()]//g')
       +                outln "$lifetime $unit"
       +        fi
       +
       +        pr_bold " Server key size              "
       +        keysize=$(grep -aw "^Server public key is" $TMPFILE | sed -e 's/^Server public key is //' -e 's/bit//' -e 's/ //')
       +        sig_algo=$($OPENSSL x509 -in $HOSTCERT -noout -text 2>>$ERRFILE | grep "Signature Algorithm" | sed 's/^.*Signature Algorithm: //' | sort -u )
       +        key_algo=$($OPENSSL x509 -in $HOSTCERT -noout -text 2>>$ERRFILE | awk -F':' '/Public Key Algorithm:/ { print $2 }' | sort -u )
       +
       +        if [[ -z "$keysize" ]]; then
       +                outln "(couldn't determine)"
       +        else
       +                if [[ "$keysize" -le 768 ]]; then
       +                        if [[ $sig_algo =~ ecdsa ]] || [[ $key_algo =~ ecPublicKey  ]]; then
       +                                pr_litegreen "EC $keysize"
       +                        else
       +                                pr_red "$keysize"
       +                        fi
       +                elif [[ "$keysize" -le 1024 ]]; then
       +                        pr_brown "$keysize"
       +                elif [[ "$keysize" -le 2048 ]]; then
       +                        out "$keysize"
       +                elif [[ "$keysize" -le 4096 ]]; then
       +                        pr_litegreen "$keysize"
       +                else
       +                        out "weird keysize: $keysize"
       +                fi
       +        fi
       +        outln " bit"
       +
       +        pr_bold " Signature Algorithm          "
       +        case $sig_algo in
       +                    sha1WithRSAEncryption)         pr_brownln "SHA1 with RSA" ;;
       +             sha256WithRSAEncryption) pr_litegreenln "SHA256 with RSA" ;;
       +             sha512WithRSAEncryption) pr_litegreenln "SHA512 with RSA" ;;
       +             ecdsa-with-SHA256)                 pr_litegreenln "ECDSA with SHA256" ;;
       +             md5*)                                 pr_redln "MD5" ;;
       +                *)                                         outln "$algo" ;;
       +        esac
       +        # old, but interesting: https://blog.hboeck.de/archives/754-Playing-with-the-EFF-SSL-Observatory.html
       +
       +        pr_bold " Fingerprint / Serial         "
       +        outln "$($OPENSSL x509 -noout -in $HOSTCERT -fingerprint -sha1 2>>$ERRFILE | sed 's/Fingerprint=//' | sed 's/://g' ) / $($OPENSSL x509 -noout -in $HOSTCERT -serial 2>>$ERRFILE | sed 's/serial=//')"
       +        outln "$spaces$($OPENSSL x509 -noout -in $HOSTCERT -fingerprint -sha256 2>>$ERRFILE | sed 's/Fingerprint=//' | sed 's/://g' )"
       +
       +        pr_bold " Common Name (CN)             "
       +        if $OPENSSL x509 -in $HOSTCERT -noout -subject 2>>$ERRFILE | grep -wq CN; then
       +                cn=$($OPENSSL x509 -in $HOSTCERT -noout -subject 2>>$ERRFILE | sed 's/subject= //' | sed -e 's/^.*CN=//' -e 's/\/emailAdd.*//')
       +                pr_underline "$cn"
       +                if echo -n "$cn" | grep -q '^*.' ; then
       +                        out " (wildcard certificate"
       +                        if [[ "$cn" == "*.$(echo -n "$cn" | sed 's/^\*.//')" ]]; then
       +                                out " match)"
       +                                wildcard=true
       +                        else
       +                                :
       +                                #FIXME: we need to test also the SANs as they can contain a wild card (google.de .e.g) ==> 2.7dev
       +                        fi
       +                fi
       +        else
       +                cn="(no CN field in subject)"
       +                out "$cn"
       +        fi
       +
       +        cn_nosni=""
       +        if [[ -s $HOSTCERT.nosni ]]; then
       +                if $OPENSSL x509 -in $HOSTCERT.nosni -noout -subject 2>>$ERRFILE | grep -wq CN; then
       +                        cn_nosni=$($OPENSSL x509 -in $HOSTCERT.nosni -noout -subject 2>>$ERRFILE | sed 's/subject= //' | sed -e 's/^.*CN=//' -e 's/\/emailAdd.*//')
       +                else
       +                        cn_nosni="no CN field in subject"
       +                fi
       +        fi
       +
       +        debugme out "\"$NODE\" | \"$cn\" | \"$cn_nosni\""
       +        if [[ $NODE == "$cn_nosni" ]]; then
       +                if [[ $SERVICE == "HTTP" ]]; then
       +                        outln " (works w/o SNI)"
       +                else
       +                        outln " (matches certificate directly)"
       +                        # for services != HTTP it depends on the protocol, server and client but it is not named "SNI"
       +                fi
       +        else
       +                if [[ $SERVICE != "HTTP" ]]; then
       +                        outln
       +                        #pr_brownln " (non-SNI clients don't match CN but for non-HTTP services it might be ok)"
       +                        #FIXME: this is irritating and needs to be redone. Then also the wildcard match needs to be tested against  "$cn_nosni"
       +                elif [[ -z "$cn_nosni" ]]; then
       +                        out " (request w/o SNI didn't succeed";
       +                        [[ $algo =~ ecdsa ]] && out ", usual for EC certificates"
       +                        outln ")"
       +                elif [[ "$cn_nosni" == "*no CN field*" ]]; then
       +                        outln ", (request w/o SNI: $cn_nosni)"
       +                else
       +                        out " (CN in response to request w/o SNI: "; pr_underline "$cn_nosni"; outln ")"
       +                fi
       +        fi
       +
       +        sans=$($OPENSSL x509 -in $HOSTCERT -noout -text 2>>$ERRFILE | grep -A3 "Subject Alternative Name" | grep "DNS:" | \
       +                sed -e 's/DNS://g' -e 's/ //g' -e 's/,/ /g' -e 's/othername:<unsupported>//g')
       +#                                                       ^^^ CACert
       +
       +        pr_bold " subjectAltName (SAN)         "
       +        if [[ -n "$sans" ]]; then
       +                for san in $sans; do
       +                        out "$underline$san$off "
       +                done
       +        else
       +                out "-- "
       +        fi
       +        outln
       +        pr_bold " Issuer                       "
       +        issuer=$($OPENSSL x509 -in $HOSTCERT -noout -issuer 2>>$ERRFILE| sed -e 's/^.*CN=//g' -e 's/\/.*$//g')
       +        issuer_o=$($OPENSSL x509 -in $HOSTCERT -noout -issuer 2>>$ERRFILE | sed 's/^.*O=//g' | sed 's/\/.*$//g')
       +        if $OPENSSL x509 -in $HOSTCERT -noout -issuer 2>>$ERRFILE | grep -q 'C=' ; then
       +                issuer_c=$($OPENSSL x509 -in $HOSTCERT -noout -issuer 2>>$ERRFILE | sed 's/^.*C=//g' | sed 's/\/.*$//g')
       +        else
       +                issuer_c=""                 # CACert would have 'issuer= ' here otherwise
       +        fi
       +        if [[ "$issuer_o" == "issuer=" ]] || [[ "$issuer_o" == "issuer= " ]] || [[ "$issuer" == "$CN" ]]; then
       +                pr_redln "selfsigned (not OK)"
       +        else
       +                [[ "$issuer_c" == "" ]] && \
       +                        outln "$underline$issuer$off ($underline$issuer_o$off)" || \
       +                        outln "$underline$issuer$off ($underline$issuer_o$off from $underline$issuer_c$off)"
       +        fi
       +
       +        # http://events.ccc.de/congress/2010/Fahrplan/attachments/1777_is-the-SSLiverse-a-safe-place.pdf, see page 40pp
       +        pr_bold " EV cert"; out " (experimental)       "
       +        policy_oid=$($OPENSSL x509 -in $HOSTCERT -text 2>>$ERRFILE | awk '/ .Policy: / { print $2 }')
       +        if echo "$issuer" | egrep -q 'Extended Validation|Extended Validated|EV SSL|EV CA' || \
       +                [[ "2.16.840.1.114028.10.1.2" == "$policy_oid" ]] || \
       +                [[ 2.16.840.1.114412.1.3.0.2 == "$policy_oid" ]] || \
       +                [[ 2.16.840.1.114412.2.1 == "$policy_oid" ]] || \
       +                [[ 2.16.578.1.26.1.3.3 == "$policy_oid" ]] || \
       +                [[ 1.3.6.1.4.1.17326.10.14.2.1.2 == "$policy_oid" ]] || \
       +                [[ 1.3.6.1.4.1.17326.10.8.12.1.2 == "$policy_oid" ]] || \
       +                [[ 1.3.6.1.4.1.13177.10.1.3.10 == "$policy_oid" ]] ; then
       +                out "yes "
       +        else
       +                out "no "
       +        fi
       +        debugme echo "($(newline_to_spaces "$policy_oid"))"
       +        outln
       +#TODO: use browser OIDs: 
       +#                https://mxr.mozilla.org/mozilla-central/source/security/certverifier/ExtendedValidation.cpp
       +#                http://src.chromium.org/chrome/trunk/src/net/cert/ev_root_ca_metadata.cc
       +#                https://certs.opera.com/03/ev-oids.xml
       +
       +        pr_bold " Certificate Expiration       "
       +        expire=$($OPENSSL x509 -in $HOSTCERT -checkend 0 2>>$ERRFILE)
       +        if ! echo $expire | grep -qw not; then
       +        pr_red "expired!"
       +        else
       +                secs2warn=$((24 * 60 * 60 * DAYS2WARN2))  # low threshold first
       +             expire=$($OPENSSL x509 -in $HOSTCERT -checkend $secs2warn 2>>$ERRFILE)
       +                if echo "$expire" | grep -qw not; then
       +                        secs2warn=$((24 * 60 * 60 * DAYS2WARN1))
       +                        expire=$($OPENSSL x509 -in $HOSTCERT -checkend $secs2warn 2>>$ERRFILE)
       +                        if echo "$expire" | grep -qw not; then
       +                                pr_litegreen ">= $DAYS2WARN1 days"
       +                        else
       +                        pr_brown "expires < $DAYS2WARN1 days"
       +                        fi
       +                else
       +                        pr_litered "expires < $DAYS2WARN2 days!"
       +                fi
       +        fi
       +
       +        if $HAS_GNUDATE ; then
       +                enddate=$(date --date="$($OPENSSL x509 -in $HOSTCERT -noout -enddate 2>>$ERRFILE | cut -d= -f 2)" +"%F %H:%M %z")
       +                startdate=$(date --date="$($OPENSSL x509 -in $HOSTCERT -noout -startdate 2>>$ERRFILE | cut -d= -f 2)" +"%F %H:%M")
       +        else
       +                enddate=$(date -j -f "%b %d %T %Y %Z" "$($OPENSSL x509 -in $HOSTCERT -noout -enddate 2>>$ERRFILE | cut -d= -f 2)" +"%F %H:%M %z")
       +                startdate=$(date -j -f "%b %d %T %Y %Z" "$($OPENSSL x509 -in $HOSTCERT -noout -startdate 2>>$ERRFILE | cut -d= -f 2)" +"%F %H:%M")
       +        fi
       +
       +        outln " ($startdate --> $enddate)"
       +
       +
       +        pr_bold " # of certificates provided"; outln "   $(get_all_certs)"
       +
       +        pr_bold " Certificate Revocation List  "
       +        crl="$($OPENSSL x509 -in $HOSTCERT -noout -text 2>>$ERRFILE | grep -A 4 "CRL Distribution" | grep URI | sed 's/^.*URI://')"
       +        case $(count_lines "$crl") in
       +                0)        pr_literedln "--" ;;
       +                1)        outln "$crl" ;;
       +                *)   out_row_aligned "$crl" "$spaces" ;;
       +        esac
       +
       +        pr_bold " OCSP URI                     "
       +        ocsp_uri=$($OPENSSL x509 -in $HOSTCERT -noout -ocsp_uri 2>>$ERRFILE)
       +        [[ x"$ocsp_uri" == "x" ]] && pr_literedln "--" || echo "$ocsp_uri"
       +
       +        pr_bold " OCSP stapling               "
       +        if grep "OCSP response" $TMPFILE | grep -q "no response sent" ; then
       +                out " not offered"
       +        else
       +                if grep "OCSP Response Status" $TMPFILE | grep -q successful; then
       +                        pr_litegreen " offered"
       +                else
       +                        if $gost_status_problem; then
       +                                outln " (GOST servers make problems here, sorry)"
       +                                ret=0
       +                        else
       +                                outln " not sure what's going on here, debug:"
       +                                grep -A 20 "OCSP response"  $TMPFILE
       +                                ret=2
       +                        fi
       +                fi
       +        fi
       +        outln
       +
       +        # if we call tls_time before tmpfile_handle it throws an error because the function tls_sockets removed $TMPFILE 
       +        # already -- and that was a different one -- means that would get overwritten anyway
       +        tmpfile_handle tlsextdebug+status.txt
       +
       +        tls_time
       +
       +        return $ret
       +}
       +# FIXME: revoked, see checkcert.sh
       +# FIXME: Trust (only CN)
       +
       +
       +# http://www.heise.de/security/artikel/Forward-Secrecy-testen-und-einrichten-1932806.html
       +run_pfs() {
       +        local ret ret2
       +        local -i pfs_offered=1
       +        local tmpfile
       +        local dhlen
       +        local hexcode dash pfs_cipher sslvers kx auth enc mac
       +        # https://community.qualys.com/blogs/securitylabs/2013/08/05/configuring-apache-nginx-and-openssl-for-forward-secrecy -- but with RC4:
       +        #local pfs_ciphers='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'
       +        #w/o RC4:
       +        #local pfs_ciphers='EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA256 EECDH+aRSA+SHA256 EDH+aRSA EECDH !RC4-SHA !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS:@STRENGTH'
       +#
       +# hardcoded: (the exclusion via ! doesn't work with libressl and openssl 0.9.8) and it's reproducible
       +        local pfs_cipher_list="ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-CAMELLIA256-SHA256:DHE-RSA-CAMELLIA256-SHA:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-CAMELLIA256-SHA384:ECDHE-ECDSA-CAMELLIA256-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-CAMELLIA128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-CAMELLIA128-SHA256:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-CAMELLIA128-SHA256:DHE-RSA-SEED-SHA:DHE-RSA-CAMELLIA128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-RC4-SHA:ECDHE-ECDSA-RC4-SHA"
       +        local -i no_supported_ciphers=0
       +
       +        outln
       +        pr_blue "--> Testing (perfect) forward secrecy, (P)FS"; outln " -- omitting 3DES, RC4 and Null Encryption here"
       +        ! $HAS_DH_BITS && $WIDE && pr_litemagentaln "    (Your $OPENSSL cannot show DH/ECDH bits)"
       +
       +        no_supported_ciphers=$(count_ciphers $(actually_supported_ciphers $pfs_cipher_list))
       +        if [[ "$no_supported_ciphers" -le "$CLIENT_MIN_PFS" ]]; then
       +                outln
       +                local_problem "You only have $number_pfs PFS ciphers on the client side "
       +                return 1
       +        fi
       +
       +        $OPENSSL s_client -cipher 'ECDH:DH' $STARTTLS -connect $NODEIP:$PORT $PROXY $SNI &>$TMPFILE </dev/null
       +        ret=$?
       +        outln
       +        if [[ $ret -ne 0 ]] || [[ $(grep -ac "BEGIN CERTIFICATE" $TMPFILE) -eq 0 ]]; then
       +                pr_brownln "Not OK: No ciphers supporting Forward Secrecy offered"
       +        else
       +                pfs_offered=0
       +                pr_litegreen " PFS is offered (OK)"
       +                if $WIDE; then
       +                        outln ", ciphers follow (client/browser support is here specially important) \n"
       +                        neat_header
       +                else
       +                        out "  "
       +                fi
       +                while read hexcode dash pfs_cipher sslvers kx auth enc mac; do
       +                        tmpfile=$TMPFILE.$hexcode
       +                        $OPENSSL s_client -cipher $pfs_cipher $STARTTLS -connect $NODEIP:$PORT $PROXY $SNI &>$tmpfile </dev/null
       +                        ret2=$?
       +                        if [[ $ret2 -ne 0 ]] && [[ "$SHOW_EACH_C" -eq 0 ]]; then
       +                                continue # no successful connect AND not verbose displaying each cipher
       +                        fi
       +                        if $WIDE; then
       +                                normalize_ciphercode $hexcode
       +                                if [[ $kx == "Kx=ECDH" ]] || [[ $kx == "Kx=DH" ]] || [[ $kx == "Kx=EDH" ]]; then
       +                                        dhlen=$(read_dhbits_from_file "$tmpfile" quiet)
       +                                        kx="$kx $dhlen"
       +                                fi
       +                                neat_list $HEXC $pfs_cipher "$kx" $enc $strength
       +                                let "pfs_offered++"
       +                                if [[ "$SHOW_EACH_C" -ne 0 ]]; then
       +                                        if [[ $ret2 -eq 0 ]]; then
       +                                                pr_green "works"
       +                                        else
       +                                                out "not a/v"
       +                                        fi
       +                                fi
       +                                outln
       +                        else
       +                                out "$pfs_cipher "
       +                        fi
       +                done < <($OPENSSL ciphers -V "$pfs_cipher_list" 2>$ERRFILE)                # -V doesn't work with openssl < 1.0
       +                #    ^^^^^ posix redirect as shopt will either segfault or doesn't work with old bash versions
       +                debugme echo $pfs_offered
       +
       +                if [[ "$pfs_offered" -eq 1 ]]; then
       +                         pr_brown "no PFS ciphers found"
       +                fi
       +        fi
       +        outln
       +        $WIDE && outln
       +
       +        debugme echo $(actually_supported_ciphers $pfs_cipher_list)
       +        debugme echo $no_supported_ciphers
       +
       +        tmpfile_handle $FUNCNAME.txt
       +        return $pfs_offered
       +}
       +
       +
       +# 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
       +
       +
       +spdy_pre(){
       +        if [[ ! -z "$STARTTLS" ]]; then
       +                [[ -n "$1" ]] && out "$1"
       +                out "(SPDY is a HTTP protocol and thus not tested here)"
       +                return 1
       +        fi
       +        if [[ ! -z "$PROXY" ]]; then
       +                [[ -n "$1" ]] && pr_litemagenta "$1 "
       +                pr_litemagenta "not tested as proxies do not support proxying it"
       +                return 1
       +        fi
       +        # first, does the current openssl support it?
       +        $OPENSSL s_client help 2>&1 | grep -qw nextprotoneg
       +        if [[ $? -ne 0 ]]; then
       +                local_problem "$OPENSSL doesn't support SPDY/NPN";
       +                return 7
       +        fi
       +        return 0
       +}
       +
       +run_spdy() {
       +        local tmpstr
       +        local -i ret=0
       +
       +        pr_bold " SPDY/NPN   "
       +        if ! spdy_pre ; then
       +                echo
       +                return 0
       +        fi
       +        $OPENSSL s_client -host $NODE -port $PORT -nextprotoneg $NPN_PROTOs </dev/null 2>$ERRFILE >$TMPFILE
       +        tmpstr=$(grep -a '^Protocols' $TMPFILE | sed 's/Protocols.*: //')
       +        if [[ -z "$tmpstr" ]] || [[ "$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 -aq "spdy|http" ; then
       +                        out "$tmpstr" ; out " (advertised)"
       +                        ret=0
       +                else
       +                        pr_litemagenta "please check manually, server response was ambigious ..."
       +                        ret=10
       +                fi
       +        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
       +        tmpfile_handle $FUNCNAME.txt
       +        return $ret
       +}
       +
       +
       +# arg1: string to send
       +# arg2: possible success strings a egrep pattern, needed!
       +starttls_line() {
       +     debugme echo -e "\n=== sending \"$1\" ..."
       +     echo -e "$1" >&5
       +
       +        # we don't know how much to read and it's blocking! So we just put a cat into the 
       +        # background and read until $STARTTLS_SLEEP and: cross our fingers
       +        cat <&5 >$TMPFILE &
       +     wait_kill $! $STARTTLS_SLEEP
       +     debugme echo "... received result: "
       +     debugme cat $TMPFILE
       +     if [[ -n "$2" ]]; then
       +          if egrep -q "$2" $TMPFILE; then
       +               debugme echo "---> reply matched \"$2\""
       +          else
       +               debugme echo "---> reply didn't match \"$2\", see $TMPFILE"
       +               pr_magenta "STARTTLS handshake problem. "
       +                        outln "Either switch to native openssl (--ssl-native), "
       +                        outln "   give the server more time to reply (STARTTLS_SLEEP=<seconds> ./testssh.sh ..) -- "
       +                        outln "   or debug what happened (add --debug=2)"
       +               exit -3
       +          fi
       +     fi
       +
       +        return 0
       +}
       +
       +starttls_just_send(){
       +        debugme echo -e "\n=== sending \"$1\" ..."
       +        echo -e "$1" >&5
       +}
       +
       +starttls_just_read(){
       +     debugme echo "=== just read banner ==="
       +        if [[ "$DEBUG" -ge 2 ]]; then
       +                cat <&5 &
       +             wait_kill $! $STARTTLS_SLEEP
       +        else
       +                dd of=/dev/null count=8 <&5 2>/dev/null &
       +                wait_kill $! $STARTTLS_SLEEP
       +        fi
       +
       +        return 0
       +}
       +
       +
       +# arg for a fd doesn't work here
       +fd_socket() {
       +        local jabber=""
       +        local proyxline=""
       +
       +        if [[ -n "$PROXY" ]]; then
       +                if ! exec 5<> /dev/tcp/${PROXYIP}/${PROXYPORT}; then
       +                        outln
       +                        pr_magenta "$PROG_NAME: unable to open a socket to proxy $PROXYIP:$PROXYPORT"
       +                        return 6
       +                fi
       +                echo "CONNECT $NODEIP:$PORT" >&5
       +                while true ; do
       +                        read proyxline <&5
       +                        if [[ "${proyxline%/*}" == "HTTP" ]]; then
       +                                proyxline=${proyxline#* }
       +                                if [[ "${proyxline%% *}" != "200" ]]; then
       +                                        [[ "$PORT" != 443 ]] && outln "Check whether your proxy supports port $PORT and the underlying protocol."
       +                                        pr_magenta "Unable to CONNECT via proxy. "
       +                                        return 6
       +                                fi
       +                        fi
       +                        if [[ "$proyxline" == $'\r' ]]; then
       +                                break
       +                        fi
       +                done
       +        elif ! exec 5<>/dev/tcp/$NODEIP/$PORT; then        #  2>/dev/null would remove an error message, but disables debugging
       +                outln
       +                pr_magenta "Unable to open a socket to $NODEIP:$PORT. "
       +                # It can last ~2 minutes but for for those rare occasions we don't do a timeout handler here, KISS
       +                return 6
       +        fi
       +
       +        if [[ -n "$STARTTLS" ]]; then
       +                case "$STARTTLS_PROTOCOL" in # port
       +                        ftp|ftps)  # https://tools.ietf.org/html/rfc4217
       +                                $FAST_STARTTLS || starttls_just_read
       +                                $FAST_STARTTLS || starttls_line "FEAT" "211" && starttls_just_send "FEAT"
       +                                starttls_line "AUTH TLS" "successful|234"
       +                                ;;
       +                        smtp|smtps)  # SMTP, see https://tools.ietf.org/html/rfc4217
       +                                $FAST_STARTTLS || starttls_just_read
       +                                $FAST_STARTTLS || starttls_line "EHLO testssl.sh" "220|250" && starttls_just_send "EHLO testssl.sh" 
       +                                starttls_line "STARTTLS" "220"
       +                                ;;
       +                        pop3|pop3s) # POP, see https://tools.ietf.org/html/rfc2595
       +                                $FAST_STARTTLS || starttls_just_read
       +                                starttls_line "STLS" "OK"
       +                                ;;
       +                        nntp|nntps) # NNTP, see https://tools.ietf.org/html/rfc4642
       +                                $FAST_STARTTLS || starttls_just_read
       +                                $FAST_STARTTLS || starttls_line "CAPABILITIES" "101|200" && starttls_just_send "CAPABILITIES"
       +                                starttls_line "STARTTLS" "382"
       +                                ;;
       +                        imap|imaps) # IMAP, https://tools.ietf.org/html/rfc2595
       +                                $FAST_STARTTLS || starttls_just_read
       +                                $FAST_STARTTLS || starttls_line "a001 CAPABILITY" "OK" && starttls_just_send "a001 CAPABILITY"
       +                                starttls_line "a002 STARTTLS" "OK"
       +                                ;;
       +                        ldap|ldaps) # LDAP, https://tools.ietf.org/html/rfc2830, https://tools.ietf.org/html/rfc4511
       +                                fatal "FIXME: LDAP+STARTTLS over sockets not yet supported (try \"--ssl-native\")" -4
       +                                ;;
       +                        acap|acaps) # ACAP = Application Configuration Access Protocol, see https://tools.ietf.org/html/rfc2595
       +                                fatal "ACAP Easteregg: not implemented -- probably never will" -4
       +                                ;;
       +                        xmpp|xmpps) # XMPP, see https://tools.ietf.org/html/rfc6120
       +                                starttls_just_read
       +                                [[ -z $XMPP_HOST ]] && XMPP_HOST="$NODE"
       +                                jabber=$(cat <<EOF
       +<?xml version='1.0' ?>
       +<stream:stream 
       +xmlns:stream='http://etherx.jabber.org/streams' 
       +xmlns='jabber:client' 
       +to='$XMPP_HOST'
       +xml:lang='en'
       +version='1.0'>
       +EOF
       +)
       +                                starttls_line "$jabber"
       +                                starttls_line "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>" "proceed"
       +                                # BTW: https://xmpp.net !
       +                                ;;
       +                        *) # we need to throw an error here -- otherwise testssl.sh treats the STARTTLS protocol as plain SSL/TLS which leads to FP
       +                                fatal "FIXME: STARTTLS protocol $STARTTLS_PROTOCOL is not yet supported" -4
       +                esac
       +        fi
       +
       +     return 0
       +}
       +
       +
       +close_socket(){
       +        exec 5<&-
       +        exec 5>&-
       +        return 0
       +}
       +
       +
       +# first: helper function for protocol checks
       +code2network() {
       +        # arg1: formatted string here in the code
       +        NW_STR=$(echo "$1" | sed -e 's/,/\\\x/g' | sed -e 's/# .*$//g' -e 's/ //g' -e '/^$/d' | tr -d '\n' | tr -d '\t')
       +        #TODO: just echo, no additional global var
       +}
       +
       +len2twobytes() {
       +     local len_arg1=${#1}
       +     [[ $len_arg1 -le 2 ]] && LEN_STR=$(printf "00, %02s \n" "$1")
       +     [[ $len_arg1 -eq 3 ]] && LEN_STR=$(printf "%02s, %02s \n" "${1:0:1}" "${1:1:2}")
       +     [[ $len_arg1 -eq 4 ]] && LEN_STR=$(printf "%02s, %02s \n" "${1:0:2}" "${1:2:2}")
       +}
       +
       +socksend_sslv2_clienthello() {
       +        local data=""
       +
       +        code2network "$1"
       +        data="$NW_STR"
       +        [[ "$DEBUG" -ge 4 ]] && echo "\"$data\""
       +        printf -- "$data" >&5 2>/dev/null &
       +        sleep $USLEEP_SND
       +}
       +
       +# for SSLv2 to TLS 1.2:
       +sockread_serverhello() {
       +     [[ -z "$2" ]] && maxsleep=$MAX_WAITSOCK || maxsleep=$2
       +
       +     SOCK_REPLY_FILE=$(mktemp $TEMPDIR/ddreply.XXXXXX) || return 7
       +     dd bs=$1 of=$SOCK_REPLY_FILE count=1 <&5 2>/dev/null &
       +        wait_kill $! $maxsleep
       +
       +        return $?
       +}
       +
       +# arg1: name of file with socket reply
       +parse_sslv2_serverhello() {
       +        # server hello:                                                                        in hex representation, see below
       +        # byte 1+2: length of server hello                                                0123
       +        # 3:        04=Handshake message, server hello                        45
       +        # 4:        session id hit or not (boolean: 00=false, this  67
       +        #           is the normal case)
       +        # 5:        certificate type, 01 = x509                                        89
       +        # 6+7       version (00 02 = SSLv2)                                        10-13
       +        # 8+9       certificate length                                                14-17
       +        # 10+11     cipher spec length                                                17-20
       +        # 12+13     connection id length
       +        # [certificate length] ==> certificate
       +        # [cipher spec length] ==> ciphers GOOD: HERE ARE ALL CIPHERS ALREADY!
       +
       +        local ret=3
       +
       +        v2_hello_ascii=$(hexdump -v -e '16/1 "%02X"' $1)
       +        [[ "$DEBUG" -ge 5 ]] && echo "$v2_hello_ascii"
       +        if [[ -z "$v2_hello_ascii" ]]; then
       +                ret=0                                                                # 1 line without any blanks: no server hello received
       +                debugme echo "server hello empty"
       +        else
       +                # now scrape two bytes out of the reply per byte
       +                v2_hello_initbyte="${v2_hello_ascii:0:1}"  # normally this belongs to the next, should be 8!
       +                v2_hello_length="${v2_hello_ascii:1:3}"    # + 0x8000 see above
       +                v2_hello_handshake="${v2_hello_ascii:4:2}"
       +                v2_hello_cert_length="${v2_hello_ascii:14:4}"
       +                v2_hello_cipherspec_length="${v2_hello_ascii:18:4}"
       +
       +                V2_HELLO_CIPHERSPEC_LENGTH=$(printf "%d\n" "0x$v2_hello_cipherspec_length" 2>/dev/null)
       +                [[ $? -ne 0 ]] && ret=7
       +
       +                if [[ $v2_hello_initbyte != "8" ]] || [[ $v2_hello_handshake != "04" ]]; then
       +                        ret=1
       +                        if [[ $DEBUG -ge 2 ]]; then
       +                                echo "no correct server hello"
       +                                echo "SSLv2 server init byte:    0x0$v2_hello_initbyte"
       +                                echo "SSLv2 hello handshake :    0x$v2_hello_handshake"
       +                        fi
       +                fi
       +
       +                if [[ $DEBUG -ge 3 ]]; then
       +                        echo "SSLv2 server hello length: 0x0$v2_hello_length"
       +                        echo "SSLv2 certificate length:  0x$v2_hello_cert_length"
       +                        echo "SSLv2 cipher spec length:  0x$v2_hello_cipherspec_length"
       +                fi
       +        fi
       +        return $ret
       +}
       +
       +
       +# arg1: name of file with socket reply
       +parse_tls_serverhello() {
       +        local tls_hello_ascii=$(hexdump -v -e '16/1 "%02X"' "$1")
       +        local tls_content_type tls_protocol tls_len_all
       +#TODO: all vars here
       +
       +        TLS_TIME=""
       +        DETECTED_TLS_VERSION=""
       +
       +        # server hello, handshake details see http://en.wikipedia.org/wiki/Transport_Layer_Security-SSL#TLS_record
       +        # byte 0:      content type:                        0x14=CCS,    0x15=TLS alert  x16=Handshake,  0x17 Aplication, 0x18=HB
       +        # byte 1+2:    TLS version word, major is 03, minor 00=SSL3, 01=TLS1 02=TLS1.1 03=TLS 1.2
       +        # byte 3+4:    length all
       +        # byte 5:      handshake type (2=hello)                TLS alert: level (2=fatal), descr (0x28=handshake failure)
       +        # byte 6+7+8:  length server hello
       +        # byte 9+10:   03, TLS version word                see byte 1+2
       +        # byte 11-14:  TLS timestamp                                for OpenSSL <1.01f
       +        # byte 15-42:  random, 28 bytes
       +        # byte 43:     session id length
       +        # byte 44+45+sid-len:  cipher suite!
       +        # byte 46+sid-len:     compression method:  00: none, 01: deflate
       +        # byte 47+48+sid-len:  extension length
       +
       +        [[ "$DEBUG" -eq 5 ]] && echo $tls_hello_ascii      # one line without any blanks
       +        if [[ -z "$tls_hello_ascii" ]]; then
       +                debugme echo "server hello empty, TCP connection closed" 
       +                return 1              # no server hello received
       +        fi
       +
       +        # now scrape two bytes out of the reply per byte
       +        tls_content_type="${tls_hello_ascii:0:2}"                  # normally this is x16 (Handshake) here
       +        tls_protocol="${tls_hello_ascii:2:4}"
       +        DETECTED_TLS_VERSION=$tls_protocol
       +
       +        tls_len_all=${tls_hello_ascii:6:4}
       +
       +        sid_len_offset=86
       +        tls_hello="${tls_hello_ascii:10:2}"                        # normally this is x02
       +        tls_protocol2="${tls_hello_ascii:18:4}"
       +        tls_hello_time="${tls_hello_ascii:22:8}"
       +
       +        if [[ $tls_content_type == "15" ]]; then                # TLS ALERT
       +                tls_err_level=${tls_hello_ascii:10:2}                 # 1: warning, 2: fatal
       +                tls_err_descr=${tls_hello_ascii:12:2}                # 112/0x70: Unrecognized name, 111/0x6F: certificate_unobtainable, 
       +                                                                                        # 113/0x71: bad_certificate_status_response, #114/0x72: bad_certificate_hash_value
       +                if [[ $DEBUG -ge 2 ]]; then
       +                        echo "tls_content_type:       0x$tls_content_type"
       +                        echo "tls_protocol:           0x$tls_protocol"
       +                        echo "tls_len_all:            $tls_len_all"
       +                        echo "tls_err_descr:          0x${tls_err_descr} / = $(hex2dec ${tls_err_descr})"
       +                        echo "tls_err_level:          ${tls_err_level} (warning:1, fatal:2)"        
       +                fi
       +                # now, here comes a strange thing... -- on the first glance
       +                # IF an apache 2.2/2.4 server e.g. has a default servername configured but we send SNI <myhostname>
       +                # we get a TLS ALERT saying "unrecognized_name" (0x70) and a warning (0x1), see RFC https://tools.ietf.org/html/rfc6066#page-17
       +                # note that RFC recommended to fail instead: https://tools.ietf.org/html/rfc6066#section-3
       +                # we need to handle this properly -- otherwise we always return that the protocol or cipher is not available!
       +                if [[ "$tls_err_descr" == 70 ]] && [[ "${tls_err_level}" == "01" ]]; then
       +                        sid_len_offset=100                      # we are 2x7 bytes off (formerly: 86 instead of 100)
       +                        tls_hello="${tls_hello_ascii:24:2}"        # here, too       (normally this is (02)
       +                        tls_protocol2="${tls_hello_ascii:32:4}" # here, too
       +                        tls_hello_time="${tls_hello_ascii:36:8}"        # and here, too
       +                else
       +                        return 1
       +                fi
       +        fi
       +
       +        TLS_TIME=$(hex2dec "$tls_hello_time")
       +        tls_sid_len=$(hex2dec "${tls_hello_ascii:$sid_len_offset:2}")
       +        let sid_offset=$sid_len_offset+2+$tls_sid_len*2
       +        tls_cipher_suite="${tls_hello_ascii:$sid_offset:4}"
       +        let sid_offset=$sid_len_offset+6++$tls_sid_len*2
       +        tls_compression_method="${tls_hello_ascii:$sid_offset:2}"
       +
       +        if [[ $DEBUG -ge 2 ]]; then
       +                echo "tls_hello:              0x$tls_hello"
       +                if [[ $DEBUG -ge 4 ]]; then
       +                        echo "tls_protocol2:          0x$tls_protocol2"
       +                        echo "tls_sid_len:            0x$(dec2hex $tls_sid_len) / = $tls_sid_len"
       +                fi
       +                echo -n "tls_hello_time:         0x$tls_hello_time "
       +                if $HAS_GNUDATE ; then
       +                        date --date="@$TLS_TIME" "+%Y-%m-%d %r"
       +                else
       +                        date -j -f %s "$TLS_TIME" "+%Y-%m-%d %r"
       +                fi
       +                echo "tls_cipher_suite:       0x$tls_cipher_suite"
       +                echo "tls_compression_method: 0x$tls_compression_method"
       +                outln
       +        fi
       +        return 0
       +}
       +
       +
       +sslv2_sockets() {
       +        local ciphers_detected
       +
       +        fd_socket 5 || return 6
       +        [[ "$DEBUG" -ge 2 ]] && outln "sending client hello... "
       +        socksend_sslv2_clienthello "$SSLv2_CLIENT_HELLO"
       +
       +        sockread_serverhello 32768
       +        [[ "$DEBUG" -ge 2 ]] && outln "reading server hello... "
       +        if [[ "$DEBUG" -ge 4 ]]; then
       +                hexdump -C "$SOCK_REPLY_FILE" | head -6
       +                outln
       +        fi
       +
       +        parse_sslv2_serverhello "$SOCK_REPLY_FILE"
       +        case $? in
       +                7) # strange reply, couldn't convert the cipher spec length to a hex number
       +                        pr_litemagenta "strange v2 reply "
       +                        outln " (rerun with DEBUG >=2)"
       +                        [[ $DEBUG -ge 3 ]] && hexdump -C "$SOCK_REPLY_FILE" | head -1
       +                        ret=7 ;;
       +                1) # no sslv2 server hello returned, like in openlitespeed which returns HTTP!
       +                        pr_greenln "not offered (OK)"
       +                        ret=0 ;;
       +                0) # reset
       +                        pr_greenln "not offered (OK)"
       +                        ret=0 ;;
       +                3) # everything else
       +                        lines=$(hexdump -C "$SOCK_REPLY_FILE" 2>/dev/null | wc -l | sed 's/ //g')
       +                        [[ "$DEBUG" -ge 2 ]] && out "  ($lines lines)  "
       +                        if [[ "$lines" -gt 1 ]]; then
       +                                ciphers_detected=$((V2_HELLO_CIPHERSPEC_LENGTH / 3))
       +                                if [[ 0 -eq "$ciphers_detected" ]]; then
       +                                        pr_litered "supported but couldn't detect a cipher"; outln " (may need further attention)"
       +                                else
       +                                        pr_red "offered (NOT ok)"; outln " -- $ciphers_detected ciphers"
       +                                fi
       +                                ret=1
       +                        fi ;;
       +        esac
       +        pr_off
       +        debugme outln
       +
       +        close_socket
       +        TMPFILE=$SOCK_REPLY_FILE
       +        tmpfile_handle $FUNCNAME.dd
       +        return $ret
       +}
       +
       +
       +# ARG1: TLS version low byte (00: SSLv3,  01: TLS 1.0,  02: TLS 1.1,  03: TLS 1.2)
       +# ARG2: CIPHER_SUITES string
       +socksend_tls_clienthello() {
       +#FIXME: redo this with all extensions!
       +        local tls_low_byte="$1"
       +        local tls_low_byte1="01"                # the first TLS version number is always 0301 -- except: SSLv3
       +        local servername_hexstr len_servername len_servername_hex
       +        local hexdump_format_str
       +        local all_extensions
       +        local len_sni_listlen len_sni_ext len_extension_hex
       +        local cipher_suites len_ciph_suites len_ciph_suites_word
       +        local len_client_hello_word len_all_word
       +        
       +        #len_servername=$(echo ${#NODE})
       +        len_servername=${#NODE}
       +        hexdump_format_str="$len_servername/1 \"%02x,\""
       +        servername_hexstr=$(printf $NODE | hexdump -v -e "${hexdump_format_str}" | sed 's/,$//')
       +
       +        code2network "$2"                # convert CIPHER_SUITES
       +        cipher_suites="$NW_STR"                # we don't have the leading \x here so string length is two byte less, see next
       +
       +#formatted example for SNI
       +#00 00         # extension server_name
       +#00 1a    # length                               = the following +2 = server_name length + 5
       +#00 18    # server_name list_length        = server_name length +3
       +#00                 # server_name type (hostname)
       +#00 15         # server_name length
       +#66 66 66 66 66 66 2e 66 66 66 66 66 66 66 66 66 66 2e 66 66 66  target.mydomain1.tld # server_name target
       +
       +        # convert lengths we need to fill in from dec to hex:
       +        len_servername_hex=$(printf "%02x\n" $len_servername)
       +        len_sni_listlen=$(printf "%02x\n" $((len_servername+3)))
       +        len_sni_ext=$(printf "%02x\n" $((len_servername+5)))
       +        len_extension_hex=$(printf "%02x\n" $((len_servername+9)))        #FIXME: for TLS 1.2 and IIS servers we need extension_signature_algorithms!!
       +
       +        len_ciph_suites_byte=$(echo ${#cipher_suites})
       +        let "len_ciph_suites_byte += 2"
       +
       +        # we have additional 2 chars \x in each 2 byte string and 2 byte ciphers, so we need to divide by 4:
       +        len_ciph_suites=$(printf "%02x\n" $(($len_ciph_suites_byte / 4 )))
       +        len2twobytes "$len_ciph_suites"
       +        len_ciph_suites_word="$LEN_STR"
       +        #[[ $DEBUG -ge 3 ]] && echo $len_ciph_suites_word
       +
       +        # RFC 3546 doesn't specify SSLv3 to have SNI, openssl just ignores the switch if supplied
       +        if [[ "$tls_low_byte" == "00" ]]; then
       +                len2twobytes $(printf "%02x\n" $((0x$len_ciph_suites + 0x27)))
       +        else
       +                len2twobytes $(printf "%02x\n" $((0x$len_ciph_suites + 0x27 + 0x$len_extension_hex + 0x2)))
       +        fi
       +        len_client_hello_word="$LEN_STR"
       +        #[[ $DEBUG -ge 3 ]] && echo $len_client_hello_word
       +
       +        if [[ "$tls_low_byte" == "00" ]]; then
       +                len2twobytes $(printf "%02x\n" $((0x$len_ciph_suites + 0x2b)))
       +        else
       +                len2twobytes $(printf "%02x\n" $((0x$len_ciph_suites + 0x2b + 0x$len_extension_hex + 0x2)))
       +        fi
       +        len_all_word="$LEN_STR"
       +        #[[ $DEBUG -ge 3 ]] && echo $len_all_word
       +
       +        # if we have SSLv3, the first occurence of TLS protocol is SSLv3, otherwise TLS 1.0
       +        [[ $tls_low_byte == "00" ]] && tls_low_byte1="00"
       +
       +        TLS_CLIENT_HELLO="
       +        # TLS header ( 5 bytes)
       +        ,16, 03, $tls_low_byte1  # TLS Version: in wireshark this is always 00 for TLS 1.0-1.2
       +        ,$len_all_word           # Length  <---
       +        # Handshake header:
       +        ,01                      # Type (x01 for ClientHello)
       +        ,00, $len_client_hello_word   # Length ClientHello
       +        ,03, $tls_low_byte       # TLS Version (again)
       +        ,54, 51, 1e, 7a          # Unix time since  see www.moserware.com/2009/06/first-few-milliseconds-of-https.html
       +        ,de, ad, be, ef          # Random 28 bytes
       +        ,31, 33, 07, 00, 00, 00, 00, 00
       +        ,cf, bd, 39, 04, cc, 16, 0a, 85
       +        ,03, 90, 9f, 77, 04, 33, d4, de
       +        ,00                      # Session ID length
       +        ,$len_ciph_suites_word   # Cipher suites length
       +        ,$cipher_suites
       +        ,01                      # Compression methods length
       +        ,00"                     # Compression method (x00 for NULL)
       +
       +#TODO,add (see heartbleed)
       +# extension lenghth (word)
       +# extension ec_point_formats (4 words) 1st: 00 0b
       +#len                              00 04
       +# ec prot formats len:            03
       +# uncompressed                    00
       +# EC point format: ansiX962_compressed_prime  01
       +# EC point format: ansiX962_compressed_char2  02
       +
       +# ec, 1st:                 00 0a
       +#         2nd length: (word)         e.g. 0x34
       +#         3rd: ec curve len    ln-2  e.g. 0x32
       +#         4.-n.  curves              e.g. 25 words
       +
       +# Extension: Session Ticket        00 23
       +
       +        extension_signature_algorithms="
       +     00, 0d,                    # Type: signature_algorithms , see RFC 5246
       +     00, 20,                    # len
       +     00,1e, 06,01, 06,02, 06,03, 05,01, 05,02, 05,03, 
       +     04,01, 04,02, 04,03, 03,01, 03,02, 03,03, 02,01, 02,02, 02,03"
       +
       +# Extension: Haertbeat             00 0f 
       +# len                              00 01
       +# peer allowed to send requests       01
       +
       +        if [[ "$tls_low_byte" == "00" ]]; then
       +                all_extensions=""
       +        else                                                #FIXME: we (probably) need extension_signature_algorithms here. TLS 1.2 fails on IIS otherwise
       +                all_extensions="
       +                ,00, $len_extension_hex  # first the len of all (here: 1) extentions. We assume len(hostname) < FF - 9
       +                ,00, 00                  # extension server_name
       +                ,00, $len_sni_ext        # length SNI EXT
       +                ,00, $len_sni_listlen    # server_name list_length
       +                ,00                      # server_name type (hostname)
       +                ,00, $len_servername_hex # server_name length
       +                ,$servername_hexstr"     # server_name target
       +        fi
       +
       +        fd_socket 5 || return 6
       +
       +        code2network "$TLS_CLIENT_HELLO$all_extensions"
       +        data=$(echo $NW_STR)
       +        [[ "$DEBUG" -ge 4 ]] && echo "\"$data\""
       +        printf -- "$data" >&5 2>/dev/null &
       +        sleep $USLEEP_SND
       +
       +        return 0
       +}
       +
       +# arg1: TLS version low byte 
       +#       (00: SSLv3,  01: TLS 1.0,  02: TLS 1.1,  03: TLS 1.2)
       +tls_sockets() {
       +        local -i ret=0
       +        local -i save=0
       +        local lines
       +        local tls_low_byte
       +        local cipher_list_2send
       +
       +        tls_low_byte="$1"
       +        if [[ -n "$2" ]]; then                        # use supplied string in arg2 if there is one
       +                cipher_list_2send="$2"
       +        else                                                 # otherwise use std ciphers then
       +                if [[ "$tls_low_byte" == "03" ]]; then
       +                        cipher_list_2send="$TLS12_CIPHER"
       +                else
       +                        cipher_list_2send="$TLS_CIPHER"
       +                fi
       +        fi
       +
       +        [[ "$DEBUG" -ge 2 ]] && echo "sending client hello..."
       +        socksend_tls_clienthello "$tls_low_byte" "$cipher_list_2send"
       +        ret=$?                                                # 6 means opening socket didn't succeed, e.g. timeout
       +
       +        # if sending didn't succeed we don't bother
       +        if [[ $ret -eq 0 ]]; then
       +                sockread_serverhello 32768
       +                TLS_NOW=$(date "+%s")
       +                [[ "$DEBUG" -ge 2 ]] && outln "reading server hello..."
       +                if [[ "$DEBUG" -ge 3 ]]; then
       +                        hexdump -C $SOCK_REPLY_FILE | head -6
       +                        echo
       +                fi
       +
       +                parse_tls_serverhello "$SOCK_REPLY_FILE"
       +                save=$?
       +
       +                # see https://secure.wand.net.nz/trac/libprotoident/wiki/SSL
       +                lines=$(count_lines "$(hexdump -C "$SOCK_REPLY_FILE" 2>$ERRFILE)")
       +                [[ "$DEBUG" -ge 2 ]] && out "  (returned $lines lines)  "
       +
       +                # determine the return value for higher level, so that they can tell what the result is
       +                if [[ $save -eq 1 ]] || [[ $lines -eq 1 ]]; then
       +                        ret=1                # NOT available
       +                else
       +                        if [[ 03$tls_low_byte -eq $DETECTED_TLS_VERSION ]]; then
       +                                ret=0        # protocol available, TLS version returned equal to the one send
       +                        else
       +                                [[ $DEBUG -ge 2 ]] && echo -n "protocol send: 0x03$tls_low_byte, returned: 0x$DETECTED_TLS_VERSION"
       +                                ret=2        # protocol NOT available, server downgraded to $DETECTED_TLS_VERSION
       +                        fi
       +                fi
       +                debugme outln
       +        else
       +                debugme "stuck on sending: $ret"
       +        fi
       +
       +        close_socket
       +        TMPFILE=$SOCK_REPLY_FILE
       +        tmpfile_handle $FUNCNAME.dd
       +        return $ret
       +}
       +
       +
       +####### vulnerabilities follow #######
       +
       +# general overview which browser "supports" which vulnerability:
       +# http://en.wikipedia.org/wiki/Transport_Layer_Security-SSL#Web_browsers
       +
       +
       +# mainly adapted from https://gist.github.com/takeshixx/10107280
       +run_heartbleed(){
       +        [ $VULN_COUNT -le $VULN_THRESHLD ]  && outln && pr_blue "--> Testing for heartbleed vulnerability" && outln "\n"
       +        pr_bold " Heartbleed\c"; out " (CVE-2014-0160)                "
       +
       +     #if [[ -n "$STARTTLS" ]] && [[ $EXPERIMENTAL != "yes" ]]; then
       +        #        outln "(not yet implemented for STARTTLS)"
       +        #        return 0
       +        #fi
       +
       +        # determine TLS versions available:
       +        $OPENSSL s_client $STARTTLS -connect $NODEIP:$PORT $PROXY -tlsextdebug &>$TMPFILE </dev/null
       +
       +        if $HAS_SED_E; then
       +                tls_proto_offered=$(grep -aw Protocol $TMPFILE | sed -E 's/[^[:digit:]]//g')
       +        else
       +                tls_proto_offered=$(grep -aw Protocol $TMPFILE | sed -r 's/[^[:digit:]]//g')
       +        fi
       +        case $tls_proto_offered in
       +                12)        tls_hexcode="x03, x03" ;;
       +                11)        tls_hexcode="x03, x02" ;;
       +                *) tls_hexcode="x03, x01" ;;
       +        esac
       +        heartbleed_payload=", x18, $tls_hexcode, x00, x03, x01, x40, x00"
       +
       +        client_hello="
       +        # TLS header ( 5 bytes)
       +        ,x16,                      # content type (x16 for handshake)
       +        $tls_hexcode,              # TLS version
       +        x00, xdc,                  # length
       +        # Handshake header
       +        x01,                       # type (x01 for ClientHello)
       +        x00, x00, xd8,             # length
       +        $tls_hexcode,              # 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: session ticket TLS
       +        x00, x23, x00, x00,
       +        # extension: heartbeat
       +        x00, x0f, x00, x01, x01"
       +
       +        fd_socket 5 || return 6
       +
       +        [[ $DEBUG -ge 2 ]] && outln "\nsending client hello (TLS version $tls_hexcode)"
       +        socksend "$client_hello" 1
       +        sockread 16384
       +
       +        [[ $DEBUG -ge 2 ]] && outln "\nreading server hello"
       +        if [[ $DEBUG -ge 3 ]]; then
       +                echo "$SOCKREPLY" | "${HEXDUMPVIEW[@]}" | head -20
       +                outln "[...]"
       +                outln "\nsending payload with TLS version $tls_hexcode:"
       +        fi
       +
       +        socksend "$heartbleed_payload" 1
       +        sockread 16384 $HEARTBLEED_MAX_WAITSOCK
       +        retval=$?
       +
       +        if [[ $DEBUG -ge 3 ]]; then
       +                outln "\nheartbleed reply: "
       +                echo "$SOCKREPLY" | "${HEXDUMPVIEW[@]}"
       +                outln
       +        fi
       +
       +        lines_returned=$(echo "$SOCKREPLY" | "${HEXDUMP[@]}" | wc -l | sed 's/ //g')
       +        if [[ $lines_returned -gt 1 ]]; then
       +                pr_red "VULNERABLE (NOT ok)"
       +                ret=1
       +        else
       +                pr_green "not vulnerable (OK)"
       +                ret=0
       +        fi
       +        [[ $retval -eq 3 ]] && out " (timed out)"
       +        outln
       +
       +        close_socket
       +        tmpfile_handle $FUNCNAME.txt
       +        return $ret
       +}
       +
       +# helper function
       +ok_ids(){
       +        pr_greenln "\n ok -- something resetted our ccs packets"
       +        return 0
       +}
       +
       +#FIXME: At a certain point heartbleed and ccs needs to be changed and make use of code2network using a file, then tls_sockets
       +run_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
       +        [[ $VULN_COUNT -le $VULN_THRESHLD ]] && outln && pr_blue "--> Testing for CCS injection vulnerability" && outln "\n"
       +        pr_bold " CCS"; out " (CVE-2014-0224)                       "
       +
       +     #if [[ -n "$STARTTLS" ]] && [[ $EXPERIMENTAL != "yes" ]]; then
       +        #        outln "(not yet implemented for STARTTLS)"
       +        #        return 0
       +        #fi
       +        $OPENSSL s_client $STARTTLS -connect $NODEIP:$PORT $PROXY &>$TMPFILE </dev/null
       +
       +        if $HAS_SED_E; then
       +                tls_proto_offered=$(grep -aw Protocol $TMPFILE | sed -E 's/[^[:digit:]]//g')
       +        else
       +                tls_proto_offered=$(grep -aw Protocol $TMPFILE | sed -r 's/[^[:digit:]]//g')
       +        fi
       +        case $tls_proto_offered in
       +                12)        tls_hexcode="x03, x03" ;;
       +                11)        tls_hexcode="x03, x02" ;;
       +                *) tls_hexcode="x03, x01" ;;
       +        esac
       +        ccs_message=", x14, $tls_hexcode ,x00, x01, x01"
       +
       +        client_hello="
       +        # TLS header (5 bytes)
       +        ,x16,               # content type (x16 for handshake)
       +        $tls_hexcode,       # TLS version
       +        x00, x93,           # length
       +        # Handshake header
       +        x01,                # type (x01 for ClientHello)
       +        x00, x00, x8f,      # length
       +        $tls_hexcode,       # 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"
       +
       +        fd_socket 5 || return 6
       +
       +# we now make a standard handshake ...
       +        debugme out "\nsending client hello, "
       +        socksend "$client_hello" 1
       +        sockread 16384
       +
       +        debugme outln "\nreading server hello"
       +        if [[ $DEBUG -ge 3 ]]; then
       +                echo "$SOCKREPLY" | "${HEXDUMPVIEW[@]}" | head -20
       +                outln "[...]"
       +                outln "\npayload #1 with TLS version $tls_hexcode:"
       +        fi
       +
       +# ... and then send the a change cipher spec message
       +        socksend "$ccs_message" 1 || ok_ids
       +        sockread 2048 $CCS_MAX_WAITSOCK
       +        if [[ $DEBUG -ge 3 ]]; then
       +                outln "\n1st reply: "
       +                out "$SOCKREPLY" | "${HEXDUMPVIEW[@]}" | head -20
       +# ok:      15 | 0301    |  02 | 02 | 0a 
       +#       ALERT | TLS 1.0 | Length=2 | Unexpected Message (0a)
       +#    or just timed out
       +                outln
       +                outln "payload #2 with TLS version $tls_hexcode:"
       +        fi
       +
       +        socksend "$ccs_message" 2 || ok_ids
       +        sockread 2048 $CCS_MAX_WAITSOCK
       +        retval=$?
       +
       +        if [[ $DEBUG -ge 3 ]]; then
       +                outln "\n2nd reply: "
       +                printf -- "$SOCKREPLY" | "${HEXDUMPVIEW[@]}"
       +# not ok:  15 | 0301    | 02 | 02  | 15 
       +#       ALERT | TLS 1.0 | Length=2 | Decryption failed (21)
       +# ok:  0a or nothing: ==> RST
       +                outln
       +        fi
       +
       +        byte6=$(echo "$SOCKREPLY" | "${HEXDUMPPLAIN[@]}" | sed 's/^..........//')
       +        lines=$(echo "$SOCKREPLY" | "${HEXDUMP[@]}" | count_lines )
       +        debugme echo "lines: $lines, byte6: $byte6"
       +
       +        if [[ "$byte6" == "0a" ]] || [[ "$lines" -gt 1 ]]; then
       +                pr_green "not vulnerable (OK)"
       +                ret=0
       +        else
       +                pr_red "VULNERABLE (NOT ok)"
       +                ret=1
       +        fi
       +        [[ $retval -eq 3 ]] && out " (timed out)"
       +        outln
       +
       +        close_socket
       +        tmpfile_handle $FUNCNAME.txt
       +        return $ret
       +}
       +
       +local_problem() {
       +        pr_litemagentaln "Local problem: $1"
       +}
       +
       +run_renego() {
       +# no SNI here. Not needed as there won't be two different SSL stacks for one IP
       +        local legacycmd=""
       +        local insecure_renogo_str="Secure Renegotiation IS NOT"
       +        local sec_renego sec_client_renego
       +
       +        [ $VULN_COUNT -le $VULN_THRESHLD ]  && outln && pr_blue "--> Testing for Renegotiation vulnerability" && outln "\n"
       +
       +        pr_bold " Secure Renegotiation "; out "(CVE-2009-3555)      "         # and RFC5746, OSVDB 59968-59974
       +                                                                                                                # community.qualys.com/blogs/securitylabs/2009/11/05/ssl-and-tls-authentication-gap-vulnerability-discovered
       +        if $OPENSSL s_client $OPTIMAL_PROTO $STARTTLS -connect $NODEIP:$PORT $SNI $PROXY 2>&1 </dev/null &>$TMPFILE; then
       +                grep -iaq "$insecure_renogo_str" $TMPFILE
       +                sec_renego=$?                                                                                        # 0= Secure Renegotiation IS NOT supported
       +#FIXME: didn't occur to me yet but why not also to check on "Secure Renegotiation IS supported"
       +                case $sec_renego in
       +                        0) pr_redln "VULNERABLE (NOT ok)" ;;
       +                        1) pr_greenln "not vulnerable (OK)" ;;
       +                        *) pr_litemagentaln "FIXME (bug): $sec_renego" ;;
       +                esac
       +        else
       +                pr_litemagentaln "handshake didn't succeed" 
       +        fi
       +
       +        pr_bold " Secure Client-Initiated Renegotiation     "        # RFC 5746
       +        # see: https://community.qualys.com/blogs/securitylabs/2011/10/31/tls-renegotiation-and-denial-of-service-attacks
       +        #      http://blog.ivanristic.com/2009/12/testing-for-ssl-renegotiation.html -- head/get doesn't seem to be needed though
       +        case "$OSSL_VER" in
       +                0.9.8*)                          # we need this for Mac OSX unfortunately
       +                        case "$OSSL_VER_APPENDIX" in
       +                                [a-l]) local_problem "$OPENSSL cannot test this secure renegotiation vulnerability"
       +                                          return 3 ;;
       +                                [m-z]) ;; # all ok
       +                        esac ;;
       +                1.0.1*|1.0.2*) legacycmd="-legacy_renegotiation" ;;
       +                0.9.9*|1.0*) ;;   # all ok
       +        esac
       +
       +        # We need up to two tries here, as some LiteSpeed servers don't answer on "R" and block. Thus first try in the background
       +        echo R | $OPENSSL s_client $OPTIMAL_PROTO $legacycmd $STARTTLS -msg -connect $NODEIP:$PORT $SNI $PROXY &>$TMPFILE &         # msg enables us to look deeper into it while debugging
       +        wait_kill $! $HEADER_MAXSLEEP
       +        if [[ $? -eq 3 ]]; then
       +                pr_litegreen "likely not vulnerable (OK)"; outln " (timed out)"                 # it hung
       +                sec_client_renego=1
       +        else
       +                # second try in the foreground as we are sure now it won't hang
       +                echo R | $OPENSSL s_client $legacycmd $STARTTLS -msg -connect $NODEIP:$PORT $SNI $PROXY &>$TMPFILE
       +                sec_client_renego=$?                                                                                                        # 0=client is renegotiating & doesn't return an error --> vuln!
       +                case $sec_client_renego in
       +                        0) pr_litered "VULNERABLE (NOT ok)"; outln ", DoS threat" ;;
       +                        1) pr_litegreenln "not vulnerable (OK)" ;;
       +                        *) "FIXME (bug): $sec_client_renego" ;;
       +                esac
       +        fi
       +
       +        #FIXME Insecure Client-Initiated Renegotiation is missing
       +
       +        tmpfile_handle $FUNCNAME.txt
       +        return $(($sec_renego + $sec_client_renego))
       +#FIXME: the return value is wrong, should be 0 if all ok. But as the caller doesn't care we don't care either ... yet ;-)
       +}
       +
       +run_crime() {
       +        local -i ret=0
       +        local addcmd=""
       +        # 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
       +
       +        [ $VULN_COUNT -le $VULN_THRESHLD ]  && outln && pr_blue "--> Testing for CRIME vulnerability" && outln "\n"
       +        pr_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
       +                local_problem "$OPENSSL lacks zlib support"
       +                return 7
       +        fi
       +
       +        [[ "$OSSL_VER" == "*0.9.8*" ]] && addcmd="-no_ssl2" 
       +        $OPENSSL s_client $OPTIMAL_PROTO $addcmd $STARTTLS -connect $NODEIP:$PORT $PROXY $SNI </dev/null &>$TMPFILE
       +        if grep -a Compression $TMPFILE | grep -aq NONE >/dev/null; then
       +                pr_litegreen "not vulnerable (OK)"
       +                [[ $SERVICE == "HTTP" ]] || out " (not using HTTP anyway)"
       +                ret=0
       +        else
       +                if [[ $SERVICE == "HTTP" ]]; then
       +                        pr_litered "VULNERABLE (NOT ok)"
       +                else
       +                        pr_brown "VULNERABLE (NOT ok), but not using HTTP: probably no exploit known"
       +                fi
       +                ret=1
       +        fi
       +        # not clear whether this is a protocol != HTTP as one needs to have the ability to modify the
       +        # compression input which is done via javascript in the context of HTTP
       +        outln
       +
       +# 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
       +#                        pr_bold "CRIME Vulnerability, SPDY \c" ; outln "(CVE-2012-4929): \c"
       +
       +#                        STR=$(grep Compression $TMPFILE )
       +#                        if echo $STR | grep -q NONE >/dev/null; then
       +#                                pr_green "not vulnerable (OK)"
       +#                                ret=$((ret + 0))
       +#                        else
       +#                                pr_red "VULNERABLE (NOT ok)"
       +#                                ret=$((ret + 1))
       +#                        fi
       +#                fi
       +#        fi
       +#        [[ $DEBUG -eq 2 ]] outln "$STR"
       +        tmpfile_handle $FUNCNAME.txt
       +        return $ret
       +}
       +
       +# BREACH is a 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/ . Foreign referrers are the important thing here!
       +run_breach() {
       +        local header
       +        local -i ret=0
       +        local referer useragent
       +        local url
       +
       +        [[ $SERVICE != "HTTP" ]] && return 7
       +
       +        [[ $VULN_COUNT -le $VULN_THRESHLD ]] && outln && pr_blue "--> Testing for BREACH (HTTP compression) vulnerability" && outln "\n"
       +        pr_bold " BREACH"; out " (CVE-2013-3587)                    "
       +
       +        url="$1"
       +        [[ -z "$url" ]] && url="/"
       +        if $SNEAKY; then
       +                # see https://community.qualys.com/message/20360
       +                if [[ "$NODE" =~ google ]]; then
       +                        referer="http://yandex.ru/" # otherwise we have a false positive for google.com
       +                else
       +                        referer="http://google.com/"
       +                fi
       +                useragent="$UA_SNEAKY"
       +        else
       +                referer="TLS/SSL-Tester from $SWURL"
       +                useragent="$UA_STD"
       +        fi
       +        (
       +        $OPENSSL s_client $OPTIMAL_PROTO -quiet -connect $NODEIP:$PORT $PROXY $SNI << EOF
       +GET $url HTTP/1.1
       +Host: $NODE
       +User-Agent: $useragent
       +Accept: text/*
       +Accept-Language: en-US,en
       +Accept-encoding: gzip,deflate,compress
       +Referer: $referer
       +Connection: close
       +
       +EOF
       +) >$HEADERFILE_BREACH 2>$ERRFILE &
       +        if wait_kill $! $HEADER_MAXSLEEP; then
       +                result=$(grep -a '^Content-Encoding' $HEADERFILE_BREACH | sed -e 's/^Content-Encoding//' -e 's/://' -e 's/ //g')
       +                result=$(echo $result | tr -cd '\40-\176')
       +                if [[ -z $result ]]; then
       +                        pr_green "no HTTP compression (OK) "
       +                        ret=0
       +                else
       +                        pr_litered "NOT ok: uses $result HTTP compression "
       +                        ret=1
       +                fi
       +                # Catch: any URL can be vulnerable. I am testing now only the root. URL!
       +                outln "(only \"$url\" tested)"
       +        else
       +                pr_litemagentaln "failed (HTTP header request stalled)"
       +                ret=3
       +        fi
       +        return $ret
       +}
       +
       +# Padding Oracle On Downgraded Legacy Encryption, in a nutshell: don't use CBC Ciphers in SSLv3
       +run_ssl_poodle() {
       +        local -i ret=0
       +        local cbc_ciphers
       +        local cbc_ciphers="SRP-DSS-AES-256-CBC-SHA:SRP-RSA-AES-256-CBC-SHA:SRP-AES-256-CBC-SHA:RSA-PSK-AES256-CBC-SHA:PSK-AES256-CBC-SHA:SRP-DSS-AES-128-CBC-SHA:SRP-RSA-AES-128-CBC-SHA:SRP-AES-128-CBC-SHA:IDEA-CBC-SHA:IDEA-CBC-MD5:RC2-CBC-MD5:RSA-PSK-AES128-CBC-SHA:PSK-AES128-CBC-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:SRP-DSS-3DES-EDE-CBC-SHA:SRP-RSA-3DES-EDE-CBC-SHA:SRP-3DES-EDE-CBC-SHA:EDH-RSA-DES-CBC3-SHA:EDH-DSS-DES-CBC3-SHA:DH-RSA-DES-CBC3-SHA:DH-DSS-DES-CBC3-SHA:AECDH-DES-CBC3-SHA:ADH-DES-CBC3-SHA:ECDH-RSA-DES-CBC3-SHA:ECDH-ECDSA-DES-CBC3-SHA:DES-CBC3-SHA:DES-CBC3-MD5:RSA-PSK-3DES-EDE-CBC-SHA:PSK-3DES-EDE-CBC-SHA:EXP1024-DHE-DSS-DES-CBC-SHA:EDH-RSA-DES-CBC-SHA:EDH-DSS-DES-CBC-SHA:DH-RSA-DES-CBC-SHA:DH-DSS-DES-CBC-SHA:ADH-DES-CBC-SHA:EXP1024-DES-CBC-SHA:DES-CBC-SHA:EXP1024-RC2-CBC-MD5:DES-CBC-MD5:EXP-EDH-RSA-DES-CBC-SHA:EXP-EDH-DSS-DES-CBC-SHA:EXP-ADH-DES-CBC-SHA:EXP-DES-CBC-SHA:EXP-RC2-CBC-MD5:EXP-RC2-CBC-MD5"
       +        local cbc_ciphers_krb="KRB5-IDEA-CBC-SHA:KRB5-IDEA-CBC-MD5:KRB5-DES-CBC3-SHA:KRB5-DES-CBC3-MD5:KRB5-DES-CBC-SHA:KRB5-DES-CBC-MD5:EXP-KRB5-RC2-CBC-SHA:EXP-KRB5-DES-CBC-SHA:EXP-KRB5-RC2-CBC-MD5:EXP-KRB5-DES-CBC-MD5"
       +
       +        [ $VULN_COUNT -le $VULN_THRESHLD ]  && outln && pr_blue "--> Testing for SSLv3 POODLE (Padding Oracle On Downgraded Legacy Encryption)" && outln "\n"
       +        pr_bold " POODLE, SSL"; out " (CVE-2014-3566)               "
       +        cbc_ciphers=$($OPENSSL ciphers -v 'ALL:eNULL' 2>$ERRFILE | awk '/CBC/ { print $1 }' | tr '\n' ':')
       +#FIXME: even with worst openssl client (FreeBSD9) we have 17 reasonable ciphers but is that enough to check??
       +        debugme echo $cbc_ciphers
       +        $OPENSSL s_client -ssl3 $STARTTLS -cipher $cbc_ciphers -connect $NODEIP:$PORT $PROXY $SNI &>$TMPFILE </dev/null
       +        ret=$?
       +        [[ $DEBUG -eq 2 ]] && egrep -q "error|failure" $TMPFILE | egrep -av "unable to get local|verify error"
       +        if [[ $ret -eq 0 ]]; then
       +                pr_litered "VULNERABLE (NOT ok)"; out ", uses SSLv3+CBC (check TLS_FALLBACK_SCSV mitigation below)"
       +        else
       +                pr_green "not vulnerable (OK)"
       +        fi
       +        outln
       +        tmpfile_handle $FUNCNAME.txt
       +        return $ret
       +}
       +
       +# for appliance which use padding, no fallback needed
       +run_tls_poodle() {
       +        pr_bold " POODLE, SSL"; out " CVE-2014-8730), experimental "
       +        #FIXME
       +        echo "#FIXME"
       +        return 7
       +}
       +
       +run_tls_fallback_scsv() {
       +        local -i ret=0
       +
       +        [ $VULN_COUNT -le $VULN_THRESHLD ]  && outln && pr_blue "--> Testing for TLS_FALLBACK_SCSV Protection" && outln "\n"
       +        pr_bold " TLS_FALLBACK_SCSV"; out " (RFC 7507), experim.    "
       +        # This isn't a vulnerability check per se, but checks for the existence of
       +        # the countermeasure to protect against protocol downgrade attacks.
       +
       +        # First check we have support for TLS_FALLBACK_SCSV in our local OpenSSL
       +        $OPENSSL s_client -h 2>&1 | grep -q "\-fallback_scsv"
       +        if [[ $? -gt 0 ]]; then
       +                local_problem "$OPENSSL lacks TLS_FALLBACK_SCSV support"
       +                return 4
       +        fi
       +        #TODO: this need some tuning: a) if one protocol is supported only it has practcally no value (theoretical it's interesting though)
       +        # b) for IIS6 + openssl 1.0.2 this won't work
       +        # c) best to make sure that we hit a specific protocol, see https://alpacapowered.wordpress.com/2014/10/20/ssl-poodle-attack-what-is-this-scsv-thingy/
       +        # d) minor: we should do "-state" here
       +
       +        # first: make sure we have tls1_2:
       +        if ! $OPENSSL s_client $STARTTLS -connect $NODEIP:$PORT $PROXY $SNI -no_tls1_2  &>/dev/null </dev/null; then
       +                pr_litemagenta "Check failed: seems like TLS 1.2 is the only protocol "
       +                ret=7
       +        else
       +                # ...and do the test
       +                $OPENSSL s_client $STARTTLS -connect $NODEIP:$PORT $PROXY $SNI -no_tls1_2 -fallback_scsv &>$TMPFILE </dev/null
       +                if grep -q "CONNECTED(00" "$TMPFILE"; then
       +                        if grep -qa "BEGIN CERTIFICATE" "$TMPFILE"; then
       +                                pr_brown "Downgrade attack prevention NOT supported"
       +                                ret=1
       +                        elif grep -qa "alert inappropriate fallback" "$TMPFILE"; then
       +                                pr_litegreen "Downgrade attack prevention supported (OK)"
       +                                ret=0
       +                        elif grep -qa "alert handshake failure" "$TMPFILE"; then
       +                                # see RFC 7507, https://github.com/drwetter/testssl.sh/issues/121
       +                                pr_brown "\"handshake failure\" instead of \"inappropriate fallback\" (likely NOT ok)"
       +                                ret=2
       +                        elif grep -qa "ssl handshake failure" "$TMPFILE"; then
       +                                pr_brown "some unexpected \"handshake failure\" instead of \"inappropriate fallback\" (likely NOT ok)"
       +                                ret=3
       +                        else
       +                                pr_litemagenta "Check failed, unexpected result "
       +                                out ", run $PROG_NAME -Z --debug=1 and look at $TEMPDIR/*tls_fallback_scsv.txt"
       +                        fi
       +                else
       +                        pr_litemagenta "test failed (couldn't connect)"
       +                        ret=7
       +                fi
       +        fi
       +
       +        outln
       +        tmpfile_handle $FUNCNAME.txt
       +        return $ret
       +}
       +
       +
       +# Factoring RSA Export Keys: don't use EXPORT RSA ciphers, see https://freakattack.com/
       +run_freak() {
       +        local -i ret=0
       +        local -i no_supported_ciphers=0
       +        # with correct build it should list these 7 ciphers (plus the two latter as SSLv2 ciphers):
       +        local exportrsa_cipher_list="EXP1024-DES-CBC-SHA:EXP1024-RC4-SHA:EXP-EDH-RSA-DES-CBC-SHA:EXP-DH-RSA-DES-CBC-SHA:EXP-DES-CBC-SHA:EXP-RC2-CBC-MD5:EXP-RC2-CBC-MD5:EXP-RC4-MD5:EXP-RC4-MD5"
       +        local addtl_warning=""
       +
       +        [ $VULN_COUNT -le $VULN_THRESHLD ]  && outln && pr_blue "--> Testing for FREAK attack" && outln "\n"
       +        pr_bold " FREAK"; out " (CVE-2015-0204)                     "
       +
       +        no_supported_ciphers=$(count_ciphers $(actually_supported_ciphers $exportrsa_cipher_list))
       +        #echo "========= ${PIPESTATUS[*]}
       +
       +        case $no_supported_ciphers in
       +                0)         local_problem "$OPENSSL doesn't have any EXPORT RSA ciphers configured"
       +                        return 7 ;;
       +                1|2|3)
       +                        addtl_warning=" ($magenta""tested only with $no_supported_ciphers out of 9 ciphers only!$off)" ;;
       +                8|9|10|11)
       +                        addtl_warning="" ;;
       +                4|5|6|7)
       +                        addtl_warning=" (tested with $no_supported_ciphers/9 ciphers)" ;;
       +        esac
       +        $OPENSSL s_client $STARTTLS -cipher $exportrsa_cipher_list -connect $NODEIP:$PORT $PROXY $SNI &>$TMPFILE </dev/null
       +        ret=$?
       +        [[ $DEBUG -eq 2 ]] && egrep -a "error|failure" $TMPFILE | egrep -av "unable to get local|verify error"
       +        if [[ $ret -eq 0 ]]; then
       +                pr_red "VULNERABLE (NOT ok)"; out ", uses EXPORT RSA ciphers"
       +        else
       +                pr_green "not vulnerable (OK)"; out "$addtl_warning"
       +        fi
       +        outln
       +
       +        debugme echo $(actually_supported_ciphers $exportrsa_cipher_list)
       +        debugme echo $no_supported_ciphers
       +
       +        tmpfile_handle $FUNCNAME.txt
       +        return $ret
       +}
       +
       +
       +# see https://weakdh.org/logjam.html
       +run_logjam() {
       +        local -i ret=0
       +        local exportdhe_cipher_list="EXP1024-DHE-DSS-DES-CBC-SHA:EXP1024-DHE-DSS-RC4-SHA:EXP-EDH-RSA-DES-CBC-SHA:EXP-EDH-DSS-DES-CBC-SHA"
       +        local -i no_supported_ciphers=0
       +        local addtl_warning=""
       +
       +        [ $VULN_COUNT -le $VULN_THRESHLD ]  && outln && pr_blue "--> Testing for LOGJAM vulnerability" && outln "\n"
       +        pr_bold " LOGJAM"; out " (CVE-2015-4000), experimental      "
       +
       +        no_supported_ciphers=$(count_ciphers $(actually_supported_ciphers $exportdhe_cipher_list))
       +
       +        case $no_supported_ciphers in
       +                0)         local_problem "$OPENSSL doesn't have any DHE EXPORT ciphers configured"
       +                        return 3 ;;
       +                1|2) addtl_warning=" ($magenta""tested w/ $no_supported_ciphers/4 ciphers only!$off)" ;;
       +                3) addtl_warning=" (tested w/ $no_supported_ciphers/4 ciphers)" ;;
       +                4)        ;;
       +        esac
       +        $OPENSSL s_client $STARTTLS -cipher $exportdhe_cipher_list -connect $NODEIP:$PORT $PROXY $SNI &>$TMPFILE </dev/null
       +        ret=$?
       +        [[ $DEBUG -eq 2 ]] && egrep -a "error|failure" $TMPFILE | egrep -av "unable to get local|verify error"
       +        addtl_warning="$addtl_warning, common primes not checked."
       +        if $HAS_DH_BITS; then
       +                if ! $do_allciphers && ! $do_cipher_per_proto && $HAS_DH_BITS; then
       +                        addtl_warning="$addtl_warning \"$PROG_NAME -E/-e\" spots candidates"
       +                else
       +                        addtl_warning="$addtl_warning See below for any DH ciphers + bit size"
       +                fi
       +        fi
       +                
       +        if [[ $ret -eq 0 ]]; then
       +                pr_red "VULNERABLE (NOT ok)"; out ", uses DHE EXPORT ciphers, common primes not checked."
       +        else
       +                pr_green "not vulnerable (OK)"; out "$addtl_warning"
       +        fi
       +        outln
       +
       +        debugme echo $(actually_supported_ciphers $exportdhe_cipher_list)
       +        debugme echo $no_supported_ciphers
       +
       +        tmpfile_handle $FUNCNAME.txt
       +        return $ret
       +}
       +# TODO: perfect candidate for replacement by sockets, so is freak
       +
       +
       +
       +# Browser Exploit Against SSL/TLS: don't use CBC Ciphers in SSLv3 TLSv1.0
       +run_beast(){
       +        local hexcode dash cbc_cipher sslvers kx auth enc mac export
       +        local detected_proto
       +        local -i ret=0
       +        local detected_cbc_ciphers=""
       +        local higher_proto_supported=""
       +        local openssl_ret=0
       +        local vuln_beast=false
       +        local spaces="                                           "
       +        local cr=$'\n'
       +        local first=true
       +        local continued=false
parazyd.org:70 /git/scripts/commit/b52b934adf0622975d5a61dcf938e4f80ce1e9d2.gph:4969: line too long