#!/bin/bash

set -e #Exit this script if any commands exit with a non zero status

# need to use functions here to clean this up
# not sure why it wasn't done at first

. /usr/share/openvpn-server/functions.sh

#These are the Certificate Authority defaults
DEFAULT_COUNTRY=AU   #This MUST be a 2 letter ISO country code or the CA setup will fail
DEFAULT_PROVINCE=NSW
DEFAULT_CITY=Sydney
DEFAULT_ORGANISATION="Acme Inc"
DEFAULT_EMAIL="support@sol1.com.au"

#These are the OVS defaults
DEFAULT_ORGNICK=acme #Short organisation nickname 4-12 chars long to be used by OVS in naming of files
DEFAULT_PORT=1194 #Default OpenVPN Port
DEFAULT_PROTOCOL_SELECTION=1 #Default OpenVPN Protocol to use, set 1 for UDP and 2 for TCP

# first check if the encrypted ca-store exists
# and is mounted

if [ -f /var/lib/openvpn-server/ca-store ]
then
    if grep -q ca-store /proc/mounts
    then
        echo "ca-store mounted"
    else
        echo "ca-store detected but not mounted, or your session has expired."
        echo "Use ovs mount-ca-store to mount your ca-store"
        exit 1
    fi

fi


#then lets check if this script is being run on an already initialized OVS instance and warn the user if it is
if [ -f /etc/openvpn-server/openssl/openssl.cnf ] || [ -f /var/lib/openvpn-server/openssl/ca.key ] || [ -f /var/lib/openvpn-server/openssl/ca.crt ]; then
CA_EXISTS=YES
	echo ""
	echo "------------------------------------------"
	echo "WARNING!!  WARNING!!  WARNING!!  WARNING!!"
	echo "------------------------------------------"
	echo "It appears you are running this init script on an already initialized OVS system!!"
	echo "------------------------------------------"
	echo "This script will delete ***ALL*** previous OVS configuration settings!!"
	echo "The CA will be deleted and ALL issued certificates will become useless."
	echo "A brand new CA will be created and you will need to reissue ALL certificates"
	echo "------------------------------------------"
	echo ""
	read -p  "Do you wish to proceed with this script and reset your CA yes/no? " KILLEXISTINGCA
	echo ""
else
CA_EXISTS=NO
fi


if [ "$CA_EXISTS" = "YES" ]; then
	if [ "$KILLEXISTINGCA" = "yes" ] || [ "$KILLEXISTINGCA" = "y" ]; then
		echo "------------------------------------------"
		echo "Deleting previous CA and OVS settings and starting new CA initialization"
		echo "------------------------------------------"
	else
    	echo "------------------------------------------"
		echo "OVS CA Initialization aborted"
		echo "------------------------------------------"
		exit 0
	fi
fi

# now we need to decide who we want to be. ca-store only, or actual server

echo ""
read -p "Do you want to set this machine up as a CA-only? 
This implies that you will specify other machines to be the openvpn servers, 
and that this machine will just be the CA and manage the certificates. 
You will need to be able to reach these servers on ssh immediately, so make sure that is working first!

Note that this enforces an encrypted CA store as well, as the private keys for ssh are stored there. Please enter: y/n " CAONLYYN

if [ "$CAONLYYN" == "y" ]
then echo "CA Only installation selected, proceeding with this setup"
else echo "CA Only install NOT selected, proceeding with an integrated CA on same machine as openvpn"
fi

# now create an encrypted CA store from the functions we already have

if [ "$CAONLYYN" == "y" ]
then echo "CA Only installs need an encrypted ca-store" 
	read -p "CA Only needs at least 1 other machine that is actual openvpn server. Please type the IP or hostname that this machine can ssh to for this first server: " OVSSERVER1
	read -p "Please type the IP or hostname that this machine can ssh to for second server: " OVSSERVER2
	echo "more servers can be added to the file in /etc/openvpn-server/servers.conf, one per line"
	echo "each server needs the public key from this CA in its /root/.ssh/authorized_keys file"
	echo "$OVSSERVER1"> /tmp/openvpn-servers.conf
	echo "$OVSSERVER2">> /tmp/openvpn-servers.conf

		 

