#!/bin/sh
#
# /usr/local/bin/localuserconfig
# Copyright 2004-2006 Jonas Smedegaard <dr@jones.dk>
#
# $Id: localuserconfig,v 1.8 2006-07-16 12:29:16 jonas Exp $
#
# Set/change local account settings
#
# TODO: Use the following syntax to add info to .smbpasswd
#   grep -q SomeOption ~/file || echo "line with SomeOption and such" >> ~/file
#
# TODO: Move relevant stuff from user-init and make it use this instead
# TODO: Use getopt, and implement --help
# TODO: Implement runmodes noninteractive and force (in addition to the default: interactive)
# TODO: Runmode noninteractive by default if no tty attached
# TODO: Implement verbosity levels (0=quiet 1=oneliner 2=default 3=chatty 4=debug)

set -e

# config (edit /etc/local/users.conf to override)

# which are user accounts (adduser values are used if empty)
first_uid=""
last_uid=""

do_quota="no"    # Manage disk quota
do_distrib="no"  # Distributed shares (software archive)
do_personal="no" # Personal shares (mac, pc, public_html)
do_xchange="no"  # Group-readable shares
do_public="no"   # Public share (web homepage)
do_mac="no"      # AppleShare-optimized share (netatalk)
do_pc="no"       # SMB-ptimized share (Samba)
do_server="no"   # Personal share on remote SMB server

quota_roots="" # space-delimited list of disk devices
quota_soft="100000"
quota_hard="1000000"
quota_newstyle="yes" # Woody used a different syntax...

xchange_root="xchange"
xchange_sharedroot="/home/XCHANGE"

mac_root="mac"

pc_root="pc"

server_name="SERVER" # SMB name of remote server 
server_desc="remote server" 
server_root="server"
server_conf="/etc/security/pam_mount.conf"
server_userconf=".winpassword"

### No servicable parts below this line! ###

if [ -e /etc/adduser.conf ]; then
	. /etc/adduser.conf
else
	echo "/etc/adduser.conf missing. Exiting..."
	exit 1
fi

[ -r /etc/local/users.conf ] && . /etc/local/users.conf

# Flags used internally
root_required="no"
runmode="interactive"

user="`id -u -n`"
uid="`id -u`"
HOME="`getent passwd \"$user\" | awk -F: '{print $6}' | head -n 1`"
#TODO: Allow root to pass the above as options

# Safety checks (disable silently - the user can't correct it anyway)

[ "$do_mac" = "yes" -a -n "$mac_root" ] || do_mac="no"
[ "$do_pc" = "yes" -a -n "$pc_root" ] || do_pc="no"
[ "$do_xchange" = "yes" -a -n "$xchange_root" ] || do_xchange="no"
[ "$do_server" = "yes" -a -n "$server_root" ] || do_server="no"
#TODO: do a loop instead for the above

# only do user accounts (checked against /etc/adduser.conf values)
[ -n "$first_uid" ] || first_uid="$FIRST_UID"
[ -n "$last_uid" ] || last_uid="$LAST_UID"
[ "$uid" -ge "$FIRST_UID" -a "$uid" -le "$LAST_UID" ] || exit 0
#TODO: check if above is numeric
#TODO: Always use adduser values as strict outer limits

if [ -z "$HOME" ]; then
	echo "Error: Unable to resolve home of user $user!"
	exit 1
fi
if [ ! -d "$HOME" ]; then
	echo "Error: Home of user $user doesn't exist: \"$HOME\"!"
	exit 1
fi

