#!/bin/bash
# -*- mode: sh; tab-width: 8; coding: utf-8-unix -*-

. /usr/local/bin/usr_local_tput.bash || exit 2
PREFIX=/usr/local
ROLE=proxy
DELAY=10
prog=proxy_whonix_host

PL=$PREFIX/bin/proxy_libvirt_lib.bash

USAGE="config|from_tor|to_tor|start|status|test|refresh|update"

[ -f /usr/local/etc/testforge/testforge.bash ] && \
    . /usr/local/etc/testforge/testforge.bash
[ $( id -u ) -eq 0 ] || { ERROR $prog should be run as root ; exit 1 ; }

. /usr/local/sbin/proxy_whonix_lib.bash || \
    { ERROR loading /usr/local/sbin/proxy_whonix_lib.bash ; exit 2; }
. /usr/local/bin/proxy_ping_lib.bash || exit 3

prog=proxy_whonix_host
[ -z "$MODE" ] && MODE=`proxy_ping_mode`

HTTP_PROXY_PORT=3128
HTTP_PROXY_HOST=127.0.0.1
HTTPS_PORT=9128
HTTPS_HOST=127.0.0.1
proxy_ping_get_socks
[ -z "$SOCKS_HOST" ] || SOCKS_HOST=127.0.0.1
[ -z "$SOCKS_PORT" ] || SOCKS_PORT=9050
proxy_ping_get_https
proxy_ping_get_http

WD=$PWD

NEEDED_DIRS=""
# /usr/local/lib/helper-scripts
# /usr/local/etc/ssl

NEEDED_SCRIPTS="
/usr/local/bin/proxy_get_if.bash
/usr/local/bin/proxy_libvirt_hook_qemu.bash
/usr/local/bin/proxy_ping_lib.bash
/usr/local/bin/proxy_ping_test.bash
/usr/local/etc/jnettop.conf
/usr/local/lib/helper-scripts/tor_bootstrap_check.py
/usr/local/lib/helper-scripts/tor_bootstrap_check.bsh
/usr/local/etc/ssl/cacert-testforge.pem
/usr/local/sbin/Whonix-Gateway.rc
/usr/local/sbin/debian_cache_to_archives.bash
/usr/local/sbin/debian_elts_to_uris.bash
/usr/local/sbin/debian_uris_to_urls.bash
/usr/local/sbin/proxy_libvirt_ga_test.bash
/usr/local/sbin/proxy_whonix_gateway_tor.bash
/usr/local/sbin/proxy_whonix_guest_gateway.bash
/usr/local/sbin/proxy_whonix_host-firewall.bash
/usr/local/sbin/proxy_whonix_host_lib.bash
/usr/local/sbin/proxy_whonix_host.bash
/usr/local/sbin/proxy_whonix_host_tor.bash
/usr/local/sbin/root_nm_wireless.bash
"

proxy_install_package () {
    for pkg in $* ; do
    if [ -d /etc/apt ] ; then
        [ "$pkg" = guestfish ] && pkg=libguestfs-tools
        apt-get install -y $pkg || return $?
    elif [ -d /etc/portage ] ; then
        apt-get install -y $pkg || return $?
      fi
      done
    return 0
}

## proxy_whonix_host_dmesg_blocks
proxy_whonix_host_dmesg_blocks () {
    local retval=0

    [ -f /etc/firewall.conf.block ] || touch /etc/firewall.conf.block
    [ -z "$PROXY_WLAN" ] && PROXY_WLAN=`proxy_get_if` && retval=$?
    [ $retval -ne 0 -o -z "$PROXY_WLAN" ] && {
	ERROR $prog null interface && return 1
	}
    dmesg|tail -1000 | grep IPTABLES_FWI_REJECT-o| \
	sed -e 's/.*SRC=//' -e 's/ .*//'|sort -u| \
	while read elt ; do
	    grep -q $elt /etc/firewall.conf.block && continue
	    grep -q $elt /etc/firewall.conf && continue
	    echo $elt >> /etc/firewall.conf.block
	done
    [ -s /etc/firewall.conf.block ] || proxy_whonix_host_prepare_blocks || return 1$?
    proxy_whonix_host_add_block $( cat /etc/firewall.conf.block ) || return 2$?

    if [ ! -f /etc/firewall.conf.$$ -o ! -f /etc/firewall.conf ] ; then
	return 3
    elif diff /etc/firewall.conf.$$ /etc/firewall.conf ; then
	return 4
    else
	base_wall.bash WARN: $prog BLOCKING \
	  $(diff /etc/firewall.conf.$$ /etc/firewall.conf | grep -v , | cut -f 7 -d ' ') \
	  in /etc/firewall.conf.block
	proxy_ping_wlan_config /etc/firewall.conf.$$
	mv /etc/firewall.conf /etc/firewall.conf.bak && \
	    mv /etc/firewall.conf.$$ /etc/firewall.conf && \
	    /usr/local/bin/proxy_libvirt_hook_network.bash
    fi
    return 0
}

