Example #1
0
        /// <summary>Sends client SASL negotiation for a peer if required.</summary>
        /// <param name="peer">connection peer</param>
        /// <param name="encryptionKeyFactory">for creation of an encryption key</param>
        /// <param name="accessToken">connection block access token</param>
        /// <param name="datanodeId">ID of destination DataNode</param>
        /// <returns>new pair of streams, wrapped after SASL negotiation</returns>
        /// <exception cref="System.IO.IOException">for any error</exception>
        public virtual Peer PeerSend(Peer peer, DataEncryptionKeyFactory encryptionKeyFactory
                                     , Org.Apache.Hadoop.Security.Token.Token <BlockTokenIdentifier> accessToken, DatanodeID
                                     datanodeId)
        {
            IOStreamPair ios = CheckTrustAndSend(DataTransferSaslUtil.GetPeerAddress(peer), peer
                                                 .GetOutputStream(), peer.GetInputStream(), encryptionKeyFactory, accessToken, datanodeId
                                                 );

            // TODO: Consider renaming EncryptedPeer to SaslPeer.
            return(ios != null ? new EncryptedPeer(peer, ios) : peer);
        }
Example #2
0
        /// <summary>Sends client SASL negotiation for specialized encrypted handshake.</summary>
        /// <param name="underlyingOut">connection output stream</param>
        /// <param name="underlyingIn">connection input stream</param>
        /// <param name="encryptionKey">for an encrypted SASL handshake</param>
        /// <returns>new pair of streams, wrapped after SASL negotiation</returns>
        /// <exception cref="System.IO.IOException">for any error</exception>
        private IOStreamPair GetEncryptedStreams(OutputStream underlyingOut, InputStream
                                                 underlyingIn, DataEncryptionKey encryptionKey)
        {
            IDictionary <string, string> saslProps = DataTransferSaslUtil.CreateSaslPropertiesForEncryption
                                                         (encryptionKey.encryptionAlgorithm);

            Log.Debug("Client using encryption algorithm {}", encryptionKey.encryptionAlgorithm
                      );
            string userName = GetUserNameFromEncryptionKey(encryptionKey);

            char[] password = DataTransferSaslUtil.EncryptionKeyToPassword(encryptionKey.encryptionKey
                                                                           );
            CallbackHandler callbackHandler = new SaslDataTransferClient.SaslClientCallbackHandler
                                                  (userName, password);

            return(DoSaslHandshake(underlyingOut, underlyingIn, userName, saslProps, callbackHandler
                                   ));
        }
        /// <summary>Receives SASL negotiation for specialized encrypted handshake.</summary>
        /// <param name="peer">connection peer</param>
        /// <param name="underlyingOut">connection output stream</param>
        /// <param name="underlyingIn">connection input stream</param>
        /// <returns>new pair of streams, wrapped after SASL negotiation</returns>
        /// <exception cref="System.IO.IOException">for any error</exception>
        private IOStreamPair GetEncryptedStreams(Peer peer, OutputStream underlyingOut, InputStream
                                                 underlyingIn)
        {
            if (peer.HasSecureChannel() || dnConf.GetTrustedChannelResolver().IsTrusted(DataTransferSaslUtil.GetPeerAddress
                                                                                            (peer)))
            {
                return(new IOStreamPair(underlyingIn, underlyingOut));
            }
            IDictionary <string, string> saslProps = DataTransferSaslUtil.CreateSaslPropertiesForEncryption
                                                         (dnConf.GetEncryptionAlgorithm());

            if (Log.IsDebugEnabled())
            {
                Log.Debug("Server using encryption algorithm " + dnConf.GetEncryptionAlgorithm());
            }
            CallbackHandler callbackHandler = new SaslDataTransferServer.SaslServerCallbackHandler
                                                  (new _PasswordFunction_172(this));

            return(DoSaslHandshake(underlyingOut, underlyingIn, saslProps, callbackHandler));
        }
