#!/usr/bin/perl

# Folgende Variable bitte anpassen:

# full system path to the user password file including the file itself
$AuthUserFile = "/opt/www/etc/.htpasswd";

# mail program
$mailprog = "/usr/lib/sendmail";

# webmasters email address.
$yourmail = "webmaster\@netzmafia.de";

# The script will send you an email if somebody entered a wrong password
# for entering the admin script. (n=off, y=on)
$alert = "y";

# Nothing to be changed below (please leave this line unchanged)
#######################################################################
$exlock=2;
$unlock=8;

read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
@pairs = split(/&/, $buffer);
foreach $pair (@pairs) 
  {
  ($name, $value) = split(/=/, $pair);
  $value =~ tr/+/ /;
  $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
  $input{$name} = $value;
  }

print "Content-type: text/html\n\n";
print "<html><head><title>htpasswd Manager</title></head><body>\n";
print "<H1>htpasswd Manager</H1>\n";
print "<H4>Action: $input{'action'}</H4>\n";
if ($input{'action'} eq "adduser") { &adduser; }
if ($input{'action'} eq "deluser") { &deluser; }
if ($input{'action'} eq "changepw") { &changepassword; }
if ($input{'action'} eq "listusers") { &listusers; }
print "</body></html>\n";
exit;


sub adduser 
  {
  &verifyadmin;
  &checkpasswd;

  open (data, "<$AuthUserFile") 
       or &error("Unable to open $AuthUserFile");
  flock data, $exlock; 
  @data=<data>;
  flock data, $unlock; 
  close(data); 

  foreach $dat(@data) 
    {
    ($user,$pass) = split(/:/, $dat);
    unless ($input{'username'} ne "$user" or $input{'username'} != $user)
      {
      print "Sorry, den User <i>\"$input{'username'}\"</i> gibt es schon.";
      print "</body></html>\n";
      exit;
      }
    }

  $password = crypt($input{'password1'}, "JP");

  open (wdata, ">>$AuthUserFile") 
       or &error("Unable to write to $AuthUserFile.");
  flock data, $exlock; 
  print wdata "$input{'username'}:$password\n";
  flock data, $unlock; 
  close(wdata); 

  print "Benutzer \"$input{'username'}\" ist eingetragen.";
  print "</body></html>\n";
  exit;
  }	

sub changepassword 
  {
  &verifyadmin;
  &checkpasswd;

  $found = 0;
  open (data, "<$AuthUserFile") 
       or &error("Unable to open $AuthUserFile");
  flock data, $exlock; 
  @data=<data>;
  flock data, $unlock; 
  close(data); 
  $count=0;

  $password = crypt($input{'password1'}, "JP");
  $newentry = $input{'username'} .':' . $password;
  foreach $dat(@data)
    {
    $count++;
    ($user,$pass)=split(/:/, $dat);
    if ($input{'username'} eq $user)
      {
      $found = 1;
      $count--;
      splice (@data, $count, 1, $newentry);
      open (wdata, ">$AuthUserFile") 
           or &error("Unable to write to $AuthUserFile.");
      flock data, $exlock; 
      print wdata @data;
      flock data, $unlock; 
      close(wdata); 
      } 
    }	
  if ($found == 0)
    {
    print "Benutzer \"$input{'username'}\" nicht gefunden!";
    }
  else
    {
    print "Benutzer \"$input{'username'}\" wurde geaendert.";
    }
  print "</body></html>\n";
  exit;
  }	

sub deluser 
  {
  &verifyadmin;
  open (data, "<$AuthUserFile") 
       or &error("Unable to open $AuthUserFile");
  flock data, $exlock; 
  @data=<data>;
  flock data, $unlock; 
  close(data); 
  $count=0;

  foreach $dat(@data)
    {
    $count++;
    ($user,$pass)=split(/:/, $dat);
    if ($input{'username'} eq $user)
      {
      $count--;
      splice (@data, $count, 1);
      open (wdata, ">$AuthUserFile") 
           or &error("Unable to write to $AuthUserFile.");
      flock data, $exlock; 
      print wdata @data;
      flock data, $unlock; 
      close(wdata); 
      print "Benutzer \"$input{'username'}\" wurde gel&ouml;scht.\n";
      print "</body></html>\n";
      exit;
      } 
    }	
  print "Benutzer \"$input{'username'}\" nicht gefunden!\n";
  print "</body></html>\n";
  exit;
  }	
	
sub listusers
  {
  &verifyadmin;
  open (data, "<$AuthUserFile") 
       or &error("Unable to open $AuthUserFile");
  flock data, $exlock; 
  @data=<data>;
  flock data, $unlock; 
  close(data); 
  $count=0;

  foreach $dat (sort @data)
    {
    $count++;
    ($user,$pass)=split(/:/, $dat);
    print "$count: $user<BR>\n";
    }
  print "</body></html>\n";
  exit;
  }

sub error
  {
  $errors = $_[0];
  print "<H4>Fehler aufgetreten:</H4>\n";
  print "<ul><li>$errors<li>$!</ul><P>\n";
  print "</body></html>\n";
  exit;
  }

sub verifyadmin
  {
  open (data, "<$AuthUserFile") 
       or &error("Unable to open $AuthUserFile");
  flock data, $exlock; 
  @data=<data>;
  flock data, $unlock; 
  close(data); 

  foreach $dat (@data) 
    {
    chomp($dat);
    ($user,$pass) = split(/:/, $dat);
    last if ($user eq "admin");
    }
  $pass2 = crypt($input{'apassword'}, "JP");
  unless ($pass eq $pass2) 
    {
    print "Falsches Administrator-Passwort!<br>";
    print "</body></html>";
    if ($alert eq "y") 
      {
      $timenow=localtime(time);
      open (MAIL, "|$mailprog -t") 
           or &error("Unable to open the mail program");
      print MAIL "To: $yourmail\n";
      print MAIL "From: $yourmail\n";
      print MAIL "Subject: [htpasswd] Falsches Passwort\n";
      print MAIL "Falsches Passwort fuer Htpasswd-Admin eingegeben.\n";
      print MAIL "Information:\n\n";
      print MAIL "$ENV{'REMOTE_ADDR'}\n";
      print MAIL "Password: $request{'password'}\n";
      print MAIL "$timenow\n";
      close(MAIL);
      }      
    exit;
    }
  }	


sub checkpasswd
  {
  if (!$input{'password1'} or !$input{'password2'}) 
    {
    print "Passwortfelder nicht leer lassen!";
    print "</body></html>\n";
    exit;
    }
	
  if ($input{'password1'} ne "$input{'password2'}" 
      or $input{'password1'} != $input{'password2'})
    {
    print "Die Passw&ouml;rter sind unterschiedlich!";
    print "</body></html>\n";
    exit;
    }
  }
