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: [email protected] 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.