#!/bin/bash

### BEGIN INIT INFO
# Provides:          globaleaks
# Required-Start:    $local_fs $remote_fs $network $named $time
# Required-Stop:     $local_fs $remote_fs $network $named $time
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start the GlobaLeaks server.
# Description:       Start The GlobaLeaks server, an opensource, anonymous,
#                    censorship-resistant whistleblowing platform.
### END INIT INFO

# Author: Giovanni Pellerano <giovanni.pellerano@globaleaks.org>

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
NAME=$(basename $(readlink -nf $0))

DAEMON=/usr/bin/globaleaks
SCRIPTNAME=$0
WAITFORDAEMON=60

##################################################################
# GLobaLeaks configuration is read with the following order:
# 1) /usr/share/globaleaks/default
# 2) web configuration
# 3) /etc/default/globaleaks

# The /etc/default/globaleaks is the place where one can force
# settings that could not be overridden from the configuration
# that can be issued from the web interface
if test -e "/usr/share/globaleaks/default" ; then
    . "/usr/share/globaleaks/default"
fi

REACHABLE_VIA_WEB=1
if [[ -f /var/globaleaks/globaleaks.db && "$(gl-admin getvar reachable_via_web 2>1&)" == "False" ]]; then
    REACHABLE_VIA_WEB=0
fi

if test -e "/etc/default/globaleaks" ; then
    . "/etc/default/globaleaks"
fi

##################################################################
. /lib/init/vars.sh

. /lib/lsb/init-functions

test $DEBIAN_SCRIPT_DEBUG && set -v -x

GLPID=/run/globaleaks/globaleaks.pid

wait_for_deaddaemon () {
    pid=$1
    sleep 1
    if test -n "$pid"
    then
        if kill -0 $pid 2>/dev/null
        then
            cnt=0
            while kill -0 $pid 2>/dev/null
            do
                cnt=`expr $cnt + 1`
                if [ $cnt -gt $WAITFORDAEMON ]
                then
                    log_action_end_msg 1 "still running"
                    exit 1
                fi
                sleep 1
                [ "`expr $cnt % 3`" != 2 ] || log_action_cont_msg ""
            done
        fi
    fi
    log_action_end_msg 0
}

network_sandboxing_start()
{
    log_action_begin_msg "Enabling Globaleaks Network Sandboxing"

    if ! command -v iptables >/dev/null 2>&1  || ! command -v ip6tables >/dev/null 2>&1 ; then
        log_failure_msg "GlobaLeaks Network Sandboxing Failure: requires iptables"
        exit 1
    fi

    # remove all rules with the comment: "globaleaks"
    iptables-save | grep -v "globaleaks" | iptables-restore
    ip6tables-save | grep -v "globaleaks" | ip6tables-restore

    iptables -nvL -t nat >/dev/null 2>&1
    if [ "$?" -ne "0" ]; then
        echo "GlobaLeaks Network Sandboxing Failure: missing iptables nat support"
        log_action_end_msg 1
        return
    fi

    iptables -nvL -t filter >/dev/null 2>&1
    if [ "$?" -ne "0" ]; then
        echo "GlobaLeaks Network Sandboxing Failure: missing iptables filter support"
        log_action_end_msg 1
        return
    fi

    if [[ "$REACHABLE_VIA_WEB" -eq "1" ]]; then
        iptables -m comment --comment "globaleaks" -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
        ip6tables -m comment --comment "globaleaks" -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080

        iptables -m comment --comment "globaleaks" -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 8443
        ip6tables -m comment --comment "globaleaks" -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 8443

        iptables -m comment --comment "globaleaks" -t filter -A INPUT -p tcp --dport 8080 -j ACCEPT
        ip6tables -m comment --comment "globaleaks" -t filter -A INPUT -p tcp --dport 8080 -j ACCEPT

        iptables -m comment --comment "globaleaks" -t filter -A INPUT -p tcp --dport 8443 -j ACCEPT
        ip6tables -m comment --comment "globaleaks" -t filter -A INPUT -p tcp --dport 8443 -j ACCEPT
    fi

    log_action_end_msg 0
}

