You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@serf.apache.org by ko...@apache.org on 2023/05/18 09:30:01 UTC

svn commit: r1909901 - in /serf/branches/1.3.x: ./ STATUS test/test_context.c

Author: kotkov
Date: Thu May 18 09:30:01 2023
New Revision: 1909901

URL: http://svn.apache.org/viewvc?rev=1909901&view=rev
Log:
On the '1.3.x' branch: Merge r1901040 from trunk:

 * r1901040
   Fix test_ssl_handshake() failure with OpenSSL 1.1.1i+.
   Justification:
     Serf should test cleanly against upstreams.
   Branch: ^/serf/branches/1.3.x-r1901040
   Votes:
     +1: kotkov, ivan

Modified:
    serf/branches/1.3.x/   (props changed)
    serf/branches/1.3.x/STATUS
    serf/branches/1.3.x/test/test_context.c

Propchange: serf/branches/1.3.x/
------------------------------------------------------------------------------
  Merged /serf/branches/1.3.x-r1901040:r1909255-1909900
  Merged /serf/trunk:r1901040

Modified: serf/branches/1.3.x/STATUS
URL: http://svn.apache.org/viewvc/serf/branches/1.3.x/STATUS?rev=1909901&r1=1909900&r2=1909901&view=diff
==============================================================================
--- serf/branches/1.3.x/STATUS (original)
+++ serf/branches/1.3.x/STATUS Thu May 18 09:30:01 2023
@@ -35,14 +35,6 @@ Candidate changes:
            this point for the 1.3.x branch
          - Seems to only be required for LibreSSL, not OpenSSL)
 
- * r1901040
-   Fix test_ssl_handshake() failure with OpenSSL 1.1.1i+.
-   Justification:
-     Serf should test cleanly against upstreams.
-   Branch: ^/serf/branches/1.3.x-r1901040
-   Votes:
-     +1: kotkov, ivan
-
  * r1901937
    Remove the use of ERR_GET_FUNC() to allow building against OpenSSL 3.
    Justification:

Modified: serf/branches/1.3.x/test/test_context.c
URL: http://svn.apache.org/viewvc/serf/branches/1.3.x/test/test_context.c?rev=1909901&r1=1909900&r2=1909901&view=diff
==============================================================================
--- serf/branches/1.3.x/test/test_context.c (original)
+++ serf/branches/1.3.x/test/test_context.c Thu May 18 09:30:01 2023
@@ -25,6 +25,8 @@
 #include <apr_strings.h>
 #include <apr_version.h>
 
+#include <openssl/opensslv.h>
+
 #include "serf.h"
 #include "serf_private.h"
 
@@ -1126,34 +1128,90 @@ static apr_status_t validate_rootcacert(
     return APR_SUCCESS;
 }
 
-static apr_status_t
-ssl_server_cert_cb_expect_failures(void *baton, int failures,
-                                   const serf_ssl_certificate_t *cert)
+static const char *format_cert_failures(int failures, apr_pool_t *pool)
 {
-    test_baton_t *tb = baton;
-    int expected_failures = *(int *)tb->user_baton;
+    const char *str = "";
 
-    tb->result_flags |= TEST_RESULT_SERVERCERTCB_CALLED;
+    if (failures & SERF_SSL_CERT_NOTYETVALID) {
+        str = apr_pstrcat(pool, str, *str ? "|" : "", "CERT_NOTYETVALID", NULL);
+        failures &= ~SERF_SSL_CERT_NOTYETVALID;
+    }
 
-    /* We expect an error from the certificate validation function. */
-    if (failures & expected_failures)
-        return APR_SUCCESS;
+    if (failures & SERF_SSL_CERT_EXPIRED) {
+        str = apr_pstrcat(pool, str, *str ? "|" : "", "CERT_EXPIRED", NULL);
+        failures &= ~SERF_SSL_CERT_EXPIRED;
+    }
+
+    if (failures & SERF_SSL_CERT_UNKNOWNCA) {
+        str = apr_pstrcat(pool, str, *str ? "|" : "", "CERT_UNKNOWNCA", NULL);
+        failures &= ~SERF_SSL_CERT_UNKNOWNCA;
+    }
+
+    if (failures & SERF_SSL_CERT_SELF_SIGNED) {
+        str = apr_pstrcat(pool, str, *str ? "|" : "", "CERT_SELF_SIGNED", NULL);
+        failures &= ~SERF_SSL_CERT_SELF_SIGNED;
+    }
+
+    if (failures & SERF_SSL_CERT_UNKNOWN_FAILURE) {
+        str = apr_pstrcat(pool, str, *str ? "|" : "", "CERT_UNKNOWN_FAILURE", NULL);
+        failures &= ~SERF_SSL_CERT_UNKNOWN_FAILURE;
+    }
+
+    if (failures & SERF_SSL_CERT_REVOKED) {
+        str = apr_pstrcat(pool, str, *str ? "|" : "", "CERT_REVOKED", NULL);
+        failures &= ~SERF_SSL_CERT_REVOKED;
+    }
+
+    if (failures) {
+        serf__log(TEST_VERBOSE, __FILE__, "Unexpected or unknown cert failure\n");
+        abort();
+    }
+
+    if (*str)
+        return str;
     else
-        return SERF_ERROR_ISSUE_IN_TESTSUITE;
+        return "NONE";
 }
 
