56 * common functionality (e.g. key generation) that is provided there. |
56 * common functionality (e.g. key generation) that is provided there. |
57 * |
57 * |
58 * @author David Brownell |
58 * @author David Brownell |
59 */ |
59 */ |
60 final class ClientHandshaker extends Handshaker { |
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; |
61 |
65 |
62 // the server's public key from its certificate. |
66 // the server's public key from its certificate. |
63 private PublicKey serverKey; |
67 private PublicKey serverKey; |
64 |
68 |
65 // the server's ephemeral public key from the server key exchange message |
69 // the server's ephemeral public key from the server key exchange message |
1500 X509Certificate prevCert) { |
1504 X509Certificate prevCert) { |
1501 if (thisCert.equals(prevCert)) { |
1505 if (thisCert.equals(prevCert)) { |
1502 return true; |
1506 return true; |
1503 } |
1507 } |
1504 |
1508 |
1505 // check the iPAddress field in subjectAltName extension |
1509 // check subject alternative names |
1506 Object thisIPAddress = getSubjectAltName(thisCert, 7); // 7: iPAddress |
1510 Collection<List<?>> thisSubjectAltNames = null; |
1507 Object prevIPAddress = getSubjectAltName(prevCert, 7); |
1511 try { |
1508 if (thisIPAddress != null && prevIPAddress!= null) { |
1512 thisSubjectAltNames = thisCert.getSubjectAlternativeNames(); |
1509 // only allow the exactly match |
1513 } catch (CertificateParsingException cpe) { |
1510 return Objects.equals(thisIPAddress, prevIPAddress); |
1514 if (debug != null && Debug.isOn("handshake")) { |
1511 } |
1515 System.out.println( |
1512 |
1516 "Attempt to obtain subjectAltNames extension failed!"); |
1513 // check the dNSName field in subjectAltName extension |
1517 } |
1514 Object thisDNSName = getSubjectAltName(thisCert, 2); // 2: dNSName |
1518 } |
1515 Object prevDNSName = getSubjectAltName(prevCert, 2); |
1519 |
1516 if (thisDNSName != null && prevDNSName!= null) { |
1520 Collection<List<?>> prevSubjectAltNames = null; |
1517 // only allow the exactly match |
1521 try { |
1518 return Objects.equals(thisDNSName, prevDNSName); |
1522 prevSubjectAltNames = prevCert.getSubjectAlternativeNames(); |
|
1523 } catch (CertificateParsingException cpe) { |
|
1524 if (debug != null && Debug.isOn("handshake")) { |
|
1525 System.out.println( |
|
1526 "Attempt to obtain subjectAltNames extension failed!"); |
|
1527 } |
|
1528 } |
|
1529 |
|
1530 if ((thisSubjectAltNames != null) && (prevSubjectAltNames != null)) { |
|
1531 // check the iPAddress field in subjectAltName extension |
|
1532 Collection<String> thisSubAltIPAddrs = |
|
1533 getSubjectAltNames(thisSubjectAltNames, ALTNAME_IP); |
|
1534 Collection<String> prevSubAltIPAddrs = |
|
1535 getSubjectAltNames(prevSubjectAltNames, ALTNAME_IP); |
|
1536 if ((thisSubAltIPAddrs != null) && (prevSubAltIPAddrs != null) && |
|
1537 (isEquivalent(thisSubAltIPAddrs, prevSubAltIPAddrs))) { |
|
1538 |
|
1539 return true; |
|
1540 } |
|
1541 |
|
1542 // check the dNSName field in subjectAltName extension |
|
1543 Collection<String> thisSubAltDnsNames = |
|
1544 getSubjectAltNames(thisSubjectAltNames, ALTNAME_DNS); |
|
1545 Collection<String> prevSubAltDnsNames = |
|
1546 getSubjectAltNames(prevSubjectAltNames, ALTNAME_DNS); |
|
1547 if ((thisSubAltDnsNames != null) && (prevSubAltDnsNames != null) && |
|
1548 (isEquivalent(thisSubAltDnsNames, prevSubAltDnsNames))) { |
|
1549 |
|
1550 return true; |
|
1551 } |
1519 } |
1552 } |
1520 |
1553 |
1521 // check the certificate subject and issuer |
1554 // check the certificate subject and issuer |
1522 X500Principal thisSubject = thisCert.getSubjectX500Principal(); |
1555 X500Principal thisSubject = thisCert.getSubjectX500Principal(); |
1523 X500Principal prevSubject = prevCert.getSubjectX500Principal(); |
1556 X500Principal prevSubject = prevCert.getSubjectX500Principal(); |
1535 |
1568 |
1536 /* |
1569 /* |
1537 * Returns the subject alternative name of the specified type in the |
1570 * Returns the subject alternative name of the specified type in the |
1538 * subjectAltNames extension of a certificate. |
1571 * subjectAltNames extension of a certificate. |
1539 */ |
1572 */ |
1540 private static Object getSubjectAltName(X509Certificate cert, int type) { |
1573 private static Collection<String> getSubjectAltNames( |
1541 Collection<List<?>> subjectAltNames; |
1574 Collection<List<?>> subjectAltNames, int type) { |
1542 |
1575 |
1543 try { |
1576 HashSet<String> subAltDnsNames = null; |
1544 subjectAltNames = cert.getSubjectAlternativeNames(); |
1577 for (List<?> subjectAltName : subjectAltNames) { |
1545 } catch (CertificateParsingException cpe) { |
1578 int subjectAltNameType = (Integer)subjectAltName.get(0); |
1546 if (debug != null && Debug.isOn("handshake")) { |
1579 if (subjectAltNameType == type) { |
1547 System.out.println( |
1580 String subAltDnsName = (String)subjectAltName.get(1); |
1548 "Attempt to obtain subjectAltNames extension failed!"); |
1581 if ((subAltDnsName != null) && !subAltDnsName.isEmpty()) { |
1549 } |
1582 if (subAltDnsNames == null) { |
1550 return null; |
1583 subAltDnsNames = |
1551 } |
1584 new HashSet<>(subjectAltNames.size()); |
1552 |
1585 } |
1553 if (subjectAltNames != null) { |
1586 subAltDnsNames.add(subAltDnsName); |
1554 for (List<?> subjectAltName : subjectAltNames) { |
1587 } |
1555 int subjectAltNameType = (Integer)subjectAltName.get(0); |
1588 } |
1556 if (subjectAltNameType == type) { |
1589 } |
1557 return subjectAltName.get(1); |
1590 |
1558 } |
1591 return subAltDnsNames; |
1559 } |
1592 } |
1560 } |
1593 |
1561 |
1594 private static boolean isEquivalent(Collection<String> thisSubAltNames, |
1562 return null; |
1595 Collection<String> prevSubAltNames) { |
|
1596 |
|
1597 for (String thisSubAltName : thisSubAltNames) { |
|
1598 for (String prevSubAltName : prevSubAltNames) { |
|
1599 // Only allow the exactly match. Check no wildcard character. |
|
1600 if (thisSubAltName.equalsIgnoreCase(prevSubAltName)) { |
|
1601 return true; |
|
1602 } |
|
1603 } |
|
1604 } |
|
1605 |
|
1606 return false; |
1563 } |
1607 } |
1564 } |
1608 } |