#!/bin/sh
#
# nessus-adduser
#
# Written by Renaud Deraison <deraison@cvs.nessus.org>
#
# This script is distributed under the Gnu General Public License (GPL)
#

# check whether we have echo -n, depending
# on the current shell, used
case `echo -n` in
\-n)	Xn=   ; Xc='\c' ;;
*)	Xn=-n ; Xc=
esac

prefix=/usr/local
exec_prefix=${prefix}

# add the nessus installation path
PATH=${exec_prefix}/sbin:${exec_prefix}/bin:$PATH ; export PATH

# make sure that we are root, if there is no id command,
# you loose, anyway
case `id 2>/dev/null` in 
uid=0*) 
    # check the implementation
    nessusd --gen-config
    ;; 
*)
    echo "only root should use nessus-adduser"
    exit 1
esac

prefix=/usr/local
exec_prefix=${prefix}
bindir=${exec_prefix}/bin
sbindir=${exec_prefix}/sbin
libexecdir=${exec_prefix}/libexec
datadir=${prefix}/share
sysconfdir=/etc
sharedstatedir=${prefix}/com
localstatedir=/var
libdir=${exec_prefix}/lib
includedir=${prefix}/include
oldincludedir=/usr/include
infodir=${prefix}/info
mandir=${prefix}/man

# find nessusd by the first path segment, ask for settings
nessusd_conf=` nessusd -s | sed '/^config_file  *= /!d; s/^[^=]*= *//;'`
nessusd_users=`nessusd -s | sed       '/^users  *= /!d; s/^[^=]*= *//;'`

# some checks
[ -s "$nessusd_conf" ] || {
	echo "Missing or empty configuration file \"$nessusd_conf\"!"
	exit 2
}
[ -n "$nessusd_users" ] || {
	echo "You must define the user data base entry \"nessusd_users = ...\" in the"
	echo "configuration file \"$nessusd_conf\"!"
	exit 2
}

# path to a temporary directory
test -z "$TMPDIR" && {
  	if [ -d /var/tmp ];
	then
	  echo "Using /var/tmp as a temporary file holder"
	  TMPDIR=/var/tmp
	else
	  echo "Your \$TMPDIR variable is not set ! "
	  echo $Xn "Enter the location to a place where I could place temporary files : [$HOME] $Xc"
	  read TMPDIR
	  test -z "$TMPDIR"  && TMPDIR=$HOME
	fi  
}

# function: install on local user
kfile=.nessus.keys
xfile=.nessusrc
add_local_user () {
    ulogin=$1

    # get/check the user home directory
    uhome=`awk -F: '$1 == "'"$ulogin"'" {print $6}' /etc/passwd`
    ugrp=` awk -F: '$1 == "'"$ulogin"'" {print $4}' /etc/passwd`
    [ -n "$uhome" ] || {
	echo "No Home directory for user $ulogin" >&2
	exit 2
    } 
    [ -d "$uhome" ] || (
	umask 044
	mkdir -p      $uhome
	chown $ulogin $uhome
    )
    # install the nessusd host key on the local user
    test -s $uhome/$kfile ; create_kfile=$?
    nessusd -S -X $uhome/$kfile
    chown $ulogin $uhome/$kfile

    # just in case ...
    test -f       $uhome/$xfile &&
    chown $ulogin $uhome/$xfile

    # make sure the user has a personal key
    [ 0 -lt $create_kfile ] &&
	echo "Generating the user key for \"$ulogin\" (please be patient)"
    # do not leave files inaccessible
    trap "chown $ulogin $uhome/$kfile $uhome/$xfile;
          chgrp   $ugrp $uhome/$kfile $uhome/$xfile;" 1 2 3 15
    NESSUSHOME=$uhome NESSUSUSER=$ulogin nessus -GqS
    chown $ulogin $uhome/$kfile $uhome/$xfile
    chgrp   $ugrp $uhome/$kfile $uhome/$xfile
    trap 1 2 3 15

    # save/replace the user key in the server data base
    ukeys=`nessusd -s | sed '/^peks_usrkeys  *= /!d; s/^[^=]*= *//;'`
    nessusd -K $ulogin@127.0.0.1 >/dev/null
    NESSUSHOME=$uhome NESSUSUSER=$ulogin nessus -S -X $ukeys
}

# Here we go
echo
echo "Add a new nessusd user"
echo "----------------------"
echo
echo
echo $Xn "Login : $Xc"
read login

echo $Xn "Authentication method (cipher/plaintext) [cipher] : $Xc"
read auth

