src/share/classes/sun/security/ssl/ClientHandshaker.java

Print this page




  42 import javax.crypto.SecretKey;
  43 import javax.crypto.spec.SecretKeySpec;
  44 
  45 import javax.net.ssl.*;
  46 
  47 import javax.security.auth.Subject;
  48 
  49 import sun.security.ssl.HandshakeMessage.*;
  50 import static sun.security.ssl.CipherSuite.KeyExchange.*;
  51 
  52 /**
  53  * ClientHandshaker does the protocol handshaking from the point
  54  * of view of a client.  It is driven asychronously by handshake messages
  55  * as delivered by the parent Handshaker class, and also uses
  56  * common functionality (e.g. key generation) that is provided there.
  57  *
  58  * @author David Brownell
  59  */
  60 final class ClientHandshaker extends Handshaker {
  61 




  62     // the server's public key from its certificate.
  63     private PublicKey serverKey;
  64 
  65     // the server's ephemeral public key from the server key exchange message
  66     // for ECDHE/ECDH_anon and RSA_EXPORT.
  67     private PublicKey ephemeralServerKey;
  68 
  69     // server's ephemeral public value for DHE/DH_anon key exchanges
  70     private BigInteger          serverDH;
  71 
  72     private DHCrypt             dh;
  73 
  74     private ECDHCrypt ecdh;
  75 
  76     private CertificateRequest  certRequest;
  77 
  78     private boolean serverKeyExchangeReceived;
  79 
  80     /*
  81      * The RSA PreMasterSecret needs to know the version of


1480         session.setPeerCertificates(peerCerts);
1481     }
1482 
1483     /*
1484      * Whether the certificates can represent the same identity?
1485      *
1486      * The certificates can be used to represent the same identity:
1487      *     1. If the subject alternative names of IP address are present in
1488      *        both certificates, they should be identical; otherwise,
1489      *     2. if the subject alternative names of DNS name are present in
1490      *        both certificates, they should be identical; otherwise,
1491      *     3. if the subject fields are present in both certificates, the
1492      *        certificate subjects and issuers should be identical.
1493      */
1494     private static boolean isIdentityEquivalent(X509Certificate thisCert,
1495             X509Certificate prevCert) {
1496         if (thisCert.equals(prevCert)) {
1497             return true;
1498         }
1499 






















1500         // check the iPAddress field in subjectAltName extension
1501         Object thisIPAddress = getSubjectAltName(thisCert, 7);  // 7: iPAddress
1502         Object prevIPAddress = getSubjectAltName(prevCert, 7);
1503         if (thisIPAddress != null && prevIPAddress!= null) {
1504             // only allow the exactly match
1505             return Objects.equals(thisIPAddress, prevIPAddress);



1506         }
1507 
1508         // check the dNSName field in subjectAltName extension
1509         Object thisDNSName = getSubjectAltName(thisCert, 2);    // 2: dNSName
1510         Object prevDNSName = getSubjectAltName(prevCert, 2);
1511         if (thisDNSName != null && prevDNSName!= null) {
1512             // only allow the exactly match
1513             return Objects.equals(thisDNSName, prevDNSName);



1514         }

1515 
1516         // check the certificate subject and issuer
1517         X500Principal thisSubject = thisCert.getSubjectX500Principal();
1518         X500Principal prevSubject = prevCert.getSubjectX500Principal();
1519         X500Principal thisIssuer = thisCert.getIssuerX500Principal();
1520         X500Principal prevIssuer = prevCert.getIssuerX500Principal();
1521         if (!thisSubject.getName().isEmpty() &&
1522                 !prevSubject.getName().isEmpty() &&
1523                 thisSubject.equals(prevSubject) &&
1524                 thisIssuer.equals(prevIssuer)) {
1525             return true;
1526         }
1527 
1528         return false;
1529     }
1530 
1531     /*
1532      * Returns the subject alternative name of the specified type in the
1533      * subjectAltNames extension of a certificate.



1534      */
1535     private static Object getSubjectAltName(X509Certificate cert, int type) {
1536         Collection<List<?>> subjectAltNames;
1537 
1538         try {
1539             subjectAltNames = cert.getSubjectAlternativeNames();
1540         } catch (CertificateParsingException cpe) {
1541             if (debug != null && Debug.isOn("handshake")) {
1542                 System.out.println(
1543                         "Attempt to obtain subjectAltNames extension failed!");
1544             }
1545             return null;
1546         }
1547 
1548         if (subjectAltNames != null) {
1549             for (List<?> subjectAltName : subjectAltNames) {
1550                 int subjectAltNameType = (Integer)subjectAltName.get(0);
1551                 if (subjectAltNameType == type) {
1552                     return subjectAltName.get(1);




1553                 }

1554             }
1555         }

1556 
1557         return null;
1558     }















1559 }


  42 import javax.crypto.SecretKey;
  43 import javax.crypto.spec.SecretKeySpec;
  44 
  45 import javax.net.ssl.*;
  46 
  47 import javax.security.auth.Subject;
  48 
  49 import sun.security.ssl.HandshakeMessage.*;
  50 import static sun.security.ssl.CipherSuite.KeyExchange.*;
  51 
  52 /**
  53  * ClientHandshaker does the protocol handshaking from the point
  54  * of view of a client.  It is driven asychronously by handshake messages
  55  * as delivered by the parent Handshaker class, and also uses
  56  * common functionality (e.g. key generation) that is provided there.
  57  *
  58  * @author David Brownell
  59  */
  60 final class ClientHandshaker extends Handshaker {
  61 
  62     // constants for subject alt names of type DNS and IP
  63     private final static int ALTNAME_DNS = 2;
  64     private final static int ALTNAME_IP  = 7;
  65 
  66     // the server's public key from its certificate.
  67     private PublicKey serverKey;
  68 
  69     // the server's ephemeral public key from the server key exchange message
  70     // for ECDHE/ECDH_anon and RSA_EXPORT.
  71     private PublicKey ephemeralServerKey;
  72 
  73     // server's ephemeral public value for DHE/DH_anon key exchanges
  74     private BigInteger          serverDH;
  75 
  76     private DHCrypt             dh;
  77 
  78     private ECDHCrypt ecdh;
  79 
  80     private CertificateRequest  certRequest;
  81 
  82     private boolean serverKeyExchangeReceived;
  83 
  84     /*
  85      * The RSA PreMasterSecret needs to know the version of


1484         session.setPeerCertificates(peerCerts);
1485     }
1486 
1487     /*
1488      * Whether the certificates can represent the same identity?
1489      *
1490      * The certificates can be used to represent the same identity:
1491      *     1. If the subject alternative names of IP address are present in
1492      *        both certificates, they should be identical; otherwise,
1493      *     2. if the subject alternative names of DNS name are present in
1494      *        both certificates, they should be identical; otherwise,
1495      *     3. if the subject fields are present in both certificates, the
1496      *        certificate subjects and issuers should be identical.
1497      */
1498     private static boolean isIdentityEquivalent(X509Certificate thisCert,
1499             X509Certificate prevCert) {
1500         if (thisCert.equals(prevCert)) {
1501             return true;
1502         }
1503 
1504         // check subject alternative names
1505         Collection<List<?>> thisSubjectAltNames = null;
1506         try {
1507             thisSubjectAltNames = thisCert.getSubjectAlternativeNames();
1508         } catch (CertificateParsingException cpe) {
1509             if (debug != null && Debug.isOn("handshake")) {
1510                 System.out.println(
1511                         "Attempt to obtain subjectAltNames extension failed!");
1512             }
1513         }
1514 
1515         Collection<List<?>> prevSubjectAltNames = null;
1516         try {
1517             prevSubjectAltNames = prevCert.getSubjectAlternativeNames();
1518         } catch (CertificateParsingException cpe) {
1519             if (debug != null && Debug.isOn("handshake")) {
1520                 System.out.println(
1521                         "Attempt to obtain subjectAltNames extension failed!");
1522             }
1523         }
1524 
1525         if ((thisSubjectAltNames != null) && (prevSubjectAltNames != null)) {
1526             // check the iPAddress field in subjectAltName extension
1527             Collection<String> thisSubAltIPAddrs =
1528                         getSubjectAltNames(thisSubjectAltNames, ALTNAME_IP);
1529             Collection<String> prevSubAltIPAddrs =
1530                         getSubjectAltNames(prevSubjectAltNames, ALTNAME_IP);
1531             if ((thisSubAltIPAddrs != null) && (prevSubAltIPAddrs != null) &&
1532                 (isEquivalent(thisSubAltIPAddrs, prevSubAltIPAddrs))) {
1533 
1534                 return true;
1535             }
1536 
1537             // check the dNSName field in subjectAltName extension
1538             Collection<String> thisSubAltDnsNames =
1539                         getSubjectAltNames(thisSubjectAltNames, ALTNAME_DNS);
1540             Collection<String> prevSubAltDnsNames =
1541                         getSubjectAltNames(prevSubjectAltNames, ALTNAME_DNS);
1542             if ((thisSubAltDnsNames != null) && (prevSubAltDnsNames != null) &&
1543                 (isEquivalent(thisSubAltDnsNames, prevSubAltDnsNames))) {
1544 
1545                 return true;
1546             }
1547         }
1548 
1549         // check the certificate subject and issuer
1550         X500Principal thisSubject = thisCert.getSubjectX500Principal();
1551         X500Principal prevSubject = prevCert.getSubjectX500Principal();
1552         X500Principal thisIssuer = thisCert.getIssuerX500Principal();
1553         X500Principal prevIssuer = prevCert.getIssuerX500Principal();
1554         if (!thisSubject.getName().isEmpty() &&
1555                 !prevSubject.getName().isEmpty() &&
1556                 thisSubject.equals(prevSubject) &&
1557                 thisIssuer.equals(prevIssuer)) {
1558             return true;
1559         }
1560 
1561         return false;
1562     }
1563 
1564     /*
1565      * Returns the subject alternative name of the specified type in the
1566      * subjectAltNames extension of a certificate.
1567      *
1568      * Note that only those subjectAltName types that use String data
1569      * should be passed into this function.
1570      */
1571     private static Collection<String> getSubjectAltNames(
1572             Collection<List<?>> subjectAltNames, int type) {
1573 
1574         HashSet<String> subAltDnsNames = null;










1575         for (List<?> subjectAltName : subjectAltNames) {
1576             int subjectAltNameType = (Integer)subjectAltName.get(0);
1577             if (subjectAltNameType == type) {
1578                 String subAltDnsName = (String)subjectAltName.get(1);
1579                 if ((subAltDnsName != null) && !subAltDnsName.isEmpty()) {
1580                     if (subAltDnsNames == null) {
1581                         subAltDnsNames =
1582                                 new HashSet<>(subjectAltNames.size());
1583                     }
1584                     subAltDnsNames.add(subAltDnsName);
1585                 }
1586             }
1587         }
1588 
1589         return subAltDnsNames;
1590     }
1591 
1592     private static boolean isEquivalent(Collection<String> thisSubAltNames,
1593             Collection<String> prevSubAltNames) {
1594 
1595         for (String thisSubAltName : thisSubAltNames) {
1596             for (String prevSubAltName : prevSubAltNames) {
1597                 // Only allow the exactly match.  Check no wildcard character.
1598                 if (thisSubAltName.equalsIgnoreCase(prevSubAltName)) {
1599                     return true;
1600                 }
1601             }
1602         }
1603 
1604         return false;
1605     }
1606 }