fi

echo ""
echo "Do you want to enable clients to have to use a username and password to connect? This is needed for RADIUS, AD, and PAM for 2fa"
read -p "Client config template to have auth-user-pass and reneg-sec 0? y/n " AUTHUSERPASSYN


echo ""
read -p "Do you want to configure Nextcloud credentials and URL to upload files to a temporary share folder? y/n " NEXTCLOUDYN

if [ "$NEXTCLOUDYN" == "y" ]
then echo "OK please supply nextcloud details - note you will need to generate a token, the password won't work."
	echo "The token can be generated in Settings -> Security -> Devices and Sessions - new app password"
	read -p "Nextcloud server URL: " NEXTCLOUDURL
	read -p "Nextcloud upload account: " NEXTCLOUDUSER
	read -p "Nextcloud upload token: " NEXTCLOUDTOKEN


fi

#Ask for the country code this server is located in
echo ""
read -p  "What is the 2-letter ISO country code where this server is located?
For example, 'AU' for Australia, 'GB' for Great Britain, 'US' for the
United States, and so on.  The value isn't particularly critical. [$DEFAULT_COUNTRY]: " KEY_COUNTRY

COUNTRY_VALID=0 #Set up for the country code validation below
COUNT=($(echo -n $KEY_COUNTRY | wc -m)) #Count the number of characters entered

if [ $COUNT -eq 0 ]; then
		#Enter must have been pressed without any entry so lets just set KEY_COUNTRY to the default country here and set COUNTRY_VALID to 1
        KEY_COUNTRY=$DEFAULT_COUNTRY
        COUNT=($(echo -n $KEY_COUNTRY | wc -m))
        COUNTRY_VALID=1
else
        #Ok so there was something entered so lets validate the country code
        if [[ $COUNT -eq 2 ]]; then
		#We have 2 characters, checking if they are letters
                if [[ $KEY_COUNTRY =~ ^[A-Za-z]+$ ]]; then
                    COUNTRY_VALID=1  #Yay they must have been 2 letters so setting country valid to 1
                fi
		else
		#There must have not been 2 characters in the variable so it is impossible to be valid and we continue to the while loop below
		COUNTRY_VALID=0
        fi

fi

#If the COUNTRY_VALID variable is was not set to 1 above then we go into this loop
while [[ $COUNTRY_VALID != 1 ]]; do
        echo ""
        echo "Country code can only be 2 letter ISO value, you entered [$KEY_COUNTRY]"
        read -p "Default country is [$DEFAULT_COUNTRY]:" KEY_COUNTRY
        COUNT=($(echo -n $KEY_COUNTRY | wc -m))

        if [ $COUNT -eq 0 ]; then
				#This lets us get out of the loop if you just press enter and it also sets KEY_COUNTRY to the default
                KEY_COUNTRY=$DEFAULT_COUNTRY
                COUNTRY_VALID=1
        else
        #Ok we had something entered above, lets check if it is 2 characters and that they are letters
        	if [[ $COUNT -eq 2 ]]; then
                #We have 2 characters, checking if they are letters
                if [[ $KEY_COUNTRY =~ ^[A-Za-z]+$ ]]; then
                        #YAY they must have been 2 letters, setting COUNTRY_VALID to 1 so we can exit this loop
                        COUNTRY_VALID=1
                fi
			fi
        fi

done

KEY_COUNTRY=${KEY_COUNTRY^^}  #Lastly make sure the country code is all upper case



#Ask for the state/province this server is located in
echo ""
echo ""
read -p  "What State/province is this server located in? [$DEFAULT_PROVINCE]: " KEY_PROVINCE

#Count the number of characters entered
COUNT=($(echo -n $KEY_PROVINCE | wc -m))

#If enter was pressed then lets just set the default province here
if [ $COUNT -eq 0 ]
then
	KEY_PROVINCE=$DEFAULT_PROVINCE
fi



#Ask for the City/Town this server is located in
echo ""
echo ""
read -p  "What City/town/locality is this server located in? [$DEFAULT_CITY]: " KEY_CITY

