#!/bin/bash -e

inet_aton ()
{
    IFS="." read -a ipaddr <<< "$1"

    for i in 3 2 1 0
    do
        (( ip32 += ipaddr[3-i] * (256 ** i) ))
    done

    echo $ip32
}

range_match ()
{
    ip=`inet_aton "$1"`
    range_min=`inet_aton "$2"`
    range_max=`inet_aton "$3"`

    if [ $ip -gt $(($range_min - 1)) ] && [ $ip -lt $(($range_max + 1)) ]; then
        echo 1;
    else
        echo 0;
    fi
}

is_ipv4_address ()
{
    if [ `echo $1 | grep -Pc "^([0-2]?\d)?\d.([0-2]?\d)?\d.([0-2]?\d)?\d.([0-2]?\d)?\d$"` -eq 0 ]; then
        echo 0;
        return;
    fi

    IFS="." read -a ipaddr <<< "$1"

    for i in 3 2 1 0
    do
        if [ ${ipaddr[3-i]} -lt 0 ] || [ ${ipaddr[3-i]} -gt 255 ]; then
            echo 0;
            return;
        fi
    done

    echo 1;
}

custom_integration=0
ip_address=""
install_client=1
install_realtime=-1 # -1 means unspecified or unanswered, this is to avoid asking to install real-time when a --realtime flag is passed

while [ $# -gt 0 ]
do
    arg="$1"

    case $arg in
        -a)
        ip_address="$2"
        if [ `is_ipv4_address "$ip_address"` -eq 0 ]; then
            echo "Invalid IPv4 address specified: $ip_address"
            exit 1
        fi
        shift
        ;;
        --ip-address=*)
        ip_address="${arg#*=}"
        if [ `is_ipv4_address "$ip_address"` -eq 0 ]; then
            echo "Invalid IPv4 address specified: $ip_address"
            exit 1
        fi
        ;;
        -c)
        custom_integration=1
        ;;
        --realtime=*)
        if [ "${arg#*=}" == "yes" ]; then
            install_realtime=1
        elif [ "${arg#*=}" == "no" ]; then
            install_realtime=0
        else
            echo "Invalid real-time setting specified: ${arg#*=}"
            exit 1
        fi
        ;;
        *)
        if [ `is_ipv4_address "$1"` -eq 1 ]; then
            ip_address="$1"
        else
            echo "Invalid argument specified: $1"
            exit 1
        fi
        ;;
    esac
    shift
done

if [ -e /etc/redhat-release ]; then
    if [ `yum list installed | grep -c patchman-client` -gt 0 ]; then
        echo "Patchman is already installed."
        echo ""
        install_client=0
    fi
elif [ -e /etc/debian_version ]; then
    if [ `dpkg --get-selections | grep "install" | grep -v "deinstall" | grep -c patchman-client` -gt 0 ]; then
        echo "Patchman is already installed."
        echo ""
        install_client=0
    fi
fi

