| // | |
| // Copyright 2021 gRPC authors. | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // http://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| // | |
| #include "test/cpp/util/tls_test_utils.h" | |
| #include <memory> | |
| #include "src/core/lib/gprpp/thd.h" | |
| #include "test/core/util/port.h" | |
| #include "test/core/util/test_config.h" | |
| using ::grpc::experimental::TlsCustomVerificationCheckRequest; | |
| namespace grpc { | |
| namespace testing { | |
| bool SyncCertificateVerifier::Verify(TlsCustomVerificationCheckRequest*, | |
| std::function<void(grpc::Status)>, | |
| grpc::Status* sync_status) { | |
| if (!success_) { | |
| *sync_status = grpc::Status(grpc::StatusCode::UNAUTHENTICATED, | |
| "SyncCertificateVerifier failed"); | |
| } else { | |
| *sync_status = grpc::Status(grpc::StatusCode::OK, ""); | |
| } | |
| return true; | |
| } | |
| AsyncCertificateVerifier::AsyncCertificateVerifier(bool success) | |
| : success_(success), | |
| thread_("AsyncCertificateVerifierWorkerThread", WorkerThread, this) { | |
| thread_.Start(); | |
| } | |
| AsyncCertificateVerifier::~AsyncCertificateVerifier() { | |
| // Tell the thread to shut down. | |
| { | |
| internal::MutexLock lock(&mu_); | |
| queue_.push_back(Request{nullptr, nullptr, true}); | |
| } | |
| // Wait for thread to exit. | |
| thread_.Join(); | |
| } | |
| bool AsyncCertificateVerifier::Verify( | |
| TlsCustomVerificationCheckRequest* request, | |
| std::function<void(grpc::Status)> callback, grpc::Status*) { | |
| internal::MutexLock lock(&mu_); | |
| queue_.push_back(Request{request, std::move(callback), false}); | |
| return false; // Asynchronous call | |
| } | |
| void AsyncCertificateVerifier::WorkerThread(void* arg) { | |
| auto* self = static_cast<AsyncCertificateVerifier*>(arg); | |
| while (true) { | |
| // Check queue for work. | |
| bool got_request = false; | |
| Request request; | |
| { | |
| internal::MutexLock lock(&self->mu_); | |
| if (!self->queue_.empty()) { | |
| got_request = true; | |
| request = self->queue_.front(); | |
| self->queue_.pop_front(); | |
| } | |
| } | |
| // If nothing found in the queue, sleep for a bit and try again. | |
| if (!got_request) { | |
| gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(100)); | |
| continue; | |
| } | |
| // If we're being told to shut down, return. | |
| if (request.shutdown) return; | |
| auto return_status = grpc::Status(grpc::StatusCode::OK, ""); | |
| // Process the request. | |
| if (!self->success_) { | |
| return_status = grpc::Status(grpc::StatusCode::UNAUTHENTICATED, | |
| "AsyncCertificateVerifier failed"); | |
| } | |
| request.callback(return_status); | |
| } | |
| } | |
| bool VerifiedRootCertSubjectVerifier::Verify( | |
| TlsCustomVerificationCheckRequest* request, | |
| std::function<void(grpc::Status)>, grpc::Status* sync_status) { | |
| if (request->verified_root_cert_subject() != expected_subject_) { | |
| *sync_status = grpc::Status(grpc::StatusCode::UNAUTHENTICATED, | |
| "VerifiedRootCertSubjectVerifier failed"); | |
| } else { | |
| *sync_status = grpc::Status::OK; | |
| } | |
| return true; | |
| } | |
| } // namespace testing | |
| } // namespace grpc |