#Count the number of characters entered
COUNT=($(echo -n $KEY_CITY | wc -m))

#If enter was pressed then lets just set the default province here
if [ $COUNT -eq 0 ]
then
	KEY_CITY=$DEFAULT_CITY
fi



#Ask for the name of the organisation using this server
echo ""
echo ""
read -p  "What is the name of the organisation who will be using the server? [$DEFAULT_ORGANISATION]: " KEY_ORGANISATION

#Count the number of characters entered
COUNT=($(echo -n $KEY_ORGANISATION | wc -m))

#If enter was pressed then lets just set the default organisation here
if [ $COUNT -eq 0 ]
then
	KEY_ORGANISATION=$DEFAULT_ORGANISATION
fi



#Ask for an organisation nickname to be used for files generated by ovs
## TODO use a little awk program which makes some short name from $org as the default prompt value.
#TODO: Make the error messages in the Orgnick validation a bit more pretty and informative.
#eg instead of just printing what you entered, print that it is too short or too long or has invalid characters
echo ""
echo ""
read -p  "Please provide a short (4-12) character "nickname" for your organisation.
This nickname will be used as part of various filenames and package names,
so it must be fairly short and consist only of lowercase letters and digits. [$DEFAULT_ORGNICK]: " ORGNICK

#Count the number of characters entered
COUNT=($(echo -n $ORGNICK | wc -m))

if [ $COUNT -eq 0 ]; then
		#Enter must have been pressed without any entry so lets just set ORGNICK to the default and set ORGNICK_VALID to 1
        ORGNICK=$DEFAULT_ORGNICK
        ORGNICK_VALID=1
else
        #There was something entered so lets validate the ORGNICK
        if [ $COUNT -gt 3 ] && [ $COUNT -lt 13 ]; then
		#We have between 4 and 12 characters in the variable, lets validate they are valid letters
			if [[ $ORGNICK =~ ^[0-9a-z]+$ ]]; then
                ORGNICK_VALID=1  #Yay they must have been all lower case letters so we set ORGNICK_VALID to 1
            fi
		else
		#There must not have been a valid ORGNICK entered so we continue to the while loop below
		ORGNICK_VALID=0
        fi

fi

#If the ORGNICK_VALID variable is was not set to 1 above then we go into this loop to try again
while [[ $ORGNICK_VALID != 1 ]]; do
        echo ""
        echo "Organisation nickname can only consist of (4-12) lowercase letters or numbers."
        read -p "You entered [$ORGNICK]. Please try again [$DEFAULT_ORGNICK]:" ORGNICK
        COUNT=($(echo -n $ORGNICK | wc -m))

        if [ $COUNT -eq 0 ]; then
				#This lets us get out of the loop if you just press enter and it also sets ORGNICK to the default
                ORGNICK=$DEFAULT_ORGNICK
                ORGNICK_VALID=1
        else
        #There was something entered so lets validate the ORGNICK
        	if [ $COUNT -gt 3 ] && [ $COUNT -lt 13 ]; then
                #We have between 4 and 12 characters in the variable, lets validate they are valid letters
                if [[ $ORGNICK =~ ^[0-9a-z]+$ ]]; then
                        ORGNICK_VALID=1  #Yay they must have been all lower case letters so we set ORGNICK_VALID to 1
                fi
			fi
        fi

done



#Ask for an organisation email address to be used in CA initialization
echo ""
echo ""
read -p  "Organisation email address to be used for the certificate authority [$DEFAULT_EMAIL]: " ORG_EMAIL

#Count the number of characters entered
COUNT=($(echo -n $ORG_EMAIL | wc -m))

#If enter was pressed then lets just set the default organisation email here
if [ $COUNT -eq 0 ]
then
	ORG_EMAIL=$DEFAULT_EMAIL
fi



#Ask for any subnets to push to clients
## TODO subnet input validation. A shell case statement might be enough
## since it provides pattern matching.
echo ""
echo ""
read -p  "Specify the subnet you want VPN clients to be able to access.
If you provide a value here, this subnet range will be pushed to
clients as one which can be accessed via this VPN server.

