From a7d4f30131b374baaa1efba22c7ae8e80c000f45 Mon Sep 17 00:00:00 2001 From: Daryn Sharp Date: Wed, 3 Oct 2012 13:43:53 +0000 Subject: [PATCH] HADOOP-8783. Improve RPC.Server's digest auth (daryn) git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1393483 13f79535-47bb-0310-9956-ffa450edef68 --- .../hadoop-common/CHANGES.txt | 2 + .../java/org/apache/hadoop/ipc/Server.java | 54 +++++++++++-------- .../org/apache/hadoop/ipc/TestSaslRPC.java | 20 ++++++- 3 files changed, 53 insertions(+), 23 deletions(-) diff --git a/hadoop-common-project/hadoop-common/CHANGES.txt b/hadoop-common-project/hadoop-common/CHANGES.txt index 3b10f00c0c..dee2d9dba0 100644 --- a/hadoop-common-project/hadoop-common/CHANGES.txt +++ b/hadoop-common-project/hadoop-common/CHANGES.txt @@ -288,6 +288,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 66c81c2da0..bb2c2055e5 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 @@ -87,7 +87,6 @@ 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; @@ -1374,20 +1373,38 @@ public int readAndProcess() throws IOException, InterruptedException { 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; @@ -1396,9 +1413,6 @@ public int readAndProcess() throws IOException, InterruptedException { // to simple auth from now on. skipInitialSaslHandshake = true; } - if (authMethod != AuthMethod.SIMPLE) { - useSasl = true; - } connectionHeaderBuf = null; connectionHeaderRead = true; @@ -1532,8 +1546,6 @@ private void processConnectionContext(byte[] buf) throws IOException { UserGroupInformation realUser = user; user = UserGroupInformation.createProxyUser(protocolUser .getUserName(), realUser); - // Now the user is a proxy user, set Authentication method Proxy. - user.setAuthenticationMethod(AuthenticationMethod.PROXY); } } } @@ -1883,7 +1895,7 @@ protected Server(String bindAddress, int port, // 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 fed7051f97..5207879521 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.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 @@ static void testKerberosRpc(String principal, String keytab) throws Exception { } @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();