You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2008/05/10 13:22:13 UTC

svn commit: r655048 - in /httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl: auth/NTLMEngine.java auth/NTLMEngineException.java auth/NTLMScheme.java client/DefaultClientRequestDirector.java client/RequestWrapper.java

Author: olegk
Date: Sat May 10 04:22:12 2008
New Revision: 655048

URL: http://svn.apache.org/viewvc?rev=655048&view=rev
Log:
Partial support for NTLM authentication. NTLM auth scheme must be provided with a concrete implementation NTLMEngine interface in order to work. Documentation to follow. 

Added:
    httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/auth/NTLMEngine.java   (with props)
    httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/auth/NTLMEngineException.java   (with props)
    httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/auth/NTLMScheme.java   (with props)
Modified:
    httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/client/DefaultClientRequestDirector.java
    httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/client/RequestWrapper.java

Added: httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/auth/NTLMEngine.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/auth/NTLMEngine.java?rev=655048&view=auto
==============================================================================
--- httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/auth/NTLMEngine.java (added)
+++ httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/auth/NTLMEngine.java Sat May 10 04:22:12 2008
@@ -0,0 +1,76 @@
+/*
+ * $HeadURL$
+ * $Revision$
+ * $Date$
+ *
+ * ====================================================================
+ *
+ *  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/>.
+ *
+ */
+
+package org.apache.http.impl.auth;
+
+/**
+ * Abstract NTLM authentication engine. The engine can be used to
+ * generate Type1 messages and Type3 messages in response to a 
+ * Type2 challenge.
+ * <p/>
+ * For details see {@linkplain http://davenport.sourceforge.net/ntlm.html}}
+ * 
+ * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
+*/
+public interface NTLMEngine {
+
+    /**
+     * Generates a Type1 message given the domain and workstation.
+     * 
+     * @param domain Optional Windows domain name. Can be <code>null</code>.
+     * @param workstation Optional Windows workstation name. Can be 
+     *  <code>null</code>.
+     * @return Type1 message
+     * @throws NTLMEngineException
+     */
+    String generateType1Msg(
+            String domain, 
+            String workstation) throws NTLMEngineException;
+    
+    /**
+     * Generates a Type3 message given the user credentials and the 
+     * authentication challenge.
+     *  
+     * @param username Windows user name
+     * @param password Password
+     * @param domain Windows domain name
+     * @param workstation Windows workstation name
+     * @param challenge Type2 challenge.
+     * @return Type3 response.
+     * @throws NTLMEngineException
+     */
+    String generateType3Msg(
+            String username,
+            String password,
+            String domain, 
+            String workstation,
+            String challenge) throws NTLMEngineException;
+    
+}

Propchange: httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/auth/NTLMEngine.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/auth/NTLMEngine.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/auth/NTLMEngine.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/auth/NTLMEngineException.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/auth/NTLMEngineException.java?rev=655048&view=auto
==============================================================================
--- httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/auth/NTLMEngineException.java (added)
+++ httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/auth/NTLMEngineException.java Sat May 10 04:22:12 2008
@@ -0,0 +1,70 @@
+/*
+ * $HeadURL$
+ * $Revision$
+ * $Date$
+ *
+ * ====================================================================
+ *
+ *  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/>.
+ *
+ */
+
+package org.apache.http.impl.auth;
+
+import org.apache.http.auth.AuthenticationException;
+
+/**
+ * Signals NTLM protocol failure.
+ *
+ * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
+ * 
+ * @since 4.0
+ */
+public class NTLMEngineException extends AuthenticationException {
+
+    private static final long serialVersionUID = 6027981323731768824L;
+
+    public NTLMEngineException() {
+        super();
+    }
+
+    /**
+     * Creates a new NTLMEngineException with the specified message.
+     * 
+     * @param message the exception detail message
+     */
+    public NTLMEngineException(String message) {
+        super(message);
+    }
+
+    /**
+     * Creates a new NTLMEngineException with the specified detail message and cause.
+     * 
+     * @param message the exception detail message
+     * @param cause the <tt>Throwable</tt> that caused this exception, or <tt>null</tt>
+     * if the cause is unavailable, unknown, or not a <tt>Throwable</tt>
+     */
+    public NTLMEngineException(String message, Throwable cause) {
+        super(message, cause);
+    }
+    
+}

