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 2011/10/10 17:17:26 UTC

svn commit: r1181015 - /httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/auth/NegotiateScheme.java

Author: olegk
Date: Mon Oct 10 15:17:26 2011
New Revision: 1181015

URL: http://svn.apache.org/viewvc?rev=1181015&view=rev
Log:
Better state handling in NegotiateScheme#authenticate

Modified:
    httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/auth/NegotiateScheme.java

Modified: httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/auth/NegotiateScheme.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/auth/NegotiateScheme.java?rev=1181015&r1=1181014&r2=1181015&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/auth/NegotiateScheme.java (original)
+++ httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/auth/NegotiateScheme.java Mon Oct 10 15:17:26 2011
@@ -152,124 +152,129 @@ public class NegotiateScheme extends Aut
         if (request == null) {
             throw new IllegalArgumentException("HTTP request may not be null");
         }
-        if (state != State.CHALLENGE_RECEIVED) {
-            throw new IllegalStateException(
-                    "Negotiation authentication process has not been initiated");
-        }
-        try {
-            String key = null;
-            if (isProxy()) {
-                key = ExecutionContext.HTTP_PROXY_HOST;
-            } else {
-                key = ExecutionContext.HTTP_TARGET_HOST;
-            }
-            HttpHost host = (HttpHost) context.getAttribute(key);
-            if (host == null) {
-                throw new AuthenticationException("Authentication host is not set " +
-                        "in the execution context");
-            }
-            String authServer;
-            if (!this.stripPort && host.getPort() > 0) {
-                authServer = host.toHostString();
-            } else {
-                authServer = host.getHostName();
-            }
+        switch (state) {
+        case UNINITIATED:
+            throw new AuthenticationException("SPNEGO authentication has not been initiated");
+        case FAILED:
+            throw new AuthenticationException("SPNEGO authentication has failed");
+        case CHALLENGE_RECEIVED:
+            try {
+                String key = null;
+                if (isProxy()) {
+                    key = ExecutionContext.HTTP_PROXY_HOST;
+                } else {
+                    key = ExecutionContext.HTTP_TARGET_HOST;
+                }
+                HttpHost host = (HttpHost) context.getAttribute(key);
+                if (host == null) {
+                    throw new AuthenticationException("Authentication host is not set " +
+                            "in the execution context");
+                }
+                String authServer;
+                if (!this.stripPort && host.getPort() > 0) {
+                    authServer = host.toHostString();
+                } else {
+                    authServer = host.getHostName();
+                }
 
-            if (log.isDebugEnabled()) {
-                log.debug("init " + authServer);
-            }
-            /* Using the SPNEGO OID is the correct method.
-             * Kerberos v5 works for IIS but not JBoss. Unwrapping
-             * the initial token when using SPNEGO OID looks like what is
-             * described here...
-             *
-             * http://msdn.microsoft.com/en-us/library/ms995330.aspx
-             *
-             * Another helpful URL...
-             *
-             * http://publib.boulder.ibm.com/infocenter/wasinfo/v7r0/index.jsp?topic=/com.ibm.websphere.express.doc/info/exp/ae/tsec_SPNEGO_token.html
-             *
-             * Unfortunately SPNEGO is JRE >=1.6.
-             */
+                if (log.isDebugEnabled()) {
+                    log.debug("init " + authServer);
+                }
+                /* Using the SPNEGO OID is the correct method.
+                 * Kerberos v5 works for IIS but not JBoss. Unwrapping
+                 * the initial token when using SPNEGO OID looks like what is
+                 * described here...
+                 *
+                 * http://msdn.microsoft.com/en-us/library/ms995330.aspx
+                 *
+                 * Another helpful URL...
+                 *
+                 * http://publib.boulder.ibm.com/infocenter/wasinfo/v7r0/index.jsp?topic=/com.ibm.websphere.express.doc/info/exp/ae/tsec_SPNEGO_token.html
+                 *
+                 * Unfortunately SPNEGO is JRE >=1.6.
+                 */
+
+                /** Try SPNEGO by default, fall back to Kerberos later if error */
+                negotiationOid  = new Oid(SPNEGO_OID);
+
+                boolean tryKerberos = false;
+                try {
+                    GSSManager manager = getManager();
+                    GSSName serverName = manager.createName("HTTP@" + authServer, GSSName.NT_HOSTBASED_SERVICE);
+                    gssContext = manager.createContext(
+                            serverName.canonicalize(negotiationOid), negotiationOid, null,
+                            GSSContext.DEFAULT_LIFETIME);
+                    gssContext.requestMutualAuth(true);
+                    gssContext.requestCredDeleg(true);
+                } catch (GSSException ex){
+                    // BAD MECH means we are likely to be using 1.5, fall back to Kerberos MECH.
+                    // Rethrow any other exception.
+                    if (ex.getMajor() == GSSException.BAD_MECH ){
+                        log.debug("GSSException BAD_MECH, retry with Kerberos MECH");
+                        tryKerberos = true;
+                    } else {
+                        throw ex;
+                    }
 
-            /** Try SPNEGO by default, fall back to Kerberos later if error */
-            negotiationOid  = new Oid(SPNEGO_OID);
+                }
+                if (tryKerberos){
+                    /* Kerberos v5 GSS-API mechanism defined in RFC 1964.*/
+                    log.debug("Using Kerberos MECH " + KERBEROS_OID);
+                    negotiationOid  = new Oid(KERBEROS_OID);
+                    GSSManager manager = getManager();
+                    GSSName serverName = manager.createName("HTTP@" + authServer, GSSName.NT_HOSTBASED_SERVICE);
+                    gssContext = manager.createContext(
+                            serverName.canonicalize(negotiationOid), negotiationOid, null,
+                            GSSContext.DEFAULT_LIFETIME);
+                    gssContext.requestMutualAuth(true);
+                    gssContext.requestCredDeleg(true);
+                }
+                if (token == null) {
+                    token = new byte[0];
+                }
+                token = gssContext.initSecContext(token, 0, token.length);
+                if (token == null) {
+                    state = State.FAILED;
+                    throw new AuthenticationException("GSS security context initialization failed");
+                }
 
-            boolean tryKerberos = false;
-            try {
-                GSSManager manager = getManager();
-                GSSName serverName = manager.createName("HTTP@" + authServer, GSSName.NT_HOSTBASED_SERVICE);
-                gssContext = manager.createContext(
-                        serverName.canonicalize(negotiationOid), negotiationOid, null,
-                        GSSContext.DEFAULT_LIFETIME);
-                gssContext.requestMutualAuth(true);
-                gssContext.requestCredDeleg(true);
-            } catch (GSSException ex){
-                // BAD MECH means we are likely to be using 1.5, fall back to Kerberos MECH.
-                // Rethrow any other exception.
-                if (ex.getMajor() == GSSException.BAD_MECH ){
-                    log.debug("GSSException BAD_MECH, retry with Kerberos MECH");
-                    tryKerberos = true;
-                } else {
-                    throw ex;
+                /*
+                 * IIS accepts Kerberos and SPNEGO tokens. Some other servers Jboss, Glassfish?
+                 * seem to only accept SPNEGO. Below wraps Kerberos into SPNEGO token.
+                 */
+                if (spengoGenerator != null && negotiationOid.toString().equals(KERBEROS_OID)) {
+                    token = spengoGenerator.generateSpnegoDERObject(token);
                 }
 
-            }
-            if (tryKerberos){
-                /* Kerberos v5 GSS-API mechanism defined in RFC 1964.*/
-                log.debug("Using Kerberos MECH " + KERBEROS_OID);
-                negotiationOid  = new Oid(KERBEROS_OID);
-                GSSManager manager = getManager();
-                GSSName serverName = manager.createName("HTTP@" + authServer, GSSName.NT_HOSTBASED_SERVICE);
-                gssContext = manager.createContext(
-                        serverName.canonicalize(negotiationOid), negotiationOid, null,
-                        GSSContext.DEFAULT_LIFETIME);
-                gssContext.requestMutualAuth(true);
-                gssContext.requestCredDeleg(true);
-            }
-            if (token == null) {
-                token = new byte[0];
-            }
-            token = gssContext.initSecContext(token, 0, token.length);
-            if (token == null) {
+                state = State.TOKEN_GENERATED;
+            } catch (GSSException gsse) {
                 state = State.FAILED;
-                throw new AuthenticationException("GSS security context initialization failed");
-            }
-
-            /*
-             * IIS accepts Kerberos and SPNEGO tokens. Some other servers Jboss, Glassfish?
-             * seem to only accept SPNEGO. Below wraps Kerberos into SPNEGO token.
-             */
-            if (spengoGenerator != null && negotiationOid.toString().equals(KERBEROS_OID)) {
-                token = spengoGenerator.generateSpnegoDERObject(token);
+                if (gsse.getMajor() == GSSException.DEFECTIVE_CREDENTIAL
+                        || gsse.getMajor() == GSSException.CREDENTIALS_EXPIRED)
+                    throw new InvalidCredentialsException(gsse.getMessage(), gsse);
+                if (gsse.getMajor() == GSSException.NO_CRED )
+                    throw new InvalidCredentialsException(gsse.getMessage(), gsse);
+                if (gsse.getMajor() == GSSException.DEFECTIVE_TOKEN
+                        || gsse.getMajor() == GSSException.DUPLICATE_TOKEN
+                        || gsse.getMajor() == GSSException.OLD_TOKEN)
+                    throw new AuthenticationException(gsse.getMessage(), gsse);
+                // other error
+                throw new AuthenticationException(gsse.getMessage());
+            } catch (IOException ex){
+                state = State.FAILED;
+                throw new AuthenticationException(ex.getMessage());
             }
-
-            state = State.TOKEN_GENERATED;
+        case TOKEN_GENERATED:
             String tokenstr = new String(Base64.encodeBase64(token, false));
             if (log.isDebugEnabled()) {
                 log.debug("Sending response '" + tokenstr + "' back to the auth server");
             }
             return new BasicHeader("Authorization", "Negotiate " + tokenstr);
-        } catch (GSSException gsse) {
-            state = State.FAILED;
-            if (gsse.getMajor() == GSSException.DEFECTIVE_CREDENTIAL
-                    || gsse.getMajor() == GSSException.CREDENTIALS_EXPIRED)
-                throw new InvalidCredentialsException(gsse.getMessage(), gsse);
-            if (gsse.getMajor() == GSSException.NO_CRED )
-                throw new InvalidCredentialsException(gsse.getMessage(), gsse);
-            if (gsse.getMajor() == GSSException.DEFECTIVE_TOKEN
-                    || gsse.getMajor() == GSSException.DUPLICATE_TOKEN
-                    || gsse.getMajor() == GSSException.OLD_TOKEN)
-                throw new AuthenticationException(gsse.getMessage(), gsse);
-            // other error
-            throw new AuthenticationException(gsse.getMessage());
-        } catch (IOException ex){
-            state = State.FAILED;
-            throw new AuthenticationException(ex.getMessage());
+        default:
+            throw new IllegalStateException("Illegal state: " + state);
         }
     }
 
-
     /**
      * Returns the authentication parameter with the given name, if available.
      *