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.security;
019
020import java.net.InetAddress;
021import java.util.Locale;
022import java.util.Map;
023import java.util.TreeMap;
024
025import javax.security.sasl.Sasl;
026
027import org.apache.hadoop.conf.Configurable;
028import org.apache.hadoop.conf.Configuration;
029import org.apache.hadoop.fs.CommonConfigurationKeysPublic;
030import org.apache.hadoop.security.SaslRpcServer.QualityOfProtection;
031import org.apache.hadoop.util.ReflectionUtils;
032import org.apache.hadoop.util.StringUtils;
033
034/**
035 * Provides SaslProperties to be used for a connection.
036 * The default implementation is to read the values from configuration.
037 * This class can be overridden to provide custom SaslProperties. 
038 * The custom class can be specified via configuration.
039 *
040 */
041public class SaslPropertiesResolver implements Configurable{
042  private Map<String,String> properties;
043  Configuration conf;
044
045  /**
046   * Returns an instance of SaslPropertiesResolver.
047   * Looks up the configuration to see if there is custom class specified.
048   * Constructs the instance by passing the configuration directly to the
049   * constructor to achieve thread safety using final fields.
050   * @param conf
051   * @return SaslPropertiesResolver
052   */
053  public static SaslPropertiesResolver getInstance(Configuration conf) {
054    Class<? extends SaslPropertiesResolver> clazz =
055      conf.getClass(
056          CommonConfigurationKeysPublic.HADOOP_SECURITY_SASL_PROPS_RESOLVER_CLASS,
057          SaslPropertiesResolver.class, SaslPropertiesResolver.class);
058    return ReflectionUtils.newInstance(clazz, conf);
059  }
060
061  @Override
062  public void setConf(Configuration conf) {
063    this.conf = conf;
064    properties = new TreeMap<String,String>();
065    String[] qop = conf.getTrimmedStrings(
066        CommonConfigurationKeysPublic.HADOOP_RPC_PROTECTION,
067        QualityOfProtection.AUTHENTICATION.toString());
068    for (int i=0; i < qop.length; i++) {
069      qop[i] = QualityOfProtection.valueOf(
070          StringUtils.toUpperCase(qop[i])).getSaslQop();
071    }
072    properties.put(Sasl.QOP, StringUtils.join(",", qop));
073    properties.put(Sasl.SERVER_AUTH, "true");
074  }
075
076  @Override
077  public Configuration getConf() {
078    return conf;
079  }
080
081  /**
082   * The default Sasl Properties read from the configuration
083   * @return sasl Properties
084   */
085  public Map<String,String> getDefaultProperties() {
086    return properties;
087  }
088
089  /**
090   * Identify the Sasl Properties to be used for a connection with a  client.
091   * @param clientAddress client's address
092   * @return the sasl properties to be used for the connection.
093   */
094  public Map<String, String> getServerProperties(InetAddress clientAddress){
095    return properties;
096  }
097
098  /**
099   * Identify the Sasl Properties to be used for a connection with a server.
100   * @param serverAddress server's address
101   * @return the sasl properties to be used for the connection.
102   */
103  public Map<String, String> getClientProperties(InetAddress serverAddress){
104    return properties;
105  }
106}