network_sandboxing_stop()
{
    if ! command -v iptables >/dev/null 2>&1  || ! command -v ip6tables >/dev/null 2>&1 ; then
        log_failure_msg "GlobaLeaks Network Sandboxing Failure: requires iptables"
        exit 1
    fi

    log_action_begin_msg "Disabling GlobaLeaks Network Sandboxing"

    # remove all rules with the comment: "globaleaks"
    iptables-save | grep -v "globaleaks" | iptables-restore
    ip6tables-save | grep -v "globaleaks" | ip6tables-restore

    log_action_end_msg 0
}

globaleaks_start()
{
    if [ ! -d "/run/globaleaks" ]; then
        mkdir -m 700 /run/globaleaks && chown $USERNAME:$USERNAME /run/globaleaks
    fi

    if [ ! -d "/dev/shm/globaleaks" ]; then
        mkdir -m 700 /dev/shm/globaleaks && chown $USERNAME:$USERNAME /dev/shm/globaleaks
    fi

    ARGS="--ip=${LISTENING_IP}
          --working-path=${WORKING_DIR}"

    if start-stop-daemon --stop --quiet -u ${USERNAME} -g ${USERNAME} --pidfile $GLPID --name globaleaks; then
        log_action_end_msg 0 "already running"
    else
        if [ "${APPARMOR_SANDBOXING}" -eq "1" ]; then
            if ! command -v aa-status >/dev/null 2>&1  || ! aa-status --enabled ; then
                log_failure_msg "GlobaLeaks Apparmor Sandboxing Failure: requires apparmor"
                exit 1
            fi

            if start-stop-daemon \
                --start \
                --quiet \
		--chuid ${USERNAME} \
                --pidfile $GLPID \
                --startas $(command -v aa-exec) \
                --exec $DAEMON \
                -- --profile=usr.bin.globaleaks $DAEMON $ARGS
            then
                log_action_end_msg 0
            else
                log_action_end_msg 1
                exit 1
            fi
        else
            if start-stop-daemon \
                --start \
                --quiet \
		--chuid ${USERNAME} \
                --pidfile $GLPID \
                --exec $DAEMON \
		-- $ARGS
            then
                log_action_end_msg 0
            else
                log_action_end_msg 1
                exit 1
            fi
        fi
    fi
}

globaleaks_stop()
{
    pid=`cat $GLPID 2>/dev/null` || true

    if test ! -f $GLPID -o -z "$pid"; then
        log_end_msg 0 "not running."
    else
        kill -15 $pid >/dev/null 2<&-
        wait_for_deaddaemon $pid
        log_end_msg 0 "stopped."
    fi
}

#
# Function that queries the status of the daemon/service
#
case "$1" in
  start)
    log_daemon_msg "Starting GlobaLeaks daemon" "globaleaks"

    log_action_begin_msg "Starting $DESC"

    network_sandboxing_start

    globaleaks_start

    ;;
  stop)
    log_action_begin_msg "Stopping $DESC"

    network_sandboxing_stop

    globaleaks_stop
    ;;
  status)
    if test ! -r $(dirname $GLPID); then
        log_failure_msg "cannot read PID file $GLPID"
        exit 4
    fi
    pid=`cat $GLPID 2>/dev/null` || true
    if test ! -f $GLPID -o -z "$pid"; then
        log_failure_msg "$NAME is not running"
        exit 3
    fi
    if ps "$pid" >/dev/null 2>&1; then
        log_success_msg "$NAME is running"
        exit 0
    else
        log_failure_msg "$NAME is not running"
        exit 1
    fi
    ;;
  restart|reload|force-reload)
    $0 stop
    sleep 1
    $0 start
    ;;
  *)
    log_action_msg "Usage: $0 {start|stop|restart|reload|force-reload|status}" >&2
    exit 1
    ;;
esac
