<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<html>
I (apparently like lots of others:-) had problems creating homedirs before
they were needed by Samba in our combined middle/high school. Scripts that
used to work in a simpler environment (only one Samba fileserver which
was also the sole Domain Controller) didn't always work in more complex
environments (more than one Samba fileserver, BDCs as well as PDC). And
seemingly cleverer techniques (ex: the PHP exec(...) function) didn't work
either.
<p>The reason? In a multi-server environment the computer I'm working on
(for example the LDAP master) isn't necessarily the computer where the
homedir needs to exist. I could have made it work by turning off most security
and invoking something like `rsh/rlogin` all over the place, but doing
that seemed way too reckless and risky for even a mildly security-conscious
network.
<p>I solved my problem by configuring Samba to "create" any homedirs it
finds it needs when the first logon to that share occurs (sort of a "just
in time" solution). Although this is neither rocket science nor new, I
couldn't find any code to "borrow" and so had to roll my own. To save some
effort for the next person who faces the same problem I faced, here's the
code that works for me:
<br> 
<p>========== relevant line in smb.conf ==================
<blockquote><font color="#330000">...</font>
<br><font color="#330000">[homes]</font>
<br><font color="#330000">...</font>
<br><b><font color="#330000"> root preexec = /usr/local/sbin/folderhomeuser-initial.sh
%u</font></b>
<br><font color="#330000">...</font></blockquote>

<p><br>========== new script folderhomeuser-initial.sh ==========
<blockquote><font color="#330000"><font size=-1>#!/bin/bash</font></font><font color="#330000"><font size=-1></font></font>
<p><font color="#330000"><font size=-1>## Input arguments</font></font>
<br><font color="#330000"><font size=-1>##  username (required)</font></font><font color="#330000"><font size=-1></font></font>
<p><font color="#330000"><font size=-1>## other assumed inputs:</font></font>
<br><font color="#330000"><font size=-1>##  directory and contents
/sambahome/sambahomeskel set up exactly the way</font></font>
<br><font color="#330000"><font size=-1>##  it's wanted, including
permissions/acls</font></font><font color="#330000"><font size=-1></font></font>
<p><font color="#330000"><font size=-1>## OUTPUT STATUS VALUES</font></font>
<br><font color="#330000"><font size=-1>##  0 - no error</font></font>
<br><font color="#330000"><font size=-1>##  1 - help (probably because
invalid arguments)</font></font>
<br><font color="#330000"><font size=-1>##  2 - invalid username</font></font>
<br><font color="#330000"><font size=-1>##  3 - user's home directory
already exists</font></font><font color="#330000"><font size=-1></font></font>
<p><font color="#330000"><font size=-1>if [[ $# -ne 1 || "$1" =~ '^[-\.?"/\/]'
]]; then</font></font>
<br><font color="#330000"><font size=-1> echo "usage: `basename $0`
username"</font></font>
<br><font color="#330000"><font size=-1> echo " Create new/empty home
directory."</font></font>
<br><font color="#330000"><font size=-1> echo " Can be run meaningfully
only by root."</font></font>
<br><font color="#330000"><font size=-1> exit 1</font></font>
<br><font color="#330000"><font size=-1>fi</font></font><font color="#330000"><font size=-1></font></font>
<p><font color="#330000"><font size=-1>function firstword ()</font></font>
<br><font color="#330000"><font size=-1>{</font></font>
<br><font color="#330000"><font size=-1> echo $1</font></font>
<br><font color="#330000"><font size=-1>}</font></font><font color="#330000"><font size=-1></font></font>
<p><font color="#330000"><font size=-1>function thirdword ()</font></font>
<br><font color="#330000"><font size=-1>{</font></font>
<br><font color="#330000"><font size=-1> echo $3</font></font>
<br><font color="#330000"><font size=-1>}</font></font><font color="#330000"><font size=-1></font></font>
<p><font color="#330000"><font size=-1>function sixthword ()</font></font>
<br><font color="#330000"><font size=-1>{</font></font>
<br><font color="#330000"><font size=-1> echo $6</font></font>
<br><font color="#330000"><font size=-1>}</font></font><font color="#330000"><font size=-1></font></font>
<p><font color="#330000"><font size=-1>function gethomedir ()</font></font>
<br><font color="#330000"><font size=-1>{</font></font>
<br><font color="#330000"><font size=-1> HOMEDIR=`eval echo ~$1`</font></font>
<br><font color="#330000"><font size=-1> if [ `expr "$HOMEDIR" : '\(.\)'`
= '~' ]; then</font></font>
<br><font color="#330000"><font size=-1>  echo "username  $1 
is not valid"</font></font>
<br><font color="#330000"><font size=-1>  return 2</font></font>
<br><font color="#330000"><font size=-1> fi</font></font>
<br><font color="#330000"><font size=-1> # strip trailing slash if
it exists</font></font>
<br><font color="#330000"><font size=-1> HOMEDIR=${HOMEDIR%/}</font></font>
<br><font color="#330000"><font size=-1> echo $HOMEDIR</font></font>
<br><font color="#330000"><font size=-1>}</font></font><font color="#330000"><font size=-1></font></font>
<p><font color="#330000"><font size=-1>function makeparentdirs () {</font></font>
<br><font color="#330000"><font size=-1> ONE=${1%/} # strip any trailing
slash that might mess up follow RE</font></font>
<br><font color="#330000"><font size=-1> PARENT=`expr "$ONE" : '\(.*\)/'`</font></font>
<br><font color="#330000"><font size=-1> mkdir -p $PARENT</font></font>
<br><font color="#330000"><font size=-1>}</font></font><font color="#330000"><font size=-1></font></font>
<p><font color="#330000"><font size=-1>PRIMARYGROUP=`id -g $1`</font></font><font color="#330000"><font size=-1></font></font>
<p><font color="#330000"><font size=-1>HOMEDIR=`gethomedir $1`</font></font>
<br><font color="#330000"><font size=-1>RETCODE=$?</font></font>
<br><font color="#330000"><font size=-1>if [ $RETCODE -ne 0 ]; then echo
$HOMEDIR; exit $RETCODE; fi</font></font><font color="#330000"><font size=-1></font></font>
<p><font color="#330000"><font size=-1>if [ -e $HOMEDIR ]; then</font></font>
<br><font color="#330000"><font size=-1> echo "$HOMEDIR (home for
$1) already exists"</font></font>
<br><font color="#330000"><font size=-1> exit 2</font></font>
<br><font color="#330000"><font size=-1>fi</font></font><font color="#330000"><font size=-1></font></font>
<p><font color="#330000"><font size=-1>makeparentdirs $HOMEDIR</font></font><font color="#330000"><font size=-1></font></font>
<p><font color="#330000"><font size=-1>cp -r -p /sambahome/sambahomeskel
$HOMEDIR</font></font>
<br><font color="#330000"><font size=-1># although we know this won't work
right if there's a trailing slash on</font></font>
<br><font color="#330000"><font size=-1># HOMEDIR, we can confidently assume
it's not the case since gethomedir</font></font>
<br><font color="#330000"><font size=-1># never returns such a result</font></font><font color="#330000"><font size=-1></font></font>
<p><font color="#330000"><font size=-1>chown -R $1:$PRIMARYGROUP $HOMEDIR</font></font>
<br><font color="#330000"><font size=-1># we assume permissions/acls were
already correct on the skeleton, because</font></font>
<br><font color="#330000"><font size=-1># although we could set permissions/acls
here we don't because it's too slow</font></font><font color="#330000"><font size=-1></font></font>
<p><font color="#330000"><font size=-1>logger -p daemon.info "successfully
created and populated $HOMEDIR for $1"</font></font>
<br><font color="#330000"><font size=-1>echo "$HOMEDIR (home for $1) created
and populated"</font></font>
<br><font color="#330000"><font size=-1>exit 0</font></font></blockquote>

<p><br>(The coding style of the script isn't all that great; improvements
are clearly possible. The upside is it does work.)
<p>(Note this creates new homedirs with whatever initial content you desire
by copying a template [similar to /etc/skel which is used for local logins],
specifically in this case /sambahome/sambahomeskel].)
<p>(Note this setup assumes that scripts can find a user's Samba home directory
path <u>from the *nix side</u> without any help from Samba, even if the
user is defined in LDAP and even if the user isn't able to directly logon
to the *nix system. This will be true so long as you've used `authconfig
--enableldap` so your /etc/nsswitch.conf specifies both "files" and "ldap"
on its "passwd" line. Provided this is true, you can just use the `bash`
tilde shortand [~<i><font size=-1>username</font></i>] to find a user's
homedir. It should also be possible [although arguably less flexible:-]
to eliminate this assumption and instead have Samba pass the home directory
path to the script as a calling argument.)
<p>I hope this helps somebody. Enjoy!
<br>--
<br>Chuck Kollars
<br> </html>