if [ "$do_server" = "yes" ]; then
	server_edit="1"
	if [ -r "$HOME/$server_userconf" ]; then
		server_username="$(grep '^username' $HOME/$server_userconf | awk -F= '{print $2}' | head -n 1 | awk '{print $1}')"
		server_password="$(grep '^password' $HOME/$server_userconf | awk -F= '{print $2}' | head -n 1 | awk '{print $1}')"
	fi
	if [ -n "$server_username" ]; then
		server_edit=""
		echo -n "Account info for $server_desc already exists. Edit (y/N)? "
		read server_overwrite
		case $server_overwrite in
		    y|Y)
			server_edit="1"
			;;
		esac
	else
		server_username=$user
	fi
	if [ "$server_edit" = "1" ]; then
		if [ -n "$server_username" ]; then
			echo -n "Username on $server_desc ($server_username): "
		else
			echo -n "Username on $server_desc: "
		fi
		read server_username_new
		if [ -n "$server_username_new" ]; then
			server_username="$server_username_new"
		fi
		echo -n "Password on $server_desc: "
		read -s server_password
		echo
		echo -n "Password once more: "
		read -s server_password_again
		echo
		if [ -n "$server_username" -a "$server_password" = "$server_password_again" ]; then
			echo "username = $server_username" > $HOME/$server_userconf
			echo "password = $server_password" >> $HOME/$server_userconf
			chmod 0600 $HOME/$server_userconf
		else
			echo "Setting server login info failed: problem getting either username or password"
		fi
	fi
	if grep -v -q "^volume $user " "$server_conf"; then
		root_required="yes"
	fi
fi

#if [ "$root_required" = "yes" ]; then
#	echo "Note: Some of the current setup requires action by systems administrator"
#TODO: Re-enable this, but only when able to suppress by root
#TODO: send email to root, unless invoked by root
#TODO: Collect actual items needing attention, to print and include in email
#fi

exit 0
#FIXME: The remaining is to be implemented (lifted from user-init)

#if [ -x /etc/local/quota.sh ]; then
#	/etc/local/quota.sh $user
#	fi
[ $quota_soft ] || quota_soft="0"
[ $quota_hard ] || quota_hard="0"
for quota_root in $quota_roots; do
	if [ $quota_newstyle ]; then
		setquota $user $quota_soft $quota_hard 0 0 $quota_root
	else
		setquota $user $quota_root $quota_soft $quota_hard 0 0
	fi
done

mkdir -p $HOME/mail
if [ "$USE_MBOX" ]; then
	touch $HOME/mail/mbox
elif [ -f $HOME/mail/mbox -a ! -s $HOME/mail/mbox ]; then
	rm -f $HOME/mail/mbox
fi

if [ $NETATALK ]; then
	mkdir -p $HOME/$mac_root
fi
if [ $SAMBA ]; then
	mkdir -p $HOME/$pc_root
fi

if [ $XCHANGE ]; then
	mkdir -p $xchange_sharedroot/users/root/$user
fi

if [ $PUBLIC ]; then
	mkdir -p $HOME/public_html
fi

chown $user: $HOME
chmod u=rwX,go=rX $HOME

# Mail handling
chown -R $user: $HOME/mail
chmod -R u=rw,go=,u+X $HOME/mail
if [ -f $HOME/.mailboxlist ]; then
	chown $user: $HOME/.mailboxlist
	chmod 0640 $HOME/.mailboxlist
fi
if [ -f $HOME/.forward ]; then
	chown $user: $HOME/.forward
	chmod 0640 $HOME/.forward
fi
if [ -f /var/mail/$user ]; then
	chown $user:mail /var/mail/$user
	chmod ug=rw,o= /var/mail/$user
elif [ -f /var/spool/mail/$user ]; then
	chown $user:mail /var/spool/mail/$user
	chmod ug=rw,o= /var/spool/mail/$user
fi

# MySQL handling
if [ -f $HOME/.my.cnf ]; then
	chown $user: $HOME/.my.cnf
	chmod 0600 $HOME/.my.cnf
fi

# Mac dir permissions
if [ -d $HOME/$mac_root ]; then
	chown -R $user: $HOME/$mac_root
	chmod -R u=rw,g=r,o=,ug+X $HOME/$mac_root
	rm -rf $HOME/$mac_root/Network\ Trash\ Folder
	mkdir $HOME/$mac_root/Network\ Trash\ Folder
	chown nobody: $HOME/$mac_root/Network\ Trash\ Folder
	chmod a= $HOME/$mac_root/Network\ Trash\ Folder
fi

# PC dir permissions
if [ -d $HOME/$pc_root ]; then
	chown -R $user: $HOME/$pc_root
	chmod -R u=rw,g=r,o=,ug+X $HOME/$pc_root
