blob: 3154145e49a9a1822c0ef4e2758fff8e981c9539 [file] [log] [blame]
package org.bouncycastle.est.jcajce;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import org.bouncycastle.est.ESTClientSourceProvider;
import org.bouncycastle.est.Source;
import org.bouncycastle.util.Strings;
class DefaultESTClientSourceProvider
implements ESTClientSourceProvider
{
private final SSLSocketFactory sslSocketFactory;
private final JsseHostnameAuthorizer hostNameAuthorizer;
private final int timeout;
private final ChannelBindingProvider bindingProvider;
private final Set<String> cipherSuites;
private final Long absoluteLimit;
private final boolean filterSupportedSuites;
public DefaultESTClientSourceProvider(
SSLSocketFactory socketFactory,
JsseHostnameAuthorizer hostNameAuthorizer,
int timeout, ChannelBindingProvider bindingProvider,
Set<String> cipherSuites, Long absoluteLimit,
boolean filterSupportedSuites)
throws GeneralSecurityException
{
this.sslSocketFactory = socketFactory;
this.hostNameAuthorizer = hostNameAuthorizer;
this.timeout = timeout;
this.bindingProvider = bindingProvider;
this.cipherSuites = cipherSuites;
this.absoluteLimit = absoluteLimit;
this.filterSupportedSuites = filterSupportedSuites;
}
public Source makeSource(String host, int port)
throws IOException
{
SSLSocket sock = (SSLSocket)sslSocketFactory.createSocket(host, port);
sock.setSoTimeout(timeout);
if (cipherSuites != null && !cipherSuites.isEmpty())
{
// Filter supplied list with what is actually supported.
if (filterSupportedSuites)
{
HashSet<String> fs = new HashSet<String>();
String[] supportedCipherSuites = sock.getSupportedCipherSuites();
for (int i = 0; i != supportedCipherSuites.length; i++)
{
fs.add(supportedCipherSuites[i]);
}
List<String> j = new ArrayList<String>();
for (Iterator it = cipherSuites.iterator(); it.hasNext();)
{
String s = (String)it.next();
if (fs.contains(s))
{
j.add(s);
}
}
if (j.isEmpty())
{
throw new IllegalStateException("No supplied cipher suite is supported by the provider.");
}
sock.setEnabledCipherSuites(j.toArray(new String[j.size()]));
}
else
{
sock.setEnabledCipherSuites(cipherSuites.toArray(new String[cipherSuites.size()]));
}
}
sock.startHandshake();
if (hostNameAuthorizer != null)
{
if (!hostNameAuthorizer.verified(host, sock.getSession()))
{
throw new IOException("Host name could not be verified.");
}
}
{
String t = Strings.toLowerCase(sock.getSession().getCipherSuite());
if (t.contains("_des_") || t.contains("_des40_") || t.contains("_3des_"))
{
throw new IOException("EST clients must not use DES ciphers");
}
}
// check for use of null cipher and fail.
if (Strings.toLowerCase(sock.getSession().getCipherSuite()).contains("null"))
{
throw new IOException("EST clients must not use NULL ciphers");
}
// check for use of anon cipher and fail.
if (Strings.toLowerCase(sock.getSession().getCipherSuite()).contains("anon"))
{
throw new IOException("EST clients must not use anon ciphers");
}
// check for use of export cipher.
if (Strings.toLowerCase(sock.getSession().getCipherSuite()).contains("export"))
{
throw new IOException("EST clients must not use export ciphers");
}
if (sock.getSession().getProtocol().equalsIgnoreCase("tlsv1"))
{
try
{
sock.close();
}
catch (Exception ex)
{
// Deliberately ignored.
}
throw new IOException("EST clients must not use TLSv1");
}
if (hostNameAuthorizer != null && !hostNameAuthorizer.verified(host, sock.getSession()))
{
throw new IOException("Hostname was not verified: " + host);
}
return new LimitedSSLSocketSource(sock, bindingProvider, absoluteLimit);
}
}