#!/bin/bash

###############################################################################
# GVM
# $Id$
#
# Script for checking completeness and readiness of GVM
#
# Authors:
# Jan-Oliver Wagner <jan-oliver.wagner@greenbone.net>
# Michael Wiegand <michael.wiegand@greenbone.net>
#
# Copyright:
# Copyright (C) 2011-2016 Greenbone Networks GmbH
# Copyright (C) 2020 Offensive Security
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2,
# or at your option any later version, as published by the
# Free Software Foundation
#
# 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, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
###############################################################################

LOG=/tmp/gvm-check-setup.log
# Current default version:
CHECKVERSION=21.4.3

SCANNER_MAJOR="21.4"
MANAGER_MAJOR="21.4"
GSA_MAJOR="21.4"

echo "gvm-check-setup $CHECKVERSION"
echo "  Test completeness and readiness of GVM-$CHECKVERSION"


log_and_print ()
{
  echo "       " $1
  echo "       " $1 >> $LOG
}

check_failed ()
{
  echo ""
  echo " ERROR: Your GVM-$CHECKVERSION installation is not yet complete!"
  echo ""
  echo "Please follow the instructions marked with FIX above and run this"
  echo "script again."
  echo ""
  exit 1
}


# Check if running as root
if [[ $EUID -ne 0 ]]; then
   echo -e "${RED}[-]${RESET} Error: $0 must be ${RED}run as root${RESET}" 1>&2
   exit 1
fi

# Run all commands from a publicly accessible dir.
cd /

# LOG start
echo "gvm-check-setup $CHECKVERSION" > $LOG
echo "  Date: " `date -R` >> $LOG
echo "" >> $LOG


echo "Step 1: Checking OpenVAS (Scanner)... "

echo "Checking presence of OpenVAS Scanner ..." >> $LOG
openvas --version >> $LOG 2>&1
if [ $? -ne 0 ]
then
  log_and_print "ERROR: No OpenVAS Scanner found."
  log_and_print "FIX: Please install OpenVAS Scanner."
  check_failed
fi
echo "" >> $LOG

echo "Checking OpenVAS Scanner version ..." >> $LOG

VERSION=`openvas --version 2>>$LOG | head -1 | sed -e "s/OpenVAS //"`

if [ `echo $VERSION | grep "^$SCANNER_MAJOR" | wc -l` -ne "1" ]
then
  log_and_print "ERROR: OpenVAS Scanner too old or too new: $VERSION"
  log_and_print "FIX: Please install OpenVAS Scanner >= $SCANNER_MAJOR."
  check_failed
fi
echo "" >> $LOG

log_and_print "OK: OpenVAS Scanner is present in version $VERSION."

echo "Checking Server Cert file ..." >> $LOG
CAFILE="/var/lib/gvm/CA/servercert.pem"
if [ ! -e $CAFILE ]
then
  log_and_print "ERROR: No CA certificate file for Server found."
  log_and_print "FIX: Run 'sudo runuser -u _gvm -- gvm-manage-certs -a -f'."
  check_failed
fi
echo "" >> $LOG

log_and_print "OK: Server CA Certificate is present as $CAFILE."

echo "Checking permissions of /var/lib/openvas/gnupg/*"
if [ -e /var/lib/openvas/gnupg ]
then
  wrong_files=`find /var/lib/openvas/gnupg ! -user _gvm`
  if [ "$wrong_files" != "" ]
  then
    log_and_print "ERROR: _gvm group or _gvm user does not own all the files in /var/lib/openvas/gnupg"
    log_and_print "FIX: Run 'chown -R _gvm:_gvm /var/lib/openvas/gnupg'"
    check_failed
  else
    log_and_print "OK: _gvm owns all files in /var/lib/openvas/gnupg"
  fi
fi


echo "Checking presence of redis ..." >> $LOG
BINARY=`redis-server --version`

if [ $? -ne 0 ]
then
  log_and_print "ERROR: No redis-server installation found."
  log_and_print "FIX: You must install install redis-server".
  check_failed
  else
  log_and_print "OK: redis-server is present."
  HAVE_REDIS=1
