#! /bin/bash

#*********************************************************************
#
# fai-setup -- set up FAI
#
# This script is part of FAI (Fully Automatic Installation)
# (c) 2000-2021 by Thomas Lange, lange@cs.uni-koeln.de
# Universitaet zu Koeln
#
#*********************************************************************
# This program 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 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# A copy of the GNU General Public License is available as
# `/usr/share/common-licences/GPL' in the Debian GNU/Linux distribution
# or on the World Wide Web at http://www.gnu.org/copyleft/gpl.html.  You
# can also obtain it by writing to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#*********************************************************************

PATH=/usr/local/bin:/usr/local/sbin:/bin:/sbin:/usr/bin:/usr/sbin

set -e

cfdir=/etc/fai

options=$@ # all options are also passed to fai-make-nfsroot

while getopts pPvC:efgkKV:B: opt ; do
    case "$opt" in
        C) cfdir=$OPTARG ;;
        v) verbose=1 ; v=-v ;;
        e) expert=1 ;;
    esac
done


. $cfdir/fai.conf
. $cfdir/nfsroot.conf

: ${FAI_LOGPROTO:=ssh}

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
add_export_line() {

    # add a line to /etc/exports

    pattern=$1
    shift
    options="$@"

    [ -f /etc/exports ] && grep -q "^$pattern[[:space:]]" /etc/exports && return
    echo "Adding line to /etc/exports: $pattern $options"
    echo "$pattern $options" >> /etc/exports
}
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
add_fai_account() {

    if id $LOGUSER 2>/dev/null 1>&2 ; then
        echo Account \$LOGUSER=$LOGUSER  already exists.
        echo Make sure that all install clients can
        echo log into this account without a password.
        return
    fi

    adduser --system --disabled-password --home /var/log/fai/remote-logs --gecos "FAI account for remote log files" --shell /bin/sh  $LOGUSER
    # get the home dir of a user in a variable; do not exit when set -e is used
    # loguserhome is unset if $LOGUSER does not exists
    # this is not a evil hack, it's a very clever piece of code
    loguserhome=$(eval "cd ~$LOGUSER 2>/dev/null && pwd;true")
    touch $loguserhome/.account_created_by_fai_package
}
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
setup_fai_account() {

    # most things should be executed as user $LOGUSER, since root may not have write
    # permissions to $loguserhome (e.g if mount via NFS without no_root_squash)

    set +e
    loguserhome=$(eval "cd ~$LOGUSER 2>/dev/null && pwd;true")
    sshdir=$loguserhome/.ssh
    if [ -z "$loguserhome" ]; then
        echo "Can't determine home directory for user $LOGUSER."
        echo "LOGUSER= $LOGUSER    loguserhome= $loguserhome"
        exit 8
    fi

    if [ "$FAI_LOGPROTO" = "ssh" ]; then
        # set up ssh on the server
        mkdir -p -m 700 $loguserhome/.ssh

        #Generating keys for LOGUSER
        [ -f $sshdir/id_rsa ] || {
            ssh-keygen -t rsa -N '' -f $sshdir/id_rsa -C "$LOGUSER@$HOSTNAME"
            cat $sshdir/id_rsa.pub >> $sshdir/authorized_keys
        }

        [ -f $sshdir/id_ed25519 ] || {
            ssh-keygen -t ed25519 -N '' -f $sshdir/id_ed25519 -C "$LOGUSER@$HOSTNAME"
            cat $sshdir/id_ed25519.pub >> $sshdir/authorized_keys
        }

        [ -f $sshdir/id_ecdsa ] || {
            ssh-keygen -t ecdsa -N '' -f $sshdir/id_ecdsa -C "$LOGUSER@$HOSTNAME"
            cat $sshdir/id_ecdsa.pub >> $sshdir/authorized_keys
        }

        #Adding servers keys to known_hosts list of LOGUSER.
        #So that installed clients can ssh $LOGUSER@$HOSTNAME without password
        if [ ! -f $sshdir/known_hosts ]; then
            [ -f /etc/ssh/ssh_host_ed25519_key.pub ] && ED25519SERVER=$(sed -e "s/= .*$/=/" /etc/ssh/ssh_host_ed25519_key.pub)
            [ -f /etc/ssh/ssh_host_rsa_key.pub ] && RSASERVER=$(sed -e "s/= .*$/=/" /etc/ssh/ssh_host_rsa_key.pub )
            [ -f /etc/ssh/ssh_host_ecdsa_key.pub ] && ECDSASERVER=$(sed -e "s/= .*$/=/" /etc/ssh/ssh_host_ecdsa_key.pub )
            # determine all IP addresses, and their host names
            ips=$(ip addr show up| grep -P -o '(?<=inet )[^/]+' | grep -v 127.0.0.1)
            for ip in $ips; do
                hname=$(getent hosts $ip| tr -s ' ' ',')
                : ${hname:=$ip}
                echo "Adding $hname to known_hosts."
                [ -z "$ED25519SERVER" ] || echo "$hname $ED25519SERVER" >> $sshdir/known_hosts
                [ -z "$RSASERVER" ] || echo "$hname $RSASERVER" >> $sshdir/known_hosts
                [ -z "$ECDSASERVER" ] || echo "$hname $ECDSASERVER" >> $sshdir/known_hosts
            done
            echo "$sshdir/known_hosts created."
        else
            echo "$sshdir/known_hosts remained unchanged."
        fi

        chmod 0600 $sshdir/authorized_keys
        echo "$sshdir/authorized_keys created."
    fi
    if [ "$FAI_LOGPROTO" = "rsh" -a ! -f $loguserhome/.rhosts ]; then
        # use .rhosts authentication
        echo "+@faiclients root" > $loguserhome/.rhosts
        chmod go-rwx $loguserhome/.rhosts
        echo "$loguserhome/.rhosts created."
    fi

    logusergid=$(id -ng $LOGUSER)
    echo "User account $LOGUSER set up."
    set -e
}
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