fi
	
# Exchange dir permissions
if [ -d $xchange_sharedroot/users/root/$user ]; then
	chown -R $user:users $xchange_sharedroot/users/root/$user
	chmod -R g=r,g+X $xchange_sharedroot/users/root/$user
	if [ -e "x$HOME/$xchange_root" ]; then
		if [ -L "x$HOME/$xchange_root" ]; then
			ln -sf $xchange_sharedroot/users/root/$user $HOME/$xchange_root
		else
			echo "ERROR: $HOME/$xchange_root exists already. Leaving it as is..."
		fi
	else
		ln -s $xchange_sharedroot/users/root/$user $HOME/$xchange_root
	fi
fi

# Public dir permissions
if [ -d $HOME/public_html ]; then
	chown -R $user: $HOME/public_html
	chmod -R u+rX,go=r,go+X $HOME/public_html
	if [ $NETATALK ]; then
		rm -rf $HOME/public_html/Network\ Trash\ Folder
		mkdir $HOME/public_html/Network\ Trash\ Folder
		chown nobody: $HOME/public_html/Network\ Trash\ Folder
		chmod a= $HOME/public_html/Network\ Trash\ Folder
	fi
fi

# Fileshares: <home>/shares.<sharetype>/<rogroup>/<rwgroup>/<sharename>
#   <sharetype>: Either mac or win depending on which of netatalk and samba provides r/w access to the shares
#   <rwgroup>:   Group with write access to the share (usually the default group of the owner)
#   <rogroup>:   Either rwgroup or secondary group with read-only access to the share
#   owner must be member of both groups, and rwgroup members must also be members of rogroup
find "$HOME" -mindepth 1 -maxdepth 1 -type d -print | egrep "^$HOME/shares\." | (while read thisdir; do
	sharetype="`basename \"$thisdir\" | awk -F. '{print $2}'`"
	# Define dir and file exceptions
	case "$sharetype" in
	    mac)
		dirs_world_rw_create='.AppleDB'
		dirs_group_rw_create='.AppleDesktop/Temporary Items/TheFindByContentFolder'
		dirs_group_ro_create='TheVolumeSettingsFolder'
		dirs_group_ro_update='.AppleDouble'
		files_group_ro_update=':2eDS_Store'
		dirs_no_access_purge='Network Trash Folder'
		;;
	    win)
		;;
	    *)
		continue
		;;
	esac
	exceptions="$dirs_world_rw_create/$dirs_group_rw_create/$dirs_group_ro_create/$dirs_group_ro_update/$files_group_ro_update/$dirs_no_access_purge"
	exception_dirs_create="$dirs_world_rw_create/$dirs_group_rw_create/$dirs_group_ro_create"
	chown "$user": "$thisdir"
	chmod a=rX "$thisdir"
	find "$thisdir" -mindepth 1 -maxdepth 1 -type d -print | (while read thisdir; do
		rogroup="`basename \"$thisdir\"`"
		chown "$user":"$rogroup" "$thisdir"
		chmod ug=rX,o= "$thisdir"
		find "$thisdir" -mindepth 1 -maxdepth 1 -type d -print | (while read thisdir; do
			rwgroup="`basename \"$thisdir\"`"
			chown "$user":"$rwgroup" "$thisdir"
			chmod a=rX,g+s "$thisdir"
			find "$thisdir" -mindepth 1 -maxdepth 1 -type d -print | (while read thisdir; do
				sharename="`basename \"$thisdir\"`"
				chown "$user":"$rwgroup" "$thisdir"
				chmod u=rw,go=r,a+X,g+s "$thisdir"
				ifs="$IFS"
				# Set default permissions
				find "$thisdir" -mindepth 1 -maxdepth 1 -print | (while read thisdir; do
					item="`basename \"$thisdir\"`"
					IFS="/"; for exception in $exceptions; do IFS="$ifs";
						if [ "$item" = "$exception" ]; then
							continue 2
						fi
					done
					chgrp -R "$rwgroup" "$thisdir"
					chmod -R ug=rw,o=r,a+X,g+s "$thisdir"
				done)
				# Handle exception dirs to be created if not existing
				IFS="/"; for dir in $exception_dirs_create; do IFS="$ifs";
					if [ ! -d "$thisdir/$dir" ]; then
						rm -f "$thisdir/$dir"
					fi
					if [ ! -e "$thisdir/$dir" ]; then
						mkdir "$thisdir/$dir"
					fi
					chown "$user":"$rwgroup" "$thisdir/$dir"
				done
				IFS="/"; for dir in $dirs_world_rw_create; do IFS="$ifs";
					if [ "$rogroup" = "$rwgroup" ]; then
						chmod -R ug=rw,o=r,a+X,g+s "$thisdir/$dir"
					else
						chmod -R a=rw,a+X,g+s "$thisdir/$dir"
					fi
				done
				IFS="/"; for dir in $dirs_group_rw_create; do IFS="$ifs";
					chmod -R ug=rw,o=r,a+X,g+s "$thisdir/$dir"
				done
				IFS="/"; for dir in $dirs_group_ro_create; do IFS="$ifs";
					chmod -R u=rw,go=r,a+X,g+s "$thisdir/$dir"
				done
				# Handle exception dirs to be updated if already there
				IFS="/"; for dir in $dirs_group_ro_update; do IFS="$ifs";
					if [ -e "$thisdir/$dir" ]; then
						chmod u=rw,go=r,a+X,g+s "$thisdir/$dir"
					fi
				done
				# Handle exception files to be updated if already there
				IFS="/"; for file in $files_group_ro_update; do IFS="$ifs";
					if [ -e "$thisdir/$file" ]; then
						chmod u=rw,go=r,g+s "$thisdir/$file"
					fi
				done
				# Handle exception dirs to be purged and recreated
				IFS="/"; for dir in $dirs_no_access_purge; do IFS="$ifs";
					rm -rf "$thisdir/$dir"
					mkdir -m a= "$thisdir/$dir"
					chown nobody: "$thisdir/$dir"
				done
				IFS="$ifs"
			done)
		done)
	done)
