#!/usr/bin/perl
#
# Create/modify password file for httpd
#
# http://hostwick.com/PasswordManager.html
#
$rcs = 1;
$rcslog = '/dev/null';
$parent=(caller)[1];
if(!$parent){
print "Content-type: text/html\n\n";
print "
\n";
# print $ENV{QUERY_STRING}."
\n";
&form_decode();
print <<"__HEAD__";
Easy Password Manager
__HEAD__
$pf = ".htpf" if ! $pf;
if($submit eq 'Add'){
print "Adding $u:$pw to the $pf
\n";
$r = add_userpass($pf,$u,$pw);
if($r == 1){
print "Done!" ;
}else{
print "result=$r
" ;
}
}elsif($submit eq 'Del'){
print "Deleting $u:$pw from $pf
\n";
$r = del_userpass($pf,$u);
if($r == 1){
print "Done!" ;
}else{
print "result=$r
" ;
}
}elsif($submit eq 'Change'){
print "Cahnging $u:$pw in $pf
\n";
$r =change_userpass($pf,$u,$pw);
if($r == 1){
print "Done!" ;
}else{
print "result=$r
" ;
}
}elsif($submit eq 'Check'){
print "Checking $u:$pw in $pf
\n";
$r = check_userpass($pf,$u,$pw);
if($r == 1){
print "User name and Password matched!" ;
}else{
print "User name and Password mismatch!" ;
}
}elsif($submit eq 'List'){
print "Listing users in $pf
\n";
$r = list_userpass($pf,$u,$pw);
print "result=$r
" if $r > 1;
}elsif($submit eq 'Clear'){
print "Clearing $pf
\n";
$r = clear_userpass($pf,$u,$pw);
print "result=$r
" if $r > 1;
}
print <<"__END__";
__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) = ;
#print "".@pwf."
";
seek(FHPF,0,0);
@pwf = grep { !/^$u:/; } @pwf;
@pwf = grep { !/^\n*$/; } @pwf;
push(@pwf, "$u:".enc_crypt($p)."\n" );
#print join("
",@pwf)."
\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) = ;
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) = ;
close(FHPF);
$u = escex($u);
local(@rl) = grep { s/^$u://s; } @pwf;
local($pw) = @rl[0];
chomp($pw);
#print "
$user=$u, pw=$p, enc=".$pw."
\n";
return check_crypt($p, $pw);
}
sub list_userpass{
local($pf) = @_;
open(FHPF, "$pf") || return (3,"Could not open file: $pf");
local(@pwf) = ;
close(FHPF);
print join("
",@pwf)."
\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
\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
\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;