You must specify the subnet in the format nnn.nnn.nnn.nnn/sss.sss.sss.sss,
where nnn.nnn.nnn.nnn is the network and sss.sss.sss.sss is the subnet mask.
For example, to tell clients to use this VPN to access the 192.168.10.0/24
network, enter 192.168.10.0/255.255.255.0

You may also specify multiple subnets to route by providing them all here,
separated by spaces. For example to tell clients to use this VPN to access
the 192.168.10.0/24 and 192.168.20.0/24 networks enter
192.168.10.0/255.255.255.0 192.168.11.0/255.255.255.0

If you wish this server to be standalone, and not provide access to any
other networks, leave this option blank.
: " SUBNETSTRING

#Turn the SUBNETSTRING variable into an array
SUBNETS=($SUBNETSTRING)



#TODO: Use this text as a base for subnet validation message when I wrote that check
#The subnet specification you provided was incorrect.
# The set of subnets you gave was incorrect.  Please go back and try again.


#TODO: Add some validation so we don't have an empty hostname variable
#Ask for the server hostname to be used by ovs for client file generation
echo ""
echo ""
read -p "What is the generally-accessible name or IP address of the server?
For clients to be able to connect to the server, it must have a consistent
DNS name or IP address.  Please enter this name or address here: " SERVERADDR



#Ask port to be used by this server
#TODO Port number validation
echo ""
echo ""
read -p  "What port number do you want this server to use?
For most uses the standard OpenVPN port of $DEFAULT_PORT
is fine, however if you need to use a non standard port you
can specify a port number here [$DEFAULT_PORT]: " SERVER_PORT

#Count the number of characters entered
COUNT=($(echo -n $SERVER_PORT | wc -m))

#If enter was pressed then lets just set the default OpenVPN Port here
if [ $COUNT -eq 0 ]
then
	SERVER_PORT=$DEFAULT_PORT
fi



#Ask for the transport protocol to be used by this server
if [[ $DEFAULT_PROTOCOL_SELECTION  =~ ^[2]+$ ]]; then
        DEFAULT_PROTOCOL=TCP
else
        DEFAULT_PROTOCOL=UDP
fi

echo ""
echo ""
read -p  "What transport protocol is this server to use?
For most uses the standard protocol of UDP
is fine, however if you need to use TCP you can select
that here by entering the protocol number
1 UDP
2 TCP
[$DEFAULT_PROTOCOL]: " PROTOCOL_SELECTION

#Count the number of characters entered
COUNT=($(echo -n $PROTOCOL_SELECTION | wc -m))

#If enter was pressed then lets just set the default OpenVPN Protocol here
if [ $COUNT -eq 0 ]
then
        PROTOCOL_SELECTION=$DEFAULT_PROTOCOL_SELECTION
        VALID_PROTOCOL=1
else
        #There was something entered so lets validate PROTOCOL_SELECTION
        if [[ $PROTOCOL_SELECTION  =~ ^[1]+$ ]] || [[ $PROTOCOL_SELECTION  =~ ^[2]+$ ]]; then
                #We have a 1 or 2 so the selection is valid
                VALID_PROTOCOL=1
                else
                #We don't have a 1 or 2 so selection is invalid
                VALID_PROTOCOL=0
        fi

fi

echo ""
echo "Passed the first loop and variable is $PROTOCOL_SELECTION"
echo ""

#Check to make sure it was 1 or 2 entered, and if not then head into this loop
while [[ $VALID_PROTOCOL != 1 ]]; do

        echo ""
                echo "You entered [$PROTOCOL_SELECTION]. Please only enter 1 or 2 "
                echo "1 UDP"
                echo "2 TCP"
        read -p "[$DEFAULT_PROTOCOL]:" PROTOCOL_SELECTION
        COUNT=($(echo -n $PROTOCOL_SELECTION | wc -m))

        if [ $COUNT -eq 0 ]; then
                                #This lets us get out of the loop if you just press enter and it also sets PROTOCOL_SELECTION to the default
                PROTOCOL_SELECTION=$DEFAULT_PROTOCOL_SELECTION
                VALID_PROTOCOL=1
        else
        #There was something entered so lets validate the selection
                if [[ $PROTOCOL_SELECTION =~ ^[1-2]+$ ]]; then
                #We have a valid selection so lets set VALID_PROTOCOL to 1 and get out of this loop
                    VALID_PROTOCOL=1
                        fi
        fi
