| [133] | 1 | #!/bin/bash | 
|---|
| [127] | 2 |  | 
|---|
| [133] | 3 | # webaccess | 
|---|
 | 4 | # Manage access control for scripts.mit.edu in .htaccess and .htpasswd files. | 
|---|
 | 5 | # Anders Kaseorg <andersk@mit.edu> | 
|---|
| [127] | 6 |  | 
|---|
| [133] | 7 | set -e | 
|---|
| [127] | 8 |  | 
|---|
| [133] | 9 | on_exit= | 
|---|
 | 10 | trap 'eval "$on_exit"' EXIT | 
|---|
 | 11 |  | 
|---|
 | 12 | dir="$(pwd)" | 
|---|
 | 13 | htaccess=$dir/.htaccess | 
|---|
 | 14 | authuserfile=$dir/.htpasswd | 
|---|
 | 15 |  | 
|---|
 | 16 | add_users= | 
|---|
 | 17 | del_users= | 
|---|
 | 18 | enable_auth=1 | 
|---|
 | 19 | def_authname=\"Private\" | 
|---|
 | 20 |  | 
|---|
 | 21 | begin_section="### BEGIN webaccess directives" | 
|---|
 | 22 | end_section="### END webaccess directives" | 
|---|
 | 23 |  | 
|---|
 | 24 | usage () { | 
|---|
 | 25 |     cat <<EOF >&2 | 
|---|
 | 26 | usage: | 
|---|
 | 27 |   webaccess -a <user>   Allow access from <user> and set password. | 
|---|
 | 28 |   webaccess -d <user>   Deny access from <user>. | 
|---|
 | 29 |   webaccess -r          Reset default access control. | 
|---|
 | 30 | EOF | 
|---|
 | 31 |     exit 1 | 
|---|
| [127] | 32 | } | 
|---|
 | 33 |  | 
|---|
| [133] | 34 | getpass () { | 
|---|
 | 35 |     user=$1 | 
|---|
 | 36 |     ( | 
|---|
 | 37 |         echo -n "New password for $user: " >/dev/tty | 
|---|
 | 38 |         trap 'stty echo; echo >/dev/tty' EXIT | 
|---|
 | 39 |         stty -echo | 
|---|
 | 40 |         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])' </dev/tty | 
|---|
 | 41 |     ) | 
|---|
| [127] | 42 | } | 
|---|
 | 43 |  | 
|---|
| [133] | 44 | if [ $# -eq 0 ]; then usage; fi | 
|---|
| [127] | 45 |  | 
|---|
| [133] | 46 | while [ $# -gt 0 ]; do | 
|---|
 | 47 |     arg="$1"; shift | 
|---|
 | 48 |     case "$arg" in | 
|---|
 | 49 |         -a*) | 
|---|
 | 50 |             user="${arg#-a}" | 
|---|
 | 51 |             if [ -z "$user" ]; then user=$1; shift; fi | 
|---|
 | 52 |             if [ -z "$user" ]; then usage; fi | 
|---|
 | 53 |             add_users=$add_users\ $user | 
|---|
 | 54 |             ;; | 
|---|
 | 55 |         allow) | 
|---|
 | 56 |             user="$1"; shift | 
|---|
 | 57 |             if [ -z "$user" ]; then usage; fi | 
|---|
 | 58 |             add_users=$add_users\ $user | 
|---|
 | 59 |             ;; | 
|---|
 | 60 |         -d*) | 
|---|
 | 61 |             user="${arg#-d}" | 
|---|
 | 62 |             if [ -z "$user" ]; then user=$1; shift; fi | 
|---|
 | 63 |             if [ -z "$user" ]; then usage; fi | 
|---|
 | 64 |             del_users=$del_users\ $user | 
|---|
 | 65 |             ;; | 
|---|
 | 66 |         remove) | 
|---|
 | 67 |             user="$1"; shift | 
|---|
 | 68 |             if [ -z "$user" ]; then usage; fi | 
|---|
 | 69 |             del_users=$del_users\ $user | 
|---|
 | 70 |             ;; | 
|---|
 | 71 |         -r|reset) | 
|---|
 | 72 |             enable_auth=0 | 
|---|
 | 73 |             ;; | 
|---|
 | 74 |         -n*) | 
|---|
 | 75 |             authname="${arg#-n}" | 
|---|
 | 76 |             if [ -z "$authname" ]; then authname=\"$1\"; shift; fi | 
|---|
 | 77 |             if [ -z "$authname" ]; then usage; fi | 
|---|
 | 78 |             ;; | 
|---|
 | 79 |         *) | 
|---|
 | 80 |             usage | 
