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