Repository: hbase Updated Branches: refs/heads/0.96 bd5922729 -> 6ea0b7f8c refs/heads/0.98 230a768a3 -> 7caceb23c refs/heads/master 9dcebc396 -> b168b8b2d
HBASE-11149 Wire encryption is broken (Devaraj Das) Project: http://git-wip-us.apache.org/repos/asf/hbase/repo Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/6ea0b7f8 Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/6ea0b7f8 Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/6ea0b7f8 Branch: refs/heads/0.96 Commit: 6ea0b7f8c2af72c6fd379f04e2d7145928e237ad Parents: bd59227 Author: Andrew Purtell <[email protected]> Authored: Thu May 22 18:21:30 2014 -0700 Committer: Andrew Purtell <[email protected]> Committed: Thu May 22 18:43:48 2014 -0700 ---------------------------------------------------------------------- .../org/apache/hadoop/hbase/ipc/RpcClient.java | 5 +- .../hbase/security/HBaseSaslRpcClient.java | 27 +++++++- .../apache/hadoop/hbase/security/SaslUtil.java | 32 +++++++++ .../hbase/security/HBaseSaslRpcServer.java | 33 +-------- .../hbase/security/TestHBaseSaslRpcClient.java | 72 ++++++++++++++++++++ 5 files changed, 137 insertions(+), 32 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/hbase/blob/6ea0b7f8/hbase-client/src/main/java/org/apache/hadoop/hbase/ipc/RpcClient.java ---------------------------------------------------------------------- diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/ipc/RpcClient.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/ipc/RpcClient.java index 90fe601..1615732 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/ipc/RpcClient.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/ipc/RpcClient.java @@ -72,6 +72,7 @@ import org.apache.hadoop.hbase.protobuf.generated.RPCProtos.UserInformation; import org.apache.hadoop.hbase.protobuf.generated.TracingProtos.RPCTInfo; import org.apache.hadoop.hbase.security.AuthMethod; import org.apache.hadoop.hbase.security.HBaseSaslRpcClient; +import org.apache.hadoop.hbase.security.SaslUtil.QualityOfProtection; import org.apache.hadoop.hbase.security.SecurityInfo; import org.apache.hadoop.hbase.security.User; import org.apache.hadoop.hbase.security.UserProvider; @@ -759,7 +760,9 @@ private UserProvider userProvider; private synchronized boolean setupSaslConnection(final InputStream in2, final OutputStream out2) throws IOException { - saslRpcClient = new HBaseSaslRpcClient(authMethod, token, serverPrincipal, fallbackAllowed); + saslRpcClient = new HBaseSaslRpcClient(authMethod, token, serverPrincipal, fallbackAllowed, + conf.get("hbase.rpc.protection", + QualityOfProtection.AUTHENTICATION.name().toLowerCase())); return saslRpcClient.saslConnect(in2, out2); } http://git-wip-us.apache.org/repos/asf/hbase/blob/6ea0b7f8/hbase-client/src/main/java/org/apache/hadoop/hbase/security/HBaseSaslRpcClient.java ---------------------------------------------------------------------- diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/security/HBaseSaslRpcClient.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/security/HBaseSaslRpcClient.java index 41acb4f..a591747 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/security/HBaseSaslRpcClient.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/security/HBaseSaslRpcClient.java @@ -54,7 +54,6 @@ public class HBaseSaslRpcClient { private final SaslClient saslClient; private final boolean fallbackAllowed; - /** * Create a HBaseSaslRpcClient for an authentication method * @@ -62,11 +61,37 @@ public class HBaseSaslRpcClient { * the requested authentication method * @param token * token to use if needed by the authentication method + * @param serverPrincipal + * the server principal that we are trying to set the connection up to + * @param fallbackAllowed + * does the client allow fallback to simple authentication + * @throws IOException */ public HBaseSaslRpcClient(AuthMethod method, Token<? extends TokenIdentifier> token, String serverPrincipal, boolean fallbackAllowed) throws IOException { + this(method, token, serverPrincipal, fallbackAllowed, "authentication"); + } + /** + * Create a HBaseSaslRpcClient for an authentication method + * + * @param method + * the requested authentication method + * @param token + * token to use if needed by the authentication method + * @param serverPrincipal + * the server principal that we are trying to set the connection up to + * @param fallbackAllowed + * does the client allow fallback to simple authentication + * @param rpcProtection + * the protection level ("authentication", "integrity" or "privacy") + * @throws IOException + */ + public HBaseSaslRpcClient(AuthMethod method, + Token<? extends TokenIdentifier> token, String serverPrincipal, boolean fallbackAllowed, + String rpcProtection) throws IOException { this.fallbackAllowed = fallbackAllowed; + SaslUtil.initSaslProperties(rpcProtection); switch (method) { case DIGEST: if (LOG.isDebugEnabled()) http://git-wip-us.apache.org/repos/asf/hbase/blob/6ea0b7f8/hbase-client/src/main/java/org/apache/hadoop/hbase/security/SaslUtil.java ---------------------------------------------------------------------- diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/security/SaslUtil.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/security/SaslUtil.java index 42e21be..351052b 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/security/SaslUtil.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/security/SaslUtil.java @@ -23,12 +23,30 @@ import org.apache.commons.codec.binary.Base64; import java.util.Map; import java.util.TreeMap; +import javax.security.sasl.Sasl; + public class SaslUtil { public static final String SASL_DEFAULT_REALM = "default"; public static final Map<String, String> SASL_PROPS = new TreeMap<String, String>(); public static final int SWITCH_TO_SIMPLE_AUTH = -88; + public static enum QualityOfProtection { + AUTHENTICATION("auth"), + INTEGRITY("auth-int"), + PRIVACY("auth-conf"); + + public final String saslQop; + + private QualityOfProtection(String saslQop) { + this.saslQop = saslQop; + } + + public String getSaslQop() { + return saslQop; + } + } + /** Splitting fully qualified Kerberos name into parts */ public static String[] splitKerberosName(String fullName) { return fullName.split("[/@]"); @@ -45,4 +63,18 @@ public class SaslUtil { static char[] encodePassword(byte[] password) { return new String(Base64.encodeBase64(password)).toCharArray(); } + + static void initSaslProperties(String rpcProtection) { + QualityOfProtection saslQOP = QualityOfProtection.AUTHENTICATION; + if (QualityOfProtection.INTEGRITY.name().toLowerCase() + .equals(rpcProtection)) { + saslQOP = QualityOfProtection.INTEGRITY; + } else if (QualityOfProtection.PRIVACY.name().toLowerCase().equals( + rpcProtection)) { + saslQOP = QualityOfProtection.PRIVACY; + } + + SaslUtil.SASL_PROPS.put(Sasl.QOP, saslQOP.getSaslQop()); + SaslUtil.SASL_PROPS.put(Sasl.SERVER_AUTH, "true"); + } } http://git-wip-us.apache.org/repos/asf/hbase/blob/6ea0b7f8/hbase-server/src/main/java/org/apache/hadoop/hbase/security/HBaseSaslRpcServer.java ---------------------------------------------------------------------- diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/HBaseSaslRpcServer.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/HBaseSaslRpcServer.java index 514fee3..2dd94d6 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/security/HBaseSaslRpcServer.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/security/HBaseSaslRpcServer.java @@ -29,12 +29,12 @@ import javax.security.auth.callback.PasswordCallback; import javax.security.auth.callback.UnsupportedCallbackException; import javax.security.sasl.AuthorizeCallback; import javax.security.sasl.RealmCallback; -import javax.security.sasl.Sasl; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.ipc.RpcServer; +import org.apache.hadoop.hbase.security.SaslUtil.QualityOfProtection; import org.apache.hadoop.security.UserGroupInformation; import org.apache.hadoop.security.token.SecretManager; import org.apache.hadoop.security.token.TokenIdentifier; @@ -46,36 +46,9 @@ import org.apache.hadoop.security.token.SecretManager.InvalidToken; public class HBaseSaslRpcServer { public static final Log LOG = LogFactory.getLog(HBaseSaslRpcServer.class); - public static enum QualityOfProtection { - AUTHENTICATION("auth"), - INTEGRITY("auth-int"), - PRIVACY("auth-conf"); - - public final String saslQop; - - private QualityOfProtection(String saslQop) { - this.saslQop = saslQop; - } - - public String getSaslQop() { - return saslQop; - } - } - public static void init(Configuration conf) { - QualityOfProtection saslQOP = QualityOfProtection.AUTHENTICATION; - String rpcProtection = conf.get("hbase.rpc.protection", - QualityOfProtection.AUTHENTICATION.name().toLowerCase()); - if (QualityOfProtection.INTEGRITY.name().toLowerCase() - .equals(rpcProtection)) { - saslQOP = QualityOfProtection.INTEGRITY; - } else if (QualityOfProtection.PRIVACY.name().toLowerCase().equals( - rpcProtection)) { - saslQOP = QualityOfProtection.PRIVACY; - } - - SaslUtil.SASL_PROPS.put(Sasl.QOP, saslQOP.getSaslQop()); - SaslUtil.SASL_PROPS.put(Sasl.SERVER_AUTH, "true"); + SaslUtil.initSaslProperties(conf.get("hbase.rpc.protection", + QualityOfProtection.AUTHENTICATION.name().toLowerCase())); } public static <T extends TokenIdentifier> T getIdentifier(String id, http://git-wip-us.apache.org/repos/asf/hbase/blob/6ea0b7f8/hbase-server/src/test/java/org/apache/hadoop/hbase/security/TestHBaseSaslRpcClient.java ---------------------------------------------------------------------- diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/security/TestHBaseSaslRpcClient.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/TestHBaseSaslRpcClient.java new file mode 100644 index 0000000..ab43b63 --- /dev/null +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/security/TestHBaseSaslRpcClient.java @@ -0,0 +1,72 @@ +/* + * + * 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. + */ +package org.apache.hadoop.hbase.security; + +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; + +import javax.security.sasl.Sasl; + +import org.apache.hadoop.hbase.SmallTests; +import org.apache.hadoop.security.token.Token; +import org.apache.hadoop.security.token.TokenIdentifier; +import org.apache.log4j.Level; +import org.apache.log4j.Logger; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.experimental.categories.Category; + +@Category(SmallTests.class) +public class TestHBaseSaslRpcClient { + + static { + System.setProperty("java.security.krb5.realm", "DOMAIN.COM"); + System.setProperty("java.security.krb5.kdc", "DOMAIN.COM"); + } + + static final String DEFAULT_USER_NAME = "principal"; + static final String DEFAULT_USER_PASSWORD = "password"; + + @BeforeClass + public static void before() { + Logger.getRootLogger().setLevel(Level.DEBUG); + } + + @Test + public void testSaslQOPNotEmpty() throws Exception { + // default QOP is authentication + new HBaseSaslRpcClient(AuthMethod.KERBEROS, createTokenMock(), "principal/[email protected]", false); + assertTrue(SaslUtil.SASL_PROPS.get(Sasl.QOP).equals(SaslUtil.QualityOfProtection.AUTHENTICATION.getSaslQop())); + + // check with specific QOPs + new HBaseSaslRpcClient(AuthMethod.KERBEROS, createTokenMock(), "principal/[email protected]", false, "authentication"); + assertTrue(SaslUtil.SASL_PROPS.get(Sasl.QOP).equals(SaslUtil.QualityOfProtection.AUTHENTICATION.getSaslQop())); + + new HBaseSaslRpcClient(AuthMethod.KERBEROS, createTokenMock(), "principal/[email protected]", false, "privacy"); + assertTrue(SaslUtil.SASL_PROPS.get(Sasl.QOP).equals(SaslUtil.QualityOfProtection.PRIVACY.getSaslQop())); + + new HBaseSaslRpcClient(AuthMethod.KERBEROS, createTokenMock(), "principal/[email protected]", false, "integrity"); + assertTrue(SaslUtil.SASL_PROPS.get(Sasl.QOP).equals(SaslUtil.QualityOfProtection.INTEGRITY.getSaslQop())); + } + + @SuppressWarnings("unchecked") + private Token<? extends TokenIdentifier> createTokenMock() { + return mock(Token.class); + } +}
