Search in sources :

Example 1 with CipherOption

use of org.apache.hadoop.crypto.CipherOption in project hadoop by apache.

the class SaslDataTransferServer method doSaslHandshake.

/**
   * 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
   * @param callbackHandler for responding to SASL callbacks
   * @return new pair of streams, wrapped after SASL negotiation
   * @throws IOException for any error
   */
private IOStreamPair doSaslHandshake(Peer peer, OutputStream underlyingOut, InputStream underlyingIn, Map<String, String> saslProps, CallbackHandler callbackHandler) throws IOException {
    DataInputStream in = new DataInputStream(underlyingIn);
    DataOutputStream out = new DataOutputStream(underlyingOut);
    SaslParticipant sasl = SaslParticipant.createServerSaslParticipant(saslProps, callbackHandler);
    int magicNumber = in.readInt();
    if (magicNumber != SASL_TRANSFER_MAGIC_NUMBER) {
        throw new InvalidMagicNumberException(magicNumber, dnConf.getEncryptDataTransfer());
    }
    try {
        // step 1
        byte[] remoteResponse = readSaslMessage(in);
        byte[] localResponse = sasl.evaluateChallengeOrResponse(remoteResponse);
        sendSaslMessage(out, localResponse);
        // step 2 (server-side only)
        List<CipherOption> cipherOptions = Lists.newArrayList();
        remoteResponse = readSaslMessageAndNegotiationCipherOptions(in, cipherOptions);
        localResponse = sasl.evaluateChallengeOrResponse(remoteResponse);
        // SASL handshake is complete
        checkSaslComplete(sasl, saslProps);
        CipherOption cipherOption = null;
        if (sasl.isNegotiatedQopPrivacy()) {
            // Negotiate a cipher option
            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());
                }
            }
        }
        // If negotiated cipher option is not null, wrap it before sending.
        sendSaslMessageAndNegotiatedCipherOption(out, localResponse, wrap(cipherOption, sasl));
        // stream pair.
        return cipherOption != null ? createStreamPair(dnConf.getConf(), cipherOption, underlyingOut, underlyingIn, true) : sasl.createStreamPair(out, in);
    } catch (IOException ioe) {
        if (ioe instanceof SaslException && ioe.getCause() != null && ioe.getCause() instanceof 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.getCause().getMessage());
        } else {
            sendGenericSaslErrorMessage(out, ioe.getMessage());
        }
        throw ioe;
    }
}
Also used : Configuration(org.apache.hadoop.conf.Configuration) DataOutputStream(java.io.DataOutputStream) CipherOption(org.apache.hadoop.crypto.CipherOption) IOException(java.io.IOException) DataInputStream(java.io.DataInputStream) SaslException(javax.security.sasl.SaslException) InvalidEncryptionKeyException(org.apache.hadoop.hdfs.protocol.datatransfer.InvalidEncryptionKeyException)

Example 2 with CipherOption

use of org.apache.hadoop.crypto.CipherOption in project hadoop by apache.

the class DataTransferSaslUtil method negotiateCipherOption.

/**
   * Negotiate a cipher option which server supports.
   *
   * @param conf the configuration
   * @param options the cipher options which client supports
   * @return CipherOption negotiated cipher option
   */
