HEX
Server: Apache/2.2.34 (Unix) mod_fastcgi/mod_fastcgi-SNAP-0910052141
System: Linux Kou-Etsu-Dou 4.4.59+ #25556 SMP PREEMPT Thu Mar 4 18:03:46 CST 2021 x86_64
User: hosam (1026)
PHP: 7.2.29
Disabled: NONE
Upload Files
File: //volume1/@appstore/MailPlus-Server/backend_hook/hookUtils.conf
#!/bin/bash

[ ! -z ${MAILPLUS_SERVER_LOG_UTIL+MAILPLUS_SERVER_LOG_DEFINED} ] || . /var/packages/MailPlus-Server/target/scripts/MailPlusServerLogUtil.sh

PACKAGE_NAME="MailPlus-Server"
PRIVATE_LOCATION="/var/packages/${PACKAGE_NAME}/target"
VOLUME=$(/usr/bin/readlink ${PRIVATE_LOCATION} | /usr/bin/cut -d '/' -f2)
CONF_TEMPLATE_DIR="${PRIVATE_LOCATION}/etc/template"
MAILPLUS_SERVER_BACKEND_BINARY="${PRIVATE_LOCATION}/bin/syno_mailserver_backend"
HAPROXY_BINARY="${PRIVATE_LOCATION}/sbin/haproxy"
CONFDEST_OUTPUT_DIR="/var/packages/MailPlus-Server/etc/mailconf.d/"
CONFDEST_OUTPUT_DIR_BAK="/var/packages/MailPlus-Server/etc/mailconf.d_bak/"
BACKEND_BINARY="${PRIVATE_LOCATION}/usr/bin/syno-mailplus-server-go-utils"

CALLBACK_BINARY="${PRIVATE_LOCATION}/bin/syno_action"
SET_CONF_BINARY="${PRIVATE_LOCATION}/bin/syno_set_config"

## Mail storage
MAIL_STORAGE_DIR_PATH="/var/spool/mail"
MAIL_STORAGE_DIR_PATH_BAK="/var/packages/${PACKAGE_NAME}/etc/MailDirBak"

DOVEADM_BINARY="${PRIVATE_LOCATION}/bin/doveadm"
DOVECOT_SCRIPT="${PRIVATE_LOCATION}/scripts/daemon/dovecot.sh"
POSTFIX_SCRIPT="/var/packages/${PACKAGE_NAME}/target/scripts/daemon/postfix.sh"
FIREWALL_REFRESH_FLAG="/tmp/.mailplus_server_firewall_refresh"
CURL_BACKEND_OPT="-s ${CURL_TIMEOUT} --cacert /var/packages/MailPlus-Server/etc/internal-ca-ssl/ca.crt --cert /var/packages/MailPlus-Server/etc/internal-ssl/client.crt --key /var/packages/MailPlus-Server/etc/internal-ssl/client.key"
BACKEND_IP="127.0.0.1"
BACKEND_PORT="8500"
BACKEND_PEER_PORT="8501"

SPOOL_MAILPLUS=/var/spool/@MailPlus-Server
SPOOL_MAILSCANNER=${SPOOL_MAILPLUS}/MailScanner
MAIL_SHARE_NAME="MailPlus"
SPAM_ACCOUNT="e14dd245-5d25-41b1-95da-2d1ee815cb89"

MAILPLUS_TMP_PRE_BUILD_DIR_LIST="/run/lock/mailplus_server /run/mailplus_server /run/mailplus_server/mimedefang /tmp/mailplus_server /tmp/mailplus_server/service_status /tmp/mailplus_server/service_status_db"
TMP_MAILPLUS_SERVER_DIR="/tmp/mailplus_server"
SCRIPT_LOCK_WAIT_DIR="/tmp/mailplus_server/script_lock_wait"


IPV4_REGEXP="^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"

containString()
{
	local substr=$1
	local str=$2

	if [ "${str}" == "" ]; then
		return 1
	fi

    [ -z "${str##*"$substr"*}" ]
}
getHostID()
{
	${MAILPLUS_SERVER_BACKEND_BINARY} --getHostID
}
getHostIP()
{
	${MAILPLUS_SERVER_BACKEND_BINARY} --getHostIP
}
getHostIF()
{
	${MAILPLUS_SERVER_BACKEND_BINARY} --getHostIF
}