Example #4
0
        /// <summary>This method actually executes the client-side SASL handshake.</summary>
        /// <param name="underlyingOut">connection output stream</param>
        /// <param name="underlyingIn">connection input stream</param>
        /// <param name="userName">SASL user name</param>
        /// <param name="saslProps">properties of SASL negotiation</param>
        /// <param name="callbackHandler">for responding to SASL callbacks</param>
        /// <returns>new pair of streams, wrapped after SASL negotiation</returns>
        /// <exception cref="System.IO.IOException">for any error</exception>
        private IOStreamPair DoSaslHandshake(OutputStream underlyingOut, InputStream underlyingIn
                                             , string userName, IDictionary <string, string> saslProps, CallbackHandler callbackHandler
                                             )
        {
            DataOutputStream @out = new DataOutputStream(underlyingOut);
            DataInputStream  @in  = new DataInputStream(underlyingIn);
            SaslParticipant  sasl = SaslParticipant.CreateClientSaslParticipant(userName, saslProps
                                                                                , callbackHandler);

            @out.WriteInt(SaslTransferMagicNumber);
            @out.Flush();
            try
            {
                // Start of handshake - "initial response" in SASL terminology.
                DataTransferSaslUtil.SendSaslMessage(@out, new byte[0]);
                // step 1
                byte[] remoteResponse = DataTransferSaslUtil.ReadSaslMessage(@in);
                byte[] localResponse  = sasl.EvaluateChallengeOrResponse(remoteResponse);
                IList <CipherOption> cipherOptions = null;
                if (DataTransferSaslUtil.RequestedQopContainsPrivacy(saslProps))
                {
                    // Negotiate cipher suites if configured.  Currently, the only supported
                    // cipher suite is AES/CTR/NoPadding, but the protocol allows multiple
                    // values for future expansion.
                    string cipherSuites = conf.Get(DFSConfigKeys.DfsEncryptDataTransferCipherSuitesKey
                                                   );
                    if (cipherSuites != null && !cipherSuites.IsEmpty())
                    {
                        if (!cipherSuites.Equals(CipherSuite.AesCtrNopadding.GetName()))
                        {
                            throw new IOException(string.Format("Invalid cipher suite, %s=%s", DFSConfigKeys.
                                                                DfsEncryptDataTransferCipherSuitesKey, cipherSuites));
                        }
                        CipherOption option = new CipherOption(CipherSuite.AesCtrNopadding);
                        cipherOptions = Lists.NewArrayListWithCapacity(1);
                        cipherOptions.AddItem(option);
                    }
                }
                DataTransferSaslUtil.SendSaslMessageAndNegotiationCipherOptions(@out, localResponse
                                                                                , cipherOptions);
                // step 2 (client-side only)
                SaslResponseWithNegotiatedCipherOption response = DataTransferSaslUtil.ReadSaslMessageAndNegotiatedCipherOption
                                                                      (@in);
                localResponse = sasl.EvaluateChallengeOrResponse(response.payload);
                System.Diagnostics.Debug.Assert(localResponse == null);
                // SASL handshake is complete
                DataTransferSaslUtil.CheckSaslComplete(sasl, saslProps);
                CipherOption cipherOption = null;
                if (sasl.IsNegotiatedQopPrivacy())
                {
                    // Unwrap the negotiated cipher option
                    cipherOption = DataTransferSaslUtil.Unwrap(response.cipherOption, sasl);
                }
                // If negotiated cipher option is not null, we will use it to create
                // stream pair.
                return(cipherOption != null?DataTransferSaslUtil.CreateStreamPair(conf, cipherOption
                                                                                  , underlyingOut, underlyingIn, false) : sasl.CreateStreamPair(@out, @in));
            }
            catch (IOException ioe)
            {
                DataTransferSaslUtil.SendGenericSaslErrorMessage(@out, ioe.Message);
                throw;
            }
        }
 /// <summary>Sends a SASL negotiation message indicating an invalid key error.</summary>
 /// <param name="out">stream to receive message</param>
 /// <param name="message">to send</param>
 /// <exception cref="System.IO.IOException">for any error</exception>
 private static void SendInvalidKeySaslErrorMessage(DataOutputStream @out, string
                                                    message)
 {
     DataTransferSaslUtil.SendSaslMessage(@out, DataTransferProtos.DataTransferEncryptorMessageProto.DataTransferEncryptorStatus
                                          .ErrorUnknownKey, null, message);
 }
        /// <summary>This method actually executes the server-side SASL handshake.</summary>
        /// <param name="underlyingOut">connection output stream</param>
        /// <param name="underlyingIn">connection input stream</param>
        /// <param name="saslProps">properties of SASL negotiation</param>
        /// <param name="callbackHandler">for responding to SASL callbacks</param>
        /// <returns>new pair of streams, wrapped after SASL negotiation</returns>
        /// <exception cref="System.IO.IOException">for any error</exception>
        private IOStreamPair DoSaslHandshake(OutputStream underlyingOut, InputStream underlyingIn
                                             , IDictionary <string, string> saslProps, CallbackHandler callbackHandler)
        {
            DataInputStream  @in  = new DataInputStream(underlyingIn);
            DataOutputStream @out = new DataOutputStream(underlyingOut);
            SaslParticipant  sasl = SaslParticipant.CreateServerSaslParticipant(saslProps, callbackHandler
                                                                                );
            int magicNumber = @in.ReadInt();

            if (magicNumber != SaslTransferMagicNumber)
            {
                throw new InvalidMagicNumberException(magicNumber, dnConf.GetEncryptDataTransfer(
                                                          ));
            }
            try
            {
                // step 1
                byte[] remoteResponse = DataTransferSaslUtil.ReadSaslMessage(@in);
                byte[] localResponse  = sasl.EvaluateChallengeOrResponse(remoteResponse);
                DataTransferSaslUtil.SendSaslMessage(@out, localResponse);
                // step 2 (server-side only)
                IList <CipherOption> cipherOptions = Lists.NewArrayList();
                remoteResponse = DataTransferSaslUtil.ReadSaslMessageAndNegotiationCipherOptions(
                    @in, cipherOptions);
                localResponse = sasl.EvaluateChallengeOrResponse(remoteResponse);
                // SASL handshake is complete
                DataTransferSaslUtil.CheckSaslComplete(sasl, saslProps);
                CipherOption cipherOption = null;
                if (sasl.IsNegotiatedQopPrivacy())
                {
                    // Negotiate a cipher option
                    cipherOption = DataTransferSaslUtil.NegotiateCipherOption(dnConf.GetConf(), cipherOptions
                                                                              );
                    if (cipherOption != null)
                    {
                        if (Log.IsDebugEnabled())
                        {
                            Log.Debug("Server using cipher suite " + cipherOption.GetCipherSuite().GetName());
                        }
                    }
                }
                // If negotiated cipher option is not null, wrap it before sending.
                DataTransferSaslUtil.SendSaslMessageAndNegotiatedCipherOption(@out, localResponse
                                                                              , DataTransferSaslUtil.Wrap(cipherOption, sasl));
                // If negotiated cipher option is not null, we will use it to create
                // stream pair.
                return(cipherOption != null?DataTransferSaslUtil.CreateStreamPair(dnConf.GetConf
                                                                                      (), cipherOption, underlyingOut, underlyingIn, true) : sasl.CreateStreamPair(@out
                                                                                                                                                                   , @in));
            }
            catch (IOException ioe)
            {
                if (ioe is SaslException && ioe.InnerException != null && ioe.InnerException is InvalidEncryptionKeyException)
                {
                    // This could just be because the client is long-lived and hasn't gotten
                    // a new encryption key from the NN in a while. Upon receiving this
                    // error, the client will get a new encryption key from the NN and retry
                    // connecting to this DN.
                    SendInvalidKeySaslErrorMessage(@out, ioe.InnerException.Message);
                }
                else
                {
                    DataTransferSaslUtil.SendGenericSaslErrorMessage(@out, ioe.Message);
                }
                throw;
            }
        }
        /// <summary>Receives SASL negotiation for general-purpose handshake.</summary>
        /// <param name="peer">connection peer</param>
        /// <param name="underlyingOut">connection output stream</param>
        /// <param name="underlyingIn">connection input stream</param>
        /// <returns>new pair of streams, wrapped after SASL negotiation</returns>
        /// <exception cref="System.IO.IOException">for any error</exception>
        private IOStreamPair GetSaslStreams(Peer peer, OutputStream underlyingOut, InputStream
                                            underlyingIn)
        {
            if (peer.HasSecureChannel() || dnConf.GetTrustedChannelResolver().IsTrusted(DataTransferSaslUtil.GetPeerAddress
                                                                                            (peer)))
            {
                return(new IOStreamPair(underlyingIn, underlyingOut));
            }
            SaslPropertiesResolver       saslPropsResolver = dnConf.GetSaslPropsResolver();
            IDictionary <string, string> saslProps         = saslPropsResolver.GetServerProperties(DataTransferSaslUtil.GetPeerAddress
                                                                                                       (peer));
            CallbackHandler callbackHandler = new SaslDataTransferServer.SaslServerCallbackHandler
                                                  (new _PasswordFunction_292(this));

            return(DoSaslHandshake(underlyingOut, underlyingIn, saslProps, callbackHandler));
        }
 /// <exception cref="System.IO.IOException"/>
 public char[] Apply(string userName)
 {
     return(DataTransferSaslUtil.EncryptionKeyToPassword(this._enclosing.GetEncryptionKeyFromUserName
                                                             (userName)));
 }