Directory Access Configuration
If you decide to allow per-directory configuration files, you'll need to enable them in the global access.conf file with a good deal of consideration and care. Assuming you have a <Directory> entry for the DocumentRoot, you can enable certain capabilities for individual directories beneath the DocumentRoot on an as-needed basis.
Let's suppose, for the purpose of demonstration, that your archive consists of the DocumentRoot:
/usr/local/etc/httpd/htdocs
And beneath DocumentRoot, you have a subdirectory:
/usr/local/etc/httpd/htdocs/test1
Now assume that there exists, for DocumentRoot, an entry in the access.conf file that looks something like this:
<Directory /usr/local/etc/httpd/htdocs> AuthType Basic AuthName PasswordAdmin AuthUserFile /usr/local/etc/httpd/conf/.htpasswd AccessFileName .myhtaccess AddType text/html .shtml Options Indexes SymLinksIfOwnerMatch IncludesNOEXEC AllowOverride AuthConfig FileInfo Indexes Limit </Directory>
This entry allows any directory beneath DocumentRoot to have its own .privaccess files, which can then override any of the directives specified for DocumentRoot except the Options directive, which we don't want to let anyone specify beyond what is already allowed. Note that the Options directive is already used to turn on the automatic directory indexes (when index.html doesn't exist) and to follow symlinks if the owner of the symlink and what it points to match, as well as allowing server-side includes, but not the #exec and #include directives within server-side includes files.
Now, assume that the directory test1 has some proprietary or confidential information within it. You could assure that nothing is left to chance by configuring its directory entry in the global access.conf to disallow any overrides or options, like this:
<Directory /usr/local/etc/httpd/htdocs/test1> AllowOverride None Options None <Limit GET POST> require valid-user </Limit> </Directory>
Note that we also specify here that any access to this directory also be validated from the valid users in the AuthUserFile, inherited from the directives for DocumentRoot. We'll look more at user/group authentication in a bit.
You can use Perl and the HTTPD modules to verify that your access configurations for any given file in the archive are what you expect them to be. Here we'll modify our previous script to give us some additional information on the configuration directives for each directory specified in access.conf:
use HTTPD::Config;
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";
}
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";
}
}
}
Note that we added a few lines to the foreach loop, which loops over the <Directory> entries in access.conf, to tell us about any <Limit> directives and how they're configured. Now when we run the script against our existing hierarchy, we get the following output:
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
AddType : text/html .shtml
Options : Indexes SymLinksIfOwnerMatch IncludesNOEXEC
AllowOverride : AuthConfig FileInfo Indexes Limit
Limit:
The <Limit> options for the test1 directory are now specified.