-static apr_status_t
-ssl_server_cert_cb_expect_allok(void *baton, int failures,
-                                const serf_ssl_certificate_t *cert)
+/* Logs failures in tb->user_baton, for later validation. */
+static apr_status_t ssl_server_cert_cb_log(void *baton, int failures,
+                                           const serf_ssl_certificate_t *cert)
 {
     test_baton_t *tb = baton;
+    const char *cert_str;
+
     tb->result_flags |= TEST_RESULT_SERVERCERTCB_CALLED;
 
-    /* No error expected, certificate is valid. */
-    if (failures)
-        return SERF_ERROR_ISSUE_IN_TESTSUITE;
-    else
-        return APR_SUCCESS;
+    if (cert) {
+        apr_hash_t *subject;
+        const char *common_name;
+        int depth;
+
+        subject = serf_ssl_cert_subject(cert, tb->pool);
+        if (!subject)
+            return SERF_ERROR_ISSUE_IN_TESTSUITE;
+
+        common_name = apr_hash_get(subject, "CN", APR_HASH_KEY_STRING);
+        depth = serf_ssl_cert_depth(cert);
+
+        cert_str = apr_psprintf(tb->pool, "(CN=%s, depth=%d)", common_name, depth);
+    } else {
+        cert_str = "(null)";
+    }
+
+    if (!tb->user_baton)
+        tb->user_baton = "";
+
+    tb->user_baton = apr_pstrcat(
+        tb->pool,
+        tb->user_baton,
+        "cert_cb: "
+        "failures = ", format_cert_failures(failures, tb->pool),
+        ", cert = ", cert_str,
+        "\n",
+        NULL);
+
+    return APR_SUCCESS;
 }
 
 static apr_status_t
@@ -1170,7 +1228,6 @@ static void test_ssl_handshake(CuTest *t
     test_baton_t *tb;
     handler_baton_t handler_ctx[1];
     const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]);
