#!/bin/bash 

#########################################################################################
# Copyright (C) 2010 Leon Ward
# leon@openfpc.org
# openfpc-dbmaint.pl - Part of the OpenFPC - (Full Packet Capture) project
#
# Quick script to create an OpenFPC connection database.
#
# The mysql IPv6 function source in addfuncs() came from edward@openfpc.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, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
#########################################################################################

ACTION=$1
TYPE=$2
CONFIG=$3

function die
{
	echo ERROR: $1
	exit 1
}

function chkroot()
{
	IAM=$(whoami)
        if [ "$IAM" != "root" ]
        then
                die " Must be root to run this script"
        fi  
}


function addfuncs
{
	# Create mysql IPv6 functions
	echo Adding function INET_ATON6... to DB $SESSION_DB_NAME
	SQL="
use $SESSION_DB_NAME;
DELIMITER //
CREATE FUNCTION INET_ATON6(n CHAR(39))
RETURNS DECIMAL(39) UNSIGNED
DETERMINISTIC
BEGIN
    RETURN CAST(CONV(SUBSTRING(n FROM  1 FOR 4), 16, 10) AS DECIMAL(39))
                       * 5192296858534827628530496329220096 -- 65536 ^ 7
         + CAST(CONV(SUBSTRING(n FROM  6 FOR 4), 16, 10) AS DECIMAL(39))
                       *      79228162514264337593543950336 -- 65536 ^ 6
         + CAST(CONV(SUBSTRING(n FROM 11 FOR 4), 16, 10) AS DECIMAL(39))
                       *          1208925819614629174706176 -- 65536 ^ 5
         + CAST(CONV(SUBSTRING(n FROM 16 FOR 4), 16, 10) AS DECIMAL(39))
                       *               18446744073709551616 -- 65536 ^ 4
         + CAST(CONV(SUBSTRING(n FROM 21 FOR 4), 16, 10) AS DECIMAL(39))
                       *                    281474976710656 -- 65536 ^ 3
         + CAST(CONV(SUBSTRING(n FROM 26 FOR 4), 16, 10) AS DECIMAL(39))
                       *                         4294967296 -- 65536 ^ 2
         + CAST(CONV(SUBSTRING(n FROM 31 FOR 4), 16, 10) AS DECIMAL(39))
                       *                              65536 -- 65536 ^ 1
         + CAST(CONV(SUBSTRING(n FROM 36 FOR 4), 16, 10) AS DECIMAL(39))
         ;
END;
//

CREATE FUNCTION INET_NTOA6(n DECIMAL(39) UNSIGNED)
RETURNS CHAR(39)
DETERMINISTIC
BEGIN
  DECLARE a CHAR(39)             DEFAULT '';
  DECLARE i INT                  DEFAULT 7;
  DECLARE q DECIMAL(39) UNSIGNED DEFAULT 0;
  DECLARE r INT                  DEFAULT 0;
  WHILE i DO
    -- DIV doesnt work with nubers > bigint
    SET q := FLOOR(n / 65536);
    SET r := n MOD 65536;
    SET n := q;
    SET a := CONCAT_WS(':', LPAD(CONV(r, 10, 16), 4, '0'), a);

    SET i := i - 1;
  END WHILE;

  SET a := TRIM(TRAILING ':' FROM CONCAT_WS(':',
                                            LPAD(CONV(n, 10, 16), 4, '0'),
                                            a));

  RETURN a;

END;
//
DELIMITER ;	
"
	mysql -u$DBUSER -p$DBPASS -e "$SQL"
}

function readconfig
{
    # Read in configuration from $CONFIG file.
    if [ -f $CONFIG ] ; then
		source $CONFIG || die "Unable to read config file \"$CONFIG\""
		# Check all vars required are set in $CONFIG
		[ -n "$ENABLE_SESSION" ] || die "ENABLE_SESSION not set in $CONFIG"
		[ -n "$SESSION_DB_NAME" ] || die "SESSION_DB_NAME not set in $CONFIG"
		[ -n "$SESSION_DB_USER" ] || die "SESSION_DB_USER not set in $CONFIG"
		[ -n "$SESSION_DB_PASS" ] || die "SESSION_DB_PASS not set in $CONFIG"
		[ -n "$NODENAME" ] || die "NODENAME not set in $CONFIG"
                [ -n "$GUI_DB_NAME" ] || die "GUI_DB_NAME not set in $CONFIG"
                [ -n "$GUI_DB_USER" ] || die "GUI_DB_USER not set in $CONFIG"
                [ -n "$GUI_DB_PASS" ] || die "GUI_DB_PASS not set in $CONFIG"
                
		echo -e "[*] Enter mysql \"root\" credentials to connect to your local mysql server in order to create the databases"
		read -p "    DB root Username: " DBUSER
		stty -echo
		read -p "    DB root Password: " DBPASS
		stty echo
                
                # Check we can access DB with these creds
                mysql -u$DBUSER -p$DBPASS -e 'SHOW DATABASES;' > /dev/null || die "Unable to connect to database - Did you enter the correct user/password?"
    else
        die "Cant find config file $CONFIG"
    fi

}

