1
0
mirror of https://github.com/mail-in-a-box/mailinabox.git synced 2026-03-04 15:54:48 +01:00

Merge branch 'master' into EHDD

This commit is contained in:
downtownallday
2020-06-21 17:21:17 -04:00
56 changed files with 3151 additions and 277 deletions

View File

@@ -20,7 +20,7 @@ if [ -z "$TAG" ]; then
# want to display in status checks.
if [ "`lsb_release -d | sed 's/.*:\s*//' | sed 's/18\.04\.[0-9]/18.04/' `" == "Ubuntu 18.04 LTS" ]; then
# This machine is running Ubuntu 18.04.
TAG=v0.45
TAG=v0.46
elif [ "`lsb_release -d | sed 's/.*:\s*//' | sed 's/14\.04\.[0-9]/14.04/' `" == "Ubuntu 14.04 LTS" ]; then
# This machine is running Ubuntu 14.04.

View File

@@ -62,6 +62,24 @@ for ip in $PRIVATE_IP $PRIVATE_IPV6; do
echo " ip-address: $ip" >> /etc/nsd/nsd.conf;
done
# nsd fails to start when ipv6 is disabled by the kernel on certain
# interfaces without "do-ip6" set to "no" and "control-enable" to "no"
# [confirm]. Even though the nsd docs say the default value for
# control-enable is no, running "nsd-checkconf -o control-enable
# /etc/nsd/nsd.conf" returns "yes", so we explicitly set it here.
#
# For instance, on Travis-CI, ipv6 is disabled on the lo and docker
# interfaces, but enabled on the primary interface ens4. nsd fails to
# start without these additions.
if kernel_ipv6_lo_disabled; then
cat >> /etc/nsd/nsd.conf <<EOF
do-ip4: yes
do-ip6: no
remote-control:
control-enable: no
EOF
fi
echo "include: /etc/nsd/zones.conf" >> /etc/nsd/nsd.conf;
# Create DNSSEC signing keys.

View File

