1/* 2 * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the OpenSSL license (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10#include "test_config.h" 11 12#include <stdio.h> 13#include <stdlib.h> 14#include <string.h> 15 16#include <memory> 17 18#include <openssl/evp.h> 19 20namespace { 21 22template <typename T> 23struct Flag { 24 const char *flag; 25 T TestConfig::*member; 26}; 27 28// FindField looks for the flag in |flags| that matches |flag|. If one is found, 29// it returns a pointer to the corresponding field in |config|. Otherwise, it 30// returns NULL. 31template<typename T, size_t N> 32T *FindField(TestConfig *config, const Flag<T> (&flags)[N], const char *flag) { 33 for (size_t i = 0; i < N; i++) { 34 if (strcmp(flag, flags[i].flag) == 0) { 35 return &(config->*(flags[i].member)); 36 } 37 } 38 return NULL; 39} 40 41const Flag<bool> kBoolFlags[] = { 42 { "-server", &TestConfig::is_server }, 43 { "-dtls", &TestConfig::is_dtls }, 44 { "-fallback-scsv", &TestConfig::fallback_scsv }, 45 { "-require-any-client-certificate", 46 &TestConfig::require_any_client_certificate }, 47 { "-async", &TestConfig::async }, 48 { "-write-different-record-sizes", 49 &TestConfig::write_different_record_sizes }, 50 { "-partial-write", &TestConfig::partial_write }, 51 { "-no-tls13", &TestConfig::no_tls13 }, 52 { "-no-tls12", &TestConfig::no_tls12 }, 53 { "-no-tls11", &TestConfig::no_tls11 }, 54 { "-no-tls1", &TestConfig::no_tls1 }, 55 { "-no-ssl3", &TestConfig::no_ssl3 }, 56 { "-shim-writes-first", &TestConfig::shim_writes_first }, 57 { "-expect-session-miss", &TestConfig::expect_session_miss }, 58 { "-decline-alpn", &TestConfig::decline_alpn }, 59 { "-expect-extended-master-secret", 60 &TestConfig::expect_extended_master_secret }, 61 { "-implicit-handshake", &TestConfig::implicit_handshake }, 62 { "-handshake-never-done", &TestConfig::handshake_never_done }, 63 { "-use-export-context", &TestConfig::use_export_context }, 64 { "-expect-ticket-renewal", &TestConfig::expect_ticket_renewal }, 65 { "-expect-no-session", &TestConfig::expect_no_session }, 66 { "-use-ticket-callback", &TestConfig::use_ticket_callback }, 67 { "-renew-ticket", &TestConfig::renew_ticket }, 68 { "-enable-client-custom-extension", 69 &TestConfig::enable_client_custom_extension }, 70 { "-enable-server-custom-extension", 71 &TestConfig::enable_server_custom_extension }, 72 { "-custom-extension-skip", &TestConfig::custom_extension_skip }, 73 { "-custom-extension-fail-add", &TestConfig::custom_extension_fail_add }, 74 { "-check-close-notify", &TestConfig::check_close_notify }, 75 { "-shim-shuts-down", &TestConfig::shim_shuts_down }, 76 { "-verify-fail", &TestConfig::verify_fail }, 77 { "-verify-peer", &TestConfig::verify_peer }, 78 { "-expect-verify-result", &TestConfig::expect_verify_result }, 79 { "-renegotiate-freely", &TestConfig::renegotiate_freely }, 80 { "-p384-only", &TestConfig::p384_only }, 81 { "-enable-all-curves", &TestConfig::enable_all_curves }, 82 { "-use-sparse-dh-prime", &TestConfig::use_sparse_dh_prime }, 83 { "-use-old-client-cert-callback", 84 &TestConfig::use_old_client_cert_callback }, 85 { "-use-null-client-ca-list", &TestConfig::use_null_client_ca_list }, 86 { "-peek-then-read", &TestConfig::peek_then_read }, 87}; 88 89const Flag<std::string> kStringFlags[] = { 90 { "-key-file", &TestConfig::key_file }, 91 { "-cert-file", &TestConfig::cert_file }, 92 { "-expect-server-name", &TestConfig::expected_server_name }, 93 { "-advertise-npn", &TestConfig::advertise_npn }, 94 { "-expect-next-proto", &TestConfig::expected_next_proto }, 95 { "-select-next-proto", &TestConfig::select_next_proto }, 96 { "-host-name", &TestConfig::host_name }, 97 { "-advertise-alpn", &TestConfig::advertise_alpn }, 98 { "-expect-alpn", &TestConfig::expected_alpn }, 99 { "-expect-advertised-alpn", &TestConfig::expected_advertised_alpn }, 100 { "-select-alpn", &TestConfig::select_alpn }, 101 { "-psk", &TestConfig::psk }, 102 { "-psk-identity", &TestConfig::psk_identity }, 103 { "-srtp-profiles", &TestConfig::srtp_profiles }, 104 { "-cipher", &TestConfig::cipher }, 105 { "-export-label", &TestConfig::export_label }, 106 { "-export-context", &TestConfig::export_context }, 107}; 108 109const Flag<std::string> kBase64Flags[] = { 110 { "-expect-certificate-types", &TestConfig::expected_certificate_types }, 111}; 112 113const Flag<int> kIntFlags[] = { 114 { "-port", &TestConfig::port }, 115 { "-resume-count", &TestConfig::resume_count }, 116 { "-min-version", &TestConfig::min_version }, 117 { "-max-version", &TestConfig::max_version }, 118 { "-mtu", &TestConfig::mtu }, 119 { "-export-keying-material", &TestConfig::export_keying_material }, 120 { "-expect-total-renegotiations", &TestConfig::expect_total_renegotiations }, 121 { "-max-cert-list", &TestConfig::max_cert_list }, 122}; 123 124} // namespace 125 126bool ParseConfig(int argc, char **argv, TestConfig *out_config) { 127 for (int i = 0; i < argc; i++) { 128 bool *bool_field = FindField(out_config, kBoolFlags, argv[i]); 129 if (bool_field != NULL) { 130 *bool_field = true; 131 continue; 132 } 133 134 std::string *string_field = FindField(out_config, kStringFlags, argv[i]); 135 if (string_field != NULL) { 136 const char *val; 137 138 i++; 139 if (i >= argc) { 140 fprintf(stderr, "Missing parameter\n"); 141 return false; 142 } 143 144 /* 145 * Fix up the -cipher argument. runner uses "DEFAULT:NULL-SHA" to enable 146 * the NULL-SHA cipher. However in OpenSSL "DEFAULT" permanently switches 147 * off NULL ciphers, so we use "ALL:NULL-SHA" instead. 148 */ 149 if (strcmp(argv[i - 1], "-cipher") == 0 150 && strcmp(argv[i], "DEFAULT:NULL-SHA") == 0) 151 val = "ALL:NULL-SHA"; 152 else 153 val = argv[i]; 154 155 string_field->assign(val); 156 continue; 157 } 158 159 std::string *base64_field = FindField(out_config, kBase64Flags, argv[i]); 160 if (base64_field != NULL) { 161 i++; 162 if (i >= argc) { 163 fprintf(stderr, "Missing parameter\n"); 164 return false; 165 } 166 std::unique_ptr<uint8_t[]> decoded(new uint8_t[strlen(argv[i])]); 167 int len = EVP_DecodeBlock(decoded.get(), 168 reinterpret_cast<const uint8_t *>(argv[i]), 169 strlen(argv[i])); 170 if (len < 0) { 171 fprintf(stderr, "Invalid base64: %s\n", argv[i]); 172 return false; 173 } 174 base64_field->assign(reinterpret_cast<const char *>(decoded.get()), len); 175 continue; 176 } 177 178 int *int_field = FindField(out_config, kIntFlags, argv[i]); 179 if (int_field) { 180 i++; 181 if (i >= argc) { 182 fprintf(stderr, "Missing parameter\n"); 183 return false; 184 } 185 *int_field = atoi(argv[i]); 186 continue; 187 } 188 189 fprintf(stderr, "Unknown argument: %s\n", argv[i]); 190 exit(89); 191 return false; 192 } 193 194 return true; 195} 196