fi
echo "" >> $LOG

if [ $HAVE_REDIS -eq 1 ]
then
  echo "Checking if redis-server is configured properly ..." >> $LOG
  REDISSOCKET=`grep db_address /etc/openvas/openvas.conf | sed -e "s/^db_address = //"`
  if [ -z "$REDISSOCKET" ]
  then
    log_and_print "ERROR: scanner is not configured to use a redis-server socket."
    log_and_print "FIX: Configure the db_address setting of the scanner to the path of the redis-server socket."
    check_failed
  else
    log_and_print "OK: scanner (db_address setting) is configured properly using the redis-server socket: $REDISSOCKET"
    echo "Checking if redis-server is running ..." >> $LOG
    if [ -e $REDISSOCKET ]
    then
      log_and_print "OK: redis-server is running and listening on socket: $REDISSOCKET."
    else
      log_and_print "ERROR: redis-server is not running or not listening on socket: $REDISSOCKET"
      log_and_print "FIX: You should start the redis-server with 'systemctl start redis-server@openvas.service' or configure it to listen on socket: $REDISSOCKET"
      check_failed
    fi
  fi
  log_and_print "OK: redis-server configuration is OK and redis-server is running."
fi

echo "" >> $LOG

echo "Checking NVT collection ..." >> $LOG
PLUGINSFOLDER="/var/lib/openvas/plugins"
if [ ! -d $PLUGINSFOLDER ]
then
  log_and_print "ERROR: Directory containing the NVT collection not found."
  log_and_print "FIX: Run the NVT synchronization script greenbone-nvt-sync."
  log_and_print "sudo runuser -u _gvm -- greenbone-nvt-sync."
  check_failed
fi

if [ -e $PLUGINSFOLDER ]
then
  wrong_files=`find $PLUGINSFOLDER ! -user _gvm`
  if [ "$wrong_files" != "" ]
  then
    log_and_print "ERROR: _gvm group or _gvm user does not own all the files in /var/lib/openvas/plugins"
    log_and_print "FIX: Run 'chown -R _gvm:_gvm /var/lib/openvas/plugins'"
    check_failed
  else
    log_and_print "OK: _gvm owns all files in /var/lib/openvas/plugins"
  fi
fi

NVTCOUNT=`find $PLUGINSFOLDER -name "*nasl" | wc -l`
if [ $NVTCOUNT -lt 10 ]
then
  log_and_print "ERROR: The NVT collection is very small."
  log_and_print "FIX: Run the synchronization script greenbone-nvt-sync."
  log_and_print "sudo runuser -u _gvm -- greenbone-nvt-sync."
  check_failed
fi
echo "" >> $LOG

log_and_print "OK: NVT collection in $PLUGINSFOLDER contains $NVTCOUNT NVTs."


#echo "Checking redis database ..." >> $LOG
#if ! runuser -u _gvm -- ls /var/lib/redis | grep openvas-dump.rdb
#then
#  log_and_print "WARNING: The Redis Database does not exist"
#  log_and_print "FIX: Run sudo runuser -u _gvm -- openvas -u"
#  check_failed
#else
#  log_and_print "OK: The redis database exists."
#fi
#echo "" >> $LOG

echo "Checking that the obsolete redis database has been removed"
if runuser -u _gvm -- redis-cli -s /var/run/redis-openvas/redis-server.sock --scan | grep -q OpenVAS
then
  log_and_print "ERROR: an old Redis DB still exists"
  log_and_print "FIX: You should run 'sudo runuser -u _gvm -- redis-cli -s /var/run/redis-openvas/redis-server.sock flushall'"
  log_and_print "And run 'systemctl restart redis-server@openvas.service'"
  check_failed
else
  log_and_print "OK: No old Redis DB"
fi
echo "" >> $LOG

echo "Checking presence of OSPD-OPENVAS ..." >> $LOG
ospd-openvas --version >> $LOG 2>&1
if [ $? -ne 0 ]
then
  log_and_print "ERROR: No Ospd-Openvas found."
  log_and_print "FIX: Please install ospd-openvas."
  check_failed