Propchange: httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/auth/NTLMEngineException.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/auth/NTLMEngineException.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/auth/NTLMEngineException.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/auth/NTLMScheme.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/auth/NTLMScheme.java?rev=655048&view=auto
==============================================================================
--- httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/auth/NTLMScheme.java (added)
+++ httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/auth/NTLMScheme.java Sat May 10 04:22:12 2008
@@ -0,0 +1,149 @@
+/*
+ * $HeadURL$
+ * $Revision$
+ * $Date$
+ *
+ * ====================================================================
+ *
+ *  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/>.
+ *
+ */
+
+package org.apache.http.impl.auth;
+
+import org.apache.http.Header;
+import org.apache.http.HttpRequest;
+import org.apache.http.auth.AUTH;
+import org.apache.http.auth.AuthenticationException;
+import org.apache.http.auth.Credentials;
+import org.apache.http.auth.InvalidCredentialsException;
+import org.apache.http.auth.MalformedChallengeException;
+import org.apache.http.auth.NTCredentials;
+import org.apache.http.impl.auth.AuthSchemeBase;
+import org.apache.http.message.BufferedHeader;
+import org.apache.http.util.CharArrayBuffer;
+
+public class NTLMScheme extends AuthSchemeBase {
+
+    enum State {
+        UNINITIATED,
+        CHALLENGE_RECEIVED,
+        MSG_TYPE1_GENERATED,
+        MSG_TYPE2_RECEVIED,
+        MSG_TYPE3_GENERATED,
+        FAILED,
+    }
+    
+    private final NTLMEngine engine;
+    
+    private State state;
+    private String challenge;
+    
+    public NTLMScheme(final NTLMEngine engine) {
+        super();
+        if (engine == null) {
+            throw new IllegalArgumentException("NTLM engine may not be null");
+        }
+        this.engine = engine;
+        this.state = State.UNINITIATED;
+        this.challenge = null;
+    }
+    
+    public String getSchemeName() {
+        return "ntlm";
+    }
+
+    public String getParameter(String name) {
+        // String parameters not supported
+        return null;
+    }
+
+    public String getRealm() {
+        // NTLM does not support the concept of an authentication realm
+        return null;
+    }
+
+    public boolean isConnectionBased() {
+        return true;
+    }
+
+    @Override
+    protected void parseChallenge(
+            final CharArrayBuffer buffer, int pos, int len) throws MalformedChallengeException {
+        String challenge = buffer.substringTrimmed(pos, len);
+        if (challenge.length() == 0) {
+            if (this.state == State.UNINITIATED) {
+                this.state = State.CHALLENGE_RECEIVED;
+            } else {
+                this.state = State.FAILED;
+            }
+            this.challenge = null;
+        } else {
+            this.state = State.MSG_TYPE2_RECEVIED;
+            this.challenge = challenge;
+        }
+    }
+
+    public Header authenticate(
+            final Credentials credentials, 
+            final HttpRequest request) throws AuthenticationException {
+        NTCredentials ntcredentials = null;
+        try {
+            ntcredentials = (NTCredentials) credentials;
+        } catch (ClassCastException e) {
+            throw new InvalidCredentialsException(
+             "Credentials cannot be used for NTLM authentication: " 
+              + credentials.getClass().getName());
+        }
+        String response = null;
+        if (this.state == State.CHALLENGE_RECEIVED || this.state == State.FAILED) {
+            response = this.engine.generateType1Msg(
+                    ntcredentials.getDomain(), 
+                    ntcredentials.getWorkstation());
+            this.state = State.MSG_TYPE1_GENERATED;
+        } else if (this.state == State.MSG_TYPE2_RECEVIED) {
+            response = this.engine.generateType3Msg(
+                    ntcredentials.getUserName(), 
+                    ntcredentials.getPassword(), 
+                    ntcredentials.getDomain(), 
+                    ntcredentials.getWorkstation(),
+                    this.challenge);
+            this.state = State.MSG_TYPE3_GENERATED;
+        } else {
+            throw new AuthenticationException("Unexpected state: " + this.state);
+        }
+        CharArrayBuffer buffer = new CharArrayBuffer(32);
+        if (isProxy()) {
+            buffer.append(AUTH.PROXY_AUTH_RESP);
+        } else {
+            buffer.append(AUTH.WWW_AUTH_RESP);
+        }
+        buffer.append(": NTLM ");
+        buffer.append(response);
+        return new BufferedHeader(buffer);
+    }
+
+    public boolean isComplete() {
+        return this.state == State.MSG_TYPE3_GENERATED || this.state == State.FAILED;
+    }
+
+}

Propchange: httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/auth/NTLMScheme.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/auth/NTLMScheme.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/auth/NTLMScheme.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/client/DefaultClientRequestDirector.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/client/DefaultClientRequestDirector.java?rev=655048&r1=655047&r2=655048&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/client/DefaultClientRequestDirector.java (original)
+++ httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/client/DefaultClientRequestDirector.java Sat May 10 04:22:12 2008
@@ -410,6 +410,9 @@
                         connManager.releaseConnection(managedConn);
                         managedConn = null;
                     }
+                    // In case we are going to retry the same request,
+                    // clear auto-generated headers
+                    followup.getRequest().clearHeaders();
                     roureq = followup;
                 }
             } // while not done

Modified: httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/client/RequestWrapper.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/client/RequestWrapper.java?rev=655048&r1=655047&r2=655048&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/client/RequestWrapper.java (original)
+++ httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/client/RequestWrapper.java Sat May 10 04:22:12 2008
@@ -141,4 +141,8 @@
         return this.original;
     }
     
+    public void clearHeaders() {
+        this.headergroup.clear();
+    }
+    
 }