001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.security; 019 020import java.io.IOException; 021import java.net.InetAddress; 022import java.util.Map; 023import javax.security.sasl.SaslClient; 024import javax.security.sasl.SaslException; 025import org.apache.hadoop.conf.Configuration; 026import org.apache.hadoop.hbase.security.provider.SaslClientAuthenticationProvider; 027import org.apache.hadoop.security.token.Token; 028import org.apache.hadoop.security.token.TokenIdentifier; 029import org.apache.yetus.audience.InterfaceAudience; 030 031/** 032 * A utility class that encapsulates SASL logic for RPC client. Copied from 033 * <code>org.apache.hadoop.security</code> 034 * @since 2.0.0 035 */ 036@InterfaceAudience.Private 037public abstract class AbstractHBaseSaslRpcClient { 038 private static final byte[] EMPTY_TOKEN = new byte[0]; 039 040 protected final SaslClient saslClient; 041 042 protected final boolean fallbackAllowed; 043 044 protected final Map<String, String> saslProps; 045 046 /** 047 * Create a HBaseSaslRpcClient for an authentication method 048 * @param conf the configuration object 049 * @param provider the authentication provider 050 * @param token token to use if needed by the authentication method 051 * @param serverAddr the address of the hbase service 052 * @param servicePrincipal the service principal to use if needed by the authentication method 053 * @param fallbackAllowed does the client allow fallback to simple authentication 054 */ 055 protected AbstractHBaseSaslRpcClient(Configuration conf, 056 SaslClientAuthenticationProvider provider, Token<? extends TokenIdentifier> token, 057 InetAddress serverAddr, String servicePrincipal, boolean fallbackAllowed) throws IOException { 058 this(conf, provider, token, serverAddr, servicePrincipal, fallbackAllowed, "authentication"); 059 } 060 061 /** 062 * Create a HBaseSaslRpcClient for an authentication method 063 * @param conf configuration object 064 * @param provider the authentication provider 065 * @param token token to use if needed by the authentication method 066 * @param serverAddr the address of the hbase service 067 * @param servicePrincipal the service principal to use if needed by the authentication method 068 * @param fallbackAllowed does the client allow fallback to simple authentication 069 * @param rpcProtection the protection level ("authentication", "integrity" or "privacy") 070 */ 071 protected AbstractHBaseSaslRpcClient(Configuration conf, 072 SaslClientAuthenticationProvider provider, Token<? extends TokenIdentifier> token, 073 InetAddress serverAddr, String servicePrincipal, boolean fallbackAllowed, String rpcProtection) 074 throws IOException { 075 this.fallbackAllowed = fallbackAllowed; 076 saslProps = SaslUtil.initSaslProperties(rpcProtection); 077 078 saslClient = 079 provider.createClient(conf, serverAddr, servicePrincipal, token, fallbackAllowed, saslProps); 080 if (saslClient == null) { 081 throw new IOException( 082 "Authentication provider " + provider.getClass() + " returned a null SaslClient"); 083 } 084 } 085 086 /** 087 * Computes the initial response a client sends to a server to begin the SASL challenge/response 088 * handshake. If the client's SASL mechanism does not have an initial response, an empty token 089 * will be returned without querying the evaluateChallenge method, as an authentication processing 090 * must be started by client. 091 * @return The client's initial response to send the server (which may be empty). 092 */ 093 public byte[] getInitialResponse() throws SaslException { 094 if (saslClient.hasInitialResponse()) { 095 return saslClient.evaluateChallenge(EMPTY_TOKEN); 096 } 097 return EMPTY_TOKEN; 098 } 099 100 public boolean isComplete() { 101 return saslClient.isComplete(); 102 } 103 104 public byte[] evaluateChallenge(byte[] challenge) throws SaslException { 105 return saslClient.evaluateChallenge(challenge); 106 } 107 108 /** Release resources used by wrapped saslClient */ 109 public void dispose() { 110 SaslUtil.safeDispose(saslClient); 111 } 112}