fi
echo "" >> $LOG

VERSION=`ospd-openvas --version 2>>$LOG | head -1 | sed -e "s/OSP Server for openvas: //"`
log_and_print "OK: ospd-OpenVAS is present in version $VERSION."


echo "Step 2: Checking GVMD Manager ... "

echo "Checking presence of GVMD ..." >> $LOG
gvmd --version >> $LOG 2>&1
if [ $? -ne 0 ]
then
  log_and_print "ERROR: No Manager (gvmd) found."
  log_and_print "FIX: Please install gvmd."
  check_failed
fi
echo "" >> $LOG

VERSION=`gvmd --version 2>>$LOG | head -1 | sed -e "s/Greenbone Vulnerability Manager //"`

if [ `echo $VERSION | grep "^$MANAGER_MAJOR" | wc -l` -ne "1" ]
then
  log_and_print "ERROR: GVM Manager too old or too new: $VERSION"
  log_and_print "FIX: Please install GVM Manager >= $MANAGER_MAJOR."
  check_failed
fi
echo "" >> $LOG

log_and_print "OK: GVM Manager (gvmd) is present in version $VERSION."


echo "Step 3: Checking Certificates ... "

echo "Checking GVM Manager client certificate ..." >> $LOG
CERTDIR=`dirname $CAFILE`
CLIENTCERTFILE="$CERTDIR/clientcert.pem"
if [ ! -e $CLIENTCERTFILE ]
then
  log_and_print "ERROR: No client certificate file of GVM found."
  log_and_print "FIX: Run 'sudo runuser -u _gvm -- gvm-manage-certs -a -f'"
  check_failed
#check that certificate is valid
else
  if openssl verify -CAfile $CERTDIR/cacert.pem $CLIENTCERTFILE |grep -q ^error
  then
    log_and_print "ERROR: the client certificate file of GVM is not valid."
    log_and_print "FIX: Run 'sudo runuser -u _gvm -- gvm-manage-certs -a -f'"
    check_failed
  fi
fi
echo "" >> $LOG

log_and_print "OK: GVM client certificate is valid and present as $CLIENTCERTFILE."

echo "Verifying certificate infrastructure ..." >> $LOG
gvm-manage-certs -V >> $LOG 2>&1
if [ $? -ne 0 ]
then
  log_and_print "ERROR: Your GVM certificate infrastructure did NOT pass validation."
  log_and_print "FIX: Run 'sudo runuser -u _gvm -- gvm-manage-certs -a'."
  check_failed
fi
echo "" >> $LOG

log_and_print "OK: Your GVM certificate infrastructure passed validation."


echo "Step 4: Checking data ... "

echo "Checking SCAP data ..." >> $LOG
STATEDIR="/var/lib/gvm"
SCAPCOUNT=`find $STATEDIR/scap-data -name "*xml" | wc -l`
if [ $SCAPCOUNT -lt 10 ]
then
  log_and_print "ERROR: SCAP DATA are missing."
  log_and_print "FIX: Run the SCAP synchronization script greenbone-feed-sync."
  log_and_print "sudo runuser -u _gvm -- greenbone-feed-sync --type SCAP."
  check_failed
fi
echo "" >> $LOG

log_and_print "OK: SCAP data found in $STATEDIR/scap-data."

echo "Checking CERT data ..." >> $LOG
CERTCOUNT=`find $STATEDIR/cert-data -name "*xml" | wc -l`
if [ $CERTCOUNT -lt 10 ]
then
  log_and_print "ERROR: CERT data are missing."
  log_and_print "FIX: Run the CERT synchronization script greenbone-feed-sync."
  log_and_print "sudo runuser -u _gvm -- greenbone-feed-sync --type CERT."
  check_failed
  echo "" >> $LOG
else
  log_and_print "OK: CERT data found in $STATEDIR/cert-data."
fi


echo "Step 5: Checking Postgresql DB and user ... "

