Allow for expired certificate

The code throws for an expired certificate, which results in the below
behavior:

1. If BMC starts when the time is invalid (e.g. the date is in 1970),
bmcweb will create a default certificate with hostname `testhost`;

2. In later reboots when BMC get a valid time, the bmcweb loads the
certificate as before. But phosphor-certificate-manager will throw on
this certificate. Then there is no DBus object created for this
certificate (`/xyz/openbmc_project/certs/server/https/1`)

3. Due to the missing DBus object:
 * We will not be able to replace the certificate, e.g. by below
 Redfish URI:
```
 /redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate
```
 * When the BMC gets the hostname, bmcweb will generate a new
 self-signed certificate with the hostname and replace it, the
 replacement fails as well.

This commit adds a config option that allows the expired certificate to
be created on DBus and fixes the above issues and it is enabled by
default.

Signed-off-by: Lei YU <yulei.sh@bytedance.com>
Change-Id: Ib02bd686c9bfeb6401b269af20856824647f54c5
diff --git a/config.h.in b/config.h.in
index b363fd3..3d48991 100644
--- a/config.h.in
+++ b/config.h.in
@@ -21,3 +21,6 @@
 
 /* The default name of the authorities list file. */
 inline constexpr char defaultAuthoritiesListFileName[] = "@authorities_list_name@";
+
+/* Whether to allow expired certificates. */
+inline constexpr bool allowExpired = @allow_expired@;
diff --git a/meson.build b/meson.build
index 8ab2f77..68f4503 100644
--- a/meson.build
+++ b/meson.build
@@ -42,6 +42,12 @@
      get_option('authorities-list-name')
 )
 
+if not get_option('allow-expired').disabled()
+  config_data.set('allow_expired', 'true')
+else
+  config_data.set('allow_expired', 'false')
+endif
+
 configure_file(
     input: 'config.h.in',
     output: 'config.h',
diff --git a/meson_options.txt b/meson_options.txt
index 18190e3..d29c2f9 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -26,3 +26,9 @@
     value: 'trust_bundle',
     description: 'File name of the authorities list',
 )
+
+option('allow-expired',
+    type: 'feature',
+    value: 'enabled',
+    description: 'Allow expired certificates',
+)
diff --git a/x509_utils.cpp b/x509_utils.cpp
index 4c8cc3a..6173830 100644
--- a/x509_utils.cpp
+++ b/x509_utils.cpp
@@ -1,3 +1,5 @@
+#include "config.h"
+
 #include "x509_utils.hpp"
 
 #include <openssl/asn1.h>
@@ -184,9 +186,14 @@
 
     // Allow certificate upload, for "certificate is not yet valid" and
     // trust chain related errors.
-    if (!((errCode == X509_V_OK) ||
-          (errCode == X509_V_ERR_CERT_NOT_YET_VALID) ||
-          isTrustChainError(errCode)))
+    // If ALLOW_EXPIRED is defined, allow expired certificate so that it
+    // could be replaced
+    bool isOK = (errCode == X509_V_OK) ||
+                (errCode == X509_V_ERR_CERT_NOT_YET_VALID) ||
+                isTrustChainError(errCode) ||
+                (allowExpired && errCode == X509_V_ERR_CERT_HAS_EXPIRED);
+
+    if (!isOK)
     {
         if (errCode == X509_V_ERR_CERT_HAS_EXPIRED)
         {