#!/bin/sh
#
#  Copyright (c) 2005 Canonical LTD
#
#  Author: Matt Zimmerman <mdz@canonical.com>
#
#  2006, Oliver Grawert <ogra@canonical.com>
#        Vagrant Cascadian <vagrant@freegeek.org>
#  2007, Scott Balneaves <sbalneav@ltsp.org>
#        Oliver Grawert <ogra@canonical.com>
#  2008, Vagrant Cascadian <vagrant@freegeek.org>
#        Oliver Grawert <ogra@canonical.com>
#        Warren Togami <wtogami@redhat.com>
#        Eric Harrison <eharrison@k12linux.mesd.k12.or.us>
#        Scott Balneaves <sbalneav@ltsp.org>
#  2010, Gideon Romm <gadi@ltsp.org>
#
#  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.
#
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, you can find it on the World Wide
#  Web at http://www.gnu.org/copyleft/gpl.html, or write to the Free
#  Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
#  MA 02110-1301, USA.
#

#
# Handle args
#

unset EXPORTFILE

usage() {
cat <<EOF
$0 [OPTION] [hostname1] [hostname2] [hostname3] ...

  By specifying hostnames of other servers on the command line, an additional 
file will be created in /etc/ltsp/ssh_known_hosts.auto which will append those keys to those of this server on subsequent calls to this script.

  -b, --basedir  Base of ltsp chroot.  Default is /opt/ltsp if unspecified.
  -e, --export   Export ssh key file.  Default is 
                 \${basedir}/etc/ssh/ssk_known_hosts if unspecified.
  -u, --update   When IP addresses of other servers are passed on the 
                 command line, this flag will update the ssh_known_hosts
                 in the chroot in addition to exporting an additional
                 file with the keys to be pulled in later.
  -p, --port     SSH port for remote servers.
  -h, --help     This message.
EOF
}

ARGS=$(getopt -o b:e:hup: --long base:,export:,update,port:,help -n $0 -- "$@")

[ $? != 0 ] && exit 1

eval set -- "${ARGS}"

while true ; do
    case "$1" in
        -b|--base)   BASE=$2 ; shift 2 ;;
        -e|--export) EXPORTFILE=$2 ; shift 2 ;;
        -u|--update) UPDATE=1 ; shift 1 ;;
        -p|--port)   SSH_PORT="-p $2" ; shift 2 ;;
        -h|--help)   usage ; exit 0 ;; 
        --) shift ; break ;;
        *) echo "Internal error!" ; exit 1 ;;
    esac
done

# Set up variables
BASE=${BASE:-"/opt/ltsp"}
if [ -z "${CHROOTS}" ]; then
    CHROOTS=$(find ${BASE}/ -mindepth 1 -maxdepth 1 -type d 2>/dev/null | \
              grep -v images)
fi
ENC="dsa rsa ecdsa"
OUTPUT=$(mktemp)

if [ -z "$*" ]; then
    HOSTNAME=$(hostname)
    IPS=$(/sbin/ip -o -f inet addr show | sed -e 's,.* \(.*\)/.*,\1,' | grep -v '^127')
    NAMES="${HOSTNAME} ${IPS}"
    THIS_SERVER=1
else
    # We were passed hostnames and ips
    NAMES=$*
    EXPORTFILE=${EXPORTFILE:-"/etc/ltsp/ssh_known_hosts.auto"}
    unset THIS_SERVER
fi

# Check for LOGFILE location
unset LOGFILE
[ -e /var/log/syslog ]   && LOGFILE="/var/log/syslog"
[ -e /var/log/messages ] && LOGFILE="/var/log/messages"
if [ -z "$LOGFILE" ]; then
    echo "ERROR: Neither /var/log/messages nor /var/log/syslog exists.  Unable to log."
    exit 0
fi

# Any chroots found, and not exporting?
# fixes bug #207485 per Andy Rabagliati
if [ -z "${CHROOTS}" ] && [ -z "${EXPORTFILE}" ]; then
	logger -f $LOGFILE -t ltsp \
        "No client chroots found, please run ltsp-build-client"
	exit 0
fi

# Make a "server" hostname entry
for ENCRYPTION in ${ENC}; do
    pubkey=/etc/ssh/ssh_host_${ENCRYPTION}_key.pub
    if [ -n "$THIS_SERVER" ] && [ -f "$pubkey" ] ; then
        echo $(echo server $(cat "$pubkey" | \
            awk '{split ($0, a, " "); print a[1]" "a[2]" "}')) >> $OUTPUT
    fi
done

# Get encryption keys
for NAME in ${NAMES}; do
    for ENCRYPTION in ${ENC}; do
        if [ -n "$THIS_SERVER" ]; then
            pubkey=/etc/ssh/ssh_host_${ENCRYPTION}_key.pub
            if [ -f "$pubkey" ]; then
                # Make a "server" hostname entry
                echo $(echo $NAME $(cat "$pubkey" | \
                    awk '{split ($0, a, " "); print a[1]" "a[2]" "}')) >> $OUTPUT
                logger -f $LOGFILE -t ltsp "# Creating ${ENCRYPTION}-hostkey for ${NAME}"
            else
                # missing ecdsa is valid
                if [ "$ENCRYPTION" != "ecdsa" ]; then
                    logger -f $LOGFILE -t ltsp "No ${ENCRYPTION} key found for ${NAME}, please configure your ssh server correctly"
                fi
            fi
        else
            NAMED_SERVER=${NAME%:*}
            NAMED_PORT=${NAME#*:}
            [ "${NAMED_PORT}" != "${NAMED_SERVER}" ] && SSH_PORT="-p ${NAMED_PORT}"
            ssh-keyscan -t ${ENCRYPTION} ${SSH_PORT} ${NAME%:*} >> ${OUTPUT} 2>/dev/null
        fi
    done
done

#
# export file
# We need this for multiple host support.  This way, we can do an
# ltsp-update-sshkeys --export ssh_known_hosts.myname
# and install this file in the /etc/ltsp dir, where it will be picked up
# by the above.
# Note that ltsp-update-sshkeys --export - cats to stdout
# If no export specified, then update local chroots.
#

if [ -n "${EXPORTFILE}" ]; then
    if [ "${EXPORTFILE}" = "-" ]; then
        cat ${OUTPUT}
    else
        install -m 644 ${OUTPUT} ${EXPORTFILE}
        # Now that we have our new file, use it
        [ -n "$UPDATE" ] && $0
    fi
else
    # Add any additional hosts
    for SSHHOST in $(ls /etc/ltsp/ssh_known_hosts.* 2> /dev/null); do
        cat ${SSHHOST} >> $OUTPUT
        echo >> $OUTPUT
    done
    for CHROOT in ${CHROOTS}; do
        if [ -d ${CHROOT}/etc/ssh ]; then
            install -m 644 $OUTPUT ${CHROOT}/etc/ssh/ssh_known_hosts
        fi
    done
fi

rm -f ${OUTPUT}

exit 0
