HDFS-9854. Log cipher suite negotiation more verbosely. Contributed by Wei-Chiu Chuang.

This commit is contained in:
cnauroth 2016-02-24 12:11:35 -08:00
parent d27d7fc72e
commit d1dd248b75
3 changed files with 54 additions and 18 deletions

View File

@ -238,7 +238,7 @@ private IOStreamPair send(InetAddress addr, OutputStream underlyingOut,
if (encryptionKey != null) {
LOG.debug("SASL client doing encrypted handshake for addr = {}, "
+ "datanodeId = {}", addr, datanodeId);
return getEncryptedStreams(underlyingOut, underlyingIn,
return getEncryptedStreams(addr, underlyingOut, underlyingIn,
encryptionKey);
} else if (!UserGroupInformation.isSecurityEnabled()) {
LOG.debug("SASL client skipping handshake in unsecured configuration for "
@ -275,13 +275,15 @@ private IOStreamPair send(InetAddress addr, OutputStream underlyingOut,
/**
* Sends client SASL negotiation for specialized encrypted handshake.
*
* @param addr connection address
* @param underlyingOut connection output stream
* @param underlyingIn connection input stream
* @param encryptionKey for an encrypted SASL handshake
* @return new pair of streams, wrapped after SASL negotiation
* @throws IOException for any error
*/
private IOStreamPair getEncryptedStreams(OutputStream underlyingOut,
private IOStreamPair getEncryptedStreams(InetAddress addr,
OutputStream underlyingOut,
InputStream underlyingIn, DataEncryptionKey encryptionKey)
throws IOException {
Map<String, String> saslProps = createSaslPropertiesForEncryption(
@ -294,8 +296,8 @@ private IOStreamPair getEncryptedStreams(OutputStream underlyingOut,
char[] password = encryptionKeyToPassword(encryptionKey.encryptionKey);
CallbackHandler callbackHandler = new SaslClientCallbackHandler(userName,
password);
return doSaslHandshake(underlyingOut, underlyingIn, userName, saslProps,
callbackHandler);
return doSaslHandshake(addr, underlyingOut, underlyingIn, userName,
saslProps, callbackHandler);
}
/**
@ -384,8 +386,8 @@ private IOStreamPair getSaslStreams(InetAddress addr,
char[] password = buildClientPassword(accessToken);
CallbackHandler callbackHandler = new SaslClientCallbackHandler(userName,
password);
return doSaslHandshake(underlyingOut, underlyingIn, userName, saslProps,
callbackHandler);
return doSaslHandshake(addr, underlyingOut, underlyingIn, userName,
saslProps, callbackHandler);
}
/**
@ -418,6 +420,7 @@ private char[] buildClientPassword(Token<BlockTokenIdentifier> blockToken) {
/**
* This method actually executes the client-side SASL handshake.
*
* @param addr connection address
* @param underlyingOut connection output stream
* @param underlyingIn connection input stream
* @param userName SASL user name
@ -426,8 +429,9 @@ private char[] buildClientPassword(Token<BlockTokenIdentifier> blockToken) {
* @return new pair of streams, wrapped after SASL negotiation
* @throws IOException for any error
*/
private IOStreamPair doSaslHandshake(OutputStream underlyingOut,
InputStream underlyingIn, String userName, Map<String, String> saslProps,
private IOStreamPair doSaslHandshake(InetAddress addr,
OutputStream underlyingOut, InputStream underlyingIn, String userName,
Map<String, String> saslProps,
CallbackHandler callbackHandler) throws IOException {
DataOutputStream out = new DataOutputStream(underlyingOut);
@ -447,12 +451,12 @@ private IOStreamPair doSaslHandshake(OutputStream underlyingOut,
byte[] remoteResponse = readSaslMessage(in);
byte[] localResponse = sasl.evaluateChallengeOrResponse(remoteResponse);
List<CipherOption> cipherOptions = null;
String cipherSuites = conf.get(
DFS_ENCRYPT_DATA_TRANSFER_CIPHER_SUITES_KEY);
if (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(
DFS_ENCRYPT_DATA_TRANSFER_CIPHER_SUITES_KEY);
if (cipherSuites != null && !cipherSuites.isEmpty()) {
if (!cipherSuites.equals(CipherSuite.AES_CTR_NOPADDING.getName())) {
throw new IOException(String.format("Invalid cipher suite, %s=%s",
@ -479,6 +483,20 @@ private IOStreamPair doSaslHandshake(OutputStream underlyingOut,
if (sasl.isNegotiatedQopPrivacy()) {
// Unwrap the negotiated cipher option
cipherOption = unwrap(response.cipherOption, sasl);
if (LOG.isDebugEnabled()) {
if (cipherOption == null) {
// No cipher suite is negotiated
if (cipherSuites != null && !cipherSuites.isEmpty()) {
// the client accepts some cipher suites, but the server does not.
LOG.debug("Client accepts cipher suites {}, "
+ "but server {} does not accept any of them",
cipherSuites, addr.toString());
}
} else {
LOG.debug("Client using cipher suite {} with server {}",
cipherOption.getCipherSuite().getName(), addr.toString());
}
}
}
// If negotiated cipher option is not null, we will use it to create

View File

@ -1959,6 +1959,9 @@ Release 2.8.0 - UNRELEASED
HDFS-9844. Correct path creation in getTrashRoot to handle root dir. (zhz)
HDFS-9854. Log cipher suite negotiation more verbosely
(Wei-Chiu Chuang via cnauroth)
OPTIMIZATIONS
HDFS-8026. Trace FSOutputSummer#writeChecksumChunks rather than

View File

@ -18,6 +18,7 @@
package org.apache.hadoop.hdfs.protocol.datatransfer.sasl;
import static org.apache.hadoop.hdfs.client.HdfsClientConfigKeys.DFS_DATA_TRANSFER_PROTECTION_KEY;
import static org.apache.hadoop.hdfs.client.HdfsClientConfigKeys.DFS_ENCRYPT_DATA_TRANSFER_CIPHER_SUITES_KEY;
import static org.apache.hadoop.hdfs.protocol.datatransfer.sasl.DataTransferSaslUtil.*;
import java.io.ByteArrayInputStream;
@ -40,6 +41,7 @@
import org.apache.commons.codec.binary.Base64;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.crypto.CipherOption;
import org.apache.hadoop.hdfs.net.Peer;
import org.apache.hadoop.hdfs.protocol.DatanodeID;
@ -175,7 +177,7 @@ public char[] apply(String userName) throws IOException {
return encryptionKeyToPassword(getEncryptionKeyFromUserName(userName));
}
});
return doSaslHandshake(underlyingOut, underlyingIn, saslProps,
return doSaslHandshake(peer, underlyingOut, underlyingIn, saslProps,
callbackHandler);
}
@ -295,7 +297,7 @@ public char[] apply(String userName) throws IOException {
return buildServerPassword(userName);
}
});
return doSaslHandshake(underlyingOut, underlyingIn, saslProps,
return doSaslHandshake(peer, underlyingOut, underlyingIn, saslProps,
callbackHandler);
}
@ -338,6 +340,7 @@ private BlockTokenIdentifier deserializeIdentifier(String str)
/**
* This method actually executes the server-side SASL handshake.
*
* @param peer connection peer
* @param underlyingOut connection output stream
* @param underlyingIn connection input stream
* @param saslProps properties of SASL negotiation
@ -345,7 +348,7 @@ private BlockTokenIdentifier deserializeIdentifier(String str)
* @return new pair of streams, wrapped after SASL negotiation
* @throws IOException for any error
*/
private IOStreamPair doSaslHandshake(OutputStream underlyingOut,
private IOStreamPair doSaslHandshake(Peer peer, OutputStream underlyingOut,
InputStream underlyingIn, Map<String, String> saslProps,
CallbackHandler callbackHandler) throws IOException {
@ -378,11 +381,23 @@ private IOStreamPair doSaslHandshake(OutputStream underlyingOut,
CipherOption cipherOption = null;
if (sasl.isNegotiatedQopPrivacy()) {
// Negotiate a cipher option
cipherOption = negotiateCipherOption(dnConf.getConf(), cipherOptions);
if (cipherOption != null) {
if (LOG.isDebugEnabled()) {
LOG.debug("Server using cipher suite " +
cipherOption.getCipherSuite().getName());
Configuration conf = dnConf.getConf();
cipherOption = negotiateCipherOption(conf, cipherOptions);
if (LOG.isDebugEnabled()) {
if (cipherOption == null) {
// No cipher suite is negotiated
String cipherSuites =
conf.get(DFS_ENCRYPT_DATA_TRANSFER_CIPHER_SUITES_KEY);
if (cipherSuites != null && !cipherSuites.isEmpty()) {
// the server accepts some cipher suites, but the client does not.
LOG.debug("Server accepts cipher suites {}, "
+ "but client {} does not accept any of them",
cipherSuites, peer.getRemoteAddressString());
}
} else {
LOG.debug("Server using cipher suite {} with client {}",
cipherOption.getCipherSuite().getName(),
peer.getRemoteAddressString());
}
}
}