package org.dcache.pool.movers;
import eu.emi.security.authn.x509.X509CertChainValidator;
import eu.emi.security.authn.x509.helpers.ssl.SSLTrustManager;
import eu.emi.security.authn.x509.impl.KeyAndCertCredential;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import diskCacheV111.util.CacheException;
import diskCacheV111.vehicles.ProtocolInfo;
import diskCacheV111.vehicles.RemoteHttpsDataTransferProtocolInfo;
import dmg.cells.nucleus.CellEndpoint;
import org.dcache.pool.repository.Allocator;
import org.dcache.pool.repository.RepositoryChannel;
import org.dcache.vehicles.FileAttributes;
/**
* A mover for transferring a file using HTTP over a TLS/SSL connection.
*/
public class RemoteHttpsDataTransferProtocol extends RemoteHttpDataTransferProtocol
{
private final TrustManager trustManager;
private final SecureRandom secureRandom;
private PrivateKey privateKey;
private X509Certificate[] chain;
public RemoteHttpsDataTransferProtocol(CellEndpoint cell, X509CertChainValidator validator,
SecureRandom secureRandom)
{
super(cell);
this.secureRandom = secureRandom;
this.trustManager = new SSLTrustManager(validator);
}
@Override
public void runIO(FileAttributes attributes, RepositoryChannel channel,
ProtocolInfo genericInfo, Allocator allocator, IoMode access)
throws CacheException, IOException, InterruptedException
{
RemoteHttpsDataTransferProtocolInfo info =
(RemoteHttpsDataTransferProtocolInfo) genericInfo;
privateKey = info.getPrivateKey();
chain = info.getCertificateChain();
super.runIO(attributes, channel, genericInfo, allocator, access);
}
@Override
public CloseableHttpClient createHttpClient() throws CacheException
{
try {
KeyManager[] keyManagers;
if (privateKey != null & chain != null) {
KeyAndCertCredential credential = new KeyAndCertCredential(privateKey, chain);
keyManagers = new KeyManager[]{credential.getKeyManager()};
} else {
keyManagers = new KeyManager[0];
}
SSLContext context = SSLContext.getInstance("TLS");
context.init(
keyManagers,
new TrustManager[]{trustManager},
secureRandom);
return HttpClients.custom().setUserAgent(USER_AGENT).setSSLContext(context).build();
} catch (NoSuchAlgorithmException | KeyStoreException | KeyManagementException e) {
throw new CacheException("failed to build http client: " + e.getMessage(), e);
}
}
}