225 lines
8.5 KiB
Diff
225 lines
8.5 KiB
Diff
|
Index: s390-tools-service/include/libpv/cert.h
|
||
|
===================================================================
|
||
|
--- s390-tools-service.orig/include/libpv/cert.h
|
||
|
+++ s390-tools-service/include/libpv/cert.h
|
||
|
@@ -16,7 +16,8 @@
|
||
|
|
||
|
#define PV_IBM_Z_SUBJECT_COMMON_NAME "International Business Machines Corporation"
|
||
|
#define PV_IBM_Z_SUBJECT_COUNTRY_NAME "US"
|
||
|
-#define PV_IBM_Z_SUBJECT_LOCALITY_NAME "Poughkeepsie"
|
||
|
+#define PV_IBM_Z_SUBJECT_LOCALITY_NAME_POUGHKEEPSIE "Poughkeepsie"
|
||
|
+#define PV_IBM_Z_SUBJECT_LOCALITY_NAME_ARMONK "Armonk"
|
||
|
#define PV_IBM_Z_SUBJECT_ORGANIZATIONAL_UNIT_NAME_SUFFIX "Key Signing Service"
|
||
|
#define PV_IBM_Z_SUBJECT_ORGANIZATION_NAME "International Business Machines Corporation"
|
||
|
#define PV_IBM_Z_SUBJECT_STATE "New York"
|
||
|
Index: s390-tools-service/libpv/cert.c
|
||
|
===================================================================
|
||
|
--- s390-tools-service.orig/libpv/cert.c
|
||
|
+++ s390-tools-service/libpv/cert.c
|
||
|
@@ -857,7 +857,7 @@ static gboolean x509_name_data_by_nid_eq
|
||
|
|
||
|
/* Checks whether the subject of @cert is a IBM signing key subject. For this we
|
||
|
* must check that the subject is equal to: 'C = US, ST = New York, L =
|
||
|
- * Poughkeepsie, O = International Business Machines Corporation, CN =
|
||
|
+ * Poughkeepsie or Armonk, O = International Business Machines Corporation, CN =
|
||
|
* International Business Machines Corporation' and the organization unit (OUT)
|
||
|
* must end with the suffix ' Key Signing Service'.
|
||
|
*/
|
||
|
@@ -879,7 +879,10 @@ static gboolean has_ibm_signing_subject(
|
||
|
if (!x509_name_data_by_nid_equal(subject, NID_stateOrProvinceName, PV_IBM_Z_SUBJECT_STATE))
|
||
|
return FALSE;
|
||
|
|
||
|
- if (!x509_name_data_by_nid_equal(subject, NID_localityName, PV_IBM_Z_SUBJECT_LOCALITY_NAME))
|
||
|
+ if (!(x509_name_data_by_nid_equal(subject, NID_localityName,
|
||
|
+ PV_IBM_Z_SUBJECT_LOCALITY_NAME_POUGHKEEPSIE) ||
|
||
|
+ x509_name_data_by_nid_equal(subject, NID_localityName,
|
||
|
+ PV_IBM_Z_SUBJECT_LOCALITY_NAME_ARMONK)))
|
||
|
return FALSE;
|
||
|
|
||
|
if (!x509_name_data_by_nid_equal(subject, NID_organizationName,
|
||
|
@@ -1085,10 +1088,9 @@ static int check_signature_algo_match(co
|
||
|
|
||
|
/* It's almost the same as X509_check_issed from OpenSSL does except that we
|
||
|
* don't check the key usage of the potential issuer. This means we check:
|
||
|
- * 1. issuer_name(cert) == subject_name(issuer)
|
||
|
- * 2. Check whether the akid(cert) (if available) matches the issuer skid
|
||
|
- * 3. Check that the cert algrithm matches the subject algorithm
|
||
|
- * 4. Verify the signature of certificate @cert is using the public key of
|
||
|
+ * 1. Check whether the akid(cert) (if available) matches the issuer skid
|
||
|
+ * 2. Check that the cert algrithm matches the subject algorithm
|
||
|
+ * 3. Verify the signature of certificate @cert is using the public key of
|
||
|
* @issuer.
|
||
|
*/
|
||
|
static int check_host_key_issued(X509 *cert, X509 *issuer, GError **error)
|
||
|
@@ -1097,19 +1099,6 @@ static int check_host_key_issued(X509 *c
|
||
|
const X509_NAME *cert_issuer = X509_get_issuer_name(cert);
|
||
|
g_autoptr(AUTHORITY_KEYID) akid = NULL;
|
||
|
|
||
|
- /* We cannot use X509_NAME_cmp() because it considers the order of the
|
||
|
- * X509_NAME_Entries.
|
||
|
- */
|
||
|
- if (!own_X509_NAME_equal(issuer_subject, cert_issuer)) {
|
||
|
- g_autofree char *issuer_subject_str = pv_X509_NAME_oneline(issuer_subject);
|
||
|
- g_autofree char *cert_issuer_str = pv_X509_NAME_oneline(cert_issuer);
|
||
|
-
|
||
|
- g_set_error(error, PV_CERT_ERROR, PV_CERT_ERROR_CERT_SUBJECT_ISSUER_MISMATCH,
|
||
|
- _("Subject issuer mismatch:\n'%s'\n'%s'"), issuer_subject_str,
|
||
|
- cert_issuer_str);
|
||
|
- return -1;
|
||
|
- }
|
||
|
-
|
||
|
akid = X509_get_ext_d2i(cert, NID_authority_key_identifier, NULL, NULL);
|
||
|
if (akid && X509_check_akid(issuer, akid) != X509_V_OK) {
|
||
|
g_set_error(error, PV_CERT_ERROR, PV_CERT_ERROR_SKID_AKID_MISMATCH,
|
||
|
@@ -1286,21 +1275,10 @@ int pv_verify_cert(X509_STORE_CTX *ctx,
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
-/* Verify that: subject(issuer) == issuer(crl) and SKID(issuer) == AKID(crl) */
|
||
|
+/* Verify that SKID(issuer) == AKID(crl) */
|
||
|
static int check_crl_issuer(X509_CRL *crl, X509 *issuer, GError **error)
|
||
|
{
|
||
|
- const X509_NAME *crl_issuer = X509_CRL_get_issuer(crl);
|
||
|
- const X509_NAME *issuer_subject = X509_get_subject_name(issuer);
|
||
|
- AUTHORITY_KEYID *akid = NULL;
|
||
|
-
|
||
|
- if (!own_X509_NAME_equal(issuer_subject, crl_issuer)) {
|
||
|
- g_autofree char *issuer_subject_str = pv_X509_NAME_oneline(issuer_subject);
|
||
|
- g_autofree char *crl_issuer_str = pv_X509_NAME_oneline(crl_issuer);
|
||
|
-
|
||
|
- g_set_error(error, PV_CERT_ERROR, PV_CERT_ERROR_CRL_SUBJECT_ISSUER_MISMATCH,
|
||
|
- _("issuer mismatch:\n%s\n%s"), issuer_subject_str, crl_issuer_str);
|
||
|
- return -1;
|
||
|
- }
|
||
|
+ g_autoptr(AUTHORITY_KEYID) akid = NULL;
|
||
|
|
||
|
/* If AKID(@crl) is specified it must match with SKID(@issuer) */
|
||
|
akid = X509_CRL_get_ext_d2i(crl, NID_authority_key_identifier, NULL, NULL);
|
||
|
@@ -1325,7 +1303,6 @@ int pv_verify_crl(X509_CRL *crl, X509 *c
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
- /* check that the @crl issuer matches with the subject name of @cert*/
|
||
|
if (check_crl_issuer(crl, cert, error) < 0)
|
||
|
return -1;
|
||
|
|
||
|
@@ -1393,6 +1370,93 @@ int pv_check_chain_parameters(const STAC
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
+/** Replace locality 'Armonk' with 'Pougkeepsie'. If Armonk was not set return
|
||
|
+ * `NULL`.
|
||
|
+ */
|
||
|
+static X509_NAME *x509_armonk_locality_fixup(const X509_NAME *name)
|
||
|
+{
|
||
|
+ g_autoptr(X509_NAME) ret = NULL;
|
||
|
+ int pos;
|
||
|
+
|
||
|
+ /* Check if ``L=Armonk`` */
|
||
|
+ if (!x509_name_data_by_nid_equal((X509_NAME *)name, NID_localityName,
|
||
|
+ PV_IBM_Z_SUBJECT_LOCALITY_NAME_ARMONK))
|
||
|
+ return NULL;
|
||
|
+
|
||
|
+ ret = X509_NAME_dup(name);
|
||
|
+ if (!ret)
|
||
|
+ g_abort();
|
||
|
+
|
||
|
+ pos = X509_NAME_get_index_by_NID(ret, NID_localityName, -1);
|
||
|
+ if (pos == -1)
|
||
|
+ return NULL;
|
||
|
+
|
||
|
+ X509_NAME_ENTRY_free(X509_NAME_delete_entry(ret, pos));
|
||
|
+
|
||
|
+ /* Create a new name entry at the same position as before */
|
||
|
+ if (X509_NAME_add_entry_by_NID(
|
||
|
+ ret, NID_localityName, MBSTRING_UTF8,
|
||
|
+ (const unsigned char *)&PV_IBM_Z_SUBJECT_LOCALITY_NAME_POUGHKEEPSIE,
|
||
|
+ sizeof(PV_IBM_Z_SUBJECT_LOCALITY_NAME_POUGHKEEPSIE) - 1, pos, 0) != 1)
|
||
|
+ return NULL;
|
||
|
+
|
||
|
+ return g_steal_pointer(&ret);
|
||
|
+}
|
||
|
+
|
||
|
+/* This function contains work-arounds for some known subject(CRT)<->issuer(CRL)
|
||
|
+ * issues.
|
||
|
+ */
|
||
|
+static STACK_OF_X509_CRL *quirk_X509_STORE_ctx_get1_crls(X509_STORE_CTX *ctx,
|
||
|
+ const X509_NAME *subject, GError **err)
|
||
|
+{
|
||
|
+ g_autoptr(X509_NAME) fixed_subject = NULL;
|
||
|
+ g_autoptr(STACK_OF_X509_CRL) ret = NULL;
|
||
|
+
|
||
|
+ ret = pv_X509_STORE_CTX_get1_crls(ctx, subject);
|
||
|
+ if (ret && sk_X509_CRL_num(ret) > 0)
|
||
|
+ return g_steal_pointer(&ret);
|
||
|
+
|
||
|
+ /* Workaround to fix the mismatch between issuer name of the * IBM
|
||
|
+ * signing CRLs and the IBM signing key subject name. Locality name has
|
||
|
+ * changed from Poughkeepsie to Armonk.
|
||
|
+ */
|
||
|
+ fixed_subject = x509_armonk_locality_fixup(subject);
|
||
|
+ /* Was the locality replaced? */
|
||
|
+ if (fixed_subject) {
|
||
|
+ X509_NAME *tmp;
|
||
|
+
|
||
|
+ sk_X509_CRL_free(ret);
|
||
|
+ ret = pv_X509_STORE_CTX_get1_crls(ctx, fixed_subject);
|
||
|
+ if (ret && sk_X509_CRL_num(ret) > 0)
|
||
|
+ return g_steal_pointer(&ret);
|
||
|
+
|
||
|
+ /* Workaround to fix the ordering mismatch between issuer name
|
||
|
+ * of the IBM signing CRLs and the IBM signing key subject name.
|
||
|
+ */
|
||
|
+ tmp = fixed_subject;
|
||
|
+ fixed_subject = pv_c2b_name(fixed_subject);
|
||
|
+ X509_NAME_free(tmp);
|
||
|
+ sk_X509_CRL_free(ret);
|
||
|
+ ret = pv_X509_STORE_CTX_get1_crls(ctx, fixed_subject);
|
||
|
+ if (ret && sk_X509_CRL_num(ret) > 0)
|
||
|
+ return g_steal_pointer(&ret);
|
||
|
+ X509_NAME_free(fixed_subject);
|
||
|
+ fixed_subject = NULL;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Workaround to fix the ordering mismatch between issuer name of the
|
||
|
+ * IBM signing CRLs and the IBM signing key subject name.
|
||
|
+ */
|
||
|
+ fixed_subject = pv_c2b_name(subject);
|
||
|
+ sk_X509_CRL_free(ret);
|
||
|
+ ret = pv_X509_STORE_CTX_get1_crls(ctx, fixed_subject);
|
||
|
+ if (ret && sk_X509_CRL_num(ret) > 0)
|
||
|
+ return g_steal_pointer(&ret);
|
||
|
+
|
||
|
+ g_set_error(err, PV_CERT_ERROR, PV_CERT_ERROR_NO_CRL, _("no CRL found"));
|
||
|
+ return NULL;
|
||
|
+}
|
||
|
+
|
||
|
/* Given a certificate @cert try to find valid revocation lists in @ctx. If no
|
||
|
* valid CRL was found NULL is returned.
|
||
|
*/
|
||
|
@@ -1412,21 +1476,9 @@ STACK_OF_X509_CRL *pv_store_ctx_find_val
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
- ret = pv_X509_STORE_CTX_get1_crls(ctx, subject);
|
||
|
- if (!ret) {
|
||
|
- /* Workaround to fix the mismatch between issuer name of the
|
||
|
- * IBM Z signing CRLs and the IBM Z signing key subject name.
|
||
|
- */
|
||
|
- g_autoptr(X509_NAME) broken_subject = pv_c2b_name(subject);
|
||
|
-
|
||
|
- ret = pv_X509_STORE_CTX_get1_crls(ctx, broken_subject);
|
||
|
- if (!ret) {
|
||
|
- g_set_error(error, PV_CERT_ERROR, PV_CERT_ERROR_NO_CRL, _("no CRL found"));
|
||
|
- g_info("ERROR: %s", (*error)->message);
|
||
|
- return NULL;
|
||
|
- }
|
||
|
- }
|
||
|
-
|
||
|
+ ret = quirk_X509_STORE_ctx_get1_crls(ctx, subject, error);
|
||
|
+ if (!ret)
|
||
|
+ return NULL;
|
||
|
/* Filter out non-valid CRLs for @cert */
|
||
|
for (int i = 0; i < sk_X509_CRL_num(ret); i++) {
|
||
|
X509_CRL *crl = sk_X509_CRL_value(ret, i);
|