if [ $install_client -eq 1 ] ; then
    if [ $custom_integration -eq 0 ]; then
        if [ ! -f /usr/local/cpanel/cpanel ] &&
                [ ! -f /usr/local/directadmin/directadmin ] &&
                [ ! -d /usr/local/psa/ ]; then
            echo "Patchman was not able to detect standard platform software to integrate with, and"
            echo "will not be able to determine which directories it needs to scan. This means that"
            echo "the software will not be able to perform its functions."
            echo ""
            echo "If you are using a custom integration method, you can continue the installation"
            echo "and configure Patchman for the custom integration afterwards. If you are not using"
            echo "a custom integration method, please contact customer support at support@patchman.co"
            echo "for more information."
            echo ""
            echo -n "Continue? [y/N] "
            read -n 1 continue

            if [ "$continue" != "" ]; then
                echo ""
            fi

            if [ "$continue" != "y" ] && [ "$continue" != "Y" ]; then
                exit 1
            fi

            echo ""
            echo "Note: If you want to avoid this question during future installations, you can supply"
            echo "      the -c option to this script, e.g.:"
            echo ""
            echo "      /bin/bash -e $0 -c"
            echo ""

            sleep 2
        fi
    fi

    if [ `is_ipv4_address "$ip_address"` -eq 0 ]; then
        source_address=`ip r get 139.162.216.201 | grep -Po "(?<=src ).+"`

        if [ `range_match $source_address 10.0.0.0 10.255.255.255` -eq 1 ] ||
                [ `range_match $source_address 172.16.0.0 172.31.255.255` -eq 1 ] ||
                [ `range_match $source_address 192.168.0.0 192.168.255.255` -eq 1 ]; then
            echo "Patchman can't automatically detect the outbound IP on this machine, since you're"
            echo "using a NAT. Please manually provide the outbound IPv4 address that we should use."
            echo ""
            echo -n "IP address: "
            read ip_address

            if [ `is_ipv4_address "$ip_address"` -eq 0 ]; then
                echo "Invalid IPv4 address specified, aborting."
                exit 1
            fi

            echo ""
            echo "Note: If you want to avoid this question during future installations, you can supply"
            echo "      the address to the script using the -a or --ip-address options, e.g.:"
            echo ""
            echo "      /bin/bash -e $0 -a $ip_address"
            echo "      /bin/bash -e $0 --ip-address=$ip_address"
            echo ""

            sleep 2
        fi
    fi

    if [ -e /etc/redhat-release ]; then
        version="`cat /etc/redhat-release | grep -o "release ." | cut -d' ' -f2`"

        if [ "$version" = "6" ] || [ "$version" = "7" ] || [ "$version" = "8" ]; then
            wget https://download.patchman.co/repo/rhel/RPM-GPG-KEY-Patchman -O /etc/pki/rpm-gpg/RPM-GPG-KEY-Patchman
        else
            echo "Unsupported RHEL version, terminating installation (`cat /etc/redhat-release`)"
            exit 1
        fi

        wget https://download.patchman.co/repo/rhel/patchman.repo -O /etc/yum.repos.d/patchman.repo

        yum -y install patchman-client
    elif [ -e /etc/debian_version ]; then
        apt-get -y install apt-transport-https

        which lsb_release >/dev/null || apt-get -y install lsb-release

        version="`lsb_release -c -s`"

        if [ "$version" = "precise" ] || [ "$version" = "quantal" ] || [ "$version" = "raring" ] || [ "$version" = "saucy" ] || [ "$version" = "trusty" ]; then
            wget https://download.patchman.co/repo/debian/patchman.list -O /etc/apt/sources.list.d/patchman.list
            wget https://download.patchman.co/repo/debian/patchman.gpg -O- | apt-key add -

            sed -i "s/ \w\+ main$/ wheezy main/" /etc/apt/sources.list.d/patchman.list
        elif [ "$version" = "jessie" ] || [ "$version" = "utopic" ] || [ "$version" = "vivid" ] || [ "$version" = "wily" ] || [ "$version" = "xenial" ] || [ "$version" = "yakkety" ]; then
            wget https://download.patchman.co/repo/debian/patchman.list -O /etc/apt/sources.list.d/patchman.list
            wget https://download.patchman.co/repo/debian/patchman.gpg -O- | apt-key add -

            sed -i "s/ \w\+ main$/ jessie main/" /etc/apt/sources.list.d/patchman.list
        elif [ "$version" = "stretch" ] || [ "$version" = "zesty" ] || [ "$version" = "artful" ] || [ "$version" = "bionic" ]; then
            wget https://download.patchman.co/repo/debian/patchman.list -O /etc/apt/sources.list.d/patchman.list
            wget https://download.patchman.co/repo/debian/patchman.gpg -O /usr/share/keyrings/patchman-archive-keyring.gpg

            sed -i "s/ / [signed-by=\/usr\/share\/keyrings\/patchman-archive-keyring.gpg] /" /etc/apt/sources.list.d/patchman.list
            sed -i "s/ \w\+ main$/ stretch main/" /etc/apt/sources.list.d/patchman.list
        elif [ "$version" = "buster" ] || [ "$version" = "cosmic" ] || [ "$version" = "disco" ] || [ "$version" = "eoan" ] || [ "$version" = "focal" ]; then
            wget https://download.patchman.co/repo/debian/patchman.list -O /etc/apt/sources.list.d/patchman.list
            wget https://download.patchman.co/repo/debian/patchman.gpg -O /usr/share/keyrings/patchman-archive-keyring.gpg

            sed -i "s/ / [signed-by=\/usr\/share\/keyrings\/patchman-archive-keyring.gpg] /" /etc/apt/sources.list.d/patchman.list
            sed -i "s/ \w\+ main$/ buster main/" /etc/apt/sources.list.d/patchman.list
        elif [ "$version" = "bullseye" ] || [ "$version" = "groovy" ] || [ "$version" = "hirsute" ] || [ "$version" = "impish" ]; then
            wget https://download.patchman.co/repo/debian/patchman.list -O /etc/apt/sources.list.d/patchman.list
            wget https://download.patchman.co/repo/debian/patchman.gpg -O /usr/share/keyrings/patchman-archive-keyring.gpg

            sed -i "s/ / [signed-by=\/usr\/share\/keyrings\/patchman-archive-keyring.gpg] /" /etc/apt/sources.list.d/patchman.list
            sed -i "s/ \w\+ main$/ bullseye main/" /etc/apt/sources.list.d/patchman.list
        else
            echo "Unsupported Debian version, terminating installation (`lsb_release -d -s`)"
            exit 1
        fi

        apt-get update

        apt-get -y install patchman-client
    else
        echo "Unsupported OS version, terminating installation"
        exit 1
    fi

    if [ ! -e /etc/patchman/license/key ]; then
        echo -n "Please enter your registration key: "
        read reg_key

        echo "$reg_key" > /etc/patchman/license/key
    else
        echo "Registration key found"
    fi

    if [ `is_ipv4_address $ip_address` -eq 1 ]; then
        if [ -f /etc/patchman/patchman.ini ] && [ `grep -c "^ip=" /etc/patchman/patchman.ini` -gt 0 ]; then
            sed -i "s/^ip=.\+$/ip=$ip_address/" /etc/patchman/patchman.ini
        else
            echo -e "\n[network]\nip=$ip_address" >> /etc/patchman/patchman.ini
        fi
    fi

    exec 3>&1
    exec 4>&2

    status=`(service patchman start >&3 2>&4 && echo 0) || echo $?`

    if [ $status -eq 0 ]; then
        status=`(service patchman status >/dev/null 2>&1 && echo 0) || echo $?`
    fi

    echo ""
    printf "=%.s" $(seq 1 `tput cols`)
    echo -e "\n"

    if [ $status -eq 0 ]; then
        echo "Installation finished. Patchman is now installed and running!"
        echo ""
        echo "Remember to approve the new server in your Patchman Portal account to start scanning."
        echo ""
    else
        echo "An error occurred. Please contact support@patchman.co and mail the files in /var/log/patchman/ for troubleshooting purposes."
        echo ""
        exit 0
    fi
