Revision 93f1121f
Added by Jim Pingle over 5 years ago
src/etc/inc/certs.inc | ||
---|---|---|
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); ?> |
Also available in: Unified diff
Add certificate lifetime to infoblock. Issue #7332
the info block
certificate will be expiring soon, or if it has already expired.