## proxy_whonix_host_refresh
proxy_whonix_host_refresh () {
    local dire
    [ "$#" -gt 0 ] && dire=$1
    [ -z "$dire" ] && dire=$( proxy_ping_mode )
    if [ $dire = whonix ] ; then
        $PL proxy_libvirt_clean_iptables
        proxy_whonix_host_dmesg_blocks
      fi
    return 0
}

## proxy_whonix_host_update
proxy_whonix_host_update () {
    local copy_in

    # use nbd instead
    return 0

    DOM=$( proxy_whonix_get_gateway_dom )
    [ -z "$DOM" ] && \
	WARN proxy_whonix_host_update empty DOM from proxy_whonix_get_gateway_dom && \
	DOM=Whonix-Gateway
    cd /usr/local/sbin/

    cp -p $PWD/$DOM.rc rc.local
    copy_in="copy-in $PWD/rc.local /etc"
    for dir in $NEEDED_DIRS ; do
	copy_in="$copy_in
mkdir $dir
"
    done
    for file in $NEEDED_SCRIPTS ; do
	dir=$( dirname $file )
	copy_in="$copy_in
copy-in $file $dir
"
    done

    QCOW=/var/lib/libvirt/images/$DOM.qcow2
    if [ -f $QCOW ] ; then
	which virsh 2>/dev/null >/dev/null || proxy_install_package libvirt
	proxy_virsh list | grep -q $DOM && virsh shutdown $DOM && echo sleep 60 && sleep 60
	which guestfish 2>/dev/null >/dev/null || proxy_install_package guestfish
	INFO copying in $( echo $NEEDED_SCRIPTS| wc -w ) files
	guestfish -a $QCOW << EOF
run
mount /dev/sda1 /
$copy_in
umount /
EOF
      fi
    rm -f rc.local

    return 0
}

## proxy_whonix_host_config
proxy_whonix_host_config () {
    local dire
    local retval=0
    [ "$#" -gt 0 ] && dire=$1
    [ -z "$dire" ] && dire=$( proxy_ping_mode )
    DBUG proxy_whonix_host_config dire=$dire

    [ -z "$PROXY_WLAN" ] && PROXY_WLAN=`proxy_get_if` && retval=$?
    [ $retval -ne 0 -o -z "$PROXY_WLAN" ] && {
	ERROR proxy_whonix_host_config null interface && return 1
    }

    proxy_ping_firewall_restart
    proxy_ping_firewall_check || {
	ERROR /etc/firewall.conf missing $? ; return 2 ;
    }

    proxy_ping_test_resolv $dire || return 4$?

    proxy_whonix_privoxy_config $dire
    proxy_ping_dnsmasq_config $dire || return 3$?

    if [ -f /etc/inittab ] ; then
	grep -q '^x1' /etc/inittab  || \
	    sed -e 's/^x1/#x1/' -i /etc/inittab
	#  x1:12345:respawn:/sbin/agetty
    fi

    proxy_ping_firewall_modules
    if [ "$dire" = whonix ] ; then
	[ -f /var/lib/libvirt/images/Whonix-Gateway.qcow2  ] || \
	    WARN /var/lib/libvirt/images/Whonix-Gateway.qcow2  - mount /mnt/linuxKick150154

	if [ -s /etc/firewall.conf.$dire ] ; then
	    proxy_ping_wlan_config /etc/firewall.conf.$dire /etc/firewall.conf
	    if ! diff -q  /etc/firewall.conf.$dire  /etc/firewall.conf ; then
		cp -p  /etc/firewall.conf.$dire  /etc/firewall.conf
		proxy_iptables_restore  /etc/firewall.conf || return 3
	    fi
	 elif [ -s /etc/firewall.conf ] ; then
		iptables-save |grep -q virbr1 || {
		    proxy_iptables_restore  /etc/firewall.conf || return 4
		}
	 else
	     [ -s /etc/firewall.conf.new ] || \
		 /usr/local/sbin/privacy_whonix_host-firewall.bash || \
		 { ERROR " $prog privacy_whonix_host-firewall.bash failed " ; return 5 ; }
	     [ -s /etc/firewall.conf.new ] || \
		 { ERROR "  /etc/firewall.conf.new missing " ; return 6 ; }
	     [ -s /etc/firewall.conf ] || cp -p /etc/firewall.conf.new /etc/firewall.conf
	     proxy_iptables_restore <  /etc/firewall.conf || return 7
	    fi

        proxy_host_whonix_config $dire

    elif [ "$dire" = selektor -o "$dire" = tor ] ; then
	proxy_host_selektor_config $dire
    fi


    return 0
}

