| 1 | #!/bin/bash | 
|---|
| 2 |  | 
|---|
| 3 | # webaccess | 
|---|
| 4 | # Manage access control for scripts.mit.edu in .htaccess and .htpasswd files. | 
|---|
| 5 | # Anders Kaseorg <andersk@mit.edu> | 
|---|
| 6 |  | 
|---|
| 7 | set -e | 
|---|
| 8 |  | 
|---|
| 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 | 
|---|
| 32 | } | 
|---|
| 33 |  | 
|---|
| 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 |     ) | 
|---|
| 42 | } | 
|---|
| 43 |  | 
|---|
| 44 | if [ $# -eq 0 ]; then usage; fi | 
|---|
| 45 |  | 
|---|
| 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 | 
|---|
| 84 |  | 
|---|
| 85 | tmp_htaccess=$htaccess.webaccess-new | 
|---|
| 86 | trap 'rm -f "$tmp_htaccess"' EXIT | 
|---|
| 87 | exec 3>"$tmp_htaccess" | 
|---|
| 88 |  | 
|---|
| 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 | 
|---|
| 102 | } | 
|---|
| 103 |  | 
|---|
| 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 |         mv -f "$tmp_htaccess" "$htaccess" | 
|---|
| 170 |     else | 
|---|
| 171 |         if [ -e "$htaccess" ]; then | 
|---|
| 172 |             echo "Deleting $htaccess" >&2 | 
|---|
| 173 |             rm -f "$htaccess" | 
|---|
| 174 |         fi | 
|---|
| 175 |         rm -f "$tmp_htaccess" | 
|---|
| 176 |     fi | 
|---|
| 177 | fi | 
|---|
| 178 | trap - EXIT | 
|---|
| 179 |  | 
|---|
| 180 | if [ $enable_auth -eq 1 ]; then | 
|---|
| 181 |     if [ ! -e "$authuserfile" ]; then touch "$authuserfile"; fi | 
|---|
| 182 |      | 
|---|
| 183 |     tmp_authuserfile=$authuserfile.webaccess-new | 
|---|
| 184 |     trap 'rm -f "$tmp_authuserfile"' EXIT | 
|---|
| 185 |     exec 3>"$tmp_authuserfile" | 
|---|
| 186 |  | 
|---|
| 187 |     exec 4<"$authuserfile" | 
|---|
| 188 |     while IFS=: read user pass <&4; do | 
|---|
| 189 |         for del_user in $del_users; do | 
|---|
| 190 |             if [ "$del_user" = "$user" ]; then | 
|---|
| 191 |                 echo "Deleting user $del_user:" >&2 | 
|---|
| 192 |                 pass= | 
|---|
| 193 |             fi | 
|---|
| 194 |         done | 
|---|
| 195 |         new_add_users= | 
|---|
| 196 |         for add_user in $add_users; do | 
|---|
| 197 |             if [ "$add_user" = "$user" ]; then | 
|---|
| 198 |                 pass=$(getpass "$user") | 
|---|
| 199 |             else | 
|---|
| 200 |                 new_add_users=$new_add_users\ $add_user | 
|---|
| 201 |             fi | 
|---|
| 202 |         done | 
|---|
| 203 |         add_users=$new_add_users | 
|---|
| 204 |         if [ -n "$pass" ]; then | 
|---|
| 205 |             echo "$user:$pass" >&3 | 
|---|
| 206 |         fi | 
|---|
| 207 |     done | 
|---|
| 208 |     exec 4<&- | 
|---|
| 209 |      | 
|---|
| 210 |     for add_user in $add_users; do | 
|---|
| 211 |         pass=$(getpass "$add_user") | 
|---|
| 212 |         echo "$add_user:$pass" >&3 | 
|---|
| 213 |     done | 
|---|
| 214 |      | 
|---|
| 215 |     exec 3>&- | 
|---|
| 216 |     mv -f "$tmp_authuserfile" "$authuserfile" | 
|---|
| 217 |     trap - EXIT | 
|---|
| 218 |      | 
|---|
| 219 |     echo "Done.  New list of valid users:" >&2 | 
|---|
| 220 |     sed -n 's/^\([^:]*\):.*$/  \1/ p' "$authuserfile" | 
|---|
| 221 | else | 
|---|
| 222 |     rm -f "$authuserfile" | 
|---|
| 223 | fi | 
|---|