hc-httpclient-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Ron Jacobs <Ron.Jac...@Reardencommerce.com>
Subject Full NTLMv2 Support Achieved Easily (Was: NTLM authentication with a UPN instead of domain and user name)
Date Thu, 21 Apr 2011 17:12:49 GMT
(I apologize for the delay in posting this update. It was delayed due to
matters outside of my control. Nonetheless, I am sure that anyone
struggling to gain NTLMv2 support with version 4.1.x will be helped by
taking a look at the following:)

------------------------------------------------------------------------

I have tried JCIFS and was able to get all of my test cases to pass.

But, it doesn't support NTLMv2 "out of the box" because its
NegotiateFlags (see section 2.2.2.5 of the Microsoft's [MS-NLMP] spec)
is insufficient.

My implementation is based upon the example that used to be found at:

   http://hc.apache.org/httpcomponents-client/ntlm.html

I was able to locate the info on the way-back machine at:

   http://replay.waybackmachine.org/20090611051135/http://hc.apache.org/httpcomponents-client/ntlm.html

Since the built-in NTLM implementation is insufficient, the maintainers
may wish to restore this page, with the slight adjustment that I found
necessary, or with the following code, which I have verified works with
both NTLMv1 and NTLMv2 authentication:

------------------------------------------------------------------------

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.auth.AuthScheme;
import org.apache.http.auth.AuthSchemeFactory;
import org.apache.http.client.params.AuthPolicy;
import org.apache.http.impl.auth.NTLMEngine;
import org.apache.http.impl.auth.NTLMEngineException;
import org.apache.http.impl.auth.NTLMScheme;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.HttpParams;

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());
  }

  public static void register(final DefaultHttpClient httpClient) {
    httpClient.getAuthSchemes().register(AuthPolicy.NTLM, new AuthSchemeFactory() {
      public AuthScheme newInstance(final HttpParams httpParams) {
        return new NTLMScheme(new JCIFSEngine());
      }
    });
  }
}

------------------------------------------------------------------------

Then, just insert a call to JCIFSEngine.register() for each newly
created DefaultHttpClient instance.

-----Original Message-----
From: Oleg Kalnichevski [mailto:olegk@apache.org] 
Sent: Friday, March 11, 2011 10:07 AM
To: HttpClient User Discussion
Subject: Re: NTLM authentication with a UPN instead of domain and user name

On Fri, 2011-03-11 at 17:47 +0000, Ron Jacobs wrote:
> I am using NTLM authentication and I find that when porting from 3.0.2
> to 4.1, I have several questions:
> 
> 1) Authenticating with domain and user works but with a UPN (like
>    "user@domain.local") authentication fails although both authenticate
>    fine with my previous 3.0.2 code. Why does the UPN-style not work?
> 

HttpClient 4.1 has a completely new NTML engine contributed by an
external project. Apparently it does not work with UPN style user names.
You may want to try out JCIFS based NTLM engine and see if it works
better. 


> 2) How should I set credentials for NTLM where there is no domain, like
>    when using the UPN form? NTCredentials with domain "" or null, or
>    UsernamePasswordCredentials? I have tried various combinations
>    without success.
> 

As far as I understand if it is a standalone workstation the domain
should be same as the the workstation name.

> 3) I am accessing a web service from outside the NT domain so I have no
>    workstation name for the 3rd parameter to the NTCredentials
>    constructor. I have tried passing null, "", or "somejunk" without
>    success.
> 

Again, my knowledge of MS Windows networking is awfully outdated, but as
far as I remember there is _always_ an authentication domain of some
sort. In the simplest form the workstation can act as its own auth
domain.

Anyhow it has been ages since I touches anything called Windows


> 4) The NTCredentials constructor seems happy to set workstation to null
>    but I find that when it is null a NullPointerException is thrown from
>    somewhere within your NTLM code.
> 

Feel free to raise a JIRA for this defect.

Oleg



---------------------------------------------------------------------
To unsubscribe, e-mail: httpclient-users-unsubscribe@hc.apache.org
For additional commands, e-mail: httpclient-users-help@hc.apache.org

Mime
View raw message