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