From 77549acf452a8d6e256f461e20a2f3fde325373b Mon Sep 17 00:00:00 2001
From: Bob Mottram <bob@freedombone.net>
Date: Mon, 13 Aug 2018 14:27:07 +0100
Subject: [PATCH] Add webadmin blocklist

---
 src/freedombone-installer          |  87 +++++++++++++++++++-
 src/freedombone-utils-firewall     |  16 ++++
 src/freedombone-utils-webadmin     |   2 +
 webadmin/EN/blocking_template.html | 123 +++++++++++++++++++++++++++++
 webadmin/blocking.php              |  19 +++++
 5 files changed, 246 insertions(+), 1 deletion(-)
 create mode 100644 webadmin/EN/blocking_template.html
 create mode 100755 webadmin/blocking.php

diff --git a/src/freedombone-installer b/src/freedombone-installer
index 91612058b..2773e4260 100755
--- a/src/freedombone-installer
+++ b/src/freedombone-installer
@@ -44,6 +44,9 @@ install_state=$INSTALL_STATE_FIRST_BOOT
 CONFIGURATION_FILE="/root/${PROJECT_NAME}.cfg"
 COMPLETION_FILE="/root/${PROJECT_NAME}-completed.txt"
 
+# 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"
@@ -57,6 +60,7 @@ 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
@@ -73,7 +77,6 @@ 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
-change_password_script=/root/.webadmin_change_password.sh
 
 # Files used to initiate backup or restore manually from the web UI
 backup_file="$webadmin_install_dir/.start_backup"
@@ -731,6 +734,8 @@ function after_setup_has_finished {
         rm $installer_script
     fi
 
+    regenerate_blocklist
+
     systemctl reboot -i
 }
 
@@ -1198,6 +1203,85 @@ function reset_shutdown {
     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=$(cat "$FIREWALL_DOMAINS")
+        sed -i "s|BLOCKEDLIST|$blockedlist|g" "$webadmin_install_dir/blocking.html"
+        chown www-data:www-data "$webadmin_install_dir/blocking.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
+                            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
+                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 ! grep -q "$blocked_domain" "${FIREWALL_DOMAINS}.new"; then
+                                echo "$blocked_domain" >> "${FIREWALL_DOMAINS}.new"
+                            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
+}
+
 # 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')
@@ -1256,6 +1340,7 @@ do
                 if [ $install_state -eq $INSTALL_STATE_COMMAND_SUCCESS ]; then
                     reset_shutdown
                     webadmin_change_password
+                    update_blocklist
                     backup_and_restore
                     backup_and_restore_keys
                     add_remove_users
