Apache Location directive for dynamic content fails if nested path - apache

I'm using Apache 2.2x. Most of the content is generated via mod_perl. So, it's dynamic content that has no filesystem mapping. Perfect use of < Location >.
Apache config:
<Location /finance_module1>
SetHandler perl-script
PerlResponseHandler Finance::Module1
</Location>
<Location /finance/module2>
SetHandler perl-script
PerlResponseHandler Finance::Module2
</Location>
Module1 works, and is shown here to show that my setup otherwise works.
Module2 does not work. Apache says "File does not exist: /home/joe/www/htdocs/finance". The only difference between the module configurations is that Module2 location contains multiple slashes (what I'm calling a nested path).
About the "File does not exist" error: Of course it doesn't exist -- it's a Location, not a File or Directory. So why does this happen?
I would like to be able to use paths with multiple slashes because I've got a lot of mod_perl modules, and it would be nice to categorize for purposes of control. For one trivial instance, robots.txt could simply say:
Disallow: /finance/
The Apache docs specifically state that < Location > directives need not map to the filesystem, and are well-suited for dynamically generated content.
What am I doing wrong? Is there a workaround? (Besides the obvious "just don't do that").
Thanks.

Answering my own question, for the benefit of anyone else wondering the same thing.
Short answer, use LocationMatch.
In the example above, say the urls are /finance/module1 and /finance/module2. Having the "finance/" path allows all the finance handlers to be configured as a group, in situations where that's desirable.
For example:
<LocationMatch /finance/.*>
SetHandler perl-script
PerlAccessHandler foo
</LocationMatch>
<Location /finance/module1>
SetHandler perl-script
PerlResponseHandler Finance::Module1
</Location>
<Location /finance/module2>
SetHandler perl-script
PerlResponseHandler Finance::Module2
</Location>

Slight typo perhaps?
<Location /finance_module1>
vs.
<Location /finance/module2>
Not sure if that is the issue.
Perhaps this (add to httpd.conf)
Alias /finance "path-to-files"
<Directory "path-to-files">
Options +Indexes
AllowOverride All
Order allow,deny
Allow from all
</Directory>
Then try the script. You could also make an empty folder there perhaps?

Related

Acces Control only works inside <Location> directive, Apache/2.4.6 (CentOS)

There's a server with several instances of Apache running. One instance needs access from anywhere, but only for authorized users. Instance is started up by a systemctl script with the -f option pointing to a config file in /opt/.
Config includes directives from another file in the same folder under /opt/. The relevant part of the included directives looks like the following at the present moment:
"
[...]
<Location "/subfolder">
<RequireAll>
Require all granted
Require valid-user
</RequireAll>
LimitRequestBody <someNumber>
</Location>
[...]
DavLockDB /somepath/webdav/DavLock
Alias /subfolder /mainfolder/subfolder
<Directory /mainfolder/subfolder>
Dav on
AuthType Basic
AuthName "Restricted Files"
AuthUserFile /somepath/webdav/.htpasswd
<RequireAll>
Require all granted
Require valid-user
</RequireAll>
AllowOverride All
SSLRequireSSL
Options FollowSymLinks Indexes
</Directory>
[...]
"
This works so far, it only permits access to folder if you enter your username and password.
Problem is, if I comment out the <Location directive to comply with security recommendations, then access is flat-out denied. There is no way to enter a username and a password, and if I supply them on the command line, they are ignored, while they previously worked with the <Location block intact.
The <RequireAll> block inside the <Directory> directive is completely ineffectual. In fact, if I comment it out there, it changes nothing whatsoever in the behaviour of the httpd instance. It works only when it is placed inside the <Location block. The rest of the <Directory> block on the other hand seems to be working.
Does someone have any tips as to what I may be missing here? Thanks in advance!
H/T to Apache Basic Auth not working in .htaccess or Directory blocks; works fine in Location blocks
The problem was that the configuration file the Apache instance is started up with included one of the system-wide configs in /etc/ with a default location block inside, similar to the following:
<Location />
Require all denied
[...]
</Location>
When I commented out the line Require all denied from here, the access control directives in the <Directory> block started to work as expected.
The explanation of the above is that, unlike "normal" <Location> directives, which "operate completely outside the filesystem", <Location /> refers to the entire server (see the Apache documentation: https://httpd.apache.org/docs/2.4/mod/core.html#location ), so it means pretty much the same as <Directory /> (at least when it comes to its scope), except that it can only be overridden by another <Location> directive.

Apache 2.4 mod_geoip DENY?

This is my httpd.conf, as I followed step by step the readme file.
<IfModule geoip_module>
GeoIPEnable On
GeoIPEnableUTF8 On
GeoIPOutput Env
GeoIPScanProxyHeaders On
GeoIPDBFile GeoIP.dat
SetEnvIf GEOIP_COUNTRY_CODE CN BlockCountry
Deny from env=BlockCountry
</IfModule>
I get this when I start apache2.4
AH00526: Syntax error on line 560 of httpd.conf: deny not allowed here (Deny from env=BlockCountry)
What now? How do I deny access to the WHOLE server (not by vhosts/htaccess please)? Would be great if someday someone could write a proper readme/install procedure...
cheers.
The Deny directive is only valid in directory and htaccess context. It's not valid in server context.
Putting it into directory context is easy, though:
<Directory />
Deny from env=BlockCountry
</Directory>

Apache: <Directory> directive with no path specified

I have a local server environment running on my OS X machine using MAMP, and I am currently setting up a few virtual hosts. I found that, in order for one of my virtual hosts to recognize my site's .htaccess file, I needed to add a <Directory> directive within the <VirtualHost> directive.
Here is an example of what I am using to configure one of my virtual hosts:
<VirtualHost *>
DocumentRoot "/path/to/mysite"
ServerName mysite.local
<Directory "/path/to/mysite">
AllowOverride All
Order Allow,Deny
Allow from all
</Directory>
</VirtualHost>
Now, I would like to avoid redundancy by removing the path from that <Directory> directive. I tried doing so and it seems to work, although I am not familiar with Apache enough to know the potential consequences of doing this. Furthermore, I could not find an explanation of this case in the Apache Documentation.
This is what I would like to do:
<VirtualHost *>
DocumentRoot "/path/to/mysite"
ServerName mysite.local
<Directory>
AllowOverride All
Order Allow,Deny
Allow from all
</Directory>
</VirtualHost>
Therefore, my question is this: what happens when I omit the path from the <Directory> directive (in this case)?
Directory is a directive targeting a file system directory, and should always have a path (waildcards allowed).
Using some instructions targetd to no directory may be discarded silently, or maybe with an error (you could test it), but is would certainly be useless.
Why would you write some configuration instructions targeted to no directory at all?
But there's maybe more things in your question.
Ususally a Virtualhost should contains at least one Directory instruction, the DocumentRoot directory, and usually we also add one targeting the root of the filesystem, this way:
<Directory />
(instructions to deny access and avoid .htaccess reads)
</Directory>
<Directory /my/document/root/>
(instructions to allow access and still avoid .htaccess reads or to allow them if you are lazy and feel over confident that .htaccess are useful in any way and you do not need speed)
</Directory>
And you could add more, especially to avoid usage of .htaccess files as such file stored in /path/to/somewhere is the same thing as a <Directory /path/to/somewhere> section, but slower.
Now you do not like to repeat yourself in your VH configuration, so you coud maybe use .htaccess files or global level instructions for things that are usually set there. And you could also use another magical keyword, which is Location.
You can use a lot of Apache instruction in a <Location /foo> directive. Locations works on url, not on filesystem paths.
So <Location /> is your documentRoot, and <Location /foo> is maybe the subdirectory 'foo' under you DocumentRoot. This could help you write things in your VH without reusing the documentroot prefix everywhere. But be careful, urls are not file-system paths. Any protection applied on the url level may be weaker or stronger compared to a protection applied on a directory level. It depends on your alias, the way you use urls, etc.
Update:
If you use the new Apache 2.4 version you can now use mod_macro or even easier, built-in variables support:
Define docroot "/path/to/mysite"
DocumentRoot ${docroot}
<Directory ${docroot}>
(...)

How to allow access to only a single file?

I have a apache machine which is serving a .js file. That file should be the only file that need to seen.
I have configured to do so in my apache like this :
<Location /var/www/test/test.js>
Order allow,deny
Allow from all
</Location>
The site address is test.in which points to test.js file in /var/www/test directory. That is working fine. But I wish when the user tries to hit test.in/someurl (which is not available) or some other url than test.in need to give an message with 401 error.
How do I do that? Thanks in advance.
You misused <Location> - the argument should be URI not the directory path... You should use <Directory> to get the expected behavior.
I would do something like this (you should finetune it, it shows just the principle):
# first deny access to everything
<Location />
Order Deny,Allow
Deny from All
</Location>
# then allow access to specific URL
<Location /test/test.js>
Order Allow,Deny
Allow from All
</Location>
Have a look on Order directive and one or more of following: Location, LocationMatch, Directory, DirectoryMatch, Files, FilesMatch, etc.

using apache location directive to list folders from trac

I have the following directory structure:
--var
----trac
------company1
--------project1
--------project2
------company2
--------project3
--------project4
and i was wondering if theres a way to specify in httpd.conf to list the directories when i go to domain.com/trac. Currently i wrote:
<Location /trac>
Options Indexes
</Location>
But i dont know how to specify the document root to /var/trac.
I tried to do
PythonOption TracEnvParentDir "/var/trac"
PythonOption TracUriRoot "/trac
but i get error 500, and i believe that is because the folders in /var/trac are not trac environments.
thanks.
I think you're right. You need to find a way to let Apache handle requests to "/" without the help of Python and trac.
It's a bit hard to give you advice because I don't know what your httpd.conf looks right now, but my trac-setup used a <LocationMatch> directive to catch everything that should not be handled by trac so Apache can take care of it.
So you could do something like this:
<LocationMatch "^/trac/.+">
# Your trac directives here
PythonHandler trac.web.modpython_frontend
....
</Location>
Alias /trac "/var/trac"
<Directory "/var/trac">
Options Indexes
Order allow,deny
Allow from all
</Directory>