#!/bin/bash # webaccess # Manage access control for scripts.mit.edu in .htaccess and .htpasswd files. # Anders Kaseorg set -e on_exit= trap 'eval "$on_exit"' EXIT dir="$(pwd)" htaccess=$dir/.htaccess authuserfile=$dir/.htpasswd add_users= del_users= enable_auth=1 def_authname=\"Private\" begin_section="### BEGIN webaccess directives" end_section="### END webaccess directives" usage () { cat <&2 usage: webaccess -a Allow access from and set password. webaccess -d Deny access from . webaccess -r Reset default access control. EOF exit 1 } getpass () { user=$1 ( echo -n "New password for $user: " >/dev/tty trap 'stty echo; echo >/dev/tty' EXIT stty -echo perl -e 'chop($_ = <>); print crypt($_, "\$1\$" . join "", (".", "/", "0".."9", "A".."Z", "a".."z") [rand 64, rand 64, rand 64, rand 64, rand 64, rand 64, rand 64, rand 64])' "$tmp_htaccess" config_written=0 write_config () { if [ $config_written -eq 1 ]; then return 0; fi config_written=1 if [ $enable_auth -eq 1 ]; then echo "$begin_section" >&3 echo "# See http://scripts.mit.edu/faq/23" >&3 echo "AuthUserFile $authuserfile" >&3 echo "AuthName ${authname:-$def_authname}" >&3 echo "AuthType Basic" >&3 echo "Require valid-user" >&3 echo "$end_section" >&3 fi } if [ -e "$htaccess" ]; then exec 4<"$htaccess" oldconfig_state=0 oldconfig_buffer=__END__ while read -r line <&4; do oldconfig_newstate=0 case "$line" in "AuthUserFile "*) oldconfig_newstate=1 ;; "AuthName "*) oldconfig_newstate=2; oldconfig_authname=${line#AuthName } ;; "AuthType Basic") oldconfig_newstate=3 ;; "") oldconfig_newstate=4 ;; "require valid-user") oldconfig_newstate=5 ;; "") oldconfig_newstate=6 ;; esac if [ $oldconfig_newstate -ne $(($oldconfig_state + 1)) ]; then if [ $oldconfig_state -ne 0 ]; then echo "${oldconfig_buffer% __END__}" >&3 oldconfig_state=0 oldconfig_buffer=__END__ fi fi if [ "$line" = "$begin_section" ]; then while read -r line <&4 && [ "$line" != "$end_section" ]; do case "$line" in "AuthName "*) def_authname=${line#AuthName } ;; esac done write_config elif [ $oldconfig_newstate -eq $(($oldconfig_state + 1)) ]; then oldconfig_buffer=$(echo "${oldconfig_buffer%__END__}$line"; echo __END__) oldconfig_state=$oldconfig_newstate if [ $oldconfig_state -eq 6 ]; then echo "Replacing obsolete webaccess configuration." >&2 oldconfig_state=0 oldconfig_buffer=__END__ def_authname=$oldconfig_authname fi else echo "$line" >&3 fi done if [ $oldconfig_state -ne 0 ]; then echo "${oldconfig_buffer% __END__}" oldconfig_state=0 oldconfig_buffer=__END__ fi exec 4<&- fi write_config exec 3>&- if ! cmp -s "$htaccess" "$tmp_htaccess"; then if [ -s "$tmp_htaccess" ]; then echo "Updating $htaccess" >&2 mv -f "$tmp_htaccess" "$htaccess" else if [ -e "$htaccess" ]; then echo "Deleting $htaccess" >&2 rm -f "$htaccess" fi rm -f "$tmp_htaccess" fi fi trap - EXIT if [ $enable_auth -eq 1 ]; then if [ ! -e "$authuserfile" ]; then touch "$authuserfile"; fi tmp_authuserfile=$authuserfile.webaccess-new trap 'rm -f "$tmp_authuserfile"' EXIT exec 3>"$tmp_authuserfile" exec 4<"$authuserfile" while IFS=: read user pass <&4; do for del_user in $del_users; do if [ "$del_user" = "$user" ]; then echo "Deleting user $del_user:" >&2 pass= fi done new_add_users= for add_user in $add_users; do if [ "$add_user" = "$user" ]; then pass=$(getpass "$user") else new_add_users=$new_add_users\ $add_user fi done add_users=$new_add_users if [ -n "$pass" ]; then echo "$user:$pass" >&3 fi done exec 4<&- for add_user in $add_users; do pass=$(getpass "$add_user") echo "$add_user:$pass" >&3 done exec 3>&- mv -f "$tmp_authuserfile" "$authuserfile" trap - EXIT echo "Done. New list of valid users:" >&2 sed -n 's/^\([^:]*\):.*$/ \1/ p' "$authuserfile" else rm -f "$authuserfile" fi