From 58be3194c057c9d3f9d1c41fbdd8e65eeaa340e3 Mon Sep 17 00:00:00 2001 From: Teal Dulcet Date: Thu, 21 Dec 2023 06:58:34 -0800 Subject: [PATCH] Fixed SC2086: Double quote to prevent globbing and word splitting. --- setup/bootstrap.sh | 6 ++--- setup/dkim.sh | 8 +++--- setup/dns.sh | 6 ++--- setup/firstuser.sh | 8 +++--- setup/functions.sh | 36 +++++++++++++-------------- setup/mail-dovecot.sh | 16 ++++++------ setup/mail-postfix.sh | 22 ++++++++--------- setup/mail-users.sh | 12 ++++----- setup/management.sh | 6 ++--- setup/munin.sh | 8 +++--- setup/network-checks.sh | 6 ++--- setup/nextcloud.sh | 46 +++++++++++++++++------------------ setup/preflight.sh | 6 ++--- setup/questions.sh | 12 ++++----- setup/spamassassin.sh | 10 ++++---- setup/ssl.sh | 24 +++++++++--------- setup/start.sh | 26 ++++++++++---------- setup/system.sh | 14 +++++------ setup/web.sh | 16 ++++++------ setup/webmail.sh | 18 +++++++------- tools/archive_conf_files.sh | 4 +-- tools/owncloud-restore.sh | 16 ++++++------ tools/owncloud-unlockadmin.sh | 4 +-- 23 files changed, 165 insertions(+), 165 deletions(-) diff --git a/setup/bootstrap.sh b/setup/bootstrap.sh index 9399a235..401bbe8b 100644 --- a/setup/bootstrap.sh +++ b/setup/bootstrap.sh @@ -51,7 +51,7 @@ if [[ $EUID -ne 0 ]]; then fi # Clone the Mail-in-a-Box repository if it doesn't exist. -if [ ! -d $HOME/mailinabox ]; then +if [ ! -d "$HOME/mailinabox" ]; then if [ ! -f /usr/bin/git ]; then echo Installing git . . . apt-get -q -q update @@ -67,14 +67,14 @@ if [ ! -d $HOME/mailinabox ]; then git clone \ -b $TAG --depth 1 \ $SOURCE \ - $HOME/mailinabox \ + "$HOME/mailinabox" \ < /dev/null 2> /dev/null echo fi # Change directory to it. -cd $HOME/mailinabox +cd "$HOME/mailinabox" # Update it. if [ "$TAG" != $(git describe --always) ]; then diff --git a/setup/dkim.sh b/setup/dkim.sh index d2d162a7..0001d4c4 100755 --- a/setup/dkim.sh +++ b/setup/dkim.sh @@ -15,7 +15,7 @@ apt_install opendkim opendkim-tools opendmarc # Make sure configuration directories exist. mkdir -p /etc/opendkim; -mkdir -p $STORAGE_ROOT/mail/dkim +mkdir -p "$STORAGE_ROOT/mail/dkim" # Used in InternalHosts and ExternalIgnoreList configuration directives. # Not quite sure why. @@ -53,12 +53,12 @@ fi # such as Google. But they and others use a 2048 bit key, so we'll # do the same. Keys beyond 2048 bits may exceed DNS record limits. if [ ! -f "$STORAGE_ROOT/mail/dkim/mail.private" ]; then - opendkim-genkey -b 2048 -r -s mail -D $STORAGE_ROOT/mail/dkim + opendkim-genkey -b 2048 -r -s mail -D "$STORAGE_ROOT/mail/dkim" fi # Ensure files are owned by the opendkim user and are private otherwise. -chown -R opendkim:opendkim $STORAGE_ROOT/mail/dkim -chmod go-rwx $STORAGE_ROOT/mail/dkim +chown -R opendkim:opendkim "$STORAGE_ROOT/mail/dkim" +chmod go-rwx "$STORAGE_ROOT/mail/dkim" tools/editconf.py /etc/opendmarc.conf -s \ "Syslog=true" \ diff --git a/setup/dns.sh b/setup/dns.sh index 9b9b1b0a..2501795a 100755 --- a/setup/dns.sh +++ b/setup/dns.sh @@ -106,7 +106,7 @@ if [ ! -f "$STORAGE_ROOT/dns/dnssec/$algo.conf" ]; then # (This previously used -b 2048 but it's unclear if this setting makes sense # for non-RSA keys, so it's removed. The RSA-based keys are not recommended # anymore anyway.) - KSK=$(umask 077; cd $STORAGE_ROOT/dns/dnssec; ldns-keygen -r /dev/urandom -a $algo -k _domain_); + KSK=$(umask 077; cd "$STORAGE_ROOT/dns/dnssec"; ldns-keygen -r /dev/urandom -a $algo -k _domain_); # Now create a Zone-Signing Key (ZSK) which is expected to be # rotated more often than a KSK, although we have no plans to @@ -114,7 +114,7 @@ if [ ! -f "$STORAGE_ROOT/dns/dnssec/$algo.conf" ]; then # disturbing DNS availability.) Omit `-k`. # (This previously used -b 1024 but it's unclear if this setting makes sense # for non-RSA keys, so it's removed.) - ZSK=$(umask 077; cd $STORAGE_ROOT/dns/dnssec; ldns-keygen -r /dev/urandom -a $algo _domain_); + ZSK=$(umask 077; cd "$STORAGE_ROOT/dns/dnssec"; ldns-keygen -r /dev/urandom -a $algo _domain_); # These generate two sets of files like: # @@ -126,7 +126,7 @@ if [ ! -f "$STORAGE_ROOT/dns/dnssec/$algo.conf" ]; then # options. So we'll store the names of the files we just generated. # We might have multiple keys down the road. This will identify # what keys are the current keys. - cat > $STORAGE_ROOT/dns/dnssec/$algo.conf << EOF; + cat > "$STORAGE_ROOT/dns/dnssec/$algo.conf" << EOF; KSK=$KSK ZSK=$ZSK EOF diff --git a/setup/firstuser.sh b/setup/firstuser.sh index 7caec35d..ffec7064 100644 --- a/setup/firstuser.sh +++ b/setup/firstuser.sh @@ -22,7 +22,7 @@ if [ -z "$(management/cli.py user)" ]; then input_box "Mail Account" \ "That's not a valid email address. \n\nWhat email address do you want?" \ - $EMAIL_ADDR \ + "$EMAIL_ADDR" \ EMAIL_ADDR if [ -z "$EMAIL_ADDR" ]; then # user hit ESC/cancel @@ -47,11 +47,11 @@ if [ -z "$(management/cli.py user)" ]; then fi # Create the user's mail account. This will ask for a password if none was given above. - management/cli.py user add $EMAIL_ADDR ${EMAIL_PW:-} + management/cli.py user add "$EMAIL_ADDR" ${EMAIL_PW:-} # Make it an admin. - hide_output management/cli.py user make-admin $EMAIL_ADDR + hide_output management/cli.py user make-admin "$EMAIL_ADDR" # Create an alias to which we'll direct all automatically-created administrative aliases. - management/cli.py alias add administrator@$PRIMARY_HOSTNAME $EMAIL_ADDR > /dev/null + management/cli.py alias add "administrator@$PRIMARY_HOSTNAME" "$EMAIL_ADDR" > /dev/null fi diff --git a/setup/functions.sh b/setup/functions.sh index 151c5f40..84156b9f 100644 --- a/setup/functions.sh +++ b/setup/functions.sh @@ -16,7 +16,7 @@ function hide_output { # Execute command, redirecting stderr/stdout to the temporary file. Since we # check the return code ourselves, disable 'set -e' temporarily. set +e - "$@" &> $OUTPUT + "$@" &> "$OUTPUT" E=$? set -e @@ -26,13 +26,13 @@ function hide_output { echo echo FAILED: "$@" echo ----------------------------------------- - cat $OUTPUT + cat "$OUTPUT" echo ----------------------------------------- exit $E fi # Remove temporary file. - rm -f $OUTPUT + rm -f "$OUTPUT" } function apt_get_quiet { @@ -76,7 +76,7 @@ function get_publicip_from_web_service { # # Pass '4' or '6' as an argument to this function to specify # what type of address to get (IPv4, IPv6). - curl -$1 --fail --silent --max-time 15 icanhazip.com 2>/dev/null || /bin/true + curl -"$1" --fail --silent --max-time 15 icanhazip.com 2>/dev/null || /bin/true } function get_default_privateip { @@ -119,19 +119,19 @@ function get_default_privateip { if [ "$1" == "6" ]; then target=2001:4860:4860::8888; fi # Get the route information. - route=$(ip -$1 -o route get $target 2>/dev/null | grep -v unreachable) + route=$(ip -"$1" -o route get $target 2>/dev/null | grep -v unreachable) # Parse the address out of the route information. - address=$(echo $route | sed "s/.* src \([^ ]*\).*/\1/") + address=$(echo "$route" | sed "s/.* src \([^ ]*\).*/\1/") if [[ "$1" == "6" && $address == fe80:* ]]; then # For IPv6 link-local addresses, parse the interface out # of the route information and append it with a '%'. - interface=$(echo $route | sed "s/.* dev \([^ ]*\).*/\1/") + interface=$(echo "$route" | sed "s/.* dev \([^ ]*\).*/\1/") address=$address%$interface fi - echo $address + echo "$address" } function ufw_allow { @@ -149,7 +149,7 @@ function ufw_limit { } function restart_service { - hide_output service $1 restart + hide_output service "$1" restart } ## Dialog Functions ## @@ -178,7 +178,7 @@ function input_menu { declare -n result_code=$4_EXITCODE local IFS=^$'\n' set +e - result=$(dialog --stdout --title "$1" --menu "$2" 0 0 0 $3) + result=$(dialog --stdout --title "$1" --menu "$2" 0 0 0 "$3") result_code=$? set -e } @@ -190,17 +190,17 @@ function wget_verify { HASH=$2 DEST=$3 CHECKSUM="$HASH $DEST" - rm -f $DEST - hide_output wget -O $DEST $URL + rm -f "$DEST" + hide_output wget -O "$DEST" "$URL" if ! echo "$CHECKSUM" | sha1sum --check --strict > /dev/null; then echo "------------------------------------------------------------" echo "Download of $URL did not match expected checksum." echo "Found:" - sha1sum $DEST + sha1sum "$DEST" echo echo "Expected:" echo "$CHECKSUM" - rm -f $DEST + rm -f "$DEST" exit 1 fi } @@ -216,9 +216,9 @@ function git_clone { SUBDIR=$3 TARGETPATH=$4 TMPPATH=/tmp/git-clone-$$ - rm -rf $TMPPATH $TARGETPATH - git clone -q $REPO $TMPPATH || exit 1 - (cd $TMPPATH; git checkout -q $TREEISH;) || exit 1 - mv $TMPPATH/$SUBDIR $TARGETPATH + rm -rf $TMPPATH "$TARGETPATH" + git clone -q "$REPO" $TMPPATH || exit 1 + (cd $TMPPATH; git checkout -q "$TREEISH";) || exit 1 + mv $TMPPATH/"$SUBDIR" "$TARGETPATH" rm -rf $TMPPATH } diff --git a/setup/mail-dovecot.sh b/setup/mail-dovecot.sh index 8d45a50b..39b22515 100755 --- a/setup/mail-dovecot.sh +++ b/setup/mail-dovecot.sh @@ -61,7 +61,7 @@ tools/editconf.py /etc/sysctl.conf \ # username part of the user's email address. We'll ensure that no bad domains or email addresses # are created within the management daemon. tools/editconf.py /etc/dovecot/conf.d/10-mail.conf \ - mail_location=maildir:$STORAGE_ROOT/mail/mailboxes/%d/%n \ + mail_location="maildir:$STORAGE_ROOT/mail/mailboxes/%d/%n" \ mail_privileged_group=mail \ first_valid_uid=0 @@ -152,7 +152,7 @@ EOF # Setting a `postmaster_address` is required or LMTP won't start. An alias # will be created automatically by our management daemon. tools/editconf.py /etc/dovecot/conf.d/15-lda.conf \ - postmaster_address=postmaster@$PRIMARY_HOSTNAME + "postmaster_address=postmaster@$PRIMARY_HOSTNAME" # ### Sieve @@ -201,14 +201,14 @@ chown -R mail:dovecot /etc/dovecot chmod -R o-rwx /etc/dovecot # Ensure mailbox files have a directory that exists and are owned by the mail user. -mkdir -p $STORAGE_ROOT/mail/mailboxes -chown -R mail:mail $STORAGE_ROOT/mail/mailboxes +mkdir -p "$STORAGE_ROOT/mail/mailboxes" +chown -R mail:mail "$STORAGE_ROOT/mail/mailboxes" # Same for the sieve scripts. -mkdir -p $STORAGE_ROOT/mail/sieve -mkdir -p $STORAGE_ROOT/mail/sieve/global_before -mkdir -p $STORAGE_ROOT/mail/sieve/global_after -chown -R mail:mail $STORAGE_ROOT/mail/sieve +mkdir -p "$STORAGE_ROOT/mail/sieve" +mkdir -p "$STORAGE_ROOT/mail/sieve/global_before" +mkdir -p "$STORAGE_ROOT/mail/sieve/global_after" +chown -R mail:mail "$STORAGE_ROOT/mail/sieve" # Allow the IMAP/POP ports in the firewall. ufw_allow imaps diff --git a/setup/mail-postfix.sh b/setup/mail-postfix.sh index 5787e8c9..8f616f46 100755 --- a/setup/mail-postfix.sh +++ b/setup/mail-postfix.sh @@ -55,9 +55,9 @@ apt_install postfix postfix-sqlite postfix-pcre postgrey ca-certificates # * Set the SMTP banner (which must have the hostname first, then anything). tools/editconf.py /etc/postfix/main.cf \ inet_interfaces=all \ - smtp_bind_address=$PRIVATE_IP \ - smtp_bind_address6=$PRIVATE_IPV6 \ - myhostname=$PRIMARY_HOSTNAME\ + smtp_bind_address="$PRIVATE_IP" \ + smtp_bind_address6="$PRIVATE_IPV6" \ + myhostname="$PRIMARY_HOSTNAME"\ smtpd_banner="\$myhostname ESMTP Hi, I'm a Mail-in-a-Box (Ubuntu/Postfix; see https://mailinabox.email/)" \ mydestination=localhost @@ -126,9 +126,9 @@ sed -i "s/PUBLIC_IP/$PUBLIC_IP/" /etc/postfix/outgoing_mail_header_filters tools/editconf.py /etc/postfix/main.cf \ smtpd_tls_security_level=may\ smtpd_tls_auth_only=yes \ - smtpd_tls_cert_file=$STORAGE_ROOT/ssl/ssl_certificate.pem \ - smtpd_tls_key_file=$STORAGE_ROOT/ssl/ssl_private_key.pem \ - smtpd_tls_dh1024_param_file=$STORAGE_ROOT/ssl/dh2048.pem \ + smtpd_tls_cert_file="$STORAGE_ROOT/ssl/ssl_certificate.pem" \ + smtpd_tls_key_file="$STORAGE_ROOT/ssl/ssl_private_key.pem" \ + smtpd_tls_dh1024_param_file="$STORAGE_ROOT/ssl/dh2048.pem" \ smtpd_tls_protocols="!SSLv2,!SSLv3" \ smtpd_tls_ciphers=medium \ tls_medium_cipherlist=ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA \ @@ -247,17 +247,17 @@ tools/editconf.py /etc/default/postgrey \ # If the $STORAGE_ROOT/mail/postgrey is empty, copy the postgrey database over from the old location -if [ ! -d $STORAGE_ROOT/mail/postgrey/db ]; then +if [ ! -d "$STORAGE_ROOT/mail/postgrey/db" ]; then # Stop the service service postgrey stop # Ensure the new paths for postgrey db exists - mkdir -p $STORAGE_ROOT/mail/postgrey/db + mkdir -p "$STORAGE_ROOT/mail/postgrey/db" # Move over database files - mv /var/lib/postgrey/* $STORAGE_ROOT/mail/postgrey/db/ || true + mv /var/lib/postgrey/* "$STORAGE_ROOT/mail/postgrey/db/" || true fi # Ensure permissions are set -chown -R postgrey:postgrey $STORAGE_ROOT/mail/postgrey/ -chmod 700 $STORAGE_ROOT/mail/postgrey/{,db} +chown -R postgrey:postgrey "$STORAGE_ROOT/mail/postgrey/" +chmod 700 "$STORAGE_ROOT/mail/postgrey/"{,db} # We are going to setup a newer whitelist for postgrey, the version included in the distribution is old cat > /etc/cron.daily/mailinabox-postgrey-whitelist << EOF; diff --git a/setup/mail-users.sh b/setup/mail-users.sh index b570f037..0c6be0c8 100755 --- a/setup/mail-users.sh +++ b/setup/mail-users.sh @@ -18,12 +18,12 @@ source /etc/mailinabox.conf # load global vars db_path=$STORAGE_ROOT/mail/users.sqlite # Create an empty database if it doesn't yet exist. -if [ ! -f $db_path ]; then - echo Creating new user database: $db_path; - echo "CREATE TABLE users (id INTEGER PRIMARY KEY AUTOINCREMENT, email TEXT NOT NULL UNIQUE, password TEXT NOT NULL, extra, privileges TEXT NOT NULL DEFAULT '');" | sqlite3 $db_path; - echo "CREATE TABLE aliases (id INTEGER PRIMARY KEY AUTOINCREMENT, source TEXT NOT NULL UNIQUE, destination TEXT NOT NULL, permitted_senders TEXT);" | sqlite3 $db_path; - echo "CREATE TABLE mfa (id INTEGER PRIMARY KEY AUTOINCREMENT, user_id INTEGER NOT NULL, type TEXT NOT NULL, secret TEXT NOT NULL, mru_token TEXT, label TEXT, FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE);" | sqlite3 $db_path; - echo "CREATE TABLE auto_aliases (id INTEGER PRIMARY KEY AUTOINCREMENT, source TEXT NOT NULL UNIQUE, destination TEXT NOT NULL, permitted_senders TEXT);" | sqlite3 $db_path; +if [ ! -f "$db_path" ]; then + echo "Creating new user database: $db_path"; + echo "CREATE TABLE users (id INTEGER PRIMARY KEY AUTOINCREMENT, email TEXT NOT NULL UNIQUE, password TEXT NOT NULL, extra, privileges TEXT NOT NULL DEFAULT '');" | sqlite3 "$db_path"; + echo "CREATE TABLE aliases (id INTEGER PRIMARY KEY AUTOINCREMENT, source TEXT NOT NULL UNIQUE, destination TEXT NOT NULL, permitted_senders TEXT);" | sqlite3 "$db_path"; + echo "CREATE TABLE mfa (id INTEGER PRIMARY KEY AUTOINCREMENT, user_id INTEGER NOT NULL, type TEXT NOT NULL, secret TEXT NOT NULL, mru_token TEXT, label TEXT, FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE);" | sqlite3 "$db_path"; + echo "CREATE TABLE auto_aliases (id INTEGER PRIMARY KEY AUTOINCREMENT, source TEXT NOT NULL UNIQUE, destination TEXT NOT NULL, permitted_senders TEXT);" | sqlite3 "$db_path"; fi # ### User Authentication diff --git a/setup/management.sh b/setup/management.sh index 50c24189..fc44aed6 100755 --- a/setup/management.sh +++ b/setup/management.sh @@ -52,9 +52,9 @@ hide_output $venv/bin/pip install --upgrade \ # CONFIGURATION # Create a backup directory and a random key for encrypting backups. -mkdir -p $STORAGE_ROOT/backup -if [ ! -f $STORAGE_ROOT/backup/secret_key.txt ]; then - $(umask 077; openssl rand -base64 2048 > $STORAGE_ROOT/backup/secret_key.txt) +mkdir -p "$STORAGE_ROOT/backup" +if [ ! -f "$STORAGE_ROOT/backup/secret_key.txt" ]; then + $(umask 077; openssl rand -base64 2048 > "$STORAGE_ROOT/backup/secret_key.txt") fi diff --git a/setup/munin.sh b/setup/munin.sh index 90f93521..cebecf80 100755 --- a/setup/munin.sh +++ b/setup/munin.sh @@ -40,7 +40,7 @@ chown munin /var/log/munin/munin-cgi-graph.log # ensure munin-node knows the name of this machine # and reduce logging level to warning tools/editconf.py /etc/munin/munin-node.conf -s \ - host_name=$PRIMARY_HOSTNAME \ + host_name="$PRIMARY_HOSTNAME" \ log_level=1 # Update the activated plugins through munin's autoconfiguration. @@ -52,9 +52,9 @@ find /etc/munin/plugins/ -lname /usr/share/munin/plugins/ntp_ -print0 | xargs -0 # Deactivate monitoring of network interfaces that are not up. Otherwise we can get a lot of empty charts. for f in $(find /etc/munin/plugins/ \( -lname /usr/share/munin/plugins/if_ -o -lname /usr/share/munin/plugins/if_err_ -o -lname /usr/share/munin/plugins/bonding_err_ \)); do - IF=$(echo $f | sed s/.*_//); - if ! grep -qFx up /sys/class/net/$IF/operstate 2>/dev/null; then - rm $f; + IF=$(echo "$f" | sed s/.*_//); + if ! grep -qFx up "/sys/class/net/$IF/operstate" 2>/dev/null; then + rm "$f"; fi; done diff --git a/setup/network-checks.sh b/setup/network-checks.sh index 428fa4ca..5d5351c7 100644 --- a/setup/network-checks.sh +++ b/setup/network-checks.sh @@ -6,7 +6,7 @@ apt_get_quiet install bind9-host sed netcat-openbsd # The user might have chosen a name that was previously in use by a spammer # and will not be able to reliably send mail. Do this after any automatic # choices made above. -if host $PRIMARY_HOSTNAME.dbl.spamhaus.org > /dev/null; then +if host "$PRIMARY_HOSTNAME.dbl.spamhaus.org" > /dev/null; then echo echo "The hostname you chose '$PRIMARY_HOSTNAME' is listed in the" echo "Spamhaus Domain Block List. See http://www.spamhaus.org/dbl/" @@ -22,8 +22,8 @@ fi # The user might have ended up on an IP address that was previously in use # by a spammer, or the user may be deploying on a residential network. We # will not be able to reliably send mail in these cases. -REVERSED_IPV4=$(echo $PUBLIC_IP | sed "s/\([0-9]*\).\([0-9]*\).\([0-9]*\).\([0-9]*\)/\4.\3.\2.\1/") -if host $REVERSED_IPV4.zen.spamhaus.org > /dev/null; then +REVERSED_IPV4=$(echo "$PUBLIC_IP" | sed "s/\([0-9]*\).\([0-9]*\).\([0-9]*\).\([0-9]*\)/\4.\3.\2.\1/") +if host "$REVERSED_IPV4.zen.spamhaus.org" > /dev/null; then echo echo "The IP address $PUBLIC_IP is listed in the Spamhaus Block List." echo "See http://www.spamhaus.org/query/ip/$PUBLIC_IP." diff --git a/setup/nextcloud.sh b/setup/nextcloud.sh index a2d9d2e5..95cc43f1 100755 --- a/setup/nextcloud.sh +++ b/setup/nextcloud.sh @@ -74,7 +74,7 @@ InstallNextcloud() { echo # Download and verify - wget_verify https://download.nextcloud.com/server/releases/nextcloud-$version.zip $hash /tmp/nextcloud.zip + wget_verify "https://download.nextcloud.com/server/releases/nextcloud-$version.zip" "$hash" /tmp/nextcloud.zip # Remove the current owncloud/Nextcloud rm -rf /usr/local/lib/owncloud @@ -88,18 +88,18 @@ InstallNextcloud() { # their github repositories. mkdir -p /usr/local/lib/owncloud/apps - wget_verify https://github.com/nextcloud-releases/contacts/archive/refs/tags/v$version_contacts.tar.gz $hash_contacts /tmp/contacts.tgz + wget_verify "https://github.com/nextcloud-releases/contacts/archive/refs/tags/v$version_contacts.tar.gz" "$hash_contacts" /tmp/contacts.tgz tar xf /tmp/contacts.tgz -C /usr/local/lib/owncloud/apps/ rm /tmp/contacts.tgz - wget_verify https://github.com/nextcloud-releases/calendar/archive/refs/tags/v$version_calendar.tar.gz $hash_calendar /tmp/calendar.tgz + wget_verify "https://github.com/nextcloud-releases/calendar/archive/refs/tags/v$version_calendar.tar.gz" "$hash_calendar" /tmp/calendar.tgz tar xf /tmp/calendar.tgz -C /usr/local/lib/owncloud/apps/ rm /tmp/calendar.tgz # Starting with Nextcloud 15, the app user_external is no longer included in Nextcloud core, # we will install from their github repository. if [ -n "$version_user_external" ]; then - wget_verify https://github.com/nextcloud-releases/user_external/releases/download/v$version_user_external/user_external-v$version_user_external.tar.gz $hash_user_external /tmp/user_external.tgz + wget_verify "https://github.com/nextcloud-releases/user_external/releases/download/v$version_user_external/user_external-v$version_user_external.tar.gz" "$hash_user_external" /tmp/user_external.tgz tar -xf /tmp/user_external.tgz -C /usr/local/lib/owncloud/apps/ rm /tmp/user_external.tgz fi @@ -109,16 +109,16 @@ InstallNextcloud() { # Create a symlink to the config.php in STORAGE_ROOT (for upgrades we're restoring the symlink we previously # put in, and in new installs we're creating a symlink and will create the actual config later). - ln -sf $STORAGE_ROOT/owncloud/config.php /usr/local/lib/owncloud/config/config.php + ln -sf "$STORAGE_ROOT/owncloud/config.php /usr/local/lib/owncloud/config/config.php" # Make sure permissions are correct or the upgrade step won't run. # $STORAGE_ROOT/owncloud may not yet exist, so use -f to suppress # that error. - chown -f -R www-data:www-data $STORAGE_ROOT/owncloud /usr/local/lib/owncloud || /bin/true + chown -f -R www-data:www-data "$STORAGE_ROOT/owncloud /usr/local/lib/owncloud" || /bin/true # If this isn't a new installation, immediately run the upgrade script. # Then check for success (0=ok and 3=no upgrade needed, both are success). - if [ -e $STORAGE_ROOT/owncloud/owncloud.db ]; then + if [ -e "$STORAGE_ROOT/owncloud/owncloud.db" ]; then # ownCloud 8.1.1 broke upgrades. It may fail on the first attempt, but # that can be OK. sudo -u www-data php$PHP_VER /usr/local/lib/owncloud/occ upgrade @@ -167,21 +167,21 @@ if [ ! -d /usr/local/lib/owncloud/ ] || [[ ! ${CURRENT_NEXTCLOUD_VER} =~ ^$nextc echo "Upgrading Nextcloud --- backing up existing installation, configuration, and database to directory to $BACKUP_DIRECTORY..." cp -r /usr/local/lib/owncloud "$BACKUP_DIRECTORY/owncloud-install" fi - if [ -e $STORAGE_ROOT/owncloud/owncloud.db ]; then - cp $STORAGE_ROOT/owncloud/owncloud.db $BACKUP_DIRECTORY + if [ -e "$STORAGE_ROOT/owncloud/owncloud.db" ]; then + cp "$STORAGE_ROOT/owncloud/owncloud.db" "$BACKUP_DIRECTORY" fi - if [ -e $STORAGE_ROOT/owncloud/config.php ]; then - cp $STORAGE_ROOT/owncloud/config.php $BACKUP_DIRECTORY + if [ -e "$STORAGE_ROOT/owncloud/config.php" ]; then + cp "$STORAGE_ROOT/owncloud/config.php" "$BACKUP_DIRECTORY" fi # If ownCloud or Nextcloud was previously installed.... - if [ ! -z ${CURRENT_NEXTCLOUD_VER} ]; then + if [ ! -z "${CURRENT_NEXTCLOUD_VER}" ]; then # Database migrations from ownCloud are no longer possible because ownCloud cannot be run under # PHP 7. - if [ -e $STORAGE_ROOT/owncloud/config.php ]; then + if [ -e "$STORAGE_ROOT/owncloud/config.php" ]; then # Remove the read-onlyness of the config, which is needed for migrations, especially for v24 - sed -i -e '/config_is_read_only/d' $STORAGE_ROOT/owncloud/config.php + sed -i -e '/config_is_read_only/d' "$STORAGE_ROOT/owncloud/config.php" fi if [[ ${CURRENT_NEXTCLOUD_VER} =~ ^[89] ]]; then @@ -220,13 +220,13 @@ fi # Setup Nextcloud if the Nextcloud database does not yet exist. Running setup when # the database does exist wipes the database and user data. -if [ ! -f $STORAGE_ROOT/owncloud/owncloud.db ]; then +if [ ! -f "$STORAGE_ROOT/owncloud/owncloud.db" ]; then # Create user data directory - mkdir -p $STORAGE_ROOT/owncloud + mkdir -p "$STORAGE_ROOT/owncloud" # Create an initial configuration file. - instanceid=oc$(echo $PRIMARY_HOSTNAME | sha1sum | fold -w 10 | head -n 1) - cat > $STORAGE_ROOT/owncloud/config.php < "$STORAGE_ROOT/owncloud/config.php" < '$STORAGE_ROOT/owncloud', @@ -279,7 +279,7 @@ EOF EOF # Set permissions - chown -R www-data:www-data $STORAGE_ROOT/owncloud /usr/local/lib/owncloud + chown -R www-data:www-data "$STORAGE_ROOT/owncloud" /usr/local/lib/owncloud # Execute Nextcloud's setup step, which creates the Nextcloud sqlite database. # It also wipes it if it exists. And it updates config.php with database @@ -300,7 +300,7 @@ fi # Use PHP to read the settings file, modify it, and write out the new settings array. TIMEZONE=$(cat /etc/timezone) CONFIG_TEMP=$(/bin/mktemp) -php$PHP_VER < $CONFIG_TEMP && mv $CONFIG_TEMP $STORAGE_ROOT/owncloud/config.php; +php$PHP_VER < "$CONFIG_TEMP" && mv "$CONFIG_TEMP" "$STORAGE_ROOT/owncloud/config.php"; EOF -chown www-data:www-data $STORAGE_ROOT/owncloud/config.php +chown www-data:www-data "$STORAGE_ROOT/owncloud/config.php" # Enable/disable apps. Note that this must be done after the Nextcloud setup. # The firstrunwizard gave Josh all sorts of problems, so disabling that. @@ -378,7 +378,7 @@ tools/editconf.py /etc/php/$PHP_VER/cli/conf.d/10-opcache.ini -c ';' \ # This version was probably in use in Mail-in-a-Box v0.41 (February 26, 2019) and earlier. # We moved to v0.6.3 in 193763f8. Ignore errors - maybe there are duplicated users with the # correct backend already. -sqlite3 $STORAGE_ROOT/owncloud/owncloud.db "UPDATE oc_users_external SET backend='127.0.0.1';" || /bin/true +sqlite3 "$STORAGE_ROOT/owncloud/owncloud.db" "UPDATE oc_users_external SET backend='127.0.0.1';" || /bin/true # Set up a general cron job for Nextcloud. # Also add another job for Calendar updates, per advice in the Nextcloud docs @@ -397,7 +397,7 @@ hide_output sudo -u www-data php$PHP_VER -f /usr/local/lib/owncloud/occ config:a # Now set the config to read-only. # Do this only at the very bottom when no further occ commands are needed. -sed -i'' "s/'config_is_read_only'\s*=>\s*false/'config_is_read_only' => true/" $STORAGE_ROOT/owncloud/config.php +sed -i'' "s/'config_is_read_only'\s*=>\s*false/'config_is_read_only' => true/" "$STORAGE_ROOT/owncloud/config.php" # Rotate the nextcloud.log file cat > /etc/logrotate.d/nextcloud </dev/null -chmod -R 660 $STORAGE_ROOT/mail/spamassassin -chmod 770 $STORAGE_ROOT/mail/spamassassin +chmod -R 660 "$STORAGE_ROOT/mail/spamassassin" +chmod 770 "$STORAGE_ROOT/mail/spamassassin" # Initial training? # sa-learn --ham storage/mail/mailboxes/*/*/cur/ diff --git a/setup/ssl.sh b/setup/ssl.sh index 9bd5d539..19a0c048 100755 --- a/setup/ssl.sh +++ b/setup/ssl.sh @@ -26,9 +26,9 @@ source /etc/mailinabox.conf # load global vars # Show a status line if we are going to take any action in this file. if [ ! -f /usr/bin/openssl ] \ - || [ ! -f $STORAGE_ROOT/ssl/ssl_private_key.pem ] \ - || [ ! -f $STORAGE_ROOT/ssl/ssl_certificate.pem ] \ - || [ ! -f $STORAGE_ROOT/ssl/dh2048.pem ]; then + || [ ! -f "$STORAGE_ROOT/ssl/ssl_private_key.pem" ] \ + || [ ! -f "$STORAGE_ROOT/ssl/ssl_certificate.pem" ] \ + || [ ! -f "$STORAGE_ROOT/ssl/dh2048.pem" ]; then echo "Creating initial SSL certificate and perfect forward secrecy Diffie-Hellman parameters..." fi @@ -38,7 +38,7 @@ apt_install openssl # Create a directory to store TLS-related things like "SSL" certificates. -mkdir -p $STORAGE_ROOT/ssl +mkdir -p "$STORAGE_ROOT/ssl" # Generate a new private key. # @@ -60,39 +60,39 @@ mkdir -p $STORAGE_ROOT/ssl # # Since we properly seed /dev/urandom in system.sh we should be fine, but I leave # in the rest of the notes in case that ever changes. -if [ ! -f $STORAGE_ROOT/ssl/ssl_private_key.pem ]; then +if [ ! -f "$STORAGE_ROOT/ssl/ssl_private_key.pem" ]; then # Set the umask so the key file is never world-readable. (umask 077; hide_output \ - openssl genrsa -out $STORAGE_ROOT/ssl/ssl_private_key.pem 2048) + openssl genrsa -out "$STORAGE_ROOT/ssl/ssl_private_key.pem" 2048) fi # Generate a self-signed SSL certificate because things like nginx, dovecot, # etc. won't even start without some certificate in place, and we need nginx # so we can offer the user a control panel to install a better certificate. -if [ ! -f $STORAGE_ROOT/ssl/ssl_certificate.pem ]; then +if [ ! -f "$STORAGE_ROOT/ssl/ssl_certificate.pem" ]; then # Generate a certificate signing request. CSR=/tmp/ssl_cert_sign_req-$$.csr hide_output \ - openssl req -new -key $STORAGE_ROOT/ssl/ssl_private_key.pem -out $CSR \ + openssl req -new -key "$STORAGE_ROOT/ssl/ssl_private_key.pem" -out $CSR \ -sha256 -subj "/CN=$PRIMARY_HOSTNAME" # Generate the self-signed certificate. CERT=$STORAGE_ROOT/ssl/$PRIMARY_HOSTNAME-selfsigned-$(date --rfc-3339=date | sed s/-//g).pem hide_output \ openssl x509 -req -days 365 \ - -in $CSR -signkey $STORAGE_ROOT/ssl/ssl_private_key.pem -out $CERT + -in $CSR -signkey "$STORAGE_ROOT/ssl/ssl_private_key.pem" -out "$CERT" # Delete the certificate signing request because it has no other purpose. rm -f $CSR # Symlink the certificate into the system certificate path, so system services # can find it. - ln -s $CERT $STORAGE_ROOT/ssl/ssl_certificate.pem + ln -s "$CERT" "$STORAGE_ROOT/ssl/ssl_certificate.pem" fi # Generate some Diffie-Hellman cipher bits. # openssl's default bit length for this is 1024 bits, but we'll create # 2048 bits of bits per the latest recommendations. -if [ ! -f $STORAGE_ROOT/ssl/dh2048.pem ]; then - openssl dhparam -out $STORAGE_ROOT/ssl/dh2048.pem 2048 +if [ ! -f "$STORAGE_ROOT/ssl/dh2048.pem" ]; then + openssl dhparam -out "$STORAGE_ROOT/ssl/dh2048.pem" 2048 fi diff --git a/setup/start.sh b/setup/start.sh index 3abb4fe3..2a977340 100755 --- a/setup/start.sh +++ b/setup/start.sh @@ -75,17 +75,17 @@ fi # migration (schema) number for the files stored there, assume this is a fresh # installation to that directory and write the file to contain the current # migration number for this version of Mail-in-a-Box. -if ! id -u $STORAGE_USER >/dev/null 2>&1; then - useradd -m $STORAGE_USER +if ! id -u "$STORAGE_USER" >/dev/null 2>&1; then + useradd -m "$STORAGE_USER" fi -if [ ! -d $STORAGE_ROOT ]; then - mkdir -p $STORAGE_ROOT +if [ ! -d "$STORAGE_ROOT" ]; then + mkdir -p "$STORAGE_ROOT" fi f=$STORAGE_ROOT while [[ $f != / ]]; do chmod a+rx "$f"; f=$(dirname "$f"); done; -if [ ! -f $STORAGE_ROOT/mailinabox.version ]; then - setup/migrate.py --current > $STORAGE_ROOT/mailinabox.version - chown $STORAGE_USER:$STORAGE_USER $STORAGE_ROOT/mailinabox.version +if [ ! -f "$STORAGE_ROOT/mailinabox.version" ]; then + setup/migrate.py --current > "$STORAGE_ROOT/mailinabox.version" + chown "$STORAGE_USER:$STORAGE_USER" "$STORAGE_ROOT/mailinabox.version" fi # Save the global options in /etc/mailinabox.conf so that standalone @@ -142,14 +142,14 @@ source setup/firstuser.sh # We'd let certbot ask the user interactively, but when this script is # run in the recommended curl-pipe-to-bash method there is no TTY and # certbot will fail if it tries to ask. -if [ ! -d $STORAGE_ROOT/ssl/lets_encrypt/accounts/acme-v02.api.letsencrypt.org/ ]; then +if [ ! -d "$STORAGE_ROOT/ssl/lets_encrypt/accounts/acme-v02.api.letsencrypt.org/" ]; then echo echo "-----------------------------------------------" echo "Mail-in-a-Box uses Let's Encrypt to provision free SSL/TLS certificates" echo "to enable HTTPS connections to your box. We're automatically" echo "agreeing you to their subscriber agreement. See https://letsencrypt.org." echo -certbot register --register-unsafely-without-email --agree-tos --config-dir $STORAGE_ROOT/ssl/lets_encrypt +certbot register --register-unsafely-without-email --agree-tos --config-dir "$STORAGE_ROOT/ssl/lets_encrypt" fi # Done. @@ -162,19 +162,19 @@ echo Please log in to the control panel for further instructions at: echo if management/status_checks.py --check-primary-hostname; then # Show the nice URL if it appears to be resolving and has a valid certificate. - echo https://$PRIMARY_HOSTNAME/admin + echo "https://$PRIMARY_HOSTNAME/admin" echo echo "If you have a DNS problem put the box's IP address in the URL" echo "(https://$PUBLIC_IP/admin) but then check the TLS fingerprint:" - openssl x509 -in $STORAGE_ROOT/ssl/ssl_certificate.pem -noout -fingerprint -sha256\ + openssl x509 -in "$STORAGE_ROOT/ssl/ssl_certificate.pem" -noout -fingerprint -sha256\ | sed "s/SHA256 Fingerprint=//i" else - echo https://$PUBLIC_IP/admin + echo "https://$PUBLIC_IP/admin" echo echo You will be alerted that the website has an invalid certificate. Check that echo the certificate fingerprint matches: echo - openssl x509 -in $STORAGE_ROOT/ssl/ssl_certificate.pem -noout -fingerprint -sha256\ + openssl x509 -in "$STORAGE_ROOT/ssl/ssl_certificate.pem" -noout -fingerprint -sha256\ | sed "s/SHA256 Fingerprint=//i" echo echo Then you can confirm the security exception and continue. diff --git a/setup/system.sh b/setup/system.sh index 216c2cd8..b4d1ae27 100755 --- a/setup/system.sh +++ b/setup/system.sh @@ -11,8 +11,8 @@ source setup/functions.sh # load our functions # # First set the hostname in the configuration file, then activate the setting -echo $PRIMARY_HOSTNAME > /etc/hostname -hostname $PRIMARY_HOSTNAME +echo "$PRIMARY_HOSTNAME" > /etc/hostname +hostname "$PRIMARY_HOSTNAME" # ### Fix permissions @@ -53,8 +53,8 @@ if [ -z "$SWAP_IN_FSTAB" ] && [ ! -e /swapfile ] && [ -z "$ROOT_IS_BTRFS" ] && - [ $TOTAL_PHYSICAL_MEM -lt 1900000 ] && - [ $AVAILABLE_DISK_SPACE -gt 5242880 ] + [ "$TOTAL_PHYSICAL_MEM" -lt 1900000 ] && + [ "$AVAILABLE_DISK_SPACE" -gt 5242880 ] then echo "Adding a swap file to the system..." @@ -164,7 +164,7 @@ fi # not likely the user will want to change this, so we only ask on first # setup. if [ -z "${NONINTERACTIVE:-}" ]; then - if [ ! -f /etc/timezone ] || [ ! -z ${FIRST_TIME_SETUP:-} ]; then + if [ ! -f /etc/timezone ] || [ ! -z "${FIRST_TIME_SETUP:-}" ]; then # If the file is missing or this is the user's first time running # Mail-in-a-Box setup, run the interactive timezone configuration # tool. @@ -273,8 +273,8 @@ if [ -z "${DISABLE_FIREWALL:-}" ]; then if [ ! -z "$SSH_PORT" ]; then if [ "$SSH_PORT" != "22" ]; then - echo Opening alternate SSH port $SSH_PORT. #NODOC - ufw_limit $SSH_PORT #NODOC + echo Opening alternate SSH port "$SSH_PORT". #NODOC + ufw_limit "$SSH_PORT" #NODOC fi fi diff --git a/setup/web.sh b/setup/web.sh index 392b6d92..8017df90 100755 --- a/setup/web.sh +++ b/setup/web.sh @@ -62,7 +62,7 @@ tools/editconf.py /etc/php/$PHP_VER/fpm/pool.d/www.conf -c ';' \ # Some synchronisation issues can occur when many people access the site at once. # The pm=ondemand setting is used for memory constrained machines < 2GB, this is copied over from PR: 1216 TOTAL_PHYSICAL_MEM=$(head -n 1 /proc/meminfo | awk '{print $2}' || /bin/true) -if [ $TOTAL_PHYSICAL_MEM -lt 1000000 ] +if [ "$TOTAL_PHYSICAL_MEM" -lt 1000000 ] then tools/editconf.py /etc/php/$PHP_VER/fpm/pool.d/www.conf -c ';' \ pm=ondemand \ @@ -70,7 +70,7 @@ then pm.start_servers=2 \ pm.min_spare_servers=1 \ pm.max_spare_servers=3 -elif [ $TOTAL_PHYSICAL_MEM -lt 2000000 ] +elif [ "$TOTAL_PHYSICAL_MEM" -lt 2000000 ] then tools/editconf.py /etc/php/$PHP_VER/fpm/pool.d/www.conf -c ';' \ pm=ondemand \ @@ -78,7 +78,7 @@ then pm.start_servers=4 \ pm.min_spare_servers=1 \ pm.max_spare_servers=6 -elif [ $TOTAL_PHYSICAL_MEM -lt 3000000 ] +elif [ "$TOTAL_PHYSICAL_MEM" -lt 3000000 ] then tools/editconf.py /etc/php/$PHP_VER/fpm/pool.d/www.conf -c ';' \ pm=dynamic \ @@ -138,12 +138,12 @@ cat conf/mta-sts.txt \ chmod a+r /var/lib/mailinabox/mta-sts.txt # make a default homepage -if [ -d $STORAGE_ROOT/www/static ]; then mv $STORAGE_ROOT/www/static $STORAGE_ROOT/www/default; fi # migration #NODOC -mkdir -p $STORAGE_ROOT/www/default -if [ ! -f $STORAGE_ROOT/www/default/index.html ]; then - cp conf/www_default.html $STORAGE_ROOT/www/default/index.html +if [ -d "$STORAGE_ROOT/www/static" ]; then mv "$STORAGE_ROOT/www/static" "$STORAGE_ROOT/www/default"; fi # migration #NODOC +mkdir -p "$STORAGE_ROOT/www/default" +if [ ! -f "$STORAGE_ROOT/www/default/index.html" ]; then + cp conf/www_default.html "$STORAGE_ROOT/www/default/index.html" fi -chown -R $STORAGE_USER $STORAGE_ROOT/www +chown -R "$STORAGE_USER" "$STORAGE_ROOT/www" # Start services. restart_service nginx diff --git a/setup/webmail.sh b/setup/webmail.sh index 62d18c86..41e611c3 100755 --- a/setup/webmail.sh +++ b/setup/webmail.sh @@ -170,8 +170,8 @@ cat > ${RCM_PLUGIN_DIR}/carddav/config.inc.php <