|---|
 | 81 |             ;; | 
|---|
 | 82 |     esac | 
|---|
 | 83 | done | 
|---|
| [127] | 84 |  | 
|---|
| [133] | 85 | tmp_htaccess=$htaccess.webaccess-new | 
|---|
 | 86 | trap 'rm -f "$tmp_htaccess"' EXIT | 
|---|
 | 87 | exec 3>"$tmp_htaccess" | 
|---|
| [127] | 88 |  | 
|---|
| [133] | 89 | config_written=0 | 
|---|
 | 90 | write_config () { | 
|---|
 | 91 |     if [ $config_written -eq 1 ]; then return 0; fi | 
|---|
 | 92 |     config_written=1 | 
|---|
 | 93 |     if [ $enable_auth -eq 1 ]; then | 
|---|
 | 94 |         echo "$begin_section" >&3 | 
|---|
 | 95 |         echo "# See http://scripts.mit.edu/faq/23" >&3 | 
|---|
 | 96 |         echo "AuthUserFile $authuserfile" >&3 | 
|---|
 | 97 |         echo "AuthName ${authname:-$def_authname}" >&3 | 
|---|
 | 98 |         echo "AuthType Basic" >&3 | 
|---|
 | 99 |         echo "Require valid-user" >&3 | 
|---|
 | 100 |         echo "$end_section" >&3 | 
|---|
 | 101 |     fi | 
|---|
| [127] | 102 | } | 
|---|
 | 103 |  | 
|---|
| [133] | 104 | if [ -e "$htaccess" ]; then | 
|---|
 | 105 |     exec 4<"$htaccess" | 
|---|
 | 106 |      | 
|---|
 | 107 |     oldconfig_state=0 | 
|---|
 | 108 |     oldconfig_buffer=__END__ | 
|---|
 | 109 |      | 
|---|
 | 110 |     while read -r line <&4; do | 
|---|
 | 111 |         oldconfig_newstate=0 | 
|---|
 | 112 |         case "$line" in | 
|---|
 | 113 |             "AuthUserFile "*)     oldconfig_newstate=1 ;; | 
|---|
 | 114 |             "AuthName "*)         oldconfig_newstate=2; oldconfig_authname=${line#AuthName } ;; | 
|---|
 | 115 |             "AuthType Basic")     oldconfig_newstate=3 ;; | 
|---|
 | 116 |             "<Limit GET>")        oldconfig_newstate=4 ;; | 
|---|
 | 117 |             "require valid-user") oldconfig_newstate=5 ;; | 
|---|
 | 118 |             "</Limit>")           oldconfig_newstate=6 ;; | 
|---|
 | 119 |         esac | 
|---|
 | 120 |          | 
|---|
 | 121 |         if [ $oldconfig_newstate -ne $(($oldconfig_state + 1)) ]; then | 
|---|
 | 122 |             if [ $oldconfig_state -ne 0 ]; then | 
|---|
 | 123 |                 echo "${oldconfig_buffer% | 
|---|
 | 124 | __END__}" >&3 | 
|---|
 | 125 |                 oldconfig_state=0 | 
|---|
 | 126 |                 oldconfig_buffer=__END__ | 
|---|
 | 127 |             fi | 
|---|
 | 128 |         fi | 
|---|
 | 129 |          | 
|---|
 | 130 |         if [ "$line" = "$begin_section" ]; then | 
|---|
 | 131 |             while read -r line <&4 && [ "$line" != "$end_section" ]; do | 
|---|
 | 132 |                 case "$line" in | 
|---|
 | 133 |                     "AuthName "*) | 
|---|
 | 134 |                         def_authname=${line#AuthName } | 
|---|
 | 135 |                         ;; | 
|---|
 | 136 |                 esac | 
|---|
 | 137 |             done | 
|---|
 | 138 |             write_config | 
|---|
 | 139 |         elif [ $oldconfig_newstate -eq $(($oldconfig_state + 1)) ]; then | 
|---|
 | 140 |             oldconfig_buffer=$(echo "${oldconfig_buffer%__END__}$line"; echo __END__) | 
|---|
 | 141 |             oldconfig_state=$oldconfig_newstate | 
|---|
 | 142 |             if [ $oldconfig_state -eq 6 ]; then | 
|---|
 | 143 |                 echo "Replacing obsolete webaccess configuration." >&2 | 
|---|
 | 144 |                 oldconfig_state=0 | 
|---|
 | 145 |                 oldconfig_buffer=__END__ | 
|---|
 | 146 |                 def_authname=$oldconfig_authname | 
|---|
 | 147 |             fi | 
|---|
 | 148 |         else | 
|---|
 | 149 |             echo "$line" >&3 | 
|---|
 | 150 |         fi | 
|---|
 | 151 |     done | 
|---|
 | 152 |      | 
|---|
 | 153 |     if [ $oldconfig_state -ne 0 ]; then | 
|---|
 | 154 |         echo "${oldconfig_buffer% | 
|---|
 | 155 | __END__}" | 
