Report a readable error on a duplicate cert in ca app
Commit 87e8feca (16 years ago!) introduced a bug where if we are
attempting to insert a cert with a duplicate subject name, and
duplicate subject names are not allowed (which is the default),
then we get an unhelpful error message back (error number 2). Prior
to that commit we got a helpful error message which displayed details
of the conflicting entry in the database.
That commit was itself attempting to fix a bug with the noemailDN option
where we were setting the subject field in the database too early
(before extensions had made any amendments to it).
This PR moves the check for a conflicting Subject name until after all
changes to the Subject have been made by extensions etc.
This also, co-incidentally fixes the ca crashing bug described in issue
5109.
Fixes #5109
Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/5627)
Matt Caswell
6 years ago
1368 | 1368 | CONF *lconf, unsigned long certopt, unsigned long nameopt, |
1369 | 1369 | int default_op, int ext_copy, int selfsign) |
1370 | 1370 | { |
1371 | X509_NAME *name = NULL, *CAname = NULL, *subject = NULL, *dn_subject = | |
1372 | NULL; | |
1371 | X509_NAME *name = NULL, *CAname = NULL, *subject = NULL; | |
1373 | 1372 | const ASN1_TIME *tm; |
1374 | 1373 | ASN1_STRING *str, *str2; |
1375 | 1374 | ASN1_OBJECT *obj; |
1568 | 1567 | goto end; |
1569 | 1568 | } |
1570 | 1569 | |
1570 | /* We are now totally happy, lets make and sign the certificate */ | |
1571 | if (verbose) | |
1572 | BIO_printf(bio_err, | |
1573 | "Everything appears to be ok, creating and signing the certificate\n"); | |
1574 | ||
1575 | if ((ret = X509_new()) == NULL) | |
1576 | goto end; | |
1577 | ||
1578 | #ifdef X509_V3 | |
1579 | /* Make it an X509 v3 certificate. */ | |
1580 | if (!X509_set_version(ret, 2)) | |
1581 | goto end; | |
1582 | #endif | |
1583 | ||
1584 | if (BN_to_ASN1_INTEGER(serial, X509_get_serialNumber(ret)) == NULL) | |
1585 | goto end; | |
1586 | if (selfsign) { | |
1587 | if (!X509_set_issuer_name(ret, subject)) | |
1588 | goto end; | |
1589 | } else { | |
1590 | if (!X509_set_issuer_name(ret, X509_get_subject_name(x509))) | |
1591 | goto end; | |
1592 | } | |
1593 | ||
1594 | if (!set_cert_times(ret, startdate, enddate, days)) | |
1595 | goto end; | |
1596 | ||
1597 | if (enddate != NULL) { | |
1598 | int tdays; | |
1599 | ||
1600 | if (!ASN1_TIME_diff(&tdays, NULL, NULL, X509_get0_notAfter(ret))) | |
1601 | goto end; | |
1602 | days = tdays; | |
1603 | } | |
1604 | ||
1605 | if (!X509_set_subject_name(ret, subject)) | |
1606 | goto end; | |
1607 | ||
1608 | pktmp = X509_REQ_get0_pubkey(req); | |
1609 | i = X509_set_pubkey(ret, pktmp); | |
1610 | if (!i) | |
1611 | goto end; | |
1612 | ||
1613 | /* Lets add the extensions, if there are any */ | |
1614 | if (ext_sect) { | |
1615 | X509V3_CTX ctx; | |
1616 | ||
1617 | /* Initialize the context structure */ | |
1618 | if (selfsign) | |
1619 | X509V3_set_ctx(&ctx, ret, ret, req, NULL, 0); | |
1620 | else | |
1621 | X509V3_set_ctx(&ctx, x509, ret, req, NULL, 0); | |
1622 | ||
1623 | if (extconf) { | |
1624 | if (verbose) | |
1625 | BIO_printf(bio_err, "Extra configuration file found\n"); | |
1626 | ||
1627 | /* Use the extconf configuration db LHASH */ | |
1628 | X509V3_set_nconf(&ctx, extconf); | |
1629 | ||
1630 | /* Test the structure (needed?) */ | |
1631 | /* X509V3_set_ctx_test(&ctx); */ | |
1632 | ||
1633 | /* Adds exts contained in the configuration file */ | |
1634 | if (!X509V3_EXT_add_nconf(extconf, &ctx, ext_sect, ret)) { | |
1635 | BIO_printf(bio_err, | |
1636 | "ERROR: adding extensions in section %s\n", | |
1637 | ext_sect); | |
1638 | ERR_print_errors(bio_err); | |
1639 | goto end; | |
1640 | } | |
1641 | if (verbose) | |
1642 | BIO_printf(bio_err, | |
1643 | "Successfully added extensions from file.\n"); | |
1644 | } else if (ext_sect) { | |
1645 | /* We found extensions to be set from config file */ | |
1646 | X509V3_set_nconf(&ctx, lconf); | |
1647 | ||
1648 | if (!X509V3_EXT_add_nconf(lconf, &ctx, ext_sect, ret)) { | |
1649 | BIO_printf(bio_err, | |
1650 | "ERROR: adding extensions in section %s\n", | |
1651 | ext_sect); | |
1652 | ERR_print_errors(bio_err); | |
1653 | goto end; | |
1654 | } | |
1655 | ||
1656 | if (verbose) | |
1657 | BIO_printf(bio_err, | |
1658 | "Successfully added extensions from config\n"); | |
1659 | } | |
1660 | } | |
1661 | ||
1662 | /* Copy extensions from request (if any) */ | |
1663 | ||
1664 | if (!copy_extensions(ret, req, ext_copy)) { | |
1665 | BIO_printf(bio_err, "ERROR: adding extensions from request\n"); | |
1666 | ERR_print_errors(bio_err); | |
1667 | goto end; | |
1668 | } | |
1669 | ||
1670 | { | |
1671 | const STACK_OF(X509_EXTENSION) *exts = X509_get0_extensions(ret); | |
1672 | ||
1673 | if (exts != NULL && sk_X509_EXTENSION_num(exts) > 0) | |
1674 | /* Make it an X509 v3 certificate. */ | |
1675 | if (!X509_set_version(ret, 2)) | |
1676 | goto end; | |
1677 | } | |
1678 | ||
1571 | 1679 | if (verbose) |
1572 | 1680 | BIO_printf(bio_err, |
1573 | 1681 | "The subject name appears to be ok, checking data base for clashes\n"); |
1574 | 1682 | |
1575 | /* Build the correct Subject if no e-mail is wanted in the subject */ | |
1576 | /* | |
1577 | * and add it later on because of the method extensions are added | |
1578 | * (altName) | |
1579 | */ | |
1580 | ||
1581 | if (email_dn) | |
1582 | dn_subject = subject; | |
1583 | else { | |
1683 | /* Build the correct Subject if no e-mail is wanted in the subject. */ | |
1684 | if (!email_dn) { | |
1584 | 1685 | X509_NAME_ENTRY *tmpne; |
1686 | X509_NAME *dn_subject; | |
1687 | ||
1585 | 1688 | /* |
1586 | 1689 | * Its best to dup the subject DN and then delete any email addresses |
1587 | 1690 | * because this retains its structure. |
1597 | 1700 | X509_NAME_delete_entry(dn_subject, i); |
1598 | 1701 | X509_NAME_ENTRY_free(tmpne); |
1599 | 1702 | } |
1703 | ||
1704 | if (!X509_set_subject_name(ret, dn_subject)) { | |
1705 | X509_NAME_free(dn_subject); | |
1706 | goto end; | |
1707 | } | |
1708 | X509_NAME_free(dn_subject); | |
1709 | } | |
1710 | ||
1711 | row[DB_name] = X509_NAME_oneline(X509_get_subject_name(ret), NULL, 0); | |
1712 | if (row[DB_name] == NULL) { | |
1713 | BIO_printf(bio_err, "Memory allocation failure\n"); | |
1714 | goto end; | |
1600 | 1715 | } |
1601 | 1716 | |
1602 | 1717 | if (BN_is_zero(serial)) |
1631 | 1746 | |
1632 | 1747 | if (rrow != NULL) { |
1633 | 1748 | BIO_printf(bio_err, "The matching entry has the following details\n"); |
1634 | if (rrow[DB_type][0] == 'E') | |
1749 | if (rrow[DB_type][0] == DB_TYPE_EXP) | |
1635 | 1750 | p = "Expired"; |
1636 | else if (rrow[DB_type][0] == 'R') | |
1751 | else if (rrow[DB_type][0] == DB_TYPE_REV) | |
1637 | 1752 | p = "Revoked"; |
1638 | else if (rrow[DB_type][0] == 'V') | |
1753 | else if (rrow[DB_type][0] == DB_TYPE_VAL) | |
1639 | 1754 | p = "Valid"; |
1640 | 1755 | else |
1641 | 1756 | p = "\ninvalid type, Data base error\n"; |
1642 | 1757 | BIO_printf(bio_err, "Type :%s\n", p);; |
1643 | if (rrow[DB_type][0] == 'R') { | |
1758 | if (rrow[DB_type][0] == DB_TYPE_REV) { | |
1644 | 1759 | p = rrow[DB_exp_date]; |
1645 | 1760 | if (p == NULL) |
1646 | 1761 | p = "undef"; |
1666 | 1781 | goto end; |
1667 | 1782 | } |
1668 | 1783 | |
1669 | /* We are now totally happy, lets make and sign the certificate */ | |
1670 | if (verbose) | |
1671 | BIO_printf(bio_err, | |
1672 | "Everything appears to be ok, creating and signing the certificate\n"); | |
1673 | ||
1674 | if ((ret = X509_new()) == NULL) | |
1675 | goto end; | |
1676 | ||
1677 | #ifdef X509_V3 | |
1678 | /* Make it an X509 v3 certificate. */ | |
1679 | if (!X509_set_version(ret, 2)) | |
1680 | goto end; | |
1681 | #endif | |
1682 | ||
1683 | if (BN_to_ASN1_INTEGER(serial, X509_get_serialNumber(ret)) == NULL) | |
1684 | goto end; | |
1685 | if (selfsign) { | |
1686 | if (!X509_set_issuer_name(ret, subject)) | |
1687 | goto end; | |
1688 | } else { | |
1689 | if (!X509_set_issuer_name(ret, X509_get_subject_name(x509))) | |
1690 | goto end; | |
1691 | } | |
1692 | ||
1693 | if (!set_cert_times(ret, startdate, enddate, days)) | |
1694 | goto end; | |
1695 | ||
1696 | if (enddate != NULL) { | |
1697 | int tdays; | |
1698 | ||
1699 | if (!ASN1_TIME_diff(&tdays, NULL, NULL, X509_get0_notAfter(ret))) | |
1700 | goto end; | |
1701 | days = tdays; | |
1702 | } | |
1703 | ||
1704 | if (!X509_set_subject_name(ret, subject)) | |
1705 | goto end; | |
1706 | ||
1707 | pktmp = X509_REQ_get0_pubkey(req); | |
1708 | i = X509_set_pubkey(ret, pktmp); | |
1709 | if (!i) | |
1710 | goto end; | |
1711 | ||
1712 | /* Lets add the extensions, if there are any */ | |
1713 | if (ext_sect) { | |
1714 | X509V3_CTX ctx; | |
1715 | ||
1716 | /* Initialize the context structure */ | |
1717 | if (selfsign) | |
1718 | X509V3_set_ctx(&ctx, ret, ret, req, NULL, 0); | |
1719 | else | |
1720 | X509V3_set_ctx(&ctx, x509, ret, req, NULL, 0); | |
1721 | ||
1722 | if (extconf) { | |
1723 | if (verbose) | |
1724 | BIO_printf(bio_err, "Extra configuration file found\n"); | |
1725 | ||
1726 | /* Use the extconf configuration db LHASH */ | |
1727 | X509V3_set_nconf(&ctx, extconf); | |
1728 | ||
1729 | /* Test the structure (needed?) */ | |
1730 | /* X509V3_set_ctx_test(&ctx); */ | |
1731 | ||
1732 | /* Adds exts contained in the configuration file */ | |
1733 | if (!X509V3_EXT_add_nconf(extconf, &ctx, ext_sect, ret)) { | |
1734 | BIO_printf(bio_err, | |
1735 | "ERROR: adding extensions in section %s\n", | |
1736 | ext_sect); | |
1737 | ERR_print_errors(bio_err); | |
1738 | goto end; | |
1739 | } | |
1740 | if (verbose) | |
1741 | BIO_printf(bio_err, | |
1742 | "Successfully added extensions from file.\n"); | |
1743 | } else if (ext_sect) { | |
1744 | /* We found extensions to be set from config file */ | |
1745 | X509V3_set_nconf(&ctx, lconf); | |
1746 | ||
1747 | if (!X509V3_EXT_add_nconf(lconf, &ctx, ext_sect, ret)) { | |
1748 | BIO_printf(bio_err, | |
1749 | "ERROR: adding extensions in section %s\n", | |
1750 | ext_sect); | |
1751 | ERR_print_errors(bio_err); | |
1752 | goto end; | |
1753 | } | |
1754 | ||
1755 | if (verbose) | |
1756 | BIO_printf(bio_err, | |
1757 | "Successfully added extensions from config\n"); | |
1758 | } | |
1759 | } | |
1760 | ||
1761 | /* Copy extensions from request (if any) */ | |
1762 | ||
1763 | if (!copy_extensions(ret, req, ext_copy)) { | |
1764 | BIO_printf(bio_err, "ERROR: adding extensions from request\n"); | |
1765 | ERR_print_errors(bio_err); | |
1766 | goto end; | |
1767 | } | |
1768 | ||
1769 | { | |
1770 | const STACK_OF(X509_EXTENSION) *exts = X509_get0_extensions(ret); | |
1771 | ||
1772 | if (exts != NULL && sk_X509_EXTENSION_num(exts) > 0) | |
1773 | /* Make it an X509 v3 certificate. */ | |
1774 | if (!X509_set_version(ret, 2)) | |
1775 | goto end; | |
1776 | } | |
1777 | ||
1778 | /* Set the right value for the noemailDN option */ | |
1779 | if (email_dn == 0) { | |
1780 | if (!X509_set_subject_name(ret, dn_subject)) | |
1781 | goto end; | |
1782 | } | |
1783 | ||
1784 | 1784 | if (!default_op) { |
1785 | 1785 | BIO_printf(bio_err, "Certificate Details:\n"); |
1786 | 1786 | /* |
1830 | 1830 | row[DB_exp_date][tm->length] = '\0'; |
1831 | 1831 | row[DB_rev_date] = NULL; |
1832 | 1832 | row[DB_file] = OPENSSL_strdup("unknown"); |
1833 | row[DB_name] = X509_NAME_oneline(X509_get_subject_name(ret), NULL, 0); | |
1834 | ||
1835 | 1833 | if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) || |
1836 | 1834 | (row[DB_file] == NULL) || (row[DB_name] == NULL)) { |
1837 | 1835 | BIO_printf(bio_err, "Memory allocation failure\n"); |
1859 | 1857 | |
1860 | 1858 | X509_NAME_free(CAname); |
1861 | 1859 | X509_NAME_free(subject); |
1862 | if (dn_subject != subject) | |
1863 | X509_NAME_free(dn_subject); | |
1864 | 1860 | if (ok <= 0) |
1865 | 1861 | X509_free(ret); |
1866 | 1862 | else |