public static CipherOption negotiateCipherOption(Configuration conf, List<CipherOption> options) throws IOException {
    // 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()) {
        return null;
    }
    if (!cipherSuites.equals(CipherSuite.AES_CTR_NOPADDING.getName())) {
        throw new IOException(String.format("Invalid cipher suite, %s=%s", DFS_ENCRYPT_DATA_TRANSFER_CIPHER_SUITES_KEY, cipherSuites));
    }
    if (options != null) {
        for (CipherOption option : options) {
            CipherSuite suite = option.getCipherSuite();
            if (suite == CipherSuite.AES_CTR_NOPADDING) {
                int keyLen = conf.getInt(DFS_ENCRYPT_DATA_TRANSFER_CIPHER_KEY_BITLENGTH_KEY, DFS_ENCRYPT_DATA_TRANSFER_CIPHER_KEY_BITLENGTH_DEFAULT) / 8;
                CryptoCodec codec = CryptoCodec.getInstance(conf, suite);
                byte[] inKey = new byte[keyLen];
                byte[] inIv = new byte[suite.getAlgorithmBlockSize()];
                byte[] outKey = new byte[keyLen];
                byte[] outIv = new byte[suite.getAlgorithmBlockSize()];
                assert codec != null;
                codec.generateSecureRandom(inKey);
                codec.generateSecureRandom(inIv);
                codec.generateSecureRandom(outKey);
                codec.generateSecureRandom(outIv);
                return new CipherOption(suite, inKey, inIv, outKey, outIv);
            }
        }
    }
    return null;
}
Also used : CipherOption(org.apache.hadoop.crypto.CipherOption) CipherSuite(org.apache.hadoop.crypto.CipherSuite) CryptoCodec(org.apache.hadoop.crypto.CryptoCodec) ByteString(com.google.protobuf.ByteString) IOException(java.io.IOException)

Example 3 with CipherOption

use of org.apache.hadoop.crypto.CipherOption in project hbase by apache.

the class FanOutOneBlockAsyncDFSOutputSaslHelper method createPBHelper.

private static PBHelper createPBHelper() throws NoSuchMethodException {
    Class<?> helperClass;
    try {
        helperClass = Class.forName("org.apache.hadoop.hdfs.protocolPB.PBHelperClient");
    } catch (ClassNotFoundException e) {
        LOG.debug("No PBHelperClient class found, should be hadoop 2.7-", e);
        helperClass = org.apache.hadoop.hdfs.protocolPB.PBHelper.class;
    }
    Method convertCipherOptionsMethod = helperClass.getMethod("convertCipherOptions", List.class);
    Method convertCipherOptionProtosMethod = helperClass.getMethod("convertCipherOptionProtos", List.class);
    return new PBHelper() {

        @SuppressWarnings("unchecked")
        @Override
        public List<CipherOptionProto> convertCipherOptions(List<CipherOption> options) {
            try {
                return (List<CipherOptionProto>) convertCipherOptionsMethod.invoke(null, options);
            } catch (IllegalAccessException | InvocationTargetException e) {
                throw new RuntimeException(e);
            }
        }

        @SuppressWarnings("unchecked")
        @Override
        public List<CipherOption> convertCipherOptionProtos(List<CipherOptionProto> options) {
            try {
                return (List<CipherOption>) convertCipherOptionProtosMethod.invoke(null, options);
            } catch (IllegalAccessException | InvocationTargetException e) {
                throw new RuntimeException(e);
            }
        }
    };
}
Also used : CipherOption(org.apache.hadoop.crypto.CipherOption) Method(java.lang.reflect.Method) CipherOptionProto(org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.CipherOptionProto) InvocationTargetException(java.lang.reflect.InvocationTargetException) List(java.util.List)

Example 4 with CipherOption

use of org.apache.hadoop.crypto.CipherOption in project hadoop by apache.

the class SaslDataTransferClient method doSaslHandshake.

/**
   * 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
   * @param saslProps properties of SASL negotiation
   * @param callbackHandler for responding to SASL callbacks
   * @return new pair of streams, wrapped after SASL negotiation
   * @throws IOException for any error
   */
