您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 
 

255 行
7.4 KiB

  1. /* Copyright (c) 2014, Google Inc.
  2. *
  3. * Permission to use, copy, modify, and/or distribute this software for any
  4. * purpose with or without fee is hereby granted, provided that the above
  5. * copyright notice and this permission notice appear in all copies.
  6. *
  7. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  8. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  9. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  10. * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  11. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  12. * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  13. * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
  14. #include <openssl/base.h>
  15. #include <openssl/err.h>
  16. #include <openssl/pem.h>
  17. #include <openssl/ssl.h>
  18. #include "../crypto/test/scoped_types.h"
  19. #include "../ssl/test/scoped_types.h"
  20. #include "internal.h"
  21. #include "transport_common.h"
  22. static const struct argument kArguments[] = {
  23. {
  24. "-connect", kRequiredArgument,
  25. "The hostname and port of the server to connect to, e.g. foo.com:443",
  26. },
  27. {
  28. "-cipher", kOptionalArgument,
  29. "An OpenSSL-style cipher suite string that configures the offered ciphers",
  30. },
  31. {
  32. "-max-version", kOptionalArgument,
  33. "The maximum acceptable protocol version",
  34. },
  35. {
  36. "-min-version", kOptionalArgument,
  37. "The minimum acceptable protocol version",
  38. },
  39. {
  40. "-server-name", kOptionalArgument,
  41. "The server name to advertise",
  42. },
  43. {
  44. "-select-next-proto", kOptionalArgument,
  45. "An NPN protocol to select if the server supports NPN",
  46. },
  47. {
  48. "-alpn-protos", kOptionalArgument,
  49. "A comma-separated list of ALPN protocols to advertise",
  50. },
  51. {
  52. "-fallback-scsv", kBooleanArgument,
  53. "Enable FALLBACK_SCSV",
  54. },
  55. {
  56. "-ocsp-stapling", kBooleanArgument,
  57. "Advertise support for OCSP stabling",
  58. },
  59. {
  60. "-signed-certificate-timestamps", kBooleanArgument,
  61. "Advertise support for signed certificate timestamps",
  62. },
  63. {
  64. "-channel-id-key", kOptionalArgument,
  65. "The key to use for signing a channel ID",
  66. },
  67. {
  68. "-false-start", kBooleanArgument,
  69. "Enable False Start",
  70. },
  71. {
  72. "", kOptionalArgument, "",
  73. },
  74. };
  75. static ScopedEVP_PKEY LoadPrivateKey(const std::string &file) {
  76. ScopedBIO bio(BIO_new(BIO_s_file()));
  77. if (!bio || !BIO_read_filename(bio.get(), file.c_str())) {
  78. return nullptr;
  79. }
  80. ScopedEVP_PKEY pkey(PEM_read_bio_PrivateKey(bio.get(), nullptr, nullptr,
  81. nullptr));
  82. return pkey;
  83. }
  84. static bool VersionFromString(uint16_t *out_version,
  85. const std::string& version) {
  86. if (version == "ssl3") {
  87. *out_version = SSL3_VERSION;
  88. return true;
  89. } else if (version == "tls1" || version == "tls1.0") {
  90. *out_version = TLS1_VERSION;
  91. return true;
  92. } else if (version == "tls1.1") {
  93. *out_version = TLS1_1_VERSION;
  94. return true;
  95. } else if (version == "tls1.2") {
  96. *out_version = TLS1_2_VERSION;
  97. return true;
  98. }
  99. return false;
  100. }
  101. static int NextProtoSelectCallback(SSL* ssl, uint8_t** out, uint8_t* outlen,
  102. const uint8_t* in, unsigned inlen, void* arg) {
  103. *out = reinterpret_cast<uint8_t *>(arg);
  104. *outlen = strlen(reinterpret_cast<const char *>(arg));
  105. return SSL_TLSEXT_ERR_OK;
  106. }
  107. bool Client(const std::vector<std::string> &args) {
  108. if (!InitSocketLibrary()) {
  109. return false;
  110. }
  111. std::map<std::string, std::string> args_map;
  112. if (!ParseKeyValueArguments(&args_map, args, kArguments)) {
  113. PrintUsage(kArguments);
  114. return false;
  115. }
  116. ScopedSSL_CTX ctx(SSL_CTX_new(SSLv23_client_method()));
  117. const char *keylog_file = getenv("SSLKEYLOGFILE");
  118. if (keylog_file) {
  119. BIO *keylog_bio = BIO_new_file(keylog_file, "a");
  120. if (!keylog_bio) {
  121. ERR_print_errors_cb(PrintErrorCallback, stderr);
  122. return false;
  123. }
  124. SSL_CTX_set_keylog_bio(ctx.get(), keylog_bio);
  125. }
  126. if (args_map.count("-cipher") != 0 &&
  127. !SSL_CTX_set_cipher_list(ctx.get(), args_map["-cipher"].c_str())) {
  128. fprintf(stderr, "Failed setting cipher list\n");
  129. return false;
  130. }
  131. if (args_map.count("-max-version") != 0) {
  132. uint16_t version;
  133. if (!VersionFromString(&version, args_map["-max-version"])) {
  134. fprintf(stderr, "Unknown protocol version: '%s'\n",
  135. args_map["-max-version"].c_str());
  136. return false;
  137. }
  138. SSL_CTX_set_max_version(ctx.get(), version);
  139. }
  140. if (args_map.count("-min-version") != 0) {
  141. uint16_t version;
  142. if (!VersionFromString(&version, args_map["-min-version"])) {
  143. fprintf(stderr, "Unknown protocol version: '%s'\n",
  144. args_map["-min-version"].c_str());
  145. return false;
  146. }
  147. SSL_CTX_set_min_version(ctx.get(), version);
  148. }
  149. if (args_map.count("-select-next-proto") != 0) {
  150. const std::string &proto = args_map["-select-next-proto"];
  151. if (proto.size() > 255) {
  152. fprintf(stderr, "Bad NPN protocol: '%s'\n", proto.c_str());
  153. return false;
  154. }
  155. // |SSL_CTX_set_next_proto_select_cb| is not const-correct.
  156. SSL_CTX_set_next_proto_select_cb(ctx.get(), NextProtoSelectCallback,
  157. const_cast<char *>(proto.c_str()));
  158. }
  159. if (args_map.count("-alpn-protos") != 0) {
  160. const std::string &alpn_protos = args_map["-alpn-protos"];
  161. std::vector<uint8_t> wire;
  162. size_t i = 0;
  163. while (i <= alpn_protos.size()) {
  164. size_t j = alpn_protos.find(',', i);
  165. if (j == std::string::npos) {
  166. j = alpn_protos.size();
  167. }
  168. size_t len = j - i;
  169. if (len > 255) {
  170. fprintf(stderr, "Invalid ALPN protocols: '%s'\n", alpn_protos.c_str());
  171. return false;
  172. }
  173. wire.push_back(static_cast<uint8_t>(len));
  174. wire.resize(wire.size() + len);
  175. memcpy(wire.data() + wire.size() - len, alpn_protos.data() + i, len);
  176. i = j + 1;
  177. }
  178. if (SSL_CTX_set_alpn_protos(ctx.get(), wire.data(), wire.size()) != 0) {
  179. return false;
  180. }
  181. }
  182. if (args_map.count("-fallback-scsv") != 0) {
  183. SSL_CTX_set_mode(ctx.get(), SSL_MODE_SEND_FALLBACK_SCSV);
  184. }
  185. if (args_map.count("-ocsp-stapling") != 0) {
  186. SSL_CTX_enable_ocsp_stapling(ctx.get());
  187. }
  188. if (args_map.count("-signed-certificate-timestamps") != 0) {
  189. SSL_CTX_enable_signed_cert_timestamps(ctx.get());
  190. }
  191. if (args_map.count("-channel-id-key") != 0) {
  192. ScopedEVP_PKEY pkey = LoadPrivateKey(args_map["-channel-id-key"]);
  193. if (!pkey || !SSL_CTX_set1_tls_channel_id(ctx.get(), pkey.get())) {
  194. return false;
  195. }
  196. ctx->tlsext_channel_id_enabled_new = 1;
  197. }
  198. if (args_map.count("-false-start") != 0) {
  199. SSL_CTX_set_mode(ctx.get(), SSL_MODE_ENABLE_FALSE_START);
  200. }
  201. int sock = -1;
  202. if (!Connect(&sock, args_map["-connect"])) {
  203. return false;
  204. }
  205. ScopedBIO bio(BIO_new_socket(sock, BIO_CLOSE));
  206. ScopedSSL ssl(SSL_new(ctx.get()));
  207. if (args_map.count("-server-name") != 0) {
  208. SSL_set_tlsext_host_name(ssl.get(), args_map["-server-name"].c_str());
  209. }
  210. SSL_set_bio(ssl.get(), bio.get(), bio.get());
  211. bio.release();
  212. int ret = SSL_connect(ssl.get());
  213. if (ret != 1) {
  214. int ssl_err = SSL_get_error(ssl.get(), ret);
  215. fprintf(stderr, "Error while connecting: %d\n", ssl_err);
  216. ERR_print_errors_cb(PrintErrorCallback, stderr);
  217. return false;
  218. }
  219. fprintf(stderr, "Connected.\n");
  220. PrintConnectionInfo(ssl.get());
  221. bool ok = TransferData(ssl.get(), sock);
  222. return ok;
  223. }