Remove proxy tests. Add verify callback tests.
authorEmilia Kasper <emilia@openssl.org>
Thu, 7 Apr 2016 17:07:50 +0000 (19:07 +0200)
committerEmilia Kasper <emilia@openssl.org>
Thu, 12 May 2016 17:02:42 +0000 (19:02 +0200)
The old proxy tests test the implementation of an application proxy
policy callback defined in the test itself, which is not particularly
useful.

It is, however, useful to test cert verify overrides in
general. Therefore, replace these tests with tests for cert verify
callback behaviour.

Also glob the ssl test inputs on the .in files to catch missing
generated files.

Reviewed-by: Rich Salz <rsalz@openssl.org>
13 files changed:
test/README.ssltest.md
test/handshake_helper.c
test/handshake_helper.h
test/recipes/80-test_ssl_new.t
test/recipes/80-test_ssl_old.t
test/ssl-tests/03-custom_verify.conf [new file with mode: 0644]
test/ssl-tests/03-custom_verify.conf.in [new file with mode: 0644]
test/ssl_test.c
test/ssl_test_ctx.c
test/ssl_test_ctx.h
test/ssl_test_ctx_test.c
test/ssl_test_ctx_test.conf
test/ssltest_old.c

index b65a0d73acce622e5eb2c2daa87c1e5e8d183c73..2957d85d99cada675d43ff4b57da6fd4b255dca9 100644 (file)
@@ -59,6 +59,11 @@ The test section supports the following options:
 * Protocol - expected negotiated protocol. One of
   SSLv3, TLSv1, TLSv1.1, TLSv1.2.
 
+* ClientVerifyCallback - the client's custom certificate verify callback.
+  Used to test callback behaviour. One of
+  - AcceptAll - accepts all certificates.
+  - RejectAll - rejects all certificates.
+
 ## Configuring the client and server
 
 The client and server configurations can be any valid `SSL_CTX`
index 4682d45bfb40a6e0b6ff4c4735801fe02bbf6028..0a27324899c569b292e095e0a99be95b18039231 100644 (file)
@@ -11,6 +11,7 @@
 #include <string.h>
 
 #include <openssl/bio.h>
+#include <openssl/x509_vfy.h>
 #include <openssl/ssl.h>
 
 #include "handshake_helper.h"
@@ -40,6 +41,37 @@ static void info_callback(const SSL *s, int where, int ret)
     }
 }
 
