#!/usr/local/bin/bash
################################################################################
# Don't edit this file
#
# Environment variables can be passed to change how this script runs.
#
# Set `COWRIE_VIRTUAL_ENV=my-env` to use a particular virtual environment.
# By default Cowrie will look for `cowrie-env` in the current or parent
# directory.
#
# Set `COWRIE_STDOUT=yes` to run in foreground mode and send logs to stdout
#
# Pass any other config variable as well, to further setup your environment!
# For example: `COWRIE_TELNET_ENABLED=yes`
################################################################################

DEFAULT_VIRTUAL_ENV=cowrie-env

first_time_use() {
    echo
    echo "Join the Cowrie community at: https://www.cowrie.org/slack/"
    echo
}

python_version_warning() {
    if python -V 2>&1 | grep -q  '^Python 2.'; then
        echo
        echo "DEPRECATION: Python 2.7 reached the end of its life on January 1st, 2020."
        echo "Cowrie has dropped support for Python 2.7."
        echo
    fi
    if python -V 2>&1 | grep -q  '^Python 3.5'; then
        echo
        echo "DEPRECATION: Python 3.5 is no longer supported by Cowrie."
        echo
    fi
}

find_cowrie_directory() {
    # Determine Cowrie directory
    if [[ "$0" = /* ]]
    then
        COWRIEDIR=$(dirname $0)/..
    else
        COWRIEDIR=$(dirname $PWD/$0)/..
    fi
    COWRIEDIR=$(cd ${COWRIEDIR} && pwd -P 2>/dev/null || pwd)
}

activate_venv() {
    # Activate Python virtual environment
    VENV="$1"
    if [ ! -f "$VENV/bin/activate" ]
    then
        return 1
    fi
    . $VENV/bin/activate
    return 0
}

cowrie_status() {
    # Print status
    PID=$(cat ${PIDFILE} 2>/dev/null || echo "")
    if [ -n "$PID" ]; then
        if ps -p "$PID" 2>&1 >/dev/null; then
            echo "cowrie is running (PID: ${PID})."
        else
            echo "cowrie is not running (PID: ${PID})."
            echo "Removing stale PID file ${PIDFILE}"
            rm -f ${PIDFILE}
        fi
    else
        echo "cowrie is not running."
    fi
}

cowrie_start() {
    # Start Cowrie
    COWRIEARGS="$*"
    TWISTEDARGS="${XARGS} --umask=0022 --pidfile=${PIDFILE}"

    # Run foreground or background. Foreground has no file log.
    if [ "$COWRIE_STDOUT" = "yes" ]; then
        TWISTEDARGS="${TWISTEDARGS} -n -l -"
    else
        TWISTEDARGS="${TWISTEDARGS} --logger cowrie.python.logfile.logger"
    fi

    # 1. Check if any virtual environment is active
    # 2. Try COWRIE_VIRTUAL_ENV if defined
    # 3. Try DEFAULT_VIRTUAL_ENV
    # 4. Try ../DEFAULT_VIRTUAL_ENV
    # 5. Try without virtual environment

    if [ ! -z "$VIRTUAL_ENV" ]; then
        echo 2>&1 "Using activated Python virtual environment \"$VIRTUAL_ENV\""
    elif activate_venv "$COWRIE_VIRTUAL_ENV"; then
        echo 2>&1 "Using custom Python virtual environment \"$VIRTUAL_ENV\""
    elif activate_venv "$DEFAULT_VIRTUAL_ENV"; then
        echo 2>&1 "Using default Python virtual environment \"$VIRTUAL_ENV\""
    # Look one directory higher for the virtual env to not pollute the Cowrie dir
    elif activate_venv "../$DEFAULT_VIRTUAL_ENV"; then
        echo 2>&1 "Using default Python virtual environment \"../$VIRTUAL_ENV\""
    else
        echo 2>&1 "Not using Python virtual environment"
    fi

    python_version_warning

    # Automatically check if the authbind is enabled or not
    authfile="/etc/authbind/byport/22"
    if [ -z ${AUTHBIND_ENABLED} ] && [ -x "$authfile" ] && command -v authbind >/dev/null; then
        AUTHBIND_ENABLED=yes
    else
        AUTHBIND_ENABLED=no
    fi

    echo "Starting cowrie: [twistd ${TWISTEDARGS} cowrie ${COWRIEARGS}]..."
    if [ "$AUTHBIND_ENABLED" = "no" ]
    then
        exec twistd ${TWISTEDARGS} ${COWRIEARGS} cowrie
    else
        exec authbind --deep twistd ${TWISTEDARGS} ${COWRIEARGS} cowrie
    fi
}

cowrie_stop () {
    # Stop Cowrie
    PID=$(cat ${PIDFILE} 2>/dev/null || echo "")
    if [ -n "$PID" ]; then
      echo "Stopping cowrie..."
      if kill -TERM $PID; then
          echo -n
      else
          echo "Removing stale PID file ${PIDFILE}"
          rm -f ${PIDFILE}
      fi
    else
        echo "cowrie is not running."
    fi
}

cowrie_force_stop () {
    # Force Stop Cowrie
    PID=$(cat ${PIDFILE} 2>/dev/null || echo -n "")
    if [ -n "$PID" ]; then
        echo -n "Stopping cowrie..."
        if kill -TERM $PID; then
            ((t = 60))
            while ((t > 1)); do
                sleep 1
                echo -n .
                if kill -0 $PID 2>/dev/null; then
                    ((t -= 1))
                else
                    echo "terminated."
                    return
                fi
            done
            kill -KILL $PID
            echo "killed."
        else
            echo "Removing stale PID file ${PIDFILE}"
            rm -f ${PIDFILE}
        fi
    else
        echo "cowrie is not running."
    fi
}

cowrie_usage() {
    echo "usage: $0 <start|stop|force-stop|restart|status|shell>"
}

# Mostly for Docker use, to quickly get a shell in the container
cowrie_shell() {
    $SHELL
}

################################################################################
## Main script
################################################################################

if [ "$#" = 0 ]
then
    cowrie_usage
    exit 1
fi

find_cowrie_directory $0
cd ${COWRIEDIR}
export PYTHONPATH=${PYTHONPATH}:${COWRIEDIR}/src

set -e

# Don't store pidfile on Docker persistent volume
if [ "${COWRIE_STDOUT}" = "yes" ]; then
        PIDFILE=""
else
        PIDFILE=var/run/cowrie.pid
fi

if [ ! -f ${COWRIEDIR}/var/log/cowrie/cowrie.log ]
then
    first_time_use
fi

key=$1
shift 1
case $key in
    stop)
        cowrie_stop $*
        ;;
    force-stop)
        cowrie_force_stop $*
        ;;
    start)
        cowrie_start $*
        ;;
    restart)
        cowrie_stop $*
        cowrie_start $*
        ;;
    status)
        cowrie_status $*
        ;;
    bash)
        cowrie_shell $*
        ;;
    sh)
        cowrie_shell $*
        ;;
    shell)
        cowrie_shell $*
        ;;
    *)
        cowrie_usage
        exit 1
        ;;
esac
