summaryrefslogtreecommitdiff
path: root/localuserconfig
blob: 5ccb06d4100314e00d5d7c517ddcf837cdc25b6f (plain)
  1. #!/bin/sh
  2. #
  3. # /usr/local/bin/localuserconfig
  4. # Copyright 2004-2006 Jonas Smedegaard <dr@jones.dk>
  5. #
  6. # $Id: localuserconfig,v 1.8 2006-07-16 12:29:16 jonas Exp $
  7. #
  8. # Set/change local account settings
  9. #
  10. # TODO: Use the following syntax to add info to .smbpasswd
  11. # grep -q SomeOption ~/file || echo "line with SomeOption and such" >> ~/file
  12. #
  13. # TODO: Move relevant stuff from user-init and make it use this instead
  14. # TODO: Use getopt, and implement --help
  15. # TODO: Implement runmodes noninteractive and force (in addition to the default: interactive)
  16. # TODO: Runmode noninteractive by default if no tty attached
  17. # TODO: Implement verbosity levels (0=quiet 1=oneliner 2=default 3=chatty 4=debug)
  18. set -e
  19. # config (edit /etc/local/users.conf to override)
  20. # which are user accounts (adduser values are used if empty)
  21. first_uid=""
  22. last_uid=""
  23. do_quota="no" # Manage disk quota
  24. do_distrib="no" # Distributed shares (software archive)
  25. do_personal="no" # Personal shares (mac, pc, public_html)
  26. do_xchange="no" # Group-readable shares
  27. do_public="no" # Public share (web homepage)
  28. do_mac="no" # AppleShare-optimized share (netatalk)
  29. do_pc="no" # SMB-ptimized share (Samba)
  30. do_server="no" # Personal share on remote SMB server
  31. quota_roots="" # space-delimited list of disk devices
  32. quota_soft="100000"
  33. quota_hard="1000000"
  34. quota_newstyle="yes" # Woody used a different syntax...
  35. xchange_root="xchange"
  36. xchange_sharedroot="/home/XCHANGE"
  37. mac_root="mac"
  38. pc_root="pc"
  39. server_name="SERVER" # SMB name of remote server
  40. server_desc="remote server"
  41. server_root="server"
  42. server_conf="/etc/security/pam_mount.conf"
  43. server_userconf=".winpassword"
  44. ### No servicable parts below this line! ###
  45. if [ -e /etc/adduser.conf ]; then
  46. . /etc/adduser.conf
  47. else
  48. echo "/etc/adduser.conf missing. Exiting..."
  49. exit 1
  50. fi
  51. [ -r /etc/local/users.conf ] && . /etc/local/users.conf
  52. # Flags used internally
  53. root_required="no"
  54. runmode="interactive"
  55. user="`id -u -n`"
  56. uid="`id -u`"
  57. HOME="`getent passwd \"$user\" | awk -F: '{print $6}' | head -n 1`"
  58. #TODO: Allow root to pass the above as options
  59. # Safety checks (disable silently - the user can't correct it anyway)
  60. [ "$do_mac" = "yes" -a -n "$mac_root" ] || do_mac="no"
  61. [ "$do_pc" = "yes" -a -n "$pc_root" ] || do_pc="no"
  62. [ "$do_xchange" = "yes" -a -n "$xchange_root" ] || do_xchange="no"
  63. [ "$do_server" = "yes" -a -n "$server_root" ] || do_server="no"
  64. #TODO: do a loop instead for the above
  65. # only do user accounts (checked against /etc/adduser.conf values)
  66. [ -n "$first_uid" ] || first_uid="$FIRST_UID"
  67. [ -n "$last_uid" ] || last_uid="$LAST_UID"
  68. [ "$uid" -ge "$FIRST_UID" -a "$uid" -le "$LAST_UID" ] || exit 0
  69. #TODO: check if above is numeric
  70. #TODO: Always use adduser values as strict outer limits
  71. if [ -z "$HOME" ]; then
  72. echo "Error: Unable to resolve home of user $user!"
  73. exit 1
  74. fi
  75. if [ ! -d "$HOME" ]; then
  76. echo "Error: Home of user $user doesn't exist: \"$HOME\"!"
  77. exit 1
  78. fi
  79. if [ "$do_server" = "yes" ]; then
  80. server_edit="1"
  81. if [ -r "$HOME/$server_userconf" ]; then
  82. server_username="$(grep '^username' $HOME/$server_userconf | awk -F= '{print $2}' | head -n 1 | awk '{print $1}')"
  83. server_password="$(grep '^password' $HOME/$server_userconf | awk -F= '{print $2}' | head -n 1 | awk '{print $1}')"
  84. fi
  85. if [ -n "$server_username" ]; then
  86. server_edit=""
  87. echo -n "Account info for $server_desc already exists. Edit (y/N)? "
  88. read server_overwrite
  89. case $server_overwrite in
  90. y|Y)
  91. server_edit="1"
  92. ;;
  93. esac
  94. else
  95. server_username=$user
  96. fi
  97. if [ "$server_edit" = "1" ]; then
  98. if [ -n "$server_username" ]; then
  99. echo -n "Username on $server_desc ($server_username): "
  100. else
  101. echo -n "Username on $server_desc: "
  102. fi
  103. read server_username_new
  104. if [ -n "$server_username_new" ]; then
  105. server_username="$server_username_new"
  106. fi
  107. echo -n "Password on $server_desc: "
  108. read -s server_password
  109. echo
  110. echo -n "Password once more: "
  111. read -s server_password_again
  112. echo
  113. if [ -n "$server_username" -a "$server_password" = "$server_password_again" ]; then
  114. echo "username = $server_username" > $HOME/$server_userconf
  115. echo "password = $server_password" >> $HOME/$server_userconf
  116. chmod 0600 $HOME/$server_userconf
  117. else
  118. echo "Setting server login info failed: problem getting either username or password"
  119. fi
  120. fi
  121. if grep -v -q "^volume $user " "$server_conf"; then
  122. root_required="yes"
  123. fi
  124. fi
  125. #if [ "$root_required" = "yes" ]; then
  126. # echo "Note: Some of the current setup requires action by systems administrator"
  127. #TODO: Re-enable this, but only when able to suppress by root
  128. #TODO: send email to root, unless invoked by root
  129. #TODO: Collect actual items needing attention, to print and include in email
  130. #fi
  131. exit 0
  132. #FIXME: The remaining is to be implemented (lifted from user-init)
  133. #if [ -x /etc/local/quota.sh ]; then
  134. # /etc/local/quota.sh $user
  135. # fi
  136. [ $quota_soft ] || quota_soft="0"
  137. [ $quota_hard ] || quota_hard="0"
  138. for quota_root in $quota_roots; do
  139. if [ $quota_newstyle ]; then
  140. setquota $user $quota_soft $quota_hard 0 0 $quota_root
  141. else
  142. setquota $user $quota_root $quota_soft $quota_hard 0 0
  143. fi
  144. done
  145. mkdir -p $HOME/mail
  146. if [ "$USE_MBOX" ]; then
  147. touch $HOME/mail/mbox
  148. elif [ -f $HOME/mail/mbox -a ! -s $HOME/mail/mbox ]; then
  149. rm -f $HOME/mail/mbox
  150. fi
  151. if [ $NETATALK ]; then
  152. mkdir -p $HOME/$mac_root
  153. fi
  154. if [ $SAMBA ]; then
  155. mkdir -p $HOME/$pc_root
  156. fi
  157. if [ $XCHANGE ]; then
  158. mkdir -p $xchange_sharedroot/users/root/$user
  159. fi
  160. if [ $PUBLIC ]; then
  161. mkdir -p $HOME/public_html
  162. fi
  163. chown $user: $HOME
  164. chmod u=rwX,go=rX $HOME
  165. # Mail handling
  166. chown -R $user: $HOME/mail
  167. chmod -R u=rw,go=,u+X $HOME/mail
  168. if [ -f $HOME/.mailboxlist ]; then
  169. chown $user: $HOME/.mailboxlist
  170. chmod 0640 $HOME/.mailboxlist
  171. fi
  172. if [ -f $HOME/.forward ]; then
  173. chown $user: $HOME/.forward
  174. chmod 0640 $HOME/.forward
  175. fi
  176. if [ -f /var/mail/$user ]; then
  177. chown $user:mail /var/mail/$user
  178. chmod ug=rw,o= /var/mail/$user
  179. elif [ -f /var/spool/mail/$user ]; then
  180. chown $user:mail /var/spool/mail/$user
  181. chmod ug=rw,o= /var/spool/mail/$user
  182. fi
  183. # MySQL handling
  184. if [ -f $HOME/.my.cnf ]; then
  185. chown $user: $HOME/.my.cnf
  186. chmod 0600 $HOME/.my.cnf
  187. fi
  188. # Mac dir permissions
  189. if [ -d $HOME/$mac_root ]; then
  190. chown -R $user: $HOME/$mac_root
  191. chmod -R u=rw,g=r,o=,ug+X $HOME/$mac_root
  192. rm -rf $HOME/$mac_root/Network\ Trash\ Folder
  193. mkdir $HOME/$mac_root/Network\ Trash\ Folder
  194. chown nobody: $HOME/$mac_root/Network\ Trash\ Folder
  195. chmod a= $HOME/$mac_root/Network\ Trash\ Folder
  196. fi
  197. # PC dir permissions
  198. if [ -d $HOME/$pc_root ]; then
  199. chown -R $user: $HOME/$pc_root
  200. chmod -R u=rw,g=r,o=,ug+X $HOME/$pc_root
  201. fi
  202. # Exchange dir permissions
  203. if [ -d $xchange_sharedroot/users/root/$user ]; then
  204. chown -R $user:users $xchange_sharedroot/users/root/$user
  205. chmod -R g=r,g+X $xchange_sharedroot/users/root/$user
  206. if [ -e "x$HOME/$xchange_root" ]; then
  207. if [ -L "x$HOME/$xchange_root" ]; then
  208. ln -sf $xchange_sharedroot/users/root/$user $HOME/$xchange_root
  209. else
  210. echo "ERROR: $HOME/$xchange_root exists already. Leaving it as is..."
  211. fi
  212. else
  213. ln -s $xchange_sharedroot/users/root/$user $HOME/$xchange_root
  214. fi
  215. fi
  216. # Public dir permissions
  217. if [ -d $HOME/public_html ]; then
  218. chown -R $user: $HOME/public_html
  219. chmod -R u+rX,go=r,go+X $HOME/public_html
  220. if [ $NETATALK ]; then
  221. rm -rf $HOME/public_html/Network\ Trash\ Folder
  222. mkdir $HOME/public_html/Network\ Trash\ Folder
  223. chown nobody: $HOME/public_html/Network\ Trash\ Folder
  224. chmod a= $HOME/public_html/Network\ Trash\ Folder
  225. fi
  226. fi
  227. # Fileshares: <home>/shares.<sharetype>/<rogroup>/<rwgroup>/<sharename>
  228. # <sharetype>: Either mac or win depending on which of netatalk and samba provides r/w access to the shares
  229. # <rwgroup>: Group with write access to the share (usually the default group of the owner)
  230. # <rogroup>: Either rwgroup or secondary group with read-only access to the share
  231. # owner must be member of both groups, and rwgroup members must also be members of rogroup
  232. find "$HOME" -mindepth 1 -maxdepth 1 -type d -print | egrep "^$HOME/shares\." | (while read thisdir; do
  233. sharetype="`basename \"$thisdir\" | awk -F. '{print $2}'`"
  234. # Define dir and file exceptions
  235. case "$sharetype" in
  236. mac)
  237. dirs_world_rw_create='.AppleDB'
  238. dirs_group_rw_create='.AppleDesktop/Temporary Items/TheFindByContentFolder'
  239. dirs_group_ro_create='TheVolumeSettingsFolder'
  240. dirs_group_ro_update='.AppleDouble'
  241. files_group_ro_update=':2eDS_Store'
  242. dirs_no_access_purge='Network Trash Folder'
  243. ;;
  244. win)
  245. ;;
  246. *)
  247. continue
  248. ;;
  249. esac
  250. 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"
  251. exception_dirs_create="$dirs_world_rw_create/$dirs_group_rw_create/$dirs_group_ro_create"
  252. chown "$user": "$thisdir"
  253. chmod a=rX "$thisdir"
  254. find "$thisdir" -mindepth 1 -maxdepth 1 -type d -print | (while read thisdir; do
  255. rogroup="`basename \"$thisdir\"`"
  256. chown "$user":"$rogroup" "$thisdir"
  257. chmod ug=rX,o= "$thisdir"
  258. find "$thisdir" -mindepth 1 -maxdepth 1 -type d -print | (while read thisdir; do
  259. rwgroup="`basename \"$thisdir\"`"
  260. chown "$user":"$rwgroup" "$thisdir"
  261. chmod a=rX,g+s "$thisdir"
  262. find "$thisdir" -mindepth 1 -maxdepth 1 -type d -print | (while read thisdir; do
  263. sharename="`basename \"$thisdir\"`"
  264. chown "$user":"$rwgroup" "$thisdir"
  265. chmod u=rw,go=r,a+X,g+s "$thisdir"
  266. ifs="$IFS"
  267. # Set default permissions
  268. find "$thisdir" -mindepth 1 -maxdepth 1 -print | (while read thisdir; do
  269. item="`basename \"$thisdir\"`"
  270. IFS="/"; for exception in $exceptions; do IFS="$ifs";
  271. if [ "$item" = "$exception" ]; then
  272. continue 2
  273. fi
  274. done
  275. chgrp -R "$rwgroup" "$thisdir"
  276. chmod -R ug=rw,o=r,a+X,g+s "$thisdir"
  277. done)
  278. # Handle exception dirs to be created if not existing
  279. IFS="/"; for dir in $exception_dirs_create; do IFS="$ifs";
  280. if [ ! -d "$thisdir/$dir" ]; then
  281. rm -f "$thisdir/$dir"
  282. fi
  283. if [ ! -e "$thisdir/$dir" ]; then
  284. mkdir "$thisdir/$dir"
  285. fi
  286. chown "$user":"$rwgroup" "$thisdir/$dir"
  287. done
  288. IFS="/"; for dir in $dirs_world_rw_create; do IFS="$ifs";
  289. if [ "$rogroup" = "$rwgroup" ]; then
  290. chmod -R ug=rw,o=r,a+X,g+s "$thisdir/$dir"
  291. else
  292. chmod -R a=rw,a+X,g+s "$thisdir/$dir"
  293. fi
  294. done
  295. IFS="/"; for dir in $dirs_group_rw_create; do IFS="$ifs";
  296. chmod -R ug=rw,o=r,a+X,g+s "$thisdir/$dir"
  297. done
  298. IFS="/"; for dir in $dirs_group_ro_create; do IFS="$ifs";
  299. chmod -R u=rw,go=r,a+X,g+s "$thisdir/$dir"
  300. done
  301. # Handle exception dirs to be updated if already there
  302. IFS="/"; for dir in $dirs_group_ro_update; do IFS="$ifs";
  303. if [ -e "$thisdir/$dir" ]; then
  304. chmod u=rw,go=r,a+X,g+s "$thisdir/$dir"
  305. fi
  306. done
  307. # Handle exception files to be updated if already there
  308. IFS="/"; for file in $files_group_ro_update; do IFS="$ifs";
  309. if [ -e "$thisdir/$file" ]; then
  310. chmod u=rw,go=r,g+s "$thisdir/$file"
  311. fi
  312. done
  313. # Handle exception dirs to be purged and recreated
  314. IFS="/"; for dir in $dirs_no_access_purge; do IFS="$ifs";
  315. rm -rf "$thisdir/$dir"
  316. mkdir -m a= "$thisdir/$dir"
  317. chown nobody: "$thisdir/$dir"
  318. done
  319. IFS="$ifs"
  320. done)
  321. done)
  322. done)
  323. done)
  324. # Deprecated share permissions
  325. for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/shares_win"`; do
  326. chgrp -R $user $dir
  327. chmod -R u=rw,g=rw,o=,ug+X,g+s $dir
  328. done
  329. for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/shares_mac"`; do
  330. chgrp -R $user $dir
  331. chmod -R u=rw,g=rw,o=,ug+X,g+s $dir
  332. rm -rf $dir/Network\ Trash\ Folder
  333. mkdir $dir/Network\ Trash\ Folder
  334. chown nobody: $dir/Network\ Trash\ Folder
  335. chmod a= $dir/Network\ Trash\ Folder
  336. done
  337. # Ftp shares permissions
  338. for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/ftp_$USER$"`; do
  339. chgrp -R $user $dir
  340. chmod -R ug=rw,o=r,a+X,g+s $dir
  341. rm -rf $dir/Network\ Trash\ Folder
  342. mkdir $dir/Network\ Trash\ Folder
  343. chown nobody: $dir/Network\ Trash\ Folder
  344. chmod a= $dir/Network\ Trash\ Folder
  345. done
  346. for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/ftp_${USER}_ro$"`; do
  347. chown -R $user: $dir
  348. chmod -R u=rw,go=r,a+X $dir
  349. rm -rf $dir/Network\ Trash\ Folder
  350. mkdir $dir/Network\ Trash\ Folder
  351. chown nobody: $dir/Network\ Trash\ Folder
  352. chmod a= $dir/Network\ Trash\ Folder
  353. done
  354. # Web shares permissions
  355. for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/web_"`; do
  356. chown -R $user: $dir
  357. # chmod -R u=rw,go=r,a+X $webdir
  358. #TODO: Only cgi scripts (.cgi and .pl) should be executable
  359. chmod -R u+rw,go+r,a+X $dir
  360. # leftover from ancient times with another policy
  361. if [ $NETATALK ]; then
  362. rm -rf $dir/Network\ Trash\ Folder
  363. fi
  364. done
  365. # Web shares permissions
  366. for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/websites"`; do
  367. chown root: $dir
  368. chmod a=r,u+w,a+X $dir
  369. done
  370. for dir in `find $HOME -mindepth 2 -maxdepth 2 -type d | egrep "^$HOME/websites/"`; do
  371. chown -R $user: $dir
  372. # chmod -R u=rw,go=r,a+X $webdir
  373. #TODO: Only cgi scripts (.cgi and .pl) should be executable
  374. chmod -R u+rw,go+r,a+X $dir
  375. # leftover from ancient times with another policy
  376. if [ $NETATALK ]; then
  377. rm -rf $dir/Network\ Trash\ Folder
  378. fi
  379. done
  380. for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/webscripts"`; do
  381. chown root: $dir
  382. chmod a=r,u+w,a+X $dir
  383. done
  384. for dir in `find $HOME -mindepth 2 -maxdepth 2 -type d | egrep "^$HOME/webscripts/"`; do
  385. chown -R $user: $dir
  386. # chmod -R u=rw,go=r,a+X $webdir
  387. #TODO: Only cgi scripts (.cgi and .pl) should be executable
  388. chmod -R u+rw,go+r,a+X $dir
  389. done
  390. for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/webdata"`; do
  391. chown $user: $dir
  392. chmod a=r,u+w,a+X $dir
  393. done
  394. for dir in `find $HOME -mindepth 2 -maxdepth 2 -type d | egrep "^$HOME/webdata/"`; do
  395. chown -R $user: $dir
  396. chmod -R u=rw,go=,u+X $dir
  397. done
  398. for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/webshareddata"`; do
  399. chown $user: $dir
  400. chmod a=r,u+w,a+X $dir
  401. done
  402. for dir in `find $HOME -mindepth 2 -maxdepth 2 -type d | egrep "^$HOME/webshareddata/"`; do
  403. chown -R $user: $dir
  404. chmod -R u=rw,go=r,a+X $dir
  405. done
  406. for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/webphpsites"`; do
  407. chown root: $dir
  408. chmod u=rw,go=r,a+X $dir
  409. done
  410. for dir in `find $HOME -mindepth 2 -maxdepth 2 -type d | egrep "^$HOME/webphpsites/"`; do
  411. chown -R $user:www-data $dir
  412. # chmod -R ug=rw,o=r,a+X $dir
  413. chmod -R ug=rw,o=,ug+X $dir
  414. done
  415. for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/webphpdata"`; do
  416. chown root: $dir
  417. chmod a=r,u+w,a+X $dir
  418. done
  419. for dir in `find $HOME -mindepth 2 -maxdepth 2 -type d | egrep "^$HOME/webphpdata/"`; do
  420. chown -R $user:www-data $dir
  421. chmod -R ug=rw,o=,ug+X $dir
  422. done
  423. # Dummy user restrictions
  424. if [ -n "$REALUSERS_GROUPNAME" -a -n "$DUMMYSHAREDIR" -a -n "$DUMMYSHAREOWNER" -a -n "$DUMMYSHARENAME" ]; then
  425. [ -e $DUMMYSHAREDIR/$user ] \
  426. || mkdir $DUMMYSHAREDIR/$user
  427. chown $DUMMYSHAREOWNER: $DUMMYSHAREDIR/$user
  428. chmod u=rw,go=r,a+X $DUMMYSHAREDIR/$user
  429. if [ -e $HOME/$DUMMYSHARENAME ]; then
  430. if [ -L $HOME/$DUMMYSHARENAME ]; then
  431. ln -sf $DUMMYSHAREDIR/$user $HOME/$DUMMYSHARENAME
  432. chown $user: $HOME/$DUMMYSHARENAME
  433. else
  434. echo "WARNING: $HOME/$DUMMYSHAREDIR exists already. Leaving it as is..."
  435. fi
  436. else
  437. ln -s $DUMMYSHAREDIR/$user $HOME/$DUMMYSHARENAME
  438. chown $user: $HOME/$DUMMYSHARENAME
  439. fi
  440. if [ -n "$DUMMYAPACHECFG" -a -n "$DUMMYAPACHESHAREDIR" ]; then
  441. if [ -f /etc/apache/include.d/$DUMMYAPACHECFG -a -x /etc/init.d/apache ]; then
  442. if [ -e /etc/apache/include.d/$DUMMYAPACHECFG-$user ]; then
  443. echo "/etc/apache/include.d/$DUMMYAPACHECFG-$user exists already. Ignoring..."
  444. else
  445. echo "# Created automatically by adduser.local
  446. <Location /$DUMMYAPACHESHAREDIR/$user>
  447. <Limit GET POST>
  448. require user $user
  449. </Limit>
  450. </Location>" \
  451. > /etc/apache/include.d/$DUMMYAPACHECFG-$user
  452. root_required="yes"
  453. fi
  454. fi
  455. fi
  456. fi