private IOStreamPair doSaslHandshake(InetAddress addr, OutputStream underlyingOut, InputStream underlyingIn, String userName, Map<String, String> saslProps, CallbackHandler callbackHandler) throws IOException {
    DataOutputStream out = new DataOutputStream(underlyingOut);
    DataInputStream in = new DataInputStream(underlyingIn);
    SaslParticipant sasl = SaslParticipant.createClientSaslParticipant(userName, saslProps, callbackHandler);
    out.writeInt(SASL_TRANSFER_MAGIC_NUMBER);
    out.flush();
    try {
        // Start of handshake - "initial response" in SASL terminology.
        sendSaslMessage(out, new byte[0]);
        // step 1
        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)) {
            // values for future expansion.
            if (cipherSuites != null && !cipherSuites.isEmpty()) {
                if (!cipherSuites.equals(CipherSuite.AES_CTR_NOPADDING.getName())) {
                    throw new IOException(String.format("Invalid cipher suite, %s=%s", DFS_ENCRYPT_DATA_TRANSFER_CIPHER_SUITES_KEY, cipherSuites));
                }
                CipherOption option = new CipherOption(CipherSuite.AES_CTR_NOPADDING);
                cipherOptions = Lists.newArrayListWithCapacity(1);
                cipherOptions.add(option);
            }
        }
        sendSaslMessageAndNegotiationCipherOptions(out, localResponse, cipherOptions);
        // step 2 (client-side only)
        SaslResponseWithNegotiatedCipherOption response = readSaslMessageAndNegotiatedCipherOption(in);
        localResponse = sasl.evaluateChallengeOrResponse(response.payload);
        assert localResponse == null;
        // SASL handshake is complete
        checkSaslComplete(sasl, saslProps);
        CipherOption cipherOption = null;
        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());
                }
            }
        }
        // stream pair.
        return cipherOption != null ? createStreamPair(conf, cipherOption, underlyingOut, underlyingIn, false) : sasl.createStreamPair(out, in);
    } catch (IOException ioe) {
        sendGenericSaslErrorMessage(out, ioe.getMessage());
        throw ioe;
    }
}
Also used : DataOutputStream(java.io.DataOutputStream) CipherOption(org.apache.hadoop.crypto.CipherOption) IOException(java.io.IOException) DataInputStream(java.io.DataInputStream)

Example 5 with CipherOption

use of org.apache.hadoop.crypto.CipherOption in project hadoop by apache.

the class PBHelperClient method convert.

public static CipherOption convert(HdfsProtos.CipherOptionProto proto) {
    if (proto != null) {
        CipherSuite suite = null;
        if (proto.getSuite() != null) {
            suite = convert(proto.getSuite());
        }
        byte[] inKey = null;
        if (proto.getInKey() != null) {
            inKey = proto.getInKey().toByteArray();
        }
        byte[] inIv = null;
        if (proto.getInIv() != null) {
            inIv = proto.getInIv().toByteArray();
        }
        byte[] outKey = null;
        if (proto.getOutKey() != null) {
            outKey = proto.getOutKey().toByteArray();
        }
        byte[] outIv = null;
        if (proto.getOutIv() != null) {
            outIv = proto.getOutIv().toByteArray();
        }
        return new CipherOption(suite, inKey, inIv, outKey, outIv);
    }
    return null;
}
Also used : CipherSuite(org.apache.hadoop.crypto.CipherSuite) CipherOption(org.apache.hadoop.crypto.CipherOption)

Aggregations

CipherOption (org.apache.hadoop.crypto.CipherOption)5 IOException (java.io.IOException)3 DataInputStream (java.io.DataInputStream)2 DataOutputStream (java.io.DataOutputStream)2 CipherSuite (org.apache.hadoop.crypto.CipherSuite)2 ByteString (com.google.protobuf.ByteString)1 InvocationTargetException (java.lang.reflect.InvocationTargetException)1 Method (java.lang.reflect.Method)1 List (java.util.List)1 SaslException (javax.security.sasl.SaslException)1 Configuration (org.apache.hadoop.conf.Configuration)1 CryptoCodec (org.apache.hadoop.crypto.CryptoCodec)1 InvalidEncryptionKeyException (org.apache.hadoop.hdfs.protocol.datatransfer.InvalidEncryptionKeyException)1 CipherOptionProto (org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.CipherOptionProto)1