| 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); |
| } |
| } |