Coverage Report - org.apache.giraph.comm.netty.SaslNettyServer
 
Classes in this File Line Coverage Branch Coverage Complexity
SaslNettyServer
0%
0/36
0%
0/6
3.333
SaslNettyServer$SaslDigestCallbackHandler
0%
0/40
0%
0/26
3.333
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one
 3  
  * or more contributor license agreements.  See the NOTICE file
 4  
  * distributed with this work for additional information
 5  
  * regarding copyright ownership.  The ASF licenses this file
 6  
  * to you under the Apache License, Version 2.0 (the
 7  
  * "License"); you may not use this file except in compliance
 8  
  * with the License.  You may obtain a copy of the License at
 9  
  *
 10  
  *     http://www.apache.org/licenses/LICENSE-2.0
 11  
  *
 12  
  * Unless required by applicable law or agreed to in writing, software
 13  
  * distributed under the License is distributed on an "AS IS" BASIS,
 14  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 15  
  * See the License for the specific language governing permissions and
 16  
  * limitations under the License.
 17  
  */
 18  
 package org.apache.giraph.comm.netty;
 19  
 
 20  
 import org.apache.commons.net.util.Base64;
 21  
 import org.apache.hadoop.classification.InterfaceStability;
 22  
 /*if_not[STATIC_SASL_SYMBOL]*/
 23  
 import org.apache.hadoop.conf.Configuration;
 24  
 /*end[STATIC_SASL_SYMBOL]*/
 25  
 /*if[HADOOP_1_SECURITY]
 26  
 else[HADOOP_1_SECURITY]*/
 27  
 import org.apache.hadoop.ipc.StandbyException;
 28  
 /*end[HADOOP_1_SECURITY]*/
 29  
 import org.apache.hadoop.mapreduce.security.token.JobTokenIdentifier;
 30  
 import org.apache.hadoop.mapreduce.security.token.JobTokenSecretManager;
 31  
 /*if_not[STATIC_SASL_SYMBOL]*/
 32  
 import org.apache.hadoop.security.SaslPropertiesResolver;
 33  
 /*end[STATIC_SASL_SYMBOL]*/
 34  
 import org.apache.hadoop.security.SaslRpcServer;
 35  
 import org.apache.log4j.Logger;
 36  
 
 37  
 import javax.security.auth.callback.Callback;
 38  
 import javax.security.auth.callback.CallbackHandler;
 39  
 import javax.security.auth.callback.NameCallback;
 40  
 import javax.security.auth.callback.PasswordCallback;
 41  
 import javax.security.auth.callback.UnsupportedCallbackException;
 42  
 import javax.security.sasl.AuthorizeCallback;
 43  
 import javax.security.sasl.RealmCallback;
 44  
 import javax.security.sasl.Sasl;
 45  
 import javax.security.sasl.SaslException;
 46  
 import javax.security.sasl.SaslServer;
 47  
 import java.io.IOException;
 48  
 import java.nio.charset.Charset;
 49  
 import org.apache.hadoop.security.SaslRpcServer.AuthMethod;
 50  
 
 51  
 /**
 52  
  * Encapsulates SASL server logic for Giraph BSP worker servers.
 53  
  */
 54  
 public class SaslNettyServer extends SaslRpcServer {
 55  
   /** Logger */
 56  0
   public static final Logger LOG = Logger.getLogger(SaslNettyServer.class);
 57  
 
 58  
   /**
 59  
    * Actual SASL work done by this object from javax.security.sasl.
 60  
    * Initialized below in constructor.
 61  
    */
 62  
   private SaslServer saslServer;
 63  
 
 64  
   /**
 65  
    * Constructor
 66  
    *
 67  
    * @param secretManager supplied by SaslServerHandler.
 68  
    */
 69  
   public SaslNettyServer(JobTokenSecretManager secretManager)
 70  
     throws IOException {
 71  0
     this(secretManager, AuthMethod.SIMPLE);
 72  0
   }
 73  
 
 74  
   /**
 75  
    * Constructor
 76  
    *
 77  
    * @param secretManager supplied by SaslServerHandler.
 78  
    * @param authMethod Authentication method
 79  
    */
 80  
   public SaslNettyServer(JobTokenSecretManager secretManager,
 81  
     AuthMethod authMethod) throws IOException {
 82  
 /*if[HADOOP_1_SECRET_MANAGER]
 83  
 else[HADOOP_1_SECRET_MANAGER]*/
 84  0
     super(authMethod);
 85  
 /*end[HADOOP_1_SECRET_MANAGER]*/
 86  0
     if (LOG.isDebugEnabled()) {
 87  0
       LOG.debug("SaslNettyServer: Secret manager is: " + secretManager +
 88  
         " with authmethod " + authMethod);
 89  
     }
 90  
 /*if[HADOOP_1_SECRET_MANAGER]
 91  
 else[HADOOP_1_SECRET_MANAGER]*/
 92  
     try {
 93  0
       secretManager.checkAvailableForRead();
 94  0
     } catch (StandbyException e) {
 95  0
       LOG.error("SaslNettyServer: Could not read secret manager: " + e);
 96  0
     }
 97  
 /*end[HADOOP_1_SECRET_MANAGER]*/
 98  
     try {
 99  0
       SaslDigestCallbackHandler ch =
 100  
           new SaslNettyServer.SaslDigestCallbackHandler(secretManager);
 101  
 /*if[STATIC_SASL_SYMBOL]
 102  
       saslServer =
 103  
           Sasl.createSaslServer(
 104  
               SaslNettyServer.AuthMethod.DIGEST.getMechanismName(), null,
 105  
               SaslRpcServer.SASL_DEFAULT_REALM, SaslRpcServer.SASL_PROPS, ch);
 106  
 else[STATIC_SASL_SYMBOL]*/
 107  0
       SaslPropertiesResolver saslPropsResolver =
 108  0
           SaslPropertiesResolver.getInstance(new Configuration());
 109  0
       saslServer =
 110  0
           Sasl.createSaslServer(
 111  0
               SaslNettyServer.AuthMethod.DIGEST.getMechanismName(), null,
 112  
               SaslRpcServer.SASL_DEFAULT_REALM,
 113  0
               saslPropsResolver.getDefaultProperties(), ch);
 114  
 /*end[STATIC_SASL_SYMBOL]*/
 115  0
     } catch (SaslException e) {
 116  0
       LOG.error("SaslNettyServer: Could not create SaslServer: " + e);
 117  0
     }
 118  0
   }
 119  
 
 120  
   public boolean isComplete() {
 121  0
     return saslServer.isComplete();
 122  
   }
 123  
 
 124  
   public String getUserName() {
 125  0
     return saslServer.getAuthorizationID();
 126  
   }
 127  
 
 128  
   /**
 129  
    * Used by SaslTokenMessage::processToken() to respond to server SASL tokens.
 130  
    *
 131  
    * @param token Server's SASL token
 132  
    * @return token to send back to the server.
 133  
    */
 134  
   public byte[] response(byte[] token) {
 135  
     try {
 136  0
       if (LOG.isDebugEnabled()) {
 137  0
         LOG.debug("response: Responding to input token of length: " +
 138  
             token.length);
 139  
       }
 140  0
       byte[] retval = saslServer.evaluateResponse(token);
 141  0
       if (LOG.isDebugEnabled()) {
 142  0
         LOG.debug("response: Response token length: " + retval.length);
 143  
       }
 144  0
       return retval;
 145  0
     } catch (SaslException e) {
 146  0
       LOG.error("response: Failed to evaluate client token of length: " +
 147  
           token.length + " : " + e);
 148  0
       return null;
 149  
     }
 150  
   }
 151  
 
 152  
   /**
 153  
    * Encode a byte[] identifier as a Base64-encoded string.
 154  
    *
 155  
    * @param identifier identifier to encode
 156  
    * @return Base64-encoded string
 157  
    */
 158  
   static String encodeIdentifier(byte[] identifier) {
 159  0
     return new String(Base64.encodeBase64(identifier),
 160  0
         Charset.defaultCharset());
 161  
   }
 162  
 
 163  
   /**
 164  
    * Encode a password as a base64-encoded char[] array.
 165  
    * @param password as a byte array.
 166  
    * @return password as a char array.
 167  
    */
 168  
   static char[] encodePassword(byte[] password) {
 169  0
     return new String(Base64.encodeBase64(password),
 170  0
         Charset.defaultCharset()).toCharArray();
 171  
   }
 172  
 
 173  
   /** CallbackHandler for SASL DIGEST-MD5 mechanism */
 174  
   @InterfaceStability.Evolving
 175  
   public static class SaslDigestCallbackHandler implements CallbackHandler {
 176  
     /** Used to authenticate the clients */
 177  
     private JobTokenSecretManager secretManager;
 178  
 
 179  
     /**
 180  
      * Constructor
 181  
      *
 182  
      * @param secretManager used to authenticate clients
 183  
      */
 184  
     public SaslDigestCallbackHandler(
 185  0
         JobTokenSecretManager secretManager) {
 186  0
       if (LOG.isDebugEnabled()) {
 187  0
         LOG.debug("SaslDigestCallback: Creating SaslDigestCallback handler " +
 188  
             "with secret manager: " + secretManager);
 189  
       }
 190  0
       this.secretManager = secretManager;
 191  0
     }
 192  
 
 193  
     /** {@inheritDoc} */
 194  
     @Override
 195  
     public void handle(Callback[] callbacks) throws IOException,
 196  
         UnsupportedCallbackException {
 197  0
       NameCallback nc = null;
 198  0
       PasswordCallback pc = null;
 199  0
       AuthorizeCallback ac = null;
 200  0
       for (Callback callback : callbacks) {
 201  0
         if (callback instanceof AuthorizeCallback) {
 202  0
           ac = (AuthorizeCallback) callback;
 203  0
         } else if (callback instanceof NameCallback) {
 204  0
           nc = (NameCallback) callback;
 205  0
         } else if (callback instanceof PasswordCallback) {
 206  0
           pc = (PasswordCallback) callback;
 207  0
         } else if (callback instanceof RealmCallback) {
 208  0
           continue; // realm is ignored
 209  
         } else {
 210  0
           throw new UnsupportedCallbackException(callback,
 211  
               "handle: Unrecognized SASL DIGEST-MD5 Callback");
 212  
         }
 213  
       }
 214  0
       if (pc != null) {
 215  0
         JobTokenIdentifier tokenIdentifier = getIdentifier(nc.getDefaultName(),
 216  
             secretManager);
 217  0
         char[] password =
 218  0
           encodePassword(secretManager.retrievePassword(tokenIdentifier));
 219  
 
 220  0
         if (LOG.isDebugEnabled()) {
 221  0
           LOG.debug("handle: SASL server DIGEST-MD5 callback: setting " +
 222  0
               "password for client: " + tokenIdentifier.getUser());
 223  
         }
 224  0
         pc.setPassword(password);
 225  
       }
 226  0
       if (ac != null) {
 227  0
         String authid = ac.getAuthenticationID();
 228  0
         String authzid = ac.getAuthorizationID();
 229  0
         if (authid.equals(authzid)) {
 230  0
           ac.setAuthorized(true);
 231  
         } else {
 232  0
           ac.setAuthorized(false);
 233  
         }
 234  0
         if (ac.isAuthorized()) {
 235  0
           if (LOG.isDebugEnabled()) {
 236  0
             String username =
 237  0
               getIdentifier(authzid, secretManager).getUser().getUserName();
 238  0
             if (LOG.isDebugEnabled()) {
 239  0
               LOG.debug("handle: SASL server DIGEST-MD5 callback: setting " +
 240  
                   "canonicalized client ID: " + username);
 241  
             }
 242  
           }
 243  0
           ac.setAuthorizedID(authzid);
 244  
         }
 245  
       }
 246  0
     }
 247  
   }
 248  
 }