proxy_host_selektor_config () { DBUG proxy_host_selektor_config ;
    local dire=$1

    # /var/lib/tor/.SelekTOR/3xx/SelekTOR.xml
    if [ -s /etc/firewall.conf.$dire ] ; then
	    proxy_ping_wlan_config /etc/firewall.conf.$dire /etc/firewall.conf
	    if ! diff -q /etc/firewall.conf.$dire  /etc/firewall.conf ; then
		cp -p  /etc/firewall.conf.$dire  /etc/firewall.conf
		proxy_iptables_restore  /etc/firewall.conf || return 8
	    elif [ -s /etc/firewall.conf ] ; then
		iptables-save |grep -q gid-owner || \
		    proxy_iptables_restore  /etc/firewall.conf || return 9
	    else
		{ ERROR "  /etc/firewall.conf.$dire missing " ; return 7 ; }
	    fi
    fi

    return 0
}

## proxy_whonix_host_install
proxy_whonix_host_install () { DBUG proxy_whonix_host_install $* ;

    if [ $dire = host ] ; then
	ERROR proxy_whonix_host_install host
	return 1
    elif [ $dire = whonix ] ; then
	proxy_whonix_libvirt_start
	proxy_whonix_gateway_start $dire
    else
	if /etc/init.d/libvirtd status ; then
	    proxy_virsh list | grep -q Whonix-Gateway && \
		proxy_virsh shutdown Whonix-Gateway
	    fi
    fi

    /usr/local/sbin/proxy_whonix_host_tor.bash $dire || return 7$?

    return 0
}

## proxy_host_from_config
proxy_host_from_config () {
    #? rm -f /etc/modules_load.d/vda*conf

    DOM=$( proxy_whonix_get_gateway_dom )
    [ -z "$DOM" ] && \
	WARN proxy_host_whonix_config empty DOM assuming Whonix-Gateway && \
	DOM=Whonix-Gateway

    if [ -d /etc/libvirt/qemu/ -a  /etc/libvirt/qemu/$DOM.xml ] ; then
	if [ ! -f /etc/libvirt/qemu/$DOM.xml.dst ] ; then
	    cd /etc/libvirt/qemu/
	    cp -p /etc/libvirt/qemu/$DOM.xml /etc/libvirt/qemu/$DOM.xml.dst
	    for file in $WD/$DOM.xml.?.diff ; do
		[ -f /etc/libvirt/qemu/$DOM.xml ] || \
		    ERROR $prog /etc/libvirt/qemu/$DOM.xml missing ; return 2
		patch /etc/libvirt/qemu/$DOM.xml < $file
	    done
	    cd $WD
	fi
    fi
    return 0
}
## proxy_host_from_config
proxy_host_whonix_config () {
    local dire=whonix
    local file

    [ -x /usr/local/bin/proxy_libvirt_hook_network.bash ] || return 1

    if false && ! [ -x /etc/libvirt/hooks/network ]  ; then
	cat > /etc/libvirt/hooks/network <<EOF
# BEGIN ANSIBLE MANAGED BLOCK proxy whonix_host.yml
[ ! -f /usr/local/bin/proxy_libvirt_hook_network.bash ] || \
  /usr/local/bin/proxy_libvirt_hook_network.bash
# END ANSIBLE MANAGED BLOCK proxy whonix_host.yml
EOF
	chmod 755 /etc/libvirt/hooks/network
    fi

    return 0
}