function configure_session
{
		echo ---------------------------------------------------------
		echo -e "[*] Working on Instance $CONFIG ."
		read -p "    Would you like session capture ENABLED on $NODENAME? (y/n)"  SESSION_ON
		if [ "$SESSION_ON" == "y" ] 
		then
			echo -e "[-] Enabling session capture in $NODENAME config"
			sed -e 's/^ENABLE_SESSION=0/ENABLE_SESSION=1/g' -i $CONFIG
			echo -e "    Done."
		else 
			echo -e "[-] Disabling session capture in $NODENAME config"
			sed -e 's/^ENABLE_SESSION=1/ENABLE_SESSION=0/g' -i $CONFIG
		fi

		if which cxtracker >/dev/null ; then
			echo -e "[-] Found cxtracker."	
		else 
			echo -e "[!] WARNING: cxtracker is NOT found on this host, and is required for session capture"
			echo -e "    You can find it here -> http://www.openfpc.org/downloads"
			echo -e "    Continuing, but don't expect session capture to work until cxtracker is installed"
		fi	
}

function configure_gui
{
    echo -e "\n[*] Enter an initial username for the first OpenFPC GUI user"
    read -p "    GUI Username: " ADMIN_USER
    stty -echo
    read -p "    GUI Password: " ADMIN_PASS
    stty echo
    echo ""
    read -p "    Email address: " EMAIL
    read -p "    Real Name: " REAL_NAME
    
    DESCRIPTION="Administrator"
    TIMEZONE="Europe/London"
    DEFAULTNODE="None"
    
    # Add this user to the openfpc $CONFIG to allow them to get pcaps
    # 1 Check if the user already exists
    
    if grep ^USER=$ADMIN_USER= $CONFIG
    then
        echo FOUND USER $ADMIN_USER IN $CONFIG
	sed -e "s/USER=$ADMIN_USER=.*/USER=$ADMIN_USER=$ADMIN_PASS/g" -i $CONFIG
        
    else
        echo USER NOT FOUND. Adding $ADMIN_USER.
        echo -e "USER=$ADMIN_USER=$ADMIN_PASS\n" >> $CONFIG
    fi
}

function create_gui
{

    echo CREATING GUI DATABASE
    echo ---------------------------
    # Test we have access

    # Check if DB already exists
    mysql -u$DBUSER -p$DBPASS -e "USE $GUI_DB_NAME;" > /dev/null 2>&1 && die "Database $GUI_DB_NAME already exists"

    # Create new DB
    mysql -u$DBUSER -p$DBPASS -e "CREATE DATABASE $GUI_DB_NAME;" > /dev/null 2>&1 || die "Unable to create DB $GUI_DB_NAME - Did you enter the correct user/password?"

    # Create new DB user
    mysql -u$DBUSER -p$DBPASS -e "use 'mysql'; CREATE USER '$GUI_DB_USER'@'localhost' IDENTIFIED BY '$GUI_DB_PASS';"
    mysql -u$DBUSER -p$DBPASS -e "use $GUI_DB_NAME; GRANT ALL PRIVILEGES ON $GUI_DB_NAME.* TO '$GUI_DB_USER'@'localhost';"


    echo GUI DB Created.
    
    # Create tables
    SQL="CREATE TABLE users (
         id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
         username VARCHAR(20),
         realname VARCHAR(20),
         email VARCHAR(20),
         description VARCHAR(20),
         password VARCHAR(20),
         timezone VARCHAR(30),
         defaultnode VARCHAR(30)
       );"
    mysql -u$DBUSER -p$DBPASS $GUI_DB_NAME -e "$SQL"
    
    SQL="INSERT INTO users (username,password,realname,email,description,defaultnode,timezone)
        VALUES (
            '$ADMIN_USER', '$ADMIN_PASS', '$REAL_NAME', '$EMAIL', '$DESCRIPTION', '$DEFAULTNODE', '$TIMEZONE'
        );"
    mysql -u$DBUSER -p$DBPASS $GUI_DB_NAME -e "$SQL"

    echo "New user $ADMIN_USER added."        
    

}