@@ -137,7 +137,14 @@ function get_default_privateip {
function ufw_allow {
if [ -z "${DISABLE_FIREWALL:-}" ]; then
# ufw has completely unhelpful output
ufw allow $1 > /dev/null;
ufw allow "$1" > /dev/null;
fi
}
function ufw_limit {
if [ -z "${DISABLE_FIREWALL:-}" ]; then
# ufw has completely unhelpful output
ufw limit "$1" > /dev/null;
fi
}
@@ -235,3 +242,9 @@ function generate_password() {
dd if=/dev/urandom bs=1 count=$input_len 2>/dev/null | base64 --wrap=0 | awk '{ gsub("/", ",", $0); print $0}'
}
function kernel_ipv6_lo_disabled() {
# Returns 0 if ipv6 is disabled on the loopback adapter
local v="$(sysctl -n net.ipv6.conf.lo.disable_ipv6)"
[ "$v" == "1" ] && return 0
return 0
}

View File

@@ -71,42 +71,46 @@ wait_slapd_start() {
say_verbose "...ok"
}
_add_if_missing() {
local var="$1"
local val="$2"
local conf="$MIAB_INTERNAL_CONF_FILE"
if [ $(grep -c "^${var}=" "$conf") -eq 0 ]; then
echo "${var}=\"${val}\"" >> "$conf"
fi
}
create_miab_conf() {
# create (if non-existing) or load (existing) ldap/miab_ldap.conf
if [ ! -e "$MIAB_INTERNAL_CONF_FILE" ]; then
say_verbose "Generating a new $MIAB_INTERNAL_CONF_FILE"
mkdir -p "$(dirname $MIAB_INTERNAL_CONF_FILE)"
# Use 64-character secret keys of safe characters
cat > "$MIAB_INTERNAL_CONF_FILE" <<EOF
LDAP_SERVER=127.0.0.1
LDAP_SERVER_PORT=389
LDAP_SERVER_STARTTLS=no
LDAP_SERVER_TLS=no
LDAP_URL=ldap://127.0.0.1/
LDAP_BASE="${LDAP_BASE}"
LDAP_SERVICES_BASE="${LDAP_SERVICES_BASE}"
LDAP_CONFIG_BASE="${LDAP_CONFIG_BASE}"
LDAP_DOMAINS_BASE="${LDAP_DOMAINS_BASE}"
LDAP_PERMITTED_SENDERS_BASE="${LDAP_PERMITTED_SENDERS_BASE}"
LDAP_USERS_BASE="${LDAP_USERS_BASE}"
LDAP_ALIASES_BASE="${LDAP_ALIASES_BASE}"
LDAP_ADMIN_DN="${LDAP_ADMIN_DN}"
LDAP_ADMIN_PASSWORD="$(generate_password 64)"
EOF
touch "$MIAB_INTERNAL_CONF_FILE"
fi
# ensure all required values exist, and if not set to default values
_add_if_missing LDAP_SERVER 127.0.0.1
_add_if_missing LDAP_SERVER_PORT 389
_add_if_missing LDAP_SERVER_STARTTLS no
_add_if_missing LDAP_SERVER_TLS no
_add_if_missing LDAP_URL ldap://127.0.0.1/
_add_if_missing LDAP_BASE "${LDAP_BASE}"
_add_if_missing LDAP_SERVICES_BASE "${LDAP_SERVICES_BASE}"
_add_if_missing LDAP_CONFIG_BASE "${LDAP_CONFIG_BASE}"
_add_if_missing LDAP_DOMAINS_BASE "${LDAP_DOMAINS_BASE}"
_add_if_missing LDAP_PERMITTED_SENDERS_BASE "${LDAP_PERMITTED_SENDERS_BASE}"
_add_if_missing LDAP_USERS_BASE "${LDAP_USERS_BASE}"
_add_if_missing LDAP_ALIASES_BASE "${LDAP_ALIASES_BASE}"
_add_if_missing LDAP_ADMIN_DN "${LDAP_ADMIN_DN}"
_add_if_missing LDAP_ADMIN_PASSWORD "$(generate_password 64)"
# add service account credentials
local prefix
for prefix in ${SERVICE_ACCOUNTS[*]}
do
if [ $(grep -c "^$prefix" "$MIAB_INTERNAL_CONF_FILE") -eq 0 ]; then
local cn=$(awk -F_ '{print tolower($2)}' <<< $prefix)
cat >>"$MIAB_INTERNAL_CONF_FILE" <<EOF
${prefix}_DN="cn=$cn,$LDAP_SERVICES_BASE"
${prefix}_PASSWORD="$(generate_password 64)"
EOF
fi
local cn=$(awk -F_ '{print tolower($2)}' <<< $prefix)
_add_if_missing "${prefix}_DN" "cn=$cn,$LDAP_SERVICES_BASE"
_add_if_missing "${prefix}_PASSWORD" "$(generate_password 64)"
done
chmod 0640 "$MIAB_INTERNAL_CONF_FILE"
@@ -853,7 +857,13 @@ cat > /etc/logrotate.d/slapd <<EOF;
EOF
# Modify olc server config like TLS
modify_global_config
# Skip this step if no ca_certificate.pem exists - this indicates
# that the system hasn't yet been migrated from sqlite
if [ -e "$STORAGE_ROOT/ssl/ca_certificate.pem" ]; then
modify_global_config
else
say_debug "Not enabling TLS at this time - ca_certificate hasn't been generated yet"
fi
# Add overlays and ensure mail-related attributes are indexed
add_overlays

View File

@@ -61,7 +61,7 @@ tools/editconf.py /etc/postfix/main.cf \
myhostname=$PRIMARY_HOSTNAME\
smtpd_banner="\$myhostname ESMTP Hi, I'm a Mail-in-a-Box (Ubuntu/Postfix; see https://mailinabox.email/)" \
mydestination=localhost
# Tweak some queue settings:
# * Inform users when their e-mail delivery is delayed more than 3 hours (default is not to warn).
# * Stop trying to send an undeliverable e-mail after 2 days (instead of 5), and for bounce messages just try for 1 day.

View File

@@ -5,7 +5,7 @@
# helper functions for migration #13
#
import uuid, os, sqlite3, ldap3
import uuid, os, sqlite3, ldap3, hashlib
def add_user(env, ldapconn, search_base, users_base, domains_base, email, password, privs, cn=None):
@@ -29,9 +29,13 @@ def add_user(env, ldapconn, search_base, users_base, domains_base, email, passwo
print("user already exists: %s" % email)
return ldapconn.response[0]['dn']
# Generate a unique id for uid
uid = '%s' % uuid.uuid4()
## Generate a unique id for uid
#uid = '%s' % uuid.uuid4()
# use a sha-1 hash of the email address for uid
m = hashlib.sha1()
m.update(bytearray(email.lower(),'utf-8'))
uid = m.hexdigest()
# Attributes to apply to the new ldap entry
attrs = {
"mail" : email,

View File

@@ -0,0 +1,16 @@
<?php
/***********************************************
* File : config.php
* Project : Z-Push
* Descr : CalDAV backend configuration file
************************************************/
define('CALDAV_PROTOCOL', 'NC_PROTO');
define('CALDAV_SERVER', 'NC_HOST');
define('CALDAV_PORT', 'NC_PORT');
define('CALDAV_PATH', 'NC_PREFIX/remote.php/dav/calendars/%u/');
define('CALDAV_PERSONAL', 'PRINCIPAL');
define('CALDAV_SUPPORTS_SYNC', false);
define('CALDAV_MAX_SYNC_PERIOD', 2147483647);
?>

View File

@@ -0,0 +1,31 @@
<?php
/***********************************************
* File : config.php
* Project : Z-Push
* Descr : CardDAV backend configuration file
************************************************/
define('CARDDAV_PROTOCOL', 'NC_PROTO'); /* http or https */
define('CARDDAV_SERVER', 'NC_HOST');
define('CARDDAV_PORT', 'NC_PORT');
define('CARDDAV_PATH', 'NC_PREFIX/remote.php/dav/addressbooks/users/%u/');
define('CARDDAV_DEFAULT_PATH', 'NC_PREFIX/remote.php/dav/addressbooks/users/%u/contacts/'); /* subdirectory of the main path */
define('CARDDAV_GAL_PATH', ''); /* readonly, searchable, not syncd */
define('CARDDAV_GAL_MIN_LENGTH', 5);
define('CARDDAV_CONTACTS_FOLDER_NAME', '%u Addressbook');
define('CARDDAV_SUPPORTS_SYNC', false);
// If the CardDAV server supports the FN attribute for searches
// DAViCal supports it, but SabreDav, Nextcloud and SOGo don't
// Setting this to true will search by FN. If false will search by sn, givenName and email
// It's safe to leave it as false
define('CARDDAV_SUPPORTS_FN_SEARCH', false);
// If your carddav server needs to use file extension to recover a vcard.
// Davical needs it
// SOGo official demo online needs it, but some SOGo installation don't need it, so test it
define('CARDDAV_URL_VCARD_EXTENSION', '.vcf');
?>

View File

@@ -0,0 +1,398 @@
#!/bin/bash
#
# Run this script on your remote Nextcloud to configure it to use
# Mail-in-a-Box-LDAP.
#
# The script will:
# 1. enable the "LDAP user and group backend" in Nextcloud
# 2. install calendar and contacts
# 3. configure Nextcloud to access MiaB-LDAP for users and groups
# 4. optionally install and configure ssmtp so system mail is
# sent to MiaB-LDAP
#
VERBOSE=0
usage() {
cat <<EOF
Usage: $0 <NCDIR> <NC_ADMIN_USER> <NC_ADMIN_PASSWORD> <MIAB_HOSTNAME> <LDAP_NEXTCLOUD_PASS> [ <SSMTP_ALERTS_EMAIL> <SSMTP_AUTH_USER> <SSMTP_AUTH_PASS> ]
Configure Nextcloud to use MiaB-LDAP for users and groups
Optionally configure a mail relay to MiaB-LDAP
Arguments:
NCDIR
the path to the local Nextcloud installation directory
NC_ADMIN_USER
a current Nextcloud username that has ADMIN rights
NC_ADMIN_PASSWORD
the password for NC_ADMIN
MIAB_HOSTNAME
the fully-qualified host name of MiaB-LDAP
LDAP_NEXTCLOUD_PASS
supply the password for the LDAP service account Nextcloud
uses to locate and enumerate users and groups. A MiaB-LDAP
installation automatically creates this limited-access service
account with a long random password. Open
/home/user-data/ldap/miab_ldap.conf on your MiaB-LDAP box,
then paste the password for "$LDAP_NEXTCLOUD_DN" as a script
argument. It will be the value of the LDAP_NEXTCLOUD_PASSWORD
key.
SSMTP_ALERTS_EMAIL / SSMTP_AUTH_USER / SSMTP_AUTH_PASS
OPTIONAL. Supplying these arguments will setup ssmtp on your
system and configure it to use MiaB-LDAP as its mail relay.
Email sent with sendmail or ssmtp will be relayed to
MiaB-LDAP. SSMTP_ALERTS_EMAIL is the email address that will
receive messages for all userids less than
1000. SSMTP_AUTH_USER / SSMTP_AUTH_PASS is the email address
that will be used to authenticate with MiaB-LDAP (the sender
or envelope FROM address). You probably want a new/dedicated
email address for this - create a new account in the MiaB-LDAP
admin interface. More information on ssmtp is available at
https://help.ubuntu.com/community/EmailAlerts.
The script must be run as root.
EOF
exit 1
}
if [ "$1" == "-v" ]; then
VERBOSE=1
shift
fi
# Directory where Nextcloud is installed (must contain occ)
NCDIR="$1"
# Nextcloud admin credentials for making user-ldap API calls via curl
NC_ADMIN_USER="$2"
NC_ADMIN_PASSWORD="$3"
# Hostname of the remote MiaB-LDAP
MAILINABOX_HOSTNAME="$4"
# LDAP service account Nextcloud uses to perform ldap searches.
# Values are found in mailinabox:/home/user-data/ldap/miab_ldap.conf
LDAP_NEXTCLOUD_DN="cn=nextcloud,ou=Services,dc=mailinabox"
LDAP_NEXTCLOUD_PASSWORD="$5"
# ssmtp: the person who gets all emails for userids < 1000
SSMTP_ALERTS_EMAIL="$6"
SSMTP_AUTH_USER="$7"
SSMTP_AUTH_PASS="$8"
#
# validate arguments
#
if [ -z "$NCDIR" -o "$1" == "-h" -o "$1" == "--help" ]
then
usage
fi
if [ -z "$NCDIR" -o ! -d "$NCDIR" ]
then
echo "Invalid directory: $NCDIR" 1>&2
exit 1
fi
if [ ! -e "$NCDIR/occ" ]; then
echo "OCC not found at: $NCDIR/occ !" 1>&2
exit 1
fi
if [ -z "$NC_ADMIN_USER" -o \
-z "$MAILINABOX_HOSTNAME" -o \
-z "$LDAP_NEXTCLOUD_PASSWORD" ]
then
usage
fi
if [ ! -z "$SSMTP_ALERTS_EMAIL" ]; then
if [ -z "$(awk -F@ '{print $2}' <<< "$SSMTP_ALERTS_EMAIL")" ]; then
echo "Invalid email address: $SSMTP_ALERTS_EMAIL" 1>&2
exit 1
fi
if [ -z "$(awk -F@ '{print $2}' <<< "$SSMTP_AUTH_USER")" ]; then
echo "Invalid email address: $SSMTP_AUTH_USER" 1>&2
exit 1
fi
fi
if [ -s /etc/mailinabox.conf ]; then
echo "Run on your remote Nextcloud, not on Mail-in-a-Box !!" 1>&2
exit 1
fi
if [ "$EUID" != "0" ]; then
echo "The script must be run as root (sudo)" 1>&2
exit 1
fi
#
# other constants
#
LDAP_URL="ldaps://$MAILINABOX_HOSTNAME"
LDAP_SERVER="$MAILINABOX_HOSTNAME"
LDAP_SERVER_PORT="636"
LDAP_SERVER_STARTTLS="no"
LDAP_BASE="dc=mailinabox"
LDAP_USERS_BASE="ou=Users,dc=mailinabox"
PRIMARY_HOSTNAME="$(hostname --fqdn)"
#
# get the url used to access nextcloud as NC_ADMIN_USER
#
NC_CONFIG_CLI_URL="$(cd "$NCDIR/config"; php -n -r 'include "config.php"; print $CONFIG["overwrite.cli.url"];')"
case "$NC_CONFIG_CLI_URL" in
http:* | https:* )
urlproto=$(awk -F/ '{print $1}' <<< "$NC_CONFIG_CLI_URL")
urlhost=$(awk -F/ '{print $3}' <<< "$NC_CONFIG_CLI_URL")
urlprefix=$(awk -F/ "{ print substr(\$0,length(\"$urlproto\")+length(\"\
$urlhost\")+4) }" <<<"$NC_CONFIG_CLI_URL")
NC_AUTH_URL="$urlproto//${NC_ADMIN_USER}:${NC_ADMIN_PASSWORD}@$urlhost/\
$urlprefix"
;;
* )
NC_AUTH_URL="https://${NC_ADMIN_USER}:${NC_ADMIN_PASSWORD}@$PRIMARY_HOS\
TNAME${NC_CONFIG_CLI_URL:-/}"
;;
esac
say() {
echo "$@"
}
say_verbose() {
if [ $VERBOSE -gt 0 ]; then
echo "$@"
fi
}
die() {
echo "$@" 1>&2
exit 2
}
#
# configure Nextcloud's user-ldap for MiaB-LDAP
#
# See: https://docs.nextcloud.com/server/17/admin_manual/configuration_user/user_auth_ldap_api.html
#
config_user_ldap() {
local id="${1:-s01}"
local first_call="${2:-yes}"
local starttls=0
[ "$LDAP_SERVER_STARTTLS" == "yes" ] && starttls=1
local c=(
"--data-urlencode configData[ldapHost]=$LDAP_URL"
"--data-urlencode configData[ldapPort]=$LDAP_SERVER_PORT"
"--data-urlencode configData[ldapBase]=$LDAP_USERS_BASE"
"--data-urlencode configData[ldapTLS]=$starttls"
"--data-urlencode configData[ldapAgentName]=$LDAP_NEXTCLOUD_DN"
"--data-urlencode configData[ldapAgentPassword]=$LDAP_NEXTCLOUD_PASSWORD"
"--data-urlencode configData[ldapUserDisplayName]=cn"
"--data-urlencode configData[ldapUserDisplayName2]="
"--data-urlencode configData[ldapUserFilter]=(&(objectClass=inetOrgPerson)(objectClass=mailUser))"
"--data-urlencode configData[ldapUserFilterMode]=1"
"--data-urlencode configData[ldapLoginFilter]=(&(objectClass=inetOrgPerson)(objectClass=mailUser)(|(mail=%uid)(uid=%uid)))"
"--data-urlencode configData[ldapEmailAttribute]=mail"
"--data-urlencode configData[ldapGroupFilter]=(objectClass=mailGroup)"
"--data-urlencode configData[ldapGroupMemberAssocAttr]=member"
"--data-urlencode configData[ldapGroupDisplayName]=mail"
"--data-urlencode configData[ldapNestedGroups]=1"
"--data-urlencode configData[turnOnPasswordChange]=1"
"--data-urlencode configData[ldapExpertUsernameAttr]=maildrop"
"--data-urlencode configData[ldapExpertUUIDUserAttr]=uid"
"--data-urlencode configData[ldapExpertUUIDGroupAttr]=entryUUID"
"--data-urlencode configData[ldapConfigurationActive]=1"
)
# apply the settings - note: we can't use localhost because nginx
# will route to the wrong virtual host
local xml
say_verbose "curl \"${NC_AUTH_URL%/}/ocs/v2.php/apps/user_ldap/api/v1/config/$id\""
xml="$(curl -s -S --insecure -X PUT "${NC_AUTH_URL%/}/ocs/v2.php/apps/user_ldap/api/v1/config/$id" -H "OCS-APIREQUEST: true" ${c[@]})"
[ $? -ne 0 ] &&
die "Unable to issue a REST call as $NC_ADMIN_USER to nextcloud. url=$NC_AUTH_URL/ocs/v2.php/apps/user_ldap/api/v1/config/$id"
# did it work?
if [ -z "$xml" ]; then
die "Invalid response from Nextcloud using url '$NC_AUTH_URL'. reponse was '$xml'. Cannot continue."
fi
local statuscode
statuscode=$(python3 -c "import xml.etree.ElementTree as ET; print(ET.fromstring(r'''$xml''').findall('meta')[0].findall('statuscode')[0].text)")
if [ "$statuscode" == "404" -a "$first_call" == "yes" ]; then
# got a 404 so maybe this is the first time -- we have to create
# an initial blank ldap configuration and try again
xml="$(curl -s -S --insecure -X POST "${NC_AUTH_URL%/}/ocs/v2.php/apps/user_ldap/api/v1/config" -H "OCS-APIREQUEST: true")"
[ $? -ne 0 ] &&
die "Unable to issue a REST call as $NC_ADMIN_USER to nextcloud: $xml"
statuscode=$(python3 -c "import xml.etree.ElementTree as ET; print(ET.fromstring(r'''$xml''').findall('meta')[0].findall('statuscode')[0].text)")
[ $? -ne 0 -o "$statuscode" != "200" ] &&
die "Error creating initial ldap configuration: $xml"
id=$(python3 -c "import xml.etree.ElementTree as ET; print(ET.fromstring(r'''$xml''').findall('data')[0].findall('configID')[0].text)" 2>/dev/null)
[ $? -ne 0 ] &&
die "Error creating initial ldap configuration: $xml"
config_user_ldap "$id" no
elif [ "$statuscode" == "997" -a "$first_call" == "yes" ]; then
# could not log in
die "Could not authenticate as $NC_ADMIN_USER to perform user-ldap API call. statuscode=$statuscode: $xml"
elif [ "$statuscode" != "200" ]; then
die "Unable to apply ldap configuration to nextcloud: id=$id first_call=$first_call statuscode=$statuscode: $xml"
fi
return 0
}
enable_user_ldap() {
# install prerequisite package php-ldap
# if using Docker Hub's php image, don't install at all
if [ ! -e /etc/apt/preferences.d/no-debian-php ]; then
say_verbose "Installing system package php-ldap"
apt-get install -y -qq php-ldap || die "Could not install php-ldap package"
#restart_service php7.2-fpm
fi
# enable user_ldap
if [ ! -x /usr/bin/sudo ]; then
say "WARNING: sudo is not installed: Unable to run occ to check and/or enable Nextcloud app \"user-ldap\"."
else
say_verbose "Enable user-ldap"
sudo -E -u www-data php $NCDIR/occ app:enable user_ldap -q
[ $? -ne 0 ] && die "Unable to enable user_ldap nextcloud app"
fi
}
install_app() {
local app="$1"
if [ ! -x /usr/bin/sudo ]; then
say "WARNING: sudo is not installed: Unable to run occ to check and/or install Nextcloud app \"$app\"."
elif [ -z "$(sudo -E -u www-data php $NCDIR/occ app:list | grep $app)" ]; then
say_verbose "Install app '$app'"
sudo -E -u www-data php $NCDIR/occ app:install $app
[ $? -ne 0 ] && die "Unable to install Nextcloud app '$app'"
fi
}
setup_ssmtp() {
# sendmail-like mailer with a mailhub to remote mail-in-a-box
# see: https://help.ubuntu.com/community/EmailAlerts
if [ "$(. /etc/os-release; echo $NAME)" != "Ubuntu" ]; then
die "Sorry, ssmtp is only supported on Ubuntu"
fi
say_verbose "Installing system package ssmtp"
apt-get install -y -qq ssmtp
if [ ! -e /etc/ssmtp/ssmtp.conf.orig ]; then
cp /etc/ssmtp/ssmtp.conf /etc/ssmtp/ssmtp.conf.orig
fi
cat <<EOF >/etc/ssmtp/ssmtp.conf
# Generated by MiaB-LDAP integration script on $(date)
# The person who gets all mail for userids < 1000
root=${SSMTP_ALERTS_EMAIL}
# The place where mail goes
mailhub=${MAILINABOX_HOSTNAME}:587
AuthUser=${SSMTP_AUTH_USER}
AuthPass=${SSMTP_AUTH_PASS}
UseTLS=YES
UseSTARTTLS=YES
# The full hostname
hostname=${PRIMARY_HOSTNAME}
# Are users allowed to set their own From address?
FromLineOverride=YES
EOF
}
remote_mailinabox_handler() {
say_verbose "Installing system package ldap-utils"
apt-get install -y -qq ldap-utils python3 || die "Could not install required packages"
local count=0
local ldap_debug=""
while /bin/true; do
# ensure we can search
local output
say ""
say "Testing MiaB-LDAP connection..."
output="$(ldapsearch $ldap_debug -v -H $LDAP_URL -x -D "$LDAP_NEXTCLOUD_DN" -w "$LDAP_NEXTCLOUD_PASSWORD" -b "$LDAP_BASE" -s base 2>&1)"
local code=$?
if [ $code -ne 0 ]; then
say "Unable to contact $LDAP_URL"
say " base=$LDAP_BASE"
say " user=$LDAP_NEXTCLOUD_DN"
say " error code=$code"
say " msg= $output"
say ""
say "You may need to permit access to the ldap server running on $LDAP_SERVER"
say "On $LDAP_SERVER execute:"
local ip
for ip in $(hostname -I); do
say " \$ ufw allow proto tcp from $ip to any port ldaps"
done
say ""
let count+=1
if [ $count -gt 5 ]; then
die "Giving up"
fi
read -p "Press [enter] when ready, or \"no\" to quit: " ans
[ "$ans" == "no" ] && die "Quit"
ldap_debug="-d 9"
else
say "Test successful - able to bind and search as $LDAP_NEXTCLOUD_DN"
break
fi
done
enable_user_ldap
config_user_ldap
return 0
}
echo "Integrating Nextcloud with Mail-in-a-box LDAP"
remote_mailinabox_handler
# contacts and calendar are required for Roundcube and Z-Push
install_app "calendar"
install_app "contacts"
if [ ! -z "${SSMTP_ALERTS_EMAIL}" ]; then
setup_ssmtp
fi
say ""
say "Done!"

View File

@@ -0,0 +1,161 @@
#!/bin/bash
source setup/functions.sh # load our functions
source /etc/mailinabox.conf # load global vars
# maintain a separate conf file because setup rewrites mailinabox.conf
touch /etc/mailinabox_mods.conf
. /etc/mailinabox_mods.conf
# where webmail.sh installs roundcube
RCM_DIR=/usr/local/lib/roundcubemail
RCM_PLUGIN_DIR=${RCM_DIR}/plugins
# where zpush.sh installs z-push
ZPUSH_DIR=/usr/local/lib/z-push
configure_zpush() {
# have zpush use the remote nextcloud for carddav/caldav
# instead of the nextcloud that comes with mail-in-a-box
cp setup/mods.available/conf/zpush/backend_carddav.php $ZPUSH_DIR/backend/carddav/config.php
cp setup/mods.available/conf/zpush/backend_caldav.php $ZPUSH_DIR/backend/caldav/config.php
local var val
for var in NC_PROTO NC_HOST NC_PORT NC_PREFIX; do
eval "val=\$$var"
sed -i "s^$var^${val%/}^g" $ZPUSH_DIR/backend/carddav/config.php
sed -i "s^$var^${val%/}^g" $ZPUSH_DIR/backend/caldav/config.php
done
}
configure_roundcube() {
# replace the plugin configuration from the default Mail-In-A-Box
local name="${1:-$NC_HOST}"
local baseurl="$NC_PROTO://$NC_HOST:$NC_PORT$NC_PREFIX"
# Configure CardDav plugin
#
# 1. make MiaB ownCloud contacts read-only so users can still
# access them, but not change them, and no sync occurs
#
# a. set 'active' to 'false'
# regular expression before "bashing" it:
# (['"]active['"][ \t]*=>[ \t]*)true
#
sed -i 's/\(['"'"'"]active['"'"'"][ \t]*=>[ \t]*\)true/\1false/' ${RCM_PLUGIN_DIR}/carddav/config.inc.php
# b. set 'readonly' to 'true'
# regular expressions is like above
sed -i 's/\(['"'"'"]readonly['"'"'"][ \t]*=>[ \t]*\)false/\1true/' ${RCM_PLUGIN_DIR}/carddav/config.inc.php
#
# 2. add the remote Nextcloud
#
cat >> ${RCM_PLUGIN_DIR}/carddav/config.inc.php <<EOF
<?php
/* Do not edit. Written by Mail-in-a-Box-LDAP. Regenerated on updates. */
//\$prefs['_GLOBAL']['hide_preferences'] = true;
//\$prefs['_GLOBAL']['suppress_version_warning'] = true;
\$prefs['cloud'] = array(
'name' => '$name',
'username' => '%u', // login username
'password' => '%p', // login password
'url' => '${baseurl%/}/remote.php/carddav/addressbooks/%u/contacts',
'active' => true,
'readonly' => false,
'refresh_time' => '02:00:00',
'fixed' => array('username','password'),
'preemptive_auth' => '1',
'hide' => false,
);
?>
EOF
}
remote_nextcloud_handler() {
echo ""
echo "============================"
echo "Configure a remote Nextcloud"
echo "============================"
echo 'Enter the url or hostname and web prefix of your remote Nextcloud'
echo 'For example:'
echo ' "cloud.mydomain.com/" - Nextcloud server with no prefix'
echo ' "cloud.mydomain.com" - same as above'
echo ' "www.mydomain.com/cloud" - a Nextcloud server having a prefix /cloud'
echo ''
local ans
local current_url=""
if [ -z "${NC_HOST:-}" ]; then
if [ -z "${NONINTERACTIVE:-}" ]; then
read -p "[your Nextcloud's hostname/prefix] " ans
fi
[ -z "$ans" ] && return 0
else
current_url="$NC_PROTO://$NC_HOST:$NC_PORT$NC_PREFIX"
if [ -z "${NONINTERACTIVE:-}" ]; then
read -p "[$current_url] " ans
if [ -z "$ans" ]; then
ans="$current_url"
elif [ "$ans" == "none" ]; then
ans=""
fi
else
ans="$current_url"
fi
fi
case "$ans" in
https://* )
NC_PROTO="https"
NC_PORT="443"
ans="$(awk -F: '{print substr($0,9)}' <<< "$ans")"
;;
http://* )
NC_PROTO="http"
NC_PORT="80"
ans="$(awk -F: '{print substr($0,8)}' <<< "$ans")"
;;
* )
NC_PROTO="https"
NC_PORT="443"
;;
esac
NC_PREFIX="/$(awk -F/ '{print substr($0,length($1)+2)}' <<< "$ans")"
NC_HOST="$(awk -F/ '{print $1}' <<< "$ans")"
if grep ":" <<< "$NC_HOST" >/dev/null; then
NC_PORT="$(awk -F: '{print $2}' <<< "$NC_HOST")"
NC_HOST="$(awk -F: '{print $1}' <<< "$NC_HOST")"
fi
local new_url="$NC_PROTO://$NC_HOST:$NC_PORT$NC_PREFIX"
if [ ! -z "$NC_HOST" ]; then
echo "Using Nextcloud ${new_url}"
# configure roundcube contacts
configure_roundcube "$NC_HOST"
# configure zpush (which links to contacts & calendar)
configure_zpush
# prevent nginx from serving any miab-installed nextcloud files
chmod 000 /usr/local/lib/owncloud
fi
tools/editconf.py /etc/mailinabox_mods.conf \
"NC_PROTO=$NC_PROTO" \
"NC_HOST=$NC_HOST" \
"NC_PORT=$NC_PORT" \
"NC_PREFIX=$NC_PREFIX"
}
remote_nextcloud_handler

View File

@@ -1,6 +1,7 @@
#!/bin/bash
# Munin: resource monitoring tool
#################################################
[ "${FEATURE_MUNIN:-true}" == "false" ] && return 0
source setup/functions.sh # load our functions
source /etc/mailinabox.conf # load global vars

View File

@@ -1,6 +1,7 @@
#!/bin/bash
# Nextcloud
##########################
[ "${FEATURE_NEXTCLOUD:-true}" == "false" ] && return 0
source setup/functions.sh # load our functions
source /etc/mailinabox.conf # load global vars
@@ -100,6 +101,10 @@ nextcloud_hash=50b98d2c2f18510b9530e558ced9ab51eb4f11b0
# version.php since the restore procedure can leave the system in a state where you have a newer Nextcloud
# application version than the database.
# ensure directory is accessible
if [ -d "/usr/local/lib/owncloud" ]; then
chmod u+rx /usr/local/lib/owncloud
fi
# If config.php exists, get version number, otherwise CURRENT_NEXTCLOUD_VER is empty.
if [ -f "$STORAGE_ROOT/owncloud/config.php" ]; then
CURRENT_NEXTCLOUD_VER=$(php -r "include(\"$STORAGE_ROOT/owncloud/config.php\"); echo(\$CONFIG['version']);")

View File

@@ -96,11 +96,6 @@ if [ ! -s $STORAGE_ROOT/ssl/ssl_private_key.pem ]; then
# Set the umask so the key file is never world-readable.
(umask 037; hide_output \
openssl genrsa -out $STORAGE_ROOT/ssl/ssl_private_key.pem 2048)
# Give the group 'ssl-cert' read access so slapd can read it
groupadd -fr ssl-cert
chgrp ssl-cert $STORAGE_ROOT/ssl/ssl_private_key.pem
chmod g+r $STORAGE_ROOT/ssl/ssl_private_key.pem
# Remove the ssl_certificate.pem symbolic link to force a
# regeneration of the server certificate. It needs to be
@@ -110,6 +105,11 @@ if [ ! -s $STORAGE_ROOT/ssl/ssl_private_key.pem ]; then
fi
fi
# Give the group 'ssl-cert' read access so slapd can read it
groupadd -fr ssl-cert
chgrp ssl-cert $STORAGE_ROOT/ssl/ssl_private_key.pem
chmod g+r $STORAGE_ROOT/ssl/ssl_private_key.pem
#
# Generate a root CA certificate
#
@@ -123,15 +123,21 @@ if [ ! -f $STORAGE_ROOT/ssl/ca_certificate.pem ]; then
-passin 'pass:SECRET-PASSWORD' \
-out $CERT \
-subj '/CN=Temporary-Mail-In-A-Box-CA'
fi
# add the certificate to the system's trusted root ca list
if [ ! -e /usr/local/share/ca-certificates/mailinabox.crt ]; then
# add the CA certificate to the system's trusted root ca list
# this is required for openldap's TLS implementation
# do this as a separate step in case a CA certificate is manually
# copied onto the machine for QA/test
CERT=$STORAGE_ROOT/ssl/ca_certificate.pem
hide_output \
cp $CERT /usr/local/share/ca-certificates/mailinabox.crt
hide_output \
update-ca-certificates
fi
# Generate a 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.

View File

@@ -147,6 +147,15 @@ echo
certbot register --register-unsafely-without-email --agree-tos --config-dir $STORAGE_ROOT/ssl/lets_encrypt
fi
#
# Run setup mods
#
if [ -d "${LOCAL_MODS_DIR:-local}" ]; then
for mod in $(ls "${LOCAL_MODS_DIR:-local}" | grep -v '~$'); do
${LOCAL_MODS_DIR:-local}/$mod
done
fi
# Done.
echo
echo "-----------------------------------------------"

View File

@@ -256,7 +256,7 @@ if [ -z "${DISABLE_FIREWALL:-}" ]; then
apt_install ufw
# Allow incoming connections to SSH.
ufw_allow ssh;
ufw_limit ssh;
# ssh might be running on an alternate port. Use sshd -T to dump sshd's #NODOC
# settings, find the port it is supposedly running on, and open that port #NODOC
@@ -266,7 +266,7 @@ if [ -z "${DISABLE_FIREWALL:-}" ]; then
if [ "$SSH_PORT" != "22" ]; then
echo Opening alternate SSH port $SSH_PORT. #NODOC
ufw_allow $SSH_PORT #NODOC
ufw_limit $SSH_PORT #NODOC
fi
fi

View File

@@ -29,8 +29,8 @@ apt_install \
# Install Roundcube from source if it is not already present or if it is out of date.
# Combine the Roundcube version number with the commit hash of plugins to track
# whether we have the latest version of everything.
VERSION=1.4.4
HASH=4e425263f5bec27d39c07bde524f421bda205c07
VERSION=1.4.6
HASH=44961ef62bb9c9875141ca34704bbc7d6f36373d
PERSISTENT_LOGIN_VERSION=6b3fc450cae23ccb2f393d0ef67aa319e877e435
HTML5_NOTIFIER_VERSION=4b370e3cd60dabd2f428a26f45b677ad1b7118d5
CARDDAV_VERSION=3.0.3