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