function drop_gui
{
    echo REMOVING DATABASE
    echo ---------------------------
    # Test we have access
    mysql -u$DBUSER -p$DBPASS -e 'SHOW DATABASES;' > /dev/null 2>&1 || die "Unable to connect to database - Did you enter the correct user/password"
    # Check if DB already exists
    mysql -u$DBUSER -p$DBPASS -e "USE $GUI_DB_NAME;" > /dev/null 2>&1 || die "Database $GUI_DB_NAME Not found!"
    
    mysql -u$DBUSER -p$DBPASS -e "DROP DATABASE $GUI_DB_NAME;" > /dev/null 2>&1 || die "Database $GUI_DB_NAME Not found!"
    mysql -u$DBUSER -p$DBPASS -e "use 'mysql'; DROP USER '$GUI_DB_USER'@'localhost';" || die "Unable to remove user $GUI_DB_USER"

    echo GUI DB Dropped.

}

function create_session
{
	echo CREATING DATABASE
	echo ---------------------------
	# Test we have access
	mysql -u$DBUSER -p$DBPASS -e 'SHOW DATABASES;' > /dev/null || die "Unable to connect to database"

	# Check if DB already exists
	mysql -u$DBUSER -p$DBPASS -e "USE $SESSION_DB_NAME;" > /dev/null 2>&1 && die "Database $SESSION_DB_NAME already exists"

	# Create new DB	
	mysql -u$DBUSER -p$DBPASS -e "CREATE DATABASE $SESSION_DB_NAME;" > /dev/null 2>&1 || die "Unable to create DB $SESSION_DB_NAME"

	# Create new DB user
	mysql -u$DBUSER -p$DBPASS -e "use 'mysql'; CREATE USER '$SESSION_DB_USER'@'localhost' IDENTIFIED BY '$SESSION_DB_PASS';"
	mysql -u$DBUSER -p$DBPASS -e "use $SESSION_DB_NAME; GRANT ALL PRIVILEGES ON $SESSION_DB_NAME.* TO '$SESSION_DB_USER'@'localhost';"
	echo Session DB Created.
}

function drop_session
{
	echo REMOVING DATABASE
	echo ---------------------------
	# Test we have access
	mysql -u$DBUSER -p$DBPASS -e 'SHOW DATABASES;' > /dev/null 2>&1 || die "Unable to connect to database"
	# Check if DB already exists
	mysql -u$DBUSER -p$DBPASS -e "USE $SESSION_DB_NAME;" > /dev/null 2>&1 || die "Database $SESSION_DB_NAME Not found!"
	mysql -u$DBUSER -p$DBPASS -e "DROP DATABASE $SESSION_DB_NAME;" > /dev/null 2>&1 || die "Database $SESSION_DB_NAME Not found!"
	mysql -u$DBUSER -p$DBPASS -e "use 'mysql'; DROP USER '$SESSION_DB_USER'@'localhost';" || die "Unable to remove user $SESSION_DB_USER"

	echo Session DB Dropped.
}

function showhelp
{
    echo -e ""
    echo -e "* openfpc-dbmaint "
    echo -e "  Create and maintain an OpenFPC databases"
    echo -e ""
    echo -e "  Usage:"
    echo -e "  openfpc-dbmaint.sh <action> <db_type> <config_file>\n"
    echo -e "      action          create / drop"
    echo -e "      db_type         session / gui"
    echo -e "      config_file     /path/to/openfpc-config.conf"
    echo -e ""
    echo -e "  Example 1: Creating a session database"
    echo -e "  openfpc-dbmaint create session /etc/openfpc/openfpc-default.conf"
    echo -e ""
    echo -e "  Example 2: Dropping the gui database"
    echo -e "  openfpc-dbmaint drop gui /etc/openfpc/openfpc-default.conf"
    echo -e ""

}

function restartopenfpc
{
    echo -e "[*] Restarting OpenFPC\n"
    openfpc -a stop
    openfpc -a start
}

ARGC=$#
if [ "$ARGC" == "2" ] ; then 
	echo -e "Error: incorrect arguements"
        showhelp
	exit 1
fi

case $1 in 
	create)
       	    chkroot	
            readconfig
            
            if [ "$TYPE" == "session" ]
            then
		configure_session
                create_session
		addfuncs
                restartopenfpc
            elif [ "$TYPE" == "gui" ]
            then
                configure_gui
                create_gui
                restartopenfpc
                echo -e "[*] DB Configured and admin user added. Now navigate to http://<ip.add.re.ss>/openfpc/\n"
            else
                die "ERROR: Invalid type $TYPE. See usage"
            fi
	;;

	drop)
            chkroot
            readconfig
            
            if [ "$TYPE" == "session" ]
            then
		drop_session
            elif [ "$TYPE" == "gui" ]
            then
                drop_gui
            else
                die "ERROR: Invalid type $TYPE. See usage"
            fi
	;;
	clean)
	;;
	*)
            echo -e "\nERROR: Invalid args."
            showhelp
	;;

esac
