#!/usr/bin/env sh # Includes for System Setup # # SPDX-FileCopyrightText: Daniel Pätzold # SPDX-License-Identifier: AGPL-3.0-or-later # # This is not a runnig script-file. No real logic to execute. Its used for includes in other scripts. # # Parameters (pass as arguments to the `source` call, e.g. source setup_system.inc.sh --missingconfok): # --missingconfok Print a warning instead of prompting and aborting when config/setup_system.conf is missing. # Parse flags passed to this inc (e.g. source setup_system.inc.sh --missingconfok). # In bash, arguments to `source` temporarily replace $@ for the duration of the sourced file. _INC_MISSINGCONFOK=0 for _inc_arg in "$@"; do [[ "$_inc_arg" == "--missingconfok" ]] && _INC_MISSINGCONFOK=1 done unset _inc_arg #Get the machine_uuid wich is needed by some userspace programs. #As all Parameters that are bound to CPU or Mainboard, are only readable by root, we need to get the values at installtime. #On old installations without the file, we will write it whenever possible if [ -f $( dirname "${BASH_SOURCE[0]:-$0}" )/../config.d/machine_uuid.sys ]; then export MACHINEID="$( cat $( dirname "${BASH_SOURCE[0]:-$0}" )/../config.d/machine_uuid.sys )" elif [ "$EUID" -eq 0 ]; then dmidecode -t system | grep -i 'UUID' \ | sed 's/UUID: //' | tr '[:upper:]' '[:lower:]' \ | sed 's/[^0-9a-z]*//g' | xargs | tail -c 13 \ > "$( dirname "${BASH_SOURCE[0]:-$0}" )/../config.d/machine_uuid.sys" export MACHINEID="$( cat $( dirname "${BASH_SOURCE[0]:-$0}" )/../config.d/machine_uuid.sys )" fi #Check for configure.conf - used for first setup of system if [[ -f $(dirname "${BASH_SOURCE[0]:-$0}")/../config.d/configure.conf ]]; then echo "System in configure-mode. Will use $(dirname "${BASH_SOURCE[0]:-$0}")/../config.d/configure.conf for setup." source $(dirname "${BASH_SOURCE[0]:-$0}")/../config.d/configure.conf else #Load default system setup file if [[ ! -f $(dirname "${BASH_SOURCE[0]:-$0}")/../config/setup_system.conf ]]; then echo "System configuration not found." echo "Please copy system_setup/config.dist/setup_system.conf.dist to config/setup_system.conf and adjust the settings before running." if [[ $_INC_MISSINGCONFOK -eq 1 ]]; then echo "WARNING: Continuing without system configuration (--missingconfok)." else echo "Press any key to continue" && read -n 1 -s -r && exit 1 fi else echo "Found and use configfile $(dirname "${BASH_SOURCE[0]:-$0}")/../config/setup_system.conf" source $(dirname "${BASH_SOURCE[0]:-$0}")/../config/setup_system.conf fi #Parse additional client-configs if [[ `ls -1 $(dirname "${BASH_SOURCE[0]:-$0}")/../config.d/*.conf 2>/dev/null | wc -l ` -gt 0 ]]; then echo "Additional config file found $(dirname "${BASH_SOURCE[0]:-$0}")/../config.d/*.conf - using it" source $(dirname "${BASH_SOURCE[0]:-$0}")/../config.d/*.conf fi fi #Check if the Data- Directory is encrypted check_data_isecrypted() { CHECKRES=$( cat /etc/mtab | grep "${DECRYPTEDDATADIR}" | grep "fuse.gocryptfs" ) if [ "${CHECKRES}." == "." ]; then return 1 # Error: Directory is not mounted else return 0 # Directory is mounted fi } # Functions for logging elog_init() { #Create a new logfile and put some text in it echo $@ | tee ${LOGFILE} } elog_add() { #Append some text to the logile echo $@ | tee ${LOGFILE} -a } elog_add_command() { #Run a command, capture output (STD and ERR) to the logfile AND output to screen # WILL NOT SET RETTXT to make Output directly to screen #Returns the exit value of the command in $? and in RETNO $@ 2>&1 | tee -a ${LOGFILE} RETNO=$? return ${RETNO} } elog_add_command_subshell() { # Special Version of above, where the command will be completely executed in a subshell and then passed to Variable RETTXT. This is needed for some commands, that may output to # something else than STD or ERR and otherwise cannot be captured completely. # Benefit: Really catch everything that is send to output # Disadvantage: Output wont't display directly, but only after finshed execution RETTXT=$( { $@ > >(tee -a ${LOGFILE}); } 2> >(tee -a ${LOGFILE}) ) RETNO=$? echo "${RETTXT}" return ${RETNO} } # Will set variable DAVTOKEN_USER and DAVTOKEN_PASS to the stored value or get a new one get_nc_token() { export DAVTOKEN_USER="" export DAVTOKEN_PASS="" if [ "$EUID" -eq 0 ]; then echo "get_nc_token(): Called as superuser, which is denied." return 1 # Token for Superuser makes no sense and cannot work fi # If Filename is given andf encryption is turned on, than first check for encrypted Directory if [ ${IPAVAULTUSE} == "true" ] && [ ! -z ${DAVTOKENFILENAME} ]; then check_data_isecrypted if [ $? -ne 0 ]; then echo "Data Directory is not encrypted. Please mount it first." return 1 fi fi if [ ! -f ${DAVTOKENFILENAME} ] || [ -z ${DAVTOKENFILENAME} ]; then echo "No token found here. Getting a new WEBDAV Token for this Device." echo "Please logon to your Nextcloud instance via SSO/kerberos" # Directory is ok, but no Tokenfile was found, need to generate a new one REQJSON=$( curl -s -A "WEBDAV:${HOSTNM}" -X POST "https://${SERVERFQDN_NC}/index.php/login/v2" ) # echo "JSON is:" # echo "${REQJSON}" REQTOKEN=$( echo "${REQJSON}" | grep -oP '(?<="token":")[^"]+(?=")' ) REQURL=$( echo "${REQJSON}" | grep -oP '(?<="login":")[^"]+(?=")' ) /usr/bin/firefox "${REQURL}" & for i in {1..200} do echo "Waiting 6 seconds" sleep 6 echo -n "Poll Number ${i}..." POLLJSON=$( curl -s -X POST "https://${SERVERFQDN_NC}/login/v2/poll" -d "token=${REQTOKEN}" ) if [[ "${POLLJSON}" == *"appPassword"* ]]; then if [ ! -z ${DAVTOKENFILENAME} ]; then echo "${POLLJSON}" > ${DAVTOKENFILENAME} echo "Token has been written to ${DAVTOKENFILENAME}" else echo "Temporary token was obtained." fi pkill firefox break else echo "failed" fi done else # Tokenfile found, reading it POLLJSON=$( cat ${DAVTOKENFILENAME} ) fi export DAVTOKEN_USER=$( echo "${POLLJSON}" | grep -oP '(?<="loginName":")[^"]+(?=")' ) export DAVTOKEN_PASS=$( echo "${POLLJSON}" | grep -oP '(?<="appPassword":")[^"]+(?=")' ) } # Custom `select` implementation that allows *empty* input. # Pass the choices as individual arguments. # Output is the chosen item, or "", if the user just pressed ENTER. # Example: # choice=$(selectWithDefault 'one' 'two' 'three') selectWithDefault() { local item i=0 numItems=$# # Print numbered menu items, based on the arguments passed. for item; do # Short for: for item in "$@"; do printf '%s\n' "$((++i))) $item" done >&2 # Print to stderr, as `select` does. # Prompt the user for the index of the desired item. while :; do printf %s "${PS3-#? }" >&2 # Print the prompt string to stderr, as `select` does. read -r index # Make sure that the input is either empty or that a valid index was entered. [[ -z $index ]] && break # empty input (( index >= 1 && index <= numItems )) 2>/dev/null || { echo "Invalid selection. Please try again." >&2; continue; } break done # Output the selected item, if any. [[ -n $index ]] && printf %s "${@: index:1}" } selectExample() { # Print the prompt message and call the custom select function. echo "Include audits (default is 'Nope')?" optionsAudits=('Yep' 'Nope') opt=$(selectWithDefault "${optionsAudits[@]}") # Process the selected item. case $opt in 'Yep') includeAudits=true; ;; ''|'Nope') includeAudits=false; ;; # $opt is '' if the user just pressed ENTER esac } # This is not a runnig script-file. No Logik to execute. Its used for includes in other scripts.