PageRenderTime 53ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/projects/tomcat-7.0.2/java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 820 lines | 571 code | 89 blank | 160 comment | 134 complexity | 548f5836a9b6cf40c36a2adc378f486b MD5 | raw file
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. package org.apache.tomcat.util.net.jsse;
  18. import java.io.File;
  19. import java.io.FileInputStream;
  20. import java.io.FileNotFoundException;
  21. import java.io.IOException;
  22. import java.io.InputStream;
  23. import java.net.InetAddress;
  24. import java.net.ServerSocket;
  25. import java.net.Socket;
  26. import java.net.SocketException;
  27. import java.security.KeyStore;
  28. import java.security.SecureRandom;
  29. import java.security.cert.CRL;
  30. import java.security.cert.CRLException;
  31. import java.security.cert.CertPathParameters;
  32. import java.security.cert.CertStore;
  33. import java.security.cert.CertStoreParameters;
  34. import java.security.cert.CertificateException;
  35. import java.security.cert.CertificateFactory;
  36. import java.security.cert.CollectionCertStoreParameters;
  37. import java.security.cert.PKIXBuilderParameters;
  38. import java.security.cert.X509CertSelector;
  39. import java.util.Collection;
  40. import java.util.Locale;
  41. import java.util.Vector;
  42. import javax.net.ssl.CertPathTrustManagerParameters;
  43. import javax.net.ssl.KeyManager;
  44. import javax.net.ssl.KeyManagerFactory;
  45. import javax.net.ssl.ManagerFactoryParameters;
  46. import javax.net.ssl.SSLContext;
  47. import javax.net.ssl.SSLException;
  48. import javax.net.ssl.SSLServerSocket;
  49. import javax.net.ssl.SSLServerSocketFactory;
  50. import javax.net.ssl.SSLSession;
  51. import javax.net.ssl.SSLSessionContext;
  52. import javax.net.ssl.SSLSocket;
  53. import javax.net.ssl.TrustManager;
  54. import javax.net.ssl.TrustManagerFactory;
  55. import javax.net.ssl.X509KeyManager;
  56. import org.apache.tomcat.util.net.AbstractEndpoint;
  57. import org.apache.tomcat.util.res.StringManager;
  58. /*
  59. 1. Make the JSSE's jars available, either as an installed
  60. extension (copy them into jre/lib/ext) or by adding
  61. them to the Tomcat classpath.
  62. 2. keytool -genkey -alias tomcat -keyalg RSA
  63. Use "changeit" as password ( this is the default we use )
  64. */
  65. /**
  66. * SSL server socket factory. It _requires_ a valid RSA key and
  67. * JSSE.
  68. *
  69. * @author Harish Prabandham
  70. * @author Costin Manolache
  71. * @author Stefan Freyr Stefansson
  72. * @author EKR -- renamed to JSSESocketFactory
  73. * @author Jan Luehe
  74. * @author Bill Barker
  75. */
  76. public class JSSESocketFactory
  77. extends org.apache.tomcat.util.net.ServerSocketFactory {
  78. private static final StringManager sm =
  79. StringManager.getManager("org.apache.tomcat.util.net.jsse.res");
  80. // Defaults - made public where re-used
  81. static String defaultProtocol = "TLS";
  82. static boolean defaultClientAuth = false;
  83. static String defaultKeystoreType = "JKS";
  84. private static final String defaultKeystoreFile
  85. = System.getProperty("user.home") + "/.keystore";
  86. private static final int defaultSessionCacheSize = 0;
  87. private static final int defaultSessionTimeout = 86400;
  88. private static final String ALLOW_ALL_SUPPORTED_CIPHERS = "ALL";
  89. public static final String DEFAULT_KEY_PASS = "changeit";
  90. static final org.apache.juli.logging.Log log =
  91. org.apache.juli.logging.LogFactory.getLog(JSSESocketFactory.class);
  92. protected boolean initialized;
  93. protected String clientAuth = "false";
  94. protected SSLServerSocketFactory sslProxy = null;
  95. protected String[] enabledCiphers;
  96. protected boolean allowUnsafeLegacyRenegotiation = false;
  97. /**
  98. * Flag to state that we require client authentication.
  99. */
  100. protected boolean requireClientAuth = false;
  101. /**
  102. * Flag to state that we would like client authentication.
  103. */
  104. protected boolean wantClientAuth = false;
  105. public JSSESocketFactory () {
  106. // NOOP
  107. }
  108. @Override
  109. public ServerSocket createSocket (int port)
  110. throws IOException
  111. {
  112. if (!initialized) init();
  113. ServerSocket socket = sslProxy.createServerSocket(port);
  114. initServerSocket(socket);
  115. return socket;
  116. }
  117. @Override
  118. public ServerSocket createSocket (int port, int backlog)
  119. throws IOException
  120. {
  121. if (!initialized) init();
  122. ServerSocket socket = sslProxy.createServerSocket(port, backlog);
  123. initServerSocket(socket);
  124. return socket;
  125. }
  126. @Override
  127. public ServerSocket createSocket (int port, int backlog,
  128. InetAddress ifAddress)
  129. throws IOException
  130. {
  131. if (!initialized) init();
  132. ServerSocket socket = sslProxy.createServerSocket(port, backlog,
  133. ifAddress);
  134. initServerSocket(socket);
  135. return socket;
  136. }
  137. @Override
  138. public Socket acceptSocket(ServerSocket socket)
  139. throws IOException
  140. {
  141. SSLSocket asock = null;
  142. try {
  143. asock = (SSLSocket)socket.accept();
  144. } catch (SSLException e){
  145. throw new SocketException("SSL handshake error" + e.toString());
  146. }
  147. return asock;
  148. }
  149. @Override
  150. public void handshake(Socket sock) throws IOException {
  151. // We do getSession instead of startHandshake() so we can call this multiple times
  152. SSLSession session = ((SSLSocket)sock).getSession();
  153. if (session.getCipherSuite().equals("SSL_NULL_WITH_NULL_NULL"))
  154. throw new IOException("SSL handshake failed. Ciper suite in SSL Session is SSL_NULL_WITH_NULL_NULL");
  155. if (!allowUnsafeLegacyRenegotiation) {
  156. // Prevent futher handshakes by removing all cipher suites
  157. ((SSLSocket) sock).setEnabledCipherSuites(new String[0]);
  158. }
  159. }
  160. /*
  161. * Determines the SSL cipher suites to be enabled.
  162. *
  163. * @param requestedCiphers Comma-separated list of requested ciphers
  164. * @param supportedCiphers Array of supported ciphers
  165. *
  166. * @return Array of SSL cipher suites to be enabled, or null if none of the
  167. * requested ciphers are supported
  168. */
  169. protected String[] getEnabledCiphers(String requestedCiphers,
  170. String[] supportedCiphers) {
  171. String[] result = null;
  172. if (ALLOW_ALL_SUPPORTED_CIPHERS.equals(requestedCiphers)) {
  173. return supportedCiphers;
  174. }
  175. if (requestedCiphers != null) {
  176. Vector<String> vec = null;
  177. String cipher = requestedCiphers;
  178. int index = requestedCiphers.indexOf(',');
  179. if (index != -1) {
  180. int fromIndex = 0;
  181. while (index != -1) {
  182. cipher =
  183. requestedCiphers.substring(fromIndex, index).trim();
  184. if (cipher.length() > 0) {
  185. /*
  186. * Check to see if the requested cipher is among the
  187. * supported ciphers, i.e., may be enabled
  188. */
  189. for (int i=0; supportedCiphers != null
  190. && i<supportedCiphers.length; i++) {
  191. if (supportedCiphers[i].equals(cipher)) {
  192. if (vec == null) {
  193. vec = new Vector<String>();
  194. }
  195. vec.addElement(cipher);
  196. break;
  197. }
  198. }
  199. }
  200. fromIndex = index+1;
  201. index = requestedCiphers.indexOf(',', fromIndex);
  202. } // while
  203. cipher = requestedCiphers.substring(fromIndex);
  204. }
  205. if (cipher != null) {
  206. cipher = cipher.trim();
  207. if (cipher.length() > 0) {
  208. /*
  209. * Check to see if the requested cipher is among the
  210. * supported ciphers, i.e., may be enabled
  211. */
  212. for (int i=0; supportedCiphers != null
  213. && i<supportedCiphers.length; i++) {
  214. if (supportedCiphers[i].equals(cipher)) {
  215. if (vec == null) {
  216. vec = new Vector<String>();
  217. }
  218. vec.addElement(cipher);
  219. break;
  220. }
  221. }
  222. }
  223. }
  224. if (vec != null) {
  225. result = new String[vec.size()];
  226. vec.copyInto(result);
  227. }
  228. } else {
  229. result = sslProxy.getDefaultCipherSuites();
  230. }
  231. return result;
  232. }
  233. /*
  234. * Gets the SSL server's keystore password.
  235. */
  236. protected String getKeystorePassword() {
  237. String keyPass = (String)attributes.get(
  238. AbstractEndpoint.SSL_ATTR_KEY_PASS);
  239. if (keyPass == null) {
  240. keyPass = DEFAULT_KEY_PASS;
  241. }
  242. String keystorePass = (String)attributes.get(
  243. AbstractEndpoint.SSL_ATTR_KEYSTORE_PASS);
  244. if (keystorePass == null) {
  245. keystorePass = keyPass;
  246. }
  247. return keystorePass;
  248. }
  249. /*
  250. * Gets the SSL server's keystore.
  251. */
  252. protected KeyStore getKeystore(String type, String provider, String pass)
  253. throws IOException {
  254. String keystoreFile = (String)attributes.get(
  255. AbstractEndpoint.SSL_ATTR_KEYSTORE_FILE);
  256. if (keystoreFile == null)
  257. keystoreFile = defaultKeystoreFile;
  258. return getStore(type, provider, keystoreFile, pass);
  259. }
  260. /*
  261. * Gets the SSL server's truststore.
  262. */
  263. protected KeyStore getTrustStore(String keystoreType,
  264. String keystoreProvider) throws IOException {
  265. KeyStore trustStore = null;
  266. String truststoreFile = (String)attributes.get(
  267. AbstractEndpoint.SSL_ATTR_TRUSTSTORE_FILE);
  268. if(truststoreFile == null) {
  269. truststoreFile = System.getProperty("javax.net.ssl.trustStore");
  270. }
  271. if(log.isDebugEnabled()) {
  272. log.debug("Truststore = " + truststoreFile);
  273. }
  274. String truststorePassword = (String)attributes.get(
  275. AbstractEndpoint.SSL_ATTR_TRUSTSTORE_PASS);
  276. if( truststorePassword == null) {
  277. truststorePassword =
  278. System.getProperty("javax.net.ssl.trustStorePassword");
  279. }
  280. if(log.isDebugEnabled()) {
  281. log.debug("TrustPass = " + truststorePassword);
  282. }
  283. String truststoreType = (String)attributes.get(
  284. AbstractEndpoint.SSL_ATTR_TRUSTSTORE_TYPE);
  285. if( truststoreType == null) {
  286. truststoreType = System.getProperty("javax.net.ssl.trustStoreType");
  287. }
  288. if(truststoreType == null) {
  289. truststoreType = keystoreType;
  290. }
  291. if(log.isDebugEnabled()) {
  292. log.debug("trustType = " + truststoreType);
  293. }
  294. String truststoreProvider =
  295. (String)attributes.get(
  296. AbstractEndpoint.SSL_ATTR_TRUSTSTORE_PROVIDER);
  297. if( truststoreProvider == null) {
  298. truststoreProvider =
  299. System.getProperty("javax.net.ssl.trustStoreProvider");
  300. }
  301. if (truststoreProvider == null) {
  302. truststoreProvider = keystoreProvider;
  303. }
  304. if(log.isDebugEnabled()) {
  305. log.debug("trustProvider = " + truststoreProvider);
  306. }
  307. if (truststoreFile != null){
  308. trustStore = getStore(truststoreType, truststoreProvider,
  309. truststoreFile, truststorePassword);
  310. }
  311. return trustStore;
  312. }
  313. /*
  314. * Gets the key- or truststore with the specified type, path, and password.
  315. */
  316. private KeyStore getStore(String type, String provider, String path,
  317. String pass) throws IOException {
  318. KeyStore ks = null;
  319. InputStream istream = null;
  320. try {
  321. if (provider == null) {
  322. ks = KeyStore.getInstance(type);
  323. } else {
  324. ks = KeyStore.getInstance(type, provider);
  325. }
  326. if(!("PKCS11".equalsIgnoreCase(type) ||
  327. "".equalsIgnoreCase(path))) {
  328. File keyStoreFile = new File(path);
  329. if (!keyStoreFile.isAbsolute()) {
  330. keyStoreFile = new File(System.getProperty("catalina.base"),
  331. path);
  332. }
  333. istream = new FileInputStream(keyStoreFile);
  334. }
  335. char[] storePass = null;
  336. if (pass != null) {
  337. storePass = pass.toCharArray();
  338. }
  339. ks.load(istream, storePass);
  340. } catch (FileNotFoundException fnfe) {
  341. log.error(sm.getString("jsse.keystore_load_failed", type, path,
  342. fnfe.getMessage()), fnfe);
  343. throw fnfe;
  344. } catch (IOException ioe) {
  345. log.error(sm.getString("jsse.keystore_load_failed", type, path,
  346. ioe.getMessage()), ioe);
  347. throw ioe;
  348. } catch(Exception ex) {
  349. String msg = sm.getString("jsse.keystore_load_failed", type, path,
  350. ex.getMessage());
  351. log.error(msg, ex);
  352. throw new IOException(msg);
  353. } finally {
  354. if (istream != null) {
  355. try {
  356. istream.close();
  357. } catch (IOException ioe) {
  358. // Do nothing
  359. }
  360. }
  361. }
  362. return ks;
  363. }
  364. /**
  365. * Reads the keystore and initializes the SSL socket factory.
  366. */
  367. void init() throws IOException {
  368. try {
  369. String clientAuthStr = (String) attributes.get(
  370. AbstractEndpoint.SSL_ATTR_CLIENT_AUTH);
  371. if("true".equalsIgnoreCase(clientAuthStr) ||
  372. "yes".equalsIgnoreCase(clientAuthStr)) {
  373. requireClientAuth = true;
  374. } else if("want".equalsIgnoreCase(clientAuthStr)) {
  375. wantClientAuth = true;
  376. }
  377. // SSL protocol variant (e.g., TLS, SSL v3, etc.)
  378. String protocol = (String) attributes.get(
  379. AbstractEndpoint.SSL_ATTR_SSL_PROTOCOL);
  380. if (protocol == null) {
  381. protocol = defaultProtocol;
  382. }
  383. // Certificate encoding algorithm (e.g., SunX509)
  384. String algorithm = (String) attributes.get(
  385. AbstractEndpoint.SSL_ATTR_ALGORITHM);
  386. if (algorithm == null) {
  387. algorithm = KeyManagerFactory.getDefaultAlgorithm();
  388. }
  389. String keystoreType = (String) attributes.get(
  390. AbstractEndpoint.SSL_ATTR_KEYSTORE_TYPE);
  391. if (keystoreType == null) {
  392. keystoreType = defaultKeystoreType;
  393. }
  394. String keystoreProvider =
  395. (String) attributes.get(
  396. AbstractEndpoint.SSL_ATTR_KEYSTORE_PROVIDER);
  397. String trustAlgorithm =
  398. (String)attributes.get(
  399. AbstractEndpoint.SSL_ATTR_TRUSTSTORE_ALGORITHM);
  400. if( trustAlgorithm == null ) {
  401. trustAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
  402. }
  403. // Create and init SSLContext
  404. SSLContext context = SSLContext.getInstance(protocol);
  405. context.init(getKeyManagers(keystoreType, keystoreProvider,
  406. algorithm,
  407. (String) attributes.get(AbstractEndpoint.SSL_ATTR_KEY_ALIAS)),
  408. getTrustManagers(keystoreType, keystoreProvider,
  409. trustAlgorithm),
  410. new SecureRandom());
  411. // Configure SSL session cache
  412. int sessionCacheSize;
  413. if (attributes.get(
  414. AbstractEndpoint.SSL_ATTR_SESSION_CACHE_SIZE) != null) {
  415. sessionCacheSize = Integer.parseInt(
  416. (String)attributes.get(
  417. AbstractEndpoint.SSL_ATTR_SESSION_CACHE_SIZE));
  418. } else {
  419. sessionCacheSize = defaultSessionCacheSize;
  420. }
  421. int sessionTimeout;
  422. if (attributes.get(
  423. AbstractEndpoint.SSL_ATTR_SESSION_TIMEOUT) != null) {
  424. sessionTimeout = Integer.parseInt(
  425. (String)attributes.get(
  426. AbstractEndpoint.SSL_ATTR_SESSION_TIMEOUT));
  427. } else {
  428. sessionTimeout = defaultSessionTimeout;
  429. }
  430. SSLSessionContext sessionContext =
  431. context.getServerSessionContext();
  432. if (sessionContext != null) {
  433. sessionContext.setSessionCacheSize(sessionCacheSize);
  434. sessionContext.setSessionTimeout(sessionTimeout);
  435. }
  436. // create proxy
  437. sslProxy = context.getServerSocketFactory();
  438. // Determine which cipher suites to enable
  439. String requestedCiphers = (String)attributes.get(
  440. AbstractEndpoint.SSL_ATTR_CIPHERS);
  441. enabledCiphers = getEnabledCiphers(requestedCiphers,
  442. sslProxy.getSupportedCipherSuites());
  443. allowUnsafeLegacyRenegotiation =
  444. "true".equals(attributes.get(
  445. AbstractEndpoint.SSL_ATTR_ALLOW_UNSAFE_RENEG));
  446. // Check the SSL config is OK
  447. checkConfig();
  448. } catch(Exception e) {
  449. if( e instanceof IOException )
  450. throw (IOException)e;
  451. throw new IOException(e.getMessage());
  452. }
  453. }
  454. /**
  455. * Gets the initialized key managers.
  456. */
  457. protected KeyManager[] getKeyManagers(String keystoreType,
  458. String keystoreProvider,
  459. String algorithm,
  460. String keyAlias)
  461. throws Exception {
  462. KeyManager[] kms = null;
  463. String keystorePass = getKeystorePassword();
  464. KeyStore ks = getKeystore(keystoreType, keystoreProvider, keystorePass);
  465. if (keyAlias != null && !ks.isKeyEntry(keyAlias)) {
  466. throw new IOException(
  467. sm.getString("jsse.alias_no_key_entry", keyAlias));
  468. }
  469. KeyManagerFactory kmf = KeyManagerFactory.getInstance(algorithm);
  470. kmf.init(ks, keystorePass.toCharArray());
  471. kms = kmf.getKeyManagers();
  472. if (keyAlias != null) {
  473. String alias = keyAlias;
  474. if (JSSESocketFactory.defaultKeystoreType.equals(keystoreType)) {
  475. alias = alias.toLowerCase(Locale.ENGLISH);
  476. }
  477. for(int i=0; i<kms.length; i++) {
  478. kms[i] = new JSSEKeyManager((X509KeyManager)kms[i], alias);
  479. }
  480. }
  481. return kms;
  482. }
  483. /**
  484. * Gets the initialized trust managers.
  485. */
  486. protected TrustManager[] getTrustManagers(String keystoreType,
  487. String keystoreProvider, String algorithm)
  488. throws Exception {
  489. String crlf = (String) attributes.get(
  490. AbstractEndpoint.SSL_ATTR_CRL_FILE);
  491. TrustManager[] tms = null;
  492. KeyStore trustStore = getTrustStore(keystoreType, keystoreProvider);
  493. if (trustStore != null) {
  494. if (crlf == null) {
  495. TrustManagerFactory tmf =
  496. TrustManagerFactory.getInstance(algorithm);
  497. tmf.init(trustStore);
  498. tms = tmf.getTrustManagers();
  499. } else {
  500. TrustManagerFactory tmf =
  501. TrustManagerFactory.getInstance(algorithm);
  502. CertPathParameters params =
  503. getParameters(algorithm, crlf, trustStore);
  504. ManagerFactoryParameters mfp =
  505. new CertPathTrustManagerParameters(params);
  506. tmf.init(mfp);
  507. tms = tmf.getTrustManagers();
  508. }
  509. }
  510. return tms;
  511. }
  512. /**
  513. * Return the initialization parameters for the TrustManager.
  514. * Currently, only the default <code>PKIX</code> is supported.
  515. *
  516. * @param algorithm The algorithm to get parameters for.
  517. * @param crlf The path to the CRL file.
  518. * @param trustStore The configured TrustStore.
  519. * @return The parameters including the CRLs and TrustStore.
  520. */
  521. protected CertPathParameters getParameters(String algorithm,
  522. String crlf,
  523. KeyStore trustStore)
  524. throws Exception {
  525. CertPathParameters params = null;
  526. if("PKIX".equalsIgnoreCase(algorithm)) {
  527. PKIXBuilderParameters xparams =
  528. new PKIXBuilderParameters(trustStore, new X509CertSelector());
  529. Collection<? extends CRL> crls = getCRLs(crlf);
  530. CertStoreParameters csp = new CollectionCertStoreParameters(crls);
  531. CertStore store = CertStore.getInstance("Collection", csp);
  532. xparams.addCertStore(store);
  533. xparams.setRevocationEnabled(true);
  534. String trustLength = (String)attributes.get(
  535. AbstractEndpoint.SSL_ATTR_TRUST_MAX_CERT_LENGTH);
  536. if(trustLength != null) {
  537. try {
  538. xparams.setMaxPathLength(Integer.parseInt(trustLength));
  539. } catch(Exception ex) {
  540. log.warn("Bad maxCertLength: "+trustLength);
  541. }
  542. }
  543. params = xparams;
  544. } else {
  545. throw new CRLException("CRLs not supported for type: "+algorithm);
  546. }
  547. return params;
  548. }
  549. /**
  550. * Load the collection of CRLs.
  551. *
  552. */
  553. protected Collection<? extends CRL> getCRLs(String crlf)
  554. throws IOException, CRLException, CertificateException {
  555. File crlFile = new File(crlf);
  556. if( !crlFile.isAbsolute() ) {
  557. crlFile = new File(System.getProperty("catalina.base"), crlf);
  558. }
  559. Collection<? extends CRL> crls = null;
  560. InputStream is = null;
  561. try {
  562. CertificateFactory cf = CertificateFactory.getInstance("X.509");
  563. is = new FileInputStream(crlFile);
  564. crls = cf.generateCRLs(is);
  565. } catch(IOException iex) {
  566. throw iex;
  567. } catch(CRLException crle) {
  568. throw crle;
  569. } catch(CertificateException ce) {
  570. throw ce;
  571. } finally {
  572. if(is != null) {
  573. try{
  574. is.close();
  575. } catch(Exception ex) {
  576. // Ignore
  577. }
  578. }
  579. }
  580. return crls;
  581. }
  582. /**
  583. * Set the SSL protocol variants to be enabled.
  584. * @param socket the SSLServerSocket.
  585. * @param protocols the protocols to use.
  586. */
  587. protected void setEnabledProtocols(SSLServerSocket socket,
  588. String []protocols){
  589. if (protocols != null) {
  590. socket.setEnabledProtocols(protocols);
  591. }
  592. }
  593. /**
  594. * Determines the SSL protocol variants to be enabled.
  595. *
  596. * @param socket The socket to get supported list from.
  597. * @param requestedProtocols Comma-separated list of requested SSL
  598. * protocol variants
  599. *
  600. * @return Array of SSL protocol variants to be enabled, or null if none of
  601. * the requested protocol variants are supported
  602. */
  603. protected String[] getEnabledProtocols(SSLServerSocket socket,
  604. String requestedProtocols){
  605. String[] supportedProtocols = socket.getSupportedProtocols();
  606. String[] enabledProtocols = null;
  607. if (requestedProtocols != null) {
  608. Vector<String> vec = null;
  609. String protocol = requestedProtocols;
  610. int index = requestedProtocols.indexOf(',');
  611. if (index != -1) {
  612. int fromIndex = 0;
  613. while (index != -1) {
  614. protocol =
  615. requestedProtocols.substring(fromIndex, index).trim();
  616. if (protocol.length() > 0) {
  617. /*
  618. * Check to see if the requested protocol is among the
  619. * supported protocols, i.e., may be enabled
  620. */
  621. for (int i=0; supportedProtocols != null
  622. && i<supportedProtocols.length; i++) {
  623. if (supportedProtocols[i].equals(protocol)) {
  624. if (vec == null) {
  625. vec = new Vector<String>();
  626. }
  627. vec.addElement(protocol);
  628. break;
  629. }
  630. }
  631. }
  632. fromIndex = index+1;
  633. index = requestedProtocols.indexOf(',', fromIndex);
  634. } // while
  635. protocol = requestedProtocols.substring(fromIndex);
  636. }
  637. if (protocol != null) {
  638. protocol = protocol.trim();
  639. if (protocol.length() > 0) {
  640. /*
  641. * Check to see if the requested protocol is among the
  642. * supported protocols, i.e., may be enabled
  643. */
  644. for (int i=0; supportedProtocols != null
  645. && i<supportedProtocols.length; i++) {
  646. if (supportedProtocols[i].equals(protocol)) {
  647. if (vec == null) {
  648. vec = new Vector<String>();
  649. }
  650. vec.addElement(protocol);
  651. break;
  652. }
  653. }
  654. }
  655. }
  656. if (vec != null) {
  657. enabledProtocols = new String[vec.size()];
  658. vec.copyInto(enabledProtocols);
  659. }
  660. }
  661. return enabledProtocols;
  662. }
  663. /**
  664. * Configure Client authentication for this version of JSSE. The
  665. * JSSE included in Java 1.4 supports the 'want' value. Prior
  666. * versions of JSSE will treat 'want' as 'false'.
  667. * @param socket the SSLServerSocket
  668. */
  669. protected void configureClientAuth(SSLServerSocket socket){
  670. if (wantClientAuth){
  671. socket.setWantClientAuth(wantClientAuth);
  672. } else {
  673. socket.setNeedClientAuth(requireClientAuth);
  674. }
  675. }
  676. /**
  677. * Configures the given SSL server socket with the requested cipher suites,
  678. * protocol versions, and need for client authentication
  679. */
  680. private void initServerSocket(ServerSocket ssocket) {
  681. SSLServerSocket socket = (SSLServerSocket) ssocket;
  682. if (enabledCiphers != null) {
  683. socket.setEnabledCipherSuites(enabledCiphers);
  684. }
  685. String requestedProtocols = (String) attributes.get("protocols");
  686. setEnabledProtocols(socket, getEnabledProtocols(socket,
  687. requestedProtocols));
  688. // we don't know if client auth is needed -
  689. // after parsing the request we may re-handshake
  690. configureClientAuth(socket);
  691. }
  692. /**
  693. * Checks that the certificate is compatible with the enabled cipher suites.
  694. * If we don't check now, the JIoEndpoint can enter a nasty logging loop.
  695. * See bug 45528.
  696. */
  697. private void checkConfig() throws IOException {
  698. // Create an unbound server socket
  699. ServerSocket socket = sslProxy.createServerSocket();
  700. initServerSocket(socket);
  701. try {
  702. // Set the timeout to 1ms as all we care about is if it throws an
  703. // SSLException on accept.
  704. socket.setSoTimeout(1);
  705. socket.accept();
  706. // Will never get here - no client can connect to an unbound port
  707. } catch (SSLException ssle) {
  708. // SSL configuration is invalid. Possibly cert doesn't match ciphers
  709. IOException ioe = new IOException(sm.getString(
  710. "jsse.invalid_ssl_conf", ssle.getMessage()));
  711. ioe.initCause(ssle);
  712. throw ioe;
  713. } catch (Exception e) {
  714. /*
  715. * Possible ways of getting here
  716. * socket.accept() throws a SecurityException
  717. * socket.setSoTimeout() throws a SocketException
  718. * socket.accept() throws some other exception (after a JDK change)
  719. * In these cases the test won't work so carry on - essentially
  720. * the behaviour before this patch
  721. * socket.accept() throws a SocketTimeoutException
  722. * In this case all is well so carry on
  723. */
  724. } finally {
  725. // Should be open here but just in case
  726. if (!socket.isClosed()) {
  727. socket.close();
  728. }
  729. }
  730. }
  731. }