Hostwick.com/PasswordManager  

Home   Products   Services   Contact   Articles   Links  
 
This script manages password file for your web site.

Features:
It's a small fast pure Perl CGI (other than rcs feature).
It can add/delete/check/list/clear user:password combo in the password file of Apache.

It should work on any Linux host (other than the rcs feature).
When turned on, rcs feature will keep all records of modification tot he password file, allowing you to recover from accidental changes.

Disclaimer:
Keep the backup of your password file.
This is a freebie/DonationWare and you are agreeing to use it at your own risks by installing it.

Instruction:
Upload the script and set executable permission (often 755).
You may need to change the path for Perl (the first line of the script)

Downlodable code PasswordManager

Code:


#!/usr/bin/perl
#
#  Create/modify password file for httpd
#
# http://hostwick.com/PasswordManager.html
#

# Set $rcs to 1 if you want to use rcs to save different version of password file.
$rcs = 0;
$rcslog = '/dev/null';

$parent=(caller)[1];
if(!$parent){
  print "Content-type: text/html\n\n";
  print "<HTML><BODY bgcolor=#406060 text=#dFcFbF link=#fbe731 vlink=#fbe731 alink=#FFFF80>\n";
#  print $ENV{QUERY_STRING}."<br>\n";
  
  &form_decode();

print <<"__HEAD__";
<center>
<h1>Easy Password Manager</h1><hr>
</center>
<ul><ul>
__HEAD__


  $pf = ".htpf" if ! $pf;
  if($submit eq 'Add'){
    print "Adding $u:$pw to the $pf<br><br>\n";
	$r = add_userpass($pf,$u,$pw);
	if($r == 1){
      print "Done!" ;
	}else{
 	  print "result=$r<br>" ;
    }
  }elsif($submit eq 'Del'){
	   print "Deleting $u:$pw from $pf<br><br>\n";
	   $r = del_userpass($pf,$u);
	if($r == 1){
      print "Done!" ;
	}else{
 	  print "result=$r<br>" ;
    }
   }elsif($submit eq 'Change'){
		print "Cahnging $u:$pw in $pf<br><br>\n";
   	   $r =change_userpass($pf,$u,$pw);
	if($r == 1){
      print "Done!" ;
	}else{
 	  print "result=$r<br>" ;
    }
   }elsif($submit eq 'Check'){
	   print "Checking $u:$pw  in $pf<br><br>\n";
   	   $r = check_userpass($pf,$u,$pw);
	if($r == 1){
      print "<b><font color=lightblue>User name and Password matched!</font></b>" ;
	}else{
      print "<b><font color=red>User name and Password mismatch!</font></b>" ;
    }
   }elsif($submit eq 'List'){
	   print "Listing users in $pf<br><br>\n";
   	   $r = list_userpass($pf,$u,$pw);
	   print "result=$r<br>"  if $r > 1;
   }elsif($submit eq 'Clear'){
	   print "Clearing $pf<br><br>\n";
   	   $r = clear_userpass($pf,$u,$pw);
	   print "result=$r<br>" if $r > 1;
   }
   
  print  <<"__END__";
</ul></ul><hr>
<BR><center><Form action=\"\" method=POST>
<table><tr><td> Password file: <input type=text name=pf size=20 value=\"$pf\">  &nbsp;
 Username: <input type=text name=u size=20 value=\"$u\"> &nbsp;
 Password: <input type=text name=pw size=20 value=\"$pw\"></td></tr>
<tr><td align=right> <input type=submit name=submit value=\"Check\">
  <input type=submit name=submit value=\"Add\">
<input type=submit name=submit value=\"Del\">
<input type=submit name=submit value=\"Change\">
<input type=submit name=submit value=\"List\"></td></tr></table>
</FORM></cente>
__END__

 exit;
}

#escape string for regex
sub escex{
	local($s) = shift;	
   $s =~s/[\[\]\/\$\(\)\{\}.*!?:]/\\$1/g;
   return $s;
}

