501 error with baikal / calDAV - apache

I found some calDAV / sabre / baikal related questions and answers here at stackoverflow, so this might be the appropriate place for my question.
I set up a baikal-flat server at my domain, hosted at one.com.
My .htaccess lives at /baikal and looks like this
# Allow HTTP headers with Apache/FastCGI
# See http://code.google.com/p/sabredav/wiki/Authentication#Apache_+_(Fast)CGI
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]
</IfModule>
<IfModule mod_expires.c>
ExpiresActive Off
</IfModule>
RewriteEngine On
RewriteCond %{HTTPS} !on
RewriteCond %{REQUEST_URI} baikal
RewriteRule ^(.*)$ https://www.<mydomain>.com/baikal/$1 [R,L]
Rewriting to ssl works now, I get https connections to baikal's web interface. Accessing it via korganizer, thunderbird and android fails - I tried any thinkable address combination. My first attempt was with
https://.com/baikal/cal.php/calendars//default/
I get a 501 error.
When I do
curl -so - --digest --user <username>:<password> https://<mydomain>.com/baikal/cal.php/calendars/<username>/default
for debugging, this is the result:
<?xml version="1.0" encoding="utf-8"?>
<d:error xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns">
<s:exception>Sabre\DAV\Exception\NotImplemented</s:exception>
<s:message>GET is only implemented on File objects</s:message>
<s:sabredav-version>1.8.7</s:sabredav-version>
</d:error>
I found google hits on that messages, but they seem to be iphone-related.
<username>, <mydomain> and <password>
is replaced by the real items without brackets in the real files. (-;
Could someone give me a hint?
Greetings,
Wolf

This error message is expected. GET requests don't work by default on collections.
Try a PROPFIND request if you want to see a real response coming back.

Related

httpd RewriteRule not working as expected

On my server I am running awstats, a script that I can currently access via the following URL:
https://stats.example.com/bin/awstats.pl/?config=global
I am trying to use rewrite rules such that I can just use
https://stats.example.com/global
This is what I have defined for a rewrite rule
RewriteRule ^(.*)$ bin/awstats.pl/?config=$1 [NC,L]
httpd virtual host
# Address
ServerName stats.example.com
# Rewrite
RewriteRule ^(.*)$ bin/awstats.pl/?config=$1 [NC,L]
Options ExecCGI
AddHandler cgi-script .cgi .pl
Alias /awstatsstuff "/path/to/awstatsstuff/"
<Directory "/path/to/awstatsstuff">
Options ExecCGI
AllowOverride None
Order allow,deny
Allow from all
</Directory>
The problem is that anything I try and access (besides the index), will give me a 400, and my apache logs show no errors.
Should this rule be working correctly, do I have a different configuration issue? Or am I missing something? Yes, RewriteEngine is on.
edit
Based on Michael Berkowski's comment I determined that is is infact an issue with resources also being directed to the pl script, I have since modified and am using the following:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^/([0-9a-z]+\.[0-9a-z]+\.[0-9a-z]+)$ bin/awstats.pl/?config=$1 [NC,L]
I can now load the page again using
https://stats.example.com/bin/awstats.pl/?config=www.example.com
This means that all resources can be loaded correctly, however
https://stats.example.com/www.exmaple.com
will return a 400 ( this does not come from the pl script which will return a 200 and error message if the specified config file can not be found, again, no error messages in the logs.
another edit
In changing [NC,L] to [R=302], I am provided with the correct redirect upon request,
curl -k "https://stats.example.com/a.b.c"
...
<p>The document has moved here.</p>
...
Using [R=403] proves that the rewrite rule is working as expected
The problem that I am now facing is that when using [NC,L], I am still receiving a 400, with no errors available in the httpd log.
I strongly suspect requests for documents other than the index are being mistakenly trapped by the very permissive (.*) and sent to config= in error. The 400 (bad request) probably then results from awstats tripping over values it cannot handle there.
Two things should take place. First, you need to exclude real existing files and directories from the rewrite, conventionally done with a pair of RewriteCond. Then, instead of the very general (.*) matcher, use a matcher more specific to the values that should actually be considered valid for config=.
# If the requested document is not a known
# file or directory on disk...
RewriteCond %{REQUEST_FILENAME} !=f
RewriteCond %{REQUEST_FILENAME} !=d
# Rewrite patterns matching only the expected
# config= values for awstats
RewriteRule ^([a-z0-9]+\.[a-z0-9]+\.[a-z0-9]+)$ bin/awstats.pl?config=$1 [L,NC]
Above I have used [a-z0-9]+\. to match 3 part FQDN strings as mentioned in the comment thread. That may need additional refinement. To also support the string "global" for example, you could expand it to
RewriteRule ^(global|[a-z0-9]+\.[a-z0-9]+\.[a-z0-9]+)$ bin/awstats.pl?config=$1 [L,NC]

Can't force 'https' and reverse proxy with Apache at the same time

Really racking my brain over this one. I need to always force 'https' whenever a user requests 'http' on my site, but at the same time I need to proxy pass from Apache to Tomcat (over http). I can't get these two pieces to work in tandem.
I have the https redirect defined here in httpd.conf:
<VirtualHost *:80> ServerName myserver.foo.com
Redirect / https://myserver.foo.com/
</VirtualHost>
Then for the proxy:
RewriteEngine on
RewriteLog /opt/HTTPServer/logs/rewrite_log
RewriteLogLevel 9
RewriteRule ^/testnew/MyApp(.*)$ http://localhost:8080/test/MyApp$1?product=new [NC,P,QSA]
RewriteRule ^/testold/MyApp(.*)$ http://localhost:8080/test/MyApp$1?product=old [NC,P,QSA]
Note: This does actually work if I use ProxyPass instead, but I need to be able to add additional GET parameters to the request, hence the use of the [P] flag approach here.
So when I hit the following URL, I get the Apache HTTP Server page which reads "Not Found".
http://myserver.foo.com/testnew/MyApp/RunReport
In the access log, there's a 404
[10/Nov/2014:01:45:21 -0600] "GET /testnew/MyApp/RunReport HTTP/1.1" 404 321
Also, nothing gets written to the rewrite log.
As I understand it, RewriteRules will execute BEFORE Redirect, so even if the above URL did work (and I don't understand why it doesn't), it wouldn't get redirected from http to https. So how can I accomplish this?
I also tried this using only RewriteRules:
RewriteEngine on
RewriteCond %{HTTPS} !on
RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R=301]
RewriteRule ^/testnew/MyApp(.*)$ http://localhost:8080/test/MyApp$1?product=new [NC,P,QSA]
RewriteRule ^/testold/MyApp(.*)$ http://localhost:8080/test/MyApp$1?product=old [NC,P,QSA]
However with this, the URL gets translated to include the https scheme and hostname after the 1st redirect, so the subsequent RewriteRules fail to match. If I add the full 'https://myserver.foo.com' to the RewriteRule, it matches, but then the full URL gets translated back to http via the proxy.
I can't win! This seems to me like it would be a fairly common configuration. Did I completely miss something? I've been looking at this too long.
I was able to get this to work by moving the proxy RewriteRules under the *:443 VirtualHost and leaving the http -> https ones at the global level, i.e.
Listen 443
<VirtualHost *:443>
SSLEnable
SSLClientAuth None
RewriteEngine On
RewriteLog /opt/HTTPServer/logs/rewrite_log-443
RewriteLogLevel 9
RewriteRule ^/testnew/MyApp(.*)$ http://localhost:8080/test/MyApp$1?product=new [NC,P,QSA]
</VirtualHost>
...
...
RewriteEngine on
RewriteCond %{HTTPS} !on
RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R=301]
Works beautifully now. :)

