62 * @see javax.net.ssl.SSLSocket |
67 * @see javax.net.ssl.SSLSocket |
63 * @see SSLServerSocket |
68 * @see SSLServerSocket |
64 * |
69 * |
65 * @author David Brownell |
70 * @author David Brownell |
66 */ |
71 */ |
67 public final class SSLSocketImpl extends BaseSSLSocketImpl { |
72 public final class SSLSocketImpl |
68 |
73 extends BaseSSLSocketImpl implements SSLTransport { |
69 /* |
74 |
70 * ERROR HANDLING GUIDELINES |
75 final SSLContextImpl sslContext; |
71 * (which exceptions to throw and catch and which not to throw and catch) |
76 final TransportContext conContext; |
72 * |
77 |
73 * . if there is an IOException (SocketException) when accessing the |
78 private final AppInputStream appInput = new AppInputStream(); |
74 * underlying Socket, pass it through |
79 private final AppOutputStream appOutput = new AppOutputStream(); |
75 * |
80 |
76 * . do not throw IOExceptions, throw SSLExceptions (or a subclass) |
81 private String peerHost; |
77 * |
82 private boolean autoClose; |
78 * . for internal errors (things that indicate a bug in JSSE or a |
83 private boolean isConnected = false; |
79 * grossly misconfigured J2RE), throw either an SSLException or |
84 private boolean tlsIsClosed = false; |
80 * a RuntimeException at your convenience. |
|
81 * |
|
82 * . handshaking code (Handshaker or HandshakeMessage) should generally |
|
83 * pass through exceptions, but can handle them if they know what to |
|
84 * do. |
|
85 * |
|
86 * . exception chaining should be used for all new code. If you happen |
|
87 * to touch old code that does not use chaining, you should change it. |
|
88 * |
|
89 * . there is a top level exception handler that sits at all entry |
|
90 * points from application code to SSLSocket read/write code. It |
|
91 * makes sure that all errors are handled (see handleException()). |
|
92 * |
|
93 * . JSSE internal code should generally not call close(), call |
|
94 * closeInternal(). |
|
95 */ |
|
96 |
|
97 /* |
|
98 * There's a state machine associated with each connection, which |
|
99 * among other roles serves to negotiate session changes. |
|
100 * |
|
101 * - START with constructor, until the TCP connection's around. |
|
102 * - HANDSHAKE picks session parameters before allowing traffic. |
|
103 * There are many substates due to sequencing requirements |
|
104 * for handshake messages. |
|
105 * - DATA may be transmitted. |
|
106 * - RENEGOTIATE state allows concurrent data and handshaking |
|
107 * traffic ("same" substates as HANDSHAKE), and terminates |
|
108 * in selection of new session (and connection) parameters |
|
109 * - ERROR state immediately precedes abortive disconnect. |
|
110 * - SENT_CLOSE sent a close_notify to the peer. For layered, |
|
111 * non-autoclose socket, must now read close_notify |
|
112 * from peer before closing the connection. For nonlayered or |
|
113 * non-autoclose socket, close connection and go onto |
|
114 * cs_CLOSED state. |
|
115 * - CLOSED after sending close_notify alert, & socket is closed. |
|
116 * SSL connection objects are not reused. |
|
117 * - APP_CLOSED once the application calls close(). Then it behaves like |
|
118 * a closed socket, e.g.. getInputStream() throws an Exception. |
|
119 * |
|
120 * State affects what SSL record types may legally be sent: |
|
121 * |
|
122 * - Handshake ... only in HANDSHAKE and RENEGOTIATE states |
|
123 * - App Data ... only in DATA and RENEGOTIATE states |
|
124 * - Alert ... in HANDSHAKE, DATA, RENEGOTIATE |
|
125 * |
|
126 * Re what may be received: same as what may be sent, except that |
|
127 * HandshakeRequest handshaking messages can come from servers even |
|
128 * in the application data state, to request entry to RENEGOTIATE. |
|
129 * |
|
130 * The state machine within HANDSHAKE and RENEGOTIATE states controls |
|
131 * the pending session, not the connection state, until the change |
|
132 * cipher spec and "Finished" handshake messages are processed and |
|
133 * make the "new" session become the current one. |
|
134 * |
|
135 * NOTE: details of the SMs always need to be nailed down better. |
|
136 * The text above illustrates the core ideas. |
|
137 * |
|
138 * +---->-------+------>--------->-------+ |
|
139 * | | | |
|
140 * <-----< ^ ^ <-----< v |
|
141 *START>----->HANDSHAKE>----->DATA>----->RENEGOTIATE SENT_CLOSE |
|
142 * v v v | | |
|
143 * | | | | v |
|
144 * +------------+---------------+ v ERROR |
|
145 * | | | |
|
146 * v | | |
|
147 * ERROR>------>----->CLOSED<--------<----+-- + |
|
148 * | |
|
149 * v |
|
150 * APP_CLOSED |
|
151 * |
|
152 * ALSO, note that the purpose of handshaking (renegotiation is |
|
153 * included) is to assign a different, and perhaps new, session to |
|
154 * the connection. The SSLv3 spec is a bit confusing on that new |
|
155 * protocol feature. |
|
156 */ |
|
157 private static final int cs_START = 0; |
|
158 private static final int cs_HANDSHAKE = 1; |
|
159 private static final int cs_DATA = 2; |
|
160 private static final int cs_RENEGOTIATE = 3; |
|
161 private static final int cs_ERROR = 4; |
|
162 private static final int cs_SENT_CLOSE = 5; |
|
163 private static final int cs_CLOSED = 6; |
|
164 private static final int cs_APP_CLOSED = 7; |
|
165 |
|
166 /* |
|
167 * Drives the protocol state machine. |
|
168 */ |
|
169 private volatile int connectionState; |
|
170 |
|
171 /* |
|
172 * Flag indicating if the next record we receive MUST be a Finished |
|
173 * message. Temporarily set during the handshake to ensure that |
|
174 * a change cipher spec message is followed by a finished message. |
|
175 */ |
|
176 private boolean expectingFinished; |
|
177 |
|
178 /* |
|
179 * For improved diagnostics, we detail connection closure |
|
180 * If the socket is closed (connectionState >= cs_ERROR), |
|
181 * closeReason != null indicates if the socket was closed |
|
182 * because of an error or because or normal shutdown. |
|
183 */ |
|
184 private SSLException closeReason; |
|
185 |
|
186 /* |
|
187 * Per-connection private state that doesn't change when the |
|
188 * session is changed. |
|
189 */ |
|
190 private ClientAuthType doClientAuth = |
|
191 ClientAuthType.CLIENT_AUTH_NONE; |
|
192 private boolean roleIsServer; |
|
193 private boolean enableSessionCreation = true; |
|
194 private String host; |
|
195 private boolean autoClose = true; |
|
196 private AccessControlContext acc; |
|
197 |
|
198 // The cipher suites enabled for use on this connection. |
|
199 private CipherSuiteList enabledCipherSuites; |
|
200 |
|
201 // The endpoint identification protocol |
|
202 private String identificationProtocol = null; |
|
203 |
|
204 // The cryptographic algorithm constraints |
|
205 private AlgorithmConstraints algorithmConstraints = null; |
|
206 |
|
207 // The server name indication and matchers |
|
208 List<SNIServerName> serverNames = |
|
209 Collections.<SNIServerName>emptyList(); |
|
210 Collection<SNIMatcher> sniMatchers = |
|
211 Collections.<SNIMatcher>emptyList(); |
|
212 |
|
213 // Is the serverNames set to empty with SSLParameters.setServerNames()? |
|
214 private boolean noSniExtension = false; |
|
215 |
|
216 // Is the sniMatchers set to empty with SSLParameters.setSNIMatchers()? |
|
217 private boolean noSniMatcher = false; |
|
218 |
|
219 // Configured application protocol values |
|
220 String[] applicationProtocols = new String[0]; |
|
221 |
|
222 // Negotiated application protocol value. |
|
223 // |
|
224 // The value under negotiation will be obtained from handshaker. |
|
225 String applicationProtocol = null; |
|
226 |
|
227 // Callback function that selects the application protocol value during |
|
228 // the SSL/TLS handshake. |
|
229 BiFunction<SSLSocket, List<String>, String> applicationProtocolSelector; |
|
230 |
|
231 /* |
|
232 * READ ME * READ ME * READ ME * READ ME * READ ME * READ ME * |
|
233 * IMPORTANT STUFF TO UNDERSTANDING THE SYNCHRONIZATION ISSUES. |
|
234 * READ ME * READ ME * READ ME * READ ME * READ ME * READ ME * |
|
235 * |
|
236 * There are several locks here. |
|
237 * |
|
238 * The primary lock is the per-instance lock used by |
|
239 * synchronized(this) and the synchronized methods. It controls all |
|
240 * access to things such as the connection state and variables which |
|
241 * affect handshaking. If we are inside a synchronized method, we |
|
242 * can access the state directly, otherwise, we must use the |
|
243 * synchronized equivalents. |
|
244 * |
|
245 * The handshakeLock is used to ensure that only one thread performs |
|
246 * the *complete initial* handshake. If someone is handshaking, any |
|
247 * stray application or startHandshake() requests who find the |
|
248 * connection state is cs_HANDSHAKE will stall on handshakeLock |
|
249 * until handshaking is done. Once the handshake is done, we either |
|
250 * succeeded or failed, but we can never go back to the cs_HANDSHAKE |
|
251 * or cs_START state again. |
|
252 * |
|
253 * Note that the read/write() calls here in SSLSocketImpl are not |
|
254 * obviously synchronized. In fact, it's very nonintuitive, and |
|
255 * requires careful examination of code paths. Grab some coffee, |
|
256 * and be careful with any code changes. |
|
257 * |
|
258 * There can be only three threads active at a time in the I/O |
|
259 * subsection of this class. |
|
260 * 1. startHandshake |
|
261 * 2. AppInputStream |
|
262 * 3. AppOutputStream |
|
263 * One thread could call startHandshake(). |
|
264 * AppInputStream/AppOutputStream read() and write() calls are each |
|
265 * synchronized on 'this' in their respective classes, so only one |
|
266 * app. thread will be doing a SSLSocketImpl.read() or .write()'s at |
|
267 * a time. |
|
268 * |
|
269 * If handshaking is required (state cs_HANDSHAKE), and |
|
270 * getConnectionState() for some/all threads returns cs_HANDSHAKE, |
|
271 * only one can grab the handshakeLock, and the rest will stall |
|
272 * either on getConnectionState(), or on the handshakeLock if they |
|
273 * happen to successfully race through the getConnectionState(). |
|
274 * |
|
275 * If a writer is doing the initial handshaking, it must create a |
|
276 * temporary reader to read the responses from the other side. As a |
|
277 * side-effect, the writer's reader will have priority over any |
|
278 * other reader. However, the writer's reader is not allowed to |
|
279 * consume any application data. When handshakeLock is finally |
|
280 * released, we either have a cs_DATA connection, or a |
|
281 * cs_CLOSED/cs_ERROR socket. |
|
282 * |
|
283 * The writeLock is held while writing on a socket connection and |
|
284 * also to protect the MAC and cipher for their direction. The |
|
285 * writeLock is package private for Handshaker which holds it while |
|
286 * writing the ChangeCipherSpec message. |
|
287 * |
|
288 * To avoid the problem of a thread trying to change operational |
|
289 * modes on a socket while handshaking is going on, we synchronize |
|
290 * on 'this'. If handshaking has not started yet, we tell the |
|
291 * handshaker to change its mode. If handshaking has started, |
|
292 * we simply store that request until the next pending session |
|
293 * is created, at which time the new handshaker's state is set. |
|
294 * |
|
295 * The readLock is held during readRecord(), which is responsible |
|
296 * for reading an SSLInputRecord, decrypting it, and processing it. |
|
297 * The readLock ensures that these three steps are done atomically |
|
298 * and that once started, no other thread can block on SSLInputRecord.read. |
|
299 * This is necessary so that processing of close_notify alerts |
|
300 * from the peer are handled properly. |
|
301 */ |
|
302 private final Object handshakeLock = new Object(); |
|
303 final ReentrantLock writeLock = new ReentrantLock(); |
|
304 private final Object readLock = new Object(); |
|
305 |
|
306 InputRecord inputRecord; |
|
307 OutputRecord outputRecord; |
|
308 |
|
309 /* |
|
310 * security parameters for secure renegotiation. |
|
311 */ |
|
312 private boolean secureRenegotiation; |
|
313 private byte[] clientVerifyData; |
|
314 private byte[] serverVerifyData; |
|
315 |
|
316 /* |
|
317 * The authentication context holds all information used to establish |
|
318 * who this end of the connection is (certificate chains, private keys, |
|
319 * etc) and who is trusted (e.g. as CAs or websites). |
|
320 */ |
|
321 private SSLContextImpl sslContext; |
|
322 |
|
323 |
|
324 /* |
|
325 * This connection is one of (potentially) many associated with |
|
326 * any given session. The output of the handshake protocol is a |
|
327 * new session ... although all the protocol description talks |
|
328 * about changing the cipher spec (and it does change), in fact |
|
329 * that's incidental since it's done by changing everything that |
|
330 * is associated with a session at the same time. (TLS/IETF may |
|
331 * change that to add client authentication w/o new key exchg.) |
|
332 */ |
|
333 private Handshaker handshaker; |
|
334 private SSLSessionImpl sess; |
|
335 private volatile SSLSessionImpl handshakeSession; |
|
336 |
|
337 |
|
338 /* |
|
339 * If anyone wants to get notified about handshake completions, |
|
340 * they'll show up on this list. |
|
341 */ |
|
342 private HashMap<HandshakeCompletedListener, AccessControlContext> |
|
343 handshakeListeners; |
|
344 |
|
345 /* |
|
346 * Reuse the same internal input/output streams. |
|
347 */ |
|
348 private InputStream sockInput; |
|
349 private OutputStream sockOutput; |
|
350 |
|
351 |
|
352 /* |
|
353 * These input and output streams block their data in SSL records, |
|
354 * and usually arrange integrity and privacy protection for those |
|
355 * records. The guts of the SSL protocol are wrapped up in these |
|
356 * streams, and in the handshaking that establishes the details of |
|
357 * that integrity and privacy protection. |
|
358 */ |
|
359 private AppInputStream input; |
|
360 private AppOutputStream output; |
|
361 |
|
362 /* |
|
363 * The protocol versions enabled for use on this connection. |
|
364 * |
|
365 * Note: we support a pseudo protocol called SSLv2Hello which when |
|
366 * set will result in an SSL v2 Hello being sent with SSL (version 3.0) |
|
367 * or TLS (version 3.1, 3.2, etc.) version info. |
|
368 */ |
|
369 private ProtocolList enabledProtocols; |
|
370 |
|
371 /* |
|
372 * The SSL version associated with this connection. |
|
373 */ |
|
374 private ProtocolVersion protocolVersion = ProtocolVersion.DEFAULT_TLS; |
|
375 |
|
376 /* Class and subclass dynamic debugging support */ |
|
377 private static final Debug debug = Debug.getInstance("ssl"); |
|
378 |
|
379 /* |
|
380 * Whether local cipher suites preference in server side should be |
|
381 * honored during handshaking? |
|
382 */ |
|
383 private boolean preferLocalCipherSuites = false; |
|
384 |
|
385 /* |
|
386 * The maximum expected network packet size for SSL/TLS/DTLS records. |
|
387 */ |
|
388 private int maximumPacketSize = 0; |
|
389 |
85 |
390 /* |
86 /* |
391 * Is the local name service trustworthy? |
87 * Is the local name service trustworthy? |
392 * |
88 * |
393 * If the local name service is not trustworthy, reverse host name |
89 * If the local name service is not trustworthy, reverse host name |
394 * resolution should not be performed for endpoint identification. |
90 * resolution should not be performed for endpoint identification. |
395 */ |
91 */ |
396 static final boolean trustNameService = |
92 static final boolean trustNameService = |
397 Debug.getBooleanProperty("jdk.tls.trustNameService", false); |
93 Utilities.getBooleanProperty("jdk.tls.trustNameService", false); |
398 |
94 |
399 // |
95 /** |
400 // CONSTRUCTORS AND INITIALIZATION CODE |
96 * Package-private constructor used to instantiate an unconnected |
401 // |
97 * socket. |
402 |
98 * |
403 /** |
99 * This instance is meant to set handshake state to use "client mode". |
404 * Constructs an SSL connection to a named host at a specified port, |
100 */ |
405 * using the authentication context provided. This endpoint acts as |
101 SSLSocketImpl(SSLContextImpl sslContext) { |
406 * the client, and may rejoin an existing SSL session if appropriate. |
|
407 * |
|
408 * @param context authentication context to use |
|
409 * @param host name of the host with which to connect |
|
410 * @param port number of the server's port |
|
411 */ |
|
412 SSLSocketImpl(SSLContextImpl context, String host, int port) |
|
413 throws IOException, UnknownHostException { |
|
414 super(); |
102 super(); |
415 this.host = host; |
103 this.sslContext = sslContext; |
416 this.serverNames = |
104 HandshakeHash handshakeHash = new HandshakeHash(); |
417 Utilities.addToSNIServerNameList(this.serverNames, this.host); |
105 this.conContext = new TransportContext(sslContext, this, |
418 init(context, false); |
106 new SSLSocketInputRecord(handshakeHash), |
|
107 new SSLSocketOutputRecord(handshakeHash), true); |
|
108 } |
|
109 |
|
110 /** |
|
111 * Package-private constructor used to instantiate a server socket. |
|
112 * |
|
113 * This instance is meant to set handshake state to use "server mode". |
|
114 */ |
|
115 SSLSocketImpl(SSLContextImpl sslContext, SSLConfiguration sslConfig) { |
|
116 super(); |
|
117 this.sslContext = sslContext; |
|
118 HandshakeHash handshakeHash = new HandshakeHash(); |
|
119 this.conContext = new TransportContext(sslContext, this, sslConfig, |
|
120 new SSLSocketInputRecord(handshakeHash), |
|
121 new SSLSocketOutputRecord(handshakeHash)); |
|
122 } |
|
123 |
|
124 /** |
|
125 * Constructs an SSL connection to a named host at a specified |
|
126 * port, using the authentication context provided. |
|
127 * |
|
128 * This endpoint acts as the client, and may rejoin an existing SSL session |
|
129 * if appropriate. |
|
130 */ |
|
131 SSLSocketImpl(SSLContextImpl sslContext, String peerHost, |
|
132 int peerPort) throws IOException, UnknownHostException { |
|
133 super(); |
|
134 this.sslContext = sslContext; |
|
135 HandshakeHash handshakeHash = new HandshakeHash(); |
|
136 this.conContext = new TransportContext(sslContext, this, |
|
137 new SSLSocketInputRecord(handshakeHash), |
|
138 new SSLSocketOutputRecord(handshakeHash), true); |
|
139 this.peerHost = peerHost; |
419 SocketAddress socketAddress = |
140 SocketAddress socketAddress = |
420 host != null ? new InetSocketAddress(host, port) : |
141 peerHost != null ? new InetSocketAddress(peerHost, peerPort) : |
421 new InetSocketAddress(InetAddress.getByName(null), port); |
142 new InetSocketAddress(InetAddress.getByName(null), peerPort); |
422 connect(socketAddress, 0); |
143 connect(socketAddress, 0); |
423 } |
144 } |
424 |
145 |
425 |
146 /** |
426 /** |
147 * Constructs an SSL connection to a server at a specified |
427 * Constructs an SSL connection to a server at a specified address. |
148 * address, and TCP port, using the authentication context |
428 * and TCP port, using the authentication context provided. This |
149 * provided. |
429 * endpoint acts as the client, and may rejoin an existing SSL session |
150 * |
430 * if appropriate. |
151 * This endpoint acts as the client, and may rejoin an existing SSL |
431 * |
152 * session if appropriate. |
432 * @param context authentication context to use |
153 */ |
433 * @param address the server's host |
154 SSLSocketImpl(SSLContextImpl sslContext, |
434 * @param port its port |
155 InetAddress address, int peerPort) throws IOException { |
435 */ |
|
436 SSLSocketImpl(SSLContextImpl context, InetAddress host, int port) |
|
437 throws IOException { |
|
438 super(); |
156 super(); |
439 init(context, false); |
157 this.sslContext = sslContext; |
440 SocketAddress socketAddress = new InetSocketAddress(host, port); |
158 HandshakeHash handshakeHash = new HandshakeHash(); |
|
159 this.conContext = new TransportContext(sslContext, this, |
|
160 new SSLSocketInputRecord(handshakeHash), |
|
161 new SSLSocketOutputRecord(handshakeHash), true); |
|
162 |
|
163 SocketAddress socketAddress = new InetSocketAddress(address, peerPort); |
441 connect(socketAddress, 0); |
164 connect(socketAddress, 0); |
442 } |
165 } |
443 |
166 |
444 /** |
167 /** |
445 * Constructs an SSL connection to a named host at a specified port, |
168 * Constructs an SSL connection to a named host at a specified |
446 * using the authentication context provided. This endpoint acts as |
169 * port, using the authentication context provided. |
447 * the client, and may rejoin an existing SSL session if appropriate. |
170 * |
448 * |
171 * This endpoint acts as the client, and may rejoin an existing SSL |
449 * @param context authentication context to use |
172 * session if appropriate. |
450 * @param host name of the host with which to connect |
173 */ |
451 * @param port number of the server's port |
174 SSLSocketImpl(SSLContextImpl sslContext, |
452 * @param localAddr the local address the socket is bound to |
175 String peerHost, int peerPort, InetAddress localAddr, |
453 * @param localPort the local port the socket is bound to |
176 int localPort) throws IOException, UnknownHostException { |
454 */ |
|
455 SSLSocketImpl(SSLContextImpl context, String host, int port, |
|
456 InetAddress localAddr, int localPort) |
|
457 throws IOException, UnknownHostException { |
|
458 super(); |
177 super(); |
459 this.host = host; |
178 this.sslContext = sslContext; |
460 this.serverNames = |
179 HandshakeHash handshakeHash = new HandshakeHash(); |
461 Utilities.addToSNIServerNameList(this.serverNames, this.host); |
180 this.conContext = new TransportContext(sslContext, this, |
462 init(context, false); |
181 new SSLSocketInputRecord(handshakeHash), |
|
182 new SSLSocketOutputRecord(handshakeHash), true); |
|
183 this.peerHost = peerHost; |
|
184 |
463 bind(new InetSocketAddress(localAddr, localPort)); |
185 bind(new InetSocketAddress(localAddr, localPort)); |
464 SocketAddress socketAddress = |
186 SocketAddress socketAddress = |
465 host != null ? new InetSocketAddress(host, port) : |
187 peerHost != null ? new InetSocketAddress(peerHost, peerPort) : |
466 new InetSocketAddress(InetAddress.getByName(null), port); |
188 new InetSocketAddress(InetAddress.getByName(null), peerPort); |
467 connect(socketAddress, 0); |
189 connect(socketAddress, 0); |
468 } |
190 } |
469 |
191 |
470 |
192 /** |
471 /** |
193 * Constructs an SSL connection to a server at a specified |
472 * Constructs an SSL connection to a server at a specified address. |
194 * address, and TCP port, using the authentication context |
473 * and TCP port, using the authentication context provided. This |
195 * provided. |
474 * endpoint acts as the client, and may rejoin an existing SSL session |
196 * |
475 * if appropriate. |
197 * This endpoint acts as the client, and may rejoin an existing SSL |
476 * |
198 * session if appropriate. |
477 * @param context authentication context to use |
199 */ |
478 * @param address the server's host |
200 SSLSocketImpl(SSLContextImpl sslContext, |
479 * @param port its port |
201 InetAddress peerAddr, int peerPort, |
480 * @param localAddr the local address the socket is bound to |
202 InetAddress localAddr, int localPort) throws IOException { |
481 * @param localPort the local port the socket is bound to |
|
482 */ |
|
483 SSLSocketImpl(SSLContextImpl context, InetAddress host, int port, |
|
484 InetAddress localAddr, int localPort) |
|
485 throws IOException { |
|
486 super(); |
203 super(); |
487 init(context, false); |
204 this.sslContext = sslContext; |
|
205 HandshakeHash handshakeHash = new HandshakeHash(); |
|
206 this.conContext = new TransportContext(sslContext, this, |
|
207 new SSLSocketInputRecord(handshakeHash), |
|
208 new SSLSocketOutputRecord(handshakeHash), true); |
|
209 |
488 bind(new InetSocketAddress(localAddr, localPort)); |
210 bind(new InetSocketAddress(localAddr, localPort)); |
489 SocketAddress socketAddress = new InetSocketAddress(host, port); |
211 SocketAddress socketAddress = new InetSocketAddress(peerAddr, peerPort); |
490 connect(socketAddress, 0); |
212 connect(socketAddress, 0); |
491 } |
213 } |
492 |
214 |
493 /* |
215 /** |
494 * Package-private constructor used ONLY by SSLServerSocket. The |
216 * Creates a server mode {@link Socket} layered over an |
495 * java.net package accepts the TCP connection after this call is |
217 * existing connected socket, and is able to read data which has |
496 * made. This just initializes handshake state to use "server mode", |
218 * already been consumed/removed from the {@link Socket}'s |
497 * giving control over the use of SSL client authentication. |
219 * underlying {@link InputStream}. |
498 */ |
220 */ |
499 SSLSocketImpl(SSLContextImpl context, boolean serverMode, |
221 SSLSocketImpl(SSLContextImpl sslContext, Socket sock, |
500 CipherSuiteList suites, ClientAuthType clientAuth, |
222 InputStream consumed, boolean autoClose) throws IOException { |
501 boolean sessionCreation, ProtocolList protocols, |
223 |
502 String identificationProtocol, |
224 super(sock, consumed); |
503 AlgorithmConstraints algorithmConstraints, |
225 // We always layer over a connected socket |
504 Collection<SNIMatcher> sniMatchers, |
226 if (!sock.isConnected()) { |
505 boolean preferLocalCipherSuites, |
227 throw new SocketException("Underlying socket is not connected"); |
506 String[] applicationProtocols) throws IOException { |
228 } |
507 |
229 |
508 super(); |
230 this.sslContext = sslContext; |
509 doClientAuth = clientAuth; |
231 HandshakeHash handshakeHash = new HandshakeHash(); |
510 enableSessionCreation = sessionCreation; |
232 this.conContext = new TransportContext(sslContext, this, |
511 this.identificationProtocol = identificationProtocol; |
233 new SSLSocketInputRecord(handshakeHash), |
512 this.algorithmConstraints = algorithmConstraints; |
234 new SSLSocketOutputRecord(handshakeHash), false); |
513 this.sniMatchers = sniMatchers; |
235 this.autoClose = autoClose; |
514 this.preferLocalCipherSuites = preferLocalCipherSuites; |
236 doneConnect(); |
515 this.applicationProtocols = applicationProtocols; |
237 } |
516 init(context, serverMode); |
238 |
517 |
239 /** |
518 /* |
240 * Layer SSL traffic over an existing connection, rather than |
519 * Override what was picked out for us. |
241 * creating a new connection. |
520 */ |
242 * |
521 enabledCipherSuites = suites; |
243 * The existing connection may be used only for SSL traffic (using this |
522 enabledProtocols = protocols; |
244 * SSLSocket) until the SSLSocket.close() call returns. However, if a |
523 } |
245 * protocol error is detected, that existing connection is automatically |
524 |
246 * closed. |
525 |
247 * <p> |
526 /** |
248 * This particular constructor always uses the socket in the |
527 * Package-private constructor used to instantiate an unconnected |
|
528 * socket. The java.net package will connect it, either when the |
|
529 * connect() call is made by the application. This instance is |
|
530 * meant to set handshake state to use "client mode". |
|
531 */ |
|
532 SSLSocketImpl(SSLContextImpl context) { |
|
533 super(); |
|
534 init(context, false); |
|
535 } |
|
536 |
|
537 |
|
538 /** |
|
539 * Layer SSL traffic over an existing connection, rather than creating |
|
540 * a new connection. The existing connection may be used only for SSL |
|
541 * traffic (using this SSLSocket) until the SSLSocket.close() call |
|
542 * returns. However, if a protocol error is detected, that existing |
|
543 * connection is automatically closed. |
|
544 * |
|
545 * <P> This particular constructor always uses the socket in the |
|
546 * role of an SSL client. It may be useful in cases which start |
249 * role of an SSL client. It may be useful in cases which start |
547 * using SSL after some initial data transfers, for example in some |
250 * using SSL after some initial data transfers, for example in some |
548 * SSL tunneling applications or as part of some kinds of application |
251 * SSL tunneling applications or as part of some kinds of application |
549 * protocols which negotiate use of a SSL based security. |
252 * protocols which negotiate use of a SSL based security. |
550 * |
253 */ |
551 * @param sock the existing connection |
254 SSLSocketImpl(SSLContextImpl sslContext, Socket sock, |
552 * @param context the authentication context to use |
255 String peerHost, int port, boolean autoClose) throws IOException { |
553 */ |
|
554 SSLSocketImpl(SSLContextImpl context, Socket sock, String host, |
|
555 int port, boolean autoClose) throws IOException { |
|
556 super(sock); |
256 super(sock); |
557 // We always layer over a connected socket |
257 // We always layer over a connected socket |
558 if (!sock.isConnected()) { |
258 if (!sock.isConnected()) { |
559 throw new SocketException("Underlying socket is not connected"); |
259 throw new SocketException("Underlying socket is not connected"); |
560 } |
260 } |
561 this.host = host; |
261 |
562 this.serverNames = |
262 this.sslContext = sslContext; |
563 Utilities.addToSNIServerNameList(this.serverNames, this.host); |
263 HandshakeHash handshakeHash = new HandshakeHash(); |
564 init(context, false); |
264 this.conContext = new TransportContext(sslContext, this, |
|
265 new SSLSocketInputRecord(handshakeHash), |
|
266 new SSLSocketOutputRecord(handshakeHash), true); |
|
267 this.peerHost = peerHost; |
565 this.autoClose = autoClose; |
268 this.autoClose = autoClose; |
566 doneConnect(); |
269 doneConnect(); |
567 } |
270 } |
568 |
271 |
569 /** |
272 @Override |
570 * Creates a server mode {@link Socket} layered over an |
273 public void connect(SocketAddress endpoint, |
571 * existing connected socket, and is able to read data which has |
274 int timeout) throws IOException { |
572 * already been consumed/removed from the {@link Socket}'s |
|
573 * underlying {@link InputStream}. |
|
574 */ |
|
575 SSLSocketImpl(SSLContextImpl context, Socket sock, |
|
576 InputStream consumed, boolean autoClose) throws IOException { |
|
577 super(sock, consumed); |
|
578 // We always layer over a connected socket |
|
579 if (!sock.isConnected()) { |
|
580 throw new SocketException("Underlying socket is not connected"); |
|
581 } |
|
582 |
|
583 // In server mode, it is not necessary to set host and serverNames. |
|
584 // Otherwise, would require a reverse DNS lookup to get the hostname. |
|
585 |
|
586 init(context, true); |
|
587 this.autoClose = autoClose; |
|
588 doneConnect(); |
|
589 } |
|
590 |
|
591 /** |
|
592 * Initializes the client socket. |
|
593 */ |
|
594 private void init(SSLContextImpl context, boolean isServer) { |
|
595 sslContext = context; |
|
596 sess = SSLSessionImpl.nullSession; |
|
597 handshakeSession = null; |
|
598 |
|
599 /* |
|
600 * role is as specified, state is START until after |
|
601 * the low level connection's established. |
|
602 */ |
|
603 roleIsServer = isServer; |
|
604 connectionState = cs_START; |
|
605 |
|
606 // initial security parameters for secure renegotiation |
|
607 secureRenegotiation = false; |
|
608 clientVerifyData = new byte[0]; |
|
609 serverVerifyData = new byte[0]; |
|
610 |
|
611 enabledCipherSuites = |
|
612 sslContext.getDefaultCipherSuiteList(roleIsServer); |
|
613 enabledProtocols = |
|
614 sslContext.getDefaultProtocolList(roleIsServer); |
|
615 |
|
616 inputRecord = new SSLSocketInputRecord();; |
|
617 outputRecord = new SSLSocketOutputRecord(); |
|
618 |
|
619 maximumPacketSize = outputRecord.getMaxPacketSize(); |
|
620 |
|
621 // save the acc |
|
622 acc = AccessController.getContext(); |
|
623 |
|
624 input = new AppInputStream(this); |
|
625 output = new AppOutputStream(this); |
|
626 } |
|
627 |
|
628 /** |
|
629 * Connects this socket to the server with a specified timeout |
|
630 * value. |
|
631 * |
|
632 * This method is either called on an unconnected SSLSocketImpl by the |
|
633 * application, or it is called in the constructor of a regular |
|
634 * SSLSocketImpl. If we are layering on top on another socket, then |
|
635 * this method should not be called, because we assume that the |
|
636 * underlying socket is already connected by the time it is passed to |
|
637 * us. |
|
638 * |
|
639 * @param endpoint the <code>SocketAddress</code> |
|
640 * @param timeout the timeout value to be used, 0 is no timeout |
|
641 * @throws IOException if an error occurs during the connection |
|
642 * @throws SocketTimeoutException if timeout expires before connecting |
|
643 */ |
|
644 @Override |
|
645 public void connect(SocketAddress endpoint, int timeout) |
|
646 throws IOException { |
|
647 |
275 |
648 if (isLayered()) { |
276 if (isLayered()) { |
649 throw new SocketException("Already connected"); |
277 throw new SocketException("Already connected"); |
650 } |
278 } |
651 |
279 |
652 if (!(endpoint instanceof InetSocketAddress)) { |
280 if (!(endpoint instanceof InetSocketAddress)) { |
653 throw new SocketException( |
281 throw new SocketException( |
654 "Cannot handle non-Inet socket addresses."); |
282 "Cannot handle non-Inet socket addresses."); |
655 } |
283 } |
656 |
284 |
657 super.connect(endpoint, timeout); |
285 super.connect(endpoint, timeout); |
658 |
|
659 if (host == null || host.length() == 0) { |
|
660 useImplicitHost(false); |
|
661 } |
|
662 |
|
663 doneConnect(); |
286 doneConnect(); |
664 } |
287 } |
665 |
288 |
666 /** |
289 @Override |
667 * Initialize the handshaker and socket streams. |
290 public String[] getSupportedCipherSuites() { |
668 * |
291 return CipherSuite.namesOf(sslContext.getSupportedCipherSuites()); |
669 * Called by connect, the layered constructor, and SSLServerSocket. |
292 } |
670 */ |
293 |
671 void doneConnect() throws IOException { |
294 @Override |
672 /* |
295 public synchronized String[] getEnabledCipherSuites() { |
673 * Save the input and output streams. May be done only after |
296 return CipherSuite.namesOf(conContext.sslConfig.enabledCipherSuites); |
674 * java.net actually connects using the socket "self", else |
297 } |
675 * we get some pretty bizarre failure modes. |
298 |
|
299 @Override |
|
300 public synchronized void setEnabledCipherSuites(String[] suites) { |
|
301 if (suites == null) { |
|
302 throw new IllegalArgumentException("CipherSuites cannot be null"); |
|
303 } |
|
304 |
|
305 conContext.sslConfig.enabledCipherSuites = |
|
306 CipherSuite.validValuesOf(suites); |
|
307 } |
|
308 |
|
309 @Override |
|
310 public String[] getSupportedProtocols() { |
|
311 return ProtocolVersion.toStringArray( |
|
312 sslContext.getSuportedProtocolVersions()); |
|
313 } |
|
314 |
|
315 @Override |
|
316 public synchronized String[] getEnabledProtocols() { |
|
317 return ProtocolVersion.toStringArray( |
|
318 conContext.sslConfig.enabledProtocols); |
|
319 } |
|
320 |
|
321 @Override |
|
322 public synchronized void setEnabledProtocols(String[] protocols) { |
|
323 if (protocols == null) { |
|
324 throw new IllegalArgumentException("Protocols cannot be null"); |
|
325 } |
|
326 |
|
327 conContext.sslConfig.enabledProtocols = |
|
328 ProtocolVersion.namesOf(protocols); |
|
329 } |
|
330 |
|
331 @Override |
|
332 public synchronized SSLSession getSession() { |
|
333 try { |
|
334 // start handshaking, if failed, the connection will be closed. |
|
335 ensureNegotiated(); |
|
336 } catch (IOException ioe) { |
|
337 if (SSLLogger.isOn && SSLLogger.isOn("handshake")) { |
|
338 SSLLogger.severe("handshake failed", ioe); |
|
339 } |
|
340 |
|
341 return SSLSessionImpl.nullSession; |
|
342 } |
|
343 |
|
344 return conContext.conSession; |
|
345 } |
|
346 |
|
347 @Override |
|
348 public synchronized SSLSession getHandshakeSession() { |
|
349 if (conContext.handshakeContext != null) { |
|
350 return conContext.handshakeContext.handshakeSession; |
|
351 } |
|
352 |
|
353 return null; |
|
354 } |
|
355 |
|
356 @Override |
|
357 public synchronized void addHandshakeCompletedListener( |
|
358 HandshakeCompletedListener listener) { |
|
359 if (listener == null) { |
|
360 throw new IllegalArgumentException("listener is null"); |
|
361 } |
|
362 |
|
363 conContext.sslConfig.addHandshakeCompletedListener(listener); |
|
364 } |
|
365 |
|
366 @Override |
|
367 public synchronized void removeHandshakeCompletedListener( |
|
368 HandshakeCompletedListener listener) { |
|
369 if (listener == null) { |
|
370 throw new IllegalArgumentException("listener is null"); |
|
371 } |
|
372 |
|
373 conContext.sslConfig.removeHandshakeCompletedListener(listener); |
|
374 } |
|
375 |
|
376 @Override |
|
377 public synchronized void startHandshake() throws IOException { |
|
378 checkWrite(); |
|
379 try { |
|
380 conContext.kickstart(); |
|
381 |
|
382 // All initial handshaking goes through this operation until we |
|
383 // have a valid SSL connection. |
|
384 // |
|
385 // Handle handshake messages only, need no application data. |
|
386 if (!conContext.isNegotiated) { |
|
387 readRecord(); |
|
388 } |
|
389 } catch (IOException ioe) { |
|
390 conContext.fatal(Alert.HANDSHAKE_FAILURE, |
|
391 "Couldn't kickstart handshaking", ioe); |
|
392 } catch (Exception oe) { // including RuntimeException |
|
393 handleException(oe); |
|
394 } |
|
395 } |
|
396 |
|
397 @Override |
|
398 public synchronized void setUseClientMode(boolean mode) { |
|
399 conContext.setUseClientMode(mode); |
|
400 } |
|
401 |
|
402 @Override |
|
403 public synchronized boolean getUseClientMode() { |
|
404 return conContext.sslConfig.isClientMode; |
|
405 } |
|
406 |
|
407 @Override |
|
408 public synchronized void setNeedClientAuth(boolean need) { |
|
409 conContext.sslConfig.clientAuthType = |
|
410 (need ? ClientAuthType.CLIENT_AUTH_REQUIRED : |
|
411 ClientAuthType.CLIENT_AUTH_NONE); |
|
412 } |
|
413 |
|
414 @Override |
|
415 public synchronized boolean getNeedClientAuth() { |
|
416 return (conContext.sslConfig.clientAuthType == |
|
417 ClientAuthType.CLIENT_AUTH_REQUIRED); |
|
418 } |
|
419 |
|
420 @Override |
|
421 public synchronized void setWantClientAuth(boolean want) { |
|
422 conContext.sslConfig.clientAuthType = |
|
423 (want ? ClientAuthType.CLIENT_AUTH_REQUESTED : |
|
424 ClientAuthType.CLIENT_AUTH_NONE); |
|
425 } |
|
426 |
|
427 @Override |
|
428 public synchronized boolean getWantClientAuth() { |
|
429 return (conContext.sslConfig.clientAuthType == |
|
430 ClientAuthType.CLIENT_AUTH_REQUESTED); |
|
431 } |
|
432 |
|
433 @Override |
|
434 public synchronized void setEnableSessionCreation(boolean flag) { |
|
435 conContext.sslConfig.enableSessionCreation = flag; |
|
436 } |
|
437 |
|
438 @Override |
|
439 public synchronized boolean getEnableSessionCreation() { |
|
440 return conContext.sslConfig.enableSessionCreation; |
|
441 } |
|
442 |
|
443 @Override |
|
444 public synchronized boolean isClosed() { |
|
445 return tlsIsClosed && conContext.isClosed(); |
|
446 } |
|
447 |
|
448 @Override |
|
449 public synchronized void close() throws IOException { |
|
450 try { |
|
451 conContext.close(); |
|
452 } catch (IOException ioe) { |
|
453 // ignore the exception |
|
454 if (SSLLogger.isOn && SSLLogger.isOn("ssl")) { |
|
455 SSLLogger.warning("connection context closure failed", ioe); |
|
456 } |
|
457 } finally { |
|
458 tlsIsClosed = true; |
|
459 } |
|
460 } |
|
461 |
|
462 @Override |
|
463 public synchronized InputStream getInputStream() throws IOException { |
|
464 if (isClosed() || conContext.isInboundDone()) { |
|
465 throw new SocketException("Socket or inbound is closed"); |
|
466 } |
|
467 |
|
468 if (!isConnected) { |
|
469 throw new SocketException("Socket is not connected"); |
|
470 } |
|
471 |
|
472 return appInput; |
|
473 } |
|
474 |
|
475 private synchronized void ensureNegotiated() throws IOException { |
|
476 if (conContext.isNegotiated || conContext.isClosed()) { |
|
477 return; |
|
478 } |
|
479 |
|
480 startHandshake(); |
|
481 } |
|
482 |
|
483 private class AppInputStream extends InputStream { |
|
484 // One element array used to implement the single byte read() method |
|
485 private final byte[] oneByte = new byte[1]; |
|
486 |
|
487 // the temporary buffer used to read network |
|
488 private ByteBuffer buffer; |
|
489 |
|
490 // Is application data available in the stream? |
|
491 private boolean appDataIsAvailable; |
|
492 |
|
493 AppInputStream() { |
|
494 this.appDataIsAvailable = false; |
|
495 this.buffer = ByteBuffer.allocate(4096); |
|
496 } |
|
497 |
|
498 /** |
|
499 * Return the minimum number of bytes that can be read |
|
500 * without blocking. |
676 */ |
501 */ |
677 sockInput = super.getInputStream(); |
502 @Override |
678 sockOutput = super.getOutputStream(); |
503 public int available() throws IOException { |
679 |
504 // Currently not synchronized. |
680 inputRecord.setDeliverStream(sockOutput); |
505 if ((!appDataIsAvailable) || checkEOF()) { |
681 outputRecord.setDeliverStream(sockOutput); |
506 return 0; |
682 |
507 } |
683 /* |
508 |
684 * Move to handshaking state, with pending session initialized |
509 return buffer.remaining(); |
685 * to defaults and the appropriate kind of handshaker set up. |
510 } |
|
511 |
|
512 /** |
|
513 * Read a single byte, returning -1 on non-fault EOF status. |
686 */ |
514 */ |
687 initHandshaker(); |
515 @Override |
688 } |
516 public synchronized int read() throws IOException { |
689 |
517 int n = read(oneByte, 0, 1); |
690 private synchronized int getConnectionState() { |
518 if (n <= 0) { // EOF |
691 return connectionState; |
519 return -1; |
692 } |
520 } |
693 |
521 |
694 private synchronized void setConnectionState(int state) { |
522 return oneByte[0] & 0xFF; |
695 connectionState = state; |
523 } |
696 } |
524 |
697 |
525 /** |
698 AccessControlContext getAcc() { |
526 * Reads up to {@code len} bytes of data from the input stream |
699 return acc; |
527 * into an array of bytes. |
700 } |
528 * |
701 |
529 * An attempt is made to read as many as {@code len} bytes, but a |
702 // |
530 * smaller number may be read. The number of bytes actually read |
703 // READING AND WRITING RECORDS |
531 * is returned as an integer. |
704 // |
532 * |
705 |
533 * If the layer above needs more data, it asks for more, so we |
706 /* |
534 * are responsible only for blocking to fill at most one buffer, |
707 * Application data record output. |
535 * and returning "-1" on non-fault EOF status. |
708 * |
|
709 * Application data can't be sent until the first handshake establishes |
|
710 * a session. |
|
711 */ |
|
712 void writeRecord(byte[] source, int offset, int length) throws IOException { |
|
713 /* |
|
714 * The loop is in case of HANDSHAKE --> ERROR transitions, etc |
|
715 */ |
536 */ |
716 // Don't bother to check the emptiness of source applicatoin data |
537 @Override |
717 // before the security connection established. |
538 public synchronized int read(byte[] b, int off, int len) |
718 for (boolean readyForApp = false; !readyForApp;) { |
539 throws IOException { |
719 /* |
540 if (b == null) { |
720 * Not all states support passing application data. We |
541 throw new NullPointerException("the target buffer is null"); |
721 * synchronize access to the connection state, so that |
542 } else if (off < 0 || len < 0 || len > b.length - off) { |
722 * synchronous handshakes can complete cleanly. |
543 throw new IndexOutOfBoundsException( |
723 */ |
544 "buffer length: " + b.length + ", offset; " + off + |
724 switch (getConnectionState()) { |
545 ", bytes to read:" + len); |
725 |
546 } else if (len == 0) { |
726 /* |
547 return 0; |
727 * We've deferred the initial handshaking till just now, |
548 } |
728 * when presumably a thread's decided it's OK to block for |
549 |
729 * longish periods of time for I/O purposes (as well as |
550 if (checkEOF()) { |
730 * configured the cipher suites it wants to use). |
551 return -1; |
731 */ |
552 } |
732 case cs_HANDSHAKE: |
553 |
733 performInitialHandshake(); |
554 // start handshaking if the connection has not been negotiated. |
|
555 if (!conContext.isNegotiated && !conContext.isClosed()) { |
|
556 ensureNegotiated(); |
|
557 } |
|
558 |
|
559 // Read the available bytes at first. |
|
560 int remains = available(); |
|
561 if (remains > 0) { |
|
562 int howmany = Math.min(remains, len); |
|
563 buffer.get(b, off, howmany); |
|
564 |
|
565 return howmany; |
|
566 } |
|
567 |
|
568 appDataIsAvailable = false; |
|
569 int volume = 0; |
|
570 try { |
|
571 while (volume == 0) { |
|
572 // Clear the buffer for a new record reading. |
|
573 buffer.clear(); |
|
574 |
|
575 // grow the buffer if needed |
|
576 int inLen = conContext.inputRecord.bytesInCompletePacket(); |
|
577 if (inLen < 0) { // EOF |
|
578 // treat like receiving a close_notify warning message. |
|
579 conContext.isInputCloseNotified = true; |
|
580 conContext.closeInbound(); |
|
581 return -1; |
|
582 } |
|
583 |
|
584 // Is this packet bigger than SSL/TLS normally allows? |
|
585 if (inLen > SSLRecord.maxLargeRecordSize) { |
|
586 throw new SSLProtocolException( |
|
587 "Illegal packet size: " + inLen); |
|
588 } |
|
589 |
|
590 if (inLen > buffer.remaining()) { |
|
591 buffer = ByteBuffer.allocate(inLen); |
|
592 } |
|
593 |
|
594 volume = readRecord(buffer); |
|
595 buffer.flip(); |
|
596 if (volume < 0) { // EOF |
|
597 // treat like receiving a close_notify warning message. |
|
598 conContext.isInputCloseNotified = true; |
|
599 conContext.closeInbound(); |
|
600 return -1; |
|
601 } else if (volume > 0) { |
|
602 appDataIsAvailable = true; |
|
603 break; |
|
604 } |
|
605 } |
|
606 |
|
607 // file the destination buffer |
|
608 int howmany = Math.min(len, volume); |
|
609 buffer.get(b, off, howmany); |
|
610 return howmany; |
|
611 } catch (Exception e) { // including RuntimeException |
|
612 // shutdown and rethrow (wrapped) exception as appropriate |
|
613 handleException(e); |
|
614 |
|
615 // dummy for compiler |
|
616 return -1; |
|
617 } |
|
618 } |
|
619 |
|
620 /** |
|
621 * Skip n bytes. |
|
622 * |
|
623 * This implementation is somewhat less efficient than possible, but |
|
624 * not badly so (redundant copy). We reuse the read() code to keep |
|
625 * things simpler. Note that SKIP_ARRAY is static and may garbled by |
|
626 * concurrent use, but we are not interested in the data anyway. |
|
627 */ |
|
628 @Override |
|
629 public synchronized long skip(long n) throws IOException { |
|
630 // dummy array used to implement skip() |
|
631 byte[] skipArray = new byte[256]; |
|
632 |
|
633 long skipped = 0; |
|
634 while (n > 0) { |
|
635 int len = (int)Math.min(n, skipArray.length); |
|
636 int r = read(skipArray, 0, len); |
|
637 if (r <= 0) { |
734 break; |
638 break; |
735 |
639 } |
736 case cs_DATA: |
640 n -= r; |
737 case cs_RENEGOTIATE: |
641 skipped += r; |
738 readyForApp = true; |
642 } |
739 break; |
643 |
740 |
644 return skipped; |
741 case cs_ERROR: |
645 } |
742 fatal(Alerts.alert_close_notify, |
646 |
743 "error while writing to socket"); |
647 @Override |
744 break; // dummy |
648 public void close() throws IOException { |
745 |
649 if (SSLLogger.isOn && SSLLogger.isOn("ssl")) { |
746 case cs_SENT_CLOSE: |
650 SSLLogger.finest("Closing input stream"); |
747 case cs_CLOSED: |
651 } |
748 case cs_APP_CLOSED: |
652 |
749 // we should never get here (check in AppOutputStream) |
653 conContext.closeInbound(); |
750 // this is just a fallback |
654 } |
751 if (closeReason != null) { |
655 } |
752 throw closeReason; |
656 |
753 } else { |
657 @Override |
754 throw new SocketException("Socket closed"); |
658 public synchronized OutputStream getOutputStream() throws IOException { |
755 } |
659 if (isClosed() || conContext.isOutboundDone()) { |
756 |
660 throw new SocketException("Socket or outbound is closed"); |
757 /* |
661 } |
758 * Else something's goofy in this state machine's use. |
662 |
759 */ |
663 if (!isConnected) { |
760 default: |
664 throw new SocketException("Socket is not connected"); |
761 throw new SSLProtocolException( |
665 } |
762 "State error, send app data"); |
666 |
763 } |
667 return appOutput; |
|
668 } |
|
669 |
|
670 private class AppOutputStream extends OutputStream { |
|
671 // One element array used to implement the write(byte) method |
|
672 private final byte[] oneByte = new byte[1]; |
|
673 |
|
674 @Override |
|
675 public void write(int i) throws IOException { |
|
676 oneByte[0] = (byte)i; |
|
677 write(oneByte, 0, 1); |
|
678 } |
|
679 |
|
680 @Override |
|
681 public synchronized void write(byte[] b, |
|
682 int off, int len) throws IOException { |
|
683 if (b == null) { |
|
684 throw new NullPointerException("the source buffer is null"); |
|
685 } else if (off < 0 || len < 0 || len > b.length - off) { |
|
686 throw new IndexOutOfBoundsException( |
|
687 "buffer length: " + b.length + ", offset; " + off + |
|
688 ", bytes to read:" + len); |
|
689 } else if (len == 0) { |
|
690 return; |
|
691 } |
|
692 |
|
693 // start handshaking if the connection has not been negotiated. |
|
694 if (!conContext.isNegotiated && !conContext.isClosed()) { |
|
695 ensureNegotiated(); |
|
696 } |
|
697 |
|
698 // check if the Socket is invalid (error or closed) |
|
699 checkWrite(); |
|
700 |
|
701 // Delegate the writing to the underlying socket. |
|
702 try { |
|
703 writeRecord(b, off, len); |
|
704 checkWrite(); |
|
705 } catch (IOException ioe) { |
|
706 // shutdown and rethrow (wrapped) exception as appropriate |
|
707 handleException(ioe); |
|
708 } |
|
709 } |
|
710 |
|
711 @Override |
|
712 public void close() throws IOException { |
|
713 if (SSLLogger.isOn && SSLLogger.isOn("ssl")) { |
|
714 SSLLogger.finest("Closing output stream"); |
|
715 } |
|
716 |
|
717 conContext.closeOutbound(); |
|
718 } |
|
719 } |
|
720 |
|
721 @Override |
|
722 public synchronized SSLParameters getSSLParameters() { |
|
723 return conContext.sslConfig.getSSLParameters(); |
|
724 } |
|
725 |
|
726 @Override |
|
727 public synchronized void setSSLParameters(SSLParameters params) { |
|
728 conContext.sslConfig.setSSLParameters(params); |
|
729 |
|
730 if (conContext.sslConfig.maximumPacketSize != 0) { |
|
731 conContext.outputRecord.changePacketSize( |
|
732 conContext.sslConfig.maximumPacketSize); |
|
733 } |
|
734 } |
|
735 |
|
736 @Override |
|
737 public synchronized String getApplicationProtocol() { |
|
738 return conContext.applicationProtocol; |
|
739 } |
|
740 |
|
741 @Override |
|
742 public synchronized String getHandshakeApplicationProtocol() { |
|
743 if (conContext.handshakeContext != null) { |
|
744 return conContext.handshakeContext.applicationProtocol; |
|
745 } |
|
746 |
|
747 return null; |
|
748 } |
|
749 |
|
750 @Override |
|
751 public synchronized void setHandshakeApplicationProtocolSelector( |
|
752 BiFunction<SSLSocket, List<String>, String> selector) { |
|
753 conContext.sslConfig.socketAPSelector = selector; |
|
754 } |
|
755 |
|
756 @Override |
|
757 public synchronized BiFunction<SSLSocket, List<String>, String> |
|
758 getHandshakeApplicationProtocolSelector() { |
|
759 return conContext.sslConfig.socketAPSelector; |
|
760 } |
|
761 |
|
762 private synchronized void writeRecord(byte[] source, |
|
763 int offset, int length) throws IOException { |
|
764 if (conContext.isOutboundDone()) { |
|
765 throw new SocketException("Socket or outbound closed"); |
764 } |
766 } |
765 |
767 |
766 // |
768 // |
767 // Don't bother to really write empty records. We went this |
769 // Don't bother to really write empty records. We went this |
768 // far to drive the handshake machinery, for correctness; not |
770 // far to drive the handshake machinery, for correctness; not |
770 // time and network resource usage. However, some protocol |
772 // time and network resource usage. However, some protocol |
771 // implementations are fragile and don't like to see empty |
773 // implementations are fragile and don't like to see empty |
772 // records, so this also increases robustness. |
774 // records, so this also increases robustness. |
773 // |
775 // |
774 if (length > 0) { |
776 if (length > 0) { |
775 IOException ioe = null; |
|
776 byte description = 0; // 0: never used, make the compiler happy |
|
777 writeLock.lock(); |
|
778 try { |
777 try { |
779 outputRecord.deliver(source, offset, length); |
778 conContext.outputRecord.deliver(source, offset, length); |
780 } catch (SSLHandshakeException she) { |
779 } catch (SSLHandshakeException she) { |
781 // may be record sequence number overflow |
780 // may be record sequence number overflow |
782 description = Alerts.alert_handshake_failure; |
781 conContext.fatal(Alert.HANDSHAKE_FAILURE, she); |
783 ioe = she; |
|
784 } catch (IOException e) { |
782 } catch (IOException e) { |
785 description = Alerts.alert_unexpected_message; |
783 conContext.fatal(Alert.UNEXPECTED_MESSAGE, e); |
786 ioe = e; |
784 } |
787 } finally { |
785 } |
788 writeLock.unlock(); |
786 |
789 } |
787 // Is the sequence number is nearly overflow? |
790 |
788 if (conContext.outputRecord.seqNumIsHuge()) { |
791 // Be care of deadlock. Please don't place the call to fatal() |
789 tryKeyUpdate(); |
792 // into the writeLock locked block. |
790 } |
793 if (ioe != null) { |
791 } |
794 fatal(description, ioe); |
792 |
795 } |
793 private synchronized int readRecord() throws IOException { |
796 } |
794 while (!conContext.isInboundDone()) { |
797 |
795 try { |
798 /* |
796 Plaintext plainText = decode(null); |
799 * Check the sequence number state |
797 if ((plainText.contentType == ContentType.HANDSHAKE.id) && |
800 * |
798 conContext.isNegotiated) { |
801 * Note that in order to maintain the connection I/O |
799 return 0; |
802 * properly, we check the sequence number after the last |
800 } |
803 * record writing process. As we request renegotiation |
801 } catch (SSLException ssle) { |
804 * or close the connection for wrapped sequence number |
802 throw ssle; |
805 * when there is enough sequence number space left to |
803 } catch (IOException ioe) { |
806 * handle a few more records, so the sequence number |
804 throw new SSLException("readRecord", ioe); |
807 * of the last record cannot be wrapped. |
805 } |
808 * |
806 } |
809 * Don't bother to kickstart the renegotiation when the |
807 |
810 * local is asking for it. |
808 return -1; |
811 */ |
809 } |
812 if ((connectionState == cs_DATA) && outputRecord.seqNumIsHuge()) { |
810 |
|
811 private synchronized int readRecord(ByteBuffer buffer) throws IOException { |
|
812 while (!conContext.isInboundDone()) { |
813 /* |
813 /* |
814 * Ask for renegotiation when need to renew sequence number. |
814 * clean the buffer and check if it is too small, e.g. because |
815 * |
815 * the AppInputStream did not have the chance to see the |
816 * Don't bother to kickstart the renegotiation when the local is |
816 * current packet length but rather something like that of the |
817 * asking for it. |
817 * handshake before. In that case we return 0 at this point to |
|
818 * give the caller the chance to adjust the buffer. |
818 */ |
819 */ |
819 if (debug != null && Debug.isOn("ssl")) { |
820 buffer.clear(); |
820 System.out.println(Thread.currentThread().getName() + |
821 int inLen = conContext.inputRecord.bytesInCompletePacket(); |
821 ", request renegotiation " + |
822 if (inLen < 0) { // EOF |
822 "to avoid sequence number overflow"); |
823 return -1; |
823 } |
824 } |
824 |
825 |
825 startHandshake(); |
826 if (buffer.remaining() < inLen) { |
826 } |
827 return 0; |
827 } |
828 } |
828 |
829 |
829 /* |
|
830 * Alert record output. |
|
831 */ |
|
832 void writeAlert(byte level, byte description) throws IOException { |
|
833 |
|
834 // If the record is a close notify alert, we need to honor |
|
835 // socket option SO_LINGER. Note that we will try to send |
|
836 // the close notify even if the SO_LINGER set to zero. |
|
837 if ((description == Alerts.alert_close_notify) && getSoLinger() >= 0) { |
|
838 |
|
839 // keep and clear the current thread interruption status. |
|
840 boolean interrupted = Thread.interrupted(); |
|
841 try { |
830 try { |
842 if (writeLock.tryLock(getSoLinger(), TimeUnit.SECONDS)) { |
831 Plaintext plainText = decode(buffer); |
843 try { |
832 if (plainText.contentType == ContentType.APPLICATION_DATA.id) { |
844 outputRecord.encodeAlert(level, description); |
833 return buffer.position(); |
845 } finally { |
|
846 writeLock.unlock(); |
|
847 } |
|
848 } else { |
|
849 SSLException ssle = new SSLException( |
|
850 "SO_LINGER timeout," + |
|
851 " close_notify message cannot be sent."); |
|
852 |
|
853 |
|
854 // For layered, non-autoclose sockets, we are not |
|
855 // able to bring them into a usable state, so we |
|
856 // treat it as fatal error. |
|
857 if (isLayered() && !autoClose) { |
|
858 // Note that the alert description is |
|
859 // specified as -1, so no message will be send |
|
860 // to peer anymore. |
|
861 fatal((byte)(-1), ssle); |
|
862 } else if ((debug != null) && Debug.isOn("ssl")) { |
|
863 System.out.println( |
|
864 Thread.currentThread().getName() + |
|
865 ", received Exception: " + ssle); |
|
866 } |
|
867 |
|
868 // RFC2246 requires that the session becomes |
|
869 // unresumable if any connection is terminated |
|
870 // without proper close_notify messages with |
|
871 // level equal to warning. |
|
872 // |
|
873 // RFC4346 no longer requires that a session not be |
|
874 // resumed if failure to properly close a connection. |
|
875 // |
|
876 // We choose to make the session unresumable if |
|
877 // failed to send the close_notify message. |
|
878 // |
|
879 sess.invalidate(); |
|
880 } |
834 } |
881 } catch (InterruptedException ie) { |
835 } catch (SSLException ssle) { |
882 // keep interrupted status |
836 throw ssle; |
883 interrupted = true; |
837 } catch (IOException ioe) { |
884 } |
838 throw new SSLException("readRecord", ioe); |
885 |
839 } |
886 // restore the interrupted status |
840 } |
887 if (interrupted) { |
841 |
888 Thread.currentThread().interrupt(); |
842 // |
889 } |
843 // couldn't read, due to some kind of error |
|
844 // |
|
845 return -1; |
|
846 } |
|
847 |
|
848 private Plaintext decode(ByteBuffer destination) throws IOException { |
|
849 Plaintext plainText; |
|
850 if (destination == null) { |
|
851 plainText = SSLTransport.decode(conContext, |
|
852 null, 0, 0, null, 0, 0); |
890 } else { |
853 } else { |
891 writeLock.lock(); |
854 plainText = SSLTransport.decode(conContext, |
892 try { |
855 null, 0, 0, new ByteBuffer[]{destination}, 0, 1); |
893 outputRecord.encodeAlert(level, description); |
856 } |
894 } finally { |
857 |
895 writeLock.unlock(); |
858 // Is the sequence number is nearly overflow? |
896 } |
859 if (plainText != Plaintext.PLAINTEXT_NULL && |
897 } |
860 conContext.inputRecord.seqNumIsHuge()) { |
898 |
861 tryKeyUpdate(); |
899 // Don't bother to check sequence number overlap here. If sequence |
862 } |
900 // number is huge, there should be enough sequence number space to |
863 |
901 // request renegotiation in next application data read and write. |
864 return plainText; |
902 } |
865 } |
903 |
866 |
904 |
867 /** |
905 int bytesInCompletePacket() throws IOException { |
868 * Try renegotiation or key update for sequence number wrap. |
906 if (getConnectionState() == cs_HANDSHAKE) { |
869 * |
907 performInitialHandshake(); |
870 * Note that in order to maintain the handshake status properly, we check |
908 } |
871 * the sequence number after the last record reading/writing process. As |
909 |
872 * we request renegotiation or close the connection for wrapped sequence |
910 synchronized (readLock) { |
873 * number when there is enough sequence number space left to handle a few |
911 int state = getConnectionState(); |
874 * more records, so the sequence number of the last record cannot be |
912 if ((state == cs_CLOSED) || |
875 * wrapped. |
913 (state == cs_ERROR) || (state == cs_APP_CLOSED)) { |
876 */ |
914 return -1; |
877 private void tryKeyUpdate() throws IOException { |
915 } |
878 // Don't bother to kickstart the renegotiation or key update when the |
916 |
879 // local is asking for it. |
917 try { |
880 if ((conContext.handshakeContext == null) && |
918 return inputRecord.bytesInCompletePacket(sockInput); |
881 !conContext.isClosed() && !conContext.isBroken) { |
919 } catch (EOFException eofe) { |
882 if (SSLLogger.isOn && SSLLogger.isOn("ssl")) { |
920 boolean handshaking = (connectionState <= cs_HANDSHAKE); |
883 SSLLogger.finest("key update to wrap sequence number"); |
921 boolean rethrow = requireCloseNotify || handshaking; |
884 } |
922 if ((debug != null) && Debug.isOn("ssl")) { |
885 conContext.keyUpdate(); |
923 System.out.println(Thread.currentThread().getName() + |
886 } |
924 ", received EOFException: " |
|
925 + (rethrow ? "error" : "ignored")); |
|
926 } |
|
927 |
|
928 if (!rethrow) { |
|
929 // treat as if we had received a close_notify |
|
930 closeInternal(false); |
|
931 } else { |
|
932 SSLException e; |
|
933 if (handshaking) { |
|
934 e = new SSLHandshakeException( |
|
935 "Remote host terminated the handshake"); |
|
936 } else { |
|
937 e = new SSLProtocolException( |
|
938 "Remote host terminated the handshake"); |
|
939 } |
|
940 e.initCause(eofe); |
|
941 throw e; |
|
942 } |
|
943 } |
|
944 |
|
945 return -1; |
|
946 } |
|
947 } |
|
948 |
|
949 // the caller have synchronized readLock |
|
950 void expectingFinishFlight() { |
|
951 inputRecord.expectingFinishFlight(); |
|
952 } |
|
953 |
|
954 /* |
|
955 * Read an application data record. |
|
956 * |
|
957 * Alerts and handshake messages are internally handled directly. |
|
958 */ |
|
959 int readRecord(ByteBuffer buffer) throws IOException { |
|
960 if (getConnectionState() == cs_HANDSHAKE) { |
|
961 performInitialHandshake(); |
|
962 } |
|
963 |
|
964 return readRecord(buffer, true); |
|
965 } |
|
966 |
|
967 /* |
|
968 * Read a record, no application data input required. |
|
969 * |
|
970 * Alerts and handshake messages are internally handled directly. |
|
971 */ |
|
972 int readRecord(boolean needAppData) throws IOException { |
|
973 return readRecord(null, needAppData); |
|
974 } |
|
975 |
|
976 /* |
|
977 * Clear the pipeline of records from the peer, optionally returning |
|
978 * application data. Caller is responsible for knowing that it's |
|
979 * possible to do this kind of clearing, if they don't want app |
|
980 * data -- e.g. since it's the initial SSL handshake. |
|
981 * |
|
982 * Don't synchronize (this) during a blocking read() since it |
|
983 * protects data which is accessed on the write side as well. |
|
984 */ |
|
985 private int readRecord(ByteBuffer buffer, boolean needAppData) |
|
986 throws IOException { |
|
987 int state; |
|
988 |
|
989 // readLock protects reading and processing of an SSLInputRecord. |
|
990 // It keeps the reading from sockInput and processing of the record |
|
991 // atomic so that no two threads can be blocked on the |
|
992 // read from the same input stream at the same time. |
|
993 // This is required for example when a reader thread is |
|
994 // blocked on the read and another thread is trying to |
|
995 // close the socket. For a non-autoclose, layered socket, |
|
996 // the thread performing the close needs to read the close_notify. |
|
997 // |
|
998 // Use readLock instead of 'this' for locking because |
|
999 // 'this' also protects data accessed during writing. |
|
1000 synchronized (readLock) { |
|
1001 /* |
|
1002 * Read and handle records ... return application data |
|
1003 * ONLY if it's needed. |
|
1004 */ |
|
1005 Plaintext plainText = null; |
|
1006 while (((state = getConnectionState()) != cs_CLOSED) && |
|
1007 (state != cs_ERROR) && (state != cs_APP_CLOSED)) { |
|
1008 |
|
1009 /* |
|
1010 * clean the buffer and check if it is too small, e.g. because |
|
1011 * the AppInputStream did not have the chance to see the |
|
1012 * current packet length but rather something like that of the |
|
1013 * handshake before. In that case we return 0 at this point to |
|
1014 * give the caller the chance to adjust the buffer. |
|
1015 */ |
|
1016 if (buffer != null) { |
|
1017 buffer.clear(); |
|
1018 |
|
1019 if (buffer.remaining() < |
|
1020 inputRecord.bytesInCompletePacket(sockInput)) { |
|
1021 return 0; |
|
1022 } |
|
1023 } |
|
1024 |
|
1025 /* |
|
1026 * Read a record ... maybe emitting an alert if we get a |
|
1027 * comprehensible but unsupported "hello" message during |
|
1028 * format checking (e.g. V2). |
|
1029 */ |
|
1030 try { |
|
1031 plainText = inputRecord.decode(sockInput, buffer); |
|
1032 } catch (BadPaddingException bpe) { |
|
1033 byte alertType = (state != cs_DATA) ? |
|
1034 Alerts.alert_handshake_failure : |
|
1035 Alerts.alert_bad_record_mac; |
|
1036 fatal(alertType, bpe.getMessage(), bpe); |
|
1037 } catch (SSLProtocolException spe) { |
|
1038 try { |
|
1039 fatal(Alerts.alert_unexpected_message, spe); |
|
1040 } catch (IOException x) { |
|
1041 // discard this exception, throw the original exception |
|
1042 } |
|
1043 throw spe; |
|
1044 } catch (SSLHandshakeException she) { |
|
1045 // may be record sequence number overflow |
|
1046 fatal(Alerts.alert_handshake_failure, she); |
|
1047 } catch (EOFException eof) { |
|
1048 boolean handshaking = (connectionState <= cs_HANDSHAKE); |
|
1049 boolean rethrow = requireCloseNotify || handshaking; |
|
1050 if ((debug != null) && Debug.isOn("ssl")) { |
|
1051 System.out.println(Thread.currentThread().getName() + |
|
1052 ", received EOFException: " |
|
1053 + (rethrow ? "error" : "ignored")); |
|
1054 } |
|
1055 if (rethrow) { |
|
1056 SSLException e; |
|
1057 if (handshaking) { |
|
1058 e = new SSLHandshakeException( |
|
1059 "Remote host terminated the handshake"); |
|
1060 } else { |
|
1061 e = new SSLProtocolException( |
|
1062 "Remote host terminated the connection"); |
|
1063 } |
|
1064 e.initCause(eof); |
|
1065 throw e; |
|
1066 } else { |
|
1067 // treat as if we had received a close_notify |
|
1068 closeInternal(false); |
|
1069 continue; |
|
1070 } |
|
1071 } |
|
1072 |
|
1073 // PlainText should never be null. Process input record. |
|
1074 int volume = processInputRecord(plainText, needAppData); |
|
1075 |
|
1076 if (plainText.contentType == Record.ct_application_data) { |
|
1077 return volume; |
|
1078 } |
|
1079 |
|
1080 if (plainText.contentType == Record.ct_handshake) { |
|
1081 if (!needAppData && connectionState == cs_DATA) { |
|
1082 return volume; |
|
1083 } // otherwise, need to read more for app data. |
|
1084 } |
|
1085 |
|
1086 // continue to read more net data |
|
1087 } // while |
|
1088 |
|
1089 // |
|
1090 // couldn't read, due to some kind of error |
|
1091 // |
|
1092 return -1; |
|
1093 } // readLock synchronization |
|
1094 } |
|
1095 |
|
1096 /* |
|
1097 * Process the plainText input record. |
|
1098 */ |
|
1099 private synchronized int processInputRecord( |
|
1100 Plaintext plainText, boolean needAppData) throws IOException { |
|
1101 |
|
1102 /* |
|
1103 * Process the record. |
|
1104 */ |
|
1105 int volume = 0; // no application data |
|
1106 switch (plainText.contentType) { |
|
1107 case Record.ct_handshake: |
|
1108 /* |
|
1109 * Handshake messages always go to a pending session |
|
1110 * handshaker ... if there isn't one, create one. This |
|
1111 * must work asynchronously, for renegotiation. |
|
1112 * |
|
1113 * NOTE that handshaking will either resume a session |
|
1114 * which was in the cache (and which might have other |
|
1115 * connections in it already), or else will start a new |
|
1116 * session (new keys exchanged) with just this connection |
|
1117 * in it. |
|
1118 */ |
|
1119 initHandshaker(); |
|
1120 if (!handshaker.activated()) { |
|
1121 // prior to handshaking, activate the handshake |
|
1122 if (connectionState == cs_RENEGOTIATE) { |
|
1123 // don't use SSLv2Hello when renegotiating |
|
1124 handshaker.activate(protocolVersion); |
|
1125 } else { |
|
1126 handshaker.activate(null); |
|
1127 } |
|
1128 } |
|
1129 |
|
1130 /* |
|
1131 * process the handshake record ... may contain just |
|
1132 * a partial handshake message or multiple messages. |
|
1133 * |
|
1134 * The handshaker state machine will ensure that it's |
|
1135 * a finished message. |
|
1136 */ |
|
1137 handshaker.processRecord(plainText.fragment, expectingFinished); |
|
1138 expectingFinished = false; |
|
1139 |
|
1140 if (handshaker.invalidated) { |
|
1141 handshaker = null; |
|
1142 inputRecord.setHandshakeHash(null); |
|
1143 outputRecord.setHandshakeHash(null); |
|
1144 |
|
1145 // if state is cs_RENEGOTIATE, revert it to cs_DATA |
|
1146 if (connectionState == cs_RENEGOTIATE) { |
|
1147 connectionState = cs_DATA; |
|
1148 } |
|
1149 } else if (handshaker.isDone()) { |
|
1150 // reset the parameters for secure renegotiation. |
|
1151 secureRenegotiation = |
|
1152 handshaker.isSecureRenegotiation(); |
|
1153 clientVerifyData = handshaker.getClientVerifyData(); |
|
1154 serverVerifyData = handshaker.getServerVerifyData(); |
|
1155 // set connection ALPN value |
|
1156 applicationProtocol = |
|
1157 handshaker.getHandshakeApplicationProtocol(); |
|
1158 |
|
1159 sess = handshaker.getSession(); |
|
1160 handshakeSession = null; |
|
1161 handshaker = null; |
|
1162 inputRecord.setHandshakeHash(null); |
|
1163 outputRecord.setHandshakeHash(null); |
|
1164 connectionState = cs_DATA; |
|
1165 |
|
1166 // |
|
1167 // Tell folk about handshake completion, but do |
|
1168 // it in a separate thread. |
|
1169 // |
|
1170 if (handshakeListeners != null) { |
|
1171 HandshakeCompletedEvent event = |
|
1172 new HandshakeCompletedEvent(this, sess); |
|
1173 |
|
1174 Thread thread = new Thread( |
|
1175 null, |
|
1176 new NotifyHandshake( |
|
1177 handshakeListeners.entrySet(), event), |
|
1178 "HandshakeCompletedNotify-Thread", |
|
1179 0, |
|
1180 false); |
|
1181 thread.start(); |
|
1182 } |
|
1183 } |
|
1184 |
|
1185 break; |
|
1186 |
|
1187 case Record.ct_application_data: |
|
1188 if (connectionState != cs_DATA |
|
1189 && connectionState != cs_RENEGOTIATE |
|
1190 && connectionState != cs_SENT_CLOSE) { |
|
1191 throw new SSLProtocolException( |
|
1192 "Data received in non-data state: " + |
|
1193 connectionState); |
|
1194 } |
|
1195 if (expectingFinished) { |
|
1196 throw new SSLProtocolException |
|
1197 ("Expecting finished message, received data"); |
|
1198 } |
|
1199 if (!needAppData) { |
|
1200 throw new SSLException("Discarding app data"); |
|
1201 } |
|
1202 |
|
1203 volume = plainText.fragment.remaining(); |
|
1204 break; |
|
1205 |
|
1206 case Record.ct_alert: |
|
1207 recvAlert(plainText.fragment); |
|
1208 break; |
|
1209 |
|
1210 case Record.ct_change_cipher_spec: |
|
1211 if ((connectionState != cs_HANDSHAKE |
|
1212 && connectionState != cs_RENEGOTIATE)) { |
|
1213 // For the CCS message arriving in the wrong state |
|
1214 fatal(Alerts.alert_unexpected_message, |
|
1215 "illegal change cipher spec msg, conn state = " |
|
1216 + connectionState); |
|
1217 } else if (plainText.fragment.remaining() != 1 |
|
1218 || plainText.fragment.get() != 1) { |
|
1219 // For structural/content issues with the CCS |
|
1220 fatal(Alerts.alert_unexpected_message, |
|
1221 "Malformed change cipher spec msg"); |
|
1222 } |
|
1223 |
|
1224 // |
|
1225 // The first message after a change_cipher_spec |
|
1226 // record MUST be a "Finished" handshake record, |
|
1227 // else it's a protocol violation. We force this |
|
1228 // to be checked by a minor tweak to the state |
|
1229 // machine. |
|
1230 // |
|
1231 handshaker.receiveChangeCipherSpec(); |
|
1232 |
|
1233 CipherBox readCipher; |
|
1234 Authenticator readAuthenticator; |
|
1235 try { |
|
1236 readCipher = handshaker.newReadCipher(); |
|
1237 readAuthenticator = handshaker.newReadAuthenticator(); |
|
1238 } catch (GeneralSecurityException e) { |
|
1239 // can't happen |
|
1240 throw new SSLException("Algorithm missing: ", e); |
|
1241 } |
|
1242 inputRecord.changeReadCiphers(readAuthenticator, readCipher); |
|
1243 |
|
1244 // next message MUST be a finished message |
|
1245 expectingFinished = true; |
|
1246 |
|
1247 break; |
|
1248 |
|
1249 default: |
|
1250 // |
|
1251 // TLS requires that unrecognized records be ignored. |
|
1252 // |
|
1253 if (debug != null && Debug.isOn("ssl")) { |
|
1254 System.out.println(Thread.currentThread().getName() + |
|
1255 ", Received record type: " + plainText.contentType); |
|
1256 } |
|
1257 break; |
|
1258 } |
|
1259 |
|
1260 /* |
|
1261 * Check the sequence number state |
|
1262 * |
|
1263 * Note that in order to maintain the connection I/O |
|
1264 * properly, we check the sequence number after the last |
|
1265 * record reading process. As we request renegotiation |
|
1266 * or close the connection for wrapped sequence number |
|
1267 * when there is enough sequence number space left to |
|
1268 * handle a few more records, so the sequence number |
|
1269 * of the last record cannot be wrapped. |
|
1270 * |
|
1271 * Don't bother to kickstart the renegotiation when the |
|
1272 * local is asking for it. |
|
1273 */ |
|
1274 if ((connectionState == cs_DATA) && inputRecord.seqNumIsHuge()) { |
|
1275 /* |
|
1276 * Ask for renegotiation when need to renew sequence number. |
|
1277 * |
|
1278 * Don't bother to kickstart the renegotiation when the local is |
|
1279 * asking for it. |
|
1280 */ |
|
1281 if (debug != null && Debug.isOn("ssl")) { |
|
1282 System.out.println(Thread.currentThread().getName() + |
|
1283 ", request renegotiation " + |
|
1284 "to avoid sequence number overflow"); |
|
1285 } |
|
1286 |
|
1287 startHandshake(); |
|
1288 } |
|
1289 |
|
1290 return volume; |
|
1291 } |
|
1292 |
|
1293 |
|
1294 // |
|
1295 // HANDSHAKE RELATED CODE |
|
1296 // |
|
1297 |
|
1298 /** |
|
1299 * Return the AppInputStream. For use by Handshaker only. |
|
1300 */ |
|
1301 AppInputStream getAppInputStream() { |
|
1302 return input; |
|
1303 } |
|
1304 |
|
1305 /** |
|
1306 * Return the AppOutputStream. For use by Handshaker only. |
|
1307 */ |
|
1308 AppOutputStream getAppOutputStream() { |
|
1309 return output; |
|
1310 } |
|
1311 |
|
1312 /** |
|
1313 * Initialize the handshaker object. This means: |
|
1314 * |
|
1315 * . if a handshake is already in progress (state is cs_HANDSHAKE |
|
1316 * or cs_RENEGOTIATE), do nothing and return |
|
1317 * |
|
1318 * . if the socket is already closed, throw an Exception (internal error) |
|
1319 * |
|
1320 * . otherwise (cs_START or cs_DATA), create the appropriate handshaker |
|
1321 * object, and advance the connection state (to cs_HANDSHAKE or |
|
1322 * cs_RENEGOTIATE, respectively). |
|
1323 * |
|
1324 * This method is called right after a new socket is created, when |
|
1325 * starting renegotiation, or when changing client/ server mode of the |
|
1326 * socket. |
|
1327 */ |
|
1328 private void initHandshaker() { |
|
1329 switch (connectionState) { |
|
1330 |
|
1331 // |
|
1332 // Starting a new handshake. |
|
1333 // |
|
1334 case cs_START: |
|
1335 case cs_DATA: |
|
1336 break; |
|
1337 |
|
1338 // |
|
1339 // We're already in the middle of a handshake. |
|
1340 // |
|
1341 case cs_HANDSHAKE: |
|
1342 case cs_RENEGOTIATE: |
|
1343 return; |
|
1344 |
|
1345 // |
|
1346 // Anyone allowed to call this routine is required to |
|
1347 // do so ONLY if the connection state is reasonable... |
|
1348 // |
|
1349 default: |
|
1350 throw new IllegalStateException("Internal error"); |
|
1351 } |
|
1352 |
|
1353 // state is either cs_START or cs_DATA |
|
1354 if (connectionState == cs_START) { |
|
1355 connectionState = cs_HANDSHAKE; |
|
1356 } else { // cs_DATA |
|
1357 connectionState = cs_RENEGOTIATE; |
|
1358 } |
|
1359 |
|
1360 if (roleIsServer) { |
|
1361 handshaker = new ServerHandshaker(this, sslContext, |
|
1362 enabledProtocols, doClientAuth, |
|
1363 protocolVersion, connectionState == cs_HANDSHAKE, |
|
1364 secureRenegotiation, clientVerifyData, serverVerifyData); |
|
1365 handshaker.setSNIMatchers(sniMatchers); |
|
1366 handshaker.setUseCipherSuitesOrder(preferLocalCipherSuites); |
|
1367 } else { |
|
1368 handshaker = new ClientHandshaker(this, sslContext, |
|
1369 enabledProtocols, |
|
1370 protocolVersion, connectionState == cs_HANDSHAKE, |
|
1371 secureRenegotiation, clientVerifyData, serverVerifyData); |
|
1372 handshaker.setSNIServerNames(serverNames); |
|
1373 } |
|
1374 handshaker.setMaximumPacketSize(maximumPacketSize); |
|
1375 handshaker.setEnabledCipherSuites(enabledCipherSuites); |
|
1376 handshaker.setEnableSessionCreation(enableSessionCreation); |
|
1377 handshaker.setApplicationProtocols(applicationProtocols); |
|
1378 handshaker.setApplicationProtocolSelectorSSLSocket( |
|
1379 applicationProtocolSelector); |
|
1380 } |
|
1381 |
|
1382 /** |
|
1383 * Synchronously perform the initial handshake. |
|
1384 * |
|
1385 * If the handshake is already in progress, this method blocks until it |
|
1386 * is completed. If the initial handshake has already been completed, |
|
1387 * it returns immediately. |
|
1388 */ |
|
1389 private void performInitialHandshake() throws IOException { |
|
1390 // use handshakeLock and the state check to make sure only |
|
1391 // one thread performs the handshake |
|
1392 synchronized (handshakeLock) { |
|
1393 if (getConnectionState() == cs_HANDSHAKE) { |
|
1394 kickstartHandshake(); |
|
1395 |
|
1396 /* |
|
1397 * All initial handshaking goes through this operation |
|
1398 * until we have a valid SSL connection. |
|
1399 * |
|
1400 * Handle handshake messages only, need no application data. |
|
1401 */ |
|
1402 readRecord(false); |
|
1403 } |
|
1404 } |
|
1405 } |
|
1406 |
|
1407 /** |
|
1408 * Starts an SSL handshake on this connection. |
|
1409 */ |
|
1410 @Override |
|
1411 public void startHandshake() throws IOException { |
|
1412 // start an ssl handshake that could be resumed from timeout exception |
|
1413 startHandshake(true); |
|
1414 } |
|
1415 |
|
1416 /** |
|
1417 * Starts an ssl handshake on this connection. |
|
1418 * |
|
1419 * @param resumable indicates the handshake process is resumable from a |
|
1420 * certain exception. If <code>resumable</code>, the socket will |
|
1421 * be reserved for exceptions like timeout; otherwise, the socket |
|
1422 * will be closed, no further communications could be done. |
|
1423 */ |
|
1424 private void startHandshake(boolean resumable) throws IOException { |
|
1425 checkWrite(); |
|
1426 try { |
|
1427 if (getConnectionState() == cs_HANDSHAKE) { |
|
1428 // do initial handshake |
|
1429 performInitialHandshake(); |
|
1430 } else { |
|
1431 // start renegotiation |
|
1432 kickstartHandshake(); |
|
1433 } |
|
1434 } catch (Exception e) { |
|
1435 // shutdown and rethrow (wrapped) exception as appropriate |
|
1436 handleException(e, resumable); |
|
1437 } |
|
1438 } |
|
1439 |
|
1440 /** |
|
1441 * Kickstart the handshake if it is not already in progress. |
|
1442 * This means: |
|
1443 * |
|
1444 * . if handshaking is already underway, do nothing and return |
|
1445 * |
|
1446 * . if the socket is not connected or already closed, throw an |
|
1447 * Exception. |
|
1448 * |
|
1449 * . otherwise, call initHandshake() to initialize the handshaker |
|
1450 * object and progress the state. Then, send the initial |
|
1451 * handshaking message if appropriate (always on clients and |
|
1452 * on servers when renegotiating). |
|
1453 */ |
|
1454 private synchronized void kickstartHandshake() throws IOException { |
|
1455 |
|
1456 switch (connectionState) { |
|
1457 |
|
1458 case cs_HANDSHAKE: |
|
1459 // handshaker already setup, proceed |
|
1460 break; |
|
1461 |
|
1462 case cs_DATA: |
|
1463 if (!secureRenegotiation && !Handshaker.allowUnsafeRenegotiation) { |
|
1464 throw new SSLHandshakeException( |
|
1465 "Insecure renegotiation is not allowed"); |
|
1466 } |
|
1467 |
|
1468 if (!secureRenegotiation) { |
|
1469 if (debug != null && Debug.isOn("handshake")) { |
|
1470 System.out.println( |
|
1471 "Warning: Using insecure renegotiation"); |
|
1472 } |
|
1473 } |
|
1474 |
|
1475 // initialize the handshaker, move to cs_RENEGOTIATE |
|
1476 initHandshaker(); |
|
1477 break; |
|
1478 |
|
1479 case cs_RENEGOTIATE: |
|
1480 // handshaking already in progress, return |
|
1481 return; |
|
1482 |
|
1483 /* |
|
1484 * The only way to get a socket in the state is when |
|
1485 * you have an unconnected socket. |
|
1486 */ |
|
1487 case cs_START: |
|
1488 throw new SocketException( |
|
1489 "handshaking attempted on unconnected socket"); |
|
1490 |
|
1491 default: |
|
1492 throw new SocketException("connection is closed"); |
|
1493 } |
|
1494 |
|
1495 // |
|
1496 // Kickstart handshake state machine if we need to ... |
|
1497 // |
|
1498 // Note that handshaker.kickstart() writes the message |
|
1499 // to its HandshakeOutStream, which calls back into |
|
1500 // SSLSocketImpl.writeRecord() to send it. |
|
1501 // |
|
1502 if (!handshaker.activated()) { |
|
1503 // prior to handshaking, activate the handshake |
|
1504 if (connectionState == cs_RENEGOTIATE) { |
|
1505 // don't use SSLv2Hello when renegotiating |
|
1506 handshaker.activate(protocolVersion); |
|
1507 } else { |
|
1508 handshaker.activate(null); |
|
1509 } |
|
1510 |
|
1511 if (handshaker instanceof ClientHandshaker) { |
|
1512 // send client hello |
|
1513 handshaker.kickstart(); |
|
1514 } else { |
|
1515 if (connectionState == cs_HANDSHAKE) { |
|
1516 // initial handshake, no kickstart message to send |
|
1517 } else { |
|
1518 // we want to renegotiate, send hello request |
|
1519 handshaker.kickstart(); |
|
1520 } |
|
1521 } |
|
1522 } |
|
1523 } |
|
1524 |
|
1525 // |
|
1526 // CLOSURE RELATED CALLS |
|
1527 // |
|
1528 |
|
1529 /** |
|
1530 * Return whether the socket has been explicitly closed by the application. |
|
1531 */ |
|
1532 @Override |
|
1533 public boolean isClosed() { |
|
1534 return connectionState == cs_APP_CLOSED; |
|
1535 } |
|
1536 |
|
1537 /** |
|
1538 * Return whether we have reached end-of-file. |
|
1539 * |
|
1540 * If the socket is not connected, has been shutdown because of an error |
|
1541 * or has been closed, throw an Exception. |
|
1542 */ |
|
1543 boolean checkEOF() throws IOException { |
|
1544 switch (getConnectionState()) { |
|
1545 case cs_START: |
|
1546 throw new SocketException("Socket is not connected"); |
|
1547 |
|
1548 case cs_HANDSHAKE: |
|
1549 case cs_DATA: |
|
1550 case cs_RENEGOTIATE: |
|
1551 case cs_SENT_CLOSE: |
|
1552 return false; |
|
1553 |
|
1554 case cs_APP_CLOSED: |
|
1555 throw new SocketException("Socket is closed"); |
|
1556 |
|
1557 case cs_ERROR: |
|
1558 case cs_CLOSED: |
|
1559 default: |
|
1560 // either closed because of error, or normal EOF |
|
1561 if (closeReason == null) { |
|
1562 return true; |
|
1563 } |
|
1564 IOException e = new SSLException |
|
1565 ("Connection has been shutdown: " + closeReason); |
|
1566 e.initCause(closeReason); |
|
1567 throw e; |
|
1568 |
|
1569 } |
|
1570 } |
|
1571 |
|
1572 /** |
|
1573 * Check if we can write data to this socket. If not, throw an IOException. |
|
1574 */ |
|
1575 void checkWrite() throws IOException { |
|
1576 if (checkEOF() || (getConnectionState() == cs_SENT_CLOSE)) { |
|
1577 // we are at EOF, write must throw Exception |
|
1578 throw new SocketException("Connection closed by remote host"); |
|
1579 } |
|
1580 } |
|
1581 |
|
1582 private void closeSocket() throws IOException { |
|
1583 |
|
1584 if ((debug != null) && Debug.isOn("ssl")) { |
|
1585 System.out.println(Thread.currentThread().getName() + |
|
1586 ", called closeSocket()"); |
|
1587 } |
|
1588 |
|
1589 super.close(); |
|
1590 } |
887 } |
1591 |
888 |
1592 private void closeSocket(boolean selfInitiated) throws IOException { |
889 private void closeSocket(boolean selfInitiated) throws IOException { |
1593 if ((debug != null) && Debug.isOn("ssl")) { |
890 if (SSLLogger.isOn && SSLLogger.isOn("ssl")) { |
1594 System.out.println(Thread.currentThread().getName() + |
891 SSLLogger.fine("close the ssl connection " + |
1595 ", called closeSocket(" + selfInitiated + ")"); |
892 (selfInitiated ? "(initiative)" : "(passive)")); |
1596 } |
893 } |
1597 if (!isLayered() || autoClose) { |
894 |
|
895 if (autoClose || !isLayered()) { |
1598 super.close(); |
896 super.close(); |
1599 } else if (selfInitiated) { |
897 } else if (selfInitiated) { |
1600 // layered && non-autoclose |
898 // wait for close_notify alert to clear input stream. |
1601 // read close_notify alert to clear input stream |
899 waitForClose(); |
1602 waitForClose(false); |
900 } |
1603 } |
901 } |
1604 } |
902 |
1605 |
903 /** |
1606 /* |
904 * Wait for close_notify alert for a graceful closure. |
1607 * Closing the connection is tricky ... we can't officially close the |
905 * |
1608 * connection until we know the other end is ready to go away too, |
906 * [RFC 5246] If the application protocol using TLS provides that any |
1609 * and if ever the connection gets aborted we must forget session |
907 * data may be carried over the underlying transport after the TLS |
1610 * state (it becomes invalid). |
908 * connection is closed, the TLS implementation must receive the responding |
1611 */ |
909 * close_notify alert before indicating to the application layer that |
1612 |
910 * the TLS connection has ended. If the application protocol will not |
1613 /** |
911 * transfer any additional data, but will only close the underlying |
1614 * Closes the SSL connection. SSL includes an application level |
912 * transport connection, then the implementation MAY choose to close the |
1615 * shutdown handshake; you should close SSL sockets explicitly |
913 * transport without waiting for the responding close_notify. |
1616 * rather than leaving it for finalization, so that your remote |
914 */ |
1617 * peer does not experience a protocol error. |
915 private void waitForClose() throws IOException { |
1618 */ |
916 if (SSLLogger.isOn && SSLLogger.isOn("ssl")) { |
1619 @Override |
917 SSLLogger.fine("wait for close_notify or alert"); |
1620 public void close() throws IOException { |
918 } |
1621 if ((debug != null) && Debug.isOn("ssl")) { |
919 |
1622 System.out.println(Thread.currentThread().getName() + |
920 while (!conContext.isInboundDone()) { |
1623 ", called close()"); |
|
1624 } |
|
1625 closeInternal(true); // caller is initiating close |
|
1626 |
|
1627 // Clearup the resources. |
|
1628 try { |
|
1629 synchronized (readLock) { |
|
1630 inputRecord.close(); |
|
1631 } |
|
1632 |
|
1633 writeLock.lock(); |
|
1634 try { |
921 try { |
1635 outputRecord.close(); |
922 Plaintext plainText = decode(null); |
1636 } finally { |
923 // discard and continue |
1637 writeLock.unlock(); |
924 if (SSLLogger.isOn && SSLLogger.isOn("ssl")) { |
1638 } |
925 SSLLogger.finest( |
1639 } catch (IOException ioe) { |
926 "discard plaintext while waiting for close", plainText); |
1640 // ignore |
|
1641 } |
|
1642 |
|
1643 setConnectionState(cs_APP_CLOSED); |
|
1644 } |
|
1645 |
|
1646 /** |
|
1647 * Don't synchronize the whole method because waitForClose() |
|
1648 * (which calls readRecord()) might be called. |
|
1649 * |
|
1650 * @param selfInitiated Indicates which party initiated the close. |
|
1651 * If selfInitiated, this side is initiating a close; for layered and |
|
1652 * non-autoclose socket, wait for close_notify response. |
|
1653 * If !selfInitiated, peer sent close_notify; we reciprocate but |
|
1654 * no need to wait for response. |
|
1655 */ |
|
1656 private void closeInternal(boolean selfInitiated) throws IOException { |
|
1657 if ((debug != null) && Debug.isOn("ssl")) { |
|
1658 System.out.println(Thread.currentThread().getName() + |
|
1659 ", called closeInternal(" + selfInitiated + ")"); |
|
1660 } |
|
1661 |
|
1662 int state = getConnectionState(); |
|
1663 boolean closeSocketCalled = false; |
|
1664 Throwable cachedThrowable = null; |
|
1665 try { |
|
1666 switch (state) { |
|
1667 case cs_START: |
|
1668 // unconnected socket or handshaking has not been initialized |
|
1669 closeSocket(selfInitiated); |
|
1670 break; |
|
1671 |
|
1672 /* |
|
1673 * If we're closing down due to error, we already sent (or else |
|
1674 * received) the fatal alert ... no niceties, blow the connection |
|
1675 * away as quickly as possible (even if we didn't allocate the |
|
1676 * socket ourselves; it's unusable, regardless). |
|
1677 */ |
|
1678 case cs_ERROR: |
|
1679 closeSocket(); |
|
1680 break; |
|
1681 |
|
1682 /* |
|
1683 * Sometimes close() gets called more than once. |
|
1684 */ |
|
1685 case cs_CLOSED: |
|
1686 case cs_APP_CLOSED: |
|
1687 break; |
|
1688 |
|
1689 /* |
|
1690 * Otherwise we indicate clean termination. |
|
1691 */ |
|
1692 // case cs_HANDSHAKE: |
|
1693 // case cs_DATA: |
|
1694 // case cs_RENEGOTIATE: |
|
1695 // case cs_SENT_CLOSE: |
|
1696 default: |
|
1697 synchronized (this) { |
|
1698 if (((state = getConnectionState()) == cs_CLOSED) || |
|
1699 (state == cs_ERROR) || (state == cs_APP_CLOSED)) { |
|
1700 return; // connection was closed while we waited |
|
1701 } |
|
1702 if (state != cs_SENT_CLOSE) { |
|
1703 try { |
|
1704 warning(Alerts.alert_close_notify); |
|
1705 connectionState = cs_SENT_CLOSE; |
|
1706 } catch (Throwable th) { |
|
1707 // we need to ensure socket is closed out |
|
1708 // if we encounter any errors. |
|
1709 connectionState = cs_ERROR; |
|
1710 // cache this for later use |
|
1711 cachedThrowable = th; |
|
1712 closeSocketCalled = true; |
|
1713 closeSocket(selfInitiated); |
|
1714 } |
|
1715 } |
|
1716 } |
927 } |
1717 // If state was cs_SENT_CLOSE before, we don't do the actual |
928 } catch (Exception e) { // including RuntimeException |
1718 // closing since it is already in progress. |
929 handleException(e); |
1719 if (state == cs_SENT_CLOSE) { |
930 } |
1720 if (debug != null && Debug.isOn("ssl")) { |
931 } |
1721 System.out.println(Thread.currentThread().getName() + |
932 } |
1722 ", close invoked again; state = " + |
933 |
1723 getConnectionState()); |
934 /** |
1724 } |
935 * Initialize the handshaker and socket streams. |
1725 if (selfInitiated == false) { |
936 * |
1726 // We were called because a close_notify message was |
937 * Called by connect, the layered constructor, and SSLServerSocket. |
1727 // received. This may be due to another thread calling |
938 */ |
1728 // read() or due to our call to waitForClose() below. |
939 synchronized void doneConnect() throws IOException { |
1729 // In either case, just return. |
940 // In server mode, it is not necessary to set host and serverNames. |
1730 return; |
941 // Otherwise, would require a reverse DNS lookup to get the hostname. |
1731 } |
942 if ((peerHost == null) || (peerHost.length() == 0)) { |
1732 // Another thread explicitly called close(). We need to |
943 boolean useNameService = |
1733 // wait for the closing to complete before returning. |
944 trustNameService && conContext.sslConfig.isClientMode; |
1734 synchronized (this) { |
945 useImplicitHost(useNameService); |
1735 while (connectionState < cs_CLOSED) { |
|
1736 try { |
|
1737 this.wait(); |
|
1738 } catch (InterruptedException e) { |
|
1739 // ignore |
|
1740 } |
|
1741 } |
|
1742 } |
|
1743 if ((debug != null) && Debug.isOn("ssl")) { |
|
1744 System.out.println(Thread.currentThread().getName() + |
|
1745 ", after primary close; state = " + |
|
1746 getConnectionState()); |
|
1747 } |
|
1748 return; |
|
1749 } |
|
1750 |
|
1751 if (!closeSocketCalled) { |
|
1752 closeSocketCalled = true; |
|
1753 closeSocket(selfInitiated); |
|
1754 } |
|
1755 |
|
1756 break; |
|
1757 } |
|
1758 } finally { |
|
1759 synchronized (this) { |
|
1760 // Upon exit from this method, the state is always >= cs_CLOSED |
|
1761 connectionState = (connectionState == cs_APP_CLOSED) |
|
1762 ? cs_APP_CLOSED : cs_CLOSED; |
|
1763 // notify any threads waiting for the closing to finish |
|
1764 this.notifyAll(); |
|
1765 } |
|
1766 |
|
1767 if (cachedThrowable != null) { |
|
1768 /* |
|
1769 * Rethrow the error to the calling method |
|
1770 * The Throwable caught can only be an Error or RuntimeException |
|
1771 */ |
|
1772 if (cachedThrowable instanceof Error) { |
|
1773 throw (Error)cachedThrowable; |
|
1774 } else if (cachedThrowable instanceof RuntimeException) { |
|
1775 throw (RuntimeException)cachedThrowable; |
|
1776 } // Otherwise, unlikely |
|
1777 } |
|
1778 } |
|
1779 } |
|
1780 |
|
1781 /** |
|
1782 * Reads a close_notify or a fatal alert from the input stream. |
|
1783 * Keep reading records until we get a close_notify or until |
|
1784 * the connection is otherwise closed. The close_notify or alert |
|
1785 * might be read by another reader, |
|
1786 * which will then process the close and set the connection state. |
|
1787 */ |
|
1788 void waitForClose(boolean rethrow) throws IOException { |
|
1789 if (debug != null && Debug.isOn("ssl")) { |
|
1790 System.out.println(Thread.currentThread().getName() + |
|
1791 ", waiting for close_notify or alert: state " |
|
1792 + getConnectionState()); |
|
1793 } |
|
1794 |
|
1795 try { |
|
1796 int state; |
|
1797 |
|
1798 while (((state = getConnectionState()) != cs_CLOSED) && |
|
1799 (state != cs_ERROR) && (state != cs_APP_CLOSED)) { |
|
1800 |
|
1801 // Ask for app data and then throw it away |
|
1802 try { |
|
1803 readRecord(true); |
|
1804 } catch (SocketTimeoutException e) { |
|
1805 if ((debug != null) && Debug.isOn("ssl")) { |
|
1806 System.out.println( |
|
1807 Thread.currentThread().getName() + |
|
1808 ", received Exception: " + e); |
|
1809 } |
|
1810 fatal((byte)(-1), "Did not receive close_notify from peer", e); |
|
1811 } |
|
1812 } |
|
1813 } catch (IOException e) { |
|
1814 if (debug != null && Debug.isOn("ssl")) { |
|
1815 System.out.println(Thread.currentThread().getName() + |
|
1816 ", Exception while waiting for close " +e); |
|
1817 } |
|
1818 if (rethrow) { |
|
1819 throw e; // pass exception up |
|
1820 } |
|
1821 } |
|
1822 } |
|
1823 |
|
1824 // |
|
1825 // EXCEPTION AND ALERT HANDLING |
|
1826 // |
|
1827 |
|
1828 /** |
|
1829 * Handle an exception. This method is called by top level exception |
|
1830 * handlers (in read(), write()) to make sure we always shutdown the |
|
1831 * connection correctly and do not pass runtime exception to the |
|
1832 * application. |
|
1833 */ |
|
1834 void handleException(Exception e) throws IOException { |
|
1835 handleException(e, true); |
|
1836 } |
|
1837 |
|
1838 /** |
|
1839 * Handle an exception. This method is called by top level exception |
|
1840 * handlers (in read(), write(), startHandshake()) to make sure we |
|
1841 * always shutdown the connection correctly and do not pass runtime |
|
1842 * exception to the application. |
|
1843 * |
|
1844 * This method never returns normally, it always throws an IOException. |
|
1845 * |
|
1846 * We first check if the socket has already been shutdown because of an |
|
1847 * error. If so, we just rethrow the exception. If the socket has not |
|
1848 * been shutdown, we sent a fatal alert and remember the exception. |
|
1849 * |
|
1850 * @param e the Exception |
|
1851 * @param resumable indicates the caller process is resumable from the |
|
1852 * exception. If <code>resumable</code>, the socket will be |
|
1853 * reserved for exceptions like timeout; otherwise, the socket |
|
1854 * will be closed, no further communications could be done. |
|
1855 */ |
|
1856 private synchronized void handleException(Exception e, boolean resumable) |
|
1857 throws IOException { |
|
1858 if ((debug != null) && Debug.isOn("ssl")) { |
|
1859 System.out.println(Thread.currentThread().getName() + |
|
1860 ", handling exception: " + e.toString()); |
|
1861 } |
|
1862 |
|
1863 // don't close the Socket in case of timeouts or interrupts if |
|
1864 // the process is resumable. |
|
1865 if (e instanceof InterruptedIOException && resumable) { |
|
1866 throw (IOException)e; |
|
1867 } |
|
1868 |
|
1869 // if we've already shutdown because of an error, |
|
1870 // there is nothing to do except rethrow the exception |
|
1871 if (closeReason != null) { |
|
1872 if (e instanceof IOException) { // includes SSLException |
|
1873 throw (IOException)e; |
|
1874 } else { |
|
1875 // this is odd, not an IOException. |
|
1876 // normally, this should not happen |
|
1877 // if closeReason has been already been set |
|
1878 throw Alerts.getSSLException(Alerts.alert_internal_error, e, |
|
1879 "Unexpected exception"); |
|
1880 } |
|
1881 } |
|
1882 |
|
1883 // need to perform error shutdown |
|
1884 boolean isSSLException = (e instanceof SSLException); |
|
1885 if ((!isSSLException) && (e instanceof IOException)) { |
|
1886 // IOException from the socket |
|
1887 // this means the TCP connection is already dead |
|
1888 // we call fatal just to set the error status |
|
1889 try { |
|
1890 fatal(Alerts.alert_unexpected_message, e); |
|
1891 } catch (IOException ee) { |
|
1892 // ignore (IOException wrapped in SSLException) |
|
1893 } |
|
1894 // rethrow original IOException |
|
1895 throw (IOException)e; |
|
1896 } |
|
1897 |
|
1898 // must be SSLException or RuntimeException |
|
1899 byte alertType; |
|
1900 if (isSSLException) { |
|
1901 if (e instanceof SSLHandshakeException) { |
|
1902 alertType = Alerts.alert_handshake_failure; |
|
1903 } else { |
|
1904 alertType = Alerts.alert_unexpected_message; |
|
1905 } |
|
1906 } else { |
946 } else { |
1907 alertType = Alerts.alert_internal_error; |
947 conContext.sslConfig.serverNames = |
1908 } |
948 Utilities.addToSNIServerNameList( |
1909 fatal(alertType, e); |
949 conContext.sslConfig.serverNames, peerHost); |
1910 } |
950 } |
1911 |
951 |
1912 /* |
952 InputStream sockInput = super.getInputStream(); |
1913 * Send a warning alert. |
953 conContext.inputRecord.setReceiverStream(sockInput); |
1914 */ |
954 |
1915 void warning(byte description) { |
955 OutputStream sockOutput = super.getOutputStream(); |
1916 sendAlert(Alerts.alert_warning, description); |
956 conContext.inputRecord.setDeliverStream(sockOutput); |
1917 } |
957 conContext.outputRecord.setDeliverStream(sockOutput); |
1918 |
958 |
1919 synchronized void fatal(byte description, String diagnostic) |
959 this.isConnected = true; |
1920 throws IOException { |
960 } |
1921 fatal(description, diagnostic, null); |
961 |
1922 } |
962 private void useImplicitHost(boolean useNameService) { |
1923 |
|
1924 synchronized void fatal(byte description, Throwable cause) |
|
1925 throws IOException { |
|
1926 fatal(description, null, cause); |
|
1927 } |
|
1928 |
|
1929 /* |
|
1930 * Send a fatal alert, and throw an exception so that callers will |
|
1931 * need to stand on their heads to accidentally continue processing. |
|
1932 */ |
|
1933 synchronized void fatal(byte description, String diagnostic, |
|
1934 Throwable cause) throws IOException { |
|
1935 |
|
1936 // Be care of deadlock. Please don't synchronize readLock. |
|
1937 try { |
|
1938 inputRecord.close(); |
|
1939 } catch (IOException ioe) { |
|
1940 // ignore |
|
1941 } |
|
1942 |
|
1943 sess.invalidate(); |
|
1944 if (handshakeSession != null) { |
|
1945 handshakeSession.invalidate(); |
|
1946 } |
|
1947 |
|
1948 int oldState = connectionState; |
|
1949 if (connectionState < cs_ERROR) { |
|
1950 connectionState = cs_ERROR; |
|
1951 } |
|
1952 |
|
1953 /* |
|
1954 * Has there been an error received yet? If not, remember it. |
|
1955 * By RFC 2246, we don't bother waiting for a response. |
|
1956 * Fatal errors require immediate shutdown. |
|
1957 */ |
|
1958 if (closeReason == null) { |
|
1959 /* |
|
1960 * Try to clear the kernel buffer to avoid TCP connection resets. |
|
1961 */ |
|
1962 if (oldState == cs_HANDSHAKE) { |
|
1963 sockInput.skip(sockInput.available()); |
|
1964 } |
|
1965 |
|
1966 // If the description equals -1, the alert won't be sent to peer. |
|
1967 if (description != -1) { |
|
1968 sendAlert(Alerts.alert_fatal, description); |
|
1969 } |
|
1970 if (cause instanceof SSLException) { // only true if != null |
|
1971 closeReason = (SSLException)cause; |
|
1972 } else { |
|
1973 closeReason = |
|
1974 Alerts.getSSLException(description, cause, diagnostic); |
|
1975 } |
|
1976 } |
|
1977 |
|
1978 /* |
|
1979 * Clean up our side. |
|
1980 */ |
|
1981 closeSocket(); |
|
1982 |
|
1983 // Be care of deadlock. Please don't synchronize writeLock. |
|
1984 try { |
|
1985 outputRecord.close(); |
|
1986 } catch (IOException ioe) { |
|
1987 // ignore |
|
1988 } |
|
1989 |
|
1990 throw closeReason; |
|
1991 } |
|
1992 |
|
1993 |
|
1994 /* |
|
1995 * Process an incoming alert ... caller must already have synchronized |
|
1996 * access to "this". |
|
1997 */ |
|
1998 private void recvAlert(ByteBuffer fragment) throws IOException { |
|
1999 byte level = fragment.get(); |
|
2000 byte description = fragment.get(); |
|
2001 |
|
2002 if (description == -1) { // check for short message |
|
2003 fatal(Alerts.alert_illegal_parameter, "Short alert message"); |
|
2004 } |
|
2005 |
|
2006 if (debug != null && (Debug.isOn("record") || |
|
2007 Debug.isOn("handshake"))) { |
|
2008 synchronized (System.out) { |
|
2009 System.out.print(Thread.currentThread().getName()); |
|
2010 System.out.print(", RECV " + protocolVersion + " ALERT: "); |
|
2011 if (level == Alerts.alert_fatal) { |
|
2012 System.out.print("fatal, "); |
|
2013 } else if (level == Alerts.alert_warning) { |
|
2014 System.out.print("warning, "); |
|
2015 } else { |
|
2016 System.out.print("<level " + (0x0ff & level) + ">, "); |
|
2017 } |
|
2018 System.out.println(Alerts.alertDescription(description)); |
|
2019 } |
|
2020 } |
|
2021 |
|
2022 if (level == Alerts.alert_warning) { |
|
2023 if (description == Alerts.alert_close_notify) { |
|
2024 if (connectionState == cs_HANDSHAKE) { |
|
2025 fatal(Alerts.alert_unexpected_message, |
|
2026 "Received close_notify during handshake"); |
|
2027 } else { |
|
2028 closeInternal(false); // reply to close |
|
2029 } |
|
2030 } else { |
|
2031 |
|
2032 // |
|
2033 // The other legal warnings relate to certificates, |
|
2034 // e.g. no_certificate, bad_certificate, etc; these |
|
2035 // are important to the handshaking code, which can |
|
2036 // also handle illegal protocol alerts if needed. |
|
2037 // |
|
2038 if (handshaker != null) { |
|
2039 handshaker.handshakeAlert(description); |
|
2040 } |
|
2041 } |
|
2042 } else { // fatal or unknown level |
|
2043 String reason = "Received fatal alert: " |
|
2044 + Alerts.alertDescription(description); |
|
2045 if (closeReason == null) { |
|
2046 closeReason = Alerts.getSSLException(description, reason); |
|
2047 } |
|
2048 fatal(Alerts.alert_unexpected_message, reason); |
|
2049 } |
|
2050 } |
|
2051 |
|
2052 |
|
2053 /* |
|
2054 * Emit alerts. Caller must have synchronized with "this". |
|
2055 */ |
|
2056 private void sendAlert(byte level, byte description) { |
|
2057 // the connectionState cannot be cs_START |
|
2058 if (connectionState >= cs_SENT_CLOSE) { |
|
2059 return; |
|
2060 } |
|
2061 |
|
2062 // For initial handshaking, don't send alert message to peer if |
|
2063 // handshaker has not started. |
|
2064 // |
|
2065 // Shall we send an fatal alter to terminate the connection gracefully? |
|
2066 if (connectionState <= cs_HANDSHAKE && |
|
2067 (handshaker == null || !handshaker.started() || |
|
2068 !handshaker.activated())) { |
|
2069 return; |
|
2070 } |
|
2071 |
|
2072 boolean useDebug = debug != null && Debug.isOn("ssl"); |
|
2073 if (useDebug) { |
|
2074 synchronized (System.out) { |
|
2075 System.out.print(Thread.currentThread().getName()); |
|
2076 System.out.print(", SEND " + protocolVersion + " ALERT: "); |
|
2077 if (level == Alerts.alert_fatal) { |
|
2078 System.out.print("fatal, "); |
|
2079 } else if (level == Alerts.alert_warning) { |
|
2080 System.out.print("warning, "); |
|
2081 } else { |
|
2082 System.out.print("<level = " + (0x0ff & level) + ">, "); |
|
2083 } |
|
2084 System.out.println("description = " |
|
2085 + Alerts.alertDescription(description)); |
|
2086 } |
|
2087 } |
|
2088 |
|
2089 try { |
|
2090 writeAlert(level, description); |
|
2091 } catch (IOException e) { |
|
2092 if (useDebug) { |
|
2093 System.out.println(Thread.currentThread().getName() + |
|
2094 ", Exception sending alert: " + e); |
|
2095 } |
|
2096 } |
|
2097 } |
|
2098 |
|
2099 // |
|
2100 // VARIOUS OTHER METHODS |
|
2101 // |
|
2102 |
|
2103 // used by Handshaker |
|
2104 void changeWriteCiphers() throws IOException { |
|
2105 Authenticator writeAuthenticator; |
|
2106 CipherBox writeCipher; |
|
2107 try { |
|
2108 writeCipher = handshaker.newWriteCipher(); |
|
2109 writeAuthenticator = handshaker.newWriteAuthenticator(); |
|
2110 } catch (GeneralSecurityException e) { |
|
2111 // "can't happen" |
|
2112 throw new SSLException("Algorithm missing: ", e); |
|
2113 } |
|
2114 outputRecord.changeWriteCiphers(writeAuthenticator, writeCipher); |
|
2115 } |
|
2116 |
|
2117 /* |
|
2118 * Updates the SSL version associated with this connection. |
|
2119 * Called from Handshaker once it has determined the negotiated version. |
|
2120 */ |
|
2121 synchronized void setVersion(ProtocolVersion protocolVersion) { |
|
2122 this.protocolVersion = protocolVersion; |
|
2123 outputRecord.setVersion(protocolVersion); |
|
2124 } |
|
2125 |
|
2126 // |
|
2127 // ONLY used by ClientHandshaker for the server hostname during handshaking |
|
2128 // |
|
2129 synchronized String getHost() { |
|
2130 // Note that the host may be null or empty for localhost. |
|
2131 if (host == null || host.length() == 0) { |
|
2132 useImplicitHost(true); |
|
2133 } |
|
2134 |
|
2135 return host; |
|
2136 } |
|
2137 |
|
2138 /* |
|
2139 * Try to set and use the implicit specified hostname |
|
2140 */ |
|
2141 private synchronized void useImplicitHost(boolean noSniUpdate) { |
|
2142 |
|
2143 // Note: If the local name service is not trustworthy, reverse |
963 // Note: If the local name service is not trustworthy, reverse |
2144 // host name resolution should not be performed for endpoint |
964 // host name resolution should not be performed for endpoint |
2145 // identification. Use the application original specified |
965 // identification. Use the application original specified |
2146 // hostname or IP address instead. |
966 // hostname or IP address instead. |
2147 |
967 |
2155 SharedSecrets.getJavaNetInetAddressAccess(); |
975 SharedSecrets.getJavaNetInetAddressAccess(); |
2156 String originalHostname = jna.getOriginalHostName(inetAddress); |
976 String originalHostname = jna.getOriginalHostName(inetAddress); |
2157 if ((originalHostname != null) && |
977 if ((originalHostname != null) && |
2158 (originalHostname.length() != 0)) { |
978 (originalHostname.length() != 0)) { |
2159 |
979 |
2160 host = originalHostname; |
980 this.peerHost = originalHostname; |
2161 if (!noSniUpdate && serverNames.isEmpty() && !noSniExtension) { |
981 if (conContext.sslConfig.serverNames.isEmpty() && |
2162 serverNames = |
982 !conContext.sslConfig.noSniExtension) { |
2163 Utilities.addToSNIServerNameList(serverNames, host); |
983 conContext.sslConfig.serverNames = |
2164 |
984 Utilities.addToSNIServerNameList( |
2165 if (!roleIsServer && |
985 conContext.sslConfig.serverNames, peerHost); |
2166 (handshaker != null) && !handshaker.activated()) { |
|
2167 handshaker.setSNIServerNames(serverNames); |
|
2168 } |
|
2169 } |
986 } |
2170 |
987 |
2171 return; |
988 return; |
2172 } |
989 } |
2173 |
990 |
2174 // No explicitly specified hostname, no server name indication. |
991 // No explicitly specified hostname, no server name indication. |
2175 if (!trustNameService) { |
992 if (!useNameService) { |
2176 // The local name service is not trustworthy, use IP address. |
993 // The local name service is not trustworthy, use IP address. |
2177 host = inetAddress.getHostAddress(); |
994 this.peerHost = inetAddress.getHostAddress(); |
2178 } else { |
995 } else { |
2179 // Use the underlying reverse host name resolution service. |
996 // Use the underlying reverse host name resolution service. |
2180 host = getInetAddress().getHostName(); |
997 this.peerHost = getInetAddress().getHostName(); |
2181 } |
998 } |
2182 } |
999 } |
2183 |
1000 |
2184 // ONLY used by HttpsClient to setup the URI specified hostname |
1001 // ONLY used by HttpsClient to setup the URI specified hostname |
2185 // |
1002 // |
2186 // Please NOTE that this method MUST be called before calling to |
1003 // Please NOTE that this method MUST be called before calling to |
2187 // SSLSocket.setSSLParameters(). Otherwise, the {@code host} parameter |
1004 // SSLSocket.setSSLParameters(). Otherwise, the {@code host} parameter |
2188 // may override SNIHostName in the customized server name indication. |
1005 // may override SNIHostName in the customized server name indication. |
2189 public synchronized void setHost(String host) { |
1006 public synchronized void setHost(String host) { |
2190 this.host = host; |
1007 this.peerHost = host; |
2191 this.serverNames = |
1008 this.conContext.sslConfig.serverNames = |
2192 Utilities.addToSNIServerNameList(this.serverNames, this.host); |
1009 Utilities.addToSNIServerNameList( |
2193 |
1010 conContext.sslConfig.serverNames, host); |
2194 if (!roleIsServer && (handshaker != null) && !handshaker.activated()) { |
1011 } |
2195 handshaker.setSNIServerNames(serverNames); |
1012 |
2196 } |
1013 /** |
2197 } |
1014 * Return whether we have reached end-of-file. |
2198 |
1015 * |
2199 /** |
1016 * If the socket is not connected, has been shutdown because of an error |
2200 * Gets an input stream to read from the peer on the other side. |
1017 * or has been closed, throw an Exception. |
2201 * Data read from this stream was always integrity protected in |
1018 */ |
2202 * transit, and will usually have been confidentiality protected. |
1019 synchronized boolean checkEOF() throws IOException { |
2203 */ |
1020 if (conContext.isClosed()) { |
2204 @Override |
|
2205 public synchronized InputStream getInputStream() throws IOException { |
|
2206 if (isClosed()) { |
|
2207 throw new SocketException("Socket is closed"); |
1021 throw new SocketException("Socket is closed"); |
2208 } |
1022 } else if (conContext.isInputCloseNotified || conContext.isBroken) { |
2209 |
1023 if (conContext.closeReason == null) { |
2210 /* |
1024 return true; |
2211 * Can't call isConnected() here, because the Handshakers |
1025 } else { |
2212 * do some initialization before we actually connect. |
1026 throw new SSLException( |
2213 */ |
1027 "Connection has been shutdown: " + conContext.closeReason, |
2214 if (connectionState == cs_START) { |
1028 conContext.closeReason); |
|
1029 } |
|
1030 } |
|
1031 |
|
1032 return false; |
|
1033 } |
|
1034 |
|
1035 /** |
|
1036 * Check if we can write data to this socket. |
|
1037 */ |
|
1038 synchronized void checkWrite() throws IOException { |
|
1039 if (checkEOF() || conContext.isOutboundDone()) { |
|
1040 // we are at EOF, write must throw Exception |
|
1041 throw new SocketException("Connection closed"); |
|
1042 } |
|
1043 if (!isConnected) { |
2215 throw new SocketException("Socket is not connected"); |
1044 throw new SocketException("Socket is not connected"); |
2216 } |
1045 } |
2217 |
1046 } |
2218 return input; |
1047 |
2219 } |
1048 /** |
2220 |
1049 * Handle an exception. |
2221 /** |
1050 * |
2222 * Gets an output stream to write to the peer on the other side. |
1051 * This method is called by top level exception handlers (in read(), |
2223 * Data written on this stream is always integrity protected, and |
1052 * write()) to make sure we always shutdown the connection correctly |
2224 * will usually be confidentiality protected. |
1053 * and do not pass runtime exception to the application. |
2225 */ |
1054 * |
2226 @Override |
1055 * This method never returns normally, it always throws an IOException. |
2227 public synchronized OutputStream getOutputStream() throws IOException { |
1056 */ |
2228 if (isClosed()) { |
1057 private void handleException(Exception cause) throws IOException { |
2229 throw new SocketException("Socket is closed"); |
1058 if (SSLLogger.isOn && SSLLogger.isOn("ssl")) { |
2230 } |
1059 SSLLogger.warning("handling exception", cause); |
2231 |
1060 } |
2232 /* |
1061 |
2233 * Can't call isConnected() here, because the Handshakers |
1062 // Don't close the Socket in case of timeouts or interrupts. |
2234 * do some initialization before we actually connect. |
1063 if (cause instanceof InterruptedIOException) { |
2235 */ |
1064 throw (IOException)cause; |
2236 if (connectionState == cs_START) { |
1065 } |
2237 throw new SocketException("Socket is not connected"); |
1066 |
2238 } |
1067 // need to perform error shutdown |
2239 |
1068 boolean isSSLException = (cause instanceof SSLException); |
2240 return output; |
1069 Alert alert; |
2241 } |
1070 if (isSSLException) { |
2242 |
1071 if (cause instanceof SSLHandshakeException) { |
2243 /** |
1072 alert = Alert.HANDSHAKE_FAILURE; |
2244 * Returns the SSL Session in use by this connection. These can |
1073 } else { |
2245 * be long lived, and frequently correspond to an entire login session |
1074 alert = Alert.UNEXPECTED_MESSAGE; |
2246 * for some user. |
1075 } |
2247 */ |
1076 } else { |
2248 @Override |
1077 if (cause instanceof IOException) { |
2249 public SSLSession getSession() { |
1078 alert = Alert.UNEXPECTED_MESSAGE; |
2250 /* |
1079 } else { |
2251 * Force a synchronous handshake, if appropriate. |
1080 // RuntimeException |
2252 */ |
1081 alert = Alert.INTERNAL_ERROR; |
2253 if (getConnectionState() == cs_HANDSHAKE) { |
1082 } |
|
1083 } |
|
1084 conContext.fatal(alert, cause); |
|
1085 } |
|
1086 |
|
1087 @Override |
|
1088 public String getPeerHost() { |
|
1089 return peerHost; |
|
1090 } |
|
1091 |
|
1092 @Override |
|
1093 public int getPeerPort() { |
|
1094 return getPort(); |
|
1095 } |
|
1096 |
|
1097 @Override |
|
1098 public boolean useDelegatedTask() { |
|
1099 return false; |
|
1100 } |
|
1101 |
|
1102 @Override |
|
1103 public void shutdown() throws IOException { |
|
1104 if (!isClosed()) { |
|
1105 if (SSLLogger.isOn && SSLLogger.isOn("ssl")) { |
|
1106 SSLLogger.fine("close the underlying socket"); |
|
1107 } |
|
1108 |
2254 try { |
1109 try { |
2255 // start handshaking, if failed, the connection will be closed. |
1110 if (conContext.isInputCloseNotified) { |
2256 startHandshake(false); |
1111 // Close the connection, no wait for more peer response. |
2257 } catch (IOException e) { |
1112 closeSocket(false); |
2258 // handshake failed. log and return a nullSession |
1113 } else { |
2259 if (debug != null && Debug.isOn("handshake")) { |
1114 // Close the connection, may wait for peer close_notify. |
2260 System.out.println(Thread.currentThread().getName() + |
1115 closeSocket(true); |
2261 ", IOException in getSession(): " + e); |
|
2262 } |
1116 } |
2263 } |
1117 } finally { |
2264 } |
1118 tlsIsClosed = true; |
2265 synchronized (this) { |
1119 } |
2266 return sess; |
1120 } |
2267 } |
|
2268 } |
|
2269 |
|
2270 @Override |
|
2271 public synchronized SSLSession getHandshakeSession() { |
|
2272 return handshakeSession; |
|
2273 } |
|
2274 |
|
2275 synchronized void setHandshakeSession(SSLSessionImpl session) { |
|
2276 // update the fragment size, which may be negotiated during handshaking |
|
2277 inputRecord.changeFragmentSize(session.getNegotiatedMaxFragSize()); |
|
2278 outputRecord.changeFragmentSize(session.getNegotiatedMaxFragSize()); |
|
2279 |
|
2280 handshakeSession = session; |
|
2281 } |
|
2282 |
|
2283 /** |
|
2284 * Controls whether new connections may cause creation of new SSL |
|
2285 * sessions. |
|
2286 * |
|
2287 * As long as handshaking has not started, we can change |
|
2288 * whether we enable session creations. Otherwise, |
|
2289 * we will need to wait for the next handshake. |
|
2290 */ |
|
2291 @Override |
|
2292 public synchronized void setEnableSessionCreation(boolean flag) { |
|
2293 enableSessionCreation = flag; |
|
2294 |
|
2295 if ((handshaker != null) && !handshaker.activated()) { |
|
2296 handshaker.setEnableSessionCreation(enableSessionCreation); |
|
2297 } |
|
2298 } |
|
2299 |
|
2300 /** |
|
2301 * Returns true if new connections may cause creation of new SSL |
|
2302 * sessions. |
|
2303 */ |
|
2304 @Override |
|
2305 public synchronized boolean getEnableSessionCreation() { |
|
2306 return enableSessionCreation; |
|
2307 } |
|
2308 |
|
2309 |
|
2310 /** |
|
2311 * Sets the flag controlling whether a server mode socket |
|
2312 * *REQUIRES* SSL client authentication. |
|
2313 * |
|
2314 * As long as handshaking has not started, we can change |
|
2315 * whether client authentication is needed. Otherwise, |
|
2316 * we will need to wait for the next handshake. |
|
2317 */ |
|
2318 @Override |
|
2319 public synchronized void setNeedClientAuth(boolean flag) { |
|
2320 doClientAuth = (flag ? ClientAuthType.CLIENT_AUTH_REQUIRED : |
|
2321 ClientAuthType.CLIENT_AUTH_NONE); |
|
2322 |
|
2323 if ((handshaker != null) && |
|
2324 (handshaker instanceof ServerHandshaker) && |
|
2325 !handshaker.activated()) { |
|
2326 ((ServerHandshaker) handshaker).setClientAuth(doClientAuth); |
|
2327 } |
|
2328 } |
|
2329 |
|
2330 @Override |
|
2331 public synchronized boolean getNeedClientAuth() { |
|
2332 return (doClientAuth == ClientAuthType.CLIENT_AUTH_REQUIRED); |
|
2333 } |
|
2334 |
|
2335 /** |
|
2336 * Sets the flag controlling whether a server mode socket |
|
2337 * *REQUESTS* SSL client authentication. |
|
2338 * |
|
2339 * As long as handshaking has not started, we can change |
|
2340 * whether client authentication is requested. Otherwise, |
|
2341 * we will need to wait for the next handshake. |
|
2342 */ |
|
2343 @Override |
|
2344 public synchronized void setWantClientAuth(boolean flag) { |
|
2345 doClientAuth = (flag ? ClientAuthType.CLIENT_AUTH_REQUESTED : |
|
2346 ClientAuthType.CLIENT_AUTH_NONE); |
|
2347 |
|
2348 if ((handshaker != null) && |
|
2349 (handshaker instanceof ServerHandshaker) && |
|
2350 !handshaker.activated()) { |
|
2351 ((ServerHandshaker) handshaker).setClientAuth(doClientAuth); |
|
2352 } |
|
2353 } |
|
2354 |
|
2355 @Override |
|
2356 public synchronized boolean getWantClientAuth() { |
|
2357 return (doClientAuth == ClientAuthType.CLIENT_AUTH_REQUESTED); |
|
2358 } |
|
2359 |
|
2360 |
|
2361 /** |
|
2362 * Sets the flag controlling whether the socket is in SSL |
|
2363 * client or server mode. Must be called before any SSL |
|
2364 * traffic has started. |
|
2365 */ |
|
2366 @Override |
|
2367 @SuppressWarnings("fallthrough") |
|
2368 public synchronized void setUseClientMode(boolean flag) { |
|
2369 switch (connectionState) { |
|
2370 |
|
2371 case cs_START: |
|
2372 /* |
|
2373 * If we need to change the socket mode and the enabled |
|
2374 * protocols and cipher suites haven't specifically been |
|
2375 * set by the user, change them to the corresponding |
|
2376 * default ones. |
|
2377 */ |
|
2378 if (roleIsServer != (!flag)) { |
|
2379 if (sslContext.isDefaultProtocolList(enabledProtocols)) { |
|
2380 enabledProtocols = |
|
2381 sslContext.getDefaultProtocolList(!flag); |
|
2382 } |
|
2383 |
|
2384 if (sslContext.isDefaultCipherSuiteList(enabledCipherSuites)) { |
|
2385 enabledCipherSuites = |
|
2386 sslContext.getDefaultCipherSuiteList(!flag); |
|
2387 } |
|
2388 } |
|
2389 |
|
2390 roleIsServer = !flag; |
|
2391 break; |
|
2392 |
|
2393 case cs_HANDSHAKE: |
|
2394 /* |
|
2395 * If we have a handshaker, but haven't started |
|
2396 * SSL traffic, we can throw away our current |
|
2397 * handshaker, and start from scratch. Don't |
|
2398 * need to call doneConnect() again, we already |
|
2399 * have the streams. |
|
2400 */ |
|
2401 assert(handshaker != null); |
|
2402 if (!handshaker.activated()) { |
|
2403 /* |
|
2404 * If we need to change the socket mode and the enabled |
|
2405 * protocols and cipher suites haven't specifically been |
|
2406 * set by the user, change them to the corresponding |
|
2407 * default ones. |
|
2408 */ |
|
2409 if (roleIsServer != (!flag)) { |
|
2410 if (sslContext.isDefaultProtocolList(enabledProtocols)) { |
|
2411 enabledProtocols = |
|
2412 sslContext.getDefaultProtocolList(!flag); |
|
2413 } |
|
2414 |
|
2415 if (sslContext.isDefaultCipherSuiteList( |
|
2416 enabledCipherSuites)) { |
|
2417 enabledCipherSuites = |
|
2418 sslContext.getDefaultCipherSuiteList(!flag); |
|
2419 } |
|
2420 } |
|
2421 |
|
2422 roleIsServer = !flag; |
|
2423 connectionState = cs_START; |
|
2424 initHandshaker(); |
|
2425 break; |
|
2426 } |
|
2427 |
|
2428 // If handshake has started, that's an error. Fall through... |
|
2429 |
|
2430 default: |
|
2431 if (debug != null && Debug.isOn("ssl")) { |
|
2432 System.out.println(Thread.currentThread().getName() + |
|
2433 ", setUseClientMode() invoked in state = " + |
|
2434 connectionState); |
|
2435 } |
|
2436 throw new IllegalArgumentException( |
|
2437 "Cannot change mode after SSL traffic has started"); |
|
2438 } |
|
2439 } |
|
2440 |
|
2441 @Override |
|
2442 public synchronized boolean getUseClientMode() { |
|
2443 return !roleIsServer; |
|
2444 } |
|
2445 |
|
2446 |
|
2447 /** |
|
2448 * Returns the names of the cipher suites which could be enabled for use |
|
2449 * on an SSL connection. Normally, only a subset of these will actually |
|
2450 * be enabled by default, since this list may include cipher suites which |
|
2451 * do not support the mutual authentication of servers and clients, or |
|
2452 * which do not protect data confidentiality. Servers may also need |
|
2453 * certain kinds of certificates to use certain cipher suites. |
|
2454 * |
|
2455 * @return an array of cipher suite names |
|
2456 */ |
|
2457 @Override |
|
2458 public String[] getSupportedCipherSuites() { |
|
2459 return sslContext.getSupportedCipherSuiteList().toStringArray(); |
|
2460 } |
|
2461 |
|
2462 /** |
|
2463 * Controls which particular cipher suites are enabled for use on |
|
2464 * this connection. The cipher suites must have been listed by |
|
2465 * getCipherSuites() as being supported. Even if a suite has been |
|
2466 * enabled, it might never be used if no peer supports it or the |
|
2467 * requisite certificates (and private keys) are not available. |
|
2468 * |
|
2469 * @param suites Names of all the cipher suites to enable. |
|
2470 */ |
|
2471 @Override |
|
2472 public synchronized void setEnabledCipherSuites(String[] suites) { |
|
2473 enabledCipherSuites = new CipherSuiteList(suites); |
|
2474 if ((handshaker != null) && !handshaker.activated()) { |
|
2475 handshaker.setEnabledCipherSuites(enabledCipherSuites); |
|
2476 } |
|
2477 } |
|
2478 |
|
2479 /** |
|
2480 * Returns the names of the SSL cipher suites which are currently enabled |
|
2481 * for use on this connection. When an SSL socket is first created, |
|
2482 * all enabled cipher suites <em>(a)</em> protect data confidentiality, |
|
2483 * by traffic encryption, and <em>(b)</em> can mutually authenticate |
|
2484 * both clients and servers. Thus, in some environments, this value |
|
2485 * might be empty. |
|
2486 * |
|
2487 * @return an array of cipher suite names |
|
2488 */ |
|
2489 @Override |
|
2490 public synchronized String[] getEnabledCipherSuites() { |
|
2491 return enabledCipherSuites.toStringArray(); |
|
2492 } |
|
2493 |
|
2494 |
|
2495 /** |
|
2496 * Returns the protocols that are supported by this implementation. |
|
2497 * A subset of the supported protocols may be enabled for this connection |
|
2498 * @return an array of protocol names. |
|
2499 */ |
|
2500 @Override |
|
2501 public String[] getSupportedProtocols() { |
|
2502 return sslContext.getSuportedProtocolList().toStringArray(); |
|
2503 } |
|
2504 |
|
2505 /** |
|
2506 * Controls which protocols are enabled for use on |
|
2507 * this connection. The protocols must have been listed by |
|
2508 * getSupportedProtocols() as being supported. |
|
2509 * |
|
2510 * @param protocols protocols to enable. |
|
2511 * @exception IllegalArgumentException when one of the protocols |
|
2512 * named by the parameter is not supported. |
|
2513 */ |
|
2514 @Override |
|
2515 public synchronized void setEnabledProtocols(String[] protocols) { |
|
2516 enabledProtocols = new ProtocolList(protocols); |
|
2517 if ((handshaker != null) && !handshaker.activated()) { |
|
2518 handshaker.setEnabledProtocols(enabledProtocols); |
|
2519 } |
|
2520 } |
|
2521 |
|
2522 @Override |
|
2523 public synchronized String[] getEnabledProtocols() { |
|
2524 return enabledProtocols.toStringArray(); |
|
2525 } |
|
2526 |
|
2527 /** |
|
2528 * Assigns the socket timeout. |
|
2529 * @see java.net.Socket#setSoTimeout |
|
2530 */ |
|
2531 @Override |
|
2532 public void setSoTimeout(int timeout) throws SocketException { |
|
2533 if ((debug != null) && Debug.isOn("ssl")) { |
|
2534 System.out.println(Thread.currentThread().getName() + |
|
2535 ", setSoTimeout(" + timeout + ") called"); |
|
2536 } |
|
2537 |
|
2538 super.setSoTimeout(timeout); |
|
2539 } |
|
2540 |
|
2541 /** |
|
2542 * Registers an event listener to receive notifications that an |
|
2543 * SSL handshake has completed on this connection. |
|
2544 */ |
|
2545 @Override |
|
2546 public synchronized void addHandshakeCompletedListener( |
|
2547 HandshakeCompletedListener listener) { |
|
2548 if (listener == null) { |
|
2549 throw new IllegalArgumentException("listener is null"); |
|
2550 } |
|
2551 if (handshakeListeners == null) { |
|
2552 handshakeListeners = new |
|
2553 HashMap<HandshakeCompletedListener, AccessControlContext>(4); |
|
2554 } |
|
2555 handshakeListeners.put(listener, AccessController.getContext()); |
|
2556 } |
|
2557 |
|
2558 |
|
2559 /** |
|
2560 * Removes a previously registered handshake completion listener. |
|
2561 */ |
|
2562 @Override |
|
2563 public synchronized void removeHandshakeCompletedListener( |
|
2564 HandshakeCompletedListener listener) { |
|
2565 if (handshakeListeners == null) { |
|
2566 throw new IllegalArgumentException("no listeners"); |
|
2567 } |
|
2568 if (handshakeListeners.remove(listener) == null) { |
|
2569 throw new IllegalArgumentException("listener not registered"); |
|
2570 } |
|
2571 if (handshakeListeners.isEmpty()) { |
|
2572 handshakeListeners = null; |
|
2573 } |
|
2574 } |
|
2575 |
|
2576 /** |
|
2577 * Returns the SSLParameters in effect for this SSLSocket. |
|
2578 */ |
|
2579 @Override |
|
2580 public synchronized SSLParameters getSSLParameters() { |
|
2581 SSLParameters params = super.getSSLParameters(); |
|
2582 |
|
2583 // the super implementation does not handle the following parameters |
|
2584 params.setEndpointIdentificationAlgorithm(identificationProtocol); |
|
2585 params.setAlgorithmConstraints(algorithmConstraints); |
|
2586 |
|
2587 if (sniMatchers.isEmpty() && !noSniMatcher) { |
|
2588 // 'null' indicates none has been set |
|
2589 params.setSNIMatchers(null); |
|
2590 } else { |
|
2591 params.setSNIMatchers(sniMatchers); |
|
2592 } |
|
2593 |
|
2594 if (serverNames.isEmpty() && !noSniExtension) { |
|
2595 // 'null' indicates none has been set |
|
2596 params.setServerNames(null); |
|
2597 } else { |
|
2598 params.setServerNames(serverNames); |
|
2599 } |
|
2600 |
|
2601 params.setUseCipherSuitesOrder(preferLocalCipherSuites); |
|
2602 params.setMaximumPacketSize(maximumPacketSize); |
|
2603 params.setApplicationProtocols(applicationProtocols); |
|
2604 |
|
2605 // DTLS handshake retransmissions parameter does not apply here. |
|
2606 |
|
2607 return params; |
|
2608 } |
|
2609 |
|
2610 /** |
|
2611 * Applies SSLParameters to this socket. |
|
2612 */ |
|
2613 @Override |
|
2614 public synchronized void setSSLParameters(SSLParameters params) { |
|
2615 super.setSSLParameters(params); |
|
2616 |
|
2617 // the super implementation does not handle the following parameters |
|
2618 identificationProtocol = params.getEndpointIdentificationAlgorithm(); |
|
2619 algorithmConstraints = params.getAlgorithmConstraints(); |
|
2620 preferLocalCipherSuites = params.getUseCipherSuitesOrder(); |
|
2621 maximumPacketSize = params.getMaximumPacketSize(); |
|
2622 |
|
2623 // DTLS handshake retransmissions parameter does not apply here. |
|
2624 |
|
2625 if (maximumPacketSize != 0) { |
|
2626 outputRecord.changePacketSize(maximumPacketSize); |
|
2627 } else { |
|
2628 // use the implicit maximum packet size. |
|
2629 maximumPacketSize = outputRecord.getMaxPacketSize(); |
|
2630 } |
|
2631 |
|
2632 List<SNIServerName> sniNames = params.getServerNames(); |
|
2633 if (sniNames != null) { |
|
2634 noSniExtension = sniNames.isEmpty(); |
|
2635 serverNames = sniNames; |
|
2636 } |
|
2637 |
|
2638 Collection<SNIMatcher> matchers = params.getSNIMatchers(); |
|
2639 if (matchers != null) { |
|
2640 noSniMatcher = matchers.isEmpty(); |
|
2641 sniMatchers = matchers; |
|
2642 } |
|
2643 |
|
2644 applicationProtocols = params.getApplicationProtocols(); |
|
2645 |
|
2646 if ((handshaker != null) && !handshaker.activated()) { |
|
2647 handshaker.setIdentificationProtocol(identificationProtocol); |
|
2648 handshaker.setAlgorithmConstraints(algorithmConstraints); |
|
2649 handshaker.setMaximumPacketSize(maximumPacketSize); |
|
2650 handshaker.setApplicationProtocols(applicationProtocols); |
|
2651 if (roleIsServer) { |
|
2652 handshaker.setSNIMatchers(sniMatchers); |
|
2653 handshaker.setUseCipherSuitesOrder(preferLocalCipherSuites); |
|
2654 } else { |
|
2655 handshaker.setSNIServerNames(serverNames); |
|
2656 } |
|
2657 } |
|
2658 } |
|
2659 |
|
2660 @Override |
|
2661 public synchronized String getApplicationProtocol() { |
|
2662 return applicationProtocol; |
|
2663 } |
|
2664 |
|
2665 @Override |
|
2666 public synchronized String getHandshakeApplicationProtocol() { |
|
2667 if ((handshaker != null) && handshaker.started()) { |
|
2668 return handshaker.getHandshakeApplicationProtocol(); |
|
2669 } |
|
2670 return null; |
|
2671 } |
|
2672 |
|
2673 @Override |
|
2674 public synchronized void setHandshakeApplicationProtocolSelector( |
|
2675 BiFunction<SSLSocket, List<String>, String> selector) { |
|
2676 applicationProtocolSelector = selector; |
|
2677 if ((handshaker != null) && !handshaker.activated()) { |
|
2678 handshaker.setApplicationProtocolSelectorSSLSocket(selector); |
|
2679 } |
|
2680 } |
|
2681 |
|
2682 @Override |
|
2683 public synchronized BiFunction<SSLSocket, List<String>, String> |
|
2684 getHandshakeApplicationProtocolSelector() { |
|
2685 return this.applicationProtocolSelector; |
|
2686 } |
|
2687 |
|
2688 // |
|
2689 // We allocate a separate thread to deliver handshake completion |
|
2690 // events. This ensures that the notifications don't block the |
|
2691 // protocol state machine. |
|
2692 // |
|
2693 private static class NotifyHandshake implements Runnable { |
|
2694 |
|
2695 private Set<Map.Entry<HandshakeCompletedListener,AccessControlContext>> |
|
2696 targets; // who gets notified |
|
2697 private HandshakeCompletedEvent event; // the notification |
|
2698 |
|
2699 NotifyHandshake( |
|
2700 Set<Map.Entry<HandshakeCompletedListener,AccessControlContext>> |
|
2701 entrySet, HandshakeCompletedEvent e) { |
|
2702 |
|
2703 targets = new HashSet<>(entrySet); // clone the entry set |
|
2704 event = e; |
|
2705 } |
|
2706 |
|
2707 @Override |
|
2708 public void run() { |
|
2709 // Don't need to synchronize, as it only runs in one thread. |
|
2710 for (Map.Entry<HandshakeCompletedListener,AccessControlContext> |
|
2711 entry : targets) { |
|
2712 |
|
2713 final HandshakeCompletedListener l = entry.getKey(); |
|
2714 AccessControlContext acc = entry.getValue(); |
|
2715 AccessController.doPrivileged(new PrivilegedAction<Void>() { |
|
2716 @Override |
|
2717 public Void run() { |
|
2718 l.handshakeCompleted(event); |
|
2719 return null; |
|
2720 } |
|
2721 }, acc); |
|
2722 } |
|
2723 } |
|
2724 } |
|
2725 |
|
2726 /** |
|
2727 * Returns a printable representation of this end of the connection. |
|
2728 */ |
|
2729 @Override |
|
2730 public String toString() { |
|
2731 StringBuilder retval = new StringBuilder(80); |
|
2732 |
|
2733 retval.append(Integer.toHexString(hashCode())); |
|
2734 retval.append("["); |
|
2735 retval.append(sess.getCipherSuite()); |
|
2736 retval.append(": "); |
|
2737 |
|
2738 retval.append(super.toString()); |
|
2739 retval.append("]"); |
|
2740 |
|
2741 return retval.toString(); |
|
2742 } |
1121 } |
2743 } |
1122 } |