done)

# Deprecated share permissions
for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/shares_win"`; do
	chgrp -R $user $dir
	chmod -R u=rw,g=rw,o=,ug+X,g+s $dir
done
for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/shares_mac"`; do
	chgrp -R $user $dir
	chmod -R u=rw,g=rw,o=,ug+X,g+s $dir
	rm -rf $dir/Network\ Trash\ Folder
	mkdir $dir/Network\ Trash\ Folder
	chown nobody: $dir/Network\ Trash\ Folder
	chmod a= $dir/Network\ Trash\ Folder
done

# Ftp shares permissions
for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/ftp_$USER$"`; do
	chgrp -R $user $dir
	chmod -R ug=rw,o=r,a+X,g+s $dir
	rm -rf $dir/Network\ Trash\ Folder
	mkdir $dir/Network\ Trash\ Folder
	chown nobody: $dir/Network\ Trash\ Folder
	chmod a= $dir/Network\ Trash\ Folder
done
for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/ftp_${USER}_ro$"`; do
	chown -R $user: $dir
	chmod -R u=rw,go=r,a+X $dir
	rm -rf $dir/Network\ Trash\ Folder
	mkdir $dir/Network\ Trash\ Folder
	chown nobody: $dir/Network\ Trash\ Folder
	chmod a= $dir/Network\ Trash\ Folder
done

# Web shares permissions
for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/web_"`; do
	chown -R $user: $dir
#	chmod -R u=rw,go=r,a+X $webdir
#TODO: Only cgi scripts (.cgi and .pl) should be executable
	chmod -R u+rw,go+r,a+X $dir
	# leftover from ancient times with another policy
	if [ $NETATALK ]; then
		rm -rf $dir/Network\ Trash\ Folder
	fi
done
	
# Web shares permissions
for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/websites"`; do
	chown root: $dir
	chmod a=r,u+w,a+X $dir
done
for dir in `find $HOME -mindepth 2 -maxdepth 2 -type d | egrep "^$HOME/websites/"`; do
	chown -R $user: $dir
