| /* |
| * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. |
| * |
| * Licensed under the OpenSSL license (the "License"). You may not use |
| * this file except in compliance with the License. You can obtain a copy |
| * in the file LICENSE in the source distribution or at |
| * https://www.openssl.org/source/license.html |
| */ |
| |
| #include <string.h> |
| |
| #include <openssl/e_os2.h> |
| #include <openssl/crypto.h> |
| |
| #include "e_os.h" |
| #include "ssl_test_ctx.h" |
| |
| /* True enums and other test configuration values that map to an int. */ |
| typedef struct { |
| const char *name; |
| int value; |
| } test_enum; |
| |
| |
| __owur static int parse_enum(const test_enum *enums, size_t num_enums, |
| int *value, const char *name) |
| { |
| size_t i; |
| for (i = 0; i < num_enums; i++) { |
| if (strcmp(enums[i].name, name) == 0) { |
| *value = enums[i].value; |
| return 1; |
| } |
| } |
| return 0; |
| } |
| |
| static const char *enum_name(const test_enum *enums, size_t num_enums, |
| int value) |
| { |
| size_t i; |
| for (i = 0; i < num_enums; i++) { |
| if (enums[i].value == value) { |
| return enums[i].name; |
| } |
| } |
| return "InvalidValue"; |
| } |
| |
| |
| /*******************/ |
| /* ExpectedResult. */ |
| /*******************/ |
| |
| static const test_enum ssl_test_results[] = { |
| {"Success", SSL_TEST_SUCCESS}, |
| {"ServerFail", SSL_TEST_SERVER_FAIL}, |
| {"ClientFail", SSL_TEST_CLIENT_FAIL}, |
| {"InternalError", SSL_TEST_INTERNAL_ERROR}, |
| }; |
| |
| __owur static int parse_expected_result(SSL_TEST_CTX *test_ctx, const char *value) |
| { |
| int ret_value; |
| if (!parse_enum(ssl_test_results, OSSL_NELEM(ssl_test_results), |
| &ret_value, value)) { |
| return 0; |
| } |
| test_ctx->expected_result = ret_value; |
| return 1; |
| } |
| |
| const char *ssl_test_result_name(ssl_test_result_t result) |
| { |
| return enum_name(ssl_test_results, OSSL_NELEM(ssl_test_results), result); |
| } |
| |
| /******************************/ |
| /* ClientAlert / ServerAlert. */ |
| /******************************/ |
| |
| 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) |
| { |
| return parse_enum(ssl_alerts, OSSL_NELEM(ssl_alerts), alert, value); |
| } |
| |
| __owur static int parse_client_alert(SSL_TEST_CTX *test_ctx, const char *value) |
| { |
| return parse_alert(&test_ctx->client_alert, value); |
| } |
| |
| __owur static int parse_server_alert(SSL_TEST_CTX *test_ctx, const char *value) |
| { |
| return parse_alert(&test_ctx->server_alert, value); |
| } |
| |
| const char *ssl_alert_name(int alert) |
| { |
| return enum_name(ssl_alerts, OSSL_NELEM(ssl_alerts), alert); |
| } |
| |
| /************/ |
| /* Protocol */ |
| /************/ |
| |
| static const test_enum ssl_protocols[] = { |
| {"TLSv1.2", TLS1_2_VERSION}, |
| {"TLSv1.1", TLS1_1_VERSION}, |
| {"TLSv1", TLS1_VERSION}, |
| {"SSLv3", SSL3_VERSION}, |
| }; |
| |
| __owur static int parse_protocol(SSL_TEST_CTX *test_ctx, const char *value) |
| { |
| return parse_enum(ssl_protocols, OSSL_NELEM(ssl_protocols), |
| &test_ctx->protocol, value); |
| } |
| |
| 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. */ |
| /*************************************************************/ |
| |
| typedef struct { |
| const char *name; |
| int (*parse)(SSL_TEST_CTX *test_ctx, const char *value); |
| } ssl_test_ctx_option; |
| |
| static const ssl_test_ctx_option ssl_test_ctx_options[] = { |
| { "ExpectedResult", &parse_expected_result }, |
| { "ClientAlert", &parse_client_alert }, |
| { "ServerAlert", &parse_server_alert }, |
| { "Protocol", &parse_protocol }, |
| { "ClientVerifyCallback", &parse_client_verify_callback }, |
| }; |
| |
| |
| /* |
| * Since these methods are used to create tests, we use OPENSSL_assert liberally |
| * for malloc failures and other internal errors. |
| */ |
| SSL_TEST_CTX *SSL_TEST_CTX_new() |
| { |
| SSL_TEST_CTX *ret; |
| ret = OPENSSL_zalloc(sizeof(*ret)); |
| OPENSSL_assert(ret != NULL); |
| return ret; |
| } |
| |
| void SSL_TEST_CTX_free(SSL_TEST_CTX *ctx) |
| { |
| OPENSSL_free(ctx); |
| } |
| |
| SSL_TEST_CTX *SSL_TEST_CTX_create(const CONF *conf, const char *test_section) |
| { |
| STACK_OF(CONF_VALUE) *sk_conf; |
| SSL_TEST_CTX *ctx; |
| int i; |
| size_t j; |
| |
| sk_conf = NCONF_get_section(conf, test_section); |
| OPENSSL_assert(sk_conf != NULL); |
| |
| ctx = SSL_TEST_CTX_new(); |
| OPENSSL_assert(ctx != NULL); |
| |
| for (i = 0; i < sk_CONF_VALUE_num(sk_conf); i++) { |
| int found = 0; |
| const CONF_VALUE *option = sk_CONF_VALUE_value(sk_conf, i); |
| for (j = 0; j < OSSL_NELEM(ssl_test_ctx_options); j++) { |
| if (strcmp(option->name, ssl_test_ctx_options[j].name) == 0) { |
| if (!ssl_test_ctx_options[j].parse(ctx, option->value)) { |
| fprintf(stderr, "Bad value %s for option %s\n", |
| option->value, option->name); |
| goto err; |
| } |
| found = 1; |
| break; |
| } |
| } |
| if (!found) { |
| fprintf(stderr, "Unknown test option: %s\n", option->name); |
| goto err; |
| } |
| } |
| |
| goto done; |
| |
| err: |
| SSL_TEST_CTX_free(ctx); |
| ctx = NULL; |
| done: |
| return ctx; |
| } |