Skip to content
Snippets Groups Projects
freedombone-controlpanel 66.3 KiB
Newer Older
Bob Mottram's avatar
Bob Mottram committed
#!/bin/bash
Bob Mottram's avatar
Bob Mottram committed
#  _____               _           _
# |   __|___ ___ ___ _| |___ _____| |_ ___ ___ ___
# |   __|  _| -_| -_| . | . |     | . | . |   | -_|
# |__|  |_| |___|___|___|___|_|_|_|___|___|_|_|___|
Bob Mottram's avatar
Bob Mottram committed
#
Bob Mottram's avatar
Bob Mottram committed
#                              Freedom in the Cloud
Bob Mottram's avatar
Bob Mottram committed
#
# Administrator control panel for the Freedombone system
#
# License
# =======
#
Bob Mottram's avatar
Bob Mottram committed
# Copyright (C) 2015-2019 Bob Mottram <bob@freedombone.net>
Bob Mottram's avatar
Bob Mottram committed
#
# This program is free software: you can redistribute it and/or modify
Bob Mottram's avatar
Bob Mottram committed
# it under the terms of the GNU Affero General Public License as published by
Bob Mottram's avatar
Bob Mottram committed
# the Free Software Foundation, either version 3 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
Bob Mottram's avatar
Bob Mottram committed
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
Bob Mottram's avatar
Bob Mottram committed
#
Bob Mottram's avatar
Bob Mottram committed
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
Bob Mottram's avatar
Bob Mottram committed

Bob Mottram's avatar
Bob Mottram committed
PROJECT_NAME='freedombone'

Bob Mottram's avatar
Bob Mottram committed
export TEXTDOMAIN=${PROJECT_NAME}-controlpanel
Bob Mottram's avatar
Bob Mottram committed
export TEXTDOMAINDIR="/usr/share/locale"

if [[ $USER != 'root' ]]; then
    # show the user version of the control panel
    #${PROJECT_NAME}-controlpanel-user
    controluser
    exit 0
fi

