summaryrefslogtreecommitdiff
path: root/localuserconfig
blob: e84cdf39663ffe51b0d7460519e1b3ef91975f77 (plain)
  1. #!/bin/sh
  2. #
  3. # /usr/local/bin/localuserconfig
  4. # Copyright 2004 Jonas Smedegaard <dr@jones.dk>
  5. #
  6. # $Id: localuserconfig,v 1.5 2004-04-15 23:06:44 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 -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 -1 | awk '{print $1}')"
  83. server_password="$(grep '^password' $HOME/$server_userconf | awk -F= '{print $2}' | head -1 | awk '{print $1}')"
  84. fi
  85. if [ -n "$server_username" -o -n "$server_password" ]; 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: send email to root, unless invoked by root
  128. #TODO: Collect actual items needing attention, to print and include in email
  129. #fi
  130. exit 0
  131. #FIXME: The remaining is to be implemented (lifted from user-init)
  132. #if [ -x /etc/local/quota.sh ]; then
  133. # /etc/local/quota.sh $user
  134. # fi
  135. [ $quota_soft ] || quota_soft="0"
  136. [ $quota_hard ] || quota_hard="0"
  137. for quota_root in $quota_roots; do
  138. if [ $quota_newstyle ]; then
  139. setquota $user $quota_soft $quota_hard 0 0 $quota_root
  140. else
  141. setquota $user $quota_root $quota_soft $quota_hard 0 0
  142. fi
  143. done
  144. mkdir -p $HOME/mail
  145. if [ "$USE_MBOX" ]; then
  146. touch $HOME/mail/mbox
  147. elif [ -f $HOME/mail/mbox -a ! -s $HOME/mail/mbox ]; then
  148. rm -f $HOME/mail/mbox
  149. fi
  150. if [ $NETATALK ]; then
  151. mkdir -p $HOME/$mac_root
  152. fi
  153. if [ $SAMBA ]; then
  154. mkdir -p $HOME/$pc_root
  155. fi
  156. if [ $XCHANGE ]; then
  157. mkdir -p $xchange_sharedroot/users/root/$user
  158. fi
  159. if [ $PUBLIC ]; then
  160. mkdir -p $HOME/public_html
  161. fi
  162. chown $user: $HOME
  163. chmod u=rwX,go=rX $HOME
  164. # Mail handling
  165. chown -R $user: $HOME/mail
  166. chmod -R u=rw,go=,u+X $HOME/mail
  167. if [ -f $HOME/.mailboxlist ]; then
  168. chown $user: $HOME/.mailboxlist
  169. chmod 0640 $HOME/.mailboxlist
  170. fi
  171. if [ -f $HOME/.forward ]; then
  172. chown $user: $HOME/.forward
  173. chmod 0640 $HOME/.forward
  174. fi
  175. if [ -f /var/mail/$user ]; then
  176. chown $user:mail /var/mail/$user
  177. chmod ug=rw,o= /var/mail/$user
  178. elif [ -f /var/spool/mail/$user ]; then
  179. chown $user:mail /var/spool/mail/$user
  180. chmod ug=rw,o= /var/spool/mail/$user
  181. fi
  182. # MySQL handling
  183. if [ -f $HOME/.my.cnf ]; then
  184. chown $user: $HOME/.my.cnf
  185. chmod 0600 $HOME/.my.cnf
  186. fi
  187. # Mac dir permissions
  188. if [ -d $HOME/$mac_root ]; then
  189. chown -R $user: $HOME/$mac_root
  190. chmod -R u=rw,g=r,o=,ug+X $HOME/$mac_root
  191. rm -rf $HOME/$mac_root/Network\ Trash\ Folder
  192. mkdir $HOME/$mac_root/Network\ Trash\ Folder
  193. chown nobody: $HOME/$mac_root/Network\ Trash\ Folder
  194. chmod a= $HOME/$mac_root/Network\ Trash\ Folder
  195. fi
  196. # PC dir permissions
  197. if [ -d $HOME/$pc_root ]; then
  198. chown -R $user: $HOME/$pc_root
  199. chmod -R u=rw,g=r,o=,ug+X $HOME/$pc_root
  200. fi
  201. # Exchange dir permissions
  202. if [ -d $xchange_sharedroot/users/root/$user ]; then
  203. chown -R $user:users $xchange_sharedroot/users/root/$user
  204. chmod -R g=r,g+X $xchange_sharedroot/users/root/$user
  205. if [ -e "x$HOME/$xchange_root" ]; then
  206. if [ -L "x$HOME/$xchange_root" ]; then
  207. ln -sf $xchange_sharedroot/users/root/$user $HOME/$xchange_root
  208. else
  209. echo "ERROR: $HOME/$xchange_root exists already. Leaving it as is..."
  210. fi
  211. else
  212. ln -s $xchange_sharedroot/users/root/$user $HOME/$xchange_root
  213. fi
  214. fi
  215. # Public dir permissions
  216. if [ -d $HOME/public_html ]; then
  217. chown -R $user: $HOME/public_html
  218. chmod -R u+rX,go=r,go+X $HOME/public_html
  219. if [ $NETATALK ]; then
  220. rm -rf $HOME/public_html/Network\ Trash\ Folder
  221. mkdir $HOME/public_html/Network\ Trash\ Folder
  222. chown nobody: $HOME/public_html/Network\ Trash\ Folder
  223. chmod a= $HOME/public_html/Network\ Trash\ Folder
  224. fi
  225. fi
  226. # Fileshares: <home>/shares.<sharetype>/<rogroup>/<rwgroup>/<sharename>
  227. # <sharetype>: Either mac or win depending on which of netatalk and samba provides r/w access to the shares
  228. # <rwgroup>: Group with write access to the share (usually the default group of the owner)
  229. # <rogroup>: Either rwgroup or secondary group with read-only access to the share
  230. # owner must be member of both groups, and rwgroup members must also be members of rogroup
  231. find "$HOME" -mindepth 1 -maxdepth 1 -type d -print | egrep "^$HOME/shares\." | (while read thisdir; do
  232. sharetype="`basename \"$thisdir\" | awk -F. '{print $2}'`"
  233. # Define dir and file exceptions
  234. case "$sharetype" in
  235. mac)
  236. dirs_world_rw_create='.AppleDB'
  237. dirs_group_rw_create='.AppleDesktop/Temporary Items/TheFindByContentFolder'
  238. dirs_group_ro_create='TheVolumeSettingsFolder'
  239. dirs_group_ro_update='.AppleDouble'
  240. files_group_ro_update=':2eDS_Store'
  241. dirs_no_access_purge='Network Trash Folder'
  242. ;;
  243. win)
  244. ;;
  245. *)
  246. continue
  247. ;;
  248. esac
  249. 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"
  250. exception_dirs_create="$dirs_world_rw_create/$dirs_group_rw_create/$dirs_group_ro_create"
  251. chown "$user": "$thisdir"
  252. chmod a=rX "$thisdir"
  253. find "$thisdir" -mindepth 1 -maxdepth 1 -type d -print | (while read thisdir; do
  254. rogroup="`basename \"$thisdir\"`"
  255. chown "$user":"$rogroup" "$thisdir"
  256. chmod ug=rX,o= "$thisdir"
  257. find "$thisdir" -mindepth 1 -maxdepth 1 -type d -print | (while read thisdir; do
  258. rwgroup="`basename \"$thisdir\"`"
  259. chown "$user":"$rwgroup" "$thisdir"
  260. chmod a=rX,g+s "$thisdir"
  261. find "$thisdir" -mindepth 1 -maxdepth 1 -type d -print | (while read thisdir; do
  262. sharename="`basename \"$thisdir\"`"
  263. chown "$user":"$rwgroup" "$thisdir"
  264. chmod u=rw,go=r,a+X,g+s "$thisdir"
  265. ifs="$IFS"
  266. # Set default permissions
  267. find "$thisdir" -mindepth 1 -maxdepth 1 -print | (while read thisdir; do
  268. item="`basename \"$thisdir\"`"
  269. IFS="/"; for exception in $exceptions; do IFS="$ifs";
  270. if [ "$item" = "$exception" ]; then
  271. continue 2
  272. fi
  273. done
  274. chgrp -R "$rwgroup" "$thisdir"
  275. chmod -R ug=rw,o=r,a+X,g+s "$thisdir"
  276. done)
  277. # Handle exception dirs to be created if not existing
  278. IFS="/"; for dir in $exception_dirs_create; do IFS="$ifs";
  279. if [ ! -d "$thisdir/$dir" ]; then
  280. rm -f "$thisdir/$dir"
  281. fi
  282. if [ ! -e "$thisdir/$dir" ]; then
  283. mkdir "$thisdir/$dir"
  284. fi
  285. chown "$user":"$rwgroup" "$thisdir/$dir"
  286. done
  287. IFS="/"; for dir in $dirs_world_rw_create; do IFS="$ifs";
  288. if [ "$rogroup" = "$rwgroup" ]; then
  289. chmod -R ug=rw,o=r,a+X,g+s "$thisdir/$dir"
  290. else
  291. chmod -R a=rw,a+X,g+s "$thisdir/$dir"
  292. fi
  293. done
  294. IFS="/"; for dir in $dirs_group_rw_create; do IFS="$ifs";
  295. chmod -R ug=rw,o=r,a+X,g+s "$thisdir/$dir"
  296. done
  297. IFS="/"; for dir in $dirs_group_ro_create; do IFS="$ifs";
  298. chmod -R u=rw,go=r,a+X,g+s "$thisdir/$dir"
  299. done
  300. # Handle exception dirs to be updated if already there
  301. IFS="/"; for dir in $dirs_group_ro_update; do IFS="$ifs";
  302. if [ -e "$thisdir/$dir" ]; then
  303. chmod u=rw,go=r,a+X,g+s "$thisdir/$dir"
  304. fi
  305. done
  306. # Handle exception files to be updated if already there
  307. IFS="/"; for file in $files_group_ro_update; do IFS="$ifs";
  308. if [ -e "$thisdir/$file" ]; then
  309. chmod u=rw,go=r,g+s "$thisdir/$file"
  310. fi
  311. done
  312. # Handle exception dirs to be purged and recreated
  313. IFS="/"; for dir in $dirs_no_access_purge; do IFS="$ifs";
  314. rm -rf "$thisdir/$dir"
  315. mkdir -m a= "$thisdir/$dir"
  316. chown nobody: "$thisdir/$dir"
  317. done
  318. IFS="$ifs"
  319. done)
  320. done)
  321. done)
  322. done)
  323. # Deprecated share permissions
  324. for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/shares_win"`; do
  325. chgrp -R $user $dir
  326. chmod -R u=rw,g=rw,o=,ug+X,g+s $dir
  327. done
  328. for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/shares_mac"`; do
  329. chgrp -R $user $dir
  330. chmod -R u=rw,g=rw,o=,ug+X,g+s $dir
  331. rm -rf $dir/Network\ Trash\ Folder
  332. mkdir $dir/Network\ Trash\ Folder
  333. chown nobody: $dir/Network\ Trash\ Folder
  334. chmod a= $dir/Network\ Trash\ Folder
  335. done
  336. # Ftp shares permissions
  337. for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/ftp_$USER$"`; do
  338. chgrp -R $user $dir
  339. chmod -R ug=rw,o=r,a+X,g+s $dir
  340. rm -rf $dir/Network\ Trash\ Folder
  341. mkdir $dir/Network\ Trash\ Folder
  342. chown nobody: $dir/Network\ Trash\ Folder
  343. chmod a= $dir/Network\ Trash\ Folder
  344. done
  345. for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/ftp_${USER}_ro$"`; do
  346. chown -R $user: $dir
  347. chmod -R u=rw,go=r,a+X $dir
  348. rm -rf $dir/Network\ Trash\ Folder
  349. mkdir $dir/Network\ Trash\ Folder
  350. chown nobody: $dir/Network\ Trash\ Folder
  351. chmod a= $dir/Network\ Trash\ Folder
  352. done
  353. # Web shares permissions
  354. for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/web_"`; do
  355. chown -R $user: $dir
  356. # chmod -R u=rw,go=r,a+X $webdir
  357. #TODO: Only cgi scripts (.cgi and .pl) should be executable
  358. chmod -R u+rw,go+r,a+X $dir
  359. # leftover from ancient times with another policy
  360. if [ $NETATALK ]; then
  361. rm -rf $dir/Network\ Trash\ Folder
  362. fi
  363. done
  364. # Web shares permissions
  365. for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/websites"`; do
  366. chown root: $dir
  367. chmod a=r,u+w,a+X $dir
  368. done
  369. for dir in `find $HOME -mindepth 2 -maxdepth 2 -type d | egrep "^$HOME/websites/"`; do
  370. chown -R $user: $dir
  371. # chmod -R u=rw,go=r,a+X $webdir
  372. #TODO: Only cgi scripts (.cgi and .pl) should be executable
  373. chmod -R u+rw,go+r,a+X $dir
  374. # leftover from ancient times with another policy
  375. if [ $NETATALK ]; then
  376. rm -rf $dir/Network\ Trash\ Folder
  377. fi
  378. done
  379. for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/webscripts"`; do
  380. chown root: $dir
  381. chmod a=r,u+w,a+X $dir
  382. done
  383. for dir in `find $HOME -mindepth 2 -maxdepth 2 -type d | egrep "^$HOME/webscripts/"`; do
  384. chown -R $user: $dir
  385. # chmod -R u=rw,go=r,a+X $webdir
  386. #TODO: Only cgi scripts (.cgi and .pl) should be executable
  387. chmod -R u+rw,go+r,a+X $dir
  388. done
  389. for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/webdata"`; do
  390. chown $user: $dir
  391. chmod a=r,u+w,a+X $dir
  392. done
  393. for dir in `find $HOME -mindepth 2 -maxdepth 2 -type d | egrep "^$HOME/webdata/"`; do
  394. chown -R $user: $dir
  395. chmod -R u=rw,go=,u+X $dir
  396. done
  397. for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/webshareddata"`; do
  398. chown $user: $dir
  399. chmod a=r,u+w,a+X $dir
  400. done
  401. for dir in `find $HOME -mindepth 2 -maxdepth 2 -type d | egrep "^$HOME/webshareddata/"`; do
  402. chown -R $user: $dir
  403. chmod -R u=rw,go=r,a+X $dir
  404. done
  405. for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/webphpsites"`; do
  406. chown root: $dir
  407. chmod u=rw,go=r,a+X $dir
  408. done
  409. for dir in `find $HOME -mindepth 2 -maxdepth 2 -type d | egrep "^$HOME/webphpsites/"`; do
  410. chown -R $user:www-data $dir
  411. # chmod -R ug=rw,o=r,a+X $dir
  412. chmod -R ug=rw,o=,ug+X $dir
  413. done
  414. for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/webphpdata"`; do
  415. chown root: $dir
  416. chmod a=r,u+w,a+X $dir
  417. done
  418. for dir in `find $HOME -mindepth 2 -maxdepth 2 -type d | egrep "^$HOME/webphpdata/"`; do
  419. chown -R $user:www-data $dir
  420. chmod -R ug=rw,o=,ug+X $dir
  421. done
  422. # Dummy user restrictions
  423. if [ -n "$REALUSERS_GROUPNAME" -a -n "$DUMMYSHAREDIR" -a -n "$DUMMYSHAREOWNER" -a -n "$DUMMYSHARENAME" ]; then
  424. [ -e $DUMMYSHAREDIR/$user ] \
  425. || mkdir $DUMMYSHAREDIR/$user
  426. chown $DUMMYSHAREOWNER: $DUMMYSHAREDIR/$user
  427. chmod u=rw,go=r,a+X $DUMMYSHAREDIR/$user
  428. if [ -e $HOME/$DUMMYSHARENAME ]; then
  429. if [ -L $HOME/$DUMMYSHARENAME ]; then
  430. ln -sf $DUMMYSHAREDIR/$user $HOME/$DUMMYSHARENAME
  431. chown $user: $HOME/$DUMMYSHARENAME
  432. else
  433. echo "WARNING: $HOME/$DUMMYSHAREDIR exists already. Leaving it as is..."
  434. fi
  435. else
  436. ln -s $DUMMYSHAREDIR/$user $HOME/$DUMMYSHARENAME
  437. chown $user: $HOME/$DUMMYSHARENAME
  438. fi
  439. if [ -n "$DUMMYAPACHECFG" -a -n "$DUMMYAPACHESHAREDIR" ]; then
  440. if [ -f /etc/apache/include.d/$DUMMYAPACHECFG -a -x /etc/init.d/apache ]; then
  441. if [ -e /etc/apache/include.d/$DUMMYAPACHECFG-$user ]; then
  442. echo "/etc/apache/include.d/$DUMMYAPACHECFG-$user exists already. Ignoring..."
  443. else
  444. echo "# Created automatically by adduser.local
  445. <Location /$DUMMYAPACHESHAREDIR/$user>
  446. <Limit GET POST>
  447. require user $user
  448. </Limit>
  449. </Location>" \
  450. > /etc/apache/include.d/$DUMMYAPACHECFG-$user
  451. root_required="yes"
  452. fi
  453. fi
  454. fi
  455. fi