36 import javax.crypto.SecretKey; |
36 import javax.crypto.SecretKey; |
37 import javax.crypto.spec.SecretKeySpec; |
37 import javax.crypto.spec.SecretKeySpec; |
38 |
38 |
39 import javax.net.ssl.*; |
39 import javax.net.ssl.*; |
40 |
40 |
41 import javax.security.auth.Subject; |
|
42 |
|
43 import sun.security.util.KeyUtil; |
41 import sun.security.util.KeyUtil; |
44 import sun.security.action.GetPropertyAction; |
42 import sun.security.action.GetPropertyAction; |
45 import sun.security.ssl.HandshakeMessage.*; |
43 import sun.security.ssl.HandshakeMessage.*; |
46 import sun.security.ssl.CipherSuite.*; |
44 import sun.security.ssl.CipherSuite.*; |
47 import sun.security.ssl.SignatureAndHashAlgorithm.*; |
45 import sun.security.ssl.SignatureAndHashAlgorithm.*; |
234 protocolVersion, clientRequestedVersion, |
232 protocolVersion, clientRequestedVersion, |
235 sslContext.getSecureRandom(), input, |
233 sslContext.getSecureRandom(), input, |
236 message_len, privateKey); |
234 message_len, privateKey); |
237 handshakeState.update(pms, resumingSession); |
235 handshakeState.update(pms, resumingSession); |
238 preMasterSecret = this.clientKeyExchange(pms); |
236 preMasterSecret = this.clientKeyExchange(pms); |
239 break; |
|
240 case K_KRB5: |
|
241 case K_KRB5_EXPORT: |
|
242 KerberosClientKeyExchange kke = |
|
243 new KerberosClientKeyExchange(protocolVersion, |
|
244 clientRequestedVersion, |
|
245 sslContext.getSecureRandom(), |
|
246 input, |
|
247 this.getAccSE(), |
|
248 serviceCreds); |
|
249 handshakeState.update(kke, resumingSession); |
|
250 preMasterSecret = this.clientKeyExchange(kke); |
|
251 break; |
237 break; |
252 case K_DHE_RSA: |
238 case K_DHE_RSA: |
253 case K_DHE_DSS: |
239 case K_DHE_DSS: |
254 case K_DH_ANON: |
240 case K_DH_ANON: |
255 /* |
241 /* |
271 new ECDHClientKeyExchange(input); |
257 new ECDHClientKeyExchange(input); |
272 handshakeState.update(ecdhcke, resumingSession); |
258 handshakeState.update(ecdhcke, resumingSession); |
273 preMasterSecret = this.clientKeyExchange(ecdhcke); |
259 preMasterSecret = this.clientKeyExchange(ecdhcke); |
274 break; |
260 break; |
275 default: |
261 default: |
276 throw new SSLProtocolException |
262 ClientKeyExchangeService p = |
277 ("Unrecognized key exchange: " + keyExchange); |
263 ClientKeyExchangeService.find(keyExchange.name); |
|
264 if (p == null) { |
|
265 throw new SSLProtocolException |
|
266 ("Unrecognized key exchange: " + keyExchange); |
|
267 } |
|
268 byte[] encodedTicket = input.getBytes16(); |
|
269 input.getBytes16(); |
|
270 byte[] secret = input.getBytes16(); |
|
271 ClientKeyExchange cke = p.createServerExchange(protocolVersion, |
|
272 clientRequestedVersion, |
|
273 sslContext.getSecureRandom(), |
|
274 encodedTicket, |
|
275 secret, |
|
276 this.getAccSE(), serviceCreds); |
|
277 handshakeState.update(cke, resumingSession); |
|
278 preMasterSecret = this.clientKeyExchange(cke); |
|
279 break; |
278 } |
280 } |
279 |
281 |
280 // |
282 // |
281 // All keys are calculated from the premaster secret |
283 // All keys are calculated from the premaster secret |
282 // and the exchanged nonces in the same way. |
284 // and the exchanged nonces in the same way. |
622 } |
624 } |
623 |
625 |
624 // validate subject identity |
626 // validate subject identity |
625 if (resumingSession) { |
627 if (resumingSession) { |
626 CipherSuite suite = previous.getSuite(); |
628 CipherSuite suite = previous.getSuite(); |
627 if (suite.keyExchange == K_KRB5 || |
629 ClientKeyExchangeService p = |
628 suite.keyExchange == K_KRB5_EXPORT) { |
630 ClientKeyExchangeService.find(suite.keyExchange.name); |
|
631 if (p != null) { |
629 Principal localPrincipal = previous.getLocalPrincipal(); |
632 Principal localPrincipal = previous.getLocalPrincipal(); |
630 |
633 |
631 Subject subject = null; |
634 if (p.isRelated( |
632 try { |
635 false, getAccSE(), localPrincipal)) { |
633 subject = AccessController.doPrivileged( |
636 if (debug != null && Debug.isOn("session")) |
634 new PrivilegedExceptionAction<Subject>() { |
637 System.out.println("Subject can" + |
635 @Override |
638 " provide creds for princ"); |
636 public Subject run() throws Exception { |
|
637 return |
|
638 Krb5Helper.getServerSubject(getAccSE()); |
|
639 }}); |
|
640 } catch (PrivilegedActionException e) { |
|
641 subject = null; |
|
642 if (debug != null && Debug.isOn("session")) { |
|
643 System.out.println("Attempt to obtain" + |
|
644 " subject failed!"); |
|
645 } |
|
646 } |
|
647 |
|
648 if (subject != null) { |
|
649 // Eliminate dependency on KerberosPrincipal |
|
650 if (Krb5Helper.isRelated(subject, localPrincipal)) { |
|
651 if (debug != null && Debug.isOn("session")) |
|
652 System.out.println("Subject can" + |
|
653 " provide creds for princ"); |
|
654 } else { |
|
655 resumingSession = false; |
|
656 if (debug != null && Debug.isOn("session")) |
|
657 System.out.println("Subject cannot" + |
|
658 " provide creds for princ"); |
|
659 } |
|
660 } else { |
639 } else { |
661 resumingSession = false; |
640 resumingSession = false; |
662 if (debug != null && Debug.isOn("session")) |
641 if (debug != null && Debug.isOn("session")) |
663 System.out.println("Kerberos credentials are" + |
642 System.out.println("Subject cannot" + |
664 " not present in the current Subject;" + |
643 " provide creds for princ"); |
665 " check if " + |
|
666 " javax.security.auth.useSubjectAsCreds" + |
|
667 " system property has been set to false"); |
|
668 } |
644 } |
669 } |
645 } |
670 } |
646 } |
671 |
647 |
672 if (resumingSession) { |
648 if (resumingSession) { |
869 * NOTE: while an "anonymous RSA" mode is explicitly allowed by |
845 * NOTE: while an "anonymous RSA" mode is explicitly allowed by |
870 * the protocol, we can't support it since all of the SSL flavors |
846 * the protocol, we can't support it since all of the SSL flavors |
871 * defined in the protocol spec are explicitly stated to require |
847 * defined in the protocol spec are explicitly stated to require |
872 * using RSA certificates. |
848 * using RSA certificates. |
873 */ |
849 */ |
874 if (keyExchange == K_KRB5 || keyExchange == K_KRB5_EXPORT) { |
850 if (ClientKeyExchangeService.find(cipherSuite.keyExchange.name) != null) { |
875 // Server certificates are omitted for Kerberos ciphers |
851 // No external key exchange provider needs a cert now. |
876 |
|
877 } else if ((keyExchange != K_DH_ANON) && (keyExchange != K_ECDH_ANON)) { |
852 } else if ((keyExchange != K_DH_ANON) && (keyExchange != K_ECDH_ANON)) { |
878 if (certs == null) { |
853 if (certs == null) { |
879 throw new RuntimeException("no certificates"); |
854 throw new RuntimeException("no certificates"); |
880 } |
855 } |
881 |
856 |
998 // algorithms. |
978 // algorithms. |
999 // |
979 // |
1000 // Needed only if server requires client to authenticate self. |
980 // Needed only if server requires client to authenticate self. |
1001 // Illegal for anonymous flavors, so we need to check that. |
981 // Illegal for anonymous flavors, so we need to check that. |
1002 // |
982 // |
1003 // CertificateRequest is omitted for Kerberos ciphers |
983 // No external key exchange provider needs a cert now. |
1004 if (doClientAuth != ClientAuthType.CLIENT_AUTH_NONE && |
984 if (doClientAuth != ClientAuthType.CLIENT_AUTH_NONE && |
1005 keyExchange != K_DH_ANON && keyExchange != K_ECDH_ANON && |
985 keyExchange != K_DH_ANON && keyExchange != K_ECDH_ANON && |
1006 keyExchange != K_KRB5 && keyExchange != K_KRB5_EXPORT) { |
986 ClientKeyExchangeService.find(keyExchange.name) == null) { |
1007 |
987 |
1008 CertificateRequest m4; |
988 CertificateRequest m4; |
1009 X509Certificate caCerts[]; |
989 X509Certificate caCerts[]; |
1010 |
990 |
1011 Collection<SignatureAndHashAlgorithm> localSignAlgs = null; |
991 Collection<SignatureAndHashAlgorithm> localSignAlgs = null; |
1329 if (setupEphemeralECDHKeys() == false) { |
1302 if (setupEphemeralECDHKeys() == false) { |
1330 return false; |
1303 return false; |
1331 } |
1304 } |
1332 break; |
1305 break; |
1333 default: |
1306 default: |
1334 // internal error, unknown key exchange |
1307 ClientKeyExchangeService p = |
1335 throw new RuntimeException("Unrecognized cipherSuite: " + suite); |
1308 ClientKeyExchangeService.find(keyExchange.name); |
|
1309 if (p == null) { |
|
1310 // internal error, unknown key exchange |
|
1311 throw new RuntimeException("Unrecognized cipherSuite: " + suite); |
|
1312 } |
|
1313 // need service creds |
|
1314 if (serviceCreds == null) { |
|
1315 AccessControlContext acc = getAccSE(); |
|
1316 serviceCreds = p.getServiceCreds(acc); |
|
1317 if (serviceCreds != null) { |
|
1318 if (debug != null && Debug.isOn("handshake")) { |
|
1319 System.out.println("Using serviceCreds"); |
|
1320 } |
|
1321 } |
|
1322 if (serviceCreds == null) { |
|
1323 return false; |
|
1324 } |
|
1325 } |
|
1326 break; |
1336 } |
1327 } |
1337 setCipherSuite(suite); |
1328 setCipherSuite(suite); |
1338 |
1329 |
1339 // set the peer implicit supported signature algorithms |
1330 // set the peer implicit supported signature algorithms |
1340 if (protocolVersion.useTLS12PlusSpec()) { |
1331 if (protocolVersion.useTLS12PlusSpec()) { |
1520 this.privateKey = tempPrivateKey; |
1511 this.privateKey = tempPrivateKey; |
1521 this.certs = tempCerts; |
1512 this.certs = tempCerts; |
1522 return true; |
1513 return true; |
1523 } |
1514 } |
1524 |
1515 |
1525 /** |
|
1526 * Retrieve the Kerberos key for the specified server principal |
|
1527 * from the JAAS configuration file. |
|
1528 * |
|
1529 * @return true if successful, false if not available or invalid |
|
1530 */ |
|
1531 private boolean setupKerberosKeys() { |
|
1532 if (serviceCreds != null) { |
|
1533 return true; |
|
1534 } |
|
1535 try { |
|
1536 final AccessControlContext acc = getAccSE(); |
|
1537 serviceCreds = AccessController.doPrivileged( |
|
1538 // Eliminate dependency on KerberosKey |
|
1539 new PrivilegedExceptionAction<Object>() { |
|
1540 @Override |
|
1541 public Object run() throws Exception { |
|
1542 // get kerberos key for the default principal |
|
1543 return Krb5Helper.getServiceCreds(acc); |
|
1544 }}); |
|
1545 |
|
1546 // check permission to access and use the secret key of the |
|
1547 // Kerberized "host" service |
|
1548 if (serviceCreds != null) { |
|
1549 if (debug != null && Debug.isOn("handshake")) { |
|
1550 System.out.println("Using Kerberos creds"); |
|
1551 } |
|
1552 String serverPrincipal = |
|
1553 Krb5Helper.getServerPrincipalName(serviceCreds); |
|
1554 if (serverPrincipal != null) { |
|
1555 // When service is bound, we check ASAP. Otherwise, |
|
1556 // will check after client request is received |
|
1557 // in Kerberos ClientKeyExchange |
|
1558 SecurityManager sm = System.getSecurityManager(); |
|
1559 try { |
|
1560 if (sm != null) { |
|
1561 // Eliminate dependency on ServicePermission |
|
1562 sm.checkPermission(Krb5Helper.getServicePermission( |
|
1563 serverPrincipal, "accept"), acc); |
|
1564 } |
|
1565 } catch (SecurityException se) { |
|
1566 serviceCreds = null; |
|
1567 // Do not destroy keys. Will affect Subject |
|
1568 if (debug != null && Debug.isOn("handshake")) { |
|
1569 System.out.println("Permission to access Kerberos" |
|
1570 + " secret key denied"); |
|
1571 } |
|
1572 return false; |
|
1573 } |
|
1574 } |
|
1575 } |
|
1576 return serviceCreds != null; |
|
1577 } catch (PrivilegedActionException e) { |
|
1578 // Likely exception here is LoginExceptin |
|
1579 if (debug != null && Debug.isOn("handshake")) { |
|
1580 System.out.println("Attempt to obtain Kerberos key failed: " |
|
1581 + e.toString()); |
|
1582 } |
|
1583 return false; |
|
1584 } |
|
1585 } |
|
1586 |
|
1587 /* |
1516 /* |
1588 * For Kerberos ciphers, the premaster secret is encrypted using |
1517 * Returns premaster secret for external key exchange services. |
1589 * the session key. See RFC 2712. |
1518 */ |
1590 */ |
1519 private SecretKey clientKeyExchange(ClientKeyExchange mesg) |
1591 private SecretKey clientKeyExchange(KerberosClientKeyExchange mesg) |
|
1592 throws IOException { |
1520 throws IOException { |
1593 |
1521 |
1594 if (debug != null && Debug.isOn("handshake")) { |
1522 if (debug != null && Debug.isOn("handshake")) { |
1595 mesg.print(System.out); |
1523 mesg.print(System.out); |
1596 } |
1524 } |
1597 |
1525 |
1598 // Record the principals involved in exchange |
1526 // Record the principals involved in exchange |
1599 session.setPeerPrincipal(mesg.getPeerPrincipal()); |
1527 session.setPeerPrincipal(mesg.getPeerPrincipal()); |
1600 session.setLocalPrincipal(mesg.getLocalPrincipal()); |
1528 session.setLocalPrincipal(mesg.getLocalPrincipal()); |
1601 |
1529 |
1602 byte[] b = mesg.getUnencryptedPreMasterSecret(); |
1530 return mesg.clientKeyExchange(); |
1603 return new SecretKeySpec(b, "TlsPremasterSecret"); |
|
1604 } |
1531 } |
1605 |
1532 |
1606 /* |
1533 /* |
1607 * Diffie Hellman key exchange is used when the server presented |
1534 * Diffie Hellman key exchange is used when the server presented |
1608 * D-H parameters in its certificate (signed using RSA or DSS/DSA), |
1535 * D-H parameters in its certificate (signed using RSA or DSS/DSA), |
1703 * Verify if client did send the certificate when client |
1630 * Verify if client did send the certificate when client |
1704 * authentication was required, otherwise server should not proceed |
1631 * authentication was required, otherwise server should not proceed |
1705 */ |
1632 */ |
1706 if (doClientAuth == ClientAuthType.CLIENT_AUTH_REQUIRED) { |
1633 if (doClientAuth == ClientAuthType.CLIENT_AUTH_REQUIRED) { |
1707 // get X500Principal of the end-entity certificate for X509-based |
1634 // get X500Principal of the end-entity certificate for X509-based |
1708 // ciphersuites, or Kerberos principal for Kerberos ciphersuites |
1635 // ciphersuites, or Kerberos principal for Kerberos ciphersuites, etc |
1709 session.getPeerPrincipal(); |
1636 session.getPeerPrincipal(); |
1710 } |
1637 } |
1711 |
1638 |
1712 /* |
1639 /* |
1713 * Verify if client did send clientCertificateVerify message following |
1640 * Verify if client did send clientCertificateVerify message following |