## proxy_whonix_host_verify
proxy_whonix_host_verify () {
    $0 --help > /dev/null || return 6
    $0 -h > /dev/null || return 7
    for elt in $( echo $USAGE | sed -e 's/|/ /g' ) ; do
	grep -q ^proxy_whonix_host_$elt $0 || { WARN proxy_whonix_host_$elt NOT in $0 ; return 8 ; }
    done

    return 0
}

## proxy_whonix_host_status
proxy_whonix_host_status () { proxy_whonix_host_test "$@" ; }

## proxy_whonix_host_test
proxy_whonix_host_test () {
    local dire
    [ "$#" -gt 0 ] && dire=$1
    [ -z "$dire" ] && dire=$( proxy_ping_mode )

    proxy_whonix_host_verify

    proxy_ping_status

    /usr/local/bin/proxy_ping_test.bash $dire || \
	    WARN $prog proxy_ping_test.bash FAILED $dire

    if [ "$dire" = whonix ] ; then
        grep "`date +%Y-%m-%d`.* error :" /var/local/log/libvirtd.log
	proxy_whonix_host_tor.bash proxy_libvirt_test || return 1
	proxy_virsh list | grep running || return 2

    # FixMe look in /etc/libvirt/qemu
    for elt in Whonix-Gateway Whonix-Workstation Pen19-1 Kick15-1 ; do
	proxy_virsh list | grep -q $elt || continue
	# /usr/local/sbin/proxy_libvirt_ga_test.bash $elt /bin/netstat -lnp4 ||
	/usr/local/sbin/proxy_libvirt_ga_test.bash $elt ls /dev/virtio-ports/ || \
	    WARN $prog $elt not responding
	# fallsover with
	# error: internal error: unable to execute QEMU agent command 'guest-exec-status': Invalid parameter 'pid'
      done
    fi

    return 0
}

## proxy_whonix_host_restart
proxy_whonix_host_restart () {
    local dire
    [ "$#" -gt 0 ] && dire=$1 || dire=$MODE

    proxy_whonix_host_start $dire || return 1$?
    proxy_whonix_host_status $dire || return 2$?
    return 0
}

## proxy_whonix_host_selektor
proxy_whonix_host_selektor () {
    local dire=selektor
    proxy_whonix_host_start $dire
    return $?
}

## proxy_whonix_host_from_tor
proxy_whonix_host_from_tor () {
    local dire=whonix
    proxy_whonix_host_start $dire
    return $?
}

## proxy_whonix_host_to_tor
proxy_whonix_host_to_tor () {
    local dire=tor
    proxy_virsh list | grep -q Whonix-Gateway && proxy_virsh shutdown Whonix-Gateway
    proxy_whonix_host_start $dire
    return $?
}

## proxy_whonix_stop
proxy_whonix_stop () {
    local dire
    [ "$#" -gt 0 ] && dire=$1
    [ -z "$dire" ] && dire=$( proxy_ping_mode )
    DBUG proxy_whonix_stop $*

    if [ $dire = whonix -o $dire = host -o $dire = tor ] ; then
        proxy_whonix_host_stop $dire
    fi
    return 0
}

## proxy_whonix_libvirt_stop
proxy_whonix_libvirt_stop () {

    proxy_virsh net-list | grep -q Whonix-External && \
      virsh net-destroy Whonix-External

    proxy_virsh net-list | grep -q Whonix-Internal && \
      virsh net-destroy Whonix-Internal

    proxy_virsh list | grep -q Whonix-Gateway && \
      virsh shutdown Whonix-Gateway

    proxy_virsh list | grep -q Whonix-Gateway && \
      virsh destroy Whonix-Gateway

    return 0
}

