#!/bin/bash -e
#
# Copyright (c) 2015 Alon Swartz <alon@turnkeylinux.org>
# 
# This file is part of InitHooks.
# 
# InitHooks is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 3 of the License, or (at your
# option) any later version.
# 
fatal() { echo "FATAL [$(basename $0)]: $@" 1>&2; exit 1; }
warn() { echo "WARN [$(basename $0)]: $@"; }
info() { echo "INFO [$(basename $0)]: $@"; }

usage() {
cat<<EOF
Syntax: $(basename $0) on|off [--disable-setpass]
Configure system to use admin user with sudo, or root

On:
    - installs sudo package
    - creates admin user and sets random password
    - configures passwordless sudo for admin user
    - configures inithooks and init-fence for admin user
    - updates confconsole services for admin user
    - merges root .ssh/authorized_keys with admin
    - locks the root user
    - disables root ssh access
    - sets root ssh login banner
    - restarts ssh daemon, if it is running
    - sets admin password interactively (unless --disable-setpass)

Off:
    - configures inithooks and init-fence for root
    - updates confconsole services for root
    - merges admin .ssh/authorized_keys with root
    - enables root ssh access
    - locks admin user
    - unsets root ssh login banner
    - restarts ssh daemon, if it is running
    - sets root password interactively (unless --disable-setpass)

EOF
exit 1
}

install_sudo() {
    info $FUNCNAME $@
    which sudo >/dev/null && return
    apt-get update
    DEBIAN_FRONTEND=noninteractive apt-get -y install sudo
}

create_user() {
    info $FUNCNAME $@
    username=$1
    grep -q ^${username}: /etc/passwd && return
    useradd --create-home --shell /bin/bash ${username}
    echo ${username}:$(mcookie) | chpasswd
}

passwordless_sudo() {
    info $FUNCNAME $@
    username=$1
    cfg="/etc/sudoers.d/99_${username}"
    str="${username} ALL=(ALL) NOPASSWD:ALL"
    touch $cfg
    grep -q "^${str}$" $cfg && return
    echo "$str" >> $cfg
    chmod 0440 $cfg
}

inithooks_sudoadmin() {
    info $FUNCNAME $@
    val=$1
    key="SUDOADMIN"
    cfg="/etc/default/inithooks"
    [ -e $cfg ] || return 0
    grep -q ^${key}= $cfg || (echo "$key=$val" >> $cfg; return)
    sed -i "s/^${key}=.*/$key=$val/" $cfg
}

setup_initfence() {
    info $FUNCNAME $@
    username=$1
    root_profiled=/root/.profile.d/turnkey-init-fence
    user_profiled=/home/${username}/.profile.d/turnkey-init-fence
    if [ -e $root_profiled ]; then
        if [ $username != "root" ]; then
            mkdir -p $(dirname $user_profiled)
            cp $root_profiled $user_profiled
            sed -i "s|^|sudo |" $user_profiled
            sed -i "s|/root|/home\/${username}|g" $user_profiled
            chown -R $username:$username $(dirname $user_profiled)
        fi
    fi
    return 0
}

update_confconsole_services() {
    info $FUNCNAME $@
    username=$1
    cfg="/etc/confconsole/services.txt"
    [ -e $cfg ] || return 0
    sed -i "s|\S*@|${username}@|g" $cfg
}

ssh_authorizedkeys_inithook() {
    info $FUNCNAME $@
    username=$1
    sshkeys_inithook=/usr/lib/inithooks/firstboot.d/40ec2-sshkeys
    [ -e $sshkeys_inithook ] || return 0
    sed -i "s|^USERNAME.*|USERNAME = \'${username}\'|" $sshkeys_inithook
}

ssh_authorizedkeys_merge() {
    info $FUNCNAME $@
    user1=$1
    user2=$2

    grep -q ^${user1}: /etc/passwd || return 0
    grep -q ^${user2}: /etc/passwd || return 0

    auth1="$(eval printf ~$user1)/.ssh/authorized_keys"
    mkdir -p $(dirname $auth1)
    chmod 0700 $(dirname $auth1)
    touch $auth1

    auth2="$(eval printf ~$user2)/.ssh/authorized_keys"
    mkdir -p $(dirname $auth2)
    chmod 0700 $(dirname $auth2)
    touch $auth2

    cat $auth1 $auth2 | sort | uniq > $auth1.new
    echo $auth1 $auth2 | xargs -n 1 cp $auth1.new
    rm $auth1.new

    chown -R $user1:$user1 $(dirname $auth1)
    chown -R $user2:$user2 $(dirname $auth2)
}

permitrootlogin_ssh() {
    info $FUNCNAME $@
    val=$1
    key="PermitRootLogin"
    cfg="/etc/ssh/sshd_config"
    grep -q ^${key} $cfg || (echo "$key $val" >> $cfg; return)
    sed -i "s/^${key} .*/$key $val/" $cfg
}

set_sshrootbanner() {
    info $FUNCNAME $@
    content=$1
    banner_path="/root/.ssh/banner"
    mkdir -p $(dirname $banner_path)
    echo $content > $banner_path
}

user_state() {
    info $FUNCNAME $@
    username=$1
    action=$2
    grep -q ^${username}: /etc/passwd || return 0
    passwd --${action} $username
    if [ $username != "root" ]; then
        [ $action == "lock" ] && usermod --expiredate "1" $username
        [ $action == "unlock" ] && usermod --expiredate "" $username
    fi
    return 0
}

restart_sshd() {
    info $FUNCNAME $@
    if [ -e /var/run/sshd.pid ]; then
        /etc/init.d/ssh restart
    fi
}

setpass() {
    info $FUNCNAME $@
    username=$1
    script=/usr/lib/inithooks/bin/setpass.py
    if [ -x $script ]; then
        $script $username
    else
        echo "Set password for $username"
        passwd $username
    fi
}

case $1 in
    on)
        [ "$(id -u)" != "0" ] && fatal "must be run with root permissions"
        install_sudo;
        create_user "admin";
        passwordless_sudo "admin";
        inithooks_sudoadmin "true";
        setup_initfence "admin";
        update_confconsole_services "admin";
        ssh_authorizedkeys_inithook "admin";
        ssh_authorizedkeys_merge "admin" "root";
        user_state "admin" "unlock";
        user_state "root" "lock";
        permitrootlogin_ssh "no";
        set_sshrootbanner 'Please login as user "admin" rather than user "root".';
        restart_sshd;
        [ "$2" == "--disable-setpass" ] || setpass "admin";
        ;;

    off)
        [ "$(id -u)" != "0" ] && fatal "must be run with root permissions"
        inithooks_sudoadmin "false";
        setup_initfence "root";
        update_confconsole_services "root";
        ssh_authorizedkeys_inithook "root";
        ssh_authorizedkeys_merge "root" "admin";
        permitrootlogin_ssh "yes";
        user_state "root" "unlock";
        user_state "admin" "lock";
        set_sshrootbanner "";
        restart_sshd;
        [ "$2" == "--disable-setpass" ] || setpass "root";
        ;;
    *)  
        usage;;
esac