done

#Finally lets read the PROTOCOL_SELECTION variable and set the SERVER_PROTOCOL variable

if [[ $PROTOCOL_SELECTION  =~ ^[2]+$ ]]; then
        SERVER_PROTOCOL=tcp
else
        SERVER_PROTOCOL=udp
fi



#Lets show the user all the values entered and allow a verification before proceeding
echo ""
echo ""
echo "------------------------------------------"
echo ""
echo "Please check all values are correct before proceeding"
echo ""
echo "CA Only server: $CAONLYYN"
if [ "$CAONLYYN" == "y" ]
	then echo "CA only is here, OpenVPN servers are here:"
	cat /tmp/openvpn-servers.conf
fi

if [ "$NEXTCLOUDYN" == "y" ]
	then echo "Nextcloud integration enabled"
	echo "Nextcloud URL is: $NEXTCLOUDURL"
	echo "Nextcloud User is: $NEXTCLOUDUSER"
	echo "Nextcloud Token is: $NEXTCLOUDTOKEN"
fi
echo "Country: $KEY_COUNTRY"
echo "Province: $KEY_PROVINCE"
echo "City: $KEY_CITY"
echo "Organisation: $KEY_ORGANISATION"
echo "Org nickname: $ORGNICK"
echo "Org Email: $ORG_EMAIL"
echo "Subnets:"
for s in "${SUBNETS[@]}"
do
	echo $s
done
echo "Server address: $SERVERADDR"
echo "Server port: $SERVER_PORT"
echo "Server protocol: $SERVER_PROTOCOL"


#Asking the user a final yes or no question if the values are correct before proceeding
echo ""
read -p  "Press y to proceed or any other key to abort: " CORRECTVALUES

if [ "$CORRECTVALUES" = "yes" ] || [ "$CORRECTVALUES" = "y" ]; then
	echo "------------------------------------------"
	echo "Here we go!!!"
	echo "------------------------------------------"
else
    echo "------------------------------------------"
	echo "OVS CA Initialization aborted"
	echo "------------------------------------------"
	exit 0
fi

#Lets make sure we are starting in a clean state, if they exist we remove the old
#openvpn-server directory, delete the old CA and clean up openvpn directory of any old
#server conf files, lastly Shorewall openvpn.vars, then we create new empty directories
#/etc/openvpn-server, /etc/openvpn-server/openssl and /etc/openvpn/ccd
if [ -d /etc/openvpn-server ]; then
rm -r /etc/openvpn-server
fi

if [ -d /var/lib/openvpn-server/openssl ]; then
rm -r /var/lib/openvpn-server/openssl
fi

if [ -f /var/lib/openvpn-server/ca-store ]; then
rm -r /var/lib/openvpn-server/ca-store
fi

if [ -d /etc/openvpn/ccd ]; then
rm -r /etc/openvpn/ccd
fi

#We clean up the /etc/openvpn directory this way instead of just deleting the
#whole directory just in case there are some client files we want to preserve
find /etc/openvpn -type f -name '*server*.conf' -exec rm {} + || true

#Clean up issued configuration files
find /root -type f -name '*openvpn*.ovpn' -exec rm {} + || true
find /root -type f -name '*openvpn*.conf' -exec rm {} + || true

if [ -f /etc/shorewall/openvpn.vars ]; then
	rm /etc/shorewall/openvpn.vars
fi

systemctl daemon-reload || true
service openvpn restart || true

mkdir -p /etc/openvpn-server/openssl
mkdir -p /var/lib/openvpn-server/openssl
mkdir -p /etc/openvpn/ccd


#Ok we should have a clean system, create a new certificate authority

