tls_utils.cc 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. //
  2. // Copyright 2020 gRPC authors.
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. //
  16. #include "test/core/util/tls_utils.h"
  17. #include <grpc/support/log.h>
  18. #include "src/core/lib/gpr/tmpfile.h"
  19. #include "src/core/lib/iomgr/load_file.h"
  20. #include "src/core/lib/slice/slice_internal.h"
  21. namespace grpc_core {
  22. namespace testing {
  23. TmpFile::TmpFile(absl::string_view data) {
  24. name_ = CreateTmpFileAndWriteData(data);
  25. GPR_ASSERT(!name_.empty());
  26. }
  27. TmpFile::~TmpFile() { GPR_ASSERT(remove(name_.c_str()) == 0); }
  28. void TmpFile::RewriteFile(absl::string_view data) {
  29. // Create a new file containing new data.
  30. std::string new_name = CreateTmpFileAndWriteData(data);
  31. GPR_ASSERT(!new_name.empty());
  32. // Remove the old file.
  33. GPR_ASSERT(remove(name_.c_str()) == 0);
  34. // Rename the new file to the original name.
  35. GPR_ASSERT(rename(new_name.c_str(), name_.c_str()) == 0);
  36. }
  37. std::string TmpFile::CreateTmpFileAndWriteData(absl::string_view data) {
  38. char* name = nullptr;
  39. FILE* file_descriptor = gpr_tmpfile("test", &name);
  40. GPR_ASSERT(fwrite(data.data(), 1, data.size(), file_descriptor) ==
  41. data.size());
  42. GPR_ASSERT(fclose(file_descriptor) == 0);
  43. GPR_ASSERT(file_descriptor != nullptr);
  44. GPR_ASSERT(name != nullptr);
  45. std::string name_to_return = name;
  46. gpr_free(name);
  47. return name_to_return;
  48. }
  49. PemKeyCertPairList MakeCertKeyPairs(absl::string_view private_key,
  50. absl::string_view certs) {
  51. if (private_key.empty() && certs.empty()) {
  52. return {};
  53. }
  54. return PemKeyCertPairList{PemKeyCertPair(private_key, certs)};
  55. }
  56. std::string GetFileContents(const char* path) {
  57. grpc_slice slice = grpc_empty_slice();
  58. GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file", grpc_load_file(path, 0, &slice)));
  59. std::string data = std::string(StringViewFromSlice(slice));
  60. grpc_slice_unref(slice);
  61. return data;
  62. }
  63. int SyncExternalVerifier::Verify(void* user_data,
  64. grpc_tls_custom_verification_check_request*,
  65. grpc_tls_on_custom_verification_check_done_cb,
  66. void*, grpc_status_code* sync_status,
  67. char** sync_error_details) {
  68. auto* self = static_cast<SyncExternalVerifier*>(user_data);
  69. if (self->success_) {
  70. *sync_status = GRPC_STATUS_OK;
  71. return true; // Synchronous call
  72. }
  73. *sync_status = GRPC_STATUS_UNAUTHENTICATED;
  74. *sync_error_details = gpr_strdup("SyncExternalVerifier failed");
  75. return true; // Synchronous call
  76. }
  77. void SyncExternalVerifier::Destruct(void* user_data) {
  78. auto* self = static_cast<SyncExternalVerifier*>(user_data);
  79. delete self;
  80. }
  81. AsyncExternalVerifier::~AsyncExternalVerifier() {
  82. // Tell the thread to shut down.
  83. {
  84. MutexLock lock(&mu_);
  85. queue_.push_back(Request{nullptr, nullptr, nullptr, true});
  86. }
  87. // Wait for thread to exit.
  88. thread_.Join();
  89. grpc_shutdown();
  90. }
  91. int AsyncExternalVerifier::Verify(
  92. void* user_data, grpc_tls_custom_verification_check_request* request,
  93. grpc_tls_on_custom_verification_check_done_cb callback, void* callback_arg,
  94. grpc_status_code*, char**) {
  95. auto* self = static_cast<AsyncExternalVerifier*>(user_data);
  96. // Add request to queue to be picked up by worker thread.
  97. MutexLock lock(&self->mu_);
  98. self->queue_.push_back(Request{request, callback, callback_arg, false});
  99. return false; // Asynchronous call
  100. }
  101. namespace {
  102. void DestroyExternalVerifier(void* arg) {
  103. auto* verifier = static_cast<AsyncExternalVerifier*>(arg);
  104. delete verifier;
  105. }
  106. } // namespace
  107. void AsyncExternalVerifier::Destruct(void* user_data) {
  108. auto* self = static_cast<AsyncExternalVerifier*>(user_data);
  109. // Spawn a detached thread to destroy the verifier, to make sure that we don't
  110. // try to join the worker thread from within the worker thread.
  111. Thread destroy_thread("DestroyExternalVerifier", DestroyExternalVerifier,
  112. self, nullptr, Thread::Options().set_joinable(false));
  113. destroy_thread.Start();
  114. }
  115. void AsyncExternalVerifier::WorkerThread(void* arg) {
  116. auto* self = static_cast<AsyncExternalVerifier*>(arg);
  117. while (true) {
  118. // Check queue for work.
  119. bool got_request = false;
  120. Request request;
  121. {
  122. MutexLock lock(&self->mu_);
  123. if (!self->queue_.empty()) {
  124. got_request = true;
  125. request = self->queue_.front();
  126. self->queue_.pop_front();
  127. }
  128. }
  129. // If nothing found in the queue, sleep for a bit and try again.
  130. if (!got_request) {
  131. gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(100));
  132. continue;
  133. }
  134. // If we're being told to shut down, return.
  135. if (request.shutdown) {
  136. return;
  137. }
  138. // Process the request.
  139. if (self->success_) {
  140. request.callback(request.request, request.callback_arg, GRPC_STATUS_OK,
  141. "");
  142. } else {
  143. request.callback(request.request, request.callback_arg,
  144. GRPC_STATUS_UNAUTHENTICATED,
  145. "AsyncExternalVerifier failed");
  146. }
  147. }
  148. }
  149. } // namespace testing
  150. } // namespace grpc_core