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