diff --git a/hadoop-common-project/hadoop-common/CHANGES.txt b/hadoop-common-project/hadoop-common/CHANGES.txt index a7752ea5d9a..e709971d3ba 100644 --- a/hadoop-common-project/hadoop-common/CHANGES.txt +++ b/hadoop-common-project/hadoop-common/CHANGES.txt @@ -28,6 +28,8 @@ Release 2.0.3-alpha - Unreleased HADOOP-8851. Use -XX:+HeapDumpOnOutOfMemoryError JVM option in the forked tests. (Ivan A. Veselovsky via atm) + HADOOP-8783. Improve RPC.Server's digest auth (daryn) + OPTIMIZATIONS HADOOP-8866. SampleQuantiles#query is O(N^2) instead of O(N). (Andrew Wang diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ipc/Server.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ipc/Server.java index 3083ba9a41f..2ab08dbc542 100644 --- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ipc/Server.java +++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ipc/Server.java @@ -84,7 +84,6 @@ import org.apache.hadoop.security.SaslRpcServer.SaslDigestCallbackHandler; import org.apache.hadoop.security.SaslRpcServer.SaslGssCallbackHandler; import org.apache.hadoop.security.SaslRpcServer.SaslStatus; import org.apache.hadoop.security.UserGroupInformation; -import org.apache.hadoop.security.UserGroupInformation.AuthenticationMethod; import org.apache.hadoop.security.authorize.AuthorizationException; import org.apache.hadoop.security.authorize.PolicyProvider; import org.apache.hadoop.security.authorize.ProxyUsers; @@ -1333,20 +1332,38 @@ public abstract class Server { dataLengthBuffer.clear(); if (authMethod == null) { throw new IOException("Unable to read authentication method"); - } - if (isSecurityEnabled && authMethod == AuthMethod.SIMPLE) { - AccessControlException ae = new AccessControlException("Authorization (" - + CommonConfigurationKeys.HADOOP_SECURITY_AUTHORIZATION - + ") is enabled but authentication (" - + CommonConfigurationKeys.HADOOP_SECURITY_AUTHENTICATION - + ") is configured as simple. Please configure another method " - + "like kerberos or digest."); - setupResponse(authFailedResponse, authFailedCall, RpcStatusProto.FATAL, - null, ae.getClass().getName(), ae.getMessage()); - responder.doRespond(authFailedCall); - throw ae; - } - if (!isSecurityEnabled && authMethod != AuthMethod.SIMPLE) { + } + final boolean clientUsingSasl; + switch (authMethod) { + case SIMPLE: { // no sasl for simple + if (isSecurityEnabled) { + AccessControlException ae = new AccessControlException("Authorization (" + + CommonConfigurationKeys.HADOOP_SECURITY_AUTHORIZATION + + ") is enabled but authentication (" + + CommonConfigurationKeys.HADOOP_SECURITY_AUTHENTICATION + + ") is configured as simple. Please configure another method " + + "like kerberos or digest."); + setupResponse(authFailedResponse, authFailedCall, RpcStatusProto.FATAL, + null, ae.getClass().getName(), ae.getMessage()); + responder.doRespond(authFailedCall); + throw ae; + } + clientUsingSasl = false; + useSasl = false; + break; + } + case DIGEST: { + clientUsingSasl = true; + useSasl = (secretManager != null); + break; + } + default: { + clientUsingSasl = true; + useSasl = isSecurityEnabled; + break; + } + } + if (clientUsingSasl && !useSasl) { doSaslReply(SaslStatus.SUCCESS, new IntWritable( SaslRpcServer.SWITCH_TO_SIMPLE_AUTH), null, null); authMethod = AuthMethod.SIMPLE; @@ -1355,9 +1372,6 @@ public abstract class Server { // to simple auth from now on. skipInitialSaslHandshake = true; } - if (authMethod != AuthMethod.SIMPLE) { - useSasl = true; - } connectionHeaderBuf = null; connectionHeaderRead = true; @@ -1491,8 +1505,6 @@ public abstract class Server { UserGroupInformation realUser = user; user = UserGroupInformation.createProxyUser(protocolUser .getUserName(), realUser); - // Now the user is a proxy user, set Authentication method Proxy. - user.setAuthenticationMethod(AuthenticationMethod.PROXY); } } } @@ -1842,7 +1854,7 @@ public abstract class Server { // Create the responder here responder = new Responder(); - if (isSecurityEnabled) { + if (secretManager != null) { SaslRpcServer.init(conf); } } diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ipc/TestSaslRPC.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ipc/TestSaslRPC.java index db4a1465428..6744283d5de 100644 --- a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ipc/TestSaslRPC.java +++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ipc/TestSaslRPC.java @@ -60,6 +60,7 @@ import org.apache.hadoop.security.token.TokenInfo; import org.apache.hadoop.security.token.TokenSelector; import org.apache.hadoop.security.token.SecretManager.InvalidToken; import org.apache.log4j.Level; +import org.junit.BeforeClass; import org.junit.Test; /** Unit tests for using Sasl over RPC. */ @@ -76,7 +77,8 @@ public class TestSaslRPC { static final String SERVER_PRINCIPAL_2 = "p2/foo@BAR"; private static Configuration conf; - static { + @BeforeClass + public static void setup() { conf = new Configuration(); conf.set(HADOOP_SECURITY_AUTHENTICATION, "kerberos"); UserGroupInformation.setConfiguration(conf); @@ -449,11 +451,25 @@ public class TestSaslRPC { } @Test - public void testDigestAuthMethod() throws Exception { + public void testDigestAuthMethodSecureServer() throws Exception { + checkDigestAuthMethod(true); + } + + @Test + public void testDigestAuthMethodInsecureServer() throws Exception { + checkDigestAuthMethod(false); + } + + private void checkDigestAuthMethod(boolean secureServer) throws Exception { TestTokenSecretManager sm = new TestTokenSecretManager(); Server server = new RPC.Builder(conf).setProtocol(TestSaslProtocol.class) .setInstance(new TestSaslImpl()).setBindAddress(ADDRESS).setPort(0) .setNumHandlers(5).setVerbose(true).setSecretManager(sm).build(); + if (secureServer) { + server.enableSecurity(); + } else { + server.disableSecurity(); + } server.start(); final UserGroupInformation current = UserGroupInformation.getCurrentUser();