34 import java.security.PrivilegedAction; |
34 import java.security.PrivilegedAction; |
35 import java.security.AlgorithmConstraints; |
35 import java.security.AlgorithmConstraints; |
36 import java.util.*; |
36 import java.util.*; |
37 import java.util.concurrent.TimeUnit; |
37 import java.util.concurrent.TimeUnit; |
38 import java.util.concurrent.locks.ReentrantLock; |
38 import java.util.concurrent.locks.ReentrantLock; |
|
39 import java.nio.charset.StandardCharsets; |
39 |
40 |
40 import javax.crypto.BadPaddingException; |
41 import javax.crypto.BadPaddingException; |
41 |
|
42 import javax.net.ssl.*; |
42 import javax.net.ssl.*; |
43 |
43 |
44 /** |
44 /** |
45 * Implementation of an SSL socket. This is a normal connection type |
45 * Implementation of an SSL socket. This is a normal connection type |
46 * socket, implementing SSL over some lower level socket, such as TCP. |
46 * socket, implementing SSL over some lower level socket, such as TCP. |
196 private boolean enableSessionCreation = true; |
196 private boolean enableSessionCreation = true; |
197 private String host; |
197 private String host; |
198 private boolean autoClose = true; |
198 private boolean autoClose = true; |
199 private AccessControlContext acc; |
199 private AccessControlContext acc; |
200 |
200 |
201 /* |
|
202 * We cannot use the hostname resolved from name services. For |
|
203 * virtual hosting, multiple hostnames may be bound to the same IP |
|
204 * address, so the hostname resolved from name services is not |
|
205 * reliable. |
|
206 */ |
|
207 private String rawHostname; |
|
208 |
|
209 // The cipher suites enabled for use on this connection. |
201 // The cipher suites enabled for use on this connection. |
210 private CipherSuiteList enabledCipherSuites; |
202 private CipherSuiteList enabledCipherSuites; |
211 |
203 |
212 // The endpoint identification protocol |
204 // The endpoint identification protocol |
213 private String identificationProtocol = null; |
205 private String identificationProtocol = null; |
214 |
206 |
215 // The cryptographic algorithm constraints |
207 // The cryptographic algorithm constraints |
216 private AlgorithmConstraints algorithmConstraints = null; |
208 private AlgorithmConstraints algorithmConstraints = null; |
|
209 |
|
210 // The server name indication and matchers |
|
211 List<SNIServerName> serverNames = |
|
212 Collections.<SNIServerName>emptyList(); |
|
213 Collection<SNIMatcher> sniMatchers = |
|
214 Collections.<SNIMatcher>emptyList(); |
217 |
215 |
218 /* |
216 /* |
219 * READ ME * READ ME * READ ME * READ ME * READ ME * READ ME * |
217 * READ ME * READ ME * READ ME * READ ME * READ ME * READ ME * |
220 * IMPORTANT STUFF TO UNDERSTANDING THE SYNCHRONIZATION ISSUES. |
218 * IMPORTANT STUFF TO UNDERSTANDING THE SYNCHRONIZATION ISSUES. |
221 * READ ME * READ ME * READ ME * READ ME * READ ME * READ ME * |
219 * READ ME * READ ME * READ ME * READ ME * READ ME * READ ME * |
395 */ |
393 */ |
396 SSLSocketImpl(SSLContextImpl context, String host, int port) |
394 SSLSocketImpl(SSLContextImpl context, String host, int port) |
397 throws IOException, UnknownHostException { |
395 throws IOException, UnknownHostException { |
398 super(); |
396 super(); |
399 this.host = host; |
397 this.host = host; |
400 this.rawHostname = host; |
398 this.serverNames = |
|
399 Utilities.addToSNIServerNameList(this.serverNames, this.host); |
401 init(context, false); |
400 init(context, false); |
402 SocketAddress socketAddress = |
401 SocketAddress socketAddress = |
403 host != null ? new InetSocketAddress(host, port) : |
402 host != null ? new InetSocketAddress(host, port) : |
404 new InetSocketAddress(InetAddress.getByName(null), port); |
403 new InetSocketAddress(InetAddress.getByName(null), port); |
405 connect(socketAddress, 0); |
404 connect(socketAddress, 0); |
438 SSLSocketImpl(SSLContextImpl context, String host, int port, |
437 SSLSocketImpl(SSLContextImpl context, String host, int port, |
439 InetAddress localAddr, int localPort) |
438 InetAddress localAddr, int localPort) |
440 throws IOException, UnknownHostException { |
439 throws IOException, UnknownHostException { |
441 super(); |
440 super(); |
442 this.host = host; |
441 this.host = host; |
443 this.rawHostname = host; |
442 this.serverNames = |
|
443 Utilities.addToSNIServerNameList(this.serverNames, this.host); |
444 init(context, false); |
444 init(context, false); |
445 bind(new InetSocketAddress(localAddr, localPort)); |
445 bind(new InetSocketAddress(localAddr, localPort)); |
446 SocketAddress socketAddress = |
446 SocketAddress socketAddress = |
447 host != null ? new InetSocketAddress(host, port) : |
447 host != null ? new InetSocketAddress(host, port) : |
448 new InetSocketAddress(InetAddress.getByName(null), port); |
448 new InetSocketAddress(InetAddress.getByName(null), port); |
480 */ |
480 */ |
481 SSLSocketImpl(SSLContextImpl context, boolean serverMode, |
481 SSLSocketImpl(SSLContextImpl context, boolean serverMode, |
482 CipherSuiteList suites, byte clientAuth, |
482 CipherSuiteList suites, byte clientAuth, |
483 boolean sessionCreation, ProtocolList protocols, |
483 boolean sessionCreation, ProtocolList protocols, |
484 String identificationProtocol, |
484 String identificationProtocol, |
485 AlgorithmConstraints algorithmConstraints) throws IOException { |
485 AlgorithmConstraints algorithmConstraints, |
|
486 Collection<SNIMatcher> sniMatchers) throws IOException { |
486 |
487 |
487 super(); |
488 super(); |
488 doClientAuth = clientAuth; |
489 doClientAuth = clientAuth; |
489 enableSessionCreation = sessionCreation; |
490 enableSessionCreation = sessionCreation; |
490 this.identificationProtocol = identificationProtocol; |
491 this.identificationProtocol = identificationProtocol; |
491 this.algorithmConstraints = algorithmConstraints; |
492 this.algorithmConstraints = algorithmConstraints; |
|
493 this.sniMatchers = sniMatchers; |
492 init(context, serverMode); |
494 init(context, serverMode); |
493 |
495 |
494 /* |
496 /* |
495 * Override what was picked out for us. |
497 * Override what was picked out for us. |
496 */ |
498 */ |
533 // We always layer over a connected socket |
535 // We always layer over a connected socket |
534 if (!sock.isConnected()) { |
536 if (!sock.isConnected()) { |
535 throw new SocketException("Underlying socket is not connected"); |
537 throw new SocketException("Underlying socket is not connected"); |
536 } |
538 } |
537 this.host = host; |
539 this.host = host; |
538 this.rawHostname = host; |
540 this.serverNames = |
|
541 Utilities.addToSNIServerNameList(this.serverNames, this.host); |
539 init(context, false); |
542 init(context, false); |
|
543 this.autoClose = autoClose; |
|
544 doneConnect(); |
|
545 } |
|
546 |
|
547 /** |
|
548 * Creates a server mode {@link Socket} layered over an |
|
549 * existing connected socket, and is able to read data which has |
|
550 * already been consumed/removed from the {@link Socket}'s |
|
551 * underlying {@link InputStream}. |
|
552 */ |
|
553 SSLSocketImpl(SSLContextImpl context, Socket sock, |
|
554 InputStream consumed, boolean autoClose) throws IOException { |
|
555 super(sock, consumed); |
|
556 // We always layer over a connected socket |
|
557 if (!sock.isConnected()) { |
|
558 throw new SocketException("Underlying socket is not connected"); |
|
559 } |
|
560 |
|
561 // In server mode, it is not necessary to set host and serverNames. |
|
562 // Otherwise, would require a reverse DNS lookup to get the hostname. |
|
563 |
|
564 init(context, true); |
540 this.autoClose = autoClose; |
565 this.autoClose = autoClose; |
541 doneConnect(); |
566 doneConnect(); |
542 } |
567 } |
543 |
568 |
544 /** |
569 /** |
602 * @throws SocketTimeoutException if timeout expires before connecting |
627 * @throws SocketTimeoutException if timeout expires before connecting |
603 */ |
628 */ |
604 public void connect(SocketAddress endpoint, int timeout) |
629 public void connect(SocketAddress endpoint, int timeout) |
605 throws IOException { |
630 throws IOException { |
606 |
631 |
607 if (self != this) { |
632 if (isLayered()) { |
608 throw new SocketException("Already connected"); |
633 throw new SocketException("Already connected"); |
609 } |
634 } |
610 |
635 |
611 if (!(endpoint instanceof InetSocketAddress)) { |
636 if (!(endpoint instanceof InetSocketAddress)) { |
612 throw new SocketException( |
637 throw new SocketException( |
626 /* |
651 /* |
627 * Save the input and output streams. May be done only after |
652 * Save the input and output streams. May be done only after |
628 * java.net actually connects using the socket "self", else |
653 * java.net actually connects using the socket "self", else |
629 * we get some pretty bizarre failure modes. |
654 * we get some pretty bizarre failure modes. |
630 */ |
655 */ |
631 if (self == this) { |
656 sockInput = super.getInputStream(); |
632 sockInput = super.getInputStream(); |
657 sockOutput = super.getOutputStream(); |
633 sockOutput = super.getOutputStream(); |
|
634 } else { |
|
635 sockInput = self.getInputStream(); |
|
636 sockOutput = self.getOutputStream(); |
|
637 } |
|
638 |
658 |
639 /* |
659 /* |
640 * Move to handshaking state, with pending session initialized |
660 * Move to handshaking state, with pending session initialized |
641 * to defaults and the appropriate kind of handshaker set up. |
661 * to defaults and the appropriate kind of handshaker set up. |
642 */ |
662 */ |
759 |
779 |
760 |
780 |
761 // For layered, non-autoclose sockets, we are not |
781 // For layered, non-autoclose sockets, we are not |
762 // able to bring them into a usable state, so we |
782 // able to bring them into a usable state, so we |
763 // treat it as fatal error. |
783 // treat it as fatal error. |
764 if (self != this && !autoClose) { |
784 if (isLayered() && !autoClose) { |
765 // Note that the alert description is |
785 // Note that the alert description is |
766 // specified as -1, so no message will be send |
786 // specified as -1, so no message will be send |
767 // to peer anymore. |
787 // to peer anymore. |
768 fatal((byte)(-1), ssle); |
788 fatal((byte)(-1), ssle); |
769 } else if ((debug != null) && Debug.isOn("ssl")) { |
789 } else if ((debug != null) && Debug.isOn("ssl")) { |
770 System.out.println(threadName() + |
790 System.out.println( |
|
791 Thread.currentThread().getName() + |
771 ", received Exception: " + ssle); |
792 ", received Exception: " + ssle); |
772 } |
793 } |
773 |
794 |
774 // RFC2246 requires that the session becomes |
795 // RFC2246 requires that the session becomes |
775 // unresumable if any connection is terminated |
796 // unresumable if any connection is terminated |
933 throw e; |
954 throw e; |
934 } catch (EOFException eof) { |
955 } catch (EOFException eof) { |
935 boolean handshaking = (getConnectionState() <= cs_HANDSHAKE); |
956 boolean handshaking = (getConnectionState() <= cs_HANDSHAKE); |
936 boolean rethrow = requireCloseNotify || handshaking; |
957 boolean rethrow = requireCloseNotify || handshaking; |
937 if ((debug != null) && Debug.isOn("ssl")) { |
958 if ((debug != null) && Debug.isOn("ssl")) { |
938 System.out.println(threadName() + |
959 System.out.println(Thread.currentThread().getName() + |
939 ", received EOFException: " |
960 ", received EOFException: " |
940 + (rethrow ? "error" : "ignored")); |
961 + (rethrow ? "error" : "ignored")); |
941 } |
962 } |
942 if (rethrow) { |
963 if (rethrow) { |
943 SSLException e; |
964 SSLException e; |
1181 * TLS protocols do not define a error alert for sequence |
1202 * TLS protocols do not define a error alert for sequence |
1182 * number overflow. We use handshake_failure error alert |
1203 * number overflow. We use handshake_failure error alert |
1183 * for handshaking and bad_record_mac for other records. |
1204 * for handshaking and bad_record_mac for other records. |
1184 */ |
1205 */ |
1185 if (debug != null && Debug.isOn("ssl")) { |
1206 if (debug != null && Debug.isOn("ssl")) { |
1186 System.out.println(threadName() + |
1207 System.out.println(Thread.currentThread().getName() + |
1187 ", sequence number extremely close to overflow " + |
1208 ", sequence number extremely close to overflow " + |
1188 "(2^64-1 packets). Closing connection."); |
1209 "(2^64-1 packets). Closing connection."); |
1189 |
1210 |
1190 } |
1211 } |
1191 |
1212 |
1198 * Don't bother to kickstart the renegotiation when the local is |
1219 * Don't bother to kickstart the renegotiation when the local is |
1199 * asking for it. |
1220 * asking for it. |
1200 */ |
1221 */ |
1201 if ((type != Record.ct_handshake) && mac.seqNumIsHuge()) { |
1222 if ((type != Record.ct_handshake) && mac.seqNumIsHuge()) { |
1202 if (debug != null && Debug.isOn("ssl")) { |
1223 if (debug != null && Debug.isOn("ssl")) { |
1203 System.out.println(threadName() + ", request renegotiation " + |
1224 System.out.println(Thread.currentThread().getName() + |
|
1225 ", request renegotiation " + |
1204 "to avoid sequence number overflow"); |
1226 "to avoid sequence number overflow"); |
1205 } |
1227 } |
1206 |
1228 |
1207 startHandshake(); |
1229 startHandshake(); |
1208 } |
1230 } |
1276 if (roleIsServer) { |
1298 if (roleIsServer) { |
1277 handshaker = new ServerHandshaker(this, sslContext, |
1299 handshaker = new ServerHandshaker(this, sslContext, |
1278 enabledProtocols, doClientAuth, |
1300 enabledProtocols, doClientAuth, |
1279 protocolVersion, connectionState == cs_HANDSHAKE, |
1301 protocolVersion, connectionState == cs_HANDSHAKE, |
1280 secureRenegotiation, clientVerifyData, serverVerifyData); |
1302 secureRenegotiation, clientVerifyData, serverVerifyData); |
|
1303 handshaker.setSNIMatchers(sniMatchers); |
1281 } else { |
1304 } else { |
1282 handshaker = new ClientHandshaker(this, sslContext, |
1305 handshaker = new ClientHandshaker(this, sslContext, |
1283 enabledProtocols, |
1306 enabledProtocols, |
1284 protocolVersion, connectionState == cs_HANDSHAKE, |
1307 protocolVersion, connectionState == cs_HANDSHAKE, |
1285 secureRenegotiation, clientVerifyData, serverVerifyData); |
1308 secureRenegotiation, clientVerifyData, serverVerifyData); |
|
1309 handshaker.setSNIServerNames(serverNames); |
1286 } |
1310 } |
1287 handshaker.setEnabledCipherSuites(enabledCipherSuites); |
1311 handshaker.setEnabledCipherSuites(enabledCipherSuites); |
1288 handshaker.setEnableSessionCreation(enableSessionCreation); |
1312 handshaker.setEnableSessionCreation(enableSessionCreation); |
1289 } |
1313 } |
1290 |
1314 |
1507 } |
1531 } |
1508 |
1532 |
1509 protected void closeSocket() throws IOException { |
1533 protected void closeSocket() throws IOException { |
1510 |
1534 |
1511 if ((debug != null) && Debug.isOn("ssl")) { |
1535 if ((debug != null) && Debug.isOn("ssl")) { |
1512 System.out.println(threadName() + ", called closeSocket()"); |
1536 System.out.println(Thread.currentThread().getName() + |
1513 } |
1537 ", called closeSocket()"); |
1514 if (self == this) { |
1538 } |
1515 super.close(); |
1539 |
1516 } else { |
1540 super.close(); |
1517 self.close(); |
|
1518 } |
|
1519 } |
1541 } |
1520 |
1542 |
1521 private void closeSocket(boolean selfInitiated) throws IOException { |
1543 private void closeSocket(boolean selfInitiated) throws IOException { |
1522 if ((debug != null) && Debug.isOn("ssl")) { |
1544 if ((debug != null) && Debug.isOn("ssl")) { |
1523 System.out.println(threadName() + |
1545 System.out.println(Thread.currentThread().getName() + |
1524 ", called closeSocket(" + selfInitiated + ")"); |
1546 ", called closeSocket(" + selfInitiated + ")"); |
1525 } |
1547 } |
1526 if (self == this) { |
1548 if (!isLayered() || autoClose) { |
1527 super.close(); |
1549 super.close(); |
1528 } else if (autoClose) { |
|
1529 self.close(); |
|
1530 } else if (selfInitiated) { |
1550 } else if (selfInitiated) { |
1531 // layered && non-autoclose |
1551 // layered && non-autoclose |
1532 // read close_notify alert to clear input stream |
1552 // read close_notify alert to clear input stream |
1533 waitForClose(false); |
1553 waitForClose(false); |
1534 } |
1554 } |
1547 * rather than leaving it for finalization, so that your remote |
1567 * rather than leaving it for finalization, so that your remote |
1548 * peer does not experience a protocol error. |
1568 * peer does not experience a protocol error. |
1549 */ |
1569 */ |
1550 public void close() throws IOException { |
1570 public void close() throws IOException { |
1551 if ((debug != null) && Debug.isOn("ssl")) { |
1571 if ((debug != null) && Debug.isOn("ssl")) { |
1552 System.out.println(threadName() + ", called close()"); |
1572 System.out.println(Thread.currentThread().getName() + |
|
1573 ", called close()"); |
1553 } |
1574 } |
1554 closeInternal(true); // caller is initiating close |
1575 closeInternal(true); // caller is initiating close |
1555 setConnectionState(cs_APP_CLOSED); |
1576 setConnectionState(cs_APP_CLOSED); |
1556 } |
1577 } |
1557 |
1578 |
1565 * If !selfInitiated, peer sent close_notify; we reciprocate but |
1586 * If !selfInitiated, peer sent close_notify; we reciprocate but |
1566 * no need to wait for response. |
1587 * no need to wait for response. |
1567 */ |
1588 */ |
1568 private void closeInternal(boolean selfInitiated) throws IOException { |
1589 private void closeInternal(boolean selfInitiated) throws IOException { |
1569 if ((debug != null) && Debug.isOn("ssl")) { |
1590 if ((debug != null) && Debug.isOn("ssl")) { |
1570 System.out.println(threadName() + ", called closeInternal(" |
1591 System.out.println(Thread.currentThread().getName() + |
1571 + selfInitiated + ")"); |
1592 ", called closeInternal(" + selfInitiated + ")"); |
1572 } |
1593 } |
1573 |
1594 |
1574 int state = getConnectionState(); |
1595 int state = getConnectionState(); |
1575 boolean closeSocketCalled = false; |
1596 boolean closeSocketCalled = false; |
1576 Throwable cachedThrowable = null; |
1597 Throwable cachedThrowable = null; |
1628 } |
1649 } |
1629 // If state was cs_SENT_CLOSE before, we don't do the actual |
1650 // If state was cs_SENT_CLOSE before, we don't do the actual |
1630 // closing since it is already in progress. |
1651 // closing since it is already in progress. |
1631 if (state == cs_SENT_CLOSE) { |
1652 if (state == cs_SENT_CLOSE) { |
1632 if (debug != null && Debug.isOn("ssl")) { |
1653 if (debug != null && Debug.isOn("ssl")) { |
1633 System.out.println(threadName() + |
1654 System.out.println(Thread.currentThread().getName() + |
1634 ", close invoked again; state = " + |
1655 ", close invoked again; state = " + |
1635 getConnectionState()); |
1656 getConnectionState()); |
1636 } |
1657 } |
1637 if (selfInitiated == false) { |
1658 if (selfInitiated == false) { |
1638 // We were called because a close_notify message was |
1659 // We were called because a close_notify message was |
1699 * might be read by another reader, |
1720 * might be read by another reader, |
1700 * which will then process the close and set the connection state. |
1721 * which will then process the close and set the connection state. |
1701 */ |
1722 */ |
1702 void waitForClose(boolean rethrow) throws IOException { |
1723 void waitForClose(boolean rethrow) throws IOException { |
1703 if (debug != null && Debug.isOn("ssl")) { |
1724 if (debug != null && Debug.isOn("ssl")) { |
1704 System.out.println(threadName() + |
1725 System.out.println(Thread.currentThread().getName() + |
1705 ", waiting for close_notify or alert: state " |
1726 ", waiting for close_notify or alert: state " |
1706 + getConnectionState()); |
1727 + getConnectionState()); |
1707 } |
1728 } |
1708 |
1729 |
1709 try { |
1730 try { |
1724 } |
1745 } |
1725 } |
1746 } |
1726 inrec = null; |
1747 inrec = null; |
1727 } catch (IOException e) { |
1748 } catch (IOException e) { |
1728 if (debug != null && Debug.isOn("ssl")) { |
1749 if (debug != null && Debug.isOn("ssl")) { |
1729 System.out.println(threadName() + |
1750 System.out.println(Thread.currentThread().getName() + |
1730 ", Exception while waiting for close " +e); |
1751 ", Exception while waiting for close " +e); |
1731 } |
1752 } |
1732 if (rethrow) { |
1753 if (rethrow) { |
1733 throw e; // pass exception up |
1754 throw e; // pass exception up |
1734 } |
1755 } |
1786 * will be closed, no further communications could be done. |
1807 * will be closed, no further communications could be done. |
1787 */ |
1808 */ |
1788 synchronized private void handleException(Exception e, boolean resumable) |
1809 synchronized private void handleException(Exception e, boolean resumable) |
1789 throws IOException { |
1810 throws IOException { |
1790 if ((debug != null) && Debug.isOn("ssl")) { |
1811 if ((debug != null) && Debug.isOn("ssl")) { |
1791 System.out.println(threadName() |
1812 System.out.println(Thread.currentThread().getName() + |
1792 + ", handling exception: " + e.toString()); |
1813 ", handling exception: " + e.toString()); |
1793 } |
1814 } |
1794 |
1815 |
1795 // don't close the Socket in case of timeouts or interrupts if |
1816 // don't close the Socket in case of timeouts or interrupts if |
1796 // the process is resumable. |
1817 // the process is resumable. |
1797 if (e instanceof InterruptedIOException && resumable) { |
1818 if (e instanceof InterruptedIOException && resumable) { |
1933 } |
1954 } |
1934 |
1955 |
1935 if (debug != null && (Debug.isOn("record") || |
1956 if (debug != null && (Debug.isOn("record") || |
1936 Debug.isOn("handshake"))) { |
1957 Debug.isOn("handshake"))) { |
1937 synchronized (System.out) { |
1958 synchronized (System.out) { |
1938 System.out.print(threadName()); |
1959 System.out.print(Thread.currentThread().getName()); |
1939 System.out.print(", RECV " + protocolVersion + " ALERT: "); |
1960 System.out.print(", RECV " + protocolVersion + " ALERT: "); |
1940 if (level == Alerts.alert_fatal) { |
1961 if (level == Alerts.alert_fatal) { |
1941 System.out.print("fatal, "); |
1962 System.out.print("fatal, "); |
1942 } else if (level == Alerts.alert_warning) { |
1963 } else if (level == Alerts.alert_warning) { |
1943 System.out.print("warning, "); |
1964 System.out.print("warning, "); |
1999 r.setVersion(protocolVersion); |
2020 r.setVersion(protocolVersion); |
2000 |
2021 |
2001 boolean useDebug = debug != null && Debug.isOn("ssl"); |
2022 boolean useDebug = debug != null && Debug.isOn("ssl"); |
2002 if (useDebug) { |
2023 if (useDebug) { |
2003 synchronized (System.out) { |
2024 synchronized (System.out) { |
2004 System.out.print(threadName()); |
2025 System.out.print(Thread.currentThread().getName()); |
2005 System.out.print(", SEND " + protocolVersion + " ALERT: "); |
2026 System.out.print(", SEND " + protocolVersion + " ALERT: "); |
2006 if (level == Alerts.alert_fatal) { |
2027 if (level == Alerts.alert_fatal) { |
2007 System.out.print("fatal, "); |
2028 System.out.print("fatal, "); |
2008 } else if (level == Alerts.alert_warning) { |
2029 } else if (level == Alerts.alert_warning) { |
2009 System.out.print("warning, "); |
2030 System.out.print("warning, "); |
2116 host = getInetAddress().getHostName(); |
2137 host = getInetAddress().getHostName(); |
2117 } |
2138 } |
2118 return host; |
2139 return host; |
2119 } |
2140 } |
2120 |
2141 |
2121 synchronized String getRawHostname() { |
|
2122 return rawHostname; |
|
2123 } |
|
2124 |
|
2125 // ONLY used by HttpsClient to setup the URI specified hostname |
2142 // ONLY used by HttpsClient to setup the URI specified hostname |
|
2143 // |
|
2144 // Please NOTE that this method MUST be called before calling to |
|
2145 // SSLSocket.setSSLParameters(). Otherwise, the {@code host} parameter |
|
2146 // may override SNIHostName in the customized server name indication. |
2126 synchronized public void setHost(String host) { |
2147 synchronized public void setHost(String host) { |
2127 this.host = host; |
2148 this.host = host; |
2128 this.rawHostname = host; |
2149 this.serverNames = |
|
2150 Utilities.addToSNIServerNameList(this.serverNames, this.host); |
2129 } |
2151 } |
2130 |
2152 |
2131 /** |
2153 /** |
2132 * Gets an input stream to read from the peer on the other side. |
2154 * Gets an input stream to read from the peer on the other side. |
2133 * Data read from this stream was always integrity protected in |
2155 * Data read from this stream was always integrity protected in |
2184 // start handshaking, if failed, the connection will be closed. |
2206 // start handshaking, if failed, the connection will be closed. |
2185 startHandshake(false); |
2207 startHandshake(false); |
2186 } catch (IOException e) { |
2208 } catch (IOException e) { |
2187 // handshake failed. log and return a nullSession |
2209 // handshake failed. log and return a nullSession |
2188 if (debug != null && Debug.isOn("handshake")) { |
2210 if (debug != null && Debug.isOn("handshake")) { |
2189 System.out.println(threadName() + |
2211 System.out.println(Thread.currentThread().getName() + |
2190 ", IOException in getSession(): " + e); |
2212 ", IOException in getSession(): " + e); |
2191 } |
2213 } |
2192 } |
2214 } |
2193 } |
2215 } |
2194 synchronized (this) { |
2216 synchronized (this) { |
2326 |
2348 |
2327 // If handshake has started, that's an error. Fall through... |
2349 // If handshake has started, that's an error. Fall through... |
2328 |
2350 |
2329 default: |
2351 default: |
2330 if (debug != null && Debug.isOn("ssl")) { |
2352 if (debug != null && Debug.isOn("ssl")) { |
2331 System.out.println(threadName() + |
2353 System.out.println(Thread.currentThread().getName() + |
2332 ", setUseClientMode() invoked in state = " + |
2354 ", setUseClientMode() invoked in state = " + |
2333 connectionState); |
2355 connectionState); |
2334 } |
2356 } |
2335 throw new IllegalArgumentException( |
2357 throw new IllegalArgumentException( |
2336 "Cannot change mode after SSL traffic has started"); |
2358 "Cannot change mode after SSL traffic has started"); |
2420 * Assigns the socket timeout. |
2442 * Assigns the socket timeout. |
2421 * @see java.net.Socket#setSoTimeout |
2443 * @see java.net.Socket#setSoTimeout |
2422 */ |
2444 */ |
2423 public void setSoTimeout(int timeout) throws SocketException { |
2445 public void setSoTimeout(int timeout) throws SocketException { |
2424 if ((debug != null) && Debug.isOn("ssl")) { |
2446 if ((debug != null) && Debug.isOn("ssl")) { |
2425 System.out.println(threadName() + |
2447 System.out.println(Thread.currentThread().getName() + |
2426 ", setSoTimeout(" + timeout + ") called"); |
2448 ", setSoTimeout(" + timeout + ") called"); |
2427 } |
2449 } |
2428 if (self == this) { |
2450 |
2429 super.setSoTimeout(timeout); |
2451 super.setSoTimeout(timeout); |
2430 } else { |
|
2431 self.setSoTimeout(timeout); |
|
2432 } |
|
2433 } |
2452 } |
2434 |
2453 |
2435 /** |
2454 /** |
2436 * Registers an event listener to receive notifications that an |
2455 * Registers an event listener to receive notifications that an |
2437 * SSL handshake has completed on this connection. |
2456 * SSL handshake has completed on this connection. |
2472 SSLParameters params = super.getSSLParameters(); |
2491 SSLParameters params = super.getSSLParameters(); |
2473 |
2492 |
2474 // the super implementation does not handle the following parameters |
2493 // the super implementation does not handle the following parameters |
2475 params.setEndpointIdentificationAlgorithm(identificationProtocol); |
2494 params.setEndpointIdentificationAlgorithm(identificationProtocol); |
2476 params.setAlgorithmConstraints(algorithmConstraints); |
2495 params.setAlgorithmConstraints(algorithmConstraints); |
|
2496 params.setSNIMatchers(sniMatchers); |
|
2497 params.setServerNames(serverNames); |
2477 |
2498 |
2478 return params; |
2499 return params; |
2479 } |
2500 } |
2480 |
2501 |
2481 /** |
2502 /** |
2485 super.setSSLParameters(params); |
2506 super.setSSLParameters(params); |
2486 |
2507 |
2487 // the super implementation does not handle the following parameters |
2508 // the super implementation does not handle the following parameters |
2488 identificationProtocol = params.getEndpointIdentificationAlgorithm(); |
2509 identificationProtocol = params.getEndpointIdentificationAlgorithm(); |
2489 algorithmConstraints = params.getAlgorithmConstraints(); |
2510 algorithmConstraints = params.getAlgorithmConstraints(); |
|
2511 |
|
2512 List<SNIServerName> sniNames = params.getServerNames(); |
|
2513 if (sniNames != null) { |
|
2514 serverNames = sniNames; |
|
2515 } |
|
2516 |
|
2517 Collection<SNIMatcher> matchers = params.getSNIMatchers(); |
|
2518 if (matchers != null) { |
|
2519 sniMatchers = matchers; |
|
2520 } |
|
2521 |
2490 if ((handshaker != null) && !handshaker.started()) { |
2522 if ((handshaker != null) && !handshaker.started()) { |
2491 handshaker.setIdentificationProtocol(identificationProtocol); |
2523 handshaker.setIdentificationProtocol(identificationProtocol); |
2492 handshaker.setAlgorithmConstraints(algorithmConstraints); |
2524 handshaker.setAlgorithmConstraints(algorithmConstraints); |
|
2525 if (roleIsServer) { |
|
2526 handshaker.setSNIMatchers(sniMatchers); |
|
2527 } else { |
|
2528 handshaker.setSNIServerNames(serverNames); |
|
2529 } |
2493 } |
2530 } |
2494 } |
2531 } |
2495 |
2532 |
2496 // |
2533 // |
2497 // We allocate a separate thread to deliver handshake completion |
2534 // We allocate a separate thread to deliver handshake completion |
2529 } |
2566 } |
2530 } |
2567 } |
2531 } |
2568 } |
2532 |
2569 |
2533 /** |
2570 /** |
2534 * Return the name of the current thread. Utility method. |
|
2535 */ |
|
2536 private static String threadName() { |
|
2537 return Thread.currentThread().getName(); |
|
2538 } |
|
2539 |
|
2540 /** |
|
2541 * Returns a printable representation of this end of the connection. |
2571 * Returns a printable representation of this end of the connection. |
2542 */ |
2572 */ |
2543 public String toString() { |
2573 public String toString() { |
2544 StringBuffer retval = new StringBuffer(80); |
2574 StringBuffer retval = new StringBuffer(80); |
2545 |
2575 |
2546 retval.append(Integer.toHexString(hashCode())); |
2576 retval.append(Integer.toHexString(hashCode())); |
2547 retval.append("["); |
2577 retval.append("["); |
2548 retval.append(sess.getCipherSuite()); |
2578 retval.append(sess.getCipherSuite()); |
2549 retval.append(": "); |
2579 retval.append(": "); |
2550 |
2580 |
2551 if (self == this) { |
2581 retval.append(super.toString()); |
2552 retval.append(super.toString()); |
|
2553 } else { |
|
2554 retval.append(self.toString()); |
|
2555 } |
|
2556 retval.append("]"); |
2582 retval.append("]"); |
2557 |
2583 |
2558 return retval.toString(); |
2584 return retval.toString(); |
2559 } |
2585 } |
2560 } |
2586 } |