+static int verify_reject_callback(X509_STORE_CTX *ctx, void *arg) {
+    X509_STORE_CTX_set_error(ctx, X509_V_ERR_APPLICATION_VERIFICATION);
+    return 0;
+}
+
+static int verify_accept_callback(X509_STORE_CTX *ctx, void *arg) {
+    return 1;
+}
+
+/*
+ * Configure callbacks and other properties that can't be set directly
+ * in the server/client CONF.
+ */
+static void configure_handshake(SSL_CTX *server_ctx, SSL_CTX *client_ctx,
+                                const SSL_TEST_CTX *test_ctx)
+{
+    switch (test_ctx->client_verify_callback) {
+    case SSL_TEST_VERIFY_ACCEPT_ALL:
+        SSL_CTX_set_cert_verify_callback(client_ctx, &verify_accept_callback,
+                                         NULL);
+        break;
+    case SSL_TEST_VERIFY_REJECT_ALL:
+        SSL_CTX_set_cert_verify_callback(client_ctx, &verify_reject_callback,
+                                         NULL);
+        break;
+    default:
+        break;
+    }
+}
+
+
 typedef enum {
     PEER_SUCCESS,
     PEER_RETRY,
@@ -139,7 +171,8 @@ static handshake_status_t handshake_status(peer_status_t last_status,
     return INTERNAL_ERROR;
 }
 
-HANDSHAKE_RESULT do_handshake(SSL_CTX *server_ctx, SSL_CTX *client_ctx)
+HANDSHAKE_RESULT do_handshake(SSL_CTX *server_ctx, SSL_CTX *client_ctx,
+                              const SSL_TEST_CTX *test_ctx)
 {
     SSL *server, *client;
     BIO *client_to_server, *server_to_client;
@@ -149,6 +182,8 @@ HANDSHAKE_RESULT do_handshake(SSL_CTX *server_ctx, SSL_CTX *client_ctx)
     peer_status_t client_status = PEER_RETRY, server_status = PEER_RETRY;
     handshake_status_t status = HANDSHAKE_RETRY;
 
+    configure_handshake(server_ctx, client_ctx, test_ctx);
+
     server = SSL_new(server_ctx);
     client = SSL_new(client_ctx);
     OPENSSL_assert(server != NULL && client != NULL);
index 56dfb197e21a46f4f637eb690a7b5f933336aecd..5f1ca04ee105c1e98e97c0e3c8672cf42a76fc81 100644 (file)
@@ -30,6 +30,7 @@ typedef struct handshake_result {
 } HANDSHAKE_RESULT;
 
 /* Do a handshake and report some information about the result. */
-HANDSHAKE_RESULT do_handshake(SSL_CTX *server_ctx, SSL_CTX *client_ctx);
+HANDSHAKE_RESULT do_handshake(SSL_CTX *server_ctx, SSL_CTX *client_ctx,
+                              const SSL_TEST_CTX *test_ctx);
 
 #endif  /* HEADER_HANDSHAKE_HELPER_H */
index a0183585cb7879f3b5aefa28bee7d2b7139a6a70..57def45072ecc7ba55a24503a6a3defb6bcd2825 100644 (file)
@@ -20,8 +20,9 @@ setup("test_ssl_new");
 
 $ENV{TEST_CERTS_DIR} = srctop_dir("test", "certs");
 
-my @conf_srcs =  glob(srctop_file("test", "ssl-tests", "*.conf"));
-my @conf_files = map {basename($_)} @conf_srcs;
+my @conf_srcs =  glob(srctop_file("test", "ssl-tests", "*.conf.in"));
+my @conf_files = map { basename($_) } @conf_srcs;
+map { s/\.in// } @conf_files;
 
 # 02-protocol-version.conf test results depend on the configuration of enabled
 # protocols. We only verify generated sources in the default configuration.
@@ -39,7 +40,7 @@ foreach my $conf (@conf_files) {
 
 # We hard-code the number of tests to double-check that the globbing above
 # finds all files as expected.
-plan tests => 2;  # = scalar @conf_files
+plan tests => 3;  # = scalar @conf_srcs
 
 sub test_conf {
     plan tests => 3;
index 61fc423424ac7b2f1d839813cb7a067108f50eeb..37635308ea8aca90de2a52de51fb2e0167003f91 100644 (file)
@@ -79,8 +79,6 @@ my $client_sess="client.ss";
 plan tests =>
     1                          # For testss
     + 14                       # For the first testssl
-    + 16                       # For the first testsslproxy
-    + 16                       # For the second testsslproxy
     ;
 
 subtest 'test_ss' => sub {
@@ -98,13 +96,6 @@ subtest 'test_ss' => sub {
 note('test_ssl -- key U');
 testssl("keyU.ss", $Ucert, $CAcert);
 
-note('test_ssl -- key P1');
-testsslproxy("keyP1.ss", "certP1.ss", "intP1.ss", "AB");
-
-note('test_ssl -- key P2');
-testsslproxy("keyP2.ss", "certP2.ss", "intP2.ss", "BC");
-
-
 # -----------
 # subtest functions
 sub testss {
@@ -832,77 +823,3 @@ sub testssl {
         }
     };
 }
-
-sub testsslproxy {
-    my $key = shift || srctop_file("apps","server.pem");
-    my $cert = shift || srctop_file("apps","server.pem");
-    my $CAtmp = shift;
-    my @CA = $CAtmp ? ("-CAfile", $CAtmp) : ("-CApath", bldtop_dir("certs"));
-    my @extra = @_;
-
-    my @ssltest = ("ssltest_old",
-                  "-s_key", $key, "-s_cert", $cert,
-                  "-c_key", $key, "-c_cert", $cert);
-
-    # plan tests => 16;
-
-    note('Testing a lot of proxy conditions.');
-
-    # We happen to know that certP1.ss has policy letters "AB" and
-    # certP2.ss has policy letters "BC".  However, because certP2.ss
-    # has certP1.ss as issuer, when it's used, both their policy
-    # letters get combined into just "B".
-    # The policy letter(s) then get filtered with the given auth letter
-    # in the table below, and the result gets tested with the given
-    # condition.  For details, read ssltest_old.c
-    #
-    # certfilename => [ [ auth, cond, expected result ] ... ]
-    my %expected = ( "certP1.ss" => [ [ [ 'A',  'A'      ], 1 ],
-                                      [ [ 'A',  'B'      ], 0 ],
-                                      [ [ 'A',  'C'      ], 0 ],
-                                      [ [ 'A',  'A|B&!C' ], 1 ],
-                                      [ [ 'B',  'A'      ], 0 ],
-                                      [ [ 'B',  'B'      ], 1 ],
-                                      [ [ 'B',  'C'      ], 0 ],
-                                      [ [ 'B',  'A|B&!C' ], 1 ],
-                                      [ [ 'C',  'A'      ], 0 ],
-                                      [ [ 'C',  'B'      ], 0 ],
-                                      [ [ 'C',  'C'      ], 0 ],
-                                      [ [ 'C',  'A|B&!C' ], 0 ],
-                                      [ [ 'BC', 'A'      ], 0 ],
-                                      [ [ 'BC', 'B'      ], 1 ],
-                                      [ [ 'BC', 'C'      ], 0 ],
-                                      [ [ 'BC', 'A|B&!C' ], 1 ] ],
-                     "certP2.ss" => [ [ [ 'A',  'A'      ], 0 ],
-                                      [ [ 'A',  'B'      ], 0 ],
-                                      [ [ 'A',  'C'      ], 0 ],
-                                      [ [ 'A',  'A|B&!C' ], 0 ],
-                                      [ [ 'B',  'A'      ], 0 ],
-                                      [ [ 'B',  'B'      ], 1 ],
-                                      [ [ 'B',  'C'      ], 0 ],
-                                      [ [ 'B',  'A|B&!C' ], 1 ],
-                                      [ [ 'C',  'A'      ], 0 ],
-                                      [ [ 'C',  'B'      ], 0 ],
-                                      [ [ 'C',  'C'      ], 0 ],
-                                      [ [ 'C',  'A|B&!C' ], 0 ],
-                                      [ [ 'BC', 'A'      ], 0 ],
-                                      [ [ 'BC', 'B'      ], 1 ],
-                                      [ [ 'BC', 'C'      ], 0 ],
-                                      [ [ 'BC', 'A|B&!C' ], 1 ] ] );
-
-  SKIP: {
-      skip "Neither SSLv3 nor any TLS version are supported by this OpenSSL build", scalar(@{$expected{$cert}})
-         if $no_anytls;
-
-      foreach (@{$expected{$cert}}) {
-         my $auth = $_->[0]->[0];
-         my $cond = $_->[0]->[1];
-         my $res  = $_->[1];
-         is(run(test([@ssltest, "-server_auth", @CA,
-                      "-proxy", "-proxy_auth", $auth,
-                      "-proxy_cond", $cond])), $res,
-            "test tlsv1, server auth, proxy auth $auth and cond $cond (expect "
-            .($res ? "success" : "failure").")");
-      }
-    }
-}
diff --git a/test/ssl-tests/03-custom_verify.conf b/test/ssl-tests/03-custom_verify.conf
new file mode 100644 (file)
index 0000000..182a95d
--- /dev/null
@@ -0,0 +1,238 @@
+# Generated with generate_ssl_tests.pl
+
+num_tests = 9
+
+test-0 = 0-verify-success
+test-1 = 1-verify-custom-reject
+test-2 = 2-verify-custom-allow
+test-3 = 3-noverify-success
+test-4 = 4-noverify-ignore-custom-reject
+test-5 = 5-noverify-accept-custom-allow
+test-6 = 6-verify-fail-no-root
+test-7 = 7-verify-custom-success-no-root
+test-8 = 8-verify-custom-fail-no-root
+# ===========================================================
+
+[0-verify-success]
+ssl_conf = 0-verify-success-ssl
+
+[0-verify-success-ssl]
+server = 0-verify-success-server
+client = 0-verify-success-client
+
+[0-verify-success-server]
+Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+CipherString = DEFAULT
+PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+
+
+[0-verify-success-client]
+CipherString = DEFAULT
+VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
+VerifyMode = Peer
+
+
+[test-0]
+ExpectedResult = Success
+
+
+# ===========================================================
+
+[1-verify-custom-reject]
+ssl_conf = 1-verify-custom-reject-ssl
+
+[1-verify-custom-reject-ssl]
+server = 1-verify-custom-reject-server
+client = 1-verify-custom-reject-client
+
+[1-verify-custom-reject-server]
+Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+CipherString = DEFAULT
+PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+
+
+[1-verify-custom-reject-client]
+CipherString = DEFAULT
+VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
+VerifyMode = Peer
+
+
+[test-1]
+ClientAlert = HandshakeFailure
+ClientVerifyCallback = RejectAll
+ExpectedResult = ClientFail
+
+
+# ===========================================================
+
+[2-verify-custom-allow]
+ssl_conf = 2-verify-custom-allow-ssl
+
+[2-verify-custom-allow-ssl]
+server = 2-verify-custom-allow-server
+client = 2-verify-custom-allow-client
+
+[2-verify-custom-allow-server]
+Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+CipherString = DEFAULT
+PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+
+
+[2-verify-custom-allow-client]
+CipherString = DEFAULT
+VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
+VerifyMode = Peer
+
+
+[test-2]
+ClientVerifyCallback = AcceptAll
+ExpectedResult = Success
+
+
+# ===========================================================
+
+[3-noverify-success]
+ssl_conf = 3-noverify-success-ssl
+
+[3-noverify-success-ssl]
+server = 3-noverify-success-server
+client = 3-noverify-success-client
+
+[3-noverify-success-server]
+Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+CipherString = DEFAULT
+PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+
+
+[3-noverify-success-client]
+CipherString = DEFAULT
+
+
+[test-3]
+ExpectedResult = Success
+
+
+# ===========================================================
+
+[4-noverify-ignore-custom-reject]
+ssl_conf = 4-noverify-ignore-custom-reject-ssl
+
+[4-noverify-ignore-custom-reject-ssl]
+server = 4-noverify-ignore-custom-reject-server
+client = 4-noverify-ignore-custom-reject-client
+
+[4-noverify-ignore-custom-reject-server]
+Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+CipherString = DEFAULT
+PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+
+
+[4-noverify-ignore-custom-reject-client]
+CipherString = DEFAULT
+
+
+[test-4]
+ClientVerifyCallback = RejectAll
+ExpectedResult = Success
+
+
+# ===========================================================
+
+[5-noverify-accept-custom-allow]
+ssl_conf = 5-noverify-accept-custom-allow-ssl
+
+[5-noverify-accept-custom-allow-ssl]
+server = 5-noverify-accept-custom-allow-server
+client = 5-noverify-accept-custom-allow-client
+
+[5-noverify-accept-custom-allow-server]
+Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+CipherString = DEFAULT
+PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+
+
+[5-noverify-accept-custom-allow-client]
+CipherString = DEFAULT
+
+
+[test-5]
+ClientVerifyCallback = AcceptAll
+ExpectedResult = Success
+
+
+# ===========================================================
+
+[6-verify-fail-no-root]
+ssl_conf = 6-verify-fail-no-root-ssl
+
+[6-verify-fail-no-root-ssl]
+server = 6-verify-fail-no-root-server
+client = 6-verify-fail-no-root-client
+
+[6-verify-fail-no-root-server]
+Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+CipherString = DEFAULT
+PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+
+
+[6-verify-fail-no-root-client]
+CipherString = DEFAULT
+VerifyMode = Peer
+
+
+[test-6]
+ClientAlert = UnknownCA
+ExpectedResult = ClientFail
+
+
+# ===========================================================
+
+[7-verify-custom-success-no-root]
+ssl_conf = 7-verify-custom-success-no-root-ssl
+
+[7-verify-custom-success-no-root-ssl]
+server = 7-verify-custom-success-no-root-server
+client = 7-verify-custom-success-no-root-client
+
+[7-verify-custom-success-no-root-server]
+Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+CipherString = DEFAULT
+PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+
+
+[7-verify-custom-success-no-root-client]
+CipherString = DEFAULT
+VerifyMode = Peer
+
+
+[test-7]
+ClientVerifyCallback = AcceptAll
+ExpectedResult = Success
+
+
+# ===========================================================
+
+[8-verify-custom-fail-no-root]
+ssl_conf = 8-verify-custom-fail-no-root-ssl
+
+[8-verify-custom-fail-no-root-ssl]
+server = 8-verify-custom-fail-no-root-server
+client = 8-verify-custom-fail-no-root-client
+
+[8-verify-custom-fail-no-root-server]
+Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+CipherString = DEFAULT
+PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+
+
+[8-verify-custom-fail-no-root-client]
+CipherString = DEFAULT
+VerifyMode = Peer
+
+
+[test-8]
+ClientAlert = HandshakeFailure
+ClientVerifyCallback = RejectAll
+ExpectedResult = ClientFail
+
+
diff --git a/test/ssl-tests/03-custom_verify.conf.in b/test/ssl-tests/03-custom_verify.conf.in
new file mode 100644 (file)
index 0000000..e2f9dc7
--- /dev/null
@@ -0,0 +1,127 @@
+# -*- mode: perl; -*-
+
+## SSL test configurations
+
+package ssltests;
+
+our @tests = (
+
+    # Sanity-check that verification indeed succeeds without the
+    # restrictive callback.
+    {
+        name => "verify-success",
+        server => { },
+        client => { },
+        test   => { "ExpectedResult" => "Success" },
+    },
+
+    # Same test as above but with a custom callback that always fails.
+    {
+        name => "verify-custom-reject",
+        server => { },
+        client => { },
+        test   => {
+            "ClientVerifyCallback" => "RejectAll",
+            "ExpectedResult" => "ClientFail",
+            "ClientAlert" => "HandshakeFailure",
+        },
+    },
+
+    # Same test as above but with a custom callback that always succeeds.
+    {
+        name => "verify-custom-allow",
+        server => { },
+        client => { },
+        test   => {
+            "ClientVerifyCallback" => "AcceptAll",
+            "ExpectedResult" => "Success",
+        },
+    },
+
+    # Sanity-check that verification indeed succeeds if peer verification
+    # is not requested.
+    {
+        name => "noverify-success",
+        server => { },
+        client => {
+            "VerifyMode" => undef,
+            "VerifyCAFile" => undef,
+        },
+        test   => { "ExpectedResult" => "Success" },
+    },
+
+    # Same test as above but with a custom callback that always fails.
+    # The callback return has no impact on handshake success in this mode.
+    {
+        name => "noverify-ignore-custom-reject",
+        server => { },
+        client => {
+            "VerifyMode" => undef,
+            "VerifyCAFile" => undef,
+        },
+        test   => {
+            "ClientVerifyCallback" => "RejectAll",
+            "ExpectedResult" => "Success",
+        },
+    },
+
+    # Same test as above but with a custom callback that always succeeds.
+    # The callback return has no impact on handshake success in this mode.
+    {
+        name => "noverify-accept-custom-allow",
+        server => { },
+        client => {
+            "VerifyMode" => undef,
+            "VerifyCAFile" => undef,
+        },
+        test   => {
+            "ClientVerifyCallback" => "AcceptAll",
+            "ExpectedResult" => "Success",
+        },
+    },
+
+    # Sanity-check that verification indeed fails without the
+    # permissive callback.
+    {
+        name => "verify-fail-no-root",
+        server => { },
+        client => {
+            # Don't set up the client root file.
+            "VerifyCAFile" => undef,
+        },
+        test   => {
+          "ExpectedResult" => "ClientFail",
+          "ClientAlert" => "UnknownCA",
+        },
+    },
+
+    # Same test as above but with a custom callback that always succeeds.
+    {
+        name => "verify-custom-success-no-root",
+        server => { },
+        client => {
+            "VerifyCAFile" => undef,
+        },
+        test   => {
+            "ClientVerifyCallback" => "AcceptAll",
+            "ExpectedResult" => "Success"
+        },
+    },
+
+    # Same test as above but with a custom callback that always fails.
+    {
+        name => "verify-custom-fail-no-root",
+        server => { },
+        client => {
+            "VerifyCAFile" => undef,
+        },
+        test   => {
+            "ClientVerifyCallback" => "RejectAll",
+            "ExpectedResult" => "ClientFail",
+            "ClientAlert" => "HandshakeFailure",
+        },
+    },
+
+
+
+);
index dfe71cbc5614547f85bdc14554ec16313098dfd9..b3faffc99914d83b3451bf2164841dad642366e2 100644 (file)
@@ -44,8 +44,8 @@ static int check_result(HANDSHAKE_RESULT result, SSL_TEST_CTX *test_ctx)
 {
     if (result.result != test_ctx->expected_result) {
         fprintf(stderr, "ExpectedResult mismatch: expected %s, got %s.\n",
-                ssl_test_result_t_name(test_ctx->expected_result),
-                ssl_test_result_t_name(result.result));
+                ssl_test_result_name(test_ctx->expected_result),
+                ssl_test_result_name(result.result));
         return 0;
     }
     return 1;
@@ -160,7 +160,7 @@ static int execute_test(SSL_TEST_FIXTURE fixture)
     if (test_ctx == NULL)
         goto err;
 
-    result = do_handshake(server_ctx, client_ctx);
+    result = do_handshake(server_ctx, client_ctx, test_ctx);
 
     ret = check_test(result, test_ctx);
 
index 0c1bbbde9e87d3becead878872e51a298b349c5b..5db7bd45ce2bdfe599e36435e6886d988821c5c1 100644 (file)
@@ -71,7 +71,7 @@ __owur static int parse_expected_result(SSL_TEST_CTX *test_ctx, const char *valu
     return 1;
 }
 
-const char *ssl_test_result_t_name(ssl_test_result_t result)
+const char *ssl_test_result_name(ssl_test_result_t result)
 {
     return enum_name(ssl_test_results, OSSL_NELEM(ssl_test_results), result);
 }
@@ -82,6 +82,7 @@ const char *ssl_test_result_t_name(ssl_test_result_t result)
 
 static const test_enum ssl_alerts[] = {
     {"UnknownCA", SSL_AD_UNKNOWN_CA},
+    {"HandshakeFailure", SSL_AD_HANDSHAKE_FAILURE},
 };
 
 __owur static int parse_alert(int *alert, const char *value)
@@ -126,6 +127,34 @@ const char *ssl_protocol_name(int protocol)
     return enum_name(ssl_protocols, OSSL_NELEM(ssl_protocols), protocol);
 }
 
+/***********************/
+/* CertVerifyCallback. */
+/***********************/
+
+static const test_enum ssl_verify_callbacks[] = {
+    {"None", SSL_TEST_VERIFY_NONE},
+    {"AcceptAll", SSL_TEST_VERIFY_ACCEPT_ALL},
+    {"RejectAll", SSL_TEST_VERIFY_REJECT_ALL},
+};
+
+__owur static int parse_client_verify_callback(SSL_TEST_CTX *test_ctx,
+                                              const char *value)
+{
+    int ret_value;
+    if (!parse_enum(ssl_verify_callbacks, OSSL_NELEM(ssl_verify_callbacks),
+                    &ret_value, value)) {
+        return 0;
+    }
+    test_ctx->client_verify_callback = ret_value;
+    return 1;
+}
+
+const char *ssl_verify_callback_name(ssl_verify_callback_t callback)
+{
+    return enum_name(ssl_verify_callbacks, OSSL_NELEM(ssl_verify_callbacks),
+                     callback);
+}
+
 
 /*************************************************************/
 /* Known test options and their corresponding parse methods. */
@@ -141,6 +170,7 @@ static const ssl_test_ctx_option ssl_test_ctx_options[] = {
     { "ClientAlert", &parse_client_alert },
     { "ServerAlert", &parse_server_alert },
     { "Protocol", &parse_protocol },
+    { "ClientVerifyCallback", &parse_client_verify_callback },
 };
 
 
@@ -153,7 +183,6 @@ SSL_TEST_CTX *SSL_TEST_CTX_new()
     SSL_TEST_CTX *ret;
     ret = OPENSSL_zalloc(sizeof(*ret));
     OPENSSL_assert(ret != NULL);
-    ret->expected_result = SSL_TEST_SUCCESS;
     return ret;
 }
 
index a183272b4e3a8f1e5f7a7a0a75f81aab966d2c66..9aaa4cea505473bb6cf65900fb831b8a6d776421 100644 (file)
 #include <openssl/ssl.h>
 
 typedef enum {
-    SSL_TEST_SUCCESS,  /* Default */
+    SSL_TEST_SUCCESS = 0,  /* Default */
     SSL_TEST_SERVER_FAIL,
     SSL_TEST_CLIENT_FAIL,
     SSL_TEST_INTERNAL_ERROR
 } ssl_test_result_t;
 
+typedef enum {
+    SSL_TEST_VERIFY_NONE = 0, /* Default */
+    SSL_TEST_VERIFY_ACCEPT_ALL,
+    SSL_TEST_VERIFY_REJECT_ALL
+} ssl_verify_callback_t;
+
 typedef struct ssl_test_ctx {
     /* Test expectations. */
     /* Defaults to SUCCESS. */
@@ -34,11 +40,14 @@ typedef struct ssl_test_ctx {
     /* Negotiated protocol version. 0 if no expectation. */
     /* See ssl.h for protocol versions. */
     int protocol;
+    /* One of a number of predefined custom callbacks. */
+    ssl_verify_callback_t client_verify_callback;
 } SSL_TEST_CTX;
 
-const char *ssl_test_result_t_name(ssl_test_result_t result);
+const char *ssl_test_result_name(ssl_test_result_t result);
 const char *ssl_alert_name(int alert);
 const char *ssl_protocol_name(int protocol);
+const char *ssl_verify_callback_name(ssl_verify_callback_t verify_callback);
 
 /*
  * Load the test case context from |conf|.
index 3c6fa715f2fb68e9bc03b5c0e5b2bb820972fcc2..792f5e811fdbcb6c9fe0d51293127242291f3400 100644 (file)
@@ -37,26 +37,32 @@ static int SSL_TEST_CTX_equal(SSL_TEST_CTX *ctx, SSL_TEST_CTX *ctx2)
 {
     if (ctx->expected_result != ctx2->expected_result) {
         fprintf(stderr, "ExpectedResult mismatch: %s vs %s.\n",
-                ssl_test_result_t_name(ctx->expected_result),
-                ssl_test_result_t_name(ctx2->expected_result));
+                ssl_test_result_name(ctx->expected_result),
+                ssl_test_result_name(ctx2->expected_result));
         return 0;
     }
     if (ctx->client_alert != ctx2->client_alert) {
         fprintf(stderr, "ClientAlert mismatch: %s vs %s.\n",
-                ssl_alert_name(ctx->expected_result),
-                ssl_alert_name(ctx2->expected_result));
+                ssl_alert_name(ctx->client_alert),
+                ssl_alert_name(ctx2->client_alert));
         return 0;
     }
     if (ctx->server_alert != ctx2->server_alert) {
         fprintf(stderr, "ServerAlert mismatch: %s vs %s.\n",
-                ssl_alert_name(ctx->expected_result),
-                ssl_alert_name(ctx2->expected_result));
+                ssl_alert_name(ctx->server_alert),
+                ssl_alert_name(ctx2->server_alert));
         return 0;
     }
     if (ctx->protocol != ctx2->protocol) {
         fprintf(stderr, "ClientAlert mismatch: %s vs %s.\n",
-                ssl_protocol_name(ctx->expected_result),
-                ssl_protocol_name(ctx2->expected_result));
+                ssl_protocol_name(ctx->protocol),
+                ssl_protocol_name(ctx2->protocol));
+        return 0;
+    }
+    if (ctx->client_verify_callback != ctx2->client_verify_callback) {
+        fprintf(stderr, "ClientVerifyCallback mismatch: %s vs %s.\n",
+                ssl_verify_callback_name(ctx->client_verify_callback),
+                ssl_verify_callback_name(ctx2->client_verify_callback));
         return 0;
     }
 
@@ -136,6 +142,7 @@ static int test_good_configuration()
     fixture.expected_ctx->client_alert = SSL_AD_UNKNOWN_CA;
     fixture.expected_ctx->server_alert = 0;  /* No alert. */
     fixture.expected_ctx->protocol = TLS1_1_VERSION;
+    fixture.expected_ctx->client_verify_callback = SSL_TEST_VERIFY_REJECT_ALL,
     EXECUTE_SSL_TEST_CTX_TEST();
 }
 
@@ -144,6 +151,7 @@ static const char *bad_configurations[] = {
     "ssltest_unknown_expected_result",
     "ssltest_unknown_alert",
     "ssltest_unknown_protocol",
+    "ssltest_unknown_verify_callback",
 };
 
 static int test_bad_configuration(int idx)
index 2e6800e90d2de43b0aa74c0ff8b4947f0f9b9af8..3b146052c1e2e8f0e4e44fb92f6e3098fc29276e 100644 (file)
@@ -4,6 +4,7 @@
 ExpectedResult = ServerFail
 ClientAlert = UnknownCA
 Protocol = TLSv1.1
+ClientVerifyCallback = RejectAll
 
 [ssltest_unknown_option]
 UnknownOption = Foo
@@ -16,3 +17,6 @@ ServerAlert = Foo
 
 [ssltest_unknown_protocol]
 Protocol = Foo
+
+[ssltest_unknown_verify_callback]
+ClientVerifyCallback = Foo
index c7f3e1872d2dfa4cfbaede8614c3dab003b25e99..eb35c1d6c0803779a65788d87e931052ae313880 100644 (file)
@@ -223,9 +223,6 @@ static int app_verify_callback(X509_STORE_CTX *ctx, void *arg);
 struct app_verify_arg {
     char *string;
     int app_verify;
-    int allow_proxy_certs;
-    char *proxy_auth;
-    char *proxy_cond;
 };
 
 #ifndef OPENSSL_NO_DH
@@ -809,10 +806,6 @@ static void sv_usage(void)
 #endif
     fprintf(stderr, " -server_auth  - check server certificate\n");
     fprintf(stderr, " -client_auth  - do client authentication\n");
-    fprintf(stderr, " -proxy        - allow proxy certificates\n");
-    fprintf(stderr, " -proxy_auth <val> - set proxy policy rights\n");
-    fprintf(stderr,
-            " -proxy_cond <val> - expression to test proxy policy rights\n");
     fprintf(stderr, " -v            - more output\n");
     fprintf(stderr, " -d            - debug output\n");
     fprintf(stderr, " -reuse        - use session-id reuse\n");
@@ -1069,7 +1062,7 @@ int main(int argc, char *argv[])
     int client_auth = 0;
     int server_auth = 0, i;
     struct app_verify_arg app_verify_arg =
-        { APP_CALLBACK_STRING, 0, 0, NULL, NULL };
+        { APP_CALLBACK_STRING, 0 };
     char *p;
     SSL_CTX *c_ctx = NULL;
     const SSL_METHOD *meth = NULL;
@@ -1179,15 +1172,7 @@ int main(int argc, char *argv[])
             server_auth = 1;
         else if (strcmp(*argv, "-client_auth") == 0)
             client_auth = 1;
-        else if (strcmp(*argv, "-proxy_auth") == 0) {
-            if (--argc < 1)
-                goto bad;
-            app_verify_arg.proxy_auth = *(++argv);
-        } else if (strcmp(*argv, "-proxy_cond") == 0) {
-            if (--argc < 1)
-                goto bad;
-            app_verify_arg.proxy_cond = *(++argv);
-        } else if (strcmp(*argv, "-v") == 0)
+        else if (strcmp(*argv, "-v") == 0)
             verbose = 1;
         else if (strcmp(*argv, "-d") == 0)
             debug = 1;
@@ -1307,8 +1292,6 @@ int main(int argc, char *argv[])
 #endif
         else if (strcmp(*argv, "-app_verify") == 0) {
             app_verify_arg.app_verify = 1;
-        } else if (strcmp(*argv, "-proxy") == 0) {
-            app_verify_arg.allow_proxy_certs = 1;
         }
 #ifndef OPENSSL_NO_NEXTPROTONEG
           else if (strcmp(*argv, "-npn_client") == 0) {
@@ -3027,23 +3010,6 @@ int doit(SSL *s_ssl, SSL *c_ssl, long count)
     return (ret);
 }
 
-static CRYPTO_ONCE proxy_auth_ex_data_once = CRYPTO_ONCE_STATIC_INIT;
-static volatile int proxy_auth_ex_data_idx = -1;
-
-static void do_get_proxy_auth_ex_data_idx(void)
-{
-    proxy_auth_ex_data_idx = X509_STORE_CTX_get_ex_new_index(0,
-                                                "SSLtest for verify callback",
-                                                NULL, NULL, NULL);
-}
-
-static int get_proxy_auth_ex_data_idx(void)
-{
-    CRYPTO_THREAD_run_once(&proxy_auth_ex_data_once,
-                           do_get_proxy_auth_ex_data_idx);
-    return proxy_auth_ex_data_idx;
-}
-
 static int verify_callback(int ok, X509_STORE_CTX *ctx)
 {
     char *s, buf[256];
@@ -3076,341 +3042,13 @@ static int verify_callback(int ok, X509_STORE_CTX *ctx)
         }
     }
 
-    if (ok == 1) {
-        X509 *xs = X509_STORE_CTX_get_current_cert(ctx);
-        if (X509_get_extension_flags(xs) & EXFLAG_PROXY) {
-            unsigned int *letters = X509_STORE_CTX_get_ex_data(ctx,
-                                                               get_proxy_auth_ex_data_idx
-                                                               ());
-
-            if (letters) {
-                int found_any = 0;
-                int i;
-                PROXY_CERT_INFO_EXTENSION *pci =
-                    X509_get_ext_d2i(xs, NID_proxyCertInfo,
-                                     NULL, NULL);
-
-                switch (OBJ_obj2nid(pci->proxyPolicy->policyLanguage)) {
-                case NID_Independent:
-                    /*
-                     * Completely meaningless in this program, as there's no
-                     * way to grant explicit rights to a specific PrC.
-                     * Basically, using id-ppl-Independent is the perfect way
-                     * to grant no rights at all.
-                     */
-                    fprintf(stderr, "  Independent proxy certificate");
-                    for (i = 0; i < 26; i++)
-                        letters[i] = 0;
-                    break;
-                case NID_id_ppl_inheritAll:
-                    /*
-                     * This is basically a NOP, we simply let the current
-                     * rights stand as they are.
-                     */
-                    fprintf(stderr, "  Proxy certificate inherits all");
-                    break;
-                default:
-                    s = (char *)
-                        pci->proxyPolicy->policy->data;
-                    i = pci->proxyPolicy->policy->length;
-
-                    /*
-                     * The algorithm works as follows: it is assumed that
-                     * previous iterations or the initial granted rights has
-                     * already set some elements of `letters'.  What we need
-                     * to do is to clear those that weren't granted by the
-                     * current PrC as well.  The easiest way to do this is to
-                     * add 1 to all the elements whose letters are given with
-                     * the current policy. That way, all elements that are
-                     * set by the current policy and were already set by
-                     * earlier policies and through the original grant of
-                     * rights will get the value 2 or higher. The last thing
-                     * to do is to sweep through `letters' and keep the
-                     * elements having the value 2 as set, and clear all the
-                     * others.
-                     */
-
-                    printf("  Certificate proxy rights = %*.*s", i,
-                            i, s);
-                    while (i-- > 0) {
-                        int c = *s++;
-                        if (isascii(c) && isalpha(c)) {
-                            if (islower(c))
-                                c = toupper(c);
-                            letters[c - 'A']++;
-                        }
-                    }
-                    for (i = 0; i < 26; i++)
-                        if (letters[i] < 2)
-                            letters[i] = 0;
-                        else
-                            letters[i] = 1;
-                }
-
-                found_any = 0;
-                printf(", resulting proxy rights = ");
-                for (i = 0; i < 26; i++)
-                    if (letters[i]) {
-                        printf("%c", i + 'A');
-                        found_any = 1;
-                    }
-                if (!found_any)
-                    printf("none");
-                printf("\n");
-
-                PROXY_CERT_INFO_EXTENSION_free(pci);
-            }
-        }
-    }
-
     return (ok);
 }
 
-static void process_proxy_debug(int indent, const char *format, ...)
-{
-    /* That's 80 > */
-    static const char indentation[] =
-        ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
-        ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>";
-    char my_format[256];
-    va_list args;
-
-    BIO_snprintf(my_format, sizeof(my_format), "%*.*s %s",
-                 indent, indent, indentation, format);
-
-    va_start(args, format);
-    vfprintf(stderr, my_format, args);
-    va_end(args);
-}
-
-/*-
- * Priority levels:
- *  0   [!]var, ()
- *  1   & ^
- *  2   |
- */
-static int process_proxy_cond_adders(unsigned int letters[26],
-                                     const char *cond, const char **cond_end,
-                                     int *pos, int indent);
-static int process_proxy_cond_val(unsigned int letters[26], const char *cond,
-                                  const char **cond_end, int *pos, int indent)
-{
-    int c;
-    int ok = 1;
-    int negate = 0;
-
-    while (isspace((int)*cond)) {
-        cond++;
-        (*pos)++;
-    }
-    c = *cond;
-
-    if (debug)
-        process_proxy_debug(indent,
-                            "Start process_proxy_cond_val at position %d: %s\n",
-                            *pos, cond);
-
-    while (c == '!') {
-        negate = !negate;
-        cond++;
-        (*pos)++;
-        while (isspace((int)*cond)) {
-            cond++;
-            (*pos)++;
-        }
-        c = *cond;
-    }
-
-    if (c == '(') {
-        cond++;
-        (*pos)++;
-        ok = process_proxy_cond_adders(letters, cond, cond_end, pos,
-                                       indent + 1);
-        cond = *cond_end;
-        if (ok < 0)
-            goto end;
-        while (isspace((int)*cond)) {
-            cond++;
-            (*pos)++;
-        }
-        c = *cond;
-        if (c != ')') {
-            fprintf(stderr,
-                    "Weird condition character in position %d: "
-                    "%c\n", *pos, c);
-            ok = -1;
-            goto end;
-        }
-        cond++;
-        (*pos)++;
-    } else if (isascii(c) && isalpha(c)) {
-        if (islower(c))
-            c = toupper(c);
-        ok = letters[c - 'A'];
-        cond++;
-        (*pos)++;
-    } else {
-        fprintf(stderr,
-                "Weird condition character in position %d: " "%c\n", *pos, c);
-        ok = -1;
-        goto end;
-    }
- end:
-    *cond_end = cond;
-    if (ok >= 0 && negate)
-        ok = !ok;
-
-    if (debug)
-        process_proxy_debug(indent,
-                            "End process_proxy_cond_val at position %d: %s, returning %d\n",
-                            *pos, cond, ok);
-
-    return ok;
-}
-
-static int process_proxy_cond_multipliers(unsigned int letters[26],
-                                          const char *cond,
-                                          const char **cond_end, int *pos,
-                                          int indent)
-{
-    int ok;
-    char c;
-
-    if (debug)
-        process_proxy_debug(indent,
-                            "Start process_proxy_cond_multipliers at position %d: %s\n",
-                            *pos, cond);
-
-    ok = process_proxy_cond_val(letters, cond, cond_end, pos, indent + 1);
-    cond = *cond_end;
-    if (ok < 0)
-        goto end;
-
-    while (ok >= 0) {
-        while (isspace((int)*cond)) {
-            cond++;
-            (*pos)++;
-        }
-        c = *cond;
-
-        switch (c) {
-        case '&':
-        case '^':
-            {
-                int save_ok = ok;
-
-                cond++;
-                (*pos)++;
-                ok = process_proxy_cond_val(letters,
-                                            cond, cond_end, pos, indent + 1);
-                cond = *cond_end;
-                if (ok < 0)
-                    break;
-
-                switch (c) {
-                case '&':
-                    ok &= save_ok;
-                    break;
-                case '^':
-                    ok ^= save_ok;
-                    break;
-                default:
-                    fprintf(stderr, "SOMETHING IS SERIOUSLY WRONG!"
-                            " STOPPING\n");
-                    EXIT(1);
-                }
-            }
-            break;
-        default:
-            goto end;
-        }
-    }
- end:
-    if (debug)
-        process_proxy_debug(indent,
-                            "End process_proxy_cond_multipliers at position %d: %s, returning %d\n",
-                            *pos, cond, ok);
-
-    *cond_end = cond;
-    return ok;
-}
-
-static int process_proxy_cond_adders(unsigned int letters[26],
-                                     const char *cond, const char **cond_end,
-                                     int *pos, int indent)
-{
-    int ok;
-    char c;
-
-    if (debug)
-        process_proxy_debug(indent,
-                            "Start process_proxy_cond_adders at position %d: %s\n",
-                            *pos, cond);
-
-    ok = process_proxy_cond_multipliers(letters, cond, cond_end, pos,
-                                        indent + 1);
-    cond = *cond_end;
-    if (ok < 0)
-        goto end;
-
-    while (ok >= 0) {
-        while (isspace((int)*cond)) {
-            cond++;
-            (*pos)++;
-        }
-        c = *cond;
-
-        switch (c) {
-        case '|':
-            {
-                int save_ok = ok;
-
-                cond++;
-                (*pos)++;
-                ok = process_proxy_cond_multipliers(letters,
-                                                    cond, cond_end, pos,
-                                                    indent + 1);
-                cond = *cond_end;
-                if (ok < 0)
-                    break;
-
-                switch (c) {
-                case '|':
-                    ok |= save_ok;
-                    break;
-                default:
-                    fprintf(stderr, "SOMETHING IS SERIOUSLY WRONG!"
-                            " STOPPING\n");
-                    EXIT(1);
-                }
-            }
-            break;
-        default:
-            goto end;
-        }
-    }
- end:
-    if (debug)
-        process_proxy_debug(indent,
-                            "End process_proxy_cond_adders at position %d: %s, returning %d\n",
-                            *pos, cond, ok);
-
-    *cond_end = cond;
-    return ok;
-}
-
-static int process_proxy_cond(unsigned int letters[26],
-                              const char *cond, const char **cond_end)
-{
-    int pos = 1;
-    return process_proxy_cond_adders(letters, cond, cond_end, &pos, 1);
-}
-
 static int app_verify_callback(X509_STORE_CTX *ctx, void *arg)
 {
     int ok = 1;
     struct app_verify_arg *cb_arg = arg;
-    unsigned int letters[26];   /* only used with proxy_auth */
 
     if (cb_arg->app_verify) {
         char *s = NULL, buf[256];
@@ -3428,61 +3066,9 @@ static int app_verify_callback(X509_STORE_CTX *ctx, void *arg)
         }
         return (1);
     }
-    if (cb_arg->proxy_auth) {
-        int found_any = 0, i;
-        char *sp;
-
-        for (i = 0; i < 26; i++)
-            letters[i] = 0;
-        for (sp = cb_arg->proxy_auth; *sp; sp++) {
-            int c = *sp;
-            if (isascii(c) && isalpha(c)) {
-                if (islower(c))
-                    c = toupper(c);
-                letters[c - 'A'] = 1;
-            }
-        }
 
-        printf("  Initial proxy rights = ");
-        for (i = 0; i < 26; i++)
-            if (letters[i]) {
-                printf("%c", i + 'A');
-                found_any = 1;
-            }
-        if (!found_any)
-            printf("none");
-        printf("\n");
-
-        X509_STORE_CTX_set_ex_data(ctx,
-                                   get_proxy_auth_ex_data_idx(), letters);
-    }
-    if (cb_arg->allow_proxy_certs) {
-        X509_STORE_CTX_set_flags(ctx, X509_V_FLAG_ALLOW_PROXY_CERTS);
-    }
     ok = X509_verify_cert(ctx);
 
-    if (cb_arg->proxy_auth) {
-        if (ok > 0) {
-            const char *cond_end = NULL;
-
-            ok = process_proxy_cond(letters, cb_arg->proxy_cond, &cond_end);
-
-            if (ok < 0)
-                EXIT(3);
-            if (*cond_end) {
-                fprintf(stderr,
-                        "Stopped processing condition before it's end.\n");
-                ok = 0;
-            }
-            if (!ok)
-                fprintf(stderr,
-                        "Proxy rights check with condition '%s' invalid\n",
-                        cb_arg->proxy_cond);
-            else
-                printf("Proxy rights check with condition '%s' ok\n",
-                        cb_arg->proxy_cond);
-        }
-    }
     return (ok);
 }