Project

General

Profile

« Previous | Next » 

Revision 93f1121f

Added by Jim Pingle over 5 years ago

Add certificate lifetime to infoblock. Issue #7332

  • Adds the total lifetime and lifetime remaining before expiration to
    the info block
  • Adds a visual indication to the infoblock and end date when the
    certificate will be expiring soon, or if it has already expired.

View differences:

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