Monitoring Userids
As a final note in this section, we'll add a bit more code to our ongoing example to keep track of userids in the .htpasswd file for each <Directory> entry in access.conf.
use HTTPD::Config;
require HTTPD::UserAdmin;
require "stat.pl";
$conf = `/usr/local/etc/httpd/conf';
@files = qw(httpd.conf srm.conf access.conf);
$V= new HTTPD::Config (SERVER => Apache,
SERVER_ROOT => $conf,
FILES => [@files]);
print "Userid: ", $V->user,"\n";
print "Group: ", $V->group,"\n";
print "Administrator is: ", $V->server_admin,"\n";
print "Running at port: ", $V->port,"\n";
print "Access filename: ",$V->access_file_name,"\n";
print "User Directory: ", $V->user_dir,"\n";
print "Global Types:\t", join("\n\t\t",$V->add_type),"\n";
print "\n\n";
foreach $dir (keys %{$V->{`Directory'}}){
print "Options for Directory: $dir\n";
while(($opt,$val) = each %{$V->{`Directory'}{$dir}{`OPTIONS'}}){
print "\t",$opt, " : ", @{$val},"\n";
if($opt eq "AuthUserFile"){
($path = join(`',@{$val})) =~ s/^(.*)\/.*/$1/;
print "\tCurrent users in $opt:\n";
$users = new HTTPD::UserAdmin(DBType => "Text",
Path => $path, Locking => 0, Server => "apache");
#@users = $users->list;
foreach $user (sort($users->list)){
print "\t\t$user : ";
print $users->password($user),"\n";
}
}
}
print "\tLimit: @{$V->{Directory}{$dir}{LIMIT}{METHODS}}\n";
while(($key,$val) = each %{$V->{Directory}{$dir}{LIMIT}{OPTIONS}}) {
print "\t\t$key = @{$val}\n";
}
print "\n";
}
# rudimentary permissions checking
$webuser = (getpwnam($V->user))[2];
opendir(ROOT,$V->server_root);
@files = grep(!/\.\.?/,readdir(ROOT));
closedir(ROOT);
foreach $f (@files){
@s = Stat($V->server_root."/$f");
if($s[$ST_UID] == $webuser){
print "Warning: ",$V->server_root,"/$f is owned by ",
$V->user,"\n\n";
}
if($f eq "httpd"){
if(($s[$ST_MODE] != 0100700) or ($s[$ST_UID] != 0)){
print "\tWarning: ",$V->server_root,"/httpd may have\n";
print "\tpermission problems. Recommend root ownership\n";
print "\tand readable, writable and executable only by\n";
print "\troot user\n";
}
}
}
We get a fairly nice report back that looks like this:
Userid: nobody
Group: nogroup
Administrator is: wmiddlet@adobe.com
Running at port: 80
Access filename: .privaccess
User Directory: public_html
Global Types: text/html .shtml
Options for Directory: /usr/local/etc/httpd/cgi-bin
Options : None
AllowOverride : None
Limit:
Options for Directory: /usr/local/etc/httpd/htdocs/test1
Options : None
AllowOverride : None
Limit: GET POST
require = valid-user
Options for Directory: /usr/local/etc/httpd/htdocs
PerlHandler : main::handler
AuthUserFile : /usr/local/etc/httpd/conf/.htpasswd
Current users in AuthUserFile:
bmiddlet : ztTO6y2K.3qLE
bozo : 0Euk1WMWyXRgg
josie : _LhTDVY/y6tPo
AddType : text/html .shtml
AuthName : PasswordAdmin
Options : Indexes SymLinksIfOwnerMatch IncludesNOEXEC
AuthType : Basic
AllowOverride : AuthConfig FileInfo Indexes Limit
Limit: GET
deny = from .bozo.com
order = mutual-failure
allow = from .metronet.com
Of course, if your user database gets very large, then this script may produce more output than you want to see. The idea from the beginning has been that this script would run automatically via cron, having its output compared to the expected output, possibly from the day before, then sending on only the differences for your inspection.