summaryrefslogtreecommitdiff
path: root/user-init
blob: 5582200222a3eb3a2c2e3326956989bab2be8362 (plain)
  1. #!/bin/sh
  2. set -e
  3. # reset flags
  4. apache_reload_needed=""
  5. runmode="normal"
  6. # subfolder name defaults (edit /etc/local/users.conf to override)
  7. mac="mac" # Optimized for sharing through AppleShare (netatalk)
  8. pc="pc" # Optimized for sharing though SMB/CIFS (Samba)
  9. xchange="xchange" # Readable by group
  10. if [ -e /etc/adduser.conf ]; then
  11. . /etc/adduser.conf
  12. else
  13. echo "/etc/adduser.conf missing. Exiting..."
  14. exit 1
  15. fi
  16. [ -r /etc/local/users.conf ] && . /etc/local/users.conf
  17. # exit silently if this system lacks required hints
  18. [ -r /etc/local/volumes ] && . /etc/local/volumes || exit 0
  19. XDIRREAL="$XDIR/users/root"
  20. if [ -n "$XCHANGE" ]; then
  21. if [ ! -d "$XDIR" ]; then
  22. echo "XDIR doesn't exist. Ignoring XCHANGE!"
  23. XCHANGE=""
  24. fi
  25. fi
  26. if [ $# -gt 0 ]; then
  27. USERS=$*
  28. else
  29. # USERS=`getent passwd | awk -F: '{print $1}'`
  30. echo "uid required!"
  31. exit 1
  32. fi
  33. [ -n "$NETATALK_HOME" ] && mac="$NETATALK_HOME"
  34. [ -n "$SAMBA_HOME" ] && pc="$SAMBA_HOME"
  35. [ -n "$XCHANGE_HOME" ] && xchange="$XCHANGE_HOME"
  36. echo "Setting up additional folders and permissions..."
  37. for user in $USERS; do
  38. uid="`getent passwd \"$user\" | awk -F: '{print $3}' | head -1`"
  39. HOME="`getent passwd \"$user\" | awk -F: '{print $6}' | head -1`"
  40. if [ -z "$HOME" ]; then
  41. echo "User $user doesn't exist. Ignoring..."
  42. continue
  43. fi
  44. # Ignore non-human accounts silently
  45. [ "$uid" -ge "$FIRST_UID" -a "$uid" -le "$LAST_UID" ] || continue
  46. [ -d $HOME ] || continue
  47. # [ -L $HOME ] && continue
  48. echo -n $user
  49. # if [ -x /etc/local/quota.sh ]; then
  50. # /etc/local/quota.sh $user
  51. # fi
  52. [ $QUOTASOFT ] || QUOTASOFT="0"
  53. [ $QUOTAHARD ] || QUOTAHARD="0"
  54. for QUOTAHOME in $QUOTAHOMES; do
  55. if [ $NEW_QUOTA ]; then
  56. setquota $user $QUOTASOFT $QUOTAHARD 0 0 $QUOTAHOME
  57. else
  58. setquota $user $QUOTAHOME $QUOTASOFT $QUOTAHARD 0 0
  59. fi
  60. done
  61. mkdir -p $HOME/mail
  62. if [ "$USE_MBOX" ]; then
  63. touch $HOME/mail/mbox
  64. elif [ -f $HOME/mail/mbox -a ! -s $HOME/mail/mbox ]; then
  65. rm -f $HOME/mail/mbox
  66. fi
  67. if [ $NETATALK ]; then
  68. mkdir -p $HOME/$mac
  69. fi
  70. if [ $SAMBA ]; then
  71. mkdir -p $HOME/$pc
  72. fi
  73. if [ $XCHANGE ]; then
  74. mkdir -p $XDIRREAL/$user
  75. fi
  76. if [ $PUBLIC ]; then
  77. mkdir -p $HOME/public_html
  78. fi
  79. chown $user: $HOME
  80. chmod u=rwX,go=rX $HOME
  81. # Mail handling
  82. chown -R $user: $HOME/mail
  83. chmod -R u=rw,go=,u+X $HOME/mail
  84. if [ -f $HOME/.mailboxlist ]; then
  85. chown $user: $HOME/.mailboxlist
  86. chmod 0640 $HOME/.mailboxlist
  87. fi
  88. if [ -f $HOME/.forward ]; then
  89. chown $user: $HOME/.forward
  90. chmod 0640 $HOME/.forward
  91. fi
  92. if [ -f /var/mail/$user ]; then
  93. chown $user:mail /var/mail/$user
  94. chmod ug=rw,o= /var/mail/$user
  95. elif [ -f /var/spool/mail/$user ]; then
  96. chown $user:mail /var/spool/mail/$user
  97. chmod ug=rw,o= /var/spool/mail/$user
  98. fi
  99. # MySQL handling
  100. if [ -f $HOME/.my.cnf ]; then
  101. chown $user: $HOME/.my.cnf
  102. chmod 0600 $HOME/.my.cnf
  103. fi
  104. # Mac dir permissions
  105. if [ -d $HOME/$mac ]; then
  106. chown -R $user: $HOME/$mac
  107. chmod -R u=rw,g=r,o=,ug+X $HOME/$mac
  108. rm -rf $HOME/$mac/Network\ Trash\ Folder
  109. mkdir $HOME/$mac/Network\ Trash\ Folder
  110. chown nobody: $HOME/$mac/Network\ Trash\ Folder
  111. chmod a= $HOME/$mac/Network\ Trash\ Folder
  112. fi
  113. # PC dir permissions
  114. if [ -d $HOME/$pc ]; then
  115. chown -R $user: $HOME/$pc
  116. chmod -R u=rw,g=r,o=,ug+X $HOME/$pc
  117. fi
  118. # Exchange dir permissions
  119. if [ -d $XDIRREAL/$user ]; then
  120. chown -R $user:users $XDIRREAL/$user
  121. chmod -R g=r,g+X $XDIRREAL/$user
  122. if [ -e "x$HOME/$xchange" ]; then
  123. if [ -L "x$HOME/$xchange" ]; then
  124. ln -sf $XDIRREAL/$user $HOME/$xchange
  125. else
  126. echo "ERROR: $HOME/$xchange exists already. Leaving it as is..."
  127. fi
  128. else
  129. ln -s $XDIRREAL/$user $HOME/$xchange
  130. fi
  131. fi
  132. # Public dir permissions
  133. if [ -d $HOME/public_html ]; then
  134. chown -R $user: $HOME/public_html
  135. chmod -R u+rX,go=r,go+X $HOME/public_html
  136. if [ $NETATALK ]; then
  137. rm -rf $HOME/public_html/Network\ Trash\ Folder
  138. mkdir $HOME/public_html/Network\ Trash\ Folder
  139. chown nobody: $HOME/public_html/Network\ Trash\ Folder
  140. chmod a= $HOME/public_html/Network\ Trash\ Folder
  141. fi
  142. fi
  143. # Fileshares: <home>/shares.<sharetype>/<rogroup>/<rwgroup>/<sharename>
  144. # <sharetype>: Either mac or win depending on which of netatalk and samba provides r/w access to the shares
  145. # <rwgroup>: Group with write access to the share (usually the default group of the owner)
  146. # <rogroup>: Either rwgroup or secondary group with read-only access to the share
  147. # owner and rwgroup members must be member of both groups
  148. find "$HOME" -mindepth 1 -maxdepth 1 -type d -print | egrep "^$HOME/shares\." | (while read thisdir; do
  149. sharetype="`basename \"$thisdir\" | awk -F. '{print $2}'`"
  150. # Define dir and file exceptions
  151. case "$sharetype" in
  152. mac)
  153. dirs_world_rw_create='.AppleDB'
  154. dirs_group_rw_create='.AppleDesktop/Temporary Items/TheFindByContentFolder'
  155. dirs_group_ro_create='TheVolumeSettingsFolder'
  156. dirs_group_ro_update='.AppleDouble'
  157. files_group_ro_update=':2eDS_Store'
  158. dirs_no_access_purge='Network Trash Folder'
  159. ;;
  160. win)
  161. ;;
  162. *)
  163. continue
  164. ;;
  165. esac
  166. 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"
  167. exception_dirs_create="$dirs_world_rw_create/$dirs_group_rw_create/$dirs_group_ro_create"
  168. chown "$user": "$thisdir"
  169. chmod a=rX "$thisdir"
  170. find "$thisdir" -mindepth 1 -maxdepth 1 -type d -print | (while read thisdir; do
  171. rogroup="`basename \"$thisdir\"`"
  172. chown "$user":"$rogroup" "$thisdir"
  173. chmod ug=rX,o= "$thisdir"
  174. find "$thisdir" -mindepth 1 -maxdepth 1 -type d -print | (while read thisdir; do
  175. rwgroup="`basename \"$thisdir\"`"
  176. chown "$user":"$rwgroup" "$thisdir"
  177. chmod a=rX,g+s "$thisdir"
  178. find "$thisdir" -mindepth 1 -maxdepth 1 -type d -print | (while read thisdir; do
  179. sharename="`basename \"$thisdir\"`"
  180. chown "$user":"$rwgroup" "$thisdir"
  181. chmod u=rw,go=r,a+X,g+s "$thisdir"
  182. ifs="$IFS"
  183. # Set default permissions
  184. find "$thisdir" -mindepth 1 -maxdepth 1 -print | (while read thisdir; do
  185. item="`basename \"$thisdir\"`"
  186. IFS="/"; for exception in $exceptions; do IFS="$ifs";
  187. if [ "$item" = "$exception" ]; then
  188. continue 2
  189. fi
  190. done
  191. chgrp -R "$rwgroup" "$thisdir"
  192. chmod -R ug=rw,o=r,a+X,g+s "$thisdir"
  193. done)
  194. # Handle exception dirs to be created if not existing
  195. IFS="/"; for dir in $exception_dirs_create; do IFS="$ifs";
  196. if [ ! -d "$thisdir/$dir" ]; then
  197. rm -f "$thisdir/$dir"
  198. fi
  199. if [ ! -e "$thisdir/$dir" ]; then
  200. mkdir "$thisdir/$dir"
  201. fi
  202. chown "$user":"$rwgroup" "$thisdir/$dir"
  203. done
  204. IFS="/"; for dir in $dirs_world_rw_create; do IFS="$ifs";
  205. if [ "$rogroup" = "$rwgroup" ]; then
  206. chmod -R ug=rw,o=r,a+X,g+s "$thisdir/$dir"
  207. else
  208. chmod -R a=rw,a+X,g+s "$thisdir/$dir"
  209. fi
  210. done
  211. IFS="/"; for dir in $dirs_group_rw_create; do IFS="$ifs";
  212. chmod -R ug=rw,o=r,a+X,g+s "$thisdir/$dir"
  213. done
  214. IFS="/"; for dir in $dirs_group_ro_create; do IFS="$ifs";
  215. chmod -R u=rw,go=r,a+X,g+s "$thisdir/$dir"
  216. done
  217. # Handle exception dirs to be updated if already there
  218. IFS="/"; for dir in $dirs_group_ro_update; do IFS="$ifs";
  219. if [ -e "$thisdir/$dir" ]; then
  220. chmod u=rw,go=r,a+X,g+s "$thisdir/$dir"
  221. fi
  222. done
  223. # Handle exception files to be updated if already there
  224. IFS="/"; for file in $files_group_ro_update; do IFS="$ifs";
  225. if [ -e "$thisdir/$file" ]; then
  226. chmod u=rw,go=r,g+s "$thisdir/$file"
  227. fi
  228. done
  229. # Handle exception dirs to be purged and recreated
  230. IFS="/"; for dir in $dirs_no_access_purge; do IFS="$ifs";
  231. rm -rf "$thisdir/$dir"
  232. mkdir -m a= "$thisdir/$dir"
  233. chown nobody: "$thisdir/$dir"
  234. done
  235. IFS="$ifs"
  236. done)
  237. done)
  238. done)
  239. done)
  240. # Deprecated share permissions
  241. for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/shares_win"`; do
  242. chgrp -R $user $dir
  243. chmod -R u=rw,g=rw,o=,ug+X,g+s $dir
  244. done
  245. for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/shares_mac"`; do
  246. chgrp -R $user $dir
  247. chmod -R u=rw,g=rw,o=,ug+X,g+s $dir
  248. rm -rf $dir/Network\ Trash\ Folder
  249. mkdir $dir/Network\ Trash\ Folder
  250. chown nobody: $dir/Network\ Trash\ Folder
  251. chmod a= $dir/Network\ Trash\ Folder
  252. done
  253. # Ftp shares permissions
  254. for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/ftp_$USER$"`; do
  255. chgrp -R $user $dir
  256. chmod -R ug=rw,o=r,a+X,g+s $dir
  257. rm -rf $dir/Network\ Trash\ Folder
  258. mkdir $dir/Network\ Trash\ Folder
  259. chown nobody: $dir/Network\ Trash\ Folder
  260. chmod a= $dir/Network\ Trash\ Folder
  261. done
  262. for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/ftp_${USER}_ro$"`; do
  263. chown -R $user: $dir
  264. chmod -R u=rw,go=r,a+X $dir
  265. rm -rf $dir/Network\ Trash\ Folder
  266. mkdir $dir/Network\ Trash\ Folder
  267. chown nobody: $dir/Network\ Trash\ Folder
  268. chmod a= $dir/Network\ Trash\ Folder
  269. done
  270. # Web shares permissions
  271. for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/web_"`; do
  272. chown -R $user: $dir
  273. # chmod -R u=rw,go=r,a+X $webdir
  274. #TODO: Only cgi scripts (.cgi and .pl) should be executable
  275. chmod -R u+rw,go+r,a+X $dir
  276. # leftover from ancient times with another policy
  277. if [ $NETATALK ]; then
  278. rm -rf $dir/Network\ Trash\ Folder
  279. fi
  280. done
  281. # Web shares permissions
  282. for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/websites"`; do
  283. chown root: $dir
  284. chmod a=r,u+w,a+X $dir
  285. done
  286. for dir in `find $HOME -mindepth 2 -maxdepth 2 -type d | egrep "^$HOME/websites/"`; do
  287. chown -R $user: $dir
  288. # chmod -R u=rw,go=r,a+X $webdir
  289. #TODO: Only cgi scripts (.cgi and .pl) should be executable
  290. chmod -R u+rw,go+r,a+X $dir
  291. # leftover from ancient times with another policy
  292. if [ $NETATALK ]; then
  293. rm -rf $dir/Network\ Trash\ Folder
  294. fi
  295. done
  296. for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/webscripts"`; do
  297. chown root: $dir
  298. chmod a=r,u+w,a+X $dir
  299. done
  300. for dir in `find $HOME -mindepth 2 -maxdepth 2 -type d | egrep "^$HOME/webscripts/"`; do
  301. chown -R $user: $dir
  302. # chmod -R u=rw,go=r,a+X $webdir
  303. #TODO: Only cgi scripts (.cgi and .pl) should be executable
  304. chmod -R u+rw,go+r,a+X $dir
  305. done
  306. for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/webdata"`; do
  307. chown $user: $dir
  308. chmod a=r,u+w,a+X $dir
  309. done
  310. for dir in `find $HOME -mindepth 2 -maxdepth 2 -type d | egrep "^$HOME/webdata/"`; do
  311. chown -R $user: $dir
  312. chmod -R u=rw,go=,u+X $dir
  313. done
  314. for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/webshareddata"`; do
  315. chown $user: $dir
  316. chmod a=r,u+w,a+X $dir
  317. done
  318. for dir in `find $HOME -mindepth 2 -maxdepth 2 -type d | egrep "^$HOME/webshareddata/"`; do
  319. chown -R $user: $dir
  320. chmod -R u=rw,go=r,a+X $dir
  321. done
  322. for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/webphpsites"`; do
  323. chown root: $dir
  324. chmod u=rw,go=r,a+X $dir
  325. done
  326. for dir in `find $HOME -mindepth 2 -maxdepth 2 -type d | egrep "^$HOME/webphpsites/"`; do
  327. chown -R $user:www-data $dir
  328. # chmod -R ug=rw,o=r,a+X $dir
  329. chmod -R ug=rw,o=,ug+X $dir
  330. done
  331. for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/webphpdata"`; do
  332. chown root: $dir
  333. chmod a=r,u+w,a+X $dir
  334. done
  335. for dir in `find $HOME -mindepth 2 -maxdepth 2 -type d | egrep "^$HOME/webphpdata/"`; do
  336. chown -R $user:www-data $dir
  337. chmod -R ug=rw,o=,ug+X $dir
  338. done
  339. # Dummy user restrictions
  340. if [ -n "$REALUSERS_GROUPNAME" -a -n "$DUMMYSHAREDIR" -a -n "$DUMMYSHAREOWNER" -a -n "$DUMMYSHARENAME" ]; then
  341. [ -e $DUMMYSHAREDIR/$user ] \
  342. || mkdir $DUMMYSHAREDIR/$user
  343. chown $DUMMYSHAREOWNER: $DUMMYSHAREDIR/$user
  344. chmod u=rw,go=r,a+X $DUMMYSHAREDIR/$user
  345. if [ -e $HOME/$DUMMYSHARENAME ]; then
  346. if [ -L $HOME/$DUMMYSHARENAME ]; then
  347. ln -sf $DUMMYSHAREDIR/$user $HOME/$DUMMYSHARENAME
  348. chown $user: $HOME/$DUMMYSHARENAME
  349. else
  350. echo "WARNING: $HOME/$DUMMYSHAREDIR exists already. Leaving it as is..."
  351. fi
  352. else
  353. ln -s $DUMMYSHAREDIR/$user $HOME/$DUMMYSHARENAME
  354. chown $user: $HOME/$DUMMYSHARENAME
  355. fi
  356. if [ -n "$DUMMYAPACHECFG" -a -n "$DUMMYAPACHESHAREDIR" ]; then
  357. if [ -f /etc/apache/include.d/$DUMMYAPACHECFG -a -x /etc/init.d/apache ]; then
  358. if [ -e /etc/apache/include.d/$DUMMYAPACHECFG-$user ]; then
  359. echo "/etc/apache/include.d/$DUMMYAPACHECFG-$user exists already. Ignoring..."
  360. else
  361. echo "# Created automatically by adduser.local
  362. <Location /$DUMMYAPACHESHAREDIR/$user>
  363. <Limit GET POST>
  364. require user $user
  365. </Limit>
  366. </Location>" \
  367. > /etc/apache/include.d/$DUMMYAPACHECFG-$user
  368. apache_reload_needed="1"
  369. fi
  370. fi
  371. fi
  372. fi
  373. echo "."
  374. done
  375. if [ $XCHANGE ]; then
  376. for USER in $(ls $XDIRREAL); do
  377. id $user >/dev/null 2>&1 || rm -rf $XDIRREAL/$user
  378. done
  379. fi
  380. if [ "$apache_reload_needed" ]; then
  381. apache_do_reload=""
  382. case runmode in
  383. interactive)
  384. echo -n "Apache config changed. Reload Apache now (Y/n)? "
  385. read apache_reload
  386. case $apache_reload in
  387. y|Y|"")
  388. apache_do_reload="1"
  389. ;;
  390. esac
  391. ;;
  392. force)
  393. apache_do_reload="1"
  394. ;;
  395. *)
  396. echo "Apache config has changed. Remember to reload Apache...!"
  397. ;;
  398. esac
  399. if "$apache_do_reload" ]; then
  400. /etc/init.d/apache force-reload
  401. fi
  402. fi