diff --git a/src/freedombone-utils-firewall b/src/freedombone-utils-firewall
index 7e907164d..ae052f58e 100755
--- a/src/freedombone-utils-firewall
+++ b/src/freedombone-utils-firewall
@@ -617,6 +617,7 @@ function firewall_block_domain {
             /usr/bin/pleroma-blocking
         fi
     fi
+    regenerate_webadmin_blocklist
 }
 
 function firewall_block_ip {
@@ -680,6 +681,7 @@ function firewall_unblock_domain {
     if grep -q " $unblocked_domain" /etc/hosts; then
         sed -i "/ $unblocked_domain/d" /etc/hosts
     fi
+    regenerate_webadmin_blocklist
 }
 
 function firewall_drop_spoofed_packets {
@@ -723,4 +725,18 @@ function firewall_rate_limits {
     mark_completed "${FUNCNAME[0]}"
 }
 
+function regenerate_webadmin_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=$(cat "$FIREWALL_DOMAINS")
+        sed -i "s|BLOCKEDLIST|$blockedlist|g" "$webadmin_install_dir/blocking.html"
+        chown www-data:www-data "$webadmin_install_dir/blocking.html"
+    fi
+}
+
 # NOTE: deliberately no exit 0
diff --git a/src/freedombone-utils-webadmin b/src/freedombone-utils-webadmin
index 14b4f080f..1b726788a 100755
--- a/src/freedombone-utils-webadmin
+++ b/src/freedombone-utils-webadmin
@@ -846,6 +846,8 @@ function install_web_admin {
     web_admin_avahi
 
     web_admin_configure_installer_daemon
+
+    regenerate_webadmin_blocklist
 }
 
 # NOTE: deliberately no exit 0
diff --git a/webadmin/EN/blocking_template.html b/webadmin/EN/blocking_template.html
new file mode 100644
index 000000000..6fd7b23bb
--- /dev/null
+++ b/webadmin/EN/blocking_template.html
@@ -0,0 +1,123 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <style>
+      #headerpic {
+          width: 60%;
+          height: auto;
+          margin-right : auto;
+          margin-left : auto;
+          min-width : 220px;
+      }
+
+      .header {
+          text-align: center;
+          padding: 32px;
+      }
+
+      .card {
+          box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2);
+          max-width: 600px;
+          margin: auto;
+          text-align: center;
+          font-family: arial;
+          clear: both;
+      }
+
+      .card input[type=text] {
+          width: 90%;
+          clear: both;
+          text-align: center;
+      }
+
+      .appurl {
+          color: grey;
+          font-size: 100%;
+      }
+
+      .welcomeheader {
+          color: black;
+          font-size: 200%;
+          font-weight: bold;
+      }
+
+      .descriptiontext {
+          color: black;
+          font-size: 90%;
+      }
+
+      .logintext {
+          color: black;
+          font-size: 120%;
+          font-weight: bold;
+          color: #981737;
+      }
+
+      button {
+          border: none;
+          outline: 0;
+          display: inline-block;
+          padding: 8px;
+          color: white;
+          background-color: #000;
+          text-align: center;
+          cursor: pointer;
+          width: 100%;
+          font-size: 18px;
+      }
+
+      a {
+          text-decoration: none;
+          color: black;
+      }
+
+      button:hover, a:hover {
+          opacity: 0.7;
+      }
+
+      .chip {
+          display: inline-block;
+          padding: 0 25px;
+          height: 50px;
+          font-size: 70%;
+          line-height: 50px;
+          border-radius: 25px;
+          background-color: #f1f1f1;
+      }
+
+      .chip img {
+          float: left;
+          margin: 0 10px 0 -25px;
+          height: 50px;
+          width: 50px;
+          border-radius: 50%;
+      }
+
+      textarea {
+          width: 90%;
+          color: black;
+          font-weight: bold;
+          background: lightblue;
+          font-size: 120%;
+      }
+    </style>
+  </head>
+  <body>
+    <div class="card">
+      <div class="header">
+        <img id="headerpic" class="img-responsive" src="images/logo.png"><br>
+
+        <p class="descriptiontext">Edit, add or remove blocked domains or users. This applies to Email, XMPP and fediverse addresses</p>
+
+        <form action="blocking.php" method="post">
+          <textarea rows="10" cols="50" name="blockinglist">BLOCKEDLIST</textarea>
+          <br><br>
+          <input type="submit" name="submitblockingcancel" value="Cancel">
+          <input type="submit" name="submitblocking" value="Continue">
+        </form>
+
+        <br>
+      </div>
+    </div>
+  </body>
+</html>
diff --git a/webadmin/blocking.php b/webadmin/blocking.php
new file mode 100755
index 000000000..3bf8f4c3b
--- /dev/null
+++ b/webadmin/blocking.php
@@ -0,0 +1,19 @@
+<?php
+
+// Receives the list of blocked domains/users
+
+$output_filename = "settings.html";
+
+if (isset($_POST['submitblocking'])) {
+    $blockinglist = htmlspecialchars($_POST['blockinglist']);
+
+    $blocking_file = fopen(".blocklist.txt", "w") or die("Unable to create setup file");
+    fwrite($blocking_file, $blockinglist);
+    fclose($blocking_file);
+}
+
+$htmlfile = fopen("$output_filename", "r") or die("Unable to open $output_filename");
+echo fread($htmlfile,filesize("$output_filename"));
+fclose($htmlfile);
+
+?>
-- 
GitLab