sub add_userpass {
	local($pf, $u, $p) = @_;
	open(FHPF, "+<$pf")  || return (3,"Could not open file: $pf");
    local(@pwf) = <FHPF>;
	#print "<pre>".@pwf."</pre>";
	seek(FHPF,0,0);
    @pwf = grep { !/^$u:/; } @pwf;
	@pwf = grep { !/^\n*$/; } @pwf;
	push(@pwf, "$u:".enc_crypt($p)."\n" );
	#print join("<br>",@pwf)."<br>\n";
	print FHPF  join("",@pwf);
    close(FHPF);
    `(date;exec 2>&1;rcs -U -u $pf;ci -w$ru -M -u $pf;chmod 644 $pf)  >>$rcslog 2>&1` if $rcs;
}
sub del_userpass {
	local($pf, $u) = @_;
	open(FHPF, "+<$pf")  || return (3,"Could not open file: $pf");
    local(@pwf) = <FHPF>;
    close(FHPF);
    $u = escex($u);
    @pwf = grep { !/^$u:/; } @pwf;
    open(FHPF, ">$pf")  || return (3,"Could not open file: $pf");
	print FHPF  join("",@pwf);
    close(FHPF);
    `(date;exec 2>&1;rcs -U -u $pf;ci -w$ru -M -u $pf;chmod 644 $pf)  >>$rcslog 2>&1` if $rcs;
}
sub change_userpass{
	#del_userpass($pf,$u) || return 0;
	return add_userpass($pf,$u,$p);
}

# check if the user exists and the password matches
# check(pf, u, p)
sub check_userpass{
	local($pf, $u, $p) = @_;
	open(FHPF, "$pf")  || return (3,"Could not open file: $pf");
    local(@pwf) = <FHPF>;
    close(FHPF);
    $u = escex($u);
    local(@rl) = grep { s/^$u://s; } @pwf;
	local($pw) = @rl[0];
	chomp($pw);
	#print "<hr>$user=$u, pw=$p,  enc=".$pw."<hr>\n";
    return check_crypt($p, $pw);
}

sub list_userpass{
	local($pf) = @_;
	open(FHPF, "$pf")  || return (3,"Could not open file: $pf");
    local(@pwf) = <FHPF>;
    close(FHPF);
    print join("<br>",@pwf)."<br>\n";
	return 1;
}

sub clear_userpass {
	local($pf) = @_;
	open(FHPF, ">$pf")  || return (3,"Could not open file: $pf");
    close(FHPF) || return (3,"Could not close file: $pf");
	return 1;
}


# crypting
# arg: password
# return: crypted
# ex: $pass = &enc_crypt('PassWord');
sub enc_crypt {
    local($plain) = @_;
    local($s) = '';
    local(@salt) = ('0'..'9','A'..'Z','a'..'z','.','/');
    srand;
    1 while (length($s .= $salt[rand(@salt)]) < 8);
    crypt($plain,index(crypt('a','$1$a$'),'$1$a$') == 0 ? '$1$'.$s.'$' : $s);
}

# check
# arg: password, crypted
# return: True=OK, false=NG
# ex:&check_crypt('PassWord',$pass) ? 'OK' : 'NG'
sub check_crypt {
    local($plain,$crypt) = @_;
    ($plain ne '' && $crypt ne '' && crypt($plain,$crypt) eq $crypt);
}


sub form_decode {
	local( $pair, $name, $value, $buffer, @pairs);
    $maxbyte = 4000000;

	if ($ENV{'REQUEST_METHOD'} eq "POST") {
		if ($ENV{'CONTENT_LENGTH'} > $maxbyte) { 
			read(STDIN, $buffer, $maxbyte);
			$error .= "CONTENT_LENGTH exceeds $maxbyte\n";
		} else {
		read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
		}
	} else { $buffer = $ENV{'QUERY_STRING'}; }
	$cl = $ENV{'CONTENT_LENGTH'};
	$bl = length($buffer);
	$error .= "buffer length exceeds $maxbyte\n" if $bl > $maxbyte; 
	@pairs = split(/&/, $buffer);
	foreach $pair (@pairs) {
#		print "$pair<BR>\n";
		($name, $value) = split(/=/, $pair);
		$value =~ tr/+/ /;
		$value =~ s/%u([0-9a-fA-F]{4})/pack('H4', $1)/eg;
		$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;

		eval("\$"."$name = \$value;");
#		print "$name, $value<BR>\n";
	}
}

sub logdata{
  local(@t)= gmtime(time + $offset);
  local($wday)= ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun')[$t[6]] ;

  $mdate = sprintf("%04d/%02d/%02d(%s)%02d:%02d:%02d",
     $t[5]+1900, $t[4], $t[3],$wday, $t[2], $t[1], $t[0] ) ;

  $rh = $ENV{REMOTE_HOST};
  $addr = $ENV{REMOTE_ADDR};
  $rh = gethostbyaddr(pack("C4",split(/\./, $addr)),2) if $rh eq "" || $host eq $addr;
  $host = "$rh:$addr:$ENV{HTTP_USER_AGENT}";
  return "$mdate, $0,$ldatpre $host, $ENV{HTTP_REFERER}, $ENV{REQUEST_URI}, $ldat\n";
}

1;
 
Home   Products   Services   Contact   Articles   Links  
Hostwick.com --- Generated on 2007-01-24_07:52:52