1669 |
1669 |
return true;
|
1670 |
1670 |
}
|
1671 |
1671 |
|
1672 |
|
function cert_get_expiration_days($cert) {
|
|
1672 |
/****f* certs/cert_get_lifetime
|
|
1673 |
* NAME
|
|
1674 |
* cert_get_lifetime - Returns the number of days the certificate is valid
|
|
1675 |
* INPUTS
|
|
1676 |
* $untilexpire: Boolean
|
|
1677 |
* true: The number of days returned is from now until the certificate expiration.
|
|
1678 |
* false (default): The number of days returned is the total lifetime of the certificate.
|
|
1679 |
* RESULT
|
|
1680 |
* Integer number of days in the certificate total or remaining lifetime
|
|
1681 |
******/
|
|
1682 |
|
|
1683 |
function cert_get_lifetime($cert, $untilexpire = false) {
|
|
1684 |
/* If the certificate is not valid, bail. */
|
1673 |
1685 |
if (!is_array($cert) || empty($cert['crt'])) {
|
1674 |
1686 |
return null;
|
1675 |
1687 |
}
|
|
1688 |
/* Read certificate details */
|
1676 |
1689 |
$cert_details = openssl_x509_parse(base64_decode($cert['crt']));
|
1677 |
|
return (int) round(($cert_details['validTo_time_t'] - time()) / 86400);
|
|
1690 |
/* Determine which start time to use (now, or cert start) */
|
|
1691 |
$fromtime = ($untilexpire) ? time() : $cert_details['validFrom_time_t'];
|
|
1692 |
/* Calculate and return the requested duration, converting from seconds to days. */
|
|
1693 |
return (int) round(($cert_details['validTo_time_t'] - $fromtime) / 86400);
|
|
1694 |
}
|
|
1695 |
|
|
1696 |
/****f* certs/cert_analyze_lifetime
|
|
1697 |
* NAME
|
|
1698 |
* cert_analyze_lifetime - Analyze a certificate lifetime for expiration notices
|
|
1699 |
* INPUTS
|
|
1700 |
* $expiredays: Number of days until the certificate expires (See cert_get_lifetime())
|
|
1701 |
* RESULT
|
|
1702 |
* An array of two entries:
|
|
1703 |
* 0/$lrclass: A bootstrap name for use with classes like text-<x>
|
|
1704 |
* 1/$expstring: A text analysis describing the expiration timeframe.
|
|
1705 |
******/
|
|
1706 |
|
|
1707 |
function cert_analyze_lifetime($expiredays) {
|
|
1708 |
/* Number of days at which to warn of expiration.
|
|
1709 |
* Might move to to global or a user setting. */
|
|
1710 |
$warning_days = 30;
|
|
1711 |
|
|
1712 |
if ($expiredays > $warning_days) {
|
|
1713 |
/* Not expiring soon */
|
|
1714 |
$lrclass = 'normal';
|
|
1715 |
$expstring = gettext("%d %s until expiration");
|
|
1716 |
} elseif ($expiredays > 0) {
|
|
1717 |
/* Still valid but expiring soon */
|
|
1718 |
$lrclass = 'warning';
|
|
1719 |
$expstring = gettext("Expiring soon, in %d %s");
|
|
1720 |
} else {
|
|
1721 |
/* Certificate has expired */
|
|
1722 |
$lrclass = 'danger';
|
|
1723 |
$expstring = gettext("Expired %d %s ago");
|
|
1724 |
}
|
|
1725 |
$days = (abs($expiredays) == 1) ? gettext('day') : gettext('days');
|
|
1726 |
$expstring = sprintf($expstring, abs($expiredays), $days);
|
|
1727 |
return array($lrclass, $expstring);
|
|
1728 |
}
|
|
1729 |
|
|
1730 |
/****f* certs/cert_print_dates
|
|
1731 |
* NAME
|
|
1732 |
* cert_print_dates - Print the start and end timestamps for the given certificate
|
|
1733 |
* INPUTS
|
|
1734 |
* $cert: CA or Cert entry for which the dates will be printed
|
|
1735 |
* RESULT
|
|
1736 |
* Returns null if the passed entry is invalid
|
|
1737 |
* Otherwise, outputs the dates to the user with formatting.
|
|
1738 |
******/
|
|
1739 |
|
|
1740 |
function cert_print_dates($cert) {
|
|
1741 |
/* If the certificate is not valid, bail. */
|
|
1742 |
if (!is_array($cert) || empty($cert['crt'])) {
|
|
1743 |
return null;
|
|
1744 |
}
|
|
1745 |
/* Attempt to extract the dates from the certificate */
|
|
1746 |
list($startdate, $enddate) = cert_get_dates($cert['crt']);
|
|
1747 |
/* If either of the timestamps are empty, then do not print anything.
|
|
1748 |
* The entry may not be valid or it may just be missing date information */
|
|
1749 |
if (empty($startdate) || empty($enddate)) {
|
|
1750 |
return null;
|
|
1751 |
}
|
|
1752 |
/* Get the expiration days */
|
|
1753 |
$expiredays = cert_get_lifetime($cert, true);
|
|
1754 |
/* Analyze the lifetime value */
|
|
1755 |
list($lrclass, $expstring) = cert_analyze_lifetime($expiredays);
|
|
1756 |
/* Output the dates, with a tooltip showing days until expiration, and
|
|
1757 |
* a visual indication of warning/expired status. */
|
|
1758 |
?>
|
|
1759 |
<br />
|
|
1760 |
<small>
|
|
1761 |
<?=gettext("Valid From")?>: <b><?=$startdate ?></b><br />
|
|
1762 |
<?=gettext("Valid Until")?>:
|
|
1763 |
<span class="text-<?=$lrclass?>" data-toggle="tooltip" data-placement="bottom" title="<?= $expstring ?>">
|
|
1764 |
<b><?=$enddate ?></b>
|
|
1765 |
</span>
|
|
1766 |
</small>
|
|
1767 |
<?php
|
1678 |
1768 |
}
|
1679 |
1769 |
|
|
1770 |
/****f* certs/cert_print_infoblock
|
|
1771 |
* NAME
|
|
1772 |
* cert_print_infoblock - Print an information block containing certificate details
|
|
1773 |
* INPUTS
|
|
1774 |
* $cert: CA or Cert entry for which the information will be printed
|
|
1775 |
* RESULT
|
|
1776 |
* Returns null if the passed entry is invalid
|
|
1777 |
* Otherwise, outputs information to the user with formatting.
|
|
1778 |
******/
|
|
1779 |
|
1680 |
1780 |
function cert_print_infoblock($cert) {
|
|
1781 |
/* If the certificate is not valid, bail. */
|
1681 |
1782 |
if (!is_array($cert) || empty($cert['crt'])) {
|
1682 |
1783 |
return null;
|
1683 |
1784 |
}
|
|
1785 |
/* Variable to hold the formatted information */
|
1684 |
1786 |
$certextinfo = "";
|
|
1787 |
|
|
1788 |
/* Serial number */
|
1685 |
1789 |
$cert_details = openssl_x509_parse(base64_decode($cert['crt']));
|
1686 |
1790 |
if (isset($cert_details['serialNumber']) && (strlen($cert_details['serialNumber']) > 0)) {
|
1687 |
1791 |
$certextinfo .= '<b>' . gettext("Serial: ") . '</b> ';
|
1688 |
1792 |
$certextinfo .= htmlspecialchars(cert_escape_x509_chars($cert_details['serialNumber'], true));
|
1689 |
1793 |
$certextinfo .= '<br/>';
|
1690 |
1794 |
}
|
|
1795 |
|
|
1796 |
/* Digest type */
|
1691 |
1797 |
$certsig = cert_get_sigtype($cert['crt']);
|
1692 |
1798 |
if (is_array($certsig) && !empty($certsig) && !empty($certsig['shortname'])) {
|
1693 |
1799 |
$certextinfo .= '<b>' . gettext("Signature Digest: ") . '</b> ';
|
1694 |
1800 |
$certextinfo .= htmlspecialchars(cert_escape_x509_chars($certsig['shortname'], true));
|
1695 |
1801 |
$certextinfo .= '<br/>';
|
1696 |
1802 |
}
|
|
1803 |
|
|
1804 |
/* Subject Alternative Name (SAN) list */
|
1697 |
1805 |
$sans = cert_get_sans($cert['crt']);
|
1698 |
1806 |
if (is_array($sans) && !empty($sans)) {
|
1699 |
1807 |
$certextinfo .= '<b>' . gettext("SAN: ") . '</b> ';
|
1700 |
1808 |
$certextinfo .= htmlspecialchars(implode(', ', cert_escape_x509_chars($sans, true)));
|
1701 |
1809 |
$certextinfo .= '<br/>';
|
1702 |
1810 |
}
|
|
1811 |
|
|
1812 |
/* Key usage */
|
1703 |
1813 |
$purpose = cert_get_purpose($cert['crt']);
|
1704 |
1814 |
if (is_array($purpose) && !empty($purpose['ku'])) {
|
1705 |
1815 |
$certextinfo .= '<b>' . gettext("KU: ") . '</b> ';
|
1706 |
1816 |
$certextinfo .= htmlspecialchars(implode(', ', $purpose['ku']));
|
1707 |
1817 |
$certextinfo .= '<br/>';
|
1708 |
1818 |
}
|
|
1819 |
|
|
1820 |
/* Extended key usage */
|
1709 |
1821 |
if (is_array($purpose) && !empty($purpose['eku'])) {
|
1710 |
1822 |
$certextinfo .= '<b>' . gettext("EKU: ") . '</b> ';
|
1711 |
1823 |
$certextinfo .= htmlspecialchars(implode(', ', $purpose['eku']));
|
1712 |
1824 |
$certextinfo .= '<br/>';
|
1713 |
1825 |
}
|
|
1826 |
|
|
1827 |
/* OCSP / Must Staple */
|
1714 |
1828 |
if (cert_get_ocspstaple($cert['crt'])) {
|
1715 |
1829 |
$certextinfo .= '<b>' . gettext("OCSP: ") . '</b> ';
|
1716 |
1830 |
$certextinfo .= gettext("Must Staple");
|
1717 |
1831 |
}
|
|
1832 |
|
|
1833 |
/* Private key information */
|
1718 |
1834 |
if (!empty($cert['prv'])) {
|
1719 |
1835 |
$res_key = openssl_pkey_get_private(base64_decode($cert['prv']));
|
1720 |
1836 |
$key_details = openssl_pkey_get_details($res_key);
|
|
1837 |
|
|
1838 |
/* Key type (RSA or EC) */
|
1721 |
1839 |
$certextinfo .= '<b>' . gettext("Key Type: ") . '</b> ';
|
1722 |
1840 |
if ($key_details['type'] == OPENSSL_KEYTYPE_RSA) {
|
|
1841 |
/* RSA Key size */
|
1723 |
1842 |
$certextinfo .= 'RSA<br/>';
|
1724 |
1843 |
$certextinfo .= '<b>' . gettext("Key Size: ") . '</b> ';
|
1725 |
1844 |
$certextinfo .= $key_details['bits'] . '<br/>';
|
1726 |
1845 |
} else {
|
|
1846 |
/* Elliptic curve (EC) key curve name */
|
1727 |
1847 |
$certextinfo .= 'ECDSA<br/>';
|
1728 |
1848 |
$certextinfo .= '<b>' . gettext("Elliptic curve name: ") . '</b>';
|
1729 |
1849 |
$certextinfo .= $key_details['ec']['curve_name'] . '<br/>';
|
1730 |
1850 |
}
|
1731 |
1851 |
}
|
|
1852 |
|
|
1853 |
/* Distinguished name (DN) */
|
1732 |
1854 |
if (!empty($cert_details['name'])) {
|
1733 |
1855 |
$certextinfo .= '<b>' . gettext("DN: ") . '</b> ';
|
1734 |
1856 |
$certextinfo .= htmlspecialchars(cert_escape_x509_chars($cert_details['name'], true));
|
1735 |
1857 |
$certextinfo .= '<br/>';
|
1736 |
1858 |
}
|
|
1859 |
|
|
1860 |
/* Hash value */
|
1737 |
1861 |
if (!empty($cert_details['hash'])) {
|
1738 |
1862 |
$certextinfo .= '<b>' . gettext("Hash: ") . '</b> ';
|
1739 |
1863 |
$certextinfo .= htmlspecialchars(cert_escape_x509_chars($cert_details['hash'], true));
|
1740 |
1864 |
$certextinfo .= '<br/>';
|
1741 |
1865 |
}
|
|
1866 |
|
|
1867 |
/* Subject Key Identifier (SKID) */
|
1742 |
1868 |
if (is_array($cert_details["extensions"]) && !empty($cert_details["extensions"]["subjectKeyIdentifier"])) {
|
1743 |
1869 |
$certextinfo .= '<b>' . gettext("Subject Key ID: ") . '</b> ';
|
1744 |
1870 |
$certextinfo .= htmlspecialchars(cert_escape_x509_chars($cert_details["extensions"]["subjectKeyIdentifier"], true));
|
1745 |
1871 |
$certextinfo .= '<br/>';
|
1746 |
1872 |
}
|
|
1873 |
|
|
1874 |
/* Authority Key Identifier (AKID) */
|
1747 |
1875 |
if (is_array($cert_details["extensions"]) && !empty($cert_details["extensions"]["authorityKeyIdentifier"])) {
|
1748 |
1876 |
$certextinfo .= '<b>' . gettext("Authority Key ID: ") . '</b> ';
|
1749 |
1877 |
$certextinfo .= str_replace("\n", '<br/>', htmlspecialchars(cert_escape_x509_chars($cert_details["extensions"]["authorityKeyIdentifier"], true)));
|
1750 |
1878 |
$certextinfo .= '<br/>';
|
1751 |
1879 |
}
|
1752 |
|
$expiredays = cert_get_expiration_days($cert);
|
1753 |
|
$certextinfo .= '<b>' . gettext("Lifetime: ") . '</b> ';
|
1754 |
|
$certextinfo .= sprintf(gettext(($expiredays > 0) ? "%d days until expiration" : "Expired %d days ago"), abs($expiredays));
|
|
1880 |
|
|
1881 |
/* Total Lifetime (days from cert start to end) */
|
|
1882 |
$lifetime = cert_get_lifetime($cert);
|
|
1883 |
$certextinfo .= '<b>' . gettext("Total Lifetime: ") . '</b> ';
|
|
1884 |
$certextinfo .= sprintf("%d %s", $lifetime, (abs($lifetime) == 1) ? gettext('day') : gettext('days'));
|
1755 |
1885 |
$certextinfo .= '<br/>';
|
|
1886 |
|
|
1887 |
/* Lifetime before certificate expires (days from now to end) */
|
|
1888 |
$expiredays = cert_get_lifetime($cert, true);
|
|
1889 |
list($lrclass, $expstring) = cert_analyze_lifetime($expiredays);
|
|
1890 |
$certextinfo .= '<b>' . gettext("Lifetime Remaining: ") . '</b> ';
|
|
1891 |
$certextinfo .= "<span class=\"text-{$lrclass}\">{$expstring}</span>";
|
|
1892 |
$certextinfo .= '<br/>';
|
|
1893 |
|
|
1894 |
/* Output the infoblock */
|
1756 |
1895 |
if (!empty($certextinfo)) { ?>
|
1757 |
1896 |
<div class="infoblock">
|
1758 |
1897 |
<? print_info_box($certextinfo, 'info', false); ?>
|
Add certificate lifetime to infoblock. Issue #7332
the info block
certificate will be expiring soon, or if it has already expired.