echo "Checking postgresql ..." >> $LOG
if ! systemctl is-active -q postgresql
then
  systemctl start postgresql
  log_and_print "Starting postgresql service"
fi

# check which postgresql version is using the port 5432 and ensure that the
# version is the one used for gvmd build
postgres_version=`pg_lsclusters --no-header | awk '$3 == "5432" { print $1 }'`

# get the postgresql version used for gvmd compilation
gvmd_postgres_version=$(cat /usr/share/gvmd/postgresql-version)
gvmd_postgres_version=${gvmd_postgres_version%%.*}

if [ $postgres_version = "" ]
then
  log_and_print "ERROR: No postgresql version uses the port 5432."
  log_and_print "FIX: Please use pg_upgradecluster to upgrade your postgresql installation"
  check_failed
else
  if [ ${postgres_version%%.*} -ne $gvmd_postgres_version ]
  then
    log_and_print "ERROR: The default postgresql version is not the one used for gvmd compilation: ($postgres_version, need $gvmd_postgres_version)."
    log_and_print "FIX: Please use pg_upgradecluster to upgrade your postgresql installation"
    check_failed
  else
    log_and_print "OK: Postgresql version and default port are OK."
  fi
fi
echo "" >> $LOG

echo "Checking if database exists ..." >> $LOG
if ! runuser -u postgres -- psql -l | grep gvmd | grep _gvm
then
  log_and_print "ERROR: The Postgresql DB does not exist."
  log_and_print "FIX: Run 'sudo runuser -u postgres -- /usr/share/gvm/create-postgresql-database'"
  check_failed
fi

echo "Checking Database version ..." >> $LOG
if runuser -u _gvm -- gvmd --get-users 2>&1 | grep "Database is wrong version"
then
  log_and_print "ERROR: Database is wrong version. You have installed a new gvmd version"
  log_and_print "FIX: Run 'sudo runuser -u _gvm -- gvmd --migrate'"
  check_failed
fi

echo "Checking if users exist ..." >> $LOG
gvmd_users=`runuser -u _gvm -- gvmd --get-users`
if [ -z "$gvmd_users" ]
then
  log_and_print "ERROR: No users found. You need to create at least one user to log in."
  log_and_print "FIX: create a user by running 'sudo runuser -u _gvm -- gvmd --create-user=<name> --password=<password>'"
  check_failed
else
  log_and_print "OK: At least one user exists."
fi
echo "" >> $LOG


echo "Step 6: Checking Greenbone Security Assistant (GSA) ... "

echo "Checking presence of Greenbone Security Assistant ..." >> $LOG
gsad --version >> $LOG 2>&1
if [ $? -ne 0 ]
then
  log_and_print "ERROR: No Greenbone Security Assistant (gsad) found."
  log_and_print "FIX: Please install Greenbone Security Assistant."
  check_failed
fi
echo "" >> $LOG

VERSION=`gsad --version | head -1 | sed -e "s/Greenbone Security Assistant //"`

if [ `echo $VERSION | grep "^$GSA_MAJOR" | wc -l` -ne "1" ]
then
  log_and_print "ERROR: Greenbone Security Assistant too old or too new: $VERSION"
  log_and_print "FIX: Please install Greenbone Security Assistant >= $GSA_MAJOR."
  check_failed
fi
echo "" >> $LOG

log_and_print "OK: Greenbone Security Assistant is present in version $VERSION."

echo "Step 7: Checking if GVM services are up and running ... "

echo "Checking services ..." >> $LOG
if ! systemctl is-active -q ospd-openvas
then
  log_and_print "Starting ospd-openvas service"
  systemctl start ospd-openvas
  log_and_print "Waiting for ospd-openvas service"
  sleep 10s
  if ! systemctl is-active -q ospd-openvas
  then
    log_and_print "ERROR: ospd-openvas service did not start."
    log_and_print "Please check journalctl -xe"
    check_failed
  fi
fi
log_and_print "OK: ospd-openvas service is active."

