#!/usr/bin/perl
#
# $Id: htpasswd.pl,v 1.1 2004/03/28 23:17:30 ueli Exp $
#
# (c) 2003 by ueli@heuer.org
#
#
use lib "/home/default/includes";
use CGI qw/:standard/;
use CGI::Pretty qw( :html4 );
use Crypt::Cracklib;
use DBI;
require "htpasswd.inc";
# DB-username/passwort dieser user MUSS schreibrechte haben
# htpasswd.inc defines $dbsource, $dbuser and $dbpassword
# $dbsource should be a DBI-Resource
# --- htpasswd.inc ---
# as an Example you may use following:
#$dbuser='htadmin';
#$dbhost='localhost';
#$dbpassword='geheim';
#$dbname='htpasswd';
#$dbsource = "DBI:mysql:database=$dbname;host=$dbhost:";
#1;
# --- eof htpasswd.inc ---
# wo liegt die server config (ohne $includes !!!)
$SERVER_CONF='/etc/httpd2/httpd.conf';
$CRACKLIB = '/var/cache/cracklib/cracklib_dict';
$server_ip=$ENV{'SERVER_ADDR'};
if ($server_ip =~ /:/) {
$server_ip = "[$server_ip]";
}
$db = DBI->connect( $dbsource, $dbuser, $dbpassword) || do { print header(-Location=>"http://$server_ip/htpasswd/nodb.php"); exit(0); };
# fetch some global values
($server,$domain)=get_servername(server_name());
$master_user = remote_user();
$script = script_name();
$user=param('user');
$password=param('password');
$host_group=get_host_group();
if ( $master_user eq '' ) {
print header,h1("zu dumm, das geht einfach nicht ohne username und passwort");
exit(0);
}
# prepare some queries ...
#
$check_member_h = $db->prepare("select user_name from user_group where user_name = ? and user_group = ? and host_group = ?");
$user_h = $db->prepare("select user_name,isadmin from user_info where host_group = ? order by isadmin desc,user_name");
$is_master_h = $db->prepare("select isadmin from user_info,host_info where user_info.host_group=host_info.host_group and host=? AND user_name = ?");
$get_password_h = $db->prepare("select user_passwd from user_info,host_info where user_info.host_group=host_info.host_group and host=? AND user_name = ?");
$check_user_h = $db->prepare ("select user_name from user_info where user_name = ? and host_group = ?");
$|=1;
# do ddatabase jobs bevor any header is sent ...
if (param) {
$doit = param('doit');
$salt = sprintf("%c%c",int(rand(95))+33,int(rand(95))+33);
if ($doit eq 'saveuser') {
$old_passwd = get_password($user);
if ( is_admin($master_user) ) {
if ( param('delete') == 1 ) {
# delete user from user and group table
if ( $user ne $master_user ) {
# delete only "other" users, NOT myself!
$delete_user_h = $db->prepare ("delete from user_info where user_name = ? and host_group = ?");
$delete_group_member_h = $db->prepare ("delete from user_group where user_name = ? and host_group = ?");
$delete_user_h->execute($user,$host_group);
$delete_group_member_h->execute($user,$host_group);
print header(-Location=>"$script?action=deleted&user=$user");
exit (0);
} else {
$error{'user'} = "I do not like suicid :(
I do not delete myself!";
}
} else {
$passwd_ok = 1==0;
$admin = param('admin')+0;
if ( $password eq "" ) {
$passwd = $old_passwd;
$passwd_ok = 1==1;
} else {
if (check($password,$CRACKLIB)) {
$passwd=crypt($password,$salt);
$passwd_ok = 1==1;
}
}
if ( $passwd_ok ) {
$update_adminuser_h = $db->prepare("update user_info set user_passwd = ?,isadmin=? where user_name = ? and host_group = ?");
$update_adminuser_h->execute($passwd ,$admin ,$user,$host_group);
print header(-Location=>"$script?action=saved&user=$user");
exit (0);
} else {
$error{'user'} = "Bad Password (e.g. password was too easy to guess)";
}
}
} else {
if (param('password') eq param('password1')) {
if ( check($password,$CRACKLIB)) {
$passwd=crypt($password,$salt);
$update_user_h = $db->prepare("update user_info set user_passwd = ? where user_name = ? and host_group = ?");
$update_user_h->execute($passwd,$user,$host_group);
print header(-Location=>"$script?action=saved&user=$user");
exit (0);
} else {
$error{'user'} = "Bad Password (e.g. password was too easy to guess)";
}
} else {
$error{'user'} = "Password missmatch";
}
}
} elsif ($doit eq 'adduser') {
if (!user_exists($user)) {
# be sure, the username is something usefull
if ( $user =~ /[a-z0-9\-_]+/i ) {
if ( check($password,$CRACKLIB)) {
$passwd = crypt($password,$salt);
$isadmin = (param('isadmin')==1)+0;
$add_user_h = $db->prepare ("insert into user_info(user_name,user_passwd,isadmin,host_group,changed,created) values (?,?,?,?,now(),now())");
$add_user_h->execute($user,$passwd,$isadmin,$host_group);
print header(-Location=>"$script?action=added&user=$user");
exit(0);
} else {
$error{'user'} = "Bad Password (e.g. password was too easy to guess)";
}
} else {
$error{'user'} = "Bad username";
}
} else {
$error{'adduser'} = "User \"$user\" exists";
}
} elsif ( $doit eq 'savegroup') {
$delete_group_h = $db->prepare("delete from user_group where user_group = ? and host_group = ?");
$insert_group_h = $db->prepare("insert into user_group(user_name,user_group,host_group,changed,created) values (?,?,?,now(),now())");
$group = param('group');
@member = param('member');
$db->do('begin');
$db->do('lock tables user_group write');
$delete_group_h->execute($group,$host_group);
for ($i=0;$i<=$#member;$i++) {
$insert_group_h->execute($member[$i],$group,$host_group);
}
$db->do('unlock tables');
$db->do('commit');
print header(-Location=>"$script?action=grouplist");
exit(0);
} elsif ( $doit eq 'addgroup') {
$insert_group_h = $db->prepare("insert into user_group(user_name,user_group,host_group,changed,created) values (?,?,?,now(),now())");
$group = param('group');
@member = param('member');
if ( $group =~ /[a-z0-9\-_]+/i ) {
if ( ! group_exist($group)) {
for ($i=0;$i<=$#member;$i++) {
$insert_group_h->execute($member[$i],$group,$host_group);
}
print header(-Location=>"$script?action=grouplist");
exit(0);
} else {
$error{'addgroup'} = "Group \"$group\" exists";
}
} else {
$error{'addgroup'} = "Group \"$group\" is not allowed (wrong name)";
}
}
}
print header;
print start_html(-title=>"Manage htpasswd entries for the site http://$server/", -style=>{-src=>"http://$server_ip/htpasswd/styles/htpasswd.css"});
print h3("Manage htpasswd entries for the site http://$server/");
print p,"You're logged in as user \"$master_user\"."; # [ ",a({-href=>"http://$server$script?logout=true&bye=$master_user"},"logout"),"]";
if (param) {
@action = param('action');
if (defined (@action)) {
for ($i=0;$i<=$#action;$i++) {
if ($action[$i] eq 'list' ) {
print p,b("List user");
if ( is_admin($master_user) ) {
$user_h->execute($host_group);
#print p,$user_h->rows," found";
while (($user,$isadmin) = $user_h->fetchrow) {
print br;
if ($isadmin > 0 ) {
print img{src=>"http://$server_ip/htpasswd/star.gif",alt=>"admin"};
} else {
print img{src=>"http://$server_ip/htpasswd/empty.gif",alt=>""};
}
print " ",link_user($user);
}
} else {
print br,b("Sorry, but only administrators can see all users");
}
}
if ($action[$i] eq 'add' ) {
print p,b("Add user");
if ( is_admin($master_user) ) {
print start_form(-method=>"post",-action=>"$script");
if ($error{'adduser'}) { print span({-class=>'error'},$error{'adduser'}),p; }
print input({-type=>'hidden',-name=>'action',-value=>'add'}),
input({-type=>'hidden',-name=>'doit',-value=>'adduser'}),
"new username",br,input({-name=>'user',-type=>'text',-size=>30,-maxlength=>30,-value=>$user}),
br,"password",br,input({-name=>'password',-type=>'text',-size=>12,-maxlength=>12}),
br,checkbox(-name=>'admin',-checked=>0,-value=>1,-label=>"user is an administrator"),
p,submit({-class=>'center',-value=>'add user now'}),end_form;
if ( $error{'adduser'} ) { $user = undef; }
} else {
print br,b("Sorry, but only administrators can add users");
}
}
if ($action[$i] eq 'grouplist' ) {
print p,b("List groups");
if ( is_admin($master_user) ) {
$group_h = $db->prepare("select user_group,user_name from user_group,host_info where user_group.host_group=host_info.host_group and host=? order by user_group,user_name");
$group_h->execute($server);
$old_group="";
while (($group,$user) = $group_h->fetchrow) {
if ($old_group ne $group) {
print br,a({href=>"$script?group=$group"},$group),b("» "), link_user($user);
$old_group=$group;
} else {
print ", ",link_user($user);
}
}
} else {
print br,b("Sorry, but only administrators can see all groups");
}
}
if ($action[$i] eq 'groupadd' ) {
if ( is_admin($master_user) ) {
print p,b("Add a new group");
$user_h->execute($host_group);
$k=0;
@user_list=undef;
while ( ($user,$isadmin) = $user_h->fetchrow) {
if ( $user ne "" ) {
$user_list[$k++] = $user;
}
}
print start_form(-method=>"post",-action=>"$script"),
input({-type=>'hidden',-name=>'doit',-value=>'savegroup'}),
b("Groupname:"),br,
input({-type=>'text',-name=>'group',-value=>"$group"}),
p,scrolling_list({-name=>'member',-values=>\@user_list, -default=>'',-multiple=>true}),
p,submit({-class=>'center',-value=>'change now'}),end_form;
} else {
print p,b("Sorry, but only administrators can add groups");
}
}
if ($action[$i] eq 'saved' ) {
print p,b,"Modify user \"$user\"",
p,"Settings of user ",link_user($user)," are changed";
$user=undef;
}
if ($action[$i] eq 'added' ) {
print p,b,"Add user \"$user\"",
p,"User ",link_user($user)," added";
$user=undef;
}
if ($action[$i] eq 'deleted' ) {
print p,b,"Delete user \"$user\"",
p,"User $user deleted.";
$user=undef;
}
}
}
if ( $user ne "" ) {
print p,b("Modify user \"$user\"");
if ( $error{'user'} ) { print p,span({-class=>'error'},$error{'user'}),p; }
if ( $user eq $master_user || is_admin($master_user) ) {
print start_form(-method=>"post",-action=>"$script"),
input({-type=>'hidden',-name=>'user',-value=>"$user"}),
input({-type=>'hidden',-name=>'doit',-value=>"saveuser"});
if (is_admin($master_user)) {
print b($user),"\'s new password:",br,input({-name=>'password',-type=>'text',-size=>12,-maxlength=>12}),
br,checkbox(-name=>'admin',-checked=>is_admin($user),-value=>1,-label=>"user is an administrator");
if ( $user ne $domain && $user ne $master_user ) { # don't delet master user!
print br,checkbox(-name=>'delete',-checked=>0,-value=>1,-label=>"Delete user");
} else {
print br, sprintf ("I'll not delete %s", $user eq $domain ? "the master user" : "myself");
}
} else {
print "Please type your new password:",br,input({-name=>'password',-type=>'password',-size=>12,-maxlength=>12});
print br,"Please type your new password again:",br,input({-name=>'password1',-type=>'password',-size=>12,-maxlength=>12});
}
print p,submit({-class=>'center',-value=>'change now'}),end_form;
} else {
print br,b("Sorry, but only administrators can change other users");
}
}
$group=param('group');
if ( $group ne "" ) {
print p,b("Modify group \"$group\"");
if ( $user eq $master_user || is_admin($master_user) ) {
print p,"Please select the members of the group",br,"if there are no members, the group will be deleted.";
$user_h->execute($host_group);
$j=0;
while ( ($user,$isadmin) = $user_h->fetchrow) {
$user_list[$k++] = $user;
if (user_member($user,$group)) {
$user_sel[$j++] = $user;
}
}
print start_form(-method=>"post",-action=>"$script"),
input({-type=>'hidden',-name=>'group',-value=>"$group"}),
input({-type=>'hidden',-name=>'doit',-value=>'savegroup'}),
p,scrolling_list({-name=>'member',-values=>\@user_list, -default=>\@user_sel,-multiple=>true}),
p,submit({-class=>'center',-value=>'change now'}),end_form;
} else {
print br,b("Sorry, but only administrators can change group members");
}
}
} else {
$label{'list'} = 'list all user';
$label{'add'} = 'add a user';
$label{'grouplist'} = 'list all groups';
$label{'groupadd'} = 'add a group';
print p,b("Do following:"), br;
# print list, group, add only if you are an administrator
if (is_admin($master_user) ) {
print start_form,
checkbox_group(-name=>'action',
-values=>['list','add','grouplist','groupadd'],
-defaults=>['list'],
-linebreak=>'true',
-labels=>\%label),
p,
submit('Do it now'),
end_form;
} else {
print a({href=>"$script?user=$master_user"},"change password");
}
}
print hr({-width=>400,-align=>'left',-size=>1,-noshade}),
"[ ",a({-href=>'/'},$server),"] ",
"[ ",a({href=>$script},"Manage htpasswd"),"]",
hr({-width=>400,-align=>'left',-size=>1,-noshade}),
span({-class=>'copy'},"© 2003 by ueli(at)heuer.org");
print end_html;
# check if $user is a domainadmin or not
# return true if $user is an admin
sub is_admin {
local ($user,$dummy) = @_;
$is_master_h->execute($server,$user);
($is_admin) = $is_master_h->fetchrow;
return ($is_admin == 1);
}
sub get_host_group {
$get_host_group_h = $db->prepare("select host_group from host_info where host = ?");
$get_host_group_h->execute($server);
($host_group) = $get_host_group_h->fetchrow;
return $host_group;
}
sub get_password {
local ($user,$dummy) = @_;
$get_password_h->execute($server,$user);
($crypt_pw) = $get_password_h->fetchrow;
return $crypt_pw;
}
sub link_user {
local ($user,$dummy) = @_;
if ( user_exists($user)) {
return a({href=>"$script?user=$user"},$user);
} else {
return span({-class=>'error',-title=>"User does not exists"},$user);
}
}
sub user_member {
local ($user,$group,@dummy) = @_;
$check_member_h->execute ($user,$group,$host_group);
return ($check_member_h->rows > 0);
}
sub user_exists {
local ($user,$dummy) = @_;
$check_user_h->execute($user,$host_group);
return ($check_user_h->rows > 0);
}
sub get_servername {
# da apache2 server_name falsch (?) zurückliefert, bleibt nur der weg via configdatei
# eventuell sieht das dann mit mod_perl etwas anderst aus ...
local ($ser,$dummy) = @_;
open CONF, "< $SERVER_CONF";
while () {
next if /\s*#/;
next if (! /;
next if /\s*#/;
if (/ServerName\s+([\w\.\-]*)\s*/i ) {
$hostname = $1;
$hostname =~ /^([a-z0-9\-]*)\.([a-z0-9\-]*\.[a-z]{2,4})$/;
$host = $1;
$domain = $2;
}
if (/ServerAlias/i ) {
if (/\s+$ser\s*/i ) {
$found = 1==1;
}
}
}
if (( $hostname =~ /$ser/i ) || $found ) {
close CONF;
return ($hostname,$domain);
}
}
close CONF;
return (undef,undef);
}