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.ByteArrayInputStream;
021import java.io.DataInputStream;
022import java.io.IOException;
023import java.util.Map;
024import java.util.Optional;
025
026import javax.security.sasl.Sasl;
027import javax.security.sasl.SaslException;
028import javax.security.sasl.SaslServer;
029
030import org.apache.hadoop.hbase.security.provider.AttemptingUserProvidingSaslServer;
031import org.apache.hadoop.hbase.security.provider.SaslServerAuthenticationProvider;
032import org.apache.hadoop.security.UserGroupInformation;
033import org.apache.hadoop.security.token.SecretManager;
034import org.apache.hadoop.security.token.SecretManager.InvalidToken;
035import org.apache.hadoop.security.token.TokenIdentifier;
036import org.apache.yetus.audience.InterfaceAudience;
037
038/**
039 * A utility class that encapsulates SASL logic for RPC server. Copied from
040 * <code>org.apache.hadoop.security</code>
041 */
042@InterfaceAudience.Private
043public class HBaseSaslRpcServer {
044
045  private final AttemptingUserProvidingSaslServer serverWithProvider;
046  private final SaslServer saslServer;
047
048  public HBaseSaslRpcServer(SaslServerAuthenticationProvider provider,
049      Map<String, String> saslProps, SecretManager<TokenIdentifier> secretManager)
050          throws IOException {
051    serverWithProvider = provider.createServer(secretManager, saslProps);
052    saslServer = serverWithProvider.getServer();
053  }
054
055  public boolean isComplete() {
056    return saslServer.isComplete();
057  }
058
059  public byte[] evaluateResponse(byte[] response) throws SaslException {
060    return saslServer.evaluateResponse(response);
061  }
062
063  /** Release resources used by wrapped saslServer */
064  public void dispose() {
065    SaslUtil.safeDispose(saslServer);
066  }
067
068  public String getAttemptingUser() {
069    Optional<UserGroupInformation> optionalUser = serverWithProvider.getAttemptingUser();
070    if (optionalUser.isPresent()) {
071      optionalUser.get().toString();
072    }
073    return "Unknown";
074  }
075
076  public byte[] wrap(byte[] buf, int off, int len) throws SaslException {
077    return saslServer.wrap(buf, off, len);
078  }
079
080  public byte[] unwrap(byte[] buf, int off, int len) throws SaslException {
081    return saslServer.unwrap(buf, off, len);
082  }
083
084  public String getNegotiatedQop() {
085    return (String) saslServer.getNegotiatedProperty(Sasl.QOP);
086  }
087
088  public String getAuthorizationID() {
089    return saslServer.getAuthorizationID();
090  }
091
092  public static <T extends TokenIdentifier> T getIdentifier(String id,
093      SecretManager<T> secretManager) throws InvalidToken {
094    byte[] tokenId = SaslUtil.decodeIdentifier(id);
095    T tokenIdentifier = secretManager.createIdentifier();
096    try {
097      tokenIdentifier.readFields(new DataInputStream(new ByteArrayInputStream(tokenId)));
098    } catch (IOException e) {
099      throw (InvalidToken) new InvalidToken("Can't de-serialize tokenIdentifier").initCause(e);
100    }
101    return tokenIdentifier;
102  }
103}