getLockFullName()
{
	if [ -n "$1" ]; then
		echo "script_lock/$1"
	else
		echo "script_lock/common_lock"
	fi
}
getLockWaitingkDir()
{
	if [ -n "$1" ]; then
		echo "${SCRIPT_LOCK_WAIT_DIR}/$1"
	else
		echo "${SCRIPT_LOCK_WAIT_DIR}/common_lock"
	fi
}
getLockWaitingKey()
{
	echo "$$"
}
shouldWaitingLock() {
	local lockWaitingDir=$1
	local lockWaitingName=$2
	local lockWaitingKeys=
	local oldestPid=

	# if the directory does not exist, we do not waiting at all
	if [ ! -d "${TMP_MAILPLUS_SERVER_DIR}" ]; then
		debug_log "tmp dir does not exist, skip waiting check"
		return 1
	fi

	mkdir -p "${lockWaitingDir}"
	chown "MailPlus-Server:system" "${SCRIPT_LOCK_WAIT_DIR}"

	if ! ( ls "${lockWaitingDir}/${lockWaitingName}" || \
		cat "/proc/$$/cmdline" > "${lockWaitingDir}/${lockWaitingName}"); then
		err_log "failed to create lock waiting key [${lockWaitingName}]"
		return 0
	fi

	if ! lockWaitingKeys=$(ls -tr "${lockWaitingDir}"); then
		err_log "failed to list lock waiting keys"
		return 0
	fi

	for key in ${lockWaitingKeys}
	do
		if [ ! -d "/proc/${key}" ] || [ "$(cat /proc/$$/cmdline)" != "$(cat ${lockWaitingDir}/${key})" ]; then
			rm -f "${lockWaitingDir}/${key}"
			continue
		fi
		oldestPid=${key}
		break
	done

	if [ -z "${oldestPid}" -o "$$" = "${oldestPid}" ]; then
		return 1
	fi
	return 0
}
acquireClusterLock()
{
	# acuireClusterLock <lock_name> [ttl]
	local lockName="$(getLockFullName $1)"
	local lockWaitingDir=$(getLockWaitingkDir "$1")
	local lockWaitingName=$(getLockWaitingKey)
	local ttl=0
	if [ -n "$2" ]; then
		ttl="$2"
	fi
	if shouldWaitingLock "${lockWaitingDir}" "${lockWaitingName}"; then
		return 1
	fi

	if ${BACKEND_BINARY} backend-command --command create --key "${lockName}" --value "locked" --ttl "${ttl}"; then
		rm -f "${lockWaitingDir}/${lockWaitingName}" || \
			err_log "failed to remove waiting lock key ${lockWaitingDir}/${lockWaitingName}"
		return 0
	fi
	return 1
}
releaseClusterLock()
{
	# releaseClusterLock <lock_name>
	local lockName="$(getLockFullName $1)"
	local lockWaitingDir=$(getLockWaitingkDir "$1")
	local lockWaitingName=$(getLockWaitingKey)

	${BACKEND_BINARY} backend-command --command del --key "${lockName}" || \
		err_log "failed to remove lock key ${lockName}"
	rm -f "${lockWaitingDir}/${lockWaitingName}"
}
isLoadBalancer()
{
	${MAILPLUS_SERVER_BACKEND_BINARY} --isBalancerMaster
}
getWeight()
{
	local weight_list=$1
	local server=$2
	local serv=""

	for serv in ${weight_list}; do
		id=`echo "${serv}" | cut -d ":" -f1`
		weight=`echo "${serv}" | cut -d ":" -f2`
		ip="$(${MAILPLUS_SERVER_BACKEND_BINARY} --idToIP "${id}")"

		if [ "${server}" = "${ip}" ]; then
			echo "${weight}"
			return
		fi
	done
}
isPrefixKeyChanged()
{
	local changedKey
	local changedKeysArray=(${_MAIL_mailserver_trigger_events})
	for changedKey in "${changedKeysArray[@]}"
	do
		if [[ "${changedKey}" == "${1}"* ]]; then
			return 0
		fi
	done
	return 1
}
isKeyChanged()
{
    local key="$1"
    local changedKey="${_MAIL_mailserver_trigger_events}"
    if containString "${key} " "${changedKey}"; then
        return 0
    else
        return 1
    fi
}
isTreeChanged()
{
    local key=$1
    local changedTree=${_MAIL_mailserver_trigger_tree}

    if containString "${key}" "${changedTree}"; then
        return 0
    else
        return 1
    fi
}
reloadSmtp()
{
	local trigger_keys="$1"

	## Convert syno config
	if ! ${SET_CONF_BINARY} "smtp" "${trigger_keys}"; then
		err_log "failed to set conf smtp"
		return 1
	fi

	## Actions
	if ! ${CALLBACK_BINARY} "smtp" "${trigger_keys}"; then
		err_log "failed to callback smtp"
		return 1
	fi

	return 0
}
imapPop3PortGet()
{
	local servType="$1"

	local imapPort="143"
	local imapsPort="993"
	local pop3Port="110"
	local pop3sPort="995"

	if [ "${servType}" == "imap" ]; then
		echo "${imapPort}"
	elif [ "${servType}" == "imaps" ]; then
		local imapsEnable="$(${MAILPLUS_SERVER_BACKEND_BINARY} --getConfKeyVal "imaps_enabled")"
		if [ "yes" != "${imapsEnable}" ]; then
			imapsPort="0"
		fi
		echo "${imapsPort}"
	elif [ "${servType}" == "pop3" ]; then
		local pop3Enable="$(${MAILPLUS_SERVER_BACKEND_BINARY} --getConfKeyVal "pop3_enabled")"
		if [ "yes" != "${pop3Enable}" ]; then
			pop3Port="0"
		fi
		echo "${pop3Port}"
	elif [ "${servType}" == "pop3s" ]; then
		local pop3sEnable="$(${MAILPLUS_SERVER_BACKEND_BINARY} --getConfKeyVal "pop3s_enabled")"
		if [ "yes" != "${pop3sEnable}" ]; then
			pop3sPort="0"
		fi
		echo "${pop3sPort}"
	fi
}
GenerateInternalCert()
{
	local depot="/tmp/mailplus_server/.deopt"
	local etcdCa="${PRIVATE_LOCATION}/usr/bin/etcd-ca --depot-path $depot"
	## Due to updater may run when package stop and link is not ready so have to use real path
	local caDir="/var/packages/MailPlus-Server/etc/internal-ca-ssl"
	local sslDir="/var/packages/MailPlus-Server/etc/internal-ssl"

	local caCertPath="${caDir}/ca.crt"
	local caKeyPath="${caDir}/ca.key"
	local caInfoPath="${caDir}/ca.crt.info"
	local certPath="${sslDir}/server.crt"
	local keyPath="${sslDir}/server.key"
	local clientCertPath="${sslDir}/client.crt"
	local clientKeyPath="${sslDir}/client.key"

	local passphrase="--passphrase asdf"
	local keyBits=1024
	local certHostname="syno.interanl.ca"
	local certIP="127.0.0.1"

	# location for temporary depot
	rm -rf $depot 2>/dev/null

	oriUmask=$(umask)
	umask 022

	if [ "$1" != "onlyCert" ]; then
		if [ -e ${caCertPath} ]; then
			return
		fi

		mkdir ${caDir} ${sslDir}
		chown MailPlus-Server:MailPlus-Server ${caDir} ${sslDir}

		# create ca
		$etcdCa init --key-bits ${keyBits} $passphrase
		$etcdCa export | tar xvf -
		mv "ca.crt" ${caCertPath}
		mv "ca.key" ${caKeyPath}
		cp "${depot}/ca.crt.info" ${caInfoPath}
		chown MailPlus-Server:MailPlus-Server ${caCertPath} ${caKeyPath} ${caInfoPath}
		chmod 640 ${caCertPath} ${caKeyPath} ${caInfoPath}

		# create certificate for client
		$etcdCa new-cert --key-bits ${keyBits} $passphrase client
		$etcdCa sign $passphrase client
		$etcdCa export --insecure $passphrase client | tar xvf -
		mv "client.crt" "${clientCertPath}"
		mv "client.key.insecure" "${clientKeyPath}"
		chown MailPlus-Server:MailPlus-Server ${clientCertPath} ${clientKeyPath}
		chmod 640 ${clientCertPath} ${clientKeyPath}
	fi

	# create certificate for server
	if [ ! -e $depot ]; then
		mkdir -p $depot
		cp -a ${caCertPath} ${depot}
		cp -a ${caKeyPath} ${depot}
		cp -a ${caInfoPath} ${depot}
		chmod 666 -R ${depot}
	fi

	# Get node ip list
	local ipList="$(${MAILPLUS_SERVER_BACKEND_BINARY} --getHostIPList)"
	local ip=""
	for ip in ${ipList}; do
		certIP="${certIP},${ip}"
	done
	$etcdCa new-cert --key-bits ${keyBits} $passphrase --ip $certIP --domain $certHostname server
	$etcdCa sign $passphrase server
	$etcdCa export --insecure $passphrase server | tar xvf -
	mv "server.crt" "${certPath}"
	mv "server.key.insecure" "${keyPath}"
	chown MailPlus-Server:MailPlus-Server ${certPath} ${keyPath}
	chmod 640 ${certPath} ${keyPath}

	rm -rf $depot 2>/dev/null
	umask ${oriUmask}

	return 0
}
GenerateInternalCaChain()
{
	local caDir="/var/packages/MailPlus-Server/etc/internal-ca-ssl"
	local caChainPath="${caDir}/chain-ca.pem"
	local crt=""

	rm -f ${caChainPath}

	# Only iterator *.crt file
	for crt in ${caDir}/*.crt; do
		cat ${crt} >> ${caChainPath}
		echo "" >> ${caChainPath}
	done

	chown MailPlus-Server:MailPlus-Server ${caChainPath}
	chmod 640 ${caChainPath}
}

getNonBalancerNodeIP()
{
	local IPList="$(${MAILPLUS_SERVER_BACKEND_BINARY} --listPeersIP)"
	local BALANCER_MASTER_IP="$(${MAILPLUS_SERVER_BACKEND_BINARY} --getMasterBalancer)"
	local RESULT_IP=""
	local IP=""

	for IP in $IPList
	do
		if [ "${IP}" != "${BALANCER_MASTER_IP}" ]; then
			RESULT_IP=${IP}
		fi
	done

	echo ${RESULT_IP}
}

GetMailPlusSharePath()
{
	local share=$(/usr/syno/sbin/synoshare --get "${MAIL_SHARE_NAME}" | grep "Path " | sed -e 's?.*\[\(\S*\)\].*?\1?')
	echo ${share}
}

AddAclEntryIfnotExist()
{
	local path=$1
	local aclEntry=$2
	if [ ! -e "${path}" -o -z "${aclEntry}" ]; then
		return 1
	fi
	local grepedAcl=$(/usr/syno/bin/synoacltool -get "${path}" | grep "${aclEntry}")
	if [ -n "${grepedAcl}" ]; then
		return 0
	fi
	/usr/syno/bin/synoacltool -add "${path}" "${aclEntry}"
}

PrepareMailPlusShareEnv()
{
	local volume=`echo $1 | sed -e 's/\///g'`
	local installVolume=`/usr/bin/readlink ${PRIVATE_LOCATION} | /usr/bin/cut -d'/' -f2`
	local mailScannerVolume=${installVolume}/@MailPlus-Server/MailScanner
	local sharePath="$(GetMailPlusSharePath)"
	local quarantineDir="/${sharePath}/@quarantine"
	local virusQuarantineDir="/${quarantineDir}/virus"
	local mcpQuarantineDir="/${quarantineDir}/mcp"
	local spamDataDir="/${sharePath}/@spamdata"
	local spamReportDir="${spamDataDir}/spamreport"
	local hamReportDir="${spamDataDir}/hamreport"
	local autoLearnDir="${spamDataDir}/autolearn"
	local autoLearnDirOld="${sharePath}/${SPAM_ACCOUNT}"

	if [ -z "${sharePath}" ]; then
		/usr/syno/bin/synowebapi --exec api=SYNO.Core.Share method=create version=1 name=$MAIL_SHARE_NAME shareinfo="{\"name\":\"$MAIL_SHARE_NAME\",\"desc\":\"Synology MailPlus\",\"vol_path\":\"/$volume\",\"enable_share_cow\":false}" || err_log "failed to create ${MAIL_SHARE_NAME} on ${volume}"
		sharePath="$(GetMailPlusSharePath)"
	fi
	if [ -s "${sharePath}" -a -d "${sharePath}" ]; then
		AddAclEntryIfnotExist "${sharePath}" "owner:*:allow:rwxpdDaARWcCo:fd--"
		AddAclEntryIfnotExist "${sharePath}" "everyone:*:allow:--x----------:fd--"
		if [ ! -d "${sharePath}/spamassassin" ]; then
			mkdir "${sharePath}/spamassassin"
			chown -R postfix "${sharePath}/spamassassin"
		fi

		rm -fr "${MAIL_STORAGE_DIR_PATH}"
		ln -sfn "${sharePath}" "${MAIL_STORAGE_DIR_PATH}"
		rm -fr ${mailScannerVolume}/spamassassin
		ln -sfn ${MAIL_STORAGE_DIR_PATH}/spamassassin ${mailScannerVolume}/spamassassin
	else
		err_log "MailPlus share folder does not exist"
	fi

	# prepare folders for quarantine
	if [ ! -d "${quarantineDir}" ]; then
		mkdir "${quarantineDir}"
		chmod 700 "${quarantineDir}"
		chown admin:users "${quarantineDir}"
	fi
	if [ ! -d "${virusQuarantineDir}" ]; then
		mkdir "${virusQuarantineDir}"
		chmod 700 "${virusQuarantineDir}"
		chown admin:users "${virusQuarantineDir}"
	fi
	if [ ! -d "${mcpQuarantineDir}" ]; then
		mkdir "${mcpQuarantineDir}"
		chmod 700 "${mcpQuarantineDir}"
		chown admin:users "${mcpQuarantineDir}"
	fi

	# prepare folders for spam learning
	if [ ! -d "${spamDataDir}" ]; then
		mkdir "${spamDataDir}"
		chmod 700 "${spamDataDir}"
		chown admin:users "${spamDataDir}"
	fi
	if [ ! -d "${spamReportDir}" ]; then
		mkdir "${spamReportDir}"
		chmod 700 "${spamReportDir}"
		chown admin:users "${spamReportDir}"
	fi
	if [ ! -d "${hamReportDir}" ]; then
		mkdir "${hamReportDir}"
		chmod 700 "${hamReportDir}"
		chown admin:users "${hamReportDir}"
	fi
	if [ ! -d "${autoLearnDir}" ] && [ -d "${autoLearnDirOld}" ]; then
		mv "${autoLearnDirOld}" "${autoLearnDir}"
	elif [ ! -d "${autoLearnDir}" ]; then
		mkdir "${autoLearnDir}"
		chmod 700 "${autoLearnDir}"
		chown admin:users "${autoLearnDir}"
		cp "${PRIVATE_LOCATION}/scripts/sieve_after/spam_account.sieve.template" "${autoLearnDir}/.dovecot.sieve"
		chmod 755 "${autoLearnDir}/.dovecot.sieve"
		chown admin:users "${autoLearnDir}/.dovecot.sieve"
	fi

	return 0
}

loadEnv()
{
	local envFile="/tmp/mailplus_server/env_output"
	if [ -f "${envFile}" ]; then
		. ${envFile}
	fi
}

CreatePreBuildDir()
{
	local dir=""
	for dir in ${MAILPLUS_TMP_PRE_BUILD_DIR_LIST}; do
		mkdir -p ${dir}
		chmod 755 "${dir}"
		chown MailPlus-Server:MailPlus-Server -R ${dir}
	done
}

RemovePreBuildDir()
{
	local dir=""
	for dir in ${MAILPLUS_TMP_PRE_BUILD_DIR_LIST}; do
		rm -fr ${dir}
	done
}

setMasterInterface()
{
	local NODE_INET=$(${MAILPLUS_SERVER_BACKEND_BINARY} --getHostIF)
	local balancerIface=$(${MAILPLUS_SERVER_BACKEND_BINARY} --getBalancerIF)
	local enable_balancer_address="$(${MAILPLUS_SERVER_BACKEND_BINARY} --getConfKeyVal "enable_balancer_address")"
	local balancerAddress="$(${MAILPLUS_SERVER_BACKEND_BINARY} --getConfKeyVal "balancer_address")"
	local balancerNetmask="$(${MAILPLUS_SERVER_BACKEND_BINARY} --getConfKeyVal "balancer_netmask")"

	if [ "${enable_balancer_address}" == "no" ]; then
		/usr/sbin/ifconfig "${balancerIface}" down
		return 0
	fi

	if [ "" == "${balancerIface}" -o "" == "${balancerAddress}" -o "" == "${balancerNetmask}" ];then
		log_err "Failed to set new balancer info addr[${balancerAddress}] netmask[${balancerNetmask}] interface[${balancerIface}]"
		return 1
	fi

	if isLoadBalancer; then
		/usr/sbin/ifconfig "${balancerIface}" "${balancerAddress}" netmask "${balancerNetmask}" up
		/usr/sbin/arping -A -U -I "${NODE_INET}" "${balancerAddress}" -w 10 &
	else
		/usr/sbin/ifconfig "${balancerIface}" down
	fi
	return 0
}

getInterfaceIP()
{
	local IF_NAME=$1
	local RETRY_TIMES=0
	local IP=

	IP=$(${MAILPLUS_SERVER_BACKEND_BINARY} --getIFIP "$IF_NAME")

	if [ -n "${IP}" ]; then
		echo "${IP}"
		return 0
	fi

	while [ ${RETRY_TIMES} -lt 2 ];
	do
		IP=$(/sbin/ifconfig "${IF_NAME}" | grep "inet addr" | awk -F: '{print $2}' | awk '{print $1}')
		if [[ "${IP}" =~ ${IPV4_REGEXP} ]]; then
			echo "${IP}"
			return
		fi
		RETRY_TIMES=$((RETRY_TIMES + 1))
		sleep 1
	done
}

bringDownMPSinterface()
{
	local master_if=$1

	ip addr list | grep -o -P '\b\S+(?=:MPS$)' |
	while read -r if_name
	do
		if [ -n "${if_name}" -a "${if_name}" != "${master_if}" ]; then
			info_log "remove alias interface "${if_name}":MPS"
			ifconfig "${if_name}:MPS" down
		fi
	done
}

GetMailAccountBaseDir() {
	## Get current domain

	local domainName="@local"
	local nodeId=$(getHostID)

	if [ $? -ne 0 -o -z "${nodeId}" ]; then
		return 1
	fi

	local volumeConfigKey="general_storage_volume-${nodeId}"
	local storageVolume="$(${MAILPLUS_SERVER_BACKEND_BINARY} --getConfKeyVal "${volumeConfigKey}")"
	local accountType="$(${MAILPLUS_SERVER_BACKEND_BINARY} --getConfKeyVal "account_type")"

	if [ $? -ne 0 ]; then
		return 1
	fi

	if [ "${accountType}" == "win" ]; then
		domainName="$(${MAILPLUS_SERVER_BACKEND_BINARY} --getConfKeyVal "win_domain_short_name")"
	elif [ "${accountType}" == "ldap" ]; then
		domainName="$(${MAILPLUS_SERVER_BACKEND_BINARY} --getConfKeyVal "acc_domain_name")"
	fi

	if [ -z "${storageVolume}" -o -z "${domainName}" ]; then
		return 1
	fi

	echo "/${storageVolume}/${MAIL_SHARE_NAME}/${domainName}"
	return 0
}