TestTLSHandshake.cpp 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. /*
  2. * Copyright (c) 2021, Peter Bocan <me@pbocan.net>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/Base64.h>
  7. #include <LibCore/ConfigFile.h>
  8. #include <LibCore/EventLoop.h>
  9. #include <LibCrypto/ASN1/ASN1.h>
  10. #include <LibCrypto/ASN1/PEM.h>
  11. #include <LibFileSystem/FileSystem.h>
  12. #include <LibTLS/TLSv12.h>
  13. #include <LibTest/TestCase.h>
  14. static StringView ca_certs_file = "./cacert.pem"sv;
  15. static int port = 443;
  16. constexpr auto DEFAULT_SERVER = "www.google.com"sv;
  17. static ByteBuffer operator""_b(char const* string, size_t length)
  18. {
  19. return ByteBuffer::copy(string, length).release_value();
  20. }
  21. ErrorOr<Vector<Certificate>> load_certificates();
  22. DeprecatedString locate_ca_certs_file();
  23. DeprecatedString locate_ca_certs_file()
  24. {
  25. if (FileSystem::exists(ca_certs_file)) {
  26. return ca_certs_file;
  27. }
  28. auto on_target_path = DeprecatedString("/etc/cacert.pem");
  29. if (FileSystem::exists(on_target_path)) {
  30. return on_target_path;
  31. }
  32. return "";
  33. }
  34. ErrorOr<Vector<Certificate>> load_certificates()
  35. {
  36. auto cacert_file = TRY(Core::File::open(locate_ca_certs_file(), Core::File::OpenMode::Read));
  37. auto data = TRY(cacert_file->read_until_eof());
  38. return TRY(DefaultRootCACertificates::parse_pem_root_certificate_authorities(data));
  39. }
  40. TEST_CASE(test_TLS_hello_handshake)
  41. {
  42. Core::EventLoop loop;
  43. TLS::Options options;
  44. options.set_root_certificates(TRY_OR_FAIL(load_certificates()));
  45. options.set_alert_handler([&](TLS::AlertDescription) {
  46. FAIL("Connection failure");
  47. loop.quit(1);
  48. });
  49. options.set_finish_callback([&] {
  50. loop.quit(0);
  51. });
  52. auto tls = TRY_OR_FAIL(TLS::TLSv12::connect(DEFAULT_SERVER, port, move(options)));
  53. ByteBuffer contents;
  54. tls->on_ready_to_read = [&] {
  55. auto read_bytes = TRY_OR_FAIL(tls->read_some(contents.must_get_bytes_for_writing(4 * KiB)));
  56. if (read_bytes.is_empty()) {
  57. FAIL("No data received");
  58. loop.quit(1);
  59. }
  60. loop.quit(0);
  61. };
  62. if (tls->write_until_depleted("GET / HTTP/1.1\r\nHost: "_b).is_error()) {
  63. FAIL("write(0) failed");
  64. return;
  65. }
  66. auto the_server = DEFAULT_SERVER;
  67. if (tls->write_until_depleted(the_server.bytes()).is_error()) {
  68. FAIL("write(1) failed");
  69. return;
  70. }
  71. if (tls->write_until_depleted("\r\nConnection : close\r\n\r\n"_b).is_error()) {
  72. FAIL("write(2) failed");
  73. return;
  74. }
  75. loop.exec();
  76. }