#!/bin/bash # _____ _ _ # | __|___ ___ ___ _| |___ _____| |_ ___ ___ ___ # | __| _| -_| -_| . | . | | . | . | | -_| # |__| |_| |___|___|___|___|_|_|_|___|___|_|_|___| # # Freedom in the Cloud # # Install daemon for the web admin system # See also freedombone-utils-webadmin # # License # ======= # # Copyright (C) 2018 Bob Mottram <bob@freedombone.net> # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # 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 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # 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/>. PROJECT_NAME='freedombone' export TEXTDOMAIN=${PROJECT_NAME}-installer export TEXTDOMAINDIR="/usr/share/locale" INSTALL_STATE_FIRST_BOOT=0 INSTALL_STATE_WEBADMIN_PASSWORD_CTEATED=1 INSTALL_STATE_RUNNING_COMMAND=2 INSTALL_STATE_COMMAND_FAIL=3 INSTALL_STATE_COMMAND_SUCCESS=4 install_state=$INSTALL_STATE_FIRST_BOOT CONFIGURATION_FILE="/root/${PROJECT_NAME}.cfg" COMPLETION_FILE="/root/${PROJECT_NAME}-completed.txt" # file containing a list of removed apps REMOVED_APPS_FILE=/root/removed # contains the blocked users and domains FIREWALL_DOMAINS=/root/${PROJECT_NAME}-firewall-domains.cfg local_hostname=$(grep 'host-name' /etc/avahi/avahi-daemon.conf | awk -F '=' '{print $2}').local webadmin_install_dir="/var/www/${local_hostname}/htdocs/admin" language_file="$webadmin_install_dir/.language.txt" system_monitor_file="$webadmin_install_dir/.system_monitor.txt" dynamic_dns_file="$webadmin_install_dir/.dynamicdns.txt" reset_file="$webadmin_install_dir/.reset.txt" shutdown_file="$webadmin_install_dir/.shutdown.txt" setup_file="$webadmin_install_dir/setup.txt" domain_file="$webadmin_install_dir/.temp_domain.txt" pending_removes="$webadmin_install_dir/pending_removes.txt" pending_installs="$webadmin_install_dir/pending_installs.txt" new_user_file="$webadmin_install_dir/.new_user.txt" remove_user_file="$webadmin_install_dir/.remove_user.txt" change_password_file="$webadmin_install_dir/changepassword.dat" install_state_file="/root/.install_state.txt" blocklist_file="$webadmin_install_dir/.blocklist.txt" INSTALL_DIR=/root/build webadmin_user='admin' webadmin_temp_password_file=/root/.temp_webadmin_password installer_script=/root/.fbone_installer.sh # Used to initiate automatic backups webadmin_prev_hour=99 # temporary backup and restore scripts backup_script=/root/.webadmin_backup.sh backup_keys_script=/root/.webadmin_backup_keys.sh restore_script=/root/.webadmin_restore.sh restore_keys_script=/root/.webadmin_restore_keys.sh format_script=/root/.webadmin_format.sh new_user_script=/root/.webadmin_new_user.sh remove_user_script=/root/.webadmin_remove_user.sh # Files used to initiate backup or restore manually from the web UI backup_file="$webadmin_install_dir/.start_backup" backup_keys_file="$webadmin_install_dir/.start_backup_keys" restore_file="$webadmin_install_dir/.start_restore" restore_keys_file="$webadmin_install_dir/.start_restore_keys" format_file="$webadmin_install_dir/.start_format" # These files contain the percentage progress backup_progress_file=/root/.backup_progress.txt restore_progress_file=/root/.backup_progress.txt format_progress_file=/root/.format_progress.txt function webadmin_update_version { local_hostname=$(grep 'host-name' /etc/avahi/avahi-daemon.conf | awk -F '=' '{print $2}').local webadmin_install_dir="/var/www/${local_hostname}/htdocs/admin" if [ -f "$webadmin_install_dir/about.html" ]; then VERSION=$(grep "VERSION=" "/usr/local/bin/${PROJECT_NAME}-vars" | grep -v DEBIAN | awk -F '"' '{print $2}') sed -i "s|\"versiontext\".*|\"versiontext\">$VERSION</p>|g" "$webadmin_install_dir/about.html" fi } function web_admin_onion_only { # In onion only mode domain names or ddns codes # don't need to be provided if ! grep -q 'ONION_ONLY=' "$CONFIGURATION_FILE"; then return fi ONION_ONLY=$(grep 'ONION_ONLY=' "$CONFIGURATION_FILE" | head -n 1 | awk -F '=' '{print $2}') if [ ! "$ONION_ONLY" ]; then ONION_ONLY='no' fi if [[ "$ONION_ONLY" == 'no' ]]; then return fi # shellcheck disable=SC2154 sed -i '/freedns_code/d' "$webadmin_install_dir/app_add_template.html" # shellcheck disable=SC2154 sed -i '/freedns_code/d' "$webadmin_install_dir/add_app_confirm_template.html" sed -i '/install_domain/d' "$webadmin_install_dir/app_add_template.html" sed -i '/install_domain/d' "$webadmin_install_dir/add_app_confirm_template.html" sed -i 's|onion_only=false;|onion_only=true;|g' "$webadmin_install_dir/installapp.php" sed -i 's|onion_only=false;|onion_only=true;|g' "$webadmin_install_dir/installappconfirm.php" sed -i 's|setup_domain.html|setup_installing.html|g' "$webadmin_install_dir/setupconfirm.php" } function web_admin_create_add_apps { if grep -q 'ONION_ONLY=' "$CONFIGURATION_FILE"; then ONION_ONLY=$(grep 'ONION_ONLY=' "$CONFIGURATION_FILE" | head -n 1 | awk -F '=' '{print $2}') else ONION_ONLY='no' fi appslist_add_filename="$webadmin_install_dir/apps_add.html" apps_add_template_filename="$webadmin_install_dir/apps_add_template.html" pending_installs="$webadmin_install_dir/pending_installs.txt" icons_dir="$webadmin_install_dir/icons" app_add_template_filename="$webadmin_install_dir/app_add_template.html" FILES="/usr/share/${PROJECT_NAME}/apps/${PROJECT_NAME}-app-*" if [ ! -d "$icons_dir" ]; then mkdir -p "$icons_dir" fi if [ ! -f "$apps_add_template_filename" ]; then return fi cp "$apps_add_template_filename" "$appslist_add_filename" sed -i '/<\/body>/d' "$appslist_add_filename" sed -i '/<\/html>/d' "$appslist_add_filename" available_apps_ctr=0 for filename in $FILES do app_name=$(echo "${filename}" | awk -F '-app-' '{print $2}') app_is_installed= # check if the app is pending installation app_pending_install= if [ -f "$pending_installs" ]; then if grep -q "install_${app_name}" "$pending_installs"; then app_is_installed=1 app_pending_install=1 fi fi if [ ! $app_is_installed ]; then app_filename="/usr/share/${PROJECT_NAME}/apps/${PROJECT_NAME}-app-${app_name}" if [ -f "$app_filename" ]; then if grep -q "VARIANTS=''" "$app_filename"; then continue fi if grep -q 'VARIANTS=""' "$app_filename"; then continue fi # get the icon for the app icon_filename="/usr/share/${PROJECT_NAME}/android-app/${app_name}.png" if [ -f "$icon_filename" ]; then cp "$icon_filename" "$webadmin_install_dir/icons/${app_name}.png" else continue fi app_name_upper=$(echo "$app_name" | awk '{print toupper($0)}') DESCRIPTION= if ! grep -q "${app_name_upper}_SHORT_DESCRIPTION=" "$app_filename"; then continue fi if grep -q "#${app_name_upper}_SHORT_DESCRIPTION=" "$app_filename"; then continue fi if grep -q "${app_name_upper}_DESCRIPTION=" "$app_filename"; then DESCRIPTION="$(grep "${app_name_upper}_DESCRIPTION=" "$app_filename" | head -n 1 | sed 's|\$||g' | sed "s|'||g" | sed 's|\"||g' | awk -F '=' '{print $2}')" fi if [ $available_apps_ctr -eq 0 ]; then echo ' <div class="row">' >> "$appslist_add_filename" fi filename="$webadmin_install_dir/app_${app_name}.html" if [ -f "$filename" ]; then rm "$filename" fi filename="$webadmin_install_dir/app_add_${app_name}.html" if [ ! $app_pending_install ]; then { echo ' <div class="column">'; echo ' <div>'; echo " <a href=\"app_add_${app_name}.html\">"; echo " <img src=\"icons/${app_name}.png\" style=\"width:100%\">"; echo " <center>${app_name}</center>"; echo ' </a>'; echo ' </div>'; echo ' </div>'; } >> "$appslist_add_filename" else { echo ' <div class="column">'; echo ' <div>'; echo " <img src=\"icons/${app_name}.png\" style=\"width:100%\">"; echo " <center class=\"installing\">${app_name}</center>"; echo ' </div>'; echo ' </div>'; } >> "$appslist_add_filename" fi cp "$app_add_template_filename" "$filename" # Replace app variables sed -i "s|HOSTNAME|$(hostname)|g" "$filename" sed -i "s|APPNAME|${app_name}|g" "$filename" sed -i "s|APPDESCRIPTION|${DESCRIPTION}|g" "$filename" # remove domain if onion only if [[ "$ONION_ONLY" != 'no' ]]; then if grep -q 'install_domain' "$filename"; then sed -i '/install_domain/d' "$filename" fi sed -i "/installappconfirm.php/a <input type=\"hidden\" name=\"install_domain\" value=\"${app_name}.$(hostname)\">" "$filename" fi if grep -q 'freedns_code' "$filename"; then sed -i '/freedns_code/d' "$filename" fi available_apps_ctr=$((available_apps_ctr+1)) # four columns per row if [ $available_apps_ctr -eq 4 ]; then echo ' </div>' >> "$appslist_add_filename" available_apps_ctr=0 fi fi fi done if [ ${available_apps_ctr} -gt 0 ]; then # Complete the rest of the four column row # shellcheck disable=SC2034 for i in $(seq ${available_apps_ctr} 3) do { echo ' <div class="column">'; echo ' <div>'; echo ' </div>'; echo ' </div>'; } >> "$appslist_add_filename" done echo ' </div>' >> "$appslist_add_filename" fi { echo ' <br><br>'; echo ' </body>'; echo '</html>'; } >> "$appslist_add_filename" chown -R www-data:www-data "$webadmin_install_dir" } function web_admin_create_installed_apps { appslist_filename="$webadmin_install_dir/apps.html" appslist_template_filename="$webadmin_install_dir/apps_template.html" icons_dir="$webadmin_install_dir/icons" pending_removes="$webadmin_install_dir/pending_removes.txt" if [ ! -d "$icons_dir" ]; then mkdir -p "$icons_dir" fi if [ ! -f "$appslist_template_filename" ]; then return fi cp "$appslist_template_filename" "$appslist_filename" sed -i '/<\/body>/d' "$appslist_filename" sed -i '/<\/html>/d' "$appslist_filename" installed_apps_ctr=0 # Complete the rest of the four column row # shellcheck disable=SC2034 for i in $(seq ${installed_apps_ctr} 3) do { echo ' <div class="column">'; echo ' <div>'; echo ' </div>'; echo ' </div>'; } >> "$appslist_filename" done echo ' </body>' >> "$appslist_filename" echo '</html>' >> "$appslist_filename" chown -R www-data:www-data "$webadmin_install_dir" } function web_admin_create_users { if [ ! -d "/home/$webadmin_user" ]; then return fi users_file="$webadmin_install_dir/users.html" cp "$webadmin_install_dir"/users_template.html "$users_file" sed -i '/users list/,/end of users/d' "$users_file" sed -i '/<\/body>/d' "$users_file" sed -i '/<\/html>/d' "$users_file" echo " <div class=\"row\">" >> "$users_file" echo " <div class=\"column\">" >> "$users_file" rm "$webadmin_install_dir/userprofile_"* USERNAME="$webadmin_user" userfile="$webadmin_install_dir/userprofile_${USERNAME}.html" useremail=${USERNAME}@${HOSTNAME} GPG_ID=$(su -c "gpg --list-keys '$useremail'" - "$USERNAME" | sed -n '2p' | sed 's/^[ \t]*//') if [ -f "/home/$USERNAME/.gnupg/gpg.conf" ]; then if grep -q "default-key" "/home/$USERNAME/.gnupg/gpg.conf"; then default_gpg_key=$(grep "default-key" "/home/$USERNAME/.gnupg/gpg.conf") if [[ "$default_gpg_key" != *'#'* ]]; then default_gpg_key=$(grep "default-key" "/home/$USERNAME/.gnupg/gpg.conf" | awk -F ' ' '{print $2}') if [ ${#default_gpg_key} -gt 3 ]; then GPG_ID=$(su -c "gpg --list-keys '$default_gpg_key'" - "$USERNAME" | sed -n '2p' | sed 's/^[ \t]*//') fi fi fi fi pubkey_qrcode="$webadmin_install_dir/images/userprofile_${USERNAME}.png" su -c "gpg --armor --export \"$GPG_ID\"" - "$USERNAME" | qrencode -t PNG -o "$pubkey_qrcode" { echo ' <div class="chip">'; echo " <a href=\"userprofile_${USERNAME}.html\">"; echo ' <img src="images/admin_users.png" alt="Person" width="96" height="96">'; echo " $USERNAME"; echo ' </a>'; echo ' </div>'; } >> "$users_file" cp "$webadmin_install_dir"/userprofile.html "$userfile" sed -i "s|USERNAME|${USERNAME}|g" "$userfile" if [[ "$USERNAME" == "$webadmin_user" ]]; then sed -i "s|USERTYPE|Admin|g" "$userfile" sed -i '/remove user button/,/end of remove/d' "$userfile" else sed -i "s|USERTYPE|User|g" "$userfile" fi sed -i "s|USEREMAIL|${useremail}|g" "$userfile" sed -i "s|USERGPG|${GPG_ID}|g" "$userfile" chown www-data:www-data "$userfile" chown www-data:www-data "$pubkey_qrcode" { echo ' <div class="chip">'; echo " <a href=\"new_user.html\">"; echo ' <img src="images/admin_users.png" alt="Person" width="96" height="96">'; echo ' +'; echo ' </a>'; echo ' </div>'; echo ' </div>'; echo ' </div>'; echo ' </body>'; echo '</html>'; } >> "$users_file" chown www-data:www-data "$users_file" } function wait_for_enough_entropy { # Wait indefinitely until enough entropy is available to # generate the webadmin login password while true do ENTROPY=$(cat /proc/sys/kernel/random/entropy_avail) # shellcheck disable=SC2086 if [ $ENTROPY -gt 500 ]; then break fi sleep 2 done } function web_admin_create_user { username="$1" password="$2" if [ ! "$username" ]; then return fi if [ ! -d "/home/$username" ]; then chmod 600 /etc/shadow chmod 600 /etc/gshadow useradd -m -p "$password" -s /bin/bash "$username" groupadd "$username" chmod 0000 /etc/shadow chmod 0000 /etc/gshadow else echo "${username}:${password}"|chpasswd fi } function web_admin_setup_login { if [ $install_state -ne $INSTALL_STATE_FIRST_BOOT ]; then return fi # if an nginx password file has not been created for web admin if [ -f /etc/nginx/.webadminpasswd ]; then return fi # this file indicates that the setup screen is active # and gets removed by freedombone-installer if [ ! -f "$webadmin_install_dir/.setupscreenactive" ]; then touch "$webadmin_install_dir/.setupscreenactive" fi if [ ! -f $webadmin_temp_password_file ]; then wait_for_enough_entropy webadmin_password="$(openssl rand -base64 32 | tr -dc A-Za-z0-9 | head -c 10 ; echo -n '')" echo -n "$webadmin_password" > $webadmin_temp_password_file else webadmin_password=$(cat $webadmin_temp_password_file) fi web_admin_create_user "$webadmin_user" "$webadmin_password" # create a password for users if [ ! -f /etc/nginx/.webadminpasswd ]; then touch /etc/nginx/.webadminpasswd fi # create a password file used by nginx echo -n "$webadmin_password" | htpasswd -i -s -c /etc/nginx/.webadminpasswd "$webadmin_user" if ! grep -q "${webadmin_user}:" /etc/nginx/.webadminpasswd; then echo $"/etc/nginx/.webadminpasswd password not created for $webadmin_user" if [ -f /etc/nginx/.webadminpasswd ]; then rm /etc/nginx/.webadminpasswd fi return fi # create a setup page with the initial password inserted # and copy it to the index cp "$webadmin_install_dir"/setup.html "$webadmin_install_dir"/setup.prev cp "$webadmin_install_dir"/setup_confirm_template.html "$webadmin_install_dir"/setup_confirm.html sed -i "s|WEBADMINPASSWORD|${webadmin_password}|g" "$webadmin_install_dir/setup.prev" sed -i "s|WEBADMINPASSWORD|${webadmin_password}|g" "$webadmin_install_dir/setup_confirm.html" cp "$webadmin_install_dir"/setup.prev "$webadmin_install_dir"/index.html # if initial setup has not yet happened then create # a password file if ! grep -q 'install_final' "$COMPLETION_FILE"; then echo -n "$webadmin_password" > /root/login.txt fi echo -n "$INSTALL_STATE_WEBADMIN_PASSWORD_CTEATED" > "$install_state_file" install_state=$INSTALL_STATE_WEBADMIN_PASSWORD_CTEATED } function enable_webadmin_login { # switch on nginx authentication for freedombone.local if grep -q "#auth_basic" "/etc/nginx/sites-available/${local_hostname}"; then sed -i 's|#auth_basic|auth_basic|g' "/etc/nginx/sites-available/${local_hostname}" fi } function remove_initial_setup_page { if [ -f "$webadmin_install_dir/index.prev" ]; then curr_language=$(web_admin_get_language_subdir) # Replace the installing screen with the main index page when done # It should reload by itself if [ -f "$webadmin_install_dir/setup_installing.html" ]; then cp "$webadmin_install_dir/${curr_language}/index.html" "$webadmin_install_dir/setup_installing.html" fi # Replace the setup confirm screen with the main index if [ -f "$webadmin_install_dir/setup_confirm.html" ]; then cp "$webadmin_install_dir/${curr_language}/index.html" "$webadmin_install_dir/setup_confirm.html" fi # Replace the setup domain screen with the main index if [ -f "$webadmin_install_dir/setup_domain.html" ]; then cp "$webadmin_install_dir/${curr_language}/index.html" "$webadmin_install_dir/setup_domain.html" fi # Show the web admin index page (not the initial setup page) cp "$webadmin_install_dir/${curr_language}/index.html" "$webadmin_install_dir/index.html" rm "$webadmin_install_dir/index.prev" fi # Remove the initial setup page if [ -f "$webadmin_install_dir/setup.prev" ]; then rm "$webadmin_install_dir/setup.prev" fi } function remove_temporary_setup_files { # remove the file which indicates that the setup screen is active if [ -f "$webadmin_install_dir/.setupscreenactive" ]; then rm "$webadmin_install_dir/.setupscreenactive" fi # remove the setup file created by setup.php if [ -f "$setup_file" ]; then rm "$setup_file" fi # remove the file containing the domain name if [ -f "$domain_file" ]; then rm "$domain_file" fi } function restore_webadmin_files { # restore files which were removed for the initial setup if [ -d "$INSTALL_DIR/tempwebadmin" ]; then mv "$INSTALL_DIR/tempwebadmin"/* "$webadmin_install_dir" rm -rf "$INSTALL_DIR/tempwebadmin" fi } function set_webadmin_permissions { # set permissions for web admin site at freedombone.local chown www-data:www-data "$webadmin_install_dir/*.html" } function check_for_existing_processes { script_name="$1" { echo '#!/bin/bash'; echo ''; echo 'function exit_if_process_is_running {'; echo " process_name=\"\$1\""; echo " process_exists=\$(ps a | grep \"\$process_name\" | grep -v 'grep')"; echo " if [ \"\$process_exists\" ]; then"; echo " if [[ \"\$process_exists\" != *'grep'* ]]; then"; echo " process_id=\$(echo \"\$process_exists\" | awk -F ' ' '{print \$1}')"; echo " if [ \"\$process_id\" ]; then"; echo " exit 0"; echo ' fi'; echo ' fi'; echo ' fi'; echo '}'; echo ''; echo 'exit_if_process_is_running fbone_installer.sh'; echo 'exit_if_process_is_running webadmin_format.sh'; echo 'exit_if_process_is_running webadmin_backup.sh'; echo 'exit_if_process_is_running webadmin_backup_keys.sh'; echo 'exit_if_process_is_running webadmin_restore.sh'; echo 'exit_if_process_is_running webadmin_restore_keys.sh'; echo 'exit_if_process_is_running webadmin_new_user.sh'; echo 'exit_if_process_is_running webadmin_remove_user.sh'; echo ''; } > "$script_name" } function run_setup_command { if [ $install_state -ne $INSTALL_STATE_WEBADMIN_PASSWORD_CTEATED ]; then return fi check_for_existing_processes $installer_script { echo "echo \"Beginning install \$(date)\" > $webadmin_install_dir/log.txt"; echo "chown www-data:www-data $webadmin_install_dir/log.txt"; echo ''; echo "/usr/local/bin/freedombone -c \"$CONFIGURATION_FILE\" >> $webadmin_install_dir/log.txt;"; echo "if ! grep -q 'install_final' \"$COMPLETION_FILE\"; then"; echo " chown www-data:www-data $webadmin_install_dir/log.txt"; echo " echo '$INSTALL_STATE_COMMAND_FAIL' > $install_state_file"; echo ' exit 364873'; echo 'fi'; echo ''; echo "chown www-data:www-data $webadmin_install_dir/log.txt"; echo ''; echo "exit 0"; } >> $installer_script chmod +x $installer_script echo -n "$INSTALL_STATE_RUNNING_COMMAND" > "$install_state_file" install_state=$INSTALL_STATE_RUNNING_COMMAND # run in a separate process ./$installer_script & } function check_install_command_state { if [ $install_state -ne $INSTALL_STATE_RUNNING_COMMAND ]; then return fi reset_install_state= if [ ! -f "$install_state_file" ]; then reset_install_state=1 else curr_state=$(cat "$install_state_file") # shellcheck disable=SC2086 if [ $curr_state -eq $INSTALL_STATE_COMMAND_FAIL ]; then reset_install_state=1 fi install_has_finished= # shellcheck disable=SC2086 if [ $curr_state -eq $INSTALL_STATE_COMMAND_SUCCESS ]; then install_has_finished=1 else # Also check the install log for a message # indicating completion has happened if [ -f "$webadmin_install_dir/log.txt" ]; then end_of_log=$(tail -n 10 "$webadmin_install_dir/log.txt" | grep ${PROJECT_NAME}) end_of_log_message=$'installation is complete' if [[ "$end_of_log" == *"$end_of_log_message"* ]]; then install_has_finished=1 fi fi fi if [ $install_has_finished ]; then echo -n "$INSTALL_STATE_COMMAND_SUCCESS" > "$install_state_file" install_state=$INSTALL_STATE_COMMAND_SUCCESS restore_webadmin_files fi fi if [ $reset_install_state ]; then chown www-data:www-data "$webadmin_install_dir/log.txt" # remove the setup file containing login details if [ -f "$setup_file" ]; then rm "$setup_file" fi # remove the webadmin password file if [ -f /etc/nginx/.webadminpasswd ]; then rm /etc/nginx/.webadminpasswd fi echo -n "$INSTALL_STATE_FIRST_BOOT" > "$install_state_file" install_state=$INSTALL_STATE_FIRST_BOOT fi } function web_admin_get_language_subdir { if grep -q 'DEFAULT_LANGUAGE=' "$CONFIGURATION_FILE"; then DEFAULT_LANGUAGE=$(grep 'DEFAULT_LANGUAGE=' "$CONFIGURATION_FILE" | head -n 1 | awk -F '=' '{print $2}') fi if [ ! "$DEFAULT_LANGUAGE" ]; then echo 'EN' return fi lang_lower="${DEFAULT_LANGUAGE:0:2}" echo "$lang_lower" | awk '{print toupper($0)}' } function before_setup_runs { if [ $install_state -ne $INSTALL_STATE_WEBADMIN_PASSWORD_CTEATED ]; then return fi if [ ! -f /etc/nginx/.webadminpasswd ]; then return fi if grep -q 'install_final' "$COMPLETION_FILE"; then return fi curr_language=$(web_admin_get_language_subdir) if [ ! -f "/usr/share/${PROJECT_NAME}/webadmin/${curr_language}/setup_installing.html" ]; then return fi cp "/usr/share/${PROJECT_NAME}/webadmin/${curr_language}/setup_installing.html" "$webadmin_install_dir/index.html" # get the username and domain from the .temp_setup.txt file # created by setup.php MY_USERNAME=$(cat "$setup_file") if [ ! "$MY_USERNAME" ]; then MY_USERNAME="$webadmin_user" else if [[ "$MY_USERNAME" != "$webadmin_user" ]]; then temp_webadmin_password=$(cat $webadmin_temp_password_file) web_admin_create_user "$webadmin_user" "$temp_webadmin_password" webadmin_user="$MY_USERNAME" fi fi DEFAULT_DOMAIN_NAME=${local_hostname} if [ -f "$domain_file" ]; then DEFAULT_DOMAIN_NAME=$(cat "$domain_file") fi # change the username in the config file if grep -q 'MY_USERNAME=' "$CONFIGURATION_FILE"; then if ! grep -Fxq "MY_USERNAME=$MY_USERNAME" "$CONFIGURATION_FILE"; then sed -i "s|MY_USERNAME=.*|MY_USERNAME=$MY_USERNAME|g" "$CONFIGURATION_FILE" fi else echo "MY_USERNAME=$MY_USERNAME" >> "$CONFIGURATION_FILE" fi # change the full name in the config file if grep -q 'MY_NAME=' "$CONFIGURATION_FILE"; then if ! grep -Fxq "MY_NAME=$MY_USERNAME" "$CONFIGURATION_FILE"; then sed -i "s|MY_NAME=.*|MY_USERNAME=$MY_USERNAME|g" "$CONFIGURATION_FILE" fi else echo "MY_NAME=$MY_USERNAME" >> "$CONFIGURATION_FILE" fi # change the default domain in the config file if grep -q 'DEFAULT_DOMAIN_NAME=' "$CONFIGURATION_FILE"; then if ! grep -Fxq "DEFAULT_DOMAIN_NAME=$DEFAULT_DOMAIN_NAME" "$CONFIGURATION_FILE"; then sed -i "s|DEFAULT_DOMAIN_NAME=.*|DEFAULT_DOMAIN_NAME=$DEFAULT_DOMAIN_NAME|g" "$CONFIGURATION_FILE" fi else echo "DEFAULT_DOMAIN_NAME=$DEFAULT_DOMAIN_NAME" >> "$CONFIGURATION_FILE" fi # ensure that minimal install is set if grep -q 'MINIMAL_INSTALL=' "$CONFIGURATION_FILE"; then if ! grep -Fxq "MINIMAL_INSTALL=yes" "$CONFIGURATION_FILE"; then sed -i 's|MINIMAL_INSTALL=.*|MINIMAL_INSTALL=yes|g' "$CONFIGURATION_FILE" fi else echo 'MINIMAL_INSTALL=yes' >> "$CONFIGURATION_FILE" fi # ensure that no DDNS provider is specified if grep -q 'DDNS_PROVIDER=' "$CONFIGURATION_FILE"; then if ! grep -Fxq "DDNS_PROVIDER=none" "$CONFIGURATION_FILE"; then sed -i 's|DDNS_PROVIDER=.*|DDNS_PROVIDER=none|g' "$CONFIGURATION_FILE" fi else echo 'DDNS_PROVIDER=none' >> "$CONFIGURATION_FILE" fi run_setup_command } function after_setup_has_finished { if [ $install_state -ne $INSTALL_STATE_COMMAND_SUCCESS ]; then return fi if [ -f /root/.initial_setup ]; then rm /root/.initial_setup fi enable_webadmin_login remove_initial_setup_page set_webadmin_permissions remove_temporary_setup_files if [ -f $webadmin_temp_password_file ]; then rm $webadmin_temp_password_file fi web_admin_onion_only web_admin_create_users web_admin_create_installed_apps web_admin_create_add_apps webadmin_update_version # remove default user if [ -d /home/fbone ]; then userdel -r fbone if [ -d /home/fbone ]; then rm -rf /home/fbone fi fi systemctl restart nginx if [ -f $installer_script ]; then rm $installer_script fi regenerate_blocklist systemctl reboot -i } function install_apps_from_webadmin { if [ -f "$pending_installs" ]; then linestr=$(head -n 1 "$pending_installs") if [[ "$linestr" == "install_"* ]]; then app_name=$(echo "$linestr" | awk -F '_' '{print $2}' | awk -F ',' '{print $1}') if [ -f "/usr/share/${PROJECT_NAME}/apps/${PROJECT_NAME}-app-${app_name}" ]; then app_domain=$(echo "$linestr" | awk -F ',' '{print $2}') if [ ! "$app_domain" ]; then app_domain=${app_name}.local fi app_name_upper=$(echo "$app_name" | awk '{print toupper($0)}') freedns_code=$(echo -n "$linestr" | awk -F ',' '{print $3}') # indicate that we are installing if [[ "$linestr" != *'_running'* ]]; then sed -i "s|${app_name}|${app_name}_running|g" "$pending_installs" fi # Add domain name to the config if ! grep -q "${app_name_upper}_DOMAIN_NAME=" $CONFIGURATION_FILE; then echo "${app_name_upper}_DOMAIN_NAME=${app_domain}" >> $CONFIGURATION_FILE else sed -i "s|${app_name_upper}_DOMAIN_NAME=.*|${app_name_upper}_DOMAIN_NAME=${app_domain}|g" $CONFIGURATION_FILE fi if grep -q 'ONION_ONLY=no' $CONFIGURATION_FILE; then # Add freedns code to the config if [ "$freedns_code" ]; then # shellcheck disable=SC2086 ${app_name_upper}_CODE="${freedns_code}" if ! grep -q "${app_name_upper}_CODE=" $CONFIGURATION_FILE; then echo "${app_name_upper}_CODE=${freedns_code}" >> $CONFIGURATION_FILE else sed -i "s|${app_name_upper}_CODE=.*|${app_name_upper}_CODE=${freedns_code}|g" $CONFIGURATION_FILE fi fi fi # remove app from the removed file if ! grep -Fxq "_${app_name}_" "$REMOVED_APPS_FILE"; then sed -i "/_${app_name}_/d" "$REMOVED_APPS_FILE" fi if ! /usr/local/bin/${PROJECT_NAME}-addremove add "${app_name}" > "$webadmin_install_dir/applog.txt"; then sed -i "/$linestr/d" "$pending_installs" web_admin_create_add_apps fi chown www-data:www-data "$webadmin_install_dir/applog.txt" fi # remove the line sed -i "/$linestr/d" "$pending_installs" else # if any unusual line is found then remove the file rm "$pending_installs" fi fi } function remove_apps_from_webadmin { if [ -f "$pending_removes" ]; then linestr=$(head -n 1 "$pending_removes") if [[ "$linestr" == "remove_"* ]]; then app_name=$(echo "$linestr" | awk -F '_' '{print $2}') if [ -f "/usr/share/${PROJECT_NAME}/apps/${PROJECT_NAME}-app-${app_name}" ]; then # indicate that we are removing if [[ "$linestr" != *'_running'* ]]; then sed -i "s|${app_name}|${app_name}_running|g" "$pending_removes" fi /usr/local/bin/${PROJECT_NAME}-addremove remove "${app_name}" > "$webadmin_install_dir/applog.txt" web_admin_create_add_apps chown www-data:www-data "$webadmin_install_dir/applog.txt" fi # remove the line sed -i "/$linestr/d" "$pending_removes" else # if any unusual line is found then remove the file rm "$pending_removes" fi fi } function update_progress_bar { # shellcheck disable=SC2086 if [ $install_state -ne $INSTALL_STATE_RUNNING_COMMAND ]; then return fi if [ ! -f /root/.install_counter ]; then echo -n '1' > /root/.install_counter fi max_counter=273 installing_page="$webadmin_install_dir/setup_installing.html" progress_counter=$(cat /root/.install_counter) progress_percent=$((progress_counter * 100 / max_counter)) if [ $progress_percent -gt 100 ]; then progress_percent=100 fi sed -i "s|<div class=\"w3-container.*|<div class=\"w3-container w3-blue w3-round-xlarge\" style=\"width:${progress_percent}%\">${progress_percent}%</div>|g" "$installing_page" if ! grep -q 'w3-container w3-blue' "$webadmin_install_dir/index.html"; then cp "$webadmin_install_dir/setup_installing.html" "$webadmin_install_dir/index.html" fi sed -i "s|<div class=\"w3-container.*|<div class=\"w3-container w3-blue w3-round-xlarge\" style=\"width:${progress_percent}%\">${progress_percent}%</div>|g" "$webadmin_install_dir/index.html" } function initiate_automatic_backup { backup_hour=3 if grep -q "BACKUP_HOUR=" "$CONFIGURATION_FILE"; then backup_hour=$(grep "BACKUP_HOUR=" "$CONFIGURATION_FILE" | awk -F '=' '{print $2}') else echo "BACKUP_HOUR=$backup_hour" >> "$CONFIGURATION_FILE" fi curr_hour=$(date +%H) if [[ "$curr_hour" == "$backup_hour" ]]; then if [[ "$webadmin_prev_hour" != "$backup_hour" ]]; then touch "$backup_file" fi fi webadmin_prev_hour=$curr_hour } function update_backup_progress_bar { if [ ! -f "$backup_progress_file" ]; then return fi backup_process_exists= backup_process=$(pgrep 'webadmin_backup.sh' | grep -v 'grep') if [ "$backup_process" ]; then if [[ "$backup_process" != *'grep'* ]]; then backup_pid=$(echo "$backup_process" | awk -F ' ' '{print $1}') if [ "$backup_pid" ]; then backup_process_exists=1 fi fi fi if [ ! $backup_process_exists ]; then return fi max_counter=203 progress_page="$webadmin_install_dir/backup_progress.html" progress_counter=$(cat $backup_progress_file) progress_percent=$((progress_counter * 100 / max_counter)) if [ $progress_percent -gt 100 ]; then progress_percent=$((progress_percent - 100)) fi sed -i "s|<div class=\"w3-container.*|<div class=\"w3-container w3-blue w3-round-xlarge\" style=\"width:${progress_percent}%\">${progress_percent}%</div>|g" "$progress_page" } function update_restore_progress_bar { if [ ! -f "$restore_progress_file" ]; then return fi restore_process_exists= restore_process=$(pgrep 'webadmin_restore.sh' | grep -v 'grep') if [ "$restore_process" ]; then if [[ "$restore_process" != *'grep'* ]]; then restore_pid=$(echo "$restore_process" | awk -F ' ' '{print $1}') if [ "$restore_pid" ]; then restore_process_exists=1 fi fi fi if [ ! $restore_process_exists ]; then return fi max_counter=203 progress_page="$webadmin_install_dir/restore_progress.html" progress_counter=$(cat $restore_progress_file) progress_percent=$((progress_counter * 100 / max_counter)) if [ $progress_percent -gt 100 ]; then progress_percent=$((progress_percent - 100)) fi sed -i "s|<div class=\"w3-container.*|<div class=\"w3-container w3-blue w3-round-xlarge\" style=\"width:${progress_percent}%\">${progress_percent}%</div>|g" "$progress_page" } function update_format_progress_bar { if [ ! -f "$format_progress_file" ]; then return fi format_process_exists= format_process=$(pgrep 'webadmin_format.sh' | grep -v 'grep') if [ "$format_process" ]; then if [[ "$format_process" != *'grep'* ]]; then format_pid=$(echo "$format_process" | awk -F ' ' '{print $1}') if [ "$format_pid" ]; then format_process_exists=1 fi fi fi if [ ! $format_process_exists ]; then return fi max_counter=5 progress_page="$webadmin_install_dir/format_progress.html" progress_counter=$(cat $format_progress_file) progress_percent=$((progress_counter * 100 / max_counter)) if [ $progress_percent -gt 100 ]; then progress_percent=100 fi sed -i "s|<div class=\"w3-container.*|<div class=\"w3-container w3-blue w3-round-xlarge\" style=\"width:${progress_percent}%\">${progress_percent}%</div>|g" "$progress_page" } function backup_and_restore { update_backup_progress_bar update_restore_progress_bar update_format_progress_bar initiate_automatic_backup if [ -f "$restore_file" ]; then rm "$restore_file" restore_title=$'Restore status' restore_failed_message=$"Restore failed. See http://${HOSTNAME}/admin/restore.txt for details" restore_success_message=$"Restore succeeded" check_for_existing_processes $restore_script { echo "echo \"Beginning webadmin restore \$(date)\" > $webadmin_install_dir/restore.txt"; echo "chown www-data:www-data $webadmin_install_dir/restore.txt"; echo ''; echo "cp $webadmin_install_dir/restore_progress_template.html $webadmin_install_dir/restore_progress.html"; echo "chown www-data:www-data $webadmin_install_dir/restore_progress.html"; echo ''; echo "if /usr/local/bin/${PROJECT_NAME}-restore-local simple >> $webadmin_install_dir/restore.txt; then"; echo " echo \"Completed \$(date)\" >> $webadmin_install_dir/restore.txt"; echo " cp $webadmin_install_dir/restore_complete.html $webadmin_install_dir/restore_progress.html"; echo " /usr/local/bin/${PROJECT_NAME}-notification -m \"$restore_success_message\" -s \"$restore_title\""; echo 'else'; echo " cp $webadmin_install_dir/restore_failed.html $webadmin_install_dir/restore_progress.html"; echo " /usr/local/bin/${PROJECT_NAME}-notification -m \"$restore_failed_message\" -s \"$restore_title\""; echo 'fi'; echo ''; echo "chown www-data:www-data $webadmin_install_dir/restore.txt"; echo "chown www-data:www-data $webadmin_install_dir/restore_progress.html"; echo ''; echo "rm $restore_progress_file"; echo ''; echo "exit 0"; } >> $restore_script chmod +x $restore_script # run in a separate process ./$restore_script & else if [ -f "$backup_file" ]; then rm "$backup_file" backup_title=$'Backup status' backup_failed_message=$"Backup failed. See http://${HOSTNAME}/admin/backup.txt for details" backup_success_message=$"Backup succeeded" check_for_existing_processes $backup_script { echo "echo \"Beginning webadmin backup \$(date)\" > $webadmin_install_dir/backup.txt"; echo "chown www-data:www-data $webadmin_install_dir/backup.txt"; echo ''; echo "cp $webadmin_install_dir/backup_progress_template.html $webadmin_install_dir/backup_progress.html"; echo "chown www-data:www-data $webadmin_install_dir/backup_progress.html"; echo ''; echo "if /usr/local/bin/${PROJECT_NAME}-backup-local simple >> $webadmin_install_dir/backup.txt; then"; echo " echo \"Completed \$(date)\" >> $webadmin_install_dir/backup.txt"; echo " cp $webadmin_install_dir/backup_complete.html $webadmin_install_dir/backup_progress.html"; echo " /usr/local/bin/${PROJECT_NAME}-notification -m \"$backup_success_message\" -s \"$backup_title\""; echo 'else'; echo " cp $webadmin_install_dir/backup_failed.html $webadmin_install_dir/backup_progress.html"; echo " /usr/local/bin/${PROJECT_NAME}-notification -m \"$backup_failed_message\" -s \"$backup_title\""; echo 'fi'; echo ''; echo "chown www-data:www-data $webadmin_install_dir/backup.txt"; echo "chown www-data:www-data $webadmin_install_dir/backup_progress.html"; echo ''; echo "rm $backup_progress_file"; echo ''; echo "exit 0"; } >> $backup_script chmod +x $backup_script # run in a separate process ./$backup_script & else if [ -f "$format_file" ]; then rm "$format_file" format_title=$'USB format status' format_failed_message=$"USB format failed. See http://${HOSTNAME}/admin/format.txt for details" format_success_message=$"USB format succeeded" check_for_existing_processes $format_script { echo "if /usr/local/bin/${PROJECT_NAME}-format simple > $webadmin_install_dir/format.txt; then"; echo " cp $webadmin_install_dir/format_complete.html $webadmin_install_dir/format_progress.html"; echo " /usr/local/bin/${PROJECT_NAME}-notification -m \"$format_success_message\" -s \"$format_title\""; echo 'else'; echo " cp $webadmin_install_dir/format_failed.html $webadmin_install_dir/format_progress.html"; echo " /usr/local/bin/${PROJECT_NAME}-notification -m \"$format_failed_message\" -s \"$format_title\""; echo 'fi'; echo "chown www-data:www-data $webadmin_install_dir/format_progress.html"; echo ''; echo "rm $format_progress_file"; echo ''; echo "exit 0"; } >> $format_script chmod +x $format_script # run in a separate process ./$format_script & fi fi fi } function backup_and_restore_keys { if [ -f "$restore_keys_file" ]; then rm "$restore_keys_file" admin_username=$(grep 'MY_USERNAME=' "$CONFIGURATION_FILE" | head -n 1 | awk -F '=' '{print $2}') # check_for_existing_processes $restore_keys_script { echo "echo \"Beginning webadmin restore keys \$(date)\" > $webadmin_install_dir/restore.txt"; echo "chown www-data:www-data $webadmin_install_dir/restore.txt"; echo ''; echo "cp $webadmin_install_dir/restore_keys_progress_template.html $webadmin_install_dir/restore_keys_progress.html"; echo "chown www-data:www-data $webadmin_install_dir/restore_keys_progress.html"; echo ''; echo "if /usr/local/bin/${PROJECT_NAME}-recoverkey -u \"$admin_username\" -d \"simple\" >> $webadmin_install_dir/restore.txt; then"; echo " echo \"Completed \$(date)\" >> $webadmin_install_dir/restore.txt"; echo " cp $webadmin_install_dir/restore_keys_complete.html $webadmin_install_dir/restore_keys_progress.html"; echo 'else'; echo " cp $webadmin_install_dir/restore_keys_failed.html $webadmin_install_dir/restore_keys_progress.html"; echo 'fi'; echo ''; echo "chown www-data:www-data $webadmin_install_dir/restore.txt"; echo "chown www-data:www-data $webadmin_install_dir/restore_keys_progress.html"; echo ''; echo "exit 0"; } >> $restore_keys_script chmod +x $restore_keys_script # run in a separate process ./$restore_keys_script & else if [ -f "$backup_keys_file" ]; then rm "$backup_keys_file" admin_username=$(grep 'MY_USERNAME=' "$CONFIGURATION_FILE" | head -n 1 | awk -F '=' '{print $2}') check_for_existing_processes $backup_keys_script { echo "echo \"Beginning webadmin backup keys \$(date)\" > $webadmin_install_dir/backup.txt"; echo "chown www-data:www-data $webadmin_install_dir/backup.txt"; echo ''; echo "cp $webadmin_install_dir/backup_keys_progress_template.html $webadmin_install_dir/backup_keys_progress.html"; echo "chown www-data:www-data $webadmin_install_dir/backup_keys_progress.html"; echo ''; echo "if /usr/local/bin/${PROJECT_NAME}-keydrive -u \"$admin_username\" --master 'yes' -d \"simple\" >> $webadmin_install_dir/backup.txt; then"; echo " echo \"Completed \$(date)\" >> $webadmin_install_dir/backup.txt"; echo " cp $webadmin_install_dir/backup_keys_complete.html $webadmin_install_dir/backup_keys_progress.html"; echo 'else'; echo " cp $webadmin_install_dir/backup_keys_failed.html $webadmin_install_dir/backup_keys_progress.html"; echo 'fi'; echo ''; echo "chown www-data:www-data $webadmin_install_dir/backup.txt"; echo "chown www-data:www-data $webadmin_install_dir/backup_keys_progress.html"; echo ''; echo "exit 0"; } >> $backup_keys_script chmod +x $backup_keys_script # run in a separate process ./$backup_keys_script & fi fi } function is_valid_user { USRNAME="$1" if [[ "$USRNAME" != "turtl" && "$USRNAME" != "znc" && "$USRNAME" != "pihole" && "$USRNAME" != "fbone" && "$USRNAME" != "go" && "$USRNAME" != "gogs" && "$USRNAME" != "git" && "$USRNAME" != "sync" && "$USRNAME" != "tahoelafs" ]]; then echo "1" else echo "0" fi } function valid_username_characters { local re='^[[:lower:]_][[:lower:][:digit:]_-]{2,15}$' (( ${#1} > 16 )) && return 1 [[ $1 =~ $re ]] # return value of this comparison is used for the function } function add_remove_users { if [ -f "$new_user_file" ]; then new_username=$(awk -F ',' '{print $1}' < "$new_user_file") if [ ${#new_username} -ge 3 ]; then if [ ${#new_username} -le 32 ]; then if valid_username_characters "$new_username"; then if [ ! -d "/home/$new_username" ]; then if [[ $(is_valid_user "$new_username") == "1" ]]; then new_password=$(awk -F ',' '{print $2}' < "$new_user_file") check_for_existing_processes $new_user_script { echo "/usr/local/bin/${PROJECT_NAME}-adduser $new_username password=$new_password > $webadmin_install_dir/log.txt"; echo "exit 0"; } >> $new_user_script chmod +x $new_user_script # run in a separate process ./$new_user_script & new_password= fi fi fi fi fi rm "$new_user_file" fi if [ -f "$remove_user_file" ]; then remove_username=$(cat "$remove_user_file") if [ ${#remove_username} -ge 3 ]; then if [ ${#remove_username} -le 32 ]; then if valid_username_characters "$remove_username"; then if [ -d "/home/$remove_username" ]; then if [[ $(is_valid_user "$remove_username") == "1" ]]; then admin_username=$(grep 'MY_USERNAME=' "$CONFIGURATION_FILE" | head -n 1 | awk -F '=' '{print $2}') if [[ "$remove_username" != "$admin_username" ]]; then check_for_existing_processes $remove_user_script { echo "/usr/local/bin/${PROJECT_NAME}-rmuser $remove_username -f > $webadmin_install_dir/log.txt"; echo "exit 0"; } >> $remove_user_script chmod +x $remove_user_script # run in a separate process ./$remove_user_script & fi fi fi fi fi fi rm "$remove_user_file" fi } function webadmin_change_password { if [ ! -f "$change_password_file" ]; then return fi temp_password_file=$(cat "$change_password_file") if [ -f "$temp_password_file" ]; then curr_username=$(awk -F ',' '{print $1}' < "$temp_password_file") if [ ${#curr_username} -ge 3 ]; then if [[ $(is_valid_user "$curr_username") == "1" ]]; then if [ -d "/home/$curr_username" ]; then new_password=$(awk -F ',' '{print $2}' < "$temp_password_file") admin_username=$(grep 'MY_USERNAME=' "$CONFIGURATION_FILE" | head -n 1 | awk -F '=' '{print $2}') # change the webadmin login if [[ "$curr_username" == "$admin_username" ]]; then if [ -f /etc/nginx/.webadminpasswd ]; then sed -i "/${curr_username}:/d" /etc/nginx/.webadminpasswd fi echo -n "$new_password" | htpasswd -i -s -c /etc/nginx/.webadminpasswd "$curr_username" fi # change the login for the user echo "${curr_username}:${new_password}"|chpasswd # change passwords for each installed app /usr/local/bin/${PROJECT_NAME}-chpasswd "$curr_username" "$new_password" new_password= fi fi fi rm "$temp_password_file" fi rm "$change_password_file" } function reset_shutdown { if [ -f "$shutdown_file" ]; then rm "$shutdown_file" if [ -f "$reset_file" ]; then rm "$reset_file" fi sleep 2 systemctl poweroff fi if [ -f "$reset_file" ]; then rm "$reset_file" if [ -f "$shutdown_file" ]; then rm "$shutdown_file" fi sleep 2 systemctl reboot -i fi } function regenerate_blocklist { if [ ! -f "$FIREWALL_DOMAINS" ]; then touch "$FIREWALL_DOMAINS" fi local_hostname=$(grep 'host-name' /etc/avahi/avahi-daemon.conf | awk -F '=' '{print $2}').local webadmin_install_dir="/var/www/${local_hostname}/htdocs/admin" if [ -f "$webadmin_install_dir/blocking_template.html" ]; then cp "$webadmin_install_dir/blocking_template.html" "$webadmin_install_dir/blocking.html" blockedlist=$(sed 's@[/\&]@\\&@g;s/$/\\/' "$FIREWALL_DOMAINS"; echo .) blockedlist=${blockedlist%.} sed -i "s|BLOCKEDLIST|$blockedlist|g" "$webadmin_install_dir/blocking.html" chown www-data:www-data "$webadmin_install_dir/blocking.html" fi } function regenerate_dynamic_dns { ddns="$1" ddns_username="$2" ddns_password="$3" local_hostname=$(grep 'host-name' /etc/avahi/avahi-daemon.conf | awk -F '=' '{print $2}').local webadmin_install_dir="/var/www/${local_hostname}/htdocs/admin" if [ -f "$webadmin_install_dir/dynamicdns_template.html" ]; then cp "$webadmin_install_dir/dynamicdns_template.html" "$webadmin_install_dir/dynamicdns.html" if [[ "$ddns" == 'default@freedns.afraid.org' ]]; then ddns='freedns' fi if [[ "$ddns" == 'dyn.com' ]]; then ddns='dyn' fi sed -i "s|\"$ddns\"|\"$ddns\" selected|g" "$webadmin_install_dir/dynamicdns.html" sed -i "s|DDNS_USERNAME|$ddns_username|g" "$webadmin_install_dir/dynamicdns.html" # Note: For security don't populate the password #sed -i "s|DDNS_PASSWORD|$ddns_password|g" "$webadmin_install_dir/dynamicdns.html" chown www-data:www-data "$webadmin_install_dir/dynamicdns.html" fi } function update_blocklist { if [ -f "$blocklist_file" ]; then if [ -f "${FIREWALL_DOMAINS}.new" ]; then rm "${FIREWALL_DOMAINS}.new" fi touch "${FIREWALL_DOMAINS}.new" blocked_lines_ctr=0 while read -r line; do if [ $blocked_lines_ctr -gt 1024 ]; then # This prevents someone copy-pasting a giant amount of text # into the blocklist. If you're legitimately blocking more # than this number then you probably have other problems to # think about and should consider whitelisting instead break fi blocked_lines_ctr=$((blocked_lines_ctr + 1)) if [ "$line" ]; then # remove leading and trailing spaces newline="$(echo -e "${line}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" line="$newline" if [[ "$line" == *'@'* ]]; then # blocked user # remove leading @ if [[ "$line" == '@'* ]]; then newline=${line:1} line="$newline" fi blocked_username=$(echo "$line" | awk -F '@' '{print $1}') if valid_username_characters "$blocked_username"; then blocked_domain=$(echo "$line" | awk -F '@' '{print $2}') if [[ "$blocked_domain" == *'.'* ]]; then if [ ${#blocked_domain} -gt 3 ]; then test_domain=$(echo "$blocked_domain" | tr -dc a-z0-9.-) if [[ "$blocked_domain" == "$test_domain" ]]; then blocked_address="${blocked_username}@${blocked_domain}" if ! grep -q "$blocked_address" "${FIREWALL_DOMAINS}.new"; then echo "${blocked_username}@${blocked_domain}" >> "${FIREWALL_DOMAINS}.new" fi fi fi fi fi else # blocked domain if [[ "$line" == *'.'* ]]; then blocked_domain="$line" test_domain=$(echo "$blocked_domain" | tr -dc a-z0-9.-) if [[ "$blocked_domain" == "$test_domain" ]]; then if [ ${#blocked_domain} -gt 3 ]; then if ! grep -q "$blocked_domain" "${FIREWALL_DOMAINS}.new"; then echo "$blocked_domain" >> "${FIREWALL_DOMAINS}.new" fi fi fi fi fi fi done < "$blocklist_file" mv "${FIREWALL_DOMAINS}" "${FIREWALL_DOMAINS}.backup" mv "${FIREWALL_DOMAINS}.new" "${FIREWALL_DOMAINS}" rm "$blocklist_file" regenerate_blocklist fi } function update_dynamic_dns { if [ -f "$dynamic_dns_file" ]; then ddns=$(awk -F ',' '{print $1}' < "$dynamic_dns_file") ddns_username=$(awk -F ',' '{print $2}' < "$dynamic_dns_file") ddns_password=$(awk -F ',' '{print $3}' < "$dynamic_dns_file") ddns_is_valid= if [ "$ddns_username" ]; then if [ "$ddns_password" ]; then if [ ${#ddns_username} -gt 2 ]; then if [ ${#ddns_username} -lt 512 ]; then if [ ${#ddns_password} -gt 2 ]; then if [ ${#ddns_password} -lt 512 ]; then ddns_is_valid=1 fi fi fi fi fi fi if [ $ddns_is_valid ]; then /usr/local/bin/${PROJECT_NAME}-ddns "$ddns" "$ddns_username" "$ddns_password" regenerate_dynamic_dns "$ddns" "$ddns_username" "$ddns_password" fi rm "$dynamic_dns_file" fi } function change_language { if [ -f "$language_file" ]; then language=$(cat "$language_file") local_hostname=$(grep 'host-name' /etc/avahi/avahi-daemon.conf | awk -F '=' '{print $2}').local webadmin_install_dir="/var/www/${local_hostname}/htdocs/admin" if [ -f "$webadmin_install_dir/language_template.html" ]; then if grep -q "\"$language\"" "$webadmin_install_dir/language_template.html"; then cp "$webadmin_install_dir/language_template.html" "$webadmin_install_dir/language.html" sed -i "s|\"$language\"|\"$language\" selected|g" "$webadmin_install_dir/language.html" chown www-data:www-data "$webadmin_install_dir/language.html" config_language=$(grep "DEFAULT_LANGUAGE=" "$CONFIGURATION_FILE" | awk -F '=' '{print $2}') if [[ "$config_language" != "$language" ]]; then curr_language=$(web_admin_get_language_subdir) if [ -d "/usr/share/${PROJECT_NAME}/webadmin/${curr_language}" ]; then # copy files for the new language cp -r "/usr/share/${PROJECT_NAME}/webadmin/${curr_language}/*" "/usr/share/${PROJECT_NAME}/webadmin/" # recreate some screens from templates regenerate_blocklist touch "$system_monitor_file" update_system_monitor webadmin_update_version fi chown -R www-data:www-data "$webadmin_install_dir/*" sed -i "s|DEFAULT_LANGUAGE=.*|DEFAULT_LANGUAGE=$language|g" "$CONFIGURATION_FILE" locale-gen "${language}" update-locale LANG="${language}" update-locale LANGUAGE="${language}" update-locale LC_MESSAGES="${language}" update-locale LC_ALL="${language}" update-locale LC_CTYPE="${language}" fi fi fi rm "$language_file" fi } function update_system_monitor { if [ -f "$system_monitor_file" ]; then rm "$system_monitor_file" disk_use=$(df -h | grep /dev/sda1) disk_use_percent=0 if [[ "$disk_use" == *'/dev/sda1'* ]]; then disk_use_percent=$(df -h | grep /dev/sda1 | awk -F ' ' '{print $5}') else disk_use_percent=$(df -h | grep /dev/mmcblk0p1 | awk -F ' ' '{print $5}') fi used_memory=$(free -m | grep "Mem:" | awk -F ' ' '{print $3}') total_memory=$(free -m | grep "Mem:" | awk -F ' ' '{print $2}') used_memory_percent=$((used_memory * 100 / total_memory)) cpu_temperature=0 cpu_temp=$(cat /sys/class/thermal/thermal_zone*/temp | head -n 1) if [ "$cpu_temp" ]; then cpu_temperature=$((cpu_temp / 1000)) fi test_drive=/dev/sda1 if ! ls $test_drive; then if ls /dev/mmcblk0p2; then test_drive=/dev/mmcblk0p2 else test_drive= fi fi if [ "$test_drive" ]; then disk_io_speed_percent=0 disk_io_speed=$(hdparm -t $test_drive | awk -F '= ' '{print $2}' | awk -F ' ' '{print $1}') if [ "$disk_io_speed" ]; then disk_io_speed_percent=$((disk_io_speed * 100 / 500)) if [ $disk_io_speed_percent -gt 100 ]; then disk_io_speed_percent=100 fi fi fi local_hostname=$(grep 'host-name' /etc/avahi/avahi-daemon.conf | awk -F '=' '{print $2}').local webadmin_install_dir="/var/www/${local_hostname}/htdocs/admin" if [ -f "$webadmin_install_dir/system_monitor_template.html" ]; then cp "$webadmin_install_dir/system_monitor_template.html" "$webadmin_install_dir/system_monitor.html" if [[ "$disk_use_percent" == *'%'* ]]; then sed -i "s|<div name=\"diskspace\" class=\"w3-container.*|<div name=\"diskspace\" class=\"w3-container w3-blue w3-round-xlarge\" style=\"width:$disk_use_percent\">$disk_use_percent</div>|g" "$webadmin_install_dir/system_monitor.html" fi sed -i "s|<div name=\"memory\" class=\"w3-container.*|<div name=\"memory\" class=\"w3-container w3-blue w3-round-xlarge\" style=\"width:${used_memory_percent}%\">${used_memory_percent}%</div>|g" "$webadmin_install_dir/system_monitor.html" sed -i "s|<div name=\"cputemp\" class=\"w3-container.*|<div name=\"cputemp\" class=\"w3-container w3-blue w3-round-xlarge\" style=\"width:${cpu_temperature}%\">${cpu_temperature}C</div>|g" "$webadmin_install_dir/system_monitor.html" sed -i "s|<div name=\"diskio\" class=\"w3-container.*|<div name=\"diskio\" class=\"w3-container w3-blue w3-round-xlarge\" style=\"width:${disk_io_speed_percent}%\">${disk_io_speed} MB/s</div>|g" "$webadmin_install_dir/system_monitor.html" chown www-data:www-data "$webadmin_install_dir/system_monitor.html" fi fi } # If the freedombone command is already running then kill its process #shellcheck disable=SC2009 install_process=$(ps a | grep '/usr/local/bin/freedombone -c' | grep -v 'grep') if [ "$install_process" ]; then if [[ "$install_process" != *'grep'* ]]; then install_pid=$(echo "$install_process" | awk -F ' ' '{print $1}') if [ "$install_pid" ]; then pkill -9 "$install_pid" fi fi fi # get the current install state if [ -f "$install_state_file" ]; then install_state=$(cat "$install_state_file") # shellcheck disable=SC2086 if [ $install_state -ne $INSTALL_STATE_COMMAND_SUCCESS ]; then if grep -q 'install_final' "$COMPLETION_FILE"; then install_state=$INSTALL_STATE_COMMAND_SUCCESS else chown www-data:www-data "$webadmin_install_dir/log.txt" # remove the setup file containing login details if [ -f "$setup_file" ]; then rm "$setup_file" fi if [ -f /etc/nginx/.webadminpasswd ]; then rm /etc/nginx/.webadminpasswd fi install_state=$INSTALL_STATE_FIRST_BOOT fi echo -n "$install_state" > "$install_state_file" fi else if grep -q 'install_final' "$COMPLETION_FILE"; then install_state=$INSTALL_STATE_COMMAND_SUCCESS else install_state=$INSTALL_STATE_FIRST_BOOT fi echo -n "$install_state" > "$install_state_file" fi while true do if [ -f /tmp/.upgrading ]; then sleep 2 else web_admin_setup_login if [ -d "$webadmin_install_dir" ]; then if [ -f "$setup_file" ]; then update_progress_bar before_setup_runs check_install_command_state after_setup_has_finished sleep 1 else if [ $install_state -eq $INSTALL_STATE_COMMAND_SUCCESS ]; then reset_shutdown webadmin_change_password update_blocklist update_dynamic_dns update_system_monitor change_language backup_and_restore backup_and_restore_keys add_remove_users install_apps_from_webadmin sleep 1 remove_apps_from_webadmin fi fi fi sleep 1 fi done exit 0