NTLM Authentication on Apache 2.4 with mod_authnz_sspi
I'm having a hard time getting to a file on one Apache webserver from another webserver. Or even from the same web server.
Let me first give you descriptions of the two servers involved.
Server 1:
Windows Server 2003
Apache 2.2 32bit
PHP 5.2.10
Server 2:
Windows Server 2012 R2 Standard
Apache 2.4 64bit
PHP 5.6.5
To read a remote Windows user (for Single Sign-on), I am using the mod_auth_sspi module on an older server. Unfortunately this module is no longer supported in Apache 2.4 so I switched to mod_authnz_sspi. Reading the username works fine, but if I run the PHP script on the old server to connect to the new server and read the file there, the script gets rejected with HTTP 401 (unauthorized). When I ran the same script on the new server to try and read the same file on the old server, it works great (I hope this doesn't seem confusing. English is also not my first language as you might have learned).
I used get_headers () function to access the file, the simplified script looks like this:
<?php
print_r(get_headers("http://server1/test.txt", 1));
print_r(get_headers("http://server2/test.txt", 1));
?>
test.txt is an empty file on both servers. So the script first tries to read the file on one server and then the other. The result looks the same on both servers. Both can connect to the first server:
[0] => HTTP/1.1 200 OK
[Date] => Mon, 01 Jun 2015 13:18:56 GMT
[Server] => Apache/2.2.11 (Win32) mod_auth_sspi/1.0.4 PHP/5.2.10
[Last-Modified] => Mon, 01 Jun 2015 13:12:58 GMT
[Accept-Ranges] => bytes
[Content-Length] => 0
[Connection] => close
[Content-Type] => text/plain
But no one is second:
[0] => HTTP/1.1 401 Unauthorized
[Date] => Mon, 01 Jun 2015 13:18:56 GMT
[Server] => Apache/2.4.12 (Win64) mod_authnz_sspi/0.1.0 PHP/5.6.5
[WWW-Authenticate] => Array
(
[0] => NTLM
[1] => Basic realm="mycompany_proxy.loc"
)
[Content-Length] => 381
[Connection] => close
[Content-Type] => text/html; charset=iso-8859-1
I looked at the Apache access.log on two servers. As for test.txt, the old one shows no problems:
[IP address server1] - - [01/Jun/2015:15:22:00 +0200] "GET /test.txt HTTP/1.0" 200 -
[IP address server2] - - [01/Jun/2015:15:18:56 +0200] "GET /test.txt HTTP/1.0" 200 -
New on the other hand:
[IP address server1] - - [01/Jun/2015:15:22:00 +0200] "GET /test.txt HTTP/1.0" 401 381 "-" "-"
::1 - - [01/Jun/2015:15:18:56 +0200] "GET /test.txt HTTP/1.0" 401 381 "-" "-"
So, neither the old server (server1) nor the new one (via localhost) can access the file.
If I access test.txt from a new server through a browser on my local machine (which works great by the way), the following entries can be found in the log file:
[Local IP address] - - [01/Jun/2015:15:47:20 +0200] "GET /test.txt HTTP/1.1" 401 381
[Local IP address] - - [01/Jun/2015:15:47:20 +0200] "GET /test.txt HTTP/1.1" 401 381
[Local IP address] - cdietzel [01/Jun/2015:15:47:20 +0200] "GET /test.txt HTTP/1.1" 200 -
mod_authnz_sspi is the last module loaded in httpd.conf. For the htdocs directory, I tried several settings, for example:
<Directory "c:/Apache24/htdocs">
Require all denied
Order allow,deny
Allow from all
AllowOverride All
Options None
AuthName "mycompany_proxy.loc"
AuthType SSPI
SSPIAuth On
SSPIAuthoritative On
SSPIOfferBasic On
SSPIOmitDomain On
Require valid-user
</Directory>
And this:
<Directory "c:/Apache24/htdocs">
Options Indexes FollowSymLinks
AllowOverride None
Order allow,deny
Allow from all
AuthName "mycompany_proxy.loc"
AuthType SSPI
SSPIAuth on
SSPIAuthoritative on
SSPIDomain mycompany_proxy.loc
SSPIOmitDomain on
SSPIOfferBasic on
SSPIBasicPreferred on
SSPIOfferSSPI on
SSPIMSIE3HACK on
require valid-user
</Directory>
Also, I added the apache_request_headers () function, its output is read on both servers as follows:
[Host] => server1
[Connection] => keep-alive
[Cache-Control] => max-age=0
[Authorization] => NTLM TlRMTVN... [long base64 code]
[Accept] => text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
[User-Agent] => Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.81 Safari/537.36
[Accept-Encoding] => gzip, deflate, sdch
[Accept-Language] => de,de-DE;q=0.8,en;q=0.6,en-US;q=0.4
So, in my opinion, there is some NTLM authentication going on. If I refresh the site, the authorization record disappears (possibly because it is complete).
The Apache service runs under a valid domain user (same on both servers).
I found this thread , but I am not using script authentication on the old server so I think I don't need it on the new server.
Both servers and my local computer are on our corporate intranet. Do I need to define our proxy (usually no proxy is needed to access local servers) or any active directory?
I'm afraid this might be a very special problem, but maybe you can point me in the right direction or see what else I can do to find the reason for the HTTP 401 code.
Any help is appreciated. Thanks in advance!
EDIT 2015-06-02, 09:40 AM
I found this module , but it only works for Apache 2.4 32 bit.
EDIT 2015-06-02, 09:51 AM
When I try to access test.txt on the new server from the old one through a web browser, I am asked to provide a user and password. When I then log in to the same user that the Apache service is running under, I can access the file. The appearance in access.log shows the following:
[IP address server1] - - [02/Jun/2015:09:49:23 +0200] "GET /test.txt HTTP/1.1" 401 381
[IP address server1] - apacheuser [02/Jun/2015:09:49:23 +0200] "GET /test.txt HTTP/1.1" 200 -
source to share
The Apache server behavior was absolutely correct, the get_headers () function did not send proper authentication, so the server responded with HTTP 401.
The reason it works on the old server can be found in the httpd.conf. There I defined SSPI parameters for each individual subdirectory not for the entire htdocs directory. The desired file on the new server is in the wshelper directory, so I put it in httpd.conf on the new server:
<Directory "c:/Apache24/htdocs">
Options Indexes FollowSymLinks
AllowOverride None
Order allow,deny
Allow from all
AuthName "mycompany_proxy.loc"
AuthType SSPI
SSPIAuth on
SSPIAuthoritative on
SSPIDomain mycompany_proxy.loc
SSPIOmitDomain on
SSPIOfferBasic on
SSPIBasicPreferred on
SSPIOfferSSPI on
SSPIMSIE3HACK on
require valid-user
</Directory>
# List all subdirectories which need to be accessible without authentication
<Directory "c:/Apache24/htdocs/wshelper">
Satisfy Any
Allow from all
</Directory>
source to share