# CA Only requires all this stuff
if [ "$CAONLYYN" == "y" ]
	then echo "CA only is here, OpenVPN servers are here:"
	cat /tmp/openvpn-servers.conf
	cp /tmp/openvpn-servers.conf /etc/openvpn-server/servers.conf

	ovs make-crypt-ca
	#should be mounted!
	echo "saving ssh key to encrypted ca-store"
	mkdir -p /var/lib/openvpn-server/openssl/ssh-keys/
	ssh-keygen -t rsa -b 4096 -f /var/lib/openvpn-server/openssl/ssh-keys/id_rsa -N ''
	echo ""
	echo "Here is the public key you need to put into the /root/.ssh/authorized_keys file on $OVSSERVER1 and $OVSSERVER2:"
	cat /var/lib/openvpn-server/openssl/ssh-keys/id_rsa.pub
	echo "Please go do this right now, as the next step will test you have done so! This is a fresh key - old ones won't work!"
	read -p "Press any key to continue."
	for ovsserver in `cat /tmp/openvpn-servers.conf`
		do if ssh -q -i "/var/lib/openvpn-server/openssl/ssh-keys/id_rsa" -oStrictHostKeyChecking=accept-new -o BatchMode=yes -o ConnectTimeout=5 "root@$ovsserver" exit; then
		     echo "SSH connection using the key is successful to $ovsserver."
		   else
		     echo "SSH connection using the key failed to $ovsserver"
			echo "You can try again, or just pretty ctrl+c to abort this whole thing"
			read -p "Press any key to continue"
			  if ssh -q -i "/var/lib/openvpn-server/openssl/ssh-keys/id_rsa" -oStrictHostKeyChecking=accept-new -o BatchMode=yes -o ConnectTimeout=5 "root@$ovsserver" exit; then
		    		echo "SSH connection using the key is successful to $ovsserver."
			  else
				echo "Failed twice! giving up!"
				exit 1
			  fi
		   fi
		done

fi

if [ "$NEXTCLOUDYN" == "y" ]
	then echo "Configuring nextcloud creds"
	echo "NEXTCLOUD_URL=$NEXTCLOUDURL" > /var/lib/openvpn-server/openssl/.nextcloudupload.conf
	echo "NEXTCLOUD_USER=$NEXTCLOUDUSER" >> /var/lib/openvpn-server/openssl/.nextcloudupload.conf
	echo "NEXTCLOUD_TOKEN=$NEXTCLOUDTOKEN" >> /var/lib/openvpn-server/openssl/.nextcloudupload.conf
fi

echo "Generating random seed data for OpenSSL to use..."
dd if=/dev/urandom of=/var/lib/openvpn-server/openssl/rand bs=256 count=1
echo "done."

#Make a temporary working directory
TMPCONF=`mktemp -d`

sed "s/%%KEY_COUNTRY%%/$KEY_COUNTRY/;
     s/%%KEY_PROVINCE%%/$KEY_PROVINCE/;
     s/%%KEY_CITY%%/$KEY_CITY/;
     s/%%KEY_ORGANISATION%%/$KEY_ORGANISATION/;"			\
   < /usr/share/openvpn-server/config-templates/openssl.cnf		\
   > /etc/openvpn-server/openssl/openssl.cnf

if [ ! -f /var/lib/openvpn-server/openssl/index.txt ]; then
	touch /var/lib/openvpn-server/openssl/index.txt
fi

if [ ! -f /var/lib/openvpn-server/openssl/serial ]; then
	echo 01 >/var/lib/openvpn-server/openssl/serial
fi

if [ ! -f /var/lib/openvpn-server/openssl/ca.key ]; then
	echo "------------------------------------------"
	echo -n "Generating Certificate Authority..."
	KEY_NAME="$KEY_ORGANISATION Certificate Authority"		\
	KEY_EMAIL="$ORG_EMAIL"							\
	openssl req -days 3650 -nodes -new -x509 			\
		-keyout /var/lib/openvpn-server/openssl/ca.key		\
		-out /var/lib/openvpn-server/openssl/ca.crt		\
		-config /etc/openvpn-server/openssl/openssl.cnf

	chmod 0600 /var/lib/openvpn-server/openssl/ca.key
	echo " done."
