#!/bin/sh

# Copyright (c) 2004  Sean Farley <sean-freebsd@farley.org>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.

#
# Program:  mknulljail.sh
# Version:  0.1
# URL:  http://www.farley.org/
#

############################################################

# Initialization.
OPENSSH="NO"
SENDMAIL="NONE"
readonly VERSION="0.1"
umask 022

# Help for the user.
usage()
{
	echo -n "Usage:  `basename ${0}` [-h] [-SVachiops] "
	echo "<jail FQDN> <jail IP> <nameserver IP> "
	echo "        <root forward address>"
	echo "Options:"
	echo "  -S          Enable Sendmail"
	echo "  -V          Display version"
	echo "  -a          Enable SASL2"
	echo "  -c          Enable STARTTLS"
	echo "  -h          Help"
	echo "  -i          Enable secure IMAP (imaps)"
	echo "  -o          Enable OpenSSH"
	echo "  -p          Enable PostgreSQL"
	echo "  -s          Enable ports Sendmail"

	return
}

while getopts "SVachiops" opt
do
	case ${opt} in
	V)
		echo "`basename ${0}` v${VERSION}"
		exit 1
		;;
	a)
		readonly SASL2="YES"
		;;
	c)
		readonly SENDMAILCERTS="YES"
		;;
	i)
		readonly IMAP="YES"
		;;
	o)
		readonly OPENSSH="YES"
		;;
	p)
		readonly POSTGRESQL="YES"
		;;
	s)
		readonly SENDMAILPORT="YES"
		readonly SENDMAIL="YES"
		;;
	S)
		readonly SENDMAIL="YES"
		;;
	h|\?)
		usage
		exit 1
		;;
	esac
done
shift $((${OPTIND} - 1))

