Commit 2e21539b authored by Dr. Stephen Henson's avatar Dr. Stephen Henson
Browse files

Add ExpectedClientCANames



Add ExpectedClientCANames: for client auth this checks to see if the
list of certificate authorities supplied by the server matches the
expected value.

Reviewed-by: default avatarRichard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/2969)
parent f8f16d8e
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -98,6 +98,10 @@ handshake.
* ExpectedServerSignType, ExpectedClientSignType - the expected
  signature type used by server or client when signing messages

* ExpectedClientCANames - for client auth list of CA names the server must
  send. If this is "empty" the list is expected to be empty otherwise it
  is a file of certificates whose subject names form the list.

## Configuring the client and server

The client and server configurations can be any valid `SSL_CTX`
+1 −1
Original line number Diff line number Diff line
@@ -236,7 +236,7 @@ IF[{- !$disabled{tests} -}]

  SOURCE[ssl_test_ctx_test]=ssl_test_ctx_test.c ssl_test_ctx.c testutil.c test_main_custom.c
  INCLUDE[ssl_test_ctx_test]=.. ../include
  DEPEND[ssl_test_ctx_test]=../libcrypto
  DEPEND[ssl_test_ctx_test]=../libcrypto ../libssl

  SOURCE[ssl_test]=ssl_test.c ssl_test_ctx.c testutil.c handshake_helper.c test_main_custom.c
  INCLUDE[ssl_test]=.. ../include
+8 −0
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ void HANDSHAKE_RESULT_free(HANDSHAKE_RESULT *result)
    OPENSSL_free(result->server_npn_negotiated);
    OPENSSL_free(result->client_alpn_negotiated);
    OPENSSL_free(result->server_alpn_negotiated);
    sk_X509_NAME_pop_free(result->client_ca_names, X509_NAME_free);
    OPENSSL_free(result);
}

@@ -1122,6 +1123,7 @@ static HANDSHAKE_RESULT *do_handshake_internal(
    /* API dictates unsigned int rather than size_t. */
    unsigned int proto_len = 0;
    EVP_PKEY *tmp_key;
    STACK_OF(X509_NAME) *names;

    memset(&server_ctx_data, 0, sizeof(server_ctx_data));
    memset(&server2_ctx_data, 0, sizeof(server2_ctx_data));
@@ -1295,6 +1297,12 @@ static HANDSHAKE_RESULT *do_handshake_internal(
    SSL_get_peer_signature_type_nid(client.ssl, &ret->server_sign_type);
    SSL_get_peer_signature_type_nid(server.ssl, &ret->client_sign_type);

    names = SSL_get_client_CA_list(client.ssl);
    if (names == NULL)
        ret->client_ca_names = NULL;
    else
        ret->client_ca_names = SSL_dup_CA_list(names);

    ret->server_cert_type = peer_pkey_type(client.ssl);
    ret->client_cert_type = peer_pkey_type(server.ssl);

+2 −0
Original line number Diff line number Diff line
@@ -58,6 +58,8 @@ typedef struct handshake_result {
    int client_sign_hash;
    /* client signature type */
    int client_sign_type;
    /* Client CA names */
    STACK_OF(X509_NAME) *client_ca_names;
} HANDSHAKE_RESULT;

HANDSHAKE_RESULT *HANDSHAKE_RESULT_new(void);
+57 −0
Original line number Diff line number Diff line
@@ -255,6 +255,62 @@ static int check_client_sign_type(HANDSHAKE_RESULT *result,
                     result->client_sign_type);
}

static void print_ca_names(STACK_OF(X509_NAME) *names)
{
    BIO *err;
    int i;

    if (names == NULL || sk_X509_NAME_num(names) == 0) {
        fprintf(stderr, "    <empty>\n");
        return;
    }
    err = BIO_new_fp(stderr, BIO_NOCLOSE);
    for (i = 0; i < sk_X509_NAME_num(names); i++) {
        X509_NAME_print_ex(err, sk_X509_NAME_value(names, i), 4,
                           XN_FLAG_ONELINE);
        BIO_puts(err, "\n");
    }
    BIO_free(err);
}

static int check_ca_names(const char *name,
                          STACK_OF(X509_NAME) *expected_names,
                          STACK_OF(X509_NAME) *names)
{
    int i;

    if (expected_names == NULL)
        return 1;
    if (names == NULL || sk_X509_NAME_num(names) == 0) {
        if (sk_X509_NAME_num(expected_names) == 0)
            return 1;
        goto err;
    }
    if (sk_X509_NAME_num(names) != sk_X509_NAME_num(expected_names))
        goto err;
    for (i = 0; i < sk_X509_NAME_num(names); i++) {
        if (X509_NAME_cmp(sk_X509_NAME_value(names, i),
                          sk_X509_NAME_value(expected_names, i)) != 0) {
            goto err;
        }
    }
    return 1;
    err:
    fprintf(stderr, "%s: list mismatch\nExpected Names:\n", name);
    print_ca_names(expected_names);
    fprintf(stderr, "Received Names:\n");
    print_ca_names(names);
    return 0;
}

static int check_client_ca_names(HANDSHAKE_RESULT *result,
                                 SSL_TEST_CTX *test_ctx)
{
    return check_ca_names("Client CA names",
                          test_ctx->expected_client_ca_names,
                          result->client_ca_names);
}

/*
 * This could be further simplified by constructing an expected
 * HANDSHAKE_RESULT, and implementing comparison methods for
@@ -283,6 +339,7 @@ static int check_test(HANDSHAKE_RESULT *result, SSL_TEST_CTX *test_ctx)
        ret &= check_client_cert_type(result, test_ctx);
        ret &= check_client_sign_hash(result, test_ctx);
        ret &= check_client_sign_type(result, test_ctx);
        ret &= check_client_ca_names(result, test_ctx);
    }
    return ret;
}
Loading