fi


# now onto the server config part, which gets iffy in the bash sense


# this should be in /etc/openvpn
	echo "------------------------------------------"
	echo -n "Generating an initial CRL... "
	KEY_NAME="$KEY_ORGANISATION OpenVPN server on $(hostname)"	\
	KEY_EMAIL="$ORG_EMAIL"					\
	openssl ca -gencrl -crldays 3650				\
		-out /etc/openvpn-server/$ORGNICK-ca.crl		\
		-config /etc/openvpn-server/openssl/openssl.cnf
	echo " done."


if [ "$CAONLYYN" == "y" ]
	then for server in `cat /etc/openvpn-server/servers.conf`
		do ssh -i "/var/lib/openvpn-server/openssl/ssh-keys/id_rsa" $server mkdir -p /etc/openvpn-server/openssl
		   scp -i "/var/lib/openvpn-server/openssl/ssh-keys/id_rsa" /etc/openvpn-server/$ORGNICK-ca.crl $server:/etc/openvpn-server/$ORGNICK-ca.crl
		done

else
   cp /etc/openvpn-server/$ORGNICK-ca.crl /etc/openvpn/
fi



cat <<EOF > /etc/openvpn-server/config.sh
OVPN_ORGNICK="$ORGNICK"
OVPN_ORGNAME="$KEY_ORGANISATION"
OVPN_REMOTE="$SERVERADDR"
OVPN_PORT="$SERVER_PORT"
OVPN_PROTO="$SERVER_PROTOCOL"
FIREWALLED=no
ALLOCATEIP=yes
CACHE_BUILDS="/var/lib/openvpn-server/openssl/builds/"
EOF

if [ "$AUTHUSERPASSYN" == "y" ]
then echo "AUTHUSERPASS=yes" >> /etc/openvpn-server/config.sh
fi

if [ "$CAONLYYN" == "y" ]
then echo "CAONLY=yes" >> /etc/openvpn-server/config.sh
fi

#Generate our VPN server IP subnet range
if [ -f /etc/openvpn/$ORGNICK-server.conf ]; then
     SERVERLINE="$(grep ^server /etc/openvpn/$ORGNICK-server.conf)"
else
        OCTET2=$(($RANDOM % 16 + 16))
        OCTET3=$(($RANDOM % 256 / 4 * 4))
        SERVERLINE="server 172.$OCTET2.$OCTET3.0 255.255.252.0"
fi

