~~ ====================================================================
~~ Licensed to the Apache Software Foundation (ASF) under one
~~ or more contributor license agreements.  See the NOTICE file
~~ distributed with this work for additional information
~~ regarding copyright ownership.  The ASF licenses this file
~~ to you under the Apache License, Version 2.0 (the
~~ "License"); you may not use this file except in compliance
~~ with the License.  You may obtain a copy of the License at
~~
~~   http://www.apache.org/licenses/LICENSE-2.0
~~
~~ Unless required by applicable law or agreed to in writing,
~~ software distributed under the License is distributed on an
~~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
~~ KIND, either express or implied.  See the License for the
~~ specific language governing permissions and limitations
~~ under the License.
~~ ====================================================================
~~
~~ This software consists of voluntary contributions made by many
~~ individuals on behalf of the Apache Software Foundation.  For more
~~ information on the Apache Software Foundation, please see
~~ <http://www.apache.org/>.

    ----------
    NTLM support in HttpClient
    ----------
    ----------
    ----------

NTLM support in HttpClient

* {Background}

    NTLM is a proprietary authentication scheme developed by Microsoft and optimized for
    Windows operating system.

    Until year 2008 there was no official, publicly available, complete documentation of
    the protocol. {{{http://davenport.sourceforge.net/ntlm.html}Unofficial}} 3rd party
    protocol descriptions existed as a result of reverse-engineering efforts. It was not
    really known whether the protocol based on the reverse-engineering were complete or
    even correct.

    Microsoft published {{{http://download.microsoft.com/download/a/e/6/ae6e4142-aa58-45c6-8dcf-a657e5900cd3/%5BMS-NLMP%5D.pdf}MS-NLMP}}
    and {{{http://download.microsoft.com/download/a/e/6/ae6e4142-aa58-45c6-8dcf-a657e5900cd3/%5BMS-NTHT%5D.pdf}MS-NTHT}}
    specifications in February 2008 as a part of its
    {{{http://www.microsoft.com/interop/principles/default.mspx}Interoperability
    Principles initiative}}. 

    HttpClient as of version 4.1 initially supported NTLMv1, NTLMv2, and NTLM2SessionResponse
    authentication protocols, based on the reverse engineering approach.  As of version
    4.2.3, HttpClient now supports a more correct implementation, based in large part on
    Microsoft's own specifications.  This is expected to correct a number of problems, especially
    since Microsoft (as of Windows Server 2008 R2) began using a new implementation of its
    protocols.  This new Microsoft implementation has led to authentication failures in some
    cases from some of the older reverse-engineered client implementations of NTLM.
    
    The new HttpClient NTLM implementation is known to have been tried successfully against
    at least the following systems:
    
    * Windows Server 2000 and Server 2003 systems, configured to use LM and NTLMv1 authentication

    * Windows Server 2003 systems, configured to use NTLMv2 authentication

    * Windows Server 2008 R2 systems, configured to use NTLM2SessionResponse authentication

    []
    
    If the current HttpClient NTLM implementation should prove problematic in your environment,
    we'd definitely like to hear about it.  You are also welcome to try an alternative NTLM
    implementation, should it seem necessary. One can also use {{{http://jcifs.samba.org/}JCIFS}},
    which includes an NTLM engine developed by members of the Samba project. 

* {Using Samba JCIFS as an alternative NTLM engine}

    Follow these instructions to build an NTLMEngine implementation using JCIFS library

    <<Disclaimer: Use code at your own discretion. Do NOT report any issues related to 
    the use of JCIFS library to Apache HttpComponents project>>.

    * Download version 1.3.14 or newer of the JCIFS library from the 
    {{{http://jcifs.samba.org/}Samba}} web site

    * Implement NTLMEngine interface

----------------------------------------
import java.io.IOException;

import jcifs.ntlmssp.NtlmFlags;
import jcifs.ntlmssp.Type1Message;
import jcifs.ntlmssp.Type2Message;
import jcifs.ntlmssp.Type3Message;
import jcifs.util.Base64;

import org.apache.http.impl.auth.NTLMEngine;
import org.apache.http.impl.auth.NTLMEngineException;

public final class JCIFSEngine implements NTLMEngine {

    private static final int TYPE_1_FLAGS = 
            NtlmFlags.NTLMSSP_NEGOTIATE_56 | 
            NtlmFlags.NTLMSSP_NEGOTIATE_128 | 
            NtlmFlags.NTLMSSP_NEGOTIATE_NTLM2 | 
            NtlmFlags.NTLMSSP_NEGOTIATE_ALWAYS_SIGN | 
            NtlmFlags.NTLMSSP_REQUEST_TARGET;

    public String generateType1Msg(final String domain, final String workstation)
            throws NTLMEngineException {
        final Type1Message type1Message = new Type1Message(TYPE_1_FLAGS, domain, workstation);
        return Base64.encode(type1Message.toByteArray());
    }

    public String generateType3Msg(final String username, final String password,
            final String domain, final String workstation, final String challenge)
            throws NTLMEngineException {
        Type2Message type2Message;
        try {
            type2Message = new Type2Message(Base64.decode(challenge));
        } catch (final IOException exception) {
            throw new NTLMEngineException("Invalid NTLM type 2 message", exception);
        }
        final int type2Flags = type2Message.getFlags();
        final int type3Flags = type2Flags
                & (0xffffffff ^ (NtlmFlags.NTLMSSP_TARGET_TYPE_DOMAIN | NtlmFlags.NTLMSSP_TARGET_TYPE_SERVER));
        final Type3Message type3Message = new Type3Message(type2Message, password, domain,
                username, workstation, type3Flags);
        return Base64.encode(type3Message.toByteArray());
    }

}
----------------------------------------

    * Implement AuthSchemeProvider interface

----------------------------------------
public class JCIFSNTLMSchemeFactory implements AuthSchemeProvider {

    public AuthScheme create(final HttpContext context) {
        return new NTLMScheme(new JCIFSEngine());
    }
}
----------------------------------------

    * Register NTLMSchemeFactory with the HttpClient instance you want to NTLM 
    enable.

----------------------------------------
Registry<AuthSchemeProvider> authSchemeRegistry = RegistryBuilder.<AuthSchemeProvider>create()
        .register(AuthSchemes.NTLM, new JCIFSNTLMSchemeFactory())
        .register(AuthSchemes.BASIC, new BasicSchemeFactory())
        .register(AuthSchemes.DIGEST, new DigestSchemeFactory())
        .register(AuthSchemes.SPNEGO, new SPNegoSchemeFactory())
        .register(AuthSchemes.KERBEROS, new KerberosSchemeFactory())
        .build();
CloseableHttpClient httpClient = HttpClients.custom()
        .setDefaultAuthSchemeRegistry(authSchemeRegistry)
        .build();
----------------------------------------

    * Set NTCredentials for the web server you are going to access.