|---|
 | 156 |         oldconfig_state=0 | 
|---|
 | 157 |         oldconfig_buffer=__END__ | 
|---|
 | 158 |     fi | 
|---|
 | 159 |      | 
|---|
 | 160 |     exec 4<&- | 
|---|
 | 161 | fi | 
|---|
 | 162 |  | 
|---|
 | 163 | write_config | 
|---|
 | 164 |  | 
|---|
 | 165 | exec 3>&- | 
|---|
 | 166 | if ! cmp -s "$htaccess" "$tmp_htaccess"; then | 
|---|
 | 167 |     if [ -s "$tmp_htaccess" ]; then | 
|---|
 | 168 |         echo "Updating $htaccess" >&2 | 
|---|
 | 169 |         chmod 777 "$tmp_htaccess" | 
|---|
 | 170 |         mv -f "$tmp_htaccess" "$htaccess" | 
|---|
 | 171 |     else | 
|---|
 | 172 |         if [ -e "$htaccess" ]; then | 
|---|
 | 173 |             echo "Deleting $htaccess" >&2 | 
|---|
 | 174 |             rm -f "$htaccess" | 
|---|
 | 175 |         fi | 
|---|
 | 176 |         rm -f "$tmp_htaccess" | 
|---|
 | 177 |     fi | 
|---|
 | 178 | fi | 
|---|
 | 179 | trap - EXIT | 
|---|
 | 180 |  | 
|---|
 | 181 | if [ $enable_auth -eq 1 ]; then | 
|---|
 | 182 |     if [ ! -e "$authuserfile" ]; then touch "$authuserfile"; fi | 
|---|
 | 183 |     chmod 777 "$authuserfile" | 
|---|
 | 184 |      | 
|---|
 | 185 |     tmp_authuserfile=$authuserfile.webaccess-new | 
|---|
 | 186 |     trap 'rm -f "$tmp_authuserfile"' EXIT | 
|---|
 | 187 |     exec 3>"$tmp_authuserfile" | 
|---|
 | 188 |  | 
|---|
 | 189 |     exec 4<"$authuserfile" | 
|---|
 | 190 |     while IFS=: read user pass <&4; do | 
|---|
 | 191 |         for del_user in $del_users; do | 
|---|
 | 192 |             if [ "$del_user" = "$user" ]; then | 
|---|
 | 193 |                 echo "Deleting user $del_user:" >&2 | 
|---|
 | 194 |                 pass= | 
|---|
 | 195 |             fi | 
|---|
 | 196 |         done | 
|---|
 | 197 |         new_add_users= | 
|---|
 | 198 |         for add_user in $add_users; do | 
|---|
 | 199 |             if [ "$add_user" = "$user" ]; then | 
|---|
 | 200 |                 pass=$(getpass "$user") | 
|---|
 | 201 |             else | 
|---|
 | 202 |                 new_add_users=$new_add_users\ $add_user | 
|---|
 | 203 |             fi | 
|---|
 | 204 |         done | 
|---|
 | 205 |         add_users=$new_add_users | 
|---|
 | 206 |         if [ -n "$pass" ]; then | 
|---|
 | 207 |             echo "$user:$pass" >&3 | 
|---|
 | 208 |         fi | 
|---|
 | 209 |     done | 
|---|
 | 210 |     exec 4<&- | 
|---|
 | 211 |      | 
|---|
 | 212 |     for add_user in $add_users; do | 
|---|
 | 213 |         pass=$(getpass "$add_user") | 
|---|
 | 214 |         echo "$add_user:$pass" >&3 | 
|---|
 | 215 |     done | 
|---|
 | 216 |      | 
|---|
 | 217 |     exec 3>&- | 
|---|
 | 218 |     chmod 777 "$tmp_authuserfile" | 
|---|
 | 219 |     mv -f "$tmp_authuserfile" "$authuserfile" | 
|---|
 | 220 |     trap - EXIT | 
|---|
 | 221 |      | 
|---|
 | 222 |     echo "Done.  New list of valid users:" >&2 | 
|---|
 | 223 |     sed -n 's/^\([^:]*\):.*$/  \1/ p' "$authuserfile" | 
|---|
 | 224 | else | 
|---|
 | 225 |     rm -f "$authuserfile" | 
|---|
 | 226 | fi | 
|---|