Prevent Apache from answering invalid requests

I have an Apache web-server that acts as a web front-end for iPhone and iPad applications that communicate by POST and JSON only.
Is there any way to prevent Apache from answering requests that are invalid? I can see my error log is filled with attempts to open files such as /admin.php /index.php etc - files that don't exist on my server.
I believe this is possible with IIS, but can you do the same thing with Apache?
Basically I want the request to appear timed out unless you post exactly the right content to the right file - or at least if you do not request an existing file. This would make the server appear non-existing to everyone but my iPhone users as all communication is SSL and directories are not really guess-able.
I did disable the ServerTokens and all that, but I still get File not found etc. when I access the server requesting a random file, which is what these bots do constantly.
You can limit what HTTP methods Apache responds to by using mod_rewrite to redirect or deny unwanted requests.
Note that JSON is not an HTTP method. GET, POST, PROPFIND etc are HTTP method. For a full list of HTTP methods please see: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
If your application truly does not need to honor GET requests, then you can block all other methods.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_METHOD} !^(POST) [NC]
RewriteRule ^(.*)$ - [F,L]
</IfModule>
I've not tested this but it should block anything other than a POST method. You can add multiple methods.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_METHOD} !^(POST|GET) [NC]
RewriteRule ^(.*)$ - [F,L]
</IfModule>
Would permit only POST and GET.
You may need to also specify 'Options FollowSymLinks` on some servers due to how rewrites are handled.
If you must permit GET requests, then you will see those not found errors. There is nothing that prevents someone from issuing a HTTP request for an object that does not exist.

