| /* |
| * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0, which is available at |
| * http://www.eclipse.org/legal/epl-2.0. |
| * |
| * This Source Code may also be made available under the following Secondary |
| * Licenses when the conditions for such availability set forth in the |
| * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, |
| * version 2 with the GNU Classpath Exception, which is available at |
| * https://www.gnu.org/software/classpath/license.html. |
| * |
| * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 |
| */ |
| |
| import javax.net.ssl.SSLSocket; |
| import javax.net.ssl.SSLSocketFactory; |
| import javax.net.ssl.SSLServerSocketFactory; |
| |
| import javax.net.ssl.SSLException; |
| import javax.net.ssl.SSLHandshakeException; |
| |
| import javax.net.ServerSocketFactory; |
| |
| import java.io.InputStreamReader; |
| import java.io.OutputStreamWriter; |
| import java.io.BufferedReader; |
| import java.io.BufferedWriter; |
| import java.io.IOException; |
| |
| import com.sun.ejte.ccl.reporter.SimpleReporterAdapter; |
| |
| public class CipherTest { |
| |
| private static final String DEFAULT_HOSTNAME = "localhost"; |
| private static final int DEFAULT_PORT = 8181; |
| |
| private static final String HTTP_GET_REQUEST = "GET / HTTP/1.0"; |
| |
| private static String serverHostname = null; |
| private static int serverPort = -1; |
| |
| // Default and Supported chipher set |
| private static String[] DEFAULT_CIPHERS = null; |
| private static String[] SUPPORTED_CIPHERS = null; |
| |
| // Flags |
| private static final String INTERACTIVE_OPTION = "-i"; |
| |
| private static final String HELP_OPTION = "-h"; |
| private static final String DEBUG_OPTION = "-d"; |
| private static final String VERBOSE1_OPTION = "-v"; |
| private static final String VERBOSE2_OPTION = "-verbose"; |
| |
| private static final String HOST_OPTION = "-host"; |
| private static final String PORT_OPTION = "-port"; |
| |
| private static final String SHOULD_PASS_OPTION = "-shouldPass"; |
| private static final String SHOULD_FAIL_OPTION = "-shouldFail"; |
| private static final String ENABLED_CIPHER_OPTION = "-enabledCipher"; |
| |
| private static boolean VERBOSE_FLAG = false; |
| |
| private static void usage() { |
| System.out.println("usage: CipherTest [-i] [-d] [-h] [-host hostname] [-port port#] -shouldPass <comma-spa-ciphers> [-v|-verbose]"); |
| System.out.println("-i interactive flag"); |
| System.out.println("-d debug mode"); |
| System.out.println("-v verbose mode"); |
| System.out.println("-verbose verbose mode"); |
| System.out.println("-h help/usage"); |
| System.out.println("-host hostname - host to connect to"); |
| System.out.println("-port port# - port to connect to"); |
| System.out.println("-enabledCiphers - comma separated list of ciphers that should be "); |
| System.out.println("-shouldPass - comma separated list of ciphers that should pass"); |
| System.out.println("-shouldFail - comma separated list of ciphers that should fail"); |
| } |
| |
| private static void verbose(String msg) { |
| if( VERBOSE_FLAG) |
| System.out.println(msg); |
| } |
| |
| public static void main(String[] args) throws Exception { |
| |
| boolean interactive = false; |
| boolean debug = false; |
| boolean help = false; |
| |
| //Set<String> shouldPass = new Set<String>(); |
| //Set<String> shouldFail = new Set<String>(); |
| String shouldPass = null; |
| String shouldFail = null; |
| String enabledCipherAsString = null; |
| |
| for(int i=0; i<args.length; i++) { |
| if( args[i].intern() == INTERACTIVE_OPTION.intern() ) { |
| interactive = true; |
| } else if( args[i].intern() == HELP_OPTION.intern() ) { |
| help = true; |
| } else if( args[i].intern() == VERBOSE1_OPTION.intern() ) { |
| VERBOSE_FLAG = true; |
| } else if( args[i].intern() == VERBOSE2_OPTION.intern() ) { |
| VERBOSE_FLAG = true; |
| } else if( args[i].intern() == DEBUG_OPTION.intern() ) { |
| debug = true; |
| } else if( args[i].intern() == HOST_OPTION.intern() ) { |
| serverHostname = args[++i]; |
| } else if( args[i].intern() == PORT_OPTION.intern() ) { |
| serverPort = Integer.parseInt(args[++i]); |
| } else if( args[i].intern() == SHOULD_PASS_OPTION.intern() ) { |
| shouldPass = args[++i]; |
| |
| /* |
| * Workaround for JavaSE bug (6518827) where |
| * arguments of length 0 are not passed in on Windows. |
| */ |
| if (shouldPass.startsWith("-")) { |
| // a "" param was skipped |
| shouldPass = ""; |
| i--; |
| } |
| } else if( args[i].intern() == SHOULD_FAIL_OPTION.intern() ) { |
| shouldFail = args[++i]; |
| } else if( args[i].intern() == ENABLED_CIPHER_OPTION.intern() ) { |
| enabledCipherAsString = args[++i]; |
| } else { |
| System.out.println("Unrecognized option: " + args[i]); |
| usage(); |
| System.exit(10); |
| } |
| |
| } |
| |
| for(int i=0; i<args.length; i++) { |
| verbose("Arg[" + i + "] " + args[i]); |
| } |
| |
| if( help) { |
| usage(); |
| System.exit(0); |
| } |
| if( debug ) { |
| System.setProperty("javax.net.debug", "all"); |
| } |
| |
| if( shouldPass == null ) { |
| usage(); |
| System.exit(11); |
| } |
| |
| if( serverHostname == null ) |
| serverHostname = DEFAULT_HOSTNAME; |
| |
| if( serverPort == -1 ) |
| serverPort = DEFAULT_PORT; |
| |
| |
| initCiphers(); |
| |
| if( interactive ) { |
| interactive(); |
| } else { |
| nonInteractive(enabledCipherAsString, shouldPass, shouldFail); |
| } |
| |
| } |
| |
| private static void interactive() |
| throws IOException { |
| |
| BufferedReader reader = |
| new BufferedReader(new InputStreamReader(System.in)); |
| |
| while(true) { |
| System.out.println(); |
| System.out.print( |
| "Enter number of cipher or cipher-name to enable on this client: "); |
| String s = reader.readLine(); |
| CipherTest ct = null; |
| try { |
| int num = Integer.parseInt(s); |
| ct = new CipherTest(num, SUPPORTED_CIPHERS[num], null); |
| } catch(Exception e) { |
| // try it as a string |
| ct = new CipherTest(s, s, null); |
| } |
| |
| ct.run(); |
| } |
| } |
| |
| private static void nonInteractive(String enabledCipher, |
| String shouldPass, String shouldFail) { |
| |
| // if( enabledCipher == null ) { |
| // for(int i=0; i<SUPPORTED_CIPHERS.length; i++) { |
| // CipherTest ct = new CipherTest(i, SUPPORTED_CIPHERS[i], shouldFail); |
| // ct.run(); |
| // } |
| // } else { |
| // CipherTest ct = new CipherTest(enabledCipher, shouldPass, shouldFail); |
| // ct.run(); |
| // } |
| |
| CipherTest ct = new CipherTest(enabledCipher, shouldPass, shouldFail); |
| ct.run(); |
| } |
| |
| private static void nonInteractive(String[] enabledCipher, |
| String shouldPass, String shouldFail) { |
| // TODO |
| } |
| |
| |
| private static SimpleReporterAdapter stat = |
| new SimpleReporterAdapter("appserv-tests"); |
| |
| private int startCipher = -1; |
| String[] ciphers = null; |
| String shouldPass; |
| String shouldFail; |
| private String testId = null; |
| |
| public CipherTest(int start, String shouldPass, String shouldFail) { |
| startCipher = start; |
| ciphers = new String[1]; |
| ciphers[0] = SUPPORTED_CIPHERS[startCipher]; |
| |
| this.shouldPass = shouldPass; |
| this.shouldFail = shouldFail; |
| |
| } |
| |
| public CipherTest(String cipherName, String shouldPass, String shouldFail) { |
| if( cipherName != null ) { |
| ciphers = new String[1]; |
| ciphers[0] = cipherName; |
| } |
| |
| this.shouldPass = shouldPass; |
| this.shouldFail = shouldFail; |
| } |
| |
| public void run() { |
| |
| try { |
| |
| testId = "SSL cipher test - " + ciphers[0]; |
| stat.addDescription("Security::SSL cipher test " + ciphers[0]); |
| |
| doSSLTest(ciphers); |
| verbose("Supported cipher suite: " + ciphers[0]); |
| |
| passed(ciphers); |
| //System.exit(0); |
| |
| } catch(SSLHandshakeException e) { |
| failed(ciphers); |
| verbose("Unsupported (SSLHandshakeException) ciphers: " + ciphers[0] + " ..."); |
| } catch(SSLException e) { |
| failed(ciphers); |
| verbose("SSLException with ciphers: " + ciphers[0] + e.getMessage()); |
| } catch(IOException e) { |
| failed(ciphers); |
| verbose("IOException with ciphers: " + ciphers[0] + " ..."); |
| } finally { |
| stat.printSummary(testId); |
| } |
| } |
| |
| private void passed(String[] thatPassed) { |
| for(int i=0; i<thatPassed.length; i++) { |
| int index = shouldPass.indexOf(thatPassed[i]); |
| if( index < 0 ) { |
| // is not in the should pass, test failed |
| System.out.println("Cipher - " + thatPassed[i] + |
| " - pased, but should not have. Test failed"); |
| stat.addStatus(testId, stat.FAIL); |
| return; |
| //System.exit(1); |
| } |
| } |
| |
| System.out.println("Test passed"); |
| stat.addStatus(testId, stat.PASS); |
| //System.exit(0); |
| } |
| |
| private void failed(String[] thatFailed) { |
| for(int i=0; i<thatFailed.length; i++) { |
| int index = shouldPass.indexOf(thatFailed[i]); |
| if( index >= 0 ) { |
| // is in the should pass, but did not |
| System.out.println("Cipher - " + thatFailed[i] + |
| " - failed, but should have passed. Test failed"); |
| stat.addStatus(testId, stat.FAIL); |
| return; |
| //System.exit(1); |
| } |
| } |
| |
| System.out.println("(Negative) Test passed"); |
| stat.addStatus(testId, stat.PASS); |
| //System.exit(0); |
| } |
| |
| private void doSSLTest(String[] enableCiphers) throws IOException { |
| |
| SSLSocketFactory sslSocketFactory = |
| (SSLSocketFactory)SSLSocketFactory.getDefault(); |
| |
| SSLSocket secureSocket = (SSLSocket) |
| sslSocketFactory.createSocket(serverHostname, serverPort); |
| |
| if( enableCiphers != null ) |
| secureSocket.setEnabledCipherSuites(enableCiphers); |
| |
| BufferedWriter buffWriter = new BufferedWriter( |
| new OutputStreamWriter(secureSocket.getOutputStream())); |
| buffWriter.write(HTTP_GET_REQUEST); |
| buffWriter.newLine(); |
| buffWriter.newLine(); |
| buffWriter.flush(); |
| //buffWriter.close(); |
| |
| //System.out.println("Written request to server: " + HTTP_GET_REQUEST); |
| |
| BufferedReader buffReader = new BufferedReader( |
| new InputStreamReader(secureSocket.getInputStream())); |
| String readin = null; |
| while( (readin=buffReader.readLine()) != null ) { |
| //System.out.println(readin); |
| } |
| } |
| |
| private static void initCiphers() { |
| ServerSocketFactory ssf = SSLServerSocketFactory.getDefault(); |
| SSLServerSocketFactory sslssf = null; |
| if( ssf instanceof SSLServerSocketFactory ) { |
| sslssf = (SSLServerSocketFactory)ssf; |
| } else { |
| System.out.println(ssf.getClass().getName()); |
| System.exit(1); |
| } |
| DEFAULT_CIPHERS = sslssf.getDefaultCipherSuites(); |
| SUPPORTED_CIPHERS = sslssf.getSupportedCipherSuites(); |
| |
| for(int i=0; i<DEFAULT_CIPHERS.length; i++) { |
| verbose("Default cipher[" + i + "] "+DEFAULT_CIPHERS[i]); |
| } |
| for(int i=0; i<SUPPORTED_CIPHERS.length; i++) { |
| verbose("Supported cipher[" + i + "] " + SUPPORTED_CIPHERS[i]); |
| } |
| |
| } |
| |
| } |