Bob Mottram's avatar
Bob Mottram committed
function please_wait {
        local str width height length

        width=$(tput cols)
        height=$(tput lines)
        str=$"Please wait"
Bob Mottram's avatar
Bob Mottram committed
        length=${#str}
        clear
        tput cup $((height / 2)) $(((width / 2) - (length / 2)))
        echo "$str"
Bob Mottram's avatar
Bob Mottram committed
        tput cup $((height * 3 / 5)) $(((width / 2)))
        echo -n ''
Bob Mottram's avatar
Bob Mottram committed
}

Bob Mottram's avatar
Bob Mottram committed
please_wait
Bob Mottram's avatar
Bob Mottram committed

# Start including files

Bob Mottram's avatar
Bob Mottram committed
source /usr/local/bin/${PROJECT_NAME}-vars
Bob Mottram's avatar
Bob Mottram committed
UTILS_FILES="/usr/share/${PROJECT_NAME}/utils/${PROJECT_NAME}-utils-*"
for f in $UTILS_FILES
do
Bob Mottram's avatar
Bob Mottram committed
    source "$f"
Bob Mottram's avatar
Bob Mottram committed
done
Bob Mottram's avatar
Bob Mottram committed

source "/usr/share/${PROJECT_NAME}/base/${PROJECT_NAME}-base-email"

Bob Mottram's avatar
Bob Mottram committed
APP_FILES="/usr/share/${PROJECT_NAME}/apps/${PROJECT_NAME}-app-*"
Bob Mottram's avatar
Bob Mottram committed
for f in $APP_FILES
do
Bob Mottram's avatar
Bob Mottram committed
    source "$f"
Bob Mottram's avatar
Bob Mottram committed
done

# End including files

Bob Mottram's avatar
Bob Mottram committed
COMPLETION_FILE="$HOME/${PROJECT_NAME}-completed.txt"
Bob Mottram's avatar
Bob Mottram committed
SELECTED_USERNAME=
ADMIN_USER=
UPGRADE_SCRIPT_NAME="${PROJECT_NAME}-upgrade"
UPDATE_DATE_SCRIPT=/usr/bin/updatedate
Bob Mottram's avatar
Bob Mottram committed

Bob Mottram's avatar
Bob Mottram committed
# Minimum number of characters in a password
Bob Mottram's avatar
Bob Mottram committed
MINIMUM_PASSWORD_LENGTH=$(grep 'MINIMUM_PASSWORD_LENGTH=' "/usr/share/${PROJECT_NAME}/utils/${PROJECT_NAME}-utils-passwords" | head -n 1 | awk -F '=' '{print $2}')
# Mumble
MUMBLE_PORT=64738
MUMBLE_ONION_PORT=8095
WIFI_INTERFACE=wlan0
WIFI_SSID=
WIFI_TYPE='wpa2-psk'
WIFI_PASSPHRASE=
Bob Mottram's avatar
Bob Mottram committed
WIFI_HOTSPOT='no'
Bob Mottram's avatar
Bob Mottram committed
WIFI_NETWORKS_FILE="$HOME/${PROJECT_NAME}-wifi.cfg"
USB_DRIVE=sdb
# get default USB from config file
Bob Mottram's avatar
Bob Mottram committed
CONFIGURATION_FILE="$HOME/${PROJECT_NAME}.cfg"
Bob Mottram's avatar
Bob Mottram committed
read_config_param WIFI_HOTSPOT
read_config_param WIFI_INTERFACE
read_config_param WIFI_TYPE
read_config_param WIFI_SSID
read_config_param WIFI_PASSPHRASE
read_config_param SSH_PORT
read_config_param USB_DRIVE
read_config_param MY_USERNAME
read_config_param ONION_ONLY
Bob Mottram's avatar
Bob Mottram committed
if [[ $USB_DRIVE == *"dev"* ]]; then
    USB_DRIVE=$(echo ${USB_DRIVE} | awk -F '/' '{print $3}' | sed 's|1||g' | sed 's|2||g')
Bob Mottram's avatar
Bob Mottram committed
function any_key {
    # shellcheck disable=SC2034
    read -n1 -rsp $"Press any key to continue..." key
}

function reset_password_tries {
    passwords_select_user
Bob Mottram's avatar
Bob Mottram committed
    if [ ! "$SELECTED_USERNAME" ]; then
Bob Mottram's avatar
Bob Mottram committed
    pam_tally --user "$SELECTED_USERNAME" --reset
    dialog --title $"Reset password tries" \
           --msgbox $"Password tries have been reset for $SELECTED_USERNAME" 6 60
}

function check_for_updates {
Bob Mottram's avatar
Bob Mottram committed
    if [ ! -f "/etc/cron.weekly/$UPGRADE_SCRIPT_NAME" ]; then
        dialog --title $"Check for updates" \
               --msgbox $"Upgrade script was not found" 6 40
        return
    fi

    clear
Bob Mottram's avatar
Bob Mottram committed
    /etc/cron.weekly/$UPGRADE_SCRIPT_NAME
Bob Mottram's avatar
Bob Mottram committed
function add_user {
Bob Mottram's avatar
Bob Mottram committed
    data=$(mktemp 2>/dev/null)
    dialog --backtitle $"Freedombone Control Panel" \
           --title $"Add new user" \
Bob Mottram's avatar
Bob Mottram committed
           --form "\\n" 8 60 3 \
           $"Username:" 1 1 "" 1 28 16 15 \
           $"ssh public key (optional):" 2 1 "" 2 28 40 10000 \
Bob Mottram's avatar
Bob Mottram committed
           2> "$data"
Bob Mottram's avatar
Bob Mottram committed
        1) rm -f "$data"
           return;;
Bob Mottram's avatar
Bob Mottram committed
        255) rm -f "$data"
             return;;
Bob Mottram's avatar
Bob Mottram committed
    new_user_username=$(sed -n 1p < "$data")
    new_user_ssh_public_key=$(sed -n 2p < "$data")
    rm -f "$data"
    if [ ${#new_user_username} -lt 2 ]; then
        dialog --title $"New username" \
               --msgbox $"No username was given" 6 40
        return
    fi
    if [[ "$new_user_username" == *" "* ]]; then
        dialog --title $"Invalid username" \
               --msgbox $"The username should not contain any spaces" 6 40
        return
    fi
    if [ ${#new_user_ssh_public_key} -lt 20 ]; then
        clear
Bob Mottram's avatar
Bob Mottram committed
        "${PROJECT_NAME}-adduser" "$new_user_username"
Bob Mottram's avatar
Bob Mottram committed
        if [[ "$new_user_ssh_public_key" == 'ssh-'* ]]; then
Bob Mottram's avatar
Bob Mottram committed
            "${PROJECT_NAME}-adduser" "$new_user_username" "$new_user_ssh_public_key"
            any_key
        else
            dialog --title $"ssh public key" \
                   --msgbox $"This does not look like an ssh public key" 6 40
        fi
    fi
Bob Mottram's avatar
Bob Mottram committed
}

Bob Mottram's avatar
Bob Mottram committed
function pad_string {
    echo -n -e "$1" | sed -e :a -e 's/^.\{1,25\}$/& /;ta'
Bob Mottram's avatar
Bob Mottram committed
}

Bob Mottram's avatar
Bob Mottram committed
function show_tor_bridges {
    if ! grep -q "#BridgeRelay" /etc/tor/torrc; then
        if grep -q "BridgeRelay 1" /etc/tor/torrc; then
            read_config_param 'TOR_BRIDGE_PORT'
            read_config_param 'TOR_BRIDGE_NICKNAME'
            if [ ${#TOR_BRIDGE_NICKNAME} -gt 0 ]; then
                W+=($"Your Tor Bridge" "$(get_ipv4_address):${TOR_BRIDGE_PORT} ${TOR_BRIDGE_NICKNAME}")
            fi
        fi
    fi
    bridges_list=$(grep "Bridge " /etc/tor/torrc | grep -v '##')
    if [ ${#bridges_list} -gt 0 ]; then
        for i in "${bridges_list[@]}"
        do
            bridgestr=$(i//Bridge /)
            W+=($"Tor Bridge" "$bridgestr")
        done
    fi
}

Bob Mottram's avatar
Bob Mottram committed
function show_domains {
Bob Mottram's avatar
Bob Mottram committed
    read_config_param "DEFAULT_DOMAIN_NAME"
Bob Mottram's avatar
Bob Mottram committed
    while true
    do
        W=()
Bob Mottram's avatar
Bob Mottram committed

Bob Mottram's avatar
Bob Mottram committed
        W+=("IPv4" "$(get_ipv4_address) / $(get_external_ipv4_address)")
        ipv6_address="$(get_ipv6_address)"
        if [ ${#ipv6_address} -gt 0 ]; then
            W+=("IPv6" "${ipv6_address}")
        fi
Bob Mottram's avatar
Bob Mottram committed

Bob Mottram's avatar
Bob Mottram committed
        if [ -f /etc/ssh/ssh_host_rsa_key.pub ]; then
            W+=("ssh rsa sha256" "$(awk '{print $2}' /etc/ssh/ssh_host_rsa_key.pub | base64 -d | sha256sum -b | awk '{print $1}' | xxd -r -p | base64 | sed 's|=||g')")
        fi
        if [ -f /etc/ssh/ssh_host_ed25519_key.pub ]; then
            W+=("ssh ed25519 sha256" "$(awk '{print $2}' /etc/ssh/ssh_host_ed25519_key.pub | base64 -d | sha256sum -b | awk '{print $1}' | xxd -r -p | base64 | sed 's|=||g')")
        fi
Bob Mottram's avatar
Bob Mottram committed

Bob Mottram's avatar
Bob Mottram committed
        if grep -q "ssh onion domain" "$COMPLETION_FILE"; then
            domain_onion=$(grep 'ssh onion domain' "${COMPLETION_FILE}" | awk -F ':' '{print $2}')
            W+=("ssh" "${DEFAULT_DOMAIN_NAME} / ${domain_onion}")
        fi
        if grep -q "email onion domain" "$COMPLETION_FILE"; then
            domain_onion=$(grep 'email onion domain' "${COMPLETION_FILE}" | awk -F ':' '{print $2}')
            W+=("Email" "${DEFAULT_DOMAIN_NAME} / ${domain_onion}")
        fi
        if grep -q "sks onion domain" "$COMPLETION_FILE"; then
            read_config_param "KEYSERVER_DOMAIN_NAME"
            domain_onion=$(grep 'sks onion domain' "${COMPLETION_FILE}" | awk -F ':' '{print $2}')
Bob Mottram's avatar
Bob Mottram committed
            W+=("SKS" "${KEYSERVER_DOMAIN_NAME} / ${domain_onion}")
Bob Mottram's avatar
Bob Mottram committed
        fi
Bob Mottram's avatar
Bob Mottram committed

Bob Mottram's avatar
Bob Mottram committed
        INTRODUCER_FILENAME=/home/tahoelafs/data/private/introducer.furl
        if [ -f $INTRODUCER_FILENAME ]; then
            W+=("Tahoe-LAFS" "$(cat $INTRODUCER_FILENAME)")
        fi
Bob Mottram's avatar
Bob Mottram committed

Bob Mottram's avatar
Bob Mottram committed
        if [ -f /var/lib/turn/turnserver.conf ]; then
            W+=("TURN secret" "$(grep 'static-auth-secret' /var/lib/turn/turnserver.conf | awk -F '=' '{print $2}')")
        fi

Bob Mottram's avatar
Bob Mottram committed
        show_tor_bridges
Bob Mottram's avatar
Bob Mottram committed

Bob Mottram's avatar
Bob Mottram committed
        # shellcheck disable=SC2068
        for app_name in ${APPS_INSTALLED_NAMES[@]}
        do
            if ! grep -q "SHOW_ON_ABOUT=1" "/usr/share/${PROJECT_NAME}/apps/${PROJECT_NAME}-app-${app_name}"; then
                continue
            fi
Bob Mottram's avatar
Bob Mottram committed

Bob Mottram's avatar
Bob Mottram committed
            # handle the foibles of capitalisation
            if ! grep -q "${app_name} domain" "$COMPLETION_FILE"; then
                app_name_upper=$(echo "${app_name}" | awk '{print toupper($0)}')
                if grep -q "${app_name_upper} domain" "$COMPLETION_FILE"; then
                    app_name=${app_name_upper}
                else
                    app_name_first_upper="$(tr '[:lower:]' '[:upper:]' <<< "${app_name:0:1}")${app_name:1}"
                    if grep -q "${app_name_first_upper} domain" "$COMPLETION_FILE"; then
                        app_name=${app_name_first_upper}
                    fi
Bob Mottram's avatar
Bob Mottram committed
            if [ ${#app_name} -gt 0 ]; then
                icann_address=$(get_app_icann_address "$app_name")
                if grep -q "SHOW_CLEARNET_ADDRESS_ON_ABOUT=0" "/usr/share/${PROJECT_NAME}/apps/${PROJECT_NAME}-app-${app_name}"; then
Bob Mottram's avatar
Bob Mottram committed
                    icann_address='-'
                fi
Bob Mottram's avatar
Bob Mottram committed
                if [[ "$ONION_ONLY" != 'no' ]]; then
                    if [[ "${icann_address}" != "${LOCAL_NAME}.local" ]]; then
                        icann_address='-'
                    fi
                fi
                onion_address=$(get_app_onion_address "$app_name")
                if [ ${#onion_address} -eq 0 ]; then
                    onion_address="-"
Bob Mottram's avatar
Bob Mottram committed
                fi
Bob Mottram's avatar
Bob Mottram committed

Bob Mottram's avatar
Bob Mottram committed
                if [[ "${icann_address}" != '-' ]]; then
Bob Mottram's avatar
Bob Mottram committed
                    if [[ "${onion_address}" != '-' ]]; then
                        W+=("${app_name}" "${icann_address} / ${onion_address}")
                    else
                        W+=("${app_name}" "${icann_address}")
                    fi
Bob Mottram's avatar
Bob Mottram committed
                else
Bob Mottram's avatar
Bob Mottram committed
                    W+=("${app_name}" "${onion_address}")
                fi

                if grep -q "mobile${app_name} onion domain" "$COMPLETION_FILE"; then
                    onion_address=$(get_app_onion_address "${app_name}" "mobile")
                    if [[ "${icann_address}" != '-' ]]; then
                        W+=("${app_name} (mobile)" "${icann_address} / ${onion_address}")
                    else
                        W+=("${app_name} (mobile)" "${onion_address}")
                    fi
Bob Mottram's avatar
Bob Mottram committed
                fi
Bob Mottram's avatar
Bob Mottram committed
            fi
Bob Mottram's avatar
Bob Mottram committed
        done
Bob Mottram's avatar
Bob Mottram committed

Bob Mottram's avatar
Bob Mottram committed
        if grep -q "rss reader domain" "$COMPLETION_FILE"; then
            if [ -d /var/lib/tor/hidden_service_ttrss ]; then
                domain_onion=$(cat /var/lib/tor/hidden_service_ttrss/hostname)
                W+=("RSS Reader" "${domain_onion}")
            fi
            if [ -d /var/lib/tor/hidden_service_mobilerss ]; then
                domain_onion=$(cat /var/lib/tor/hidden_service_mobilerss/hostname)
                W+=("RSS mobile" "${domain_onion}")
            fi
Bob Mottram's avatar
Bob Mottram committed
        width=$(tput cols)
        height=$(tput lines)
Bob Mottram's avatar
Bob Mottram committed
        # shellcheck disable=SC2068
        selected=$(dialog --backtitle $"Freedombone Control Panel" --title $"Domains" --menu $"Use Shift+cursors to select and copy onion addresses" $((height-4)) $((width-4)) $((height-4)) "${W[@]}" 3>&2 2>&1 1>&3)
        if [ ! "$selected" ]; then
Bob Mottram's avatar
Bob Mottram committed
        # obtain the addresses from the key by itterating through
        # the array. This is quite crude and maybe there's a better way
        key_found=
        selected_addresses=
        for key in "${W[@]}";
        do
            if [ $key_found ]; then
                selected_addresses="$key"
                break
            fi
            if [[ "$key" == "$selected" ]]; then
                key_found=1
            fi
        done
        # Was the key matched?
        if [ ! "$selected_addresses" ]; then
            break
        fi
        # addresses were found - is this an onion?
        if [[ "$selected_addresses" != *".onion"* ]]; then
            continue
        fi
        # There are two forms of addresses: "x / y.onion" and "x.onion"
        if [[ "$selected_addresses" == *'/'* ]]; then
            onion_addr=$(echo "$selected_addresses" | awk -F '/' '{print $2}' | awk -F ' ' '{print $1}')
        else
            onion_addr="$selected_addresses"
Bob Mottram's avatar
Bob Mottram committed
        # show the onion address as a QR code
        clear
Bob Mottram's avatar
Bob Mottram committed
        echo "${selected}: ${onion_addr}"
Bob Mottram's avatar
Bob Mottram committed
        echo -n "$onion_addr" | qrencode -t UTF8
        any_key
Bob Mottram's avatar
Bob Mottram committed
function show_users {
    echo 'Users'
    echo '====='
    echo ''
    echo -n -e "$(pad_string 'Name')"
    echo -n -e "$(pad_string 'Data')"
    echo ''
    echo '----------------------------------'
    for d in /home/*/ ; do
        USRNAME=$(echo "$d" | awk -F '/' '{print $3}')
Bob Mottram's avatar
Bob Mottram committed
        if [[ $(is_valid_user "$USRNAME") == "1" ]]; then
Bob Mottram's avatar
Bob Mottram committed
            echo -n -e "$(pad_string "${USRNAME}")"

            # size of the home directory
Bob Mottram's avatar
Bob Mottram committed
            du -s -h "/home/${USRNAME}" | awk -F ' ' '{print $1}'
Bob Mottram's avatar
Bob Mottram committed
}

function show_tahoelafs {
    if [ ! -f /home/tahoelafs/storage/private/storage.furl ]; then
    echo 'Tahoe-LAFS Storage Node'
    echo '======================='
    echo "Hostname:   $(get_tahoelafs_storage_hostname)"
    echo "Public key: $(get_tahoelafs_public_key)"
    echo "Nickname:   $(get_tahoelafs_nick)"
    echo "FURL:       $(get_tahoelafs_furl)"
Bob Mottram's avatar
Bob Mottram committed
function show_about {
    detect_apps
    get_apps_installed_names
Bob Mottram's avatar
Bob Mottram committed
function select_user {
Bob Mottram's avatar
Bob Mottram committed
    # shellcheck disable=SC2207
    users_array=($(ls /home))

Bob Mottram's avatar
Bob Mottram committed
    delete=(git)
Bob Mottram's avatar
Bob Mottram committed
    # shellcheck disable=SC2068
    for del in ${delete[@]}
    do
Bob Mottram's avatar
Bob Mottram committed
        # shellcheck disable=SC2206
        users_array=(${users_array[@]/$del})
    done

    i=0
    W=()
    name=()
Bob Mottram's avatar
Bob Mottram committed
    # shellcheck disable=SC2068
    for u in ${users_array[@]}
    do
Bob Mottram's avatar
Bob Mottram committed
        if [[ $(is_valid_user "$u") == "1" ]]; then
            i=$((i+1))
Bob Mottram's avatar
Bob Mottram committed
            W+=("$i" "$u")
Bob Mottram's avatar
Bob Mottram committed
            name+=("$u")
        fi
    if [ $i -eq 1 ]; then
        SELECTED_USERNAME="${name[0]}"
    else
Bob Mottram's avatar
Bob Mottram committed
        # shellcheck disable=SC2068
        user_index=$(dialog --backtitle $"Freedombone Control Panel" --title $"Select User" --menu $"Select one of the following:" 24 40 17 ${W[@]} 3>&2 2>&1 1>&3)
Bob Mottram's avatar
Bob Mottram committed
        # shellcheck disable=SC2181
        if [ $? -eq 0 ]; then
            SELECTED_USERNAME="${name[$((user_index-1))]}"
        fi
Bob Mottram's avatar
Bob Mottram committed
}

function delete_user {
Bob Mottram's avatar
Bob Mottram committed
    if [ ! "$SELECTED_USERNAME" ]; then
Bob Mottram's avatar
Bob Mottram committed
    if grep -Fxq "Admin user:$SELECTED_USERNAME" "$COMPLETION_FILE"; then
        dialog --title $"Administrator user" \
               --msgbox $"You can't delete the administrator user" 6 40
        return
    fi
    clear
Bob Mottram's avatar
Bob Mottram committed
    "${PROJECT_NAME}-rmuser" "$SELECTED_USERNAME"
Bob Mottram's avatar
Bob Mottram committed
}

function change_password {
Bob Mottram's avatar
Bob Mottram committed
    if [ ! "$SELECTED_USERNAME" ]; then
        return
    fi

    dialog --title $"Change password" \
Bob Mottram's avatar
Bob Mottram committed
           --passwordbox $"New password for user $SELECTED_USERNAME" 8 40 2> "$data"
    newpassword=$(<"$data")
    rm -f "$data"
    if [ "${#newpassword}" -lt "${MINIMUM_PASSWORD_LENGTH}" ]; then
        dialog --title $"Change password" \
               --msgbox $"The password should be ${MINIMUM_PASSWORD_LENGTH} or more characters" 6 40
        return
    fi

Bob Mottram's avatar
Bob Mottram committed
    echo -n "$SELECTED_USERNAME:$newpassword" | /usr/sbin/chpasswd

    dialog --title $"Change password" \
           --msgbox $"Password for $SELECTED_USERNAME was changed" 6 40
Bob Mottram's avatar
Bob Mottram committed
}

Bob Mottram's avatar
Bob Mottram committed
function change_ssh_public_key {
Bob Mottram's avatar
Bob Mottram committed
    if [ ! "$SELECTED_USERNAME" ]; then
Bob Mottram's avatar
Bob Mottram committed
    if grep -Fxq "Admin user:$SELECTED_USERNAME" "$COMPLETION_FILE"; then
        dialog --title $"Change ssh public key" \
               --backtitle $"Freedombone Control Panel" \
               --defaultno \
Bob Mottram's avatar
Bob Mottram committed
               --yesno $"\\nThis is the administrator user.\\n\\nAre you sure you want to change the ssh public key for the administrator?" 10 60
        sel=$?
        case $sel in
            1) return;;
            255) return;;
        esac
    fi

Bob Mottram's avatar
Bob Mottram committed
    data=$(mktemp 2>/dev/null)
    dialog --title $"Change ssh public key for $SELECTED_USERNAME" \
           --backtitle $"Freedombone Control Panel" \
Bob Mottram's avatar
Bob Mottram committed
           --inputbox $"Paste the ssh public key below" 8 60 2>"$data"
Bob Mottram's avatar
Bob Mottram committed
            SSH_PUBLIC_KEY=$(<"$data")
            if [ "$SSH_PUBLIC_KEY" ]; then
                if [ ${#SSH_PUBLIC_KEY} -gt 5 ]; then
                    if [ -f "$SSH_PUBLIC_KEY" ]; then
Bob Mottram's avatar
Bob Mottram committed
                        if [ ! -d "/home/$SELECTED_USERNAME/.ssh" ]; then
                            mkdir "/home/$SELECTED_USERNAME/.ssh"
Bob Mottram's avatar
Bob Mottram committed
                        cp "$SSH_PUBLIC_KEY" \
                           "/home/$SELECTED_USERNAME/.ssh/authorized_keys"
                        chown -R "$SELECTED_USERNAME":"$SELECTED_USERNAME" \
                              "/home/$SELECTED_USERNAME/.ssh"
                        dialog --title $"Change ssh public key" \
                               --msgbox $"ssh public key was installed" 6 40
                    else
Bob Mottram's avatar
Bob Mottram committed
                        if [[ "$SSH_PUBLIC_KEY" == 'ssh-'* ]]; then
Bob Mottram's avatar
Bob Mottram committed
                            if [ ! -d "/home/$SELECTED_USERNAME/.ssh" ]; then
                                mkdir "/home/$SELECTED_USERNAME/.ssh"
                            fi
                            echo "$SSH_PUBLIC_KEY" > \
Bob Mottram's avatar
Bob Mottram committed
                                 "/home/$SELECTED_USERNAME/.ssh/authorized_keys"
                            chown -R "$SELECTED_USERNAME":"$SELECTED_USERNAME" \
                                  "/home/$SELECTED_USERNAME/.ssh"
                            dialog --title $"Change ssh public key" \
                                   --msgbox $"ssh public key was installed" 6 40
                        fi
                    fi
                fi
            fi
            ;;
    esac
Bob Mottram's avatar
Bob Mottram committed
    rm -f "$data"
function remove_user_from_mailing_list {
Bob Mottram's avatar
Bob Mottram committed
    if [ ! "$SELECTED_USERNAME" ]; then
Bob Mottram's avatar
Bob Mottram committed
    USER_MAILING_LISTS=$(grep '\[' "/home/$SELECTED_USERNAME/.procmailrc" | grep '\]' | awk -F '\[' '{print $2}' | awk -F '\\' '{print $1}')

    i=0
    W=()
    list_name=()
    while read -r listname; do
        i=$((i+1))
Bob Mottram's avatar
Bob Mottram committed
        W+=("$i" "$listname")
        list_name+=("$listname")
Bob Mottram's avatar
Bob Mottram committed
        echo "$listname"
    done <<< "$USER_MAILING_LISTS"

    i=$((i+1))
Bob Mottram's avatar
Bob Mottram committed
    W+=("$i" $"Exit back to user mainenance")
Bob Mottram's avatar
Bob Mottram committed
    # shellcheck disable=SC2068
    list_selected=$(dialog --default-item "$i" --backtitle $"Freedombone Control Panel" --title $"Remove a mailing list for $SELECTED_USERNAME" --menu $"Select one of the following:" 24 50 17 ${W[@]} 3>&2 2>&1 1>&3)
Bob Mottram's avatar
Bob Mottram committed
    # shellcheck disable=SC2181
    if [ $? -eq 0 ]; then # Exit with OK
Bob Mottram's avatar
Bob Mottram committed
        if [ "${list_selected}" -ne "${i}" ]; then
            remove_list_name="${list_name[$((list_selected-1))]}"

            # find the line number where the list is defined
            line_number=0
            i=0
            while read -r line
            do
Bob Mottram's avatar
Bob Mottram committed
                if [[ "$line" == *"\\[${remove_list_name}\\]"* ]]; then
                    line_number=${i}
                fi
                i=$((i+1))
            done < "/home/$SELECTED_USERNAME/.procmailrc"

            if [ ${line_number} -eq 0 ]; then
                # no match was found
                return
            fi

            # recreate the file
Bob Mottram's avatar
Bob Mottram committed
            if [ -f "/home/${SELECTED_USERNAME}/.procmailrc_new" ]; then
                rm "/home/${SELECTED_USERNAME}/.procmailrc_new"
            fi
            i=0
            clip=0
            while read -r line
            do
                i=$((i+1))
                if [ ${i} -gt $((line_number-1)) ]; then
                    if [ ${clip} -eq 0 ]; then
                        clip=1
                    fi
                    if [ ${clip} -eq 1 ]; then
                        if [ ${i} -lt $((line_number+2)) ]; then
                            continue
                        else
                            if [ ${#line} -lt 1 ]; then
                                clip=2
                                continue
                            fi
                            if [[ "$line" == ":"* || "$line" == "#"* ]]; then
                                clip=2
                            else
                                continue
                            fi
                        fi
                    fi
                fi

Bob Mottram's avatar
Bob Mottram committed
                echo "$line" >> "/home/${SELECTED_USERNAME}/.procmailrc_new"
Bob Mottram's avatar
Bob Mottram committed
                if [[ "$line" == *"\\[${remove_list_name}\\]"* ]]; then
                    line_number=${i}
                fi
            done < "/home/$SELECTED_USERNAME/.procmailrc"
Bob Mottram's avatar
Bob Mottram committed
            cp "/home/${SELECTED_USERNAME}/.procmailrc_new" "/home/${SELECTED_USERNAME}/.procmailrc"
            rm "/home/${SELECTED_USERNAME}/.procmailrc_new"
            chown "${SELECTED_USERNAME}":"${SELECTED_USERNAME}" "/home/${SELECTED_USERNAME}/.procmailrc"
            dialog --title $"Remove user from mailing list" \
                   --msgbox $"${SELECTED_USERNAME} has been removed from ${remove_list_name}" 6 50
        fi
    fi
Bob Mottram's avatar
Bob Mottram committed
function add_to_mailing_list {
Bob Mottram's avatar
Bob Mottram committed
    if [ ! "$SELECTED_USERNAME" ]; then
Bob Mottram's avatar
Bob Mottram committed
    data=$(mktemp 2>/dev/null)
    dialog --backtitle $"Freedombone Control Panel" \
           --title $"Subscribe $SELECTED_USERNAME to a mailing list" \
Bob Mottram's avatar
Bob Mottram committed
           --form $"You can either enter a subject or an email address\\n" 11 68 4 \
           $"List folder name:" 1 1 "" 1 35 26 25 \
           $"Name between [] on subject line:" 2 1 "" 2 35 26 25 \
           $"List email address:" 3 1 "" 3 35 26 25 \
           $"Public:" 4 1 $"yes" 4 35 4 25 \
Bob Mottram's avatar
Bob Mottram committed
           2> "$data"
Bob Mottram's avatar
Bob Mottram committed
        1)  rm -f "$data"
            return;;
Bob Mottram's avatar
Bob Mottram committed
        255) rm -f "$data"
             return;;
Bob Mottram's avatar
Bob Mottram committed
    LIST_NAME=$(sed -n 1p < "$data")
    LIST_SUBJECT=$(sed -n 2p < "$data")
    LIST_EMAIL=$(sed -n 3p < "$data")
    LIST_PUBLIC=$(sed -n 4p < "$data")

    if [ ${#LIST_PUBLIC} -lt 1 ]; then
        LIST_PUBLIC='no'
    fi
    if [[ $LIST_PUBLIC == $'y' || $LIST_PUBLIC == $'Y' || $LIST_PUBLIC == $'true' || $LIST_PUBLIC == $'True' || $LIST_PUBLIC == $'yes' || $LIST_PUBLIC == $'Yes' || $LIST_PUBLIC == $'YES' ]]; then
        LIST_PUBLIC='yes'
    else
        LIST_PUBLIC='no'
    fi
    if [ ${#LIST_NAME} -lt 2 ]; then
        dialog --title $"Add mailing list" \
               --msgbox $"No mailing list name was given" 6 40
Bob Mottram's avatar
Bob Mottram committed
        rm -f "$data"
        return
    fi
    if [ ${#LIST_SUBJECT} -lt 2 ]; then
        if [ ${#LIST_EMAIL} -lt 2 ]; then
            dialog --title $"Add mailing list" \
                   --msgbox $"No mailing list subject or address was given" 6 40
Bob Mottram's avatar
Bob Mottram committed
            rm -f "$data"
            return
        fi
    fi
    if [ ${#LIST_SUBJECT} -gt 1 ]; then
Bob Mottram's avatar
Bob Mottram committed
        "${PROJECT_NAME}-addlist" -u "$SELECTED_USERNAME" -l "$LIST_NAME" \
                       -s "$LIST_SUBJECT" --public "$LIST_PUBLIC"
    else
        if [[ "$LIST_EMAIL" != *"@"* || "$LIST_EMAIL" != *"."* ]]; then
            dialog --title $"Add mailing list" \
                   --msgbox $"Unrecognised email address" 6 40
Bob Mottram's avatar
Bob Mottram committed
            rm -f "$data"
Bob Mottram's avatar
Bob Mottram committed
            "${PROJECT_NAME}-addlist" -u "$SELECTED_USERNAME" -l "$LIST_NAME" \
                           -e "$LIST_EMAIL" --public "$LIST_PUBLIC"
        fi
    fi

    dialog --title $"Add mailing list" \
           --msgbox $"$LIST_NAME list was added" 6 40
Bob Mottram's avatar
Bob Mottram committed
    rm -f "$data"
Bob Mottram's avatar
Bob Mottram committed
}

function email_rule {
Bob Mottram's avatar
Bob Mottram committed
    if [ ! "$SELECTED_USERNAME" ]; then
Bob Mottram's avatar
Bob Mottram committed
    data=$(mktemp 2>/dev/null)
    dialog --backtitle $"Freedombone Control Panel" \
           --title $"Email rule for user $SELECTED_USERNAME" \
Bob Mottram's avatar
Bob Mottram committed
           --form "\\n" 9 65 4 \
           $"When email arrives from address:" 1 1 "" 1 35 24 28 \
           $"Move to folder:" 2 1 "" 2 35 24 28 \
           $"Public:" 3 1 $"no" 3 35 4 25 \
Bob Mottram's avatar
Bob Mottram committed
           2> "$data"
Bob Mottram's avatar
Bob Mottram committed
        1) rm -f "$data"
           return;;
Bob Mottram's avatar
Bob Mottram committed
        255) rm -f "$data"
             return;;
Bob Mottram's avatar
Bob Mottram committed
    RULE_EMAIL=$(sed -n 1p < "$data")
    RULE_FOLDER=$(sed -n 2p < "$data")
    RULE_PUBLIC=$(sed -n 3p < "$data")

    if [ ${#RULE_PUBLIC} -lt 1 ]; then
        RULE_PUBLIC='no'
    fi
    if [[ $RULE_PUBLIC == $'y' || $RULE_PUBLIC == $'Y' || $RULE_PUBLIC == $'true' || $RULE_PUBLIC == $'True' || $RULE_PUBLIC == $'yes' || $RULE_PUBLIC == $'Yes' || $RULE_PUBLIC == $'YES' ]]; then
        RULE_PUBLIC='yes'
    else
        RULE_PUBLIC='no'
    fi
    if [ ${#RULE_EMAIL} -lt 2 ]; then
        dialog --title $"Add email rule" \
               --msgbox $"No email address was given" 6 40
Bob Mottram's avatar
Bob Mottram committed
        rm -f "$data"
        return
    fi
    if [ ${#RULE_FOLDER} -lt 2 ]; then
        dialog --title $"Add email rule" \
               --msgbox $"No folder name was given" 6 40
Bob Mottram's avatar
Bob Mottram committed
        rm -f "$data"
        return
    fi
    if [[ "$RULE_EMAIL" != *"@"* || "$RULE_EMAIL" != *"."* ]]; then
        dialog --title $"Add email rule" \
               --msgbox $"Unrecognised email address" 6 40
Bob Mottram's avatar
Bob Mottram committed
        rm -f "$data"
Bob Mottram's avatar
Bob Mottram committed
    "${PROJECT_NAME}-addemail" -u "$SELECTED_USERNAME" -e "$RULE_EMAIL" \
                   -g "$RULE_FOLDER" --public $RULE_PUBLIC
    dialog --title $"Add email rule" \
           --msgbox $"Email rule for $RULE_EMAIL was added" 6 40
Bob Mottram's avatar
Bob Mottram committed
    rm -f "$data"
Bob Mottram's avatar
Bob Mottram committed
}

function block_unblock_email {
Bob Mottram's avatar
Bob Mottram committed
    if [ ! "$SELECTED_USERNAME" ]; then
        return
    fi
    blockstr=$"Block/Unblock email going to"
Bob Mottram's avatar
Bob Mottram committed
    data=$(mktemp 2>/dev/null)
    dialog --backtitle $"Freedombone Control Panel" \
           --title "$blockstr $SELECTED_USERNAME" \
Bob Mottram's avatar
Bob Mottram committed
           --form "\\n" 8 65 3 \
           $"When email arrives from address:" 1 1 "" 1 35 24 100 \
           $"Block it:" 2 1 "yes" 2 35 4 4 \
Bob Mottram's avatar
Bob Mottram committed
           2> "$data"
Bob Mottram's avatar
Bob Mottram committed
        1) rm -f "$data"
           return;;
Bob Mottram's avatar
Bob Mottram committed
        255) rm -f "$data"
             return;;
Bob Mottram's avatar
Bob Mottram committed
    BLOCK_EMAIL=$(sed -n 1p < "$data")
    BLOCK=$(sed -n 2p < "$data")
    rm -f "$data"
    if [ ${#BLOCK_EMAIL} -lt 2 ]; then
        dialog --title $"Block/Unblock an email" \
               --msgbox $"No email address was given" 6 40
        return
    fi
    if [[ "$BLOCK_EMAIL" != *"@"* || "$BLOCK_EMAIL" != *"."* ]]; then
        dialog --title $"Block/Unblock an email" \
               --msgbox $"Unrecognised email address" 6 40
        return
    fi
    if [[ $BLOCK == "y"* || $BLOCK == "Y"* ]]; then
Bob Mottram's avatar
Bob Mottram committed
        "${PROJECT_NAME}-ignore" -u "$SELECTED_USERNAME" -e "$BLOCK_EMAIL"
        dialog --title $"Block an email" \
               --msgbox "Email from $BLOCK_EMAIL to $SELECTED_USERNAME blocked" 6 75
    else
Bob Mottram's avatar
Bob Mottram committed
        "${PROJECT_NAME}-unignore" -u "$SELECTED_USERNAME" -e "$BLOCK_EMAIL"
        dialog --title $"Unblock an email" \
               --msgbox "Email from $BLOCK_EMAIL to $SELECTED_USERNAME unblocked" 6 75
    fi
Bob Mottram's avatar
Bob Mottram committed
}

function block_unblock_subject {
Bob Mottram's avatar
Bob Mottram committed
    if [ ! "$SELECTED_USERNAME" ]; then
        return
    fi
    blockstr=$"Block/Unblock email going to"
Bob Mottram's avatar
Bob Mottram committed
    data=$(mktemp 2>/dev/null)
    dialog --backtitle $"Freedombone Control Panel" \
           --title "$blockstr $SELECTED_USERNAME" \
Bob Mottram's avatar
Bob Mottram committed
           --form "\\n" 8 70 3 \
           $"When email arrives with subject text:" 1 1 "" 1 40 24 28 \
           $"Block it:" 2 1 "yes" 2 40 4 4 \
Bob Mottram's avatar
Bob Mottram committed
           2> "$data"
Bob Mottram's avatar
Bob Mottram committed
        1) rm -f "$data"
           return;;
Bob Mottram's avatar
Bob Mottram committed
        255) rm -f "$data"
             return;;
Bob Mottram's avatar
Bob Mottram committed
    BLOCK_SUBJECT=$(sed -n 1p < "$data")
    BLOCK=$(sed -n 2p < "$data")
    rm -f "$data"
    if [ ${#BLOCK_SUBJECT} -lt 2 ]; then
        dialog --title $"Block/Unblock an email" \
               --msgbox $"No subject was given" 6 40
        return
    fi
    if [[ $BLOCK == "y"* || $BLOCK == "Y"* ]]; then
Bob Mottram's avatar
Bob Mottram committed
        "${PROJECT_NAME}-ignore" -u "$SELECTED_USERNAME" -t "$BLOCK_SUBJECT"
        dialog --title $"Block an email" \
               --msgbox "Email with subject $BLOCK_SUBJECT to $SELECTED_USERNAME blocked" 6 40
    else
Bob Mottram's avatar
Bob Mottram committed
        "${PROJECT_NAME}-unignore" -u "$SELECTED_USERNAME" -t "$BLOCK_SUBJECT"
        dialog --title $"Unblock an email" \
               --msgbox "Email with subject $BLOCK_SUBJECT to $SELECTED_USERNAME unblocked" 6 40
    fi
Bob Mottram's avatar
Bob Mottram committed
}

function create_keydrive_master {
Bob Mottram's avatar
Bob Mottram committed
    if [ ! "$SELECTED_USERNAME" ]; then
        return
    fi
    dialog --title $"USB Master Keydrive" \
           --msgbox $"Plug in a LUKS encrypted USB drive" 6 40
    clear
    USB_DRIVE=$(detect_connected_drives)
Bob Mottram's avatar
Bob Mottram committed
    "${PROJECT_NAME}-keydrive" -u "$SELECTED_USERNAME" --master 'yes' -d "$USB_DRIVE"
Bob Mottram's avatar
Bob Mottram committed
}

function create_keydrive_fragment {
    if [ ! "$SELECTED_USERNAME" ]; then
        return
    fi
    dialog --title $"USB Fragment Keydrive" \
           --msgbox $"Plug in a LUKS encrypted USB drive" 6 40
    clear
    USB_DRIVE=$(detect_connected_drives)
Bob Mottram's avatar
Bob Mottram committed
    "${PROJECT_NAME}-keydrive" -u "$SELECTED_USERNAME" -d "$USB_DRIVE"
Bob Mottram's avatar
Bob Mottram committed
}

function backup_data {
    dialog --title $"Backup data to USB drive" \
Bob Mottram's avatar
Bob Mottram committed
           --msgbox $"Plug in a USB drive now" 6 40

    backup_password=$(${PROJECT_NAME}-pass -u "$ADMIN_USER" -a simplebackup)

    # get password with the --insecure option
    data=$(mktemp 2>/dev/null)
    dialog --title "Backup Drive Password" \
           --clear \
           --insecure \
           --passwordbox "Enter a password which will be used to encrypt the backup" 10 30 "$backup_password" 2> "$data"

    ret=$?

    # make decison
    case $ret in
        0)  backup_password=$(cat "$data")
            rm "$data"
            if [ "$backup_password" ]; then
                if [ ${#backup_password} -ge 8 ]; then
                    # shellcheck disable=SC2086
                    if /usr/bin/timeout $BACKUP_TIMEOUT_SEC /usr/local/bin/${PROJECT_NAME}-backup-local simple "$backup_password"; then
                        dialog --title $"Backup" \
                               --msgbox $"The backup succeeded" 6 40
                    else
                        any_key
                    fi
                else
                    dialog --title $"Backup" \
                           --msgbox $"Password is too short. Make it at least 8 characters" 6 40
                fi
            fi
            return
            ;;
    esac
    rm "$data"
Bob Mottram's avatar
Bob Mottram committed
}

Bob Mottram's avatar
Bob Mottram committed
function restore_data_from_storage {
    restore_type="$1"

Bob Mottram's avatar
Bob Mottram committed
    AllStr=$"all"
    ExitStr=$"Exit"
Bob Mottram's avatar
Bob Mottram committed
    RestoreStr=$"Restore apps"
Bob Mottram's avatar
Bob Mottram committed

    if [[ $restore_type == "local" ]]; then
        USB_DRIVE=$(detect_connected_drives)
Bob Mottram's avatar
Bob Mottram committed
        restore_command="${PROJECT_NAME}-restore-local $USB_DRIVE"
Bob Mottram's avatar
Bob Mottram committed
        RestoreStr=$"Restore apps from USB drive $USB_DRIVE"
    utils_installed=(configfiles
                     blocklist
Bob Mottram's avatar
Bob Mottram committed
                     mariadb
                     postgresql
Bob Mottram's avatar
Bob Mottram committed
                     letsencrypt
                     passwords
Bob Mottram's avatar
Bob Mottram committed
                     mutt
                     gpg
                     procmail
                     spamassassin
                     readme
                     ssh
                     userconfig
                     userlocal
                     userfin
                     certs
Bob Mottram's avatar
Bob Mottram committed
                     personal
                     email)
Bob Mottram's avatar
Bob Mottram committed
    while true
Bob Mottram's avatar
Bob Mottram committed
        app_list=()
Bob Mottram's avatar
Bob Mottram committed
        n=1
        applist="$n $AllStr off"
Bob Mottram's avatar
Bob Mottram committed
        n=$((n+1))
Bob Mottram's avatar
Bob Mottram committed
        app_list+=("$AllStr")
Bob Mottram's avatar
Bob Mottram committed
        util_index=0
Bob Mottram's avatar
Bob Mottram committed
        # shellcheck disable=SC2068
        for a in ${utils_installed[@]}
Bob Mottram's avatar
Bob Mottram committed
        do
            applist="$applist $n $a off"
Bob Mottram's avatar
Bob Mottram committed
            app_name=${utils_installed[util_index]}
Bob Mottram's avatar
Bob Mottram committed
            n=$((n+1))
            util_index=$((util_index+1))
Bob Mottram's avatar
Bob Mottram committed
            app_list+=("$app_name")
Bob Mottram's avatar
Bob Mottram committed
        app_index=0
Bob Mottram's avatar
Bob Mottram committed
        # shellcheck disable=SC2068
        for a in ${APPS_INSTALLED_NAMES[@]}
Bob Mottram's avatar
Bob Mottram committed
        do
            applist="$applist $n $a off"
Bob Mottram's avatar
Bob Mottram committed
            n=$((n+1))
Bob Mottram's avatar
Bob Mottram committed
            app_name=${APPS_INSTALLED_NAMES[app_index]}
Bob Mottram's avatar
Bob Mottram committed
            app_index=$((app_index+1))
Bob Mottram's avatar
Bob Mottram committed
            app_list+=("$app_name")
Bob Mottram's avatar
Bob Mottram committed
        done
        applist="$applist $n $ExitStr on"
Bob Mottram's avatar
Bob Mottram committed
        n=$((n+1))
Bob Mottram's avatar
Bob Mottram committed
        app_list+=("$ExitStr")
Bob Mottram's avatar
Bob Mottram committed
        # shellcheck disable=SC2086
Bob Mottram's avatar
Bob Mottram committed
        choice=$(dialog --stdout --backtitle $"Freedombone" \
Bob Mottram's avatar
Bob Mottram committed
                        --title "$RestoreStr" \
Bob Mottram's avatar
Bob Mottram committed
                        --radiolist $'Choose:' \
Bob Mottram's avatar
Bob Mottram committed
                        30 50 20 $applist)
Bob Mottram's avatar
Bob Mottram committed
        # shellcheck disable=SC2181
Bob Mottram's avatar
Bob Mottram committed
        if [ $? -ne 0 ]; then
            break
        fi
Bob Mottram's avatar
Bob Mottram committed
        app_index=$((choice-1))
Bob Mottram's avatar
Bob Mottram committed
        app_name=${app_list[app_index]}
Bob Mottram's avatar
Bob Mottram committed
        # exit
Bob Mottram's avatar
Bob Mottram committed
        if [[ "$app_name" == "$ExitStr" ]]; then
Bob Mottram's avatar
Bob Mottram committed
            break
        fi
Bob Mottram's avatar
Bob Mottram committed
        clear

        # Restore all
Bob Mottram's avatar
Bob Mottram committed
        if [[ "$app_name" == "$AllStr" ]]; then
Bob Mottram's avatar
Bob Mottram committed
            $restore_command
            retcode="$?"
            if [[ "$retcode" != "0" ]]; then
                any_key