changeset 50768 | 68fa3d4026ea |
parent 48225 | 718669e6b375 |
child 50987 | e4a92c455d1c |
50767:356eaea05bf0 | 50768:68fa3d4026ea |
---|---|
1 /* |
1 /* |
2 * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. Oracle designates this |
7 * published by the Free Software Foundation. Oracle designates this |
20 * |
20 * |
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
22 * or visit www.oracle.com if you need additional information or have any |
22 * or visit www.oracle.com if you need additional information or have any |
23 * questions. |
23 * questions. |
24 */ |
24 */ |
25 |
|
26 |
|
27 package sun.security.ssl; |
25 package sun.security.ssl; |
28 |
26 |
29 import java.net.*; |
27 import java.math.BigInteger; |
30 import java.util.Enumeration; |
28 import java.net.InetAddress; |
31 import java.util.Hashtable; |
29 import java.security.Principal; |
32 import java.util.Vector; |
30 import java.security.PrivateKey; |
31 import java.security.cert.CertificateEncodingException; |
|
32 import java.security.cert.X509Certificate; |
|
33 import java.util.ArrayList; |
|
34 import java.util.Queue; |
|
33 import java.util.Collection; |
35 import java.util.Collection; |
34 import java.util.Collections; |
36 import java.util.Collections; |
37 import java.util.Enumeration; |
|
35 import java.util.List; |
38 import java.util.List; |
36 import java.util.ArrayList; |
39 import java.util.Optional; |
37 |
40 import java.util.concurrent.ConcurrentHashMap; |
38 import java.security.Principal; |
41 import java.util.concurrent.ConcurrentLinkedQueue; |
39 import java.security.PrivateKey; |
|
40 import java.security.SecureRandom; |
|
41 import java.security.cert.X509Certificate; |
|
42 import java.security.cert.CertificateEncodingException; |
|
43 |
|
44 import javax.crypto.SecretKey; |
42 import javax.crypto.SecretKey; |
45 |
43 import javax.net.ssl.ExtendedSSLSession; |
46 import javax.net.ssl.SSLSessionContext; |
44 import javax.net.ssl.SNIServerName; |
47 import javax.net.ssl.SSLSessionBindingListener; |
|
48 import javax.net.ssl.SSLSessionBindingEvent; |
|
49 import javax.net.ssl.SSLPeerUnverifiedException; |
45 import javax.net.ssl.SSLPeerUnverifiedException; |
50 import javax.net.ssl.SSLPermission; |
46 import javax.net.ssl.SSLPermission; |
51 import javax.net.ssl.ExtendedSSLSession; |
47 import javax.net.ssl.SSLSessionBindingEvent; |
52 import javax.net.ssl.SNIServerName; |
48 import javax.net.ssl.SSLSessionBindingListener; |
53 |
49 import javax.net.ssl.SSLSessionContext; |
54 import static sun.security.ssl.CipherSuite.KeyExchange.*; |
|
55 |
50 |
56 /** |
51 /** |
57 * Implements the SSL session interface, and exposes the session context |
52 * Implements the SSL session interface, and exposes the session context |
58 * which is maintained by SSL servers. |
53 * which is maintained by SSL servers. |
59 * |
54 * |
76 /* |
71 /* |
77 * we only really need a single null session |
72 * we only really need a single null session |
78 */ |
73 */ |
79 static final SSLSessionImpl nullSession = new SSLSessionImpl(); |
74 static final SSLSessionImpl nullSession = new SSLSessionImpl(); |
80 |
75 |
81 // compression methods |
|
82 private static final byte compression_null = 0; |
|
83 |
|
84 /* |
76 /* |
85 * The state of a single session, as described in section 7.1 |
77 * The state of a single session, as described in section 7.1 |
86 * of the SSLv3 spec. |
78 * of the SSLv3 spec. |
87 */ |
79 */ |
88 private final ProtocolVersion protocolVersion; |
80 private final ProtocolVersion protocolVersion; |
89 private final SessionId sessionId; |
81 private final SessionId sessionId; |
90 private X509Certificate[] peerCerts; |
82 private X509Certificate[] peerCerts; |
91 private byte compressionMethod; |
|
92 private CipherSuite cipherSuite; |
83 private CipherSuite cipherSuite; |
93 private SecretKey masterSecret; |
84 private SecretKey masterSecret; |
94 private final boolean useExtendedMasterSecret; |
85 final boolean useExtendedMasterSecret; |
95 |
86 |
96 /* |
87 /* |
97 * Information not part of the SSLv3 protocol spec, but used |
88 * Information not part of the SSLv3 protocol spec, but used |
98 * to support session management policies. |
89 * to support session management policies. |
99 */ |
90 */ |
100 private final long creationTime = System.currentTimeMillis(); |
91 private final long creationTime; |
101 private long lastUsedTime = 0; |
92 private long lastUsedTime = 0; |
102 private final String host; |
93 private final String host; |
103 private final int port; |
94 private final int port; |
104 private SSLSessionContextImpl context; |
95 private SSLSessionContextImpl context; |
105 private int sessionCount; |
|
106 private boolean invalidated; |
96 private boolean invalidated; |
107 private X509Certificate[] localCerts; |
97 private X509Certificate[] localCerts; |
108 private PrivateKey localPrivateKey; |
98 private PrivateKey localPrivateKey; |
109 private String[] localSupportedSignAlgs; |
99 private final String[] localSupportedSignAlgs; |
110 private String[] peerSupportedSignAlgs; |
100 private String[] peerSupportedSignAlgs; // for certificate |
111 private List<SNIServerName> requestedServerNames; |
101 private boolean useDefaultPeerSignAlgs = false; |
112 private List<byte[]> statusResponses; |
102 private List<byte[]> statusResponses; |
113 |
103 private SecretKey resumptionMasterSecret; |
114 private int negotiatedMaxFragLen; |
104 private SecretKey preSharedKey; |
105 private byte[] pskIdentity; |
|
106 private final long ticketCreationTime = System.currentTimeMillis(); |
|
107 private int ticketAgeAdd; |
|
108 |
|
109 private int negotiatedMaxFragLen = -1; |
|
115 private int maximumPacketSize; |
110 private int maximumPacketSize; |
116 |
111 |
117 // Principals for non-certificate based cipher suites |
112 private final Queue<SSLSessionImpl> childSessions = |
118 private Principal peerPrincipal; |
113 new ConcurrentLinkedQueue<>(); |
119 private Principal localPrincipal; |
|
120 |
114 |
121 /* |
115 /* |
122 * Is the session currently re-established with a session-resumption |
116 * Is the session currently re-established with a session-resumption |
123 * abbreviated initial handshake? |
117 * abbreviated initial handshake? |
124 * |
118 * |
125 * Note that currently we only set this variable in client side. |
119 * Note that currently we only set this variable in client side. |
126 */ |
120 */ |
127 private boolean isSessionResumption = false; |
121 private boolean isSessionResumption = false; |
128 |
122 |
129 /* |
123 /* |
130 * We count session creations, eventually for statistical data but |
|
131 * also since counters make shorter debugging IDs than the big ones |
|
132 * we use in the protocol for uniqueness-over-time. |
|
133 */ |
|
134 private static volatile int counter; |
|
135 |
|
136 /* |
|
137 * Use of session caches is globally enabled/disabled. |
124 * Use of session caches is globally enabled/disabled. |
138 */ |
125 */ |
139 private static boolean defaultRejoinable = true; |
126 private static boolean defaultRejoinable = true; |
140 |
127 |
141 /* Class and subclass dynamic debugging support */ |
128 // server name indication |
142 private static final Debug debug = Debug.getInstance("ssl"); |
129 final SNIServerName serverNameIndication; |
130 private final List<SNIServerName> requestedServerNames; |
|
131 |
|
132 // Counter used to create unique nonces in NewSessionTicket |
|
133 private BigInteger ticketNonceCounter = BigInteger.ONE; |
|
143 |
134 |
144 /* |
135 /* |
145 * Create a new non-rejoinable session, using the default (null) |
136 * Create a new non-rejoinable session, using the default (null) |
146 * cipher spec. This constructor returns a session which could |
137 * cipher spec. This constructor returns a session which could |
147 * be used either by a client or by a server, as a connection is |
138 * be used either by a client or by a server, as a connection is |
148 * first opened and before handshaking begins. |
139 * first opened and before handshaking begins. |
149 */ |
140 */ |
150 private SSLSessionImpl() { |
141 private SSLSessionImpl() { |
151 this(ProtocolVersion.NONE, CipherSuite.C_NULL, null, |
142 this.protocolVersion = ProtocolVersion.NONE; |
152 new SessionId(false, null), null, -1, false); |
143 this.cipherSuite = CipherSuite.C_NULL; |
144 this.sessionId = new SessionId(false, null); |
|
145 this.host = null; |
|
146 this.port = -1; |
|
147 this.localSupportedSignAlgs = new String[0]; |
|
148 this.serverNameIndication = null; |
|
149 this.requestedServerNames = Collections.<SNIServerName>emptyList(); |
|
150 this.useExtendedMasterSecret = false; |
|
151 this.creationTime = System.currentTimeMillis(); |
|
153 } |
152 } |
154 |
153 |
155 /* |
154 /* |
156 * Create a new session, using a given cipher spec. This will |
155 * Create a new session, using a given cipher spec. This will |
157 * be rejoinable if session caching is enabled; the constructor |
156 * be rejoinable if session caching is enabled; the constructor |
158 * is intended mostly for use by serves. |
157 * is intended mostly for use by serves. |
159 */ |
158 */ |
160 SSLSessionImpl(ProtocolVersion protocolVersion, CipherSuite cipherSuite, |
159 SSLSessionImpl(HandshakeContext hc, CipherSuite cipherSuite) { |
161 Collection<SignatureAndHashAlgorithm> algorithms, |
160 this(hc, cipherSuite, |
162 SecureRandom generator, String host, int port, |
161 new SessionId(defaultRejoinable, hc.sslContext.getSecureRandom())); |
163 boolean useExtendedMasterSecret) { |
|
164 this(protocolVersion, cipherSuite, algorithms, |
|
165 new SessionId(defaultRejoinable, generator), host, port, |
|
166 useExtendedMasterSecret); |
|
167 } |
162 } |
168 |
163 |
169 /* |
164 /* |
170 * Record a new session, using a given cipher spec and session ID. |
165 * Record a new session, using a given cipher spec and session ID. |
171 */ |
166 */ |
172 SSLSessionImpl(ProtocolVersion protocolVersion, CipherSuite cipherSuite, |
167 SSLSessionImpl(HandshakeContext hc, CipherSuite cipherSuite, SessionId id) { |
173 Collection<SignatureAndHashAlgorithm> algorithms, |
168 this(hc, cipherSuite, id, System.currentTimeMillis()); |
174 SessionId id, String host, int port, |
169 } |
175 boolean useExtendedMasterSecret) { |
170 |
176 this.protocolVersion = protocolVersion; |
171 /* |
177 sessionId = id; |
172 * Record a new session, using a given cipher spec, session ID, |
178 peerCerts = null; |
173 * and creation time |
179 compressionMethod = compression_null; |
174 */ |
175 SSLSessionImpl(HandshakeContext hc, |
|
176 CipherSuite cipherSuite, SessionId id, long creationTime) { |
|
177 this.protocolVersion = hc.negotiatedProtocol; |
|
180 this.cipherSuite = cipherSuite; |
178 this.cipherSuite = cipherSuite; |
181 masterSecret = null; |
179 this.sessionId = id; |
182 this.host = host; |
180 this.host = hc.conContext.transport.getPeerHost(); |
183 this.port = port; |
181 this.port = hc.conContext.transport.getPeerPort(); |
184 sessionCount = ++counter; |
182 this.localSupportedSignAlgs = |
185 localSupportedSignAlgs = |
183 SignatureScheme.getAlgorithmNames(hc.localSupportedSignAlgs); |
186 SignatureAndHashAlgorithm.getAlgorithmNames(algorithms); |
184 this.serverNameIndication = hc.negotiatedServerName; |
187 negotiatedMaxFragLen = -1; |
185 this.requestedServerNames = Collections.<SNIServerName>unmodifiableList( |
188 statusResponses = null; |
186 hc.getRequestedServerNames()); |
189 this.useExtendedMasterSecret = useExtendedMasterSecret; |
187 if (hc.sslConfig.isClientMode) { |
190 |
188 this.useExtendedMasterSecret = |
191 if (debug != null && Debug.isOn("session")) { |
189 (hc.handshakeExtensions.get( |
192 System.out.println("%% Initialized: " + this); |
190 SSLExtension.CH_EXTENDED_MASTER_SECRET) != null) && |
191 (hc.handshakeExtensions.get( |
|
192 SSLExtension.SH_EXTENDED_MASTER_SECRET) != null); |
|
193 } else { |
|
194 this.useExtendedMasterSecret = |
|
195 (hc.handshakeExtensions.get( |
|
196 SSLExtension.CH_EXTENDED_MASTER_SECRET) != null) && |
|
197 (!hc.negotiatedProtocol.useTLS13PlusSpec()); |
|
198 } |
|
199 this.creationTime = creationTime; |
|
200 |
|
201 if (SSLLogger.isOn && SSLLogger.isOn("session")) { |
|
202 SSLLogger.finest("Session initialized: " + this); |
|
193 } |
203 } |
194 } |
204 } |
195 |
205 |
196 void setMasterSecret(SecretKey secret) { |
206 void setMasterSecret(SecretKey secret) { |
197 if (masterSecret == null) { |
207 masterSecret = secret; |
198 masterSecret = secret; |
208 } |
199 } else { |
209 |
200 throw new RuntimeException("setMasterSecret() error"); |
210 void setResumptionMasterSecret(SecretKey secret) { |
201 } |
211 resumptionMasterSecret = secret; |
212 } |
|
213 |
|
214 void setPreSharedKey(SecretKey key) { |
|
215 preSharedKey = key; |
|
216 } |
|
217 |
|
218 void addChild(SSLSessionImpl session) { |
|
219 childSessions.add(session); |
|
220 } |
|
221 |
|
222 void setTicketAgeAdd(int ticketAgeAdd) { |
|
223 this.ticketAgeAdd = ticketAgeAdd; |
|
224 } |
|
225 |
|
226 void setPskIdentity(byte[] pskIdentity) { |
|
227 this.pskIdentity = pskIdentity; |
|
228 } |
|
229 |
|
230 BigInteger incrTicketNonceCounter() { |
|
231 BigInteger result = ticketNonceCounter; |
|
232 ticketNonceCounter = ticketNonceCounter.add(BigInteger.valueOf(1)); |
|
233 return result; |
|
202 } |
234 } |
203 |
235 |
204 /** |
236 /** |
205 * Returns the master secret ... treat with extreme caution! |
237 * Returns the master secret ... treat with extreme caution! |
206 */ |
238 */ |
207 SecretKey getMasterSecret() { |
239 SecretKey getMasterSecret() { |
208 return masterSecret; |
240 return masterSecret; |
209 } |
241 } |
210 |
242 |
211 boolean getUseExtendedMasterSecret() { |
243 Optional<SecretKey> getResumptionMasterSecret() { |
212 return useExtendedMasterSecret; |
244 return Optional.ofNullable(resumptionMasterSecret); |
245 } |
|
246 |
|
247 synchronized Optional<SecretKey> getPreSharedKey() { |
|
248 return Optional.ofNullable(preSharedKey); |
|
249 } |
|
250 |
|
251 synchronized Optional<SecretKey> consumePreSharedKey() { |
|
252 Optional<SecretKey> result = Optional.ofNullable(preSharedKey); |
|
253 preSharedKey = null; |
|
254 return result; |
|
255 } |
|
256 |
|
257 int getTicketAgeAdd() { |
|
258 return ticketAgeAdd; |
|
259 } |
|
260 |
|
261 /* |
|
262 * Get the PSK identity. Take care not to use it in multiple connections. |
|
263 */ |
|
264 synchronized Optional<byte[]> getPskIdentity() { |
|
265 return Optional.ofNullable(pskIdentity); |
|
266 } |
|
267 |
|
268 /* PSK identities created from new_session_ticket messages should only |
|
269 * be used once. This method will return the identity and then clear it |
|
270 * so it cannot be used again. |
|
271 */ |
|
272 synchronized Optional<byte[]> consumePskIdentity() { |
|
273 Optional<byte[]> result = Optional.ofNullable(pskIdentity); |
|
274 pskIdentity = null; |
|
275 return result; |
|
213 } |
276 } |
214 |
277 |
215 void setPeerCertificates(X509Certificate[] peer) { |
278 void setPeerCertificates(X509Certificate[] peer) { |
216 if (peerCerts == null) { |
279 if (peerCerts == null) { |
217 peerCerts = peer; |
280 peerCerts = peer; |
225 void setLocalPrivateKey(PrivateKey privateKey) { |
288 void setLocalPrivateKey(PrivateKey privateKey) { |
226 localPrivateKey = privateKey; |
289 localPrivateKey = privateKey; |
227 } |
290 } |
228 |
291 |
229 void setPeerSupportedSignatureAlgorithms( |
292 void setPeerSupportedSignatureAlgorithms( |
230 Collection<SignatureAndHashAlgorithm> algorithms) { |
293 Collection<SignatureScheme> signatureSchemes) { |
231 peerSupportedSignAlgs = |
294 peerSupportedSignAlgs = |
232 SignatureAndHashAlgorithm.getAlgorithmNames(algorithms); |
295 SignatureScheme.getAlgorithmNames(signatureSchemes); |
233 } |
296 } |
234 |
297 |
235 void setRequestedServerNames(List<SNIServerName> requestedServerNames) { |
298 // TLS 1.2 only |
236 this.requestedServerNames = new ArrayList<>(requestedServerNames); |
299 // |
300 // Per RFC 5246, If the client supports only the default hash |
|
301 // and signature algorithms, it MAY omit the |
|
302 // signature_algorithms extension. If the client does not |
|
303 // support the default algorithms, or supports other hash |
|
304 // and signature algorithms (and it is willing to use them |
|
305 // for verifying messages sent by the server, i.e., server |
|
306 // certificates and server key exchange), it MUST send the |
|
307 // signature_algorithms extension, listing the algorithms it |
|
308 // is willing to accept. |
|
309 void setUseDefaultPeerSignAlgs() { |
|
310 useDefaultPeerSignAlgs = true; |
|
311 peerSupportedSignAlgs = new String[] { |
|
312 "SHA1withRSA", "SHA1withDSA", "SHA1withECDSA"}; |
|
313 } |
|
314 |
|
315 // Returns the connection session. |
|
316 SSLSessionImpl finish() { |
|
317 if (useDefaultPeerSignAlgs) { |
|
318 this.peerSupportedSignAlgs = new String[0]; |
|
319 } |
|
320 |
|
321 return this; |
|
237 } |
322 } |
238 |
323 |
239 /** |
324 /** |
240 * Provide status response data obtained during the SSL handshake. |
325 * Provide status response data obtained during the SSL handshake. |
241 * |
326 * |
248 statusResponses = Collections.emptyList(); |
333 statusResponses = Collections.emptyList(); |
249 } |
334 } |
250 } |
335 } |
251 |
336 |
252 /** |
337 /** |
253 * Set the peer principal. |
|
254 */ |
|
255 void setPeerPrincipal(Principal principal) { |
|
256 if (peerPrincipal == null) { |
|
257 peerPrincipal = principal; |
|
258 } |
|
259 } |
|
260 |
|
261 /** |
|
262 * Set the local principal. |
|
263 */ |
|
264 void setLocalPrincipal(Principal principal) { |
|
265 localPrincipal = principal; |
|
266 } |
|
267 |
|
268 /** |
|
269 * Returns true iff this session may be resumed ... sessions are |
338 * Returns true iff this session may be resumed ... sessions are |
270 * usually resumable. Security policies may suggest otherwise, |
339 * usually resumable. Security policies may suggest otherwise, |
271 * for example sessions that haven't been used for a while (say, |
340 * for example sessions that haven't been used for a while (say, |
272 * a working day) won't be resumable, and sessions might have a |
341 * a working day) won't be resumable, and sessions might have a |
273 * maximum lifetime in any case. |
342 * maximum lifetime in any case. |
284 |
353 |
285 /** |
354 /** |
286 * Check if the authentication used when establishing this session |
355 * Check if the authentication used when establishing this session |
287 * is still valid. Returns true if no authentication was used |
356 * is still valid. Returns true if no authentication was used |
288 */ |
357 */ |
289 boolean isLocalAuthenticationValid() { |
358 private boolean isLocalAuthenticationValid() { |
290 if (localPrivateKey != null) { |
359 if (localPrivateKey != null) { |
291 try { |
360 try { |
292 // if the private key is no longer valid, getAlgorithm() |
361 // if the private key is no longer valid, getAlgorithm() |
293 // should throw an exception |
362 // should throw an exception |
294 // (e.g. Smartcard has been removed from the reader) |
363 // (e.g. Smartcard has been removed from the reader) |
296 } catch (Exception e) { |
365 } catch (Exception e) { |
297 invalidate(); |
366 invalidate(); |
298 return false; |
367 return false; |
299 } |
368 } |
300 } |
369 } |
370 |
|
301 return true; |
371 return true; |
302 } |
372 } |
303 |
373 |
304 /** |
374 /** |
305 * Returns the ID for this session. The ID is fixed for the |
375 * Returns the ID for this session. The ID is fixed for the |
352 * Resets the cipher spec in use on this session |
422 * Resets the cipher spec in use on this session |
353 */ |
423 */ |
354 void setSuite(CipherSuite suite) { |
424 void setSuite(CipherSuite suite) { |
355 cipherSuite = suite; |
425 cipherSuite = suite; |
356 |
426 |
357 if (debug != null && Debug.isOn("session")) { |
427 if (SSLLogger.isOn && SSLLogger.isOn("session")) { |
358 System.out.println("%% Negotiating: " + this); |
428 SSLLogger.finest("Negotiating session: " + this); |
359 } |
429 } |
360 } |
430 } |
361 |
431 |
362 /** |
432 /** |
363 * Return true if the session is currently re-established with a |
433 * Return true if the session is currently re-established with a |
394 public String getProtocol() { |
464 public String getProtocol() { |
395 return getProtocolVersion().name; |
465 return getProtocolVersion().name; |
396 } |
466 } |
397 |
467 |
398 /** |
468 /** |
399 * Returns the compression technique used in this session |
|
400 */ |
|
401 byte getCompression() { |
|
402 return compressionMethod; |
|
403 } |
|
404 |
|
405 /** |
|
406 * Returns the hashcode for this session |
469 * Returns the hashcode for this session |
407 */ |
470 */ |
408 @Override |
471 @Override |
409 public int hashCode() { |
472 public int hashCode() { |
410 return sessionId.hashCode(); |
473 return sessionId.hashCode(); |
411 } |
474 } |
412 |
|
413 |
475 |
414 /** |
476 /** |
415 * Returns true if sessions have same ids, false otherwise. |
477 * Returns true if sessions have same ids, false otherwise. |
416 */ |
478 */ |
417 @Override |
479 @Override |
433 |
495 |
434 /** |
496 /** |
435 * Return the cert chain presented by the peer in the |
497 * Return the cert chain presented by the peer in the |
436 * java.security.cert format. |
498 * java.security.cert format. |
437 * Note: This method can be used only when using certificate-based |
499 * Note: This method can be used only when using certificate-based |
438 * cipher suites; using it with non-certificate-based cipher suites, |
500 * cipher suites; using it with non-certificate-based cipher suites |
439 * such as Kerberos, will throw an SSLPeerUnverifiedException. |
501 * will throw an SSLPeerUnverifiedException. |
440 * |
502 * |
441 * @return array of peer X.509 certs, with the peer's own cert |
503 * @return array of peer X.509 certs, with the peer's own cert |
442 * first in the chain, and with the "root" CA last. |
504 * first in the chain, and with the "root" CA last. |
443 */ |
505 */ |
444 @Override |
506 @Override |
447 // |
509 // |
448 // clone to preserve integrity of session ... caller can't |
510 // clone to preserve integrity of session ... caller can't |
449 // change record of peer identity even by accident, much |
511 // change record of peer identity even by accident, much |
450 // less do it intentionally. |
512 // less do it intentionally. |
451 // |
513 // |
452 if (ClientKeyExchangeService.find(cipherSuite.keyExchange.name) != null) { |
|
453 throw new SSLPeerUnverifiedException("no certificates expected" |
|
454 + " for " + cipherSuite.keyExchange + " cipher suites"); |
|
455 } |
|
456 if (peerCerts == null) { |
514 if (peerCerts == null) { |
457 throw new SSLPeerUnverifiedException("peer not authenticated"); |
515 throw new SSLPeerUnverifiedException("peer not authenticated"); |
458 } |
516 } |
459 // Certs are immutable objects, therefore we don't clone them. |
517 // Certs are immutable objects, therefore we don't clone them. |
460 // But do need to clone the array, so that nothing is inserted |
518 // But do need to clone the array, so that nothing is inserted |
483 |
541 |
484 /** |
542 /** |
485 * Return the cert chain presented by the peer in the |
543 * Return the cert chain presented by the peer in the |
486 * javax.security.cert format. |
544 * javax.security.cert format. |
487 * Note: This method can be used only when using certificate-based |
545 * Note: This method can be used only when using certificate-based |
488 * cipher suites; using it with non-certificate-based cipher suites, |
546 * cipher suites; using it with non-certificate-based cipher suites |
489 * such as Kerberos, will throw an SSLPeerUnverifiedException. |
547 * will throw an SSLPeerUnverifiedException. |
490 * |
548 * |
491 * @return array of peer X.509 certs, with the peer's own cert |
549 * @return array of peer X.509 certs, with the peer's own cert |
492 * first in the chain, and with the "root" CA last. |
550 * first in the chain, and with the "root" CA last. |
493 * |
551 * |
494 * @deprecated This method returns the deprecated |
552 * @deprecated This method returns the deprecated |
502 // |
560 // |
503 // clone to preserve integrity of session ... caller can't |
561 // clone to preserve integrity of session ... caller can't |
504 // change record of peer identity even by accident, much |
562 // change record of peer identity even by accident, much |
505 // less do it intentionally. |
563 // less do it intentionally. |
506 // |
564 // |
507 if (ClientKeyExchangeService.find(cipherSuite.keyExchange.name) != null) { |
|
508 throw new SSLPeerUnverifiedException("no certificates expected" |
|
509 + " for " + cipherSuite.keyExchange + " cipher suites"); |
|
510 } |
|
511 if (peerCerts == null) { |
565 if (peerCerts == null) { |
512 throw new SSLPeerUnverifiedException("peer not authenticated"); |
566 throw new SSLPeerUnverifiedException("peer not authenticated"); |
513 } |
567 } |
514 javax.security.cert.X509Certificate[] certs; |
568 javax.security.cert.X509Certificate[] certs; |
515 certs = new javax.security.cert.X509Certificate[peerCerts.length]; |
569 certs = new javax.security.cert.X509Certificate[peerCerts.length]; |
529 } |
583 } |
530 |
584 |
531 /** |
585 /** |
532 * Return the cert chain presented by the peer. |
586 * Return the cert chain presented by the peer. |
533 * Note: This method can be used only when using certificate-based |
587 * Note: This method can be used only when using certificate-based |
534 * cipher suites; using it with non-certificate-based cipher suites, |
588 * cipher suites; using it with non-certificate-based cipher suites |
535 * such as Kerberos, will throw an SSLPeerUnverifiedException. |
589 * will throw an SSLPeerUnverifiedException. |
536 * |
590 * |
537 * @return array of peer X.509 certs, with the peer's own cert |
591 * @return array of peer X.509 certs, with the peer's own cert |
538 * first in the chain, and with the "root" CA last. |
592 * first in the chain, and with the "root" CA last. |
539 */ |
593 */ |
540 public X509Certificate[] getCertificateChain() |
594 public X509Certificate[] getCertificateChain() |
542 /* |
596 /* |
543 * clone to preserve integrity of session ... caller can't |
597 * clone to preserve integrity of session ... caller can't |
544 * change record of peer identity even by accident, much |
598 * change record of peer identity even by accident, much |
545 * less do it intentionally. |
599 * less do it intentionally. |
546 */ |
600 */ |
547 if (ClientKeyExchangeService.find(cipherSuite.keyExchange.name) != null) { |
|
548 throw new SSLPeerUnverifiedException("no certificates expected" |
|
549 + " for " + cipherSuite.keyExchange + " cipher suites"); |
|
550 } |
|
551 if (peerCerts != null) { |
601 if (peerCerts != null) { |
552 return peerCerts.clone(); |
602 return peerCerts.clone(); |
553 } else { |
603 } else { |
554 throw new SSLPeerUnverifiedException("peer not authenticated"); |
604 throw new SSLPeerUnverifiedException("peer not authenticated"); |
555 } |
605 } |
582 /** |
632 /** |
583 * Returns the identity of the peer which was established as part of |
633 * Returns the identity of the peer which was established as part of |
584 * defining the session. |
634 * defining the session. |
585 * |
635 * |
586 * @return the peer's principal. Returns an X500Principal of the |
636 * @return the peer's principal. Returns an X500Principal of the |
587 * end-entity certificate for X509-based cipher suites, and |
637 * end-entity certificate for X509-based cipher suites. |
588 * Principal for Kerberos cipher suites, etc. |
|
589 * |
638 * |
590 * @throws SSLPeerUnverifiedException if the peer's identity has not |
639 * @throws SSLPeerUnverifiedException if the peer's identity has not |
591 * been verified |
640 * been verified |
592 */ |
641 */ |
593 @Override |
642 @Override |
594 public Principal getPeerPrincipal() |
643 public Principal getPeerPrincipal() |
595 throws SSLPeerUnverifiedException |
644 throws SSLPeerUnverifiedException |
596 { |
645 { |
597 if (ClientKeyExchangeService.find(cipherSuite.keyExchange.name) != null) { |
|
598 if (peerPrincipal == null) { |
|
599 throw new SSLPeerUnverifiedException("peer not authenticated"); |
|
600 } else { |
|
601 return peerPrincipal; |
|
602 } |
|
603 } |
|
604 if (peerCerts == null) { |
646 if (peerCerts == null) { |
605 throw new SSLPeerUnverifiedException("peer not authenticated"); |
647 throw new SSLPeerUnverifiedException("peer not authenticated"); |
606 } |
648 } |
607 return peerCerts[0].getSubjectX500Principal(); |
649 return peerCerts[0].getSubjectX500Principal(); |
608 } |
650 } |
609 |
651 |
610 /** |
652 /** |
611 * Returns the principal that was sent to the peer during handshaking. |
653 * Returns the principal that was sent to the peer during handshaking. |
612 * |
654 * |
613 * @return the principal sent to the peer. Returns an X500Principal |
655 * @return the principal sent to the peer. Returns an X500Principal |
614 * of the end-entity certificate for X509-based cipher suites, and |
656 * of the end-entity certificate for X509-based cipher suites. |
615 * Principal for Kerberos cipher suites, etc. If no principal was |
657 * If no principal was sent, then null is returned. |
616 * sent, then null is returned. |
|
617 */ |
658 */ |
618 @Override |
659 @Override |
619 public Principal getLocalPrincipal() { |
660 public Principal getLocalPrincipal() { |
620 |
661 return ((localCerts == null && localCerts.length != 0) ? null : |
621 if (ClientKeyExchangeService.find(cipherSuite.keyExchange.name) != null) { |
|
622 return (localPrincipal == null ? null : localPrincipal); |
|
623 } |
|
624 return (localCerts == null ? null : |
|
625 localCerts[0].getSubjectX500Principal()); |
662 localCerts[0].getSubjectX500Principal()); |
663 } |
|
664 |
|
665 /* |
|
666 * Return the time the ticket for this session was created. |
|
667 */ |
|
668 public long getTicketCreationTime() { |
|
669 return ticketCreationTime; |
|
626 } |
670 } |
627 |
671 |
628 /** |
672 /** |
629 * Returns the time this session was created. |
673 * Returns the time this session was created. |
630 */ |
674 */ |
693 // new connection, with no "real" session yet. |
737 // new connection, with no "real" session yet. |
694 // |
738 // |
695 if (this == nullSession) { |
739 if (this == nullSession) { |
696 return; |
740 return; |
697 } |
741 } |
698 invalidated = true; |
742 |
699 if (debug != null && Debug.isOn("session")) { |
|
700 System.out.println("%% Invalidated: " + this); |
|
701 } |
|
702 if (context != null) { |
743 if (context != null) { |
703 context.remove(sessionId); |
744 context.remove(sessionId); |
704 context = null; |
745 context = null; |
705 } |
746 } |
747 if (invalidated) { |
|
748 return; |
|
749 } |
|
750 invalidated = true; |
|
751 if (SSLLogger.isOn && SSLLogger.isOn("session")) { |
|
752 SSLLogger.finest("Invalidated session: " + this); |
|
753 } |
|
754 for (SSLSessionImpl child : childSessions) { |
|
755 child.invalidate(); |
|
756 } |
|
706 } |
757 } |
707 |
758 |
708 /* |
759 /* |
709 * Table of application-specific session data indexed by an application |
760 * Table of application-specific session data indexed by an application |
710 * key and the calling security context. This is important since |
761 * key and the calling security context. This is important since |
711 * sessions can be shared across different protection domains. |
762 * sessions can be shared across different protection domains. |
712 */ |
763 */ |
713 private Hashtable<SecureKey, Object> table = new Hashtable<>(); |
764 private final ConcurrentHashMap<SecureKey, Object> boundValues = |
765 new ConcurrentHashMap<>(); |
|
714 |
766 |
715 /** |
767 /** |
716 * Assigns a session value. Session change events are given if |
768 * Assigns a session value. Session change events are given if |
717 * appropriate, to any original value as well as the new value. |
769 * appropriate, to any original value as well as the new value. |
718 */ |
770 */ |
721 if ((key == null) || (value == null)) { |
773 if ((key == null) || (value == null)) { |
722 throw new IllegalArgumentException("arguments can not be null"); |
774 throw new IllegalArgumentException("arguments can not be null"); |
723 } |
775 } |
724 |
776 |
725 SecureKey secureKey = new SecureKey(key); |
777 SecureKey secureKey = new SecureKey(key); |
726 Object oldValue = table.put(secureKey, value); |
778 Object oldValue = boundValues.put(secureKey, value); |
727 |
779 |
728 if (oldValue instanceof SSLSessionBindingListener) { |
780 if (oldValue instanceof SSLSessionBindingListener) { |
729 SSLSessionBindingEvent e; |
781 SSLSessionBindingEvent e; |
730 |
782 |
731 e = new SSLSessionBindingEvent(this, key); |
783 e = new SSLSessionBindingEvent(this, key); |
736 |
788 |
737 e = new SSLSessionBindingEvent(this, key); |
789 e = new SSLSessionBindingEvent(this, key); |
738 ((SSLSessionBindingListener)value).valueBound(e); |
790 ((SSLSessionBindingListener)value).valueBound(e); |
739 } |
791 } |
740 } |
792 } |
741 |
|
742 |
793 |
743 /** |
794 /** |
744 * Returns the specified session value. |
795 * Returns the specified session value. |
745 */ |
796 */ |
746 @Override |
797 @Override |
748 if (key == null) { |
799 if (key == null) { |
749 throw new IllegalArgumentException("argument can not be null"); |
800 throw new IllegalArgumentException("argument can not be null"); |
750 } |
801 } |
751 |
802 |
752 SecureKey secureKey = new SecureKey(key); |
803 SecureKey secureKey = new SecureKey(key); |
753 return table.get(secureKey); |
804 return boundValues.get(secureKey); |
754 } |
805 } |
755 |
806 |
756 |
807 |
757 /** |
808 /** |
758 * Removes the specified session value, delivering a session changed |
809 * Removes the specified session value, delivering a session changed |
763 if (key == null) { |
814 if (key == null) { |
764 throw new IllegalArgumentException("argument can not be null"); |
815 throw new IllegalArgumentException("argument can not be null"); |
765 } |
816 } |
766 |
817 |
767 SecureKey secureKey = new SecureKey(key); |
818 SecureKey secureKey = new SecureKey(key); |
768 Object value = table.remove(secureKey); |
819 Object value = boundValues.remove(secureKey); |
769 |
820 |
770 if (value instanceof SSLSessionBindingListener) { |
821 if (value instanceof SSLSessionBindingListener) { |
771 SSLSessionBindingEvent e; |
822 SSLSessionBindingEvent e; |
772 |
823 |
773 e = new SSLSessionBindingEvent(this, key); |
824 e = new SSLSessionBindingEvent(this, key); |
779 /** |
830 /** |
780 * Lists the names of the session values. |
831 * Lists the names of the session values. |
781 */ |
832 */ |
782 @Override |
833 @Override |
783 public String[] getValueNames() { |
834 public String[] getValueNames() { |
784 Enumeration<SecureKey> e; |
835 ArrayList<Object> v = new ArrayList<>(); |
785 Vector<Object> v = new Vector<>(); |
|
786 SecureKey key; |
|
787 Object securityCtx = SecureKey.getCurrentSecurityContext(); |
836 Object securityCtx = SecureKey.getCurrentSecurityContext(); |
788 |
837 for (Enumeration<SecureKey> e = boundValues.keys(); |
789 for (e = table.keys(); e.hasMoreElements(); ) { |
838 e.hasMoreElements(); ) { |
790 key = e.nextElement(); |
839 SecureKey key = e.nextElement(); |
791 |
|
792 if (securityCtx.equals(key.getSecurityContext())) { |
840 if (securityCtx.equals(key.getSecurityContext())) { |
793 v.addElement(key.getAppKey()); |
841 v.add(key.getAppKey()); |
794 } |
842 } |
795 } |
843 } |
796 String[] names = new String[v.size()]; |
844 |
797 v.copyInto(names); |
845 return v.toArray(new String[0]); |
798 |
|
799 return names; |
|
800 } |
846 } |
801 |
847 |
802 /** |
848 /** |
803 * Use large packet sizes now or follow RFC 2246 packet sizes (2^14) |
849 * Use large packet sizes now or follow RFC 2246 packet sizes (2^14) |
804 * until changed. |
850 * until changed. |
811 * Application could accept large fragments up to 2^15 bytes by |
857 * Application could accept large fragments up to 2^15 bytes by |
812 * setting the system property jsse.SSLEngine.acceptLargeFragments |
858 * setting the system property jsse.SSLEngine.acceptLargeFragments |
813 * to "true". |
859 * to "true". |
814 */ |
860 */ |
815 private boolean acceptLargeFragments = |
861 private boolean acceptLargeFragments = |
816 Debug.getBooleanProperty("jsse.SSLEngine.acceptLargeFragments", false); |
862 Utilities.getBooleanProperty( |
863 "jsse.SSLEngine.acceptLargeFragments", false); |
|
817 |
864 |
818 /** |
865 /** |
819 * Expand the buffer size of both SSL/TLS network packet and |
866 * Expand the buffer size of both SSL/TLS network packet and |
820 * application data. |
867 * application data. |
821 */ |
868 */ |
833 // and negotiatedMaxFragLen. |
880 // and negotiatedMaxFragLen. |
834 int packetSize = 0; |
881 int packetSize = 0; |
835 if (negotiatedMaxFragLen > 0) { |
882 if (negotiatedMaxFragLen > 0) { |
836 packetSize = cipherSuite.calculatePacketSize( |
883 packetSize = cipherSuite.calculatePacketSize( |
837 negotiatedMaxFragLen, protocolVersion, |
884 negotiatedMaxFragLen, protocolVersion, |
838 protocolVersion.isDTLSProtocol()); |
885 protocolVersion.isDTLS); |
839 } |
886 } |
840 |
887 |
841 if (maximumPacketSize > 0) { |
888 if (maximumPacketSize > 0) { |
842 return (maximumPacketSize > packetSize) ? |
889 return (maximumPacketSize > packetSize) ? |
843 maximumPacketSize : packetSize; |
890 maximumPacketSize : packetSize; |
845 |
892 |
846 if (packetSize != 0) { |
893 if (packetSize != 0) { |
847 return packetSize; |
894 return packetSize; |
848 } |
895 } |
849 |
896 |
850 if (protocolVersion.isDTLSProtocol()) { |
897 if (protocolVersion.isDTLS) { |
851 return DTLSRecord.maxRecordSize; |
898 return DTLSRecord.maxRecordSize; |
852 } else { |
899 } else { |
853 return acceptLargeFragments ? |
900 return acceptLargeFragments ? |
854 SSLRecord.maxLargeRecordSize : SSLRecord.maxRecordSize; |
901 SSLRecord.maxLargeRecordSize : SSLRecord.maxRecordSize; |
855 } |
902 } |
865 // and negotiatedMaxFragLen. |
912 // and negotiatedMaxFragLen. |
866 int fragmentSize = 0; |
913 int fragmentSize = 0; |
867 if (maximumPacketSize > 0) { |
914 if (maximumPacketSize > 0) { |
868 fragmentSize = cipherSuite.calculateFragSize( |
915 fragmentSize = cipherSuite.calculateFragSize( |
869 maximumPacketSize, protocolVersion, |
916 maximumPacketSize, protocolVersion, |
870 protocolVersion.isDTLSProtocol()); |
917 protocolVersion.isDTLS); |
871 } |
918 } |
872 |
919 |
873 if (negotiatedMaxFragLen > 0) { |
920 if (negotiatedMaxFragLen > 0) { |
874 return (negotiatedMaxFragLen > fragmentSize) ? |
921 return (negotiatedMaxFragLen > fragmentSize) ? |
875 negotiatedMaxFragLen : fragmentSize; |
922 negotiatedMaxFragLen : fragmentSize; |
877 |
924 |
878 if (fragmentSize != 0) { |
925 if (fragmentSize != 0) { |
879 return fragmentSize; |
926 return fragmentSize; |
880 } |
927 } |
881 |
928 |
882 if (protocolVersion.isDTLSProtocol()) { |
929 if (protocolVersion.isDTLS) { |
883 return Record.maxDataSize; |
930 return Record.maxDataSize; |
884 } else { |
931 } else { |
885 int maxPacketSize = acceptLargeFragments ? |
932 int maxPacketSize = acceptLargeFragments ? |
886 SSLRecord.maxLargeRecordSize : SSLRecord.maxRecordSize; |
933 SSLRecord.maxLargeRecordSize : SSLRecord.maxRecordSize; |
887 return (maxPacketSize - SSLRecord.headerSize); |
934 return (maxPacketSize - SSLRecord.headerSize); |
951 * Obtains a <code>List</code> containing all {@link SNIServerName}s |
998 * Obtains a <code>List</code> containing all {@link SNIServerName}s |
952 * of the requested Server Name Indication (SNI) extension. |
999 * of the requested Server Name Indication (SNI) extension. |
953 */ |
1000 */ |
954 @Override |
1001 @Override |
955 public List<SNIServerName> getRequestedServerNames() { |
1002 public List<SNIServerName> getRequestedServerNames() { |
956 if (requestedServerNames != null && !requestedServerNames.isEmpty()) { |
1003 return requestedServerNames; |
957 return Collections.<SNIServerName>unmodifiableList( |
|
958 requestedServerNames); |
|
959 } |
|
960 |
|
961 return Collections.<SNIServerName>emptyList(); |
|
962 } |
1004 } |
963 |
1005 |
964 /** Returns a string representation of this SSL session */ |
1006 /** Returns a string representation of this SSL session */ |
965 @Override |
1007 @Override |
966 public String toString() { |
1008 public String toString() { |
967 return "[Session-" + sessionCount |
1009 return "Session(" + creationTime + "|" + getCipherSuite() + ")"; |
968 + ", " + getCipherSuite() |
1010 } |
969 + "]"; |
|
970 } |
|
971 |
|
972 } |
1011 } |
973 |
|
974 |
1012 |
975 /** |
1013 /** |
976 * This "struct" class serves as a Hash Key that combines an |
1014 * This "struct" class serves as a Hash Key that combines an |
977 * application-specific key and a security context. |
1015 * application-specific key and a security context. |
978 */ |
1016 */ |
979 class SecureKey { |
1017 class SecureKey { |
980 private static Object nullObject = new Object(); |
1018 private static final Object nullObject = new Object(); |
981 private Object appKey; |
1019 private final Object appKey; |
982 private Object securityCtx; |
1020 private final Object securityCtx; |
983 |
1021 |
984 static Object getCurrentSecurityContext() { |
1022 static Object getCurrentSecurityContext() { |
985 SecurityManager sm = System.getSecurityManager(); |
1023 SecurityManager sm = System.getSecurityManager(); |
986 Object context = null; |
1024 Object context = null; |
987 |
1025 |