You are viewing a plain text version of this content. The canonical link for it is here.
Posted to httpclient-users@hc.apache.org by Jeff Ling <je...@google.com> on 2006/10/31 21:51:25 UTC

ntlm issues 1 - infinite loop

Hello,

I have been using httpclient for a while. However, just recently I have run
into two customers that have some kind of issues. To simplify the situation,
I've written a very simple method to test it out. Here is the first issue:
if the username/password are not correct, or if the user does not have
authorization to access that url on the IIS 6.0 site, it enters into an
infinite loop. I am using version 3.0.1.

I've traced the source code. It seems that the problem is in
HttpMethodDirector:

            for (int redirectCount = 0;;) { //big loop
                authenticate(method);  //send out authentication request
                executeWithRetry(method); //send out message body
  ...
                boolean retry = false;
  ...
                if (isAuthenticationNeeded(method)) {  // NTLM returns 401
in handshake process, or when not authorized
                    if (processAuthenticationResponse(method)) {
                        LOG.debug("Retry authentication");
                        retry = true; //now retry becomes true
                    }
                }
                if (!retry) { //it wouldn't break
                    break;
                }
 ...


The problem (I think) is that even in the NTLM normal handshake process, 401
code is returned, so isAuthenticationNeeded() returns true. This is fine
because when it finishes the handshake process, isAuthenticationNeeded()
returns false. However, if the user name /password are wrong, or the user
doesn't have access to the web resource, 401 code will also be returned.
Since this code uses a loop instead of following/verifying the NTLM
handshake process, it just keeps retrying until connection times out.

Not sure whether this explaination is correct. I would assume that NTLM is
so widely used that there shouldn't be a problem like this. Am I missing
something? Here is how I called httpclient code:


      NTCredentials creds = new NTCredentials(context.getUserName(),
context.getPassword(),
        context.getServer(), context.getDomain());
      HttpState httpState = new HttpState();
      httpState.setAuthenticationPreemptive(true);
      HttpClient client = new HttpClient();

      httpState.setCredentials(new AuthScope(context.getHost(),
context.getPort(),
        AuthScope.ANY_REALM, AuthScope.ANY_SCHEME), creds);
      GetMethod get = new GetMethod(context.getSitePath());

      get.setDoAuthentication(true);
      setCredentialsProvider(client, creds);
      client.getParams().setAuthenticationPreemptive(true);
      client.setState(httpState);
      // execute method and handle any error responses.
      client.executeMethod(get);

Thanks!
Jeff

Re: ntlm issues 1 - infinite loop

Posted by Oleg Kalnichevski <ol...@apache.org>.
On Tue, 2006-10-31 at 12:51 -0800, Jeff Ling wrote:
> Hello,
> 
> I have been using httpclient for a while. However, just recently I have run
> into two customers that have some kind of issues. To simplify the situation,
> I've written a very simple method to test it out. Here is the first issue:
> if the username/password are not correct, or if the user does not have
> authorization to access that url on the IIS 6.0 site, it enters into an
> infinite loop. I am using version 3.0.1.
> 

Jeff,

You are not using the CredentialsProvider interface correctly

(Copied from the CredentialsProvider javadocs)
------------
HttpClient makes no provisions to check whether the same credentials
have been tried already. It is a responsibility of the custom
credentials provider to keep track of authentication attempts and to
ensure that credentials known to be invalid are not retried. HttpClient
will simply store the set of credentials returned by the custom
credentials provider in the HttpState object and will attempt to use
these credentials for all subsequent requests with the given
authentication scope.
------------

I admit CredentialsProvider is rather difficult to use for anything but
interactive authentication (which it was intended for in the first
place) for which I take full responsibility. CredentialsProvider is
likely to change drastically in HttpClient 4.0

Oleg

> I've traced the source code. It seems that the problem is in
> HttpMethodDirector:
> 
>             for (int redirectCount = 0;;) { //big loop
>                 authenticate(method);  //send out authentication request
>                 executeWithRetry(method); //send out message body
>   ...
>                 boolean retry = false;
>   ...
>                 if (isAuthenticationNeeded(method)) {  // NTLM returns 401
> in handshake process, or when not authorized
>                     if (processAuthenticationResponse(method)) {
>                         LOG.debug("Retry authentication");
>                         retry = true; //now retry becomes true
>                     }
>                 }
>                 if (!retry) { //it wouldn't break
>                     break;
>                 }
>  ...
> 
> 
> The problem (I think) is that even in the NTLM normal handshake process, 401
> code is returned, so isAuthenticationNeeded() returns true. This is fine
> because when it finishes the handshake process, isAuthenticationNeeded()
> returns false. However, if the user name /password are wrong, or the user
> doesn't have access to the web resource, 401 code will also be returned.
> Since this code uses a loop instead of following/verifying the NTLM
> handshake process, it just keeps retrying until connection times out.
> 
> Not sure whether this explaination is correct. I would assume that NTLM is
> so widely used that there shouldn't be a problem like this. Am I missing
> something? Here is how I called httpclient code:
> 
> 
>       NTCredentials creds = new NTCredentials(context.getUserName(),
> context.getPassword(),
>         context.getServer(), context.getDomain());
>       HttpState httpState = new HttpState();
>       httpState.setAuthenticationPreemptive(true);
>       HttpClient client = new HttpClient();
> 
>       httpState.setCredentials(new AuthScope(context.getHost(),
> context.getPort(),
>         AuthScope.ANY_REALM, AuthScope.ANY_SCHEME), creds);
>       GetMethod get = new GetMethod(context.getSitePath());
> 
>       get.setDoAuthentication(true);
>       setCredentialsProvider(client, creds);
>       client.getParams().setAuthenticationPreemptive(true);
>       client.setState(httpState);
>       // execute method and handle any error responses.
>       client.executeMethod(get);
> 
> Thanks!
> Jeff


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


Re: ntlm issues 1 - infinite loop

Posted by Oleg Kalnichevski <ol...@apache.org>.
On Wed, 2006-11-01 at 08:38 -0800, Jeff Ling wrote:
> Hi Oleg,
> 
> I found out this was an Axis2 bug. Axis2 sets the credentialProvider, that's
> why the "promptForCredential()" didn't return null, and keeps going in a
> loop.
> 
> Thanks!
> 
> Jeff
> 

Jeff,

As far as I know this problem should have been fixed in the coming Axis2
1.1 release

http://www.mail-archive.com/httpclient-dev%
40jakarta.apache.org/msg04464.html

Oleg


> On 11/1/06, Oleg Kalnichevski <ol...@apache.org> wrote:
> >
> > On Tue, 2006-10-31 at 18:38 -0800, Jeff Ling wrote:
> > > Hi Oleg,
> > >
> > > Here is the cleaned up code:
> > >
> > >       NTCredentials creds = new NTCredentials(username, password,
> > >         "columbus.corp.goo.com", "ent-sales-d2");
> > >       HttpState httpState = new HttpState();
> > >       HttpClient client = new HttpClient();
> > >
> > >       httpState.setCredentials(new AuthScope("columbus",
> > >         AuthScope.ANY_REALM, AuthScope.ANY_SCHEME), creds);
> > >       GetMethod get = new GetMethod("
> > > http://columbus.corp.goo.com/default.aspx");
> > >
> > >       get.setDoAuthentication(true);
> > >       client.getParams().setAuthenticationPreemptive(false);
> > >       client.setState(httpState);
> > >       client.executeMethod(get);
> > > ...
> > >
> > > Do you see any problem?
> > >
> >
> > Jeff,
> >
> > No, I do not. Could you please re-test your application with the latest
> > HttpClient release (3.1-beta1) just in case and see if the problem still
> > persists? If it does, please post a wire/context log of the HTTP session
> > that exhibits the problem. I'll take a look at it
> >
> > Oleg
> >
> >
> > > Thanks,
> > > Jeff
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: httpclient-user-unsubscribe@jakarta.apache.org
> > For additional commands, e-mail: httpclient-user-help@jakarta.apache.org
> >
> >
> 
> 


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


Re: ntlm issues 1 - infinite loop

Posted by Jeff Ling <je...@google.com>.
Hi Oleg,

I found out this was an Axis2 bug. Axis2 sets the credentialProvider, that's
why the "promptForCredential()" didn't return null, and keeps going in a
loop.

Thanks!

Jeff

On 11/1/06, Oleg Kalnichevski <ol...@apache.org> wrote:
>
> On Tue, 2006-10-31 at 18:38 -0800, Jeff Ling wrote:
> > Hi Oleg,
> >
> > Here is the cleaned up code:
> >
> >       NTCredentials creds = new NTCredentials(username, password,
> >         "columbus.corp.goo.com", "ent-sales-d2");
> >       HttpState httpState = new HttpState();
> >       HttpClient client = new HttpClient();
> >
> >       httpState.setCredentials(new AuthScope("columbus",
> >         AuthScope.ANY_REALM, AuthScope.ANY_SCHEME), creds);
> >       GetMethod get = new GetMethod("
> > http://columbus.corp.goo.com/default.aspx");
> >
> >       get.setDoAuthentication(true);
> >       client.getParams().setAuthenticationPreemptive(false);
> >       client.setState(httpState);
> >       client.executeMethod(get);
> > ...
> >
> > Do you see any problem?
> >
>
> Jeff,
>
> No, I do not. Could you please re-test your application with the latest
> HttpClient release (3.1-beta1) just in case and see if the problem still
> persists? If it does, please post a wire/context log of the HTTP session
> that exhibits the problem. I'll take a look at it
>
> Oleg
>
>
> > Thanks,
> > Jeff
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: httpclient-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: httpclient-user-help@jakarta.apache.org
>
>


-- 
Jeff Ling
Product Solutions Engineer
GOOGLE
Office: (650) 253-3095
Fax: (650) 618-1835
Email: jeffling@google.com

Re: ntlm issues 1 - infinite loop

Posted by Oleg Kalnichevski <ol...@apache.org>.
On Tue, 2006-10-31 at 18:38 -0800, Jeff Ling wrote:
> Hi Oleg,
> 
> Here is the cleaned up code:
> 
>       NTCredentials creds = new NTCredentials(username, password,
>         "columbus.corp.goo.com", "ent-sales-d2");
>       HttpState httpState = new HttpState();
>       HttpClient client = new HttpClient();
> 
>       httpState.setCredentials(new AuthScope("columbus",
>         AuthScope.ANY_REALM, AuthScope.ANY_SCHEME), creds);
>       GetMethod get = new GetMethod("
> http://columbus.corp.goo.com/default.aspx");
> 
>       get.setDoAuthentication(true);
>       client.getParams().setAuthenticationPreemptive(false);
>       client.setState(httpState);
>       client.executeMethod(get);
> ...
> 
> Do you see any problem?
> 

Jeff,

No, I do not. Could you please re-test your application with the latest
HttpClient release (3.1-beta1) just in case and see if the problem still
persists? If it does, please post a wire/context log of the HTTP session
that exhibits the problem. I'll take a look at it

Oleg


> Thanks,
> Jeff


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


Re: ntlm issues 1 - infinite loop

Posted by Jeff Ling <je...@google.com>.
Hi Oleg,

Here is the cleaned up code:

      NTCredentials creds = new NTCredentials(username, password,
        "columbus.corp.goo.com", "ent-sales-d2");
      HttpState httpState = new HttpState();
      HttpClient client = new HttpClient();

      httpState.setCredentials(new AuthScope("columbus",
        AuthScope.ANY_REALM, AuthScope.ANY_SCHEME), creds);
      GetMethod get = new GetMethod("
http://columbus.corp.goo.com/default.aspx");

      get.setDoAuthentication(true);
      client.getParams().setAuthenticationPreemptive(false);
      client.setState(httpState);
      client.executeMethod(get);
...

Do you see any problem?

Thanks,
Jeff

Re: ntlm issues 1 - infinite loop

Posted by Jeff Ling <je...@google.com>.
Hi Oleg,

Do you think this is a bug? I am expecting that even if authentication
fails, it should not enter into an infinite loop. I read the mailing list
archive about some fixes in previous releases on this issue. Is it possible
that the problem crept back?

Thanks,
Jeff

On 10/31/06, Jeff Ling <je...@google.com> wrote:
>
> Hi Oleg,
>
> This is what I used when I observed the behavior. I didn't use any custom
> provider. Do you see anything wrong with this code?
>
> HttpState httpState = new HttpState();
>       httpState.setAuthenticationPreemptive (false);
>       HttpClient client = new HttpClient();
>       httpState.setCredentials(new AuthScope(context.getHost(),
> context.getPort(),
>         AuthScope.ANY_REALM, AuthScope.ANY_SCHEME), creds);
>       client.setState(httpState);
>
>
> Thanks,
> Jeff
>



-- 
Jeff Ling
Product Solutions Engineer
GOOGLE
Office: (650) 253-3095
Fax: (650) 618-1835
Email: jeffling@google.com

Re: ntlm issues 1 - infinite loop

Posted by Jeff Ling <je...@google.com>.
Hi Oleg,

This is what I used when I observed the behavior. I didn't use any custom
provider. Do you see anything wrong with this code?

HttpState httpState = new HttpState();
      httpState.setAuthenticationPreemptive(false);
      HttpClient client = new HttpClient();
      httpState.setCredentials(new AuthScope(context.getHost(),
context.getPort(),
        AuthScope.ANY_REALM, AuthScope.ANY_SCHEME), creds);
      client.setState(httpState);


Thanks,
Jeff

Re: ntlm issues 1 - infinite loop

Posted by Oleg Kalnichevski <ol...@apache.org>.
On Tue, 2006-10-31 at 14:30 -0800, Jeff Ling wrote:
> Hi Oleg,
> 
> Thanks for the response. Could you give me an example of how to properly use
> NTLM authentication?
> 
> Thanks,
> Jeff
> 

Jeff,

Just adding appropriate authentication credentials to the HttpState
should be sufficient. HttpClient will attempt to authenticate against
the target site using the given credentials and will return 401 status
code in case of authentication failure. You should be using a custom
CredentialsProvider only if you want to present an interactive
authentication dialog to the user.

Hope this helps

Oleg

> On 10/31/06, Oleg Kalnichevski <ol...@apache.org> wrote:
> >
> > On Tue, 2006-10-31 at 22:17 +0100, Oleg Kalnichevski wrote:
> >
> > Sorry about multiple emails.
> >
> > Oleg
> >
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: httpclient-user-unsubscribe@jakarta.apache.org
> > For additional commands, e-mail: httpclient-user-help@jakarta.apache.org
> >
> >
> 
> 


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


Re: ntlm issues 1 - infinite loop

Posted by Jeff Ling <je...@google.com>.
Hi Oleg,

Thanks for the response. Could you give me an example of how to properly use
NTLM authentication?

Thanks,
Jeff

On 10/31/06, Oleg Kalnichevski <ol...@apache.org> wrote:
>
> On Tue, 2006-10-31 at 22:17 +0100, Oleg Kalnichevski wrote:
>
> Sorry about multiple emails.
>
> Oleg
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: httpclient-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: httpclient-user-help@jakarta.apache.org
>
>


-- 
Jeff Ling
Product Solutions Engineer
GOOGLE
Office: (650) 253-3095
Fax: (650) 618-1835
Email: jeffling@google.com

Re: ntlm issues 1 - infinite loop

Posted by Oleg Kalnichevski <ol...@apache.org>.
On Tue, 2006-10-31 at 22:17 +0100, Oleg Kalnichevski wrote:

Sorry about multiple emails. 

Oleg



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


Re: ntlm issues 1 - infinite loop

Posted by Oleg Kalnichevski <ol...@apache.org>.
On Tue, 2006-10-31 at 12:51 -0800, Jeff Ling wrote:
> Hello,
> 
> I have been using httpclient for a while. However, just recently I have run
> into two customers that have some kind of issues. To simplify the situation,
> I've written a very simple method to test it out. Here is the first issue:
> if the username/password are not correct, or if the user does not have
> authorization to access that url on the IIS 6.0 site, it enters into an
> infinite loop. I am using version 3.0.1.
> 

Jeff,

You are not using the CredentialsProvider interface correctly

(Copied from the CredentialsProvider javadocs)
------------
HttpClient makes no provisions to check whether the same credentials
have been tried already. It is a responsibility of the custom
credentials provider to keep track of authentication attempts and to
ensure that credentials known to be invalid are not retried. HttpClient
will simply store the set of credentials returned by the custom
credentials provider in the HttpState object and will attempt to use
these credentials for all subsequent requests with the given
authentication scope.
------------

I admit CredentialsProvider is rather difficult to use for anything but
interactive authentication (which it was intended for in the first
place) for which I take full responsibility. CredentialsProvider is
likely to change drastically in HttpClient 4.0

Oleg

> I've traced the source code. It seems that the problem is in
> HttpMethodDirector:
> 
>             for (int redirectCount = 0;;) { //big loop
>                 authenticate(method);  //send out authentication request
>                 executeWithRetry(method); //send out message body
>   ...
>                 boolean retry = false;
>   ...
>                 if (isAuthenticationNeeded(method)) {  // NTLM returns 401
> in handshake process, or when not authorized
>                     if (processAuthenticationResponse(method)) {
>                         LOG.debug("Retry authentication");
>                         retry = true; //now retry becomes true
>                     }
>                 }
>                 if (!retry) { //it wouldn't break
>                     break;
>                 }
>  ...
> 
> 
> The problem (I think) is that even in the NTLM normal handshake process, 401
> code is returned, so isAuthenticationNeeded() returns true. This is fine
> because when it finishes the handshake process, isAuthenticationNeeded()
> returns false. However, if the user name /password are wrong, or the user
> doesn't have access to the web resource, 401 code will also be returned.
> Since this code uses a loop instead of following/verifying the NTLM
> handshake process, it just keeps retrying until connection times out.
> 
> Not sure whether this explaination is correct. I would assume that NTLM is
> so widely used that there shouldn't be a problem like this. Am I missing
> something? Here is how I called httpclient code:
> 
> 
>       NTCredentials creds = new NTCredentials(context.getUserName(),
> context.getPassword(),
>         context.getServer(), context.getDomain());
>       HttpState httpState = new HttpState();
>       httpState.setAuthenticationPreemptive(true);
>       HttpClient client = new HttpClient();
> 
>       httpState.setCredentials(new AuthScope(context.getHost(),
> context.getPort(),
>         AuthScope.ANY_REALM, AuthScope.ANY_SCHEME), creds);
>       GetMethod get = new GetMethod(context.getSitePath());
> 
>       get.setDoAuthentication(true);
>       setCredentialsProvider(client, creds);
>       client.getParams().setAuthenticationPreemptive(true);
>       client.setState(httpState);
>       // execute method and handle any error responses.
>       client.executeMethod(get);
> 
> Thanks!
> Jeff


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


Re: ntlm issues 1 - infinite loop

Posted by Oleg Kalnichevski <ol...@apache.org>.
On Tue, 2006-10-31 at 12:51 -0800, Jeff Ling wrote:
> Hello,
> 
> I have been using httpclient for a while. However, just recently I have run
> into two customers that have some kind of issues. To simplify the situation,
> I've written a very simple method to test it out. Here is the first issue:
> if the username/password are not correct, or if the user does not have
> authorization to access that url on the IIS 6.0 site, it enters into an
> infinite loop. I am using version 3.0.1.
> 

Jeff,

You are not using the CredentialsProvider interface correctly

(Copied from the CredentialsProvider javadocs)
------------
HttpClient makes no provisions to check whether the same credentials
have been tried already. It is a responsibility of the custom
credentials provider to keep track of authentication attempts and to
ensure that credentials known to be invalid are not retried. HttpClient
will simply store the set of credentials returned by the custom
credentials provider in the HttpState object and will attempt to use
these credentials for all subsequent requests with the given
authentication scope.
------------

I admit CredentialsProvider is rather difficult to use for anything but
interactive authentication (which it was intended for in the first
place) for which I take full responsibility. CredentialsProvider is
likely to change drastically in HttpClient 4.0

Oleg

> I've traced the source code. It seems that the problem is in
> HttpMethodDirector:
> 
>             for (int redirectCount = 0;;) { //big loop
>                 authenticate(method);  //send out authentication request
>                 executeWithRetry(method); //send out message body
>   ...
>                 boolean retry = false;
>   ...
>                 if (isAuthenticationNeeded(method)) {  // NTLM returns 401
> in handshake process, or when not authorized
>                     if (processAuthenticationResponse(method)) {
>                         LOG.debug("Retry authentication");
>                         retry = true; //now retry becomes true
>                     }
>                 }
>                 if (!retry) { //it wouldn't break
>                     break;
>                 }
>  ...
> 
> 
> The problem (I think) is that even in the NTLM normal handshake process, 401
> code is returned, so isAuthenticationNeeded() returns true. This is fine
> because when it finishes the handshake process, isAuthenticationNeeded()
> returns false. However, if the user name /password are wrong, or the user
> doesn't have access to the web resource, 401 code will also be returned.
> Since this code uses a loop instead of following/verifying the NTLM
> handshake process, it just keeps retrying until connection times out.
> 
> Not sure whether this explaination is correct. I would assume that NTLM is
> so widely used that there shouldn't be a problem like this. Am I missing
> something? Here is how I called httpclient code:
> 
> 
>       NTCredentials creds = new NTCredentials(context.getUserName(),
> context.getPassword(),
>         context.getServer(), context.getDomain());
>       HttpState httpState = new HttpState();
>       httpState.setAuthenticationPreemptive(true);
>       HttpClient client = new HttpClient();
> 
>       httpState.setCredentials(new AuthScope(context.getHost(),
> context.getPort(),
>         AuthScope.ANY_REALM, AuthScope.ANY_SCHEME), creds);
>       GetMethod get = new GetMethod(context.getSitePath());
> 
>       get.setDoAuthentication(true);
>       setCredentialsProvider(client, creds);
>       client.getParams().setAuthenticationPreemptive(true);
>       client.setState(httpState);
>       // execute method and handle any error responses.
>       client.executeMethod(get);
> 
> Thanks!
> Jeff


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