# Enough arguments?
if [ $# -lt 4 ]
then
	usage
	exit 1
fi

# Initialization with given arguments.
readonly JAILFQDN="$1"
readonly HOST="`echo ${JAILFQDN} |cut -d'.' -f 1`"
readonly DOMAIN="`echo ${JAILFQDN} |cut -d'.' -f 2-`"
readonly JAIL="${HOST}"
readonly JAILBASE="/usr/local/jails"
readonly JAILDIR=`realpath ${JAILBASE}/${JAILFQDN}`
readonly JAILIP="$2"
readonly SRCDIR="/usr/src"
readonly FSTAB="/etc/fstab"
readonly RCDIR="${JAILDIR}/usr/local/etc/rc.d"
readonly NS="$3"
readonly ROOTMAIL="$4"

# Certificate values.
readonly CERTVALUES="XX
XX
XX
XX
XX
${JAILFQDN}
root@${DOMAIN}
"

# Create jail directory tree.
mkdir -p ${JAILDIR}
mkdir -p ${RCDIR}
cd ${SRCDIR}/etc
mtree -deU -f ${SRCDIR}/etc/mtree/BSD.root.dist -p ${JAILDIR}/
cd ${JAILDIR}/usr
mkdir X11R6 bin games include lib libdata libexec sbin share tmp \
	local/bin local/certs local/doc local/info local/lib local/libdata \
	local/libexec local/man local/openssl local/sbin local/share
chmod 1777 tmp
cd ${SRCDIR}/etc
mtree -deU -f ${SRCDIR}/etc/mtree/BSD.var.dist -p ${JAILDIR}/var
mtree -deU -f ${SRCDIR}/etc/mtree/BSD.sendmail.dist -p ${JAILDIR}
make distribution DESTDIR=${JAILDIR} -DNO_MAKEDEV_RUN -DNOMAN
cd ${JAILDIR}/dev
sh MAKEDEV jail
cd ${JAILDIR}
ln -sf dev/null kernel

# Create jail's /etc/rc.conf file.
cat << E_O_M >> ${JAILDIR}/etc/rc.conf
blanktime="NO"
hostname="${JAILFQDN}"
inetd_flags="-wW -a ${JAILIP}"
network_interfaces=""
portmap_enable="NO"
sendmail_enable="${SENDMAIL}"
sshd_enable="${OPENSSH}"
sshd_program="/usr/local/sbin/sshd"
syslogd_flags="-ss"
tcp_keepalive="NO"
E_O_M

# Configure /etc files.
touch ${JAILDIR}${FSTAB}
touch ${JAILDIR}/etc/opiekeys
touch ${JAILDIR}/etc/mail/local-host-names
sed -e 's/\(adjkerntz -i\)/#\1/' -i "" ${JAILDIR}/etc/rc
cp -fp /etc/csh.* ${JAILDIR}/etc
cp -p /etc/localtime ${JAILDIR}/etc
cat << E_O_M2 >> ${JAILDIR}/etc/resolv.conf
domain ${DOMAIN}
nameserver ${NS}
E_O_M2
printf "${JAILIP}\t\t\t${JAIL}\t${JAILFQDN}\n" >> ${JAILDIR}/etc/hosts
cp -fp /usr/local/etc/rc.subr ${JAILDIR}/usr/local/etc

# Create nullfs /etc/fstab entries if not already there.
if [ `grep -c ${JAILDIR} ${FSTAB}` -eq 0 ]
then
	printf "\n# ${JAILFQDN} (jail)\n" >> ${FSTAB}
	for nullFS in /bin /boot /sbin /usr/X11R6 /usr/bin /usr/games \
		/usr/include /usr/lib /usr/libdata /usr/libexec /usr/local/bin \
		/usr/local/certs /usr/local/doc /usr/local/info /usr/local/lib \
		/usr/local/libdata /usr/local/libexec /usr/local/man \
		/usr/local/openssl /usr/local/sbin /usr/local/share /usr/sbin \
		/usr/share /var/db/pkg
	do
		printf "${nullFS}\t${JAILDIR}${nullFS}\tnull\tro\t0\t0\n" >> ${FSTAB}
	done
fi

# Mount the null FS.
if [ `mount | grep -c "${JAILDIR}/"` -eq 0 ]
then
	mount -a -t null
fi

# Configure OpenSSH within jail.
if [ "${OPENSSH}" = "YES" ]
then
	SSHDIR=${JAILDIR}/usr/local/etc/ssh
	mkdir -m 755 -p ${SSHDIR}
	ssh-keygen -t rsa1 -N "" -f ${SSHDIR}/ssh_host_key
	ssh-keygen -t rsa -N "" -f ${SSHDIR}/ssh_host_rsa_key
	ssh-keygen -t dsa -N "" -f ${SSHDIR}/ssh_host_dsa_key
	cp -p /usr/local/etc/ssh/moduli ${SSHDIR}
	cp -p /usr/local/etc/ssh/ssh_config-dist ${SSHDIR}/ssh_config
	cp -p /usr/local/etc/ssh/sshd_config-dist ${SSHDIR}/sshd_config
	sed -e "s/#ListenAddress 0.0.0.0/ListenAddress ${JAILIP}/" \
		-e 's/#PermitRootLogin yes/PermitRootLogin yes/' \
		-e 's/PermitRootLogin no/#PermitRootLogin no/' \
		-i "" ${SSHDIR}/sshd_config
	mkdir ${JAILDIR}/usr/local/empty
	mkdir -m 700 ${JAILDIR}/root/.ssh
	cp -p /root/.ssh/authorized_keys ${JAILDIR}/root/.ssh
	cp -p /root/.ssh/authorized_keys2 ${JAILDIR}/root/.ssh
fi

# root's configuration.  Steal from the host.
cp -LR /root/.bashrc \
	/root/.cshrc \
	/root/.klogin \
	/root/.login \
	/root/.logout \
	/root/.profile \
	/root/.tcshrc \
	/root/.vim* \
	/root/.zfunc* \
	/root/.zlog* \
	/root/.zsh* ${JAILDIR}/root
mkdir -m 755 ${JAILDIR}/root/bin
chown -R root:wheel ${JAILDIR}/root

# Configure mail.
if [ "${SENDMAIL}" = "YES" ]
then
	if [ "${SENDMAILPORT}" = "YES" ]
	then
		cd /usr/ports/mail/sendmail && \
		make DESTDIR=${JAILDIR} \
			SENDMAIL=/usr/local/sbin/sendmail mailer.conf
	fi

	jail ${JAILDIR} ${JAILFQDN} ${JAILIP} /bin/sh -c \
		"cd /etc/mail; make ${JAILFQDN}.mc"

	if [ "${SENDMAILCERTS}" = "YES" ]
	then
		TEMPFILE=`mktemp -t sendmail`
		cd /usr/ports/mail/sendmail && \
		make DESTDIR=${JAILDIR} tls-install && \
		LINES=`grep Xdef files/tls-install.sh | \
			sed -e 's/^Xdef/def/' -e 's/dnl/\\\/'` && \
		cat ${JAILDIR}/etc/mail/${JAILFQDN}.mc | \
		sed -e "/^DOMAIN/a\\
			\\
			dnl TLS support.\\
			${LINES}" > ${TEMPFILE}
		mv -f ${TEMPFILE} ${JAILDIR}/etc/mail/${JAILFQDN}.mc
	fi

	cat <<- SEND_EOM >> ${JAILDIR}/etc/mail/local-host-names
		localhost
		${JAILFQDN}
	SEND_EOM

	cat <<- SEND_EOM >> ${JAILDIR}/etc/mail/virtusertable
		# E-mail for jail goes here.  Usually a base root elsewhere.
		@${DOMAIN}				${ROOTMAIL}
		@${JAILFQDN}				${ROOTMAIL}

		# Individual routing
		#someone@${DOMAIN}			someone@anotherdomain
		#someone@${JAILFQDN}			someone@anotherdomain

		# Complete domain routing except for root
		#@${DOMAIN}				someone@anotherdomain
		#@${JAILFQDN}				someone@anotherdomain
		#root@${DOMAIN}				someone@anotherdomain
		#root@${JAILFQDN}			someone@anotherdomain

		# Complete domain IMAP except for root
		#@${DOMAIN}				someone
		#@${JAILFQDN}				someone
		#root@${DOMAIN}				someone
		#root@${JAILFQDN}			someone
	SEND_EOM

	sed -e 's/DAEMON_OPTIONS(`Name=IPv6.*//' -i "" \
		${JAILDIR}/etc/mail/${JAILFQDN}.mc
	jail ${JAILDIR} ${JAILFQDN} ${JAILIP} /bin/sh -c \
		"cd /etc/mail; make install all aliases"
fi

# ldconfig
jail ${JAILDIR} ${JAILFQDN} ${JAILIP} /bin/sh -c \
	"/sbin/ldconfig -m /usr/local/lib"

# Setup PostgreSQL.
if [ "${POSTGRESQL}" = "YES" ]
then
	PGSQLDIR=${JAILDIR}/usr/local/pgsql
	install -d -o pgsql -g pgsql ${PGSQLDIR}
	cp -p /usr/local/pgsql/* ${PGSQLDIR}
	cp -p /usr/local/pgsql/.[A-z]* ${PGSQLDIR}
	pw -V ${JAILDIR}/etc groupadd pgsql -g 70
	pw -V ${JAILDIR}/etc useradd pgsql -u 70 -g 70 -h - \
		-d /usr/local/pgsql -c "PostgreSQL Daemon"
	install -m 755 /usr/ports/databases/postgresql7/files/pgsql.sh.tmpl \
		${RCDIR}/010.pgsql.sh
	sed -e 's/%%PREFIX%%/\/usr\/local/' -i "" ${RCDIR}/010.pgsql.sh
	jail ${JAILDIR} ${JAILFQDN} ${JAILIP} /bin/sh -c \
		"su - pgsql -c initdb"
fi

# SASL.
if [ "${SASL2}" = "YES" ]
then
	pw -V ${JAILDIR}/etc groupadd cyrus -g 60
	pw -V ${JAILDIR}/etc useradd cyrus -u 60 -g cyrus -d /nonexistent \
		-c "the cyrus mail server" -s /sbin/nologin -p '*'
	mkdir -p ${JAILDIR}/var/state/saslauthd
	chown -R cyrus:mail ${JAILDIR}/var/state/saslauthd
	chmod -R ug=rwx,o= ${JAILDIR}/var/state/saslauthd
	echo "pwcheck_method: saslauthd" > /usr/local/lib/sasl2/Sendmail.conf
	SASLAUTHPORTFILES=/usr/ports/security/cyrus-sasl2-saslauthd/files
	cp ${SASLAUTHPORTFILES}/saslauthd.sh ${RCDIR}
	sed -e 's/%%PREFIX%%/\/usr\/local/' \
		-e 's/%%RC_SUBR%%/\/usr\/local\/etc\/rc.subr/' -i "" \
		${RCDIR}/saslauthd.sh
	chmod 755 ${RCDIR}/saslauthd.sh
fi

# Enable secure IMAP.
if [ "${IMAP}" = "YES" ]
then
	# Create 'users' group for future users.
	pw -V ${JAILDIR}/etc groupadd users

	sed -e "s/#imap4/imap4/" -e "/^imap4/p;s/imap4/imaps/" \
		-i "" ${JAILDIR}/etc/inetd.conf
	cd /usr/ports/mail/imap-uw
	rm -f /usr/local/certs/ipop3d.pem
	printf "${CERTVALUES}" | make cert
	cd /usr/local/openssl/certs
	sed -n '/-----BEGIN CERTIFICATE-----/,$p' /usr/local/certs/imapd.pem > \
		imapd.pem
	ln -fs imapd.pem `openssl x509 -noout -hash -in imapd.pem`.0

	# Create simple script to make a mail-only user within jail.
	cat <<- 'SCRIPTEOM' >> ${JAILDIR}/root/bin/mkmailuser.sh
		#!/bin/sh

		pw useradd $1 -c "" -d /nonexistant -g users -s /sbin/nologin -w yes
	SCRIPTEOM
	chmod 700 ${JAILDIR}/root/bin/mkmailuser.sh
fi