case $auth in
''|c*) 
    auth="cipher"

    # ask for local treatment if that user exists
    awk -F: '$1=="'"$login"'"{N=-1}END{exit N+1}' /etc/passwd && {
      echo $Xn "Is \"$login\" a local user on this machine [ |n]? $Xc"
      read x ; case $x in [nN]*) ;; *) add_locally=yes ; esac
      echo
    }

    if [ x$add_locally = xyes ]
    then
      echo "Ok, treating user \"$login\" as a local user."
    else

    askPasswd="One time password :"
    sayPasswd="One time password :"
    echo  
    echo "Source restriction"
    echo "------------------"

    echo

    echo "You can, if you will, configure this account so that it can only"
    echo "be used from a given host or subnet. For instance, you may want"
    echo "$login to be able to connect to this nessusd server only from"
    echo "his work machine".

    echo 


    echo "Please enter the host (or subnet) $login is allowed to connect from. "
    echo "A blank entry will allow him to connect from anywhere"

    echo
    echo "The entry format must be an IP address followed by an optional netmask."
    echo "Hostnames are *not* accepted"
    echo
    echo "Examples of valid entries :"
    echo "   192.168.1.5"
    echo "   192.168.1.0/24"
    echo "   192.168.1.0/255.255.255.0"
    echo
    echo "Invalid entry :"
    echo "   prof.fr.nessus.org"
    echo
    echo $Xn "Source host or network [anywhere] : $Xc"
    read src

    test "$src" = "anywhere" && src=""
    echo
    fi # not treated locally
    ;;
*)  auth=plaintext
    askPasswd="Login password :"
    sayPasswd="Password          :"
esac

[ x$add_locally = xyes ] ||
ok="n"
while test "$ok" = "n";
do
 echo $Xn "$askPasswd $Xc"
 read password
 if test -z "$password"; then
   echo "Your password can not be empty."
 else
   ok="y"
fi
done

echo 
echo "User rules"
echo "----------"

echo "nessusd has a rules system which allows you to restrict the hosts"
echo "that $login has the right to test. For instance, you may want"
echo "him to be able to scan his own host only."
echo
echo "Please see the nessus-adduser(8) man page for the rules syntax"

echo
echo "Enter the rules for this user, and hit ctrl-D once you are done : "

# we do not leave any temporary files, hanging around
# so we trap the exit
trap "rm -f $TMPDIR/adduser.$$ $TMPDIR/rules.$$;
      echo; echo INTERRUPT; echo;
      trap 0;
      exit 0" 0

echo "(the user can have an empty rules set)"
cat > $TMPDIR/rules.$$ || {
  	echo "Error - could not write $TMPDIR/rules.$$"
	exit 1
}

echo 
echo
echo "Login             : $login"
case $auth in
cipher)
    echo $Xn "Auth. method      : $auth$Xc"
    if [ x$add_locally = xyes ]
    then
        echo ", local user connecting from 127.0.0.1"
	src="127.0.0.1"
    else
      echo $Xn ", can connect from $Xc"
      if [ -z "$src" ];
      then
	echo "anywhere"
	src="0/0"
      else
	echo "$src"
      fi
    fi
    ;;
*)  
    echo "Auth. method      : $auth"
esac
echo "$sayPasswd"         $password
echo "Rules             : "

cat $TMPDIR/rules.$$

echo
echo
echo $Xn "Is that ok ? (y/n) [y] $Xc"
read ok

# check for answer, default is Yes, abort on other reply
case $ok in ''|[Yy]*);; *) 
    rm -f $TMPDIR/rules.$$
    trap 0
    echo Aborted
    exit 0
esac

# add the user rules in our rules files. 
#
# The users file must end with the default user '*', so we add
# our data at the TOP of the file

if [ "$auth" = "cipher" ];
then
	if [ x$add_locally = xyes ]
	then
	  echo "$login@127.0.0.1:"
	else
	  echo "$login:"
	fi > $TMPDIR/adduser.$$
else 
	echo "$login:$password" > $TMPDIR/adduser.$$
	askyes=`nessusd -s | sed '/^force_pubkey_auth  *= /!d; s/^[^=]*= *//;'`
	case $askyes in yes)
	  echo "Set force_pubkey_auth to 'no' in $nessusd_conf to allow unciphered logins"
	esac
fi

cat $TMPDIR/rules.$$ >> $TMPDIR/adduser.$$
if [ -f $nessusd_users ];
then
 cat $nessusd_users >> $TMPDIR/adduser.$$
else
 #
 # Default user
 #
 echo "*:" >> $TMPDIR/adduser.$$
 echo "default reject" >> $TMPDIR/adduser.$$
fi

cat $TMPDIR/adduser.$$ > $nessusd_users
chmod 0600 $nessusd_users


# reset trap, clean up
trap 0
rm $TMPDIR/rules.$$
rm $TMPDIR/adduser.$$


if [ x$add_locally = xyes ]
then
 add_local_user $login 
elif [ "$auth" = "cipher" ];
then
 nessusd -P "$login@$src","$password"
fi

# HUP nessusd
test -f /var/nessus/nessusd.pid && (
    pid=`cat /var/nessus/nessusd.pid`
    set -x
    kill -1 $pid 2>/dev/null
)
 
echo "user added."