Problem with forcing SSL using .htaccess

I have the following .htaccess file:
Order deny,allow
Deny from all
Allow from XX.XXX.XXX.XXX
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php
RewriteCond %{HTTPS} !=on
RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI} [R,L]
Which is supposed to:
Only allow access from my IP (numbers changed to Xs to protect the innocent)
Send any request which is not a specific file through to /index.php
Force https for the entire domain
As far as I can see, it's identical to a previous project, which was admittedly on a different hosting provider, but that worked like a charm. This time it's resulting in a message saying "Firefox has detected that the server is redirecting the request for this address in a way that will never complete.".
Anybody know what's going on & what I need to change please?
Perhaps your new hosting provider is using some sort of setup (like a reverse proxy) that's preventing the HTTPS variable from being set. You may be able to use something else (like SERVER_PORT, or perhaps a header set by the remote proxy, assuming there is one) to determine if the request is HTTPS or HTTP.

How can I rewrite all but my IP address to the std. Apache 503 temporarily down error message?

I'm about to do some server maintenance and would like to rewrite requests to Apache's standard 503 temporarily unavailable message.
I've Googled and found a few mod_rewrite snippets, but they all involve doing an [R=503] to a PHP script which then sends its own 503 headers and a hand-written message... which just seems ugly to me, when Apache's default is there for me to use.
So, how can I rewrite all request to Apache's standard 503 error message?
Thanks for your help
(Long time Coding Horror RSS subscriber here... Just in a bit of a rush!)
To add a little bit more, I often have the following:
RewriteEngine on
RewriteCond -f path/to/my-custom-error-document
RewriteRule !^path/to/my-custom-error-document$ - [L,R=503]
What this does is check to see if the error document exists. If it does, it serves up the error page. What this allows me to do is throw up the custom error without having to restart apache. To put it back in place, I just remove (or rename) the error page.
I don’t know exactly since when mod_rewrite allows other status codes than 3xx for the R flag. But this should do it:
RewriteEngine on
RewriteRule ^ - [L,R=503]
And if you’ve set a custom error document, use this to prevent additional internal errors:
RewriteEngine on
RewriteRule !^path/to/my-custom-error-document$ - [L,R=503]
Edit   Found a better solution using the REDIRECT_STATUS environment variable:
RewriteEngine on
RewriteCond %{ENV:REDIRECT_STATUS} !=503
RewriteRule ^ - [L,R=503]
Thanks guys - worked perfectly.
Here's the exact .htaccess configuration I used (sans my IP address) during maintenance:
RewriteEngine on
RewriteCond %{REMOTE_HOST} !^123\.456\.789\.012$
RewriteCond %{ENV:REDIRECT_STATUS} !=503
RewriteRule ^ - [L,R=503]