-    int expected_failures;
     apr_status_t status;
     test_server_message_t message_list[] = {
         {CHUNKED_REQUEST(1, "1")},
@@ -1193,20 +1250,34 @@ static void test_ssl_handshake(CuTest *t
                                      get_srcdir_file(test_pool, "test/server/serfserverkey.pem"),
                                      server_certs_srcdir(server_cert, test_pool),
                                      NULL, /* no client cert */
-                                     ssl_server_cert_cb_expect_failures,
+                                     ssl_server_cert_cb_log,
                                      test_pool);
     CuAssertIntEquals(tc, APR_SUCCESS, status);
 
-    /* This unknown failures is X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE, 
-       meaning the chain has only the server cert. A good candidate for its
-       own failure code. */
-    expected_failures = SERF_SSL_CERT_UNKNOWNCA;
-    tb->user_baton = &expected_failures;
-
     create_new_request(tb, &handler_ctx[0], "GET", "/", 1);
 
     test_helper_run_requests_expect_ok(tc, tb, num_requests, handler_ctx,
                                        test_pool);
+
+    /* OpenSSL 1.1.1i allows to continue verification for certificates with an
+       unknown CA. See https://github.com/openssl/openssl/issues/11297.
+
+       These unknown failures are X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY
+       and X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE. The second one means that
+       the chain has only the server cert. A good candidate for its own failure
+       code. */
+#if OPENSSL_VERSION_NUMBER >= 0x1010109fL /* >= 1.1.1i */
+    CuAssertStrEquals(tc,
+        "cert_cb: failures = CERT_UNKNOWNCA, cert = (CN=localhost, depth=0)\n"
+        "cert_cb: failures = CERT_UNKNOWNCA, cert = (CN=localhost, depth=0)\n"
+        "cert_cb: failures = NONE, cert = (CN=localhost, depth=0)\n",
+        tb->user_baton);
+#else
+    CuAssertStrEquals(tc,
+        "cert_cb: failures = CERT_UNKNOWNCA, cert = (CN=localhost, depth=0)\n"
+        "cert_cb: failures = CERT_UNKNOWNCA, cert = (CN=localhost, depth=0)\n",
+        tb->user_baton);
+#endif
 }
 
 /* Set up the ssl context with the CA and root CA certificates needed for
@@ -1265,7 +1336,7 @@ static void test_ssl_trust_rootca(CuTest
                                      get_srcdir_file(test_pool, "test/server/serfserverkey.pem"),
                                      server_certs_srcdir(server_certs, test_pool),
                                      NULL, /* no client cert */
-                                     ssl_server_cert_cb_expect_allok,
+                                     ssl_server_cert_cb_log,
                                      test_pool);
     CuAssertIntEquals(tc, APR_SUCCESS, status);
 
@@ -1273,6 +1344,9 @@ static void test_ssl_trust_rootca(CuTest
 
     test_helper_run_requests_expect_ok(tc, tb, num_requests, handler_ctx,
                                        test_pool);
+    CuAssertStrEquals(tc,
+        "cert_cb: failures = NONE, cert = (CN=localhost, depth=0)\n",
+        tb->user_baton);
 }
 
 /* Validate that when the application rejects the cert, the context loop
@@ -1365,7 +1439,7 @@ chain_rootca_callback_conn_setup(apr_soc
         return status;
 
     serf_ssl_server_cert_chain_callback_set(tb->ssl_context,
-                                            ssl_server_cert_cb_expect_allok,
+                                            ssl_server_cert_cb_log,
                                             cert_chain_cb,
                                             tb);
 
@@ -1399,7 +1473,7 @@ static void test_ssl_certificate_chain_w
                                      get_srcdir_file(test_pool, "test/server/serfserverkey.pem"),
                                      server_certs_srcdir(server_certs, test_pool),
                                      NULL, /* no client cert */
-                                     ssl_server_cert_cb_expect_allok,
+                                     ssl_server_cert_cb_log,
                                      test_pool);
     CuAssertIntEquals(tc, APR_SUCCESS, status);
 
@@ -1407,8 +1481,9 @@ static void test_ssl_certificate_chain_w
 
     test_helper_run_requests_expect_ok(tc, tb, num_requests,
                                        handler_ctx, test_pool);
-
-    CuAssertTrue(tc, tb->result_flags & TEST_RESULT_SERVERCERTCB_CALLED);
+    CuAssertStrEquals(tc,
+        "cert_cb: failures = NONE, cert = (CN=localhost, depth=0)\n",
+        tb->user_baton);
     CuAssertTrue(tc, tb->result_flags & TEST_RESULT_SERVERCERTCHAINCB_CALLED);
 }
 
@@ -1441,7 +1516,7 @@ chain_callback_conn_setup(apr_socket_t *
         return status;
 
     serf_ssl_server_cert_chain_callback_set(tb->ssl_context,
-                                            ssl_server_cert_cb_expect_allok,
+                                            ssl_server_cert_cb_log,
                                             cert_chain_all_certs_cb,
                                             tb);
 
@@ -1474,7 +1549,7 @@ static void test_ssl_certificate_chain_a
                                      get_srcdir_file(test_pool, "test/server/serfserverkey.pem"),
                                      server_certs_srcdir(all_server_certs, test_pool),
                                      NULL, /* no client cert */
-                                     ssl_server_cert_cb_expect_allok,
+                                     ssl_server_cert_cb_log,
                                      test_pool);
     CuAssertIntEquals(tc, APR_SUCCESS, status);
 
