diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0ad064d2..4395f6e2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,7 +24,9 @@ jobs: - name: Setup Bats run: git submodule update --init --recursive - name: bats test - run: ./test/bats/bin/bats test + run: | + ./test/bats/bin/bats test/*.bats + ./test/bats/bin/bats test/include/*.bats freebsd: if: false diff --git a/.shellcheckrc b/.shellcheckrc index 52a79c4d..055ac164 100644 --- a/.shellcheckrc +++ b/.shellcheckrc @@ -1 +1 @@ -disable=SC1004,SC1091,SC2009,SC2016,SC2039,SC2086,SC2119,SC2120,SC2153,SC2154,SC3033,SC3043 \ No newline at end of file +disable=1004,1091,2009,2016,2039,2086,2119,2120,2153,2154,3033,3037,3043 \ No newline at end of file diff --git a/include/editor.sh b/include/editor.sh index 79d2b046..5f82432f 100755 --- a/include/editor.sh +++ b/include/editor.sh @@ -72,7 +72,7 @@ configure_editor() { local _base=${1:-""} - case "$TOASTER_EDITOR" in + case "$TOASTER_EDITOR_PORT" in neovim) configure_neovim ;; diff --git a/include/mua.sh b/include/mua.sh old mode 100644 new mode 100755 index 9f80b430..8ca7556d --- a/include/mua.sh +++ b/include/mua.sh @@ -1,5 +1,8 @@ #!/bin/sh +set -e + +# shellcheck disable=3003 test_imap_empty() { pkg info | grep -q ^empty || pkg install -y empty @@ -40,7 +43,8 @@ EOF test_imap_curl() { # shellcheck disable=SC2001 - curl -k -v --login-options 'AUTH=PLAIN' "imaps://$(echo $MUA_TEST_USER | sed -e 's/@/%40/'):${MUA_TEST_PASS}@${MUA_TEST_HOST}/" + curl -k -v --login-options 'AUTH=PLAIN' \ + "imaps://$(uriencode $MUA_TEST_USER):$(uriencode MUA_TEST_PASS)@${MUA_TEST_HOST}/" } test_imap() @@ -51,6 +55,7 @@ test_imap() # test_imap_empty } +# shellcheck disable=3003 test_pop3_empty() { pkg info | grep -q ^empty || pkg install -y empty @@ -77,5 +82,25 @@ test_pop3_empty() test_pop3() { # shellcheck disable=SC2001 - curl -k -v --login-options 'AUTH=PLAIN' "pop3s://$(echo $MUA_TEST_USER | sed -e 's/@/%40/'):${MUA_TEST_PASS}@${MUA_TEST_HOST}/" -} \ No newline at end of file + curl -k -v --login-options 'AUTH=PLAIN' \ + "pop3s://$(uriencode $MUA_TEST_USER):$(uriencode MUA_TEST_PASS)@${MUA_TEST_HOST}/" +} + +# https://stackoverflow.com/questions/296536/how-to-urlencode-data-for-curl-command +# shellcheck disable=3005,3018,3024,3045,3057 +uriencode() { + local string="${1}" + local strlen=${#string} + local encoded="" + local pos c o + + for (( pos=0 ; pos> "$1/root/.profile" + echo 'if [ -n "$BASH" ] && [ -r ~/.bashrc ]; then . ~/.bashrc; fi' >> "$1/root/.profile" + fi + + if [ ! -e "$1/root/.bashrc" ]; then + tell_status "creating $1/root/.bashrc" + cat <<'EO_BASH_RC' > "$1/root/.bashrc" -export EDITOR="vim" -export BLOCKSIZE=K; export HISTSIZE=10000 export HISTCONTROL=ignoredups:erasedups export HISTIGNORE="&:[bf]g:exit" + shopt -s histappend shopt -s cdspell -alias h="history 200" -alias ll="ls -alFG" -EO_BASH_PROFILE - if ! grep -qs profile "$1"; then - tee -a "$1" < "$_f" + cat < "$_f" +export EDITOR="$TOASTER_EDITOR" +export BLOCKSIZE=K; + alias h='fc -l' -alias m=$PAGER +alias m=\$PAGER +alias ls="ls -FG" alias ll="ls -alFG" alias g='egrep -i' +#alias df="df -h -tnodevfs,procfs,nullfs,tmpfs" -PS1="$(whoami)@$(hostname -s):\\w " -case $(id -u) in - 0) PS1="${PS1}# ";; - *) PS1="${PS1}$ ";; +# set prompt for bourne shell (/bin/sh) +PS1="\$(whoami)@\$(hostname -s):\\w " +case \$(id -u) in + 0) PS1="\${PS1}# ";; + *) PS1="\${PS1}\$ ";; esac jexecl() { - if [ -z "$1" ]; then /usr/sbin/jexec; - elif [ -n "$2" ]; then /usr/sbin/jexec ${@:1}; - else /usr/sbin/jexec $1 login -f -h $(hostname) root; + if [ -z "\$1" ]; then /usr/sbin/jexec; + elif [ -n "\$2" ]; then /usr/sbin/jexec \${@:1}; + else /usr/sbin/jexec \$1 login -f -h $(hostname) root; fi } EO_BOURNE_SHELL @@ -91,18 +113,18 @@ configure_csh_shell() fi tell_status "configure C shell" - cat <<'EO_CSHRC' > "$_cshrc" + cat < "$_cshrc" alias h history 25 alias j jobs -l alias la ls -aF alias lf ls -FA alias ll ls -lAFG -setenv EDITOR vi +setenv EDITOR $TOASTER_EDITOR setenv PAGER less setenv BLOCKSIZE K -if ($?prompt) then +if (\$?prompt) then # An interactive shell -- set some stuff up set prompt = "%N@%m:%~ %# " set promptchars = "%#" @@ -114,7 +136,7 @@ if ($?prompt) then # Use history to aid expansion set autoexpand set autorehash - if ( $?tcsh ) then + if ( \$?tcsh ) then bindkey "^W" backward-delete-word bindkey -k up history-search-backward bindkey -k down history-search-forward diff --git a/mail-toaster.sh b/mail-toaster.sh index c021441e..9bb74914 100755 --- a/mail-toaster.sh +++ b/mail-toaster.sh @@ -75,7 +75,8 @@ export JAIL_NET6="$(get_random_ip6net)" export ZFS_VOL="zroot" export ZFS_JAIL_MNT="/jails" export ZFS_DATA_MNT="/data" -export TOASTER_EDITOR="vim-tiny" +export TOASTER_EDITOR="vim" +export TOASTER_EDITOR_PORT="vim-tiny" export TOASTER_MSA="haraka" export TOASTER_MYSQL="1" export TOASTER_MYSQL_PASS="" @@ -172,7 +173,8 @@ export TLS_LIBRARY=${TLS_LIBRARY:=""} export TOASTER_BASE_MTA=${TOASTER_BASE_MTA:=""} export TOASTER_BASE_PKGS=${TOASTER_BASE_PKGS:="pkg ca_root_nss"} export TOASTER_BUILD_DEBUG=${TOASTER_BUILD_DEBUG:="0"} -export TOASTER_EDITOR=${TOASTER_EDITOR:="vim-tiny"} +export TOASTER_EDITOR=${TOASTER_EDITOR:="vim"} +export TOASTER_EDITOR_PORT=${TOASTER_EDITOR_PORT:="vim-tiny"} # See https://github.com/msimerson/Mail-Toaster-6/wiki/MySQL export TOASTER_MYSQL=${TOASTER_MYSQL:="1"} export TOASTER_MARIADB=${TOASTER_MARIADB:="0"} @@ -674,6 +676,7 @@ create_staged_fs() assure_ip6_addr_is_declared "$1" stage_resolv_conf + echo "MASQUERADE $1@$TOASTER_MAIL_DOMAIN" >> "$STAGE_MNT/etc/dma/dma.conf" zfs_create_fs "$ZFS_DATA_VOL/$1" "$ZFS_DATA_MNT/$1" install_fstab $1 @@ -1388,6 +1391,7 @@ store_exec() chmod 755 "$1" } +# shellcheck disable=3044,3018 onexit() { while caller $((n++)); do :; done; } if [ "$TOASTER_BUILD_DEBUG" = "1" ]; then diff --git a/provision/dcc.sh b/provision/dcc.sh index 3e7411be..6b307677 100755 --- a/provision/dcc.sh +++ b/provision/dcc.sh @@ -55,7 +55,8 @@ configure_dcc() _pf_etc="$ZFS_DATA_MNT/dcc/etc/pf.conf.d" store_config "$_pf_etc/allow.conf" < { \$ext_ip4 \$ext_ip6 $(get_jail_ip dcc) $(get_jail_ip6 dcc) } +table { $(get_jail_ip dcc), $(get_jail_ip6 dcc) } +pass in quick proto udp from any port 6277 to pass in quick proto udp from any port 6277 to EO_PF_ALLOW diff --git a/provision/dovecot.sh b/provision/dovecot.sh index 52e1e41a..f74c79a5 100755 --- a/provision/dovecot.sh +++ b/provision/dovecot.sh @@ -541,7 +541,7 @@ rdr inet proto tcp from to port { 110 143 } -> $int_ip rdr inet6 proto tcp from to port { 110 143 } -> $int_ip6 EO_PF_RDR - store_config "$_pf_etc/allow.conf" < port { 993 995 } pass in quick proto tcp from any to port { 993 995 } pass in quick proto tcp from to port { 110 143 } -EO_PF_RDR +EO_PF_ALLOW } configure_dovecot() diff --git a/provision/haraka.sh b/provision/haraka.sh index 0b92e2dc..2833c390 100755 --- a/provision/haraka.sh +++ b/provision/haraka.sh @@ -565,7 +565,6 @@ configure_haraka_helo() tee "$HARAKA_CONF/helo.checks.ini" < "$HARAKA_CONF/loglevel" + # echo 'LOGINFO' > "$HARAKA_CONF/loglevel" if [ ! -f "$HARAKA_CONF/tarpit.timeout" ]; then echo '3' > "$HARAKA_CONF/tarpit.timeout" fi @@ -749,7 +748,7 @@ start_haraka() "$STAGE_MNT/usr/local/etc/rc.d/haraka" chmod 555 "$STAGE_MNT/usr/local/etc/rc.d/haraka" stage_sysrc haraka_enable=YES - sysrc -f "$STAGE_MNT/etc/rc.conf" haraka_flags='-c /data' + stage_sysrc haraka_flags='-c /data' if [ ! -d "$HARAKA_CONF/queue" ]; then mkdir -p "$HARAKA_CONF/queue" diff --git a/provision/host.sh b/provision/host.sh index 758f02e0..0480533f 100755 --- a/provision/host.sh +++ b/provision/host.sh @@ -258,12 +258,10 @@ configure_tls_certs() configure_dhparams() { local DHP="/etc/ssl/dhparam.pem" - if [ -f "$DHP" ]; then - return + if [ ! -f "$DHP" ]; then + tell_status "Generating a 2048 bit dhparams file" + openssl dhparam -out "$DHP" 2048 fi - - tell_status "Generating a 2048 bit dhparams file" - openssl dhparam -out "$DHP" 2048 } install_sshguard() @@ -280,20 +278,13 @@ install_sshguard() sed -i.bak \ -e '/sshg-fw-null/ s/^B/#B/' \ -e '/sshg-fw-pf/ s/^#//' \ - /usr/local/etc/sshguard.conf + /usr/local/etc/sshguard.conf tell_status "starting sshguard" sysrc sshguard_enable=YES service sshguard start } -check_timezone() -{ - if [ ! -e "/etc/localtime" ]; then - tzsetup - fi -} - check_global_listeners() { tell_status "checking for host listeners on all IPs" @@ -303,7 +294,6 @@ check_global_listeners() if [ -t 0 ]; then exit 2; fi echo "Not interactive, continuing anyway." - return fi } @@ -400,74 +390,25 @@ install_jailmanage() chmod 755 /usr/local/bin/jailmanage } -set_jail_start_order() +enable_jails() { - if grep -q ^jail_list /etc/rc.conf; then - tell_status "preserving jail order" - return - fi -} + tell_status "enabling jails" + sysrc jail_enable=YES -jail_reverse_shutdown() -{ - local _fbsd_major; _fbsd_major=$(freebsd-version | cut -f1 -d'.') - if [ "$_fbsd_major" -ge 11 ]; then - if grep -q jail_reverse_stop /etc/rc.conf; then - return - fi + if ! grep -q jail_reverse_stop /etc/rc.conf; then tell_status "reverse jails when shutting down" sysrc jail_reverse_stop=YES - return fi - if grep -q _rev_jail_list /etc/rc.d/jail; then - echo "rc.d/jail is already patched" - return + if grep -q ^jail_list /etc/rc.conf; then + tell_status "preserving jail order" fi - tell_status "patching jail so shutdown reverses jail order" - patch -d / <<'EO_JAIL_RCD' -Index: etc/rc.d/jail -=================================================================== ---- etc/rc.d/jail -+++ etc/rc.d/jail -@@ -516,7 +516,10 @@ - command=$jail_program - rc_flags=$jail_flags - command_args="-f $jail_conf -r" -- $jail_jls name | while read _j; do -+ for _j in $($jail_jls name); do -+ _rev_jail_list="${_j} ${_rev_jail_list}" -+ done -+ for _j in ${_rev_jail_list}; do - echo -n " $_j" - _tmp=`mktemp -t jail` || exit 3 - $command $rc_flags $command_args $_j >> $_tmp 2>&1 -@@ -532,6 +535,9 @@ - ;; - esac - for _j in $@; do -+ _rev_jail_list="${_j} ${_rev_jail_list}" -+ done -+ for _j in ${_rev_jail_list}; do - _j=$(echo $_j | tr /. _) - parse_options $_j || continue - if ! $jail_jls -j $_j > /dev/null 2>&1; then -EO_JAIL_RCD -} - -enable_jails() -{ - sysrc jail_enable=YES - jail_reverse_shutdown - set_jail_start_order - if [ -d /etc/jail.conf.d ]; then add_jail_conf stage - return + else + grep -sq 'exec' /etc/jail.conf || jail_conf_header fi - - grep -sq 'exec' /etc/jail.conf || jail_conf_header } update_ports_tree() @@ -586,7 +527,7 @@ update_mt6() } update_host() { - sysrc background_fsck=NO + sysrc -q background_fsck=NO update_mt6 update_freebsd configure_pkg_latest "" @@ -607,7 +548,7 @@ update_host() { configure_etc_hosts configure_csh_shell "" configure_bourne_shell "" - check_timezone + if [ ! -e "/etc/localtime" ]; then tzsetup; fi check_global_listeners echo; echo "Success! Your host is ready to install Mail Toaster 6!"; echo } diff --git a/provision/wildduck.sh b/provision/wildduck.sh index e76f42b0..6b0728be 100755 --- a/provision/wildduck.sh +++ b/provision/wildduck.sh @@ -60,8 +60,8 @@ configure_pf() int_ip4 = "$(get_jail_ip wildduck)" int_ip6 = "$(get_jail_ip6 wildduck)" -rdr inet proto tcp from any to port { 3000 9993 9995 } -> $int_ip4 -rdr inet6 proto tcp from any to port { 3000 9993 9995 } -> $int_ip6 +rdr inet proto tcp from any to port { 993 995 } -> \$int_ip4 +rdr inet6 proto tcp from any to port { 993 995 } -> \$int_ip6 EO_PF_RDR store_config "$_pf_etc/allow.conf" < persist { \$int_ip4, \$int_ip6 } -pass in quick proto tcp from any to port { 3000 9993 9995 } -pass in quick proto tcp from any to port { 3000 9993 9995 } +pass in quick proto tcp from any to port { 3000 993 995 } +pass in quick proto tcp from any to port { 3000 993 995 } EO_PF_ALLOW } diff --git a/test/get_jail_ip.sh b/test/get_jail_ip.sh deleted file mode 100755 index c7924c78..00000000 --- a/test/get_jail_ip.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/sh - -. mail-toaster.sh || . ../mail-toaster.sh - - -IP=$(get_jail_ip mysql) -if [ "$IP" = "172.16.15.4" ]; then - echo "mysql IP is $IP" -else - echo "ERR: default mysql IP is not $IP" - exit 2 -fi - -IP=$(get_jail_ip haraka) -if [ "$IP" = "172.16.15.9" ]; then - echo "haraka IP is $IP" -else - echo "ERR: haraka IP is not $IP" - exit 2 -fi - -exit 0 \ No newline at end of file diff --git a/test/include.bats b/test/include.bats index a2c13927..571e6478 100644 --- a/test/include.bats +++ b/test/include.bats @@ -1,7 +1,7 @@ setup() { - load 'test_helper/bats-support/load' - load 'test_helper/bats-assert/load' + load './test_helper/bats-support/load' + load './test_helper/bats-assert/load' } @test "./include/djb.sh" { diff --git a/test/include/mua.bats b/test/include/mua.bats new file mode 100644 index 00000000..70ea909a --- /dev/null +++ b/test/include/mua.bats @@ -0,0 +1,36 @@ + +setup() { + load '../test_helper/bats-support/load' + load '../test_helper/bats-assert/load' + load ../../include/mua.sh +} + +@test "include/mua.sh" { + skip "works locally, doesn't in GHA" + run ./include/mua.sh + assert_success +} + +@test "uriencode @" { + run uriencode @ + assert_success + assert_output "%40" +} + +@test "uriencode [space]" { + run uriencode " " + assert_success + assert_output "%20" +} + +@test "uriencode '" { + run uriencode "'" + assert_success + assert_output "%27" +} + +@test "uriencode )" { + run uriencode ")" + assert_success + assert_output "%29" +} diff --git a/test/mail-toaster.bats b/test/mail-toaster.bats index 21e80ce1..a965f0f2 100644 --- a/test/mail-toaster.bats +++ b/test/mail-toaster.bats @@ -59,28 +59,40 @@ setup() { @test "get_random_pass 20" { run get_random_pass 20 - echo "# $output" >&3 + #echo "# $output" >&3 assert_success assert_equal ${#output} 20 } @test "get_random_pass (defaults)" { run get_random_pass - echo "# $output" >&3 + #echo "# $output" >&3 assert_success assert_equal ${#output} 14 } @test "get_random_pass 14 strong" { run get_random_pass 14 strong - echo "# $output" >&3 + #echo "# $output" >&3 assert_success #assert_equal ${#output} 14 } @test "get_random_pass 14 safe" { run get_random_pass 14 safe - echo "# $output" >&3 + #echo "# $output" >&3 assert_success #assert_equal ${#output} 14 } + +@test "get_jail_ip mysql" { + run get_jail_ip mysql + assert_success + assert_output "172.16.15.4" +} + +@test "get_jail_ip haraka" { + run get_jail_ip haraka + assert_success + assert_output "172.16.15.9" +} diff --git a/test/run.sh b/test/run.sh new file mode 100755 index 00000000..3526907c --- /dev/null +++ b/test/run.sh @@ -0,0 +1,13 @@ +#!/bin/sh + +echo "shellcheck *.sh" +shellcheck ./*.sh + +echo "shellcheck provision/*.sh" +shellcheck provision/*.sh + +echo "shellcheck include/*.sh" +shellcheck include/*.sh + +bats test/*.bats +bats test/include/*.bats