if ! systemctl is-active -q gvmd
then
  log_and_print "Starting gvmd service"
  systemctl start gvmd
  log_and_print "Waiting for gvmd service"
  sleep 10s
  if ! systemctl is-active -q gvmd
  then
    log_and_print "ERROR: gvmd service did not start."
    log_and_print "Please check journalctl -xe and /var/log/gvm/gvmd.log"
    check_failed
  fi
fi
log_and_print "OK: gvmd service is active."

if ! systemctl is-active -q greenbone-security-assistant
then
  log_and_print "Starting greenbone-security-assistant service"
  systemctl start greenbone-security-assistant
  log_and_print "Waiting for greenbone-security-assistant service"
  sleep 10s
  if ! systemctl is-active -q greenbone-security-assistant
  then
    log_and_print "ERROR: greenbone-security-assistant service did not start."
    log_and_print "Please check journalctl -xe and /var/log/gvm/gsad.log"
    check_failed
  fi
fi
log_and_print "OK: greenbone-security-assistant service is active."


echo "Step 8: Checking few other requirements..."

echo "Checking presence of nmap ..." >> $LOG
NMAP=`type nmap 2> /dev/null`
if [ $? -ne 0 ]
then
  if [ $SKIP_NMAP -eq 0 ]
    then 
      log_and_print "ERROR: No nmap installation found."
      log_and_print "FIX: Install nmap."
      check_failed
  fi
else
  log_and_print "OK: nmap is present in version $VERSION."
fi
echo "" >> $LOG


echo "Checking presence of ssh-keygen ..." >> $LOG
SSHKEYGEN=`type ssh-keygen 2> /dev/null`
if [ $? -ne 0 ]
then
  log_and_print "WARNING: Could not find ssh-keygen binary, LSC credential generation for GNU/Linux targets will not work."
  log_and_print "SUGGEST: Install ssh-keygen."
  HAVE_SSHKEYGEN=0
else
  log_and_print "OK: ssh-keygen found, LSC credential generation for GNU/Linux targets is likely to work."
  HAVE_SSHKEYGEN=1
fi
echo "" >> $LOG

echo "Checking presence of nsis ..." >> $LOG
NSIS=`type makensis 2> /dev/null`
if [ $? -ne 0 ]
then
  log_and_print "WARNING: Could not find makensis binary, LSC credential package generation for Microsoft Windows targets will not work."
  log_and_print "SUGGEST: Install nsis."
  HAVE_NSIS=0
else
  log_and_print "OK: nsis found, LSC credential package generation for Microsoft Windows targets is likely to work."
  HAVE_NSIS=1
fi

echo "Checking for SELinux ..." >> $LOG
selinux=`getenforce 2>/dev/null`
if [ $? -eq 0 ]
then
 if [ $selinux != "Disabled" ]
 then
  log_and_print "ERROR: SELinux is enabled. For a working OpenVAS installation you need to disable it."
  log_and_print "FIX: Please disable SELinux."
  check_failed
 else
  log_and_print "OK: SELinux is disabled."
 fi 
fi

echo "Checking xsltproc presence ..." >> $LOG
XSLTPROC=`type xsltproc 2> /dev/null`
if [ $? -ne 0 ]
then
  log_and_print "WARNING: Could not find xsltproc binary, most report formats will not work."
  log_and_print "SUGGEST: Install xsltproc."
else
  log_and_print "OK: xsltproc found."
fi
echo "" >> $LOG

echo "Checking status of password policy ..." >> $LOG
CONFDIR="/etc/gvm"
grep -v "^[#]" $CONFDIR/pwpolicy.conf | grep -v "^$" > /dev/null 2>&1
if [ $? -ne 0 ]
then
  log_and_print "WARNING: Your password policy is empty."
  log_and_print "SUGGEST: Edit the $CONFDIR/pwpolicy.conf file to set a password policy."
else
  log_and_print "OK: The password policy file at $CONFDIR/pwpolicy.conf contains entries."
fi
echo "" >> $LOG

echo "" >> $LOG


echo ""
echo "It seems like your GVM-$CHECKVERSION installation is OK."
echo ""