## proxy_whonix_host_stop
proxy_whonix_host_stop () {
    local dire=$1

    DBUG $prog proxy_whonix_host_stop $*

    if [ $dire = whonix ] ; then
        proxy_rc_service polipo status >/dev/null && proxy_rc_service polipo stop
        proxy_ping_dnsmasq_status && proxy_ping_dnsmasq_stop
        proxy_whonix_libvirt_stop     || return 3$?
    elif [ $dire = tor ] ; then
        proxy_rc_service tor status >/dev/null && proxy_rc_service tor stop
        proxy_rc_service polipo status >/dev/null && proxy_rc_service polipo stop
    fi


    return 0
}

## proxy_whonix_gateway_start - start whonix on a host
proxy_whonix_gateway_start () {
    local dire
    [ "$#" -gt 0 ] && dire=$1

        # proxy_ping_dnsmasq_status && proxy_ping_dnsmasq_stop
        proxy_whonix_libvirt_start     || return 3$?

	proxy_virsh net-list | grep -q Whonix-External  || \
	    virsh net-start Whonix-External || return 4$?
	ifconfig virbr1 || return 5$?

	proxy_virsh net-list | grep -q Whonix-Internal || \
	    virsh net-start Whonix-Internal|| return 6$?
	ifconfig virbr2 || return 7$?

	DOM=$( proxy_whonix_get_gateway_dom )
	[ -z "$GATEW_DOM" ] && \
	    WARN $prog empty DOM from proxy_whonix_get_gateway_dom && \
	    DOM=Whonix-Gateway
	proxy_virsh list | grep -q $DOM   || \
	    { INFO $prog virsh starting $DOM ; virsh start $DOM ; } || \
	    return 8$?

    return 0
}

## proxy_whonix_host_start - start either whonix or tor on a host
proxy_whonix_host_start () { DBUG $prog proxy_whonix_host_start $* ;
    local dire
    [ "$#" -gt 0 ] && dire=$1

    proxy_whonix_host_config $dire || return 2$?

    proxy_whonix_host_install $dire || return 4$?
    proxy_clobber_resolv_local

    return 0
}

if [ "$#" -eq 0 ] ; then
    echo USAGE: $prog $USAGE

  elif [ "$1" = '-h' -o "$1" = '--help'  -o "$1" = 'host' ] ; then
    echo USAGE: $prog $USAGE or:
    grep '^## ' $0 | sed -e 's/^## //'

  elif [ "$1" = config ] ; then
    [ -z "$MODE" ] && MODE=$( proxy_ping_mode )
    proxy_whonix_host_config $MODE || exit 2$?

  elif [ "$1" = start ] ; then
    [ -z "$MODE" ] && MODE=$( proxy_ping_mode )
    proxy_whonix_host_start $MODE || exit 2$?

  elif [ "$1" = selektor ] ; then
    MODE=$1
    proxy_whonix_host_start $MODE

  elif [ "$1" = to  -o "$1" = 'to_tor' -o "$1" = 'tor' ] ; then
    [ -z "$MODE" ] && MODE=$( proxy_ping_mode )
    proxy_whonix_host_to_tor || exit 3$?

  elif [ "$1" = from -o "$1" = 'from_tor' -o "$1" = 'whonix' ] ; then
    [ -z "$MODE" ] && MODE=$( proxy_ping_mode )
    proxy_whonix_host_from_tor || exit 4$?

  elif [ "$1" = verify -o "$1" = 'install' ] ; then
    [ -z "$MODE" ] && MODE=$( proxy_ping_mode )
    proxy_whonix_host_$1 $MODE || exit 5$?

  elif [ "$1" = 'test' ] ; then
    [ -z "$MODE" ] && MODE=$( proxy_ping_mode )
    proxy_whonix_host_test $MODE || exit 4$?

  elif [ "$1" = update -o "$1" = 'start' -o "$1" = 'status' -o "$1" = 'stop' ] ; then
    [ -z "$MODE" ] && MODE=$( proxy_ping_mode )
    proxy_whonix_host_$1 $MODE || exit 5$?

  elif [ "$1" = hourly -o "$1" = 'refresh' ] ; then
    [ -z "$MODE" ] && MODE=$( proxy_ping_mode )
    proxy_whonix_host_refresh || exit 6$?

  else
    DBUG $base "$@"
    eval "$@"
    exit $?

  fi

exit 0