@@ -1483,7 +1558,10 @@ static void test_ssl_certificate_chain_a
     test_helper_run_requests_expect_ok(tc, tb, num_requests,
                                        handler_ctx, test_pool);
 
-    CuAssertTrue(tc, tb->result_flags & TEST_RESULT_SERVERCERTCB_CALLED);
+    CuAssertStrEquals(tc,
+        "cert_cb: failures = CERT_SELF_SIGNED, cert = (CN=Serf Root CA, depth=2)\n"
+        "cert_cb: failures = NONE, cert = (CN=localhost, depth=0)\n",
+        tb->user_baton);
     CuAssertTrue(tc, tb->result_flags & TEST_RESULT_SERVERCERTCHAINCB_CALLED);
 }
 
@@ -1738,7 +1816,6 @@ static void test_ssl_expired_server_cert
     test_baton_t *tb;
     handler_baton_t handler_ctx[1];
     const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]);
-    int expected_failures;
     apr_status_t status;
     test_server_message_t message_list[] = {
         {CHUNKED_REQUEST(1, "1")},
@@ -1763,18 +1840,19 @@ static void test_ssl_expired_server_cert
                                      get_srcdir_file(test_pool, "test/server/serfserverkey.pem"),
                                      server_certs_srcdir(expired_server_certs, test_pool),
                                      NULL, /* no client cert */
-                                     ssl_server_cert_cb_expect_failures,
+                                     ssl_server_cert_cb_log,
                                      test_pool);
     CuAssertIntEquals(tc, APR_SUCCESS, status);
 
-    expected_failures = SERF_SSL_CERT_SELF_SIGNED |
-                        SERF_SSL_CERT_EXPIRED;
-    tb->user_baton = &expected_failures;
-
     create_new_request(tb, &handler_ctx[0], "GET", "/", 1);
 
     test_helper_run_requests_expect_ok(tc, tb, num_requests, handler_ctx,
                                        test_pool);
+    CuAssertStrEquals(tc,
+        "cert_cb: failures = CERT_SELF_SIGNED, cert = (CN=Serf Root CA, depth=2)\n"
+        "cert_cb: failures = CERT_EXPIRED, cert = (CN=localhost, depth=0)\n"
+        "cert_cb: failures = CERT_EXPIRED, cert = (CN=localhost, depth=0)\n",
+        tb->user_baton);
 }
 
 /* Validate that the expired certificate is reported as failure in the
@@ -1784,7 +1862,6 @@ static void test_ssl_future_server_cert(
     test_baton_t *tb;
     handler_baton_t handler_ctx[1];
     const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]);
-    int expected_failures;
     apr_status_t status;
     test_server_message_t message_list[] = {
         {CHUNKED_REQUEST(1, "1")},
@@ -1809,18 +1886,19 @@ static void test_ssl_future_server_cert(
                                      get_srcdir_file(test_pool, "test/server/serfserverkey.pem"),
                                      server_certs_srcdir(future_server_certs, test_pool),
                                      NULL, /* no client cert */
-                                     ssl_server_cert_cb_expect_failures,
+                                     ssl_server_cert_cb_log,
                                      test_pool);
     CuAssertIntEquals(tc, APR_SUCCESS, status);
 
-    expected_failures = SERF_SSL_CERT_SELF_SIGNED |
-                        SERF_SSL_CERT_NOTYETVALID;
-    tb->user_baton = &expected_failures;
-
     create_new_request(tb, &handler_ctx[0], "GET", "/", 1);
 
     test_helper_run_requests_expect_ok(tc, tb, num_requests, handler_ctx,
                                        test_pool);
+    CuAssertStrEquals(tc,
+        "cert_cb: failures = CERT_SELF_SIGNED, cert = (CN=Serf Root CA, depth=2)\n"
+        "cert_cb: failures = CERT_NOTYETVALID, cert = (CN=localhost, depth=0)\n"
+        "cert_cb: failures = CERT_NOTYETVALID, cert = (CN=localhost, depth=0)\n",
+        tb->user_baton);
 }