{ # start huge block for capturing output

if [ -n "$LOGUSER" ]; then
    add_fai_account
    setup_fai_account
fi

cp /dev/null /var/log/fai/variables
set +e
fai-make-nfsroot $options
err=$?
if [ $err -ne 0 ]; then
    echo "ERROR when calling fai-make-nfsroot."
    exit 9
fi
set -e

if [ -n "$LOGUSER" ]; then
    # chown only if cd was successful
    cd $loguserhome
    if [ $? -eq 0 ]; then
        [ -e .rhosts ] && chown $LOGUSER:$logusergid . .rhosts || true
        [ -d .ssh ] && chown -R $LOGUSER:$logusergid .ssh || true
    fi
    mkdir -p $TFTPROOT
    chown -R $LOGUSER:$logusergid $TFTPROOT || true
    fai-chboot -o default
fi

if [ -z "$FAI_CONFIGDIR" ]; then
    echo "FAI_CONFIGDIR not set in /etc/fai/nfsroot.conf."
    exit 7
fi
mkdir -p $FAI_CONFIGDIR

# in expert mode, do not export nfs directories
if [ -z "$expert" ]; then
    # by default use the first interface which is up
    if [ -z "$SERVERINTERFACE" ]; then
	opt="up"
    else
	opt="dev $SERVERINTERFACE"
    fi
    nip=$(ip -br ad show $opt | awk '/UP / {if ($3) print $3}' | wc -l)
    iprange=$(ip -br ad show $opt | awk '/UP / {if ($3) print $3}' | head -1)
    myip=${iprange%/*}
    if [ $nip -gt 1 ]; then
	echo "Warning. More than one network interface found for FAI server."
	echo "Using IP address $myip. Please set \$SERVERINTERFACE in"
	echo "nfsroot.conf if you want to use another interface."
    fi
    echo "FAI_CONFIGDIR=$FAI_CONFIGDIR" >> /var/log/fai/variables
    echo "FAI_CONFIG_SRC=nfs://${myip}$FAI_CONFIGDIR" >> /var/log/fai/variables

    add_export_line $FAI_CONFIGDIR  "$iprange(async,ro,no_subtree_check)"
    add_export_line $NFSROOT  "$iprange(async,ro,no_subtree_check,no_root_squash)"
    if pidof nfsd >/dev/null
    then
	invoke-rc.d nfs-kernel-server reload
    else
	invoke-rc.d nfs-kernel-server restart
    fi
fi

if [ ! -d $FAI_CONFIGDIR/class ]; then
    fai-mk-configspace
    echo "Please don't forget to fill out the FAI questionnaire after you've finished your project with FAI."
    echo ""
fi
echo "FAI setup finished."
} |& tee /var/log/fai/fai-setup.log
RC=${PIPESTATUS[0]}
echo "Log file written to /var/log/fai/fai-setup.log"
exit ${RC}
