1 // 2 // Copyright 2021 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 17 #ifndef GRPCPP_SECURITY_TLS_CERTIFICATE_VERIFIER_H 18 #define GRPCPP_SECURITY_TLS_CERTIFICATE_VERIFIER_H 19 20 #include <grpc/grpc_security_constants.h> 21 #include <grpc/status.h> 22 #include <grpcpp/impl/grpc_library.h> 23 #include <grpcpp/impl/sync.h> 24 #include <grpcpp/support/config.h> 25 #include <grpcpp/support/status.h> 26 #include <grpcpp/support/string_ref.h> 27 28 #include <functional> 29 #include <map> 30 #include <memory> 31 #include <utility> 32 #include <vector> 33 34 // TODO(yihuazhang): remove the forward declaration here and include 35 // <grpc/grpc_security.h> directly once the insecure builds are cleaned up. 36 typedef struct grpc_tls_custom_verification_check_request 37 grpc_tls_custom_verification_check_request; 38 typedef struct grpc_tls_certificate_verifier grpc_tls_certificate_verifier; 39 typedef struct grpc_tls_certificate_verifier_external 40 grpc_tls_certificate_verifier_external; 41 typedef void (*grpc_tls_on_custom_verification_check_done_cb)( 42 grpc_tls_custom_verification_check_request* request, void* callback_arg, 43 grpc_status_code status, const char* error_details); 44 extern "C" grpc_tls_certificate_verifier* 45 grpc_tls_certificate_verifier_external_create( 46 grpc_tls_certificate_verifier_external* external_verifier); 47 48 namespace grpc { 49 namespace experimental { 50 51 // Contains the verification-related information associated with a connection 52 // request. Users should not directly create or destroy this request object, but 53 // shall interact with it through CertificateVerifier's Verify() and Cancel(). 54 class TlsCustomVerificationCheckRequest { 55 public: 56 explicit TlsCustomVerificationCheckRequest( 57 grpc_tls_custom_verification_check_request* request); ~TlsCustomVerificationCheckRequest()58 ~TlsCustomVerificationCheckRequest() {} 59 60 grpc::string_ref target_name() const; 61 grpc::string_ref peer_cert() const; 62 grpc::string_ref peer_cert_full_chain() const; 63 grpc::string_ref common_name() const; 64 // The subject name of the root certificate used to verify the peer chain 65 // If verification fails or the peer cert is self-signed, this will be an 66 // empty string. If verification is successful, it is a comma-separated list, 67 // where the entries are of the form "FIELD_ABBREVIATION=string" 68 // ex: "CN=testca,O=Internet Widgits Pty Ltd,ST=Some-State,C=AU" 69 // ex: "CN=GTS Root R1,O=Google Trust Services LLC,C=US" 70 grpc::string_ref verified_root_cert_subject() const; 71 std::vector<grpc::string_ref> uri_names() const; 72 std::vector<grpc::string_ref> dns_names() const; 73 std::vector<grpc::string_ref> email_names() const; 74 std::vector<grpc::string_ref> ip_names() const; 75 c_request()76 grpc_tls_custom_verification_check_request* c_request() { return c_request_; } 77 78 private: 79 grpc_tls_custom_verification_check_request* c_request_ = nullptr; 80 }; 81 82 // The base class of all internal verifier implementations, and the ultimate 83 // class that all external verifiers will eventually be transformed into. 84 // To implement a custom verifier, do not extend this class; instead, 85 // implement a subclass of ExternalCertificateVerifier. Note that custom 86 // verifier implementations can compose their functionality with existing 87 // implementations of this interface, such as HostnameVerifier, by delegating 88 // to an instance of that class. 89 class CertificateVerifier { 90 public: 91 explicit CertificateVerifier(grpc_tls_certificate_verifier* v); 92 93 ~CertificateVerifier(); 94 95 // Verifies a connection request, based on the logic specified in an internal 96 // verifier. The check on each internal verifier could be either synchronous 97 // or asynchronous, and we will need to use return value to know. 98 // 99 // request: the verification information associated with this request 100 // callback: This will only take effect if the verifier is asynchronous. 101 // The function that gRPC will invoke when the verifier has already 102 // completed its asynchronous check. Callers can use this function 103 // to perform any additional checks. The input parameter of the 104 // std::function indicates the status of the verifier check. 105 // sync_status: This will only be useful if the verifier is synchronous. 106 // The status of the verifier as it has already done it's 107 // synchronous check. 108 // return: return true if executed synchronously, otherwise return false 109 bool Verify(TlsCustomVerificationCheckRequest* request, 110 std::function<void(grpc::Status)> callback, 111 grpc::Status* sync_status); 112 113 // Cancels a verification request previously started via Verify(). 114 // Used when the connection attempt times out or is cancelled while an async 115 // verification request is pending. 116 // 117 // request: the verification information associated with this request 118 void Cancel(TlsCustomVerificationCheckRequest* request); 119 120 // Gets the core verifier used internally. c_verifier()121 grpc_tls_certificate_verifier* c_verifier() { return verifier_; } 122 123 private: 124 static void AsyncCheckDone( 125 grpc_tls_custom_verification_check_request* request, void* callback_arg, 126 grpc_status_code status, const char* error_details); 127 128 grpc_tls_certificate_verifier* verifier_ = nullptr; 129 grpc::internal::Mutex mu_; 130 std::map<grpc_tls_custom_verification_check_request*, 131 std::function<void(grpc::Status)>> 132 request_map_ ABSL_GUARDED_BY(mu_); 133 }; 134 135 // The base class of all external, user-specified verifiers. Users should 136 // inherit this class to implement a custom verifier. 137 // Note that while implementing the custom verifier that extends this class, it 138 // is possible to compose an existing ExternalCertificateVerifier or 139 // CertificateVerifier, inside the Verify() and Cancel() function of the new 140 // custom verifier. 141 class ExternalCertificateVerifier { 142 public: 143 // A factory method for creating a |CertificateVerifier| from this class. All 144 // the user-implemented verifiers should use this function to be converted to 145 // verifiers compatible with |TlsCredentialsOptions|. 146 // The resulting CertificateVerifier takes ownership of the newly instantiated 147 // Subclass. 148 template <typename Subclass, typename... Args> Create(Args &&...args)149 static std::shared_ptr<CertificateVerifier> Create(Args&&... args) { 150 auto* external_verifier = new Subclass(std::forward<Args>(args)...); 151 return std::make_shared<CertificateVerifier>( 152 grpc_tls_certificate_verifier_external_create( 153 external_verifier->base_)); 154 } 155 156 // The verification logic that will be performed after the TLS handshake 157 // completes. Implementers can choose to do their checks synchronously or 158 // asynchronously. 159 // 160 // request: the verification information associated with this request 161 // callback: This should only be used if your check is done asynchronously. 162 // When the asynchronous work is done, invoke this callback function 163 // with the proper status, indicating the success or the failure of 164 // the check. The implementer MUST NOT invoke this |callback| in the 165 // same thread before Verify() returns, otherwise it can lead to 166 // deadlocks. 167 // sync_status: This should only be used if your check is done synchronously. 168 // Modifies this value to indicate the success or the failure of 169 // the check. 170 // return: return true if your check is done synchronously, otherwise return 171 // false 172 virtual bool Verify(TlsCustomVerificationCheckRequest* request, 173 std::function<void(grpc::Status)> callback, 174 grpc::Status* sync_status) = 0; 175 176 // Cancels a verification request previously started via Verify(). 177 // Used when the connection attempt times out or is cancelled while an async 178 // verification request is pending. The implementation should abort whatever 179 // async operation it is waiting for and quickly invoke the callback that was 180 // passed to Verify() with a status indicating the cancellation. 181 // 182 // request: the verification information associated with this request 183 virtual void Cancel(TlsCustomVerificationCheckRequest* request) = 0; 184 185 protected: 186 ExternalCertificateVerifier(); 187 188 virtual ~ExternalCertificateVerifier(); 189 190 private: 191 struct AsyncRequestState { AsyncRequestStateAsyncRequestState192 AsyncRequestState(grpc_tls_on_custom_verification_check_done_cb cb, 193 void* arg, 194 grpc_tls_custom_verification_check_request* request) 195 : callback(cb), callback_arg(arg), cpp_request(request) {} 196 197 grpc_tls_on_custom_verification_check_done_cb callback; 198 void* callback_arg; 199 TlsCustomVerificationCheckRequest cpp_request; 200 }; 201 202 static int VerifyInCoreExternalVerifier( 203 void* user_data, grpc_tls_custom_verification_check_request* request, 204 grpc_tls_on_custom_verification_check_done_cb callback, 205 void* callback_arg, grpc_status_code* sync_status, 206 char** sync_error_details); 207 208 static void CancelInCoreExternalVerifier( 209 void* user_data, grpc_tls_custom_verification_check_request* request); 210 211 static void DestructInCoreExternalVerifier(void* user_data); 212 213 // TODO(yihuazhang): after the insecure build is removed, make this an object 214 // member instead of a pointer. 215 grpc_tls_certificate_verifier_external* base_ = nullptr; 216 grpc::internal::Mutex mu_; 217 std::map<grpc_tls_custom_verification_check_request*, AsyncRequestState> 218 request_map_ ABSL_GUARDED_BY(mu_); 219 }; 220 221 // A CertificateVerifier that doesn't perform any additional checks other than 222 // certificate verification, if specified. 223 // Note: using this solely without any other authentication mechanisms on the 224 // peer identity will leave your applications to the MITM(Man-In-The-Middle) 225 // attacks. Users should avoid doing so in production environments. 226 class NoOpCertificateVerifier : public CertificateVerifier { 227 public: 228 NoOpCertificateVerifier(); 229 }; 230 231 // A CertificateVerifier that will perform hostname verification, to see if the 232 // target name set from the client side matches the identity information 233 // specified on the server's certificate. 234 class HostNameCertificateVerifier : public CertificateVerifier { 235 public: 236 HostNameCertificateVerifier(); 237 }; 238 239 } // namespace experimental 240 } // namespace grpc 241 242 #endif // GRPCPP_SECURITY_TLS_CERTIFICATE_VERIFIER_H 243