fi

if [ -e /etc/redhat-release ] && [ `yum list installed | grep -c patchman-client-realtime` -gt 0 ]; then
    # real-time is already installed so default to "no"
    install_realtime=0
elif [ -e /etc/debian_version ] && [ `dpkg --get-selections | grep "install" | grep -v "deinstall" | grep -c patchman-client-realtime` -gt 0 ]; then
    # real-time is already installed so default to "no"
    install_realtime=0
elif [ ! -e /etc/debian_version ] && [ ! -e /etc/redhat-release ]; then
    echo "Unsupported OS version, terminating installation"
    exit 1
fi

if [ $install_realtime -eq -1 ]; then
    # real-time is not installed yet
    echo "Do you also want to use real-time scanning? (Note this feature requires a plan that supports real-time scanning.)"
    echo ""
    echo -n "Install? [y/N] "
    read -rn 1 realtime

    if [ "$realtime" != "" ]; then
        echo ""
    fi

    if [ "$realtime" == "y" ] || [ "realtime" == "Y" ]; then
        install_realtime=1
    else
        install_realtime=0
    fi

    echo ""
    echo "Note: If you want to avoid this question during future installations, you can supply"
    echo "            the --realtime option to this script, e.g.:"
    echo ""
    echo "            /bin/bash -e $0 --realtime=[yes/no]"
    echo ""

    sleep 2
fi

if [ $install_realtime -eq 1 ]; then
    if [ -e /etc/redhat-release ]; then
        yum -y install patchman-client-realtime

        if [ `yum list installed | grep -c patchman-client-realtime` -eq 1 ]; then
            echo "Installation of real-time scanning finished."
            echo ""
            echo "Remember to verify that real-time scanning is enabled for this server group in the Patchman Portal."
        else
            echo "An error occurred while installing real-time scanning. Please contact support@patchman.co."
            echo ""
            exit 0
        fi
    elif [ -e /etc/debian_version ]; then
        apt-get install -y patchman-client-realtime

        if [ `dpkg --get-selections | grep "install" | grep -v "deinstall" | grep -c patchman-client-realtime` -eq 1 ]; then
            echo "Installation of real-time scanning finished."
            echo ""
            echo "Remember to verify that real-time scanning is enabled for this server group in the Patchman Portal."
        else
            echo "An error occurred while installing real-time scanning. Please contact support@patchman.co."
            exit 0
        fi
    fi

fi

echo ""