#Assemble the array containing the local networks to route into
#the correct push statements for the OpenVPN config file
if [ ${#SUBNETS[@]} -gt 0 ]; then
    for subnet in "${SUBNETS[@]}"; do
        NET=${subnet/\/*/}
        MASK=${subnet/*\//}
        SUBNET_ARRAY+=("push \"route $NET $MASK\"")
    done
fi

#Take our template OpenVPN server config file and change the approperiate settings to match
#the settings we input at the start of this script and output the result to a temporary file
sed "s/%%SERVER_PORT%%/$SERVER_PORT/;
     s/%%SERVER_PROTOCOL%%/$SERVER_PROTOCOL/;
         s/%%ORGNICK%%/$ORGNICK/;
     s/%%SERVERLINE%%/$SERVERLINE/;"                    \
   < /usr/share/openvpn-server/config-templates/server.conf             \
   > $TMPCONF/$ORGNICK-server.conf

#Insert the push statements for the "subnets to route" array into our temporary config file.
#This sed command will insert the array just below %%SUBNETROUTES%% place marker in the file.
#I could not find a way to do this other than the work around below otherwise SED
#would throw errors at me, we will remove the %%LEADING_SPACE%% in front of the
#push statements with the next sed command below
for sub in "${SUBNET_ARRAY[@]}"
do
sed -i "/%%SUBNETROUTES%%/a\%%LEADING_SPACE%%$sub" $TMPCONF/$ORGNICK-server.conf
done

#Remove the unwanted %%LEADING_SPACE%% that was put in front of all the push statements
sed -i 's/%%LEADING_SPACE%%//' $TMPCONF/$ORGNICK-server.conf

#Finally remove the %%SUBNETROUTES%% place marker
sed '/%%SUBNETROUTES%%/d' $TMPCONF/$ORGNICK-server.conf > /etc/openvpn/$ORGNICK-server.conf

if [ "$CAONLYYN" == "y" ]
	then for server in `cat /etc/openvpn-server/servers.conf`
		do 
			SERVERNICK=`echo $server|sed 's/\./_/g'`
			cp $TMPCONF/$ORGNICK-server.conf $TMPCONF/$SERVERNICK-server.conf
			sed -i "s|pkcs12 /etc/openvpn/$ORGNICK-server.p12|pkcs12 /etc/openvpn/$SERVERNICK-server.p12|" $TMPCONF/$SERVERNICK-server.conf
			sed '/%%SUBNETROUTES%%/d' $TMPCONF/$SERVERNICK-server.conf 
			ssh -i "/var/lib/openvpn-server/openssl/ssh-keys/id_rsa" $server mkdir -p /etc/openvpn/
		   	scp -i "/var/lib/openvpn-server/openssl/ssh-keys/id_rsa" $TMPCONF/$SERVERNICK-server.conf $server:/etc/openvpn/$ORGNICK-server.conf
		done

fi

#Cleanup our temp working directory


# make a server bundle

if [ "$CAONLYYN" == "y" ]
	then for server in `cat /etc/openvpn-server/servers.conf`
		do 
			SERVERNICK=`echo $server|sed 's/\./_/g'`
			make_server_bundle "$ORG_EMAIL" $SERVERNICK $TMPCONF/
		   	scp -i "/var/lib/openvpn-server/openssl/ssh-keys/id_rsa" /var/lib/openvpn-server/openssl/$ORGNICK-$SERVERNICK-server.p12 $server:/etc/openvpn/$SERVERNICK-server.p12
		done

else
	
	# Output to the throwaway temp dir (like the CA-only branch) rather than
	# straight into /etc/openvpn, so make_server_bundle's key/csr/crt copies
	# don't litter /etc/openvpn with $OVPN_ORGNICK-<cn>-server.* names. Then
	# install only the pkcs12 (it bundles key+cert+CA) under the name the
	# generated server.conf references: /etc/openvpn/$ORGNICK-server.p12.
	# make_server_bundle wrote it to /var/lib as $OVPN_ORGNICK-<cn>-server.p12
	# with cn=$ORGNICK-server.
	make_server_bundle "$ORG_EMAIL" $ORGNICK-server "$TMPCONF/"
	cp "/var/lib/openvpn-server/openssl/$ORGNICK-$ORGNICK-server-server.p12" "/etc/openvpn/$ORGNICK-server.p12"
	chmod 0600 "/etc/openvpn/$ORGNICK-server.p12"
fi


rm -rf $TMPCONF

# Initalise ovs bash completion for this session
if [ -f /etc/bash_completion.d/ovs ] ; then
	. /etc/bash_completion.d/ovs
fi

systemctl daemon-reload || true
service openvpn restart

if [ "$CAONLYYN" == "y" ]
	then for server in `cat /etc/openvpn-server/servers.conf`
		do ssh -i "/var/lib/openvpn-server/openssl/ssh-keys/id_rsa" $server apt install openvpn -y
		   ssh -i "/var/lib/openvpn-server/openssl/ssh-keys/id_rsa" $server systemctl daemon-reload || true
		   ssh -i "/var/lib/openvpn-server/openssl/ssh-keys/id_rsa" $server mkdir -p /var/lib/openvpn-server/openvpn
		   ssh -i "/var/lib/openvpn-server/openssl/ssh-keys/id_rsa" $server mkdir -p /etc/openvpn/ccd
		   ssh -i "/var/lib/openvpn-server/openssl/ssh-keys/id_rsa" $server systemctl restart openvpn
		done

fi

echo ""
echo "------------------------------------------"
echo "It looks like we made it all the way to the end.
Your OpenVPN server should now be ready to use."

# clean up mounted CA
ovs umount-ca-store
