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