cheeZer
cheeZer

Reputation: 468

NTLM authentication on Apache 2.4 with mod_authnz_sspi

I've difficulties reaching a file on one Apache web server from another web server. Or even from the same web server.

First let me give you the specfications 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 the Windows remote user (for a Single Sign-on) I use the module mod_auth_sspi on the older server. Unfortunately this module isn't supported anymore in Apache 2.4 so I switched to mod_authnz_sspi. Reading the user name works fine, but if I run a PHP script on the old server to connect to the new server and read a file there, the script gets rejected with HTTP code 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 perfectly (I hope this doesn't sound to confusing. English also isn't my first language, as you may have recognized).

I've used the function get_headers() to access the file, simplified the 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 first the script tries to read the file on one server, 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 none to the 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 in the Apache access.log on the two servers. Regarding 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 -

The new one 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 the test.txt from the new server via a browser on my local machine (which works perfectly 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 preferences, for example this one:

<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>

Additionally I added the function apache_request_headers(), its output reads 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 a NTLM authentication of some sort happens. If I refresh the site, the Authorization entry disappears (probably because it's finished).

The Apache service runs under a valid domain user (the same on both servers).

I found this thread, but I don't use an authentication script on the old server so I think I don't need one on the new server.

Both servers and my local machine are in our company intranet. Do I need to define our proxy (normally the proxy is not needed to access local servers) or the active directory somewhere?

I fear this might be a very special problem, but maybe you can point me in the right direction or know what else I can do, to find the reason for the HTTP code 401.

Any help is appreciated. Thanks in advance!

EDIT 2015-06-02, 09:40 AM

I found this module, but it only seems to work for Apache 2.4 32 bit.

EDIT 2015-06-02, 09:51 AM

When I try to access the test.txt on the new server from the old one via web browser, I'm asked to provide an user and password. When I then enter the same user under which the Apache service runs I can access the file. A look in the 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 -

Upvotes: 3

Views: 14774

Answers (1)

cheeZer
cheeZer

Reputation: 468

The behavior of the Apache server was absolutely correct, the function get_headers() didn't send a proper authentication so the server responded with HTTP code 401.

The reason that it works on the old server can be found in the httpd.conf. There I defined the SSPI options for every single subdirectory not for the whole htdocs-directory. The desired file on the new server is in the directory wshelper, so I put this in the 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>

Upvotes: 2

Related Questions