Changeset 133


Ignore:
Timestamp:
Jan 28, 2007, 6:50:47 PM (15 years ago)
Author:
andersk
Message:
Updated webaccess to fix security problems.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • locker/bin/webaccess

    r128 r133  
    1 #!/usr/bin/perl
    2 use strict;
    3 
    4 my ($op, $username) = @ARGV;
    5 
    6 if(defined $op and $op eq "reset") {
    7         system("rm -f .htaccess .htpasswd");
    8     print "\nDone.  All access restrictions removed.\n\n";
    9         exit(0);
     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
     7set -e
     8
     9on_exit=
     10trap 'eval "$on_exit"' EXIT
     11
     12dir="$(pwd)"
     13htaccess=$dir/.htaccess
     14authuserfile=$dir/.htpasswd
     15
     16add_users=
     17del_users=
     18enable_auth=1
     19def_authname=\"Private\"
     20
     21begin_section="### BEGIN webaccess directives"
     22end_section="### END webaccess directives"
     23
     24usage () {
     25    cat <<EOF >&2
     26usage:
     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.
     30EOF
     31    exit 1
    1032}
    1133
    12 if(!defined $op or !defined $username or
    13         ($op ne "allow" and $op ne "remove")) {
    14         print "Usage: webaccess [allow username] [remove username] [reset]\n";
    15         exit(0);
     34getpass () {
     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    )
    1642}
    1743
    18 if($op eq "allow" or $op eq "remove") {
    19         open(HTPASSWD, ".htpasswd");
    20         open(TMP, ">.htpasswd_tmp");
    21         while(my $line = <HTPASSWD>) {
    22                 print TMP "$line" unless($line =~ /$username\:/);
    23         }
    24         close(TMP);
    25         close(HTPASSWD);
    26         system("mv .htpasswd_tmp .htpasswd");
     44if [ $# -eq 0 ]; then usage; fi
     45
     46while [ $# -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
     83done
     84
     85tmp_htaccess=$htaccess.webaccess-new
     86trap 'rm -f "$tmp_htaccess"' EXIT
     87exec 3>"$tmp_htaccess"
     88
     89config_written=0
     90write_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
    27102}
    28103
    29 if($op eq "allow") {
    30         my $password;
    31         print "Enter new password for $username: ";
    32         system("stty -echo");
    33         chop($password = <STDIN>);
    34         system("stty echo");
    35         print "\n";
    36 
    37         open(HTACCESS, ">.htaccess");
    38         print HTACCESS <<ENDFILE;
    39 AuthUserFile $ENV{PWD}/.htpasswd
    40 AuthName Private
    41 AuthType Basic
    42 <Limit GET>
    43 require valid-user
    44 </Limit>
    45 ENDFILE
    46         close(HTACCESS);
    47         chmod(0777, ".htaccess");
    48 
    49         my $salt = join '', ('.', '/', 0..9, 'A'..'Z', 'a'..'z') [rand 64, rand 64, rand 64, rand 64, rand 64, rand 64, rand 64, rand 64];
    50         $password = crypt($password, '$1$'.$salt);
    51 
    52         open(HTPASSWD, ">>.htpasswd");
    53         print HTPASSWD "$username\:$password\n";
    54         close(HTPASSWD);
    55         chmod(0777, ".htpasswd");
    56 }
    57 
    58 print "\nDone.  New list of valid usernames:\n";
    59 open(HTPASSWD, ".htpasswd");
    60 while(my $line = <HTPASSWD>) {
    61         $line =~ /(.*):/;
    62         print "$1\n";
    63 }
    64 close(HTPASSWD);
    65 print "\n";
     104if [ -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<&-
     161fi
     162
     163write_config
     164
     165exec 3>&-
     166if ! 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
     178fi
     179trap - EXIT
     180
     181if [ $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"
     224else
     225    rm -f "$authuserfile"
     226fi
Note: See TracChangeset for help on using the changeset viewer.