#	chmod -R u=rw,go=r,a+X $webdir
#TODO: Only cgi scripts (.cgi and .pl) should be executable
	chmod -R u+rw,go+r,a+X $dir
	# leftover from ancient times with another policy
	if [ $NETATALK ]; then
		rm -rf $dir/Network\ Trash\ Folder
	fi
done
for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/webscripts"`; do
	chown root: $dir
	chmod a=r,u+w,a+X $dir
done
for dir in `find $HOME -mindepth 2 -maxdepth 2 -type d | egrep "^$HOME/webscripts/"`; do
	chown -R $user: $dir
#	chmod -R u=rw,go=r,a+X $webdir
#TODO: Only cgi scripts (.cgi and .pl) should be executable
	chmod -R u+rw,go+r,a+X $dir
done
for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/webdata"`; do
	chown $user: $dir
	chmod a=r,u+w,a+X $dir
done
for dir in `find $HOME -mindepth 2 -maxdepth 2 -type d | egrep "^$HOME/webdata/"`; do
	chown -R $user: $dir
	chmod -R u=rw,go=,u+X $dir
done
for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/webshareddata"`; do
	chown $user: $dir
	chmod a=r,u+w,a+X $dir
done
for dir in `find $HOME -mindepth 2 -maxdepth 2 -type d | egrep "^$HOME/webshareddata/"`; do
	chown -R $user: $dir
	chmod -R u=rw,go=r,a+X $dir
done
for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/webphpsites"`; do
	chown root: $dir
	chmod u=rw,go=r,a+X $dir
done
for dir in `find $HOME -mindepth 2 -maxdepth 2 -type d | egrep "^$HOME/webphpsites/"`; do
	chown -R $user:www-data $dir
#	chmod -R ug=rw,o=r,a+X $dir
	chmod -R ug=rw,o=,ug+X $dir
done
for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/webphpdata"`; do
	chown root: $dir
	chmod a=r,u+w,a+X $dir
done
for dir in `find $HOME -mindepth 2 -maxdepth 2 -type d | egrep "^$HOME/webphpdata/"`; do
	chown -R $user:www-data $dir
	chmod -R ug=rw,o=,ug+X $dir
done
	
# Dummy user restrictions
if [ -n "$REALUSERS_GROUPNAME" -a -n "$DUMMYSHAREDIR" -a -n "$DUMMYSHAREOWNER" -a -n "$DUMMYSHARENAME" ]; then
	[ -e $DUMMYSHAREDIR/$user ] \
		|| mkdir $DUMMYSHAREDIR/$user
	chown $DUMMYSHAREOWNER: $DUMMYSHAREDIR/$user
	chmod u=rw,go=r,a+X $DUMMYSHAREDIR/$user
	if [ -e $HOME/$DUMMYSHARENAME ]; then
		if [ -L $HOME/$DUMMYSHARENAME ]; then
			ln -sf $DUMMYSHAREDIR/$user $HOME/$DUMMYSHARENAME
			chown $user: $HOME/$DUMMYSHARENAME
		else
			echo "WARNING: $HOME/$DUMMYSHAREDIR exists already. Leaving it as is..."
		fi
	else
		ln -s $DUMMYSHAREDIR/$user $HOME/$DUMMYSHARENAME
		chown $user: $HOME/$DUMMYSHARENAME
	fi
	if [ -n "$DUMMYAPACHECFG" -a -n "$DUMMYAPACHESHAREDIR" ]; then
		if [ -f /etc/apache/include.d/$DUMMYAPACHECFG -a -x /etc/init.d/apache ]; then
			if [ -e /etc/apache/include.d/$DUMMYAPACHECFG-$user ]; then
				echo "/etc/apache/include.d/$DUMMYAPACHECFG-$user exists already. Ignoring..."
			else
				echo "# Created automatically by adduser.local
<Location /$DUMMYAPACHESHAREDIR/$user>
	<Limit GET POST>
		require user $user
	</Limit>
</Location>" \
					> /etc/apache/include.d/$DUMMYAPACHECFG-$user
				root_required="yes"
			fi
		fi
	fi
fi