Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
253 changes: 253 additions & 0 deletions thirdparty/patches/brpc-zz-user-verify-callback-userdata.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
diff --git a/src/brpc/details/mesalink_ssl_helper.cpp b/src/brpc/details/mesalink_ssl_helper.cpp
index afc3861359b13ec173c6d39257f3b0bc1ec27334..c2ce824ce7bbaf2c0c1d39767c5950c5555f58d3 100644
--- a/src/brpc/details/mesalink_ssl_helper.cpp
+++ b/src/brpc/details/mesalink_ssl_helper.cpp
@@ -45,6 +45,72 @@ static bool IsPemString(const std::string& input) {
return false;
}

+struct VerifyCallbackWrapper {
+ SSLVerifyCallback callback;
+ void* userdata;
+};
+
+static void FreeVerifyCallbackWrapper(void* parent, void* ptr,
+ CRYPTO_EX_DATA* ad, int idx,
+ long argl, void* argp) {
+ delete static_cast<VerifyCallbackWrapper*>(ptr);
+}
+
+static int GetVerifyCallbackWrapperIndex() {
+ static int index = SSL_CTX_get_ex_new_index(
+ 0, const_cast<char*>("brpc_ssl_verify_cb"),
+ NULL, NULL, FreeVerifyCallbackWrapper);
+ return index;
+}
+
+static VerifyCallbackWrapper* GetVerifyCallbackWrapper(SSL_CTX* ctx) {
+ const int index = GetVerifyCallbackWrapperIndex();
+ if (index < 0) {
+ return NULL;
+ }
+ return static_cast<VerifyCallbackWrapper*>(SSL_CTX_get_ex_data(ctx, index));
+}
+
+static int SetVerifyCallbackWrapper(SSL_CTX* ctx,
+ SSLVerifyCallback callback,
+ void* userdata) {
+ const int index = GetVerifyCallbackWrapperIndex();
+ if (index < 0) {
+ LOG(ERROR) << "Fail to get SSL_CTX ex data index for verify callback";
+ return -1;
+ }
+ VerifyCallbackWrapper* wrapper = new (std::nothrow) VerifyCallbackWrapper();
+ if (wrapper == NULL) {
+ LOG(ERROR) << "Fail to allocate verify callback wrapper";
+ return -1;
+ }
+ wrapper->callback = callback;
+ wrapper->userdata = userdata;
+ if (SSL_CTX_set_ex_data(ctx, index, wrapper) != 1) {
+ delete wrapper;
+ LOG(ERROR) << "Fail to set SSL_CTX ex data for verify callback";
+ return -1;
+ }
+ return 0;
+}
+
+static int SSLVerifyCallbackProxy(int preverify_ok, X509_STORE_CTX* store_ctx) {
+ SSL* ssl = static_cast<SSL*>(X509_STORE_CTX_get_ex_data(
+ store_ctx, SSL_get_ex_data_X509_STORE_CTX_idx()));
+ if (ssl == NULL) {
+ return preverify_ok;
+ }
+ SSL_CTX* ctx = SSL_get_SSL_CTX(ssl);
+ if (ctx == NULL) {
+ return preverify_ok;
+ }
+ VerifyCallbackWrapper* wrapper = GetVerifyCallbackWrapper(ctx);
+ if (wrapper == NULL || wrapper->callback == NULL) {
+ return preverify_ok;
+ }
+ return wrapper->callback(preverify_ok, store_ctx, wrapper->userdata);
+}
+
const char* SSLStateToString(SSLState s) {
switch (s) {
case SSL_UNKNOWN:
@@ -249,8 +315,16 @@ static int SetSSLOptions(SSL_CTX* ctx, const std::string& ciphers,
return -1;
}
}
- SSL_CTX_set_verify(ctx, (SSL_VERIFY_PEER
- | SSL_VERIFY_FAIL_IF_NO_PEER_CERT), NULL);
+ const int verify_mode = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
+ if (verify.verify_callback != NULL) {
+ if (SetVerifyCallbackWrapper(ctx, verify.verify_callback,
+ verify.verify_userdata) != 0) {
+ return -1;
+ }
+ SSL_CTX_set_verify(ctx, verify_mode, SSLVerifyCallbackProxy);
+ } else {
+ SSL_CTX_set_verify(ctx, verify_mode, NULL);
+ }
} else {
SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
}
diff --git a/src/brpc/details/ssl_helper.cpp b/src/brpc/details/ssl_helper.cpp
index 81460aa99c4fb9b3bcd28be462d3b1b399a951e5..77e3cba731df97b134faf58d2c4a3b8eb6fdf036 100644
--- a/src/brpc/details/ssl_helper.cpp
+++ b/src/brpc/details/ssl_helper.cpp
@@ -51,6 +51,72 @@ static bool IsPemString(const std::string& input) {
return false;
}

+struct VerifyCallbackWrapper {
+ SSLVerifyCallback callback;
+ void* userdata;
+};
+
+static void FreeVerifyCallbackWrapper(void* parent, void* ptr,
+ CRYPTO_EX_DATA* ad, int idx,
+ long argl, void* argp) {
+ delete static_cast<VerifyCallbackWrapper*>(ptr);
+}
+
+static int GetVerifyCallbackWrapperIndex() {
+ static int index = SSL_CTX_get_ex_new_index(
+ 0, const_cast<char*>("brpc_ssl_verify_cb"),
+ NULL, NULL, FreeVerifyCallbackWrapper);
+ return index;
+}
+
+static VerifyCallbackWrapper* GetVerifyCallbackWrapper(SSL_CTX* ctx) {
+ const int index = GetVerifyCallbackWrapperIndex();
+ if (index < 0) {
+ return NULL;
+ }
+ return static_cast<VerifyCallbackWrapper*>(SSL_CTX_get_ex_data(ctx, index));
+}
+
+static int SetVerifyCallbackWrapper(SSL_CTX* ctx,
+ SSLVerifyCallback callback,
+ void* userdata) {
+ const int index = GetVerifyCallbackWrapperIndex();
+ if (index < 0) {
+ LOG(ERROR) << "Fail to get SSL_CTX ex data index for verify callback";
+ return -1;
+ }
+ VerifyCallbackWrapper* wrapper = new (std::nothrow) VerifyCallbackWrapper();
+ if (wrapper == NULL) {
+ LOG(ERROR) << "Fail to allocate verify callback wrapper";
+ return -1;
+ }
+ wrapper->callback = callback;
+ wrapper->userdata = userdata;
+ if (SSL_CTX_set_ex_data(ctx, index, wrapper) != 1) {
+ delete wrapper;
+ LOG(ERROR) << "Fail to set SSL_CTX ex data for verify callback";
+ return -1;
+ }
+ return 0;
+}
+
+static int SSLVerifyCallbackProxy(int preverify_ok, X509_STORE_CTX* store_ctx) {
+ SSL* ssl = static_cast<SSL*>(X509_STORE_CTX_get_ex_data(
+ store_ctx, SSL_get_ex_data_X509_STORE_CTX_idx()));
+ if (ssl == NULL) {
+ return preverify_ok;
+ }
+ SSL_CTX* ctx = SSL_get_SSL_CTX(ssl);
+ if (ctx == NULL) {
+ return preverify_ok;
+ }
+ VerifyCallbackWrapper* wrapper = GetVerifyCallbackWrapper(ctx);
+ if (wrapper == NULL || wrapper->callback == NULL) {
+ return preverify_ok;
+ }
+ return wrapper->callback(preverify_ok, store_ctx, wrapper->userdata);
+}
+
const char* SSLStateToString(SSLState s) {
switch (s) {
case SSL_UNKNOWN:
@@ -411,8 +477,16 @@ static int SetSSLOptions(SSL_CTX* ctx, const std::string& ciphers,

// TODO: Verify the CNAME in certificate matches the requesting host
if (verify.verify_depth > 0) {
- SSL_CTX_set_verify(ctx, (SSL_VERIFY_PEER
- | SSL_VERIFY_FAIL_IF_NO_PEER_CERT), NULL);
+ const int verify_mode = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
+ int (*verify_cb)(int, X509_STORE_CTX*) = NULL;
+ if (verify.verify_callback != NULL) {
+ if (SetVerifyCallbackWrapper(ctx, verify.verify_callback,
+ verify.verify_userdata) != 0) {
+ return -1;
+ }
+ verify_cb = SSLVerifyCallbackProxy;
+ }
+ SSL_CTX_set_verify(ctx, verify_mode, verify_cb);
SSL_CTX_set_verify_depth(ctx, verify.verify_depth);
std::string cafile = verify.ca_file_path;
if (cafile.empty()) {
diff --git a/src/brpc/details/ssl_helper.h b/src/brpc/details/ssl_helper.h
index 4f1e55b253b034e8a0d8a49b95cd456dd16bb4fc..23412cceb81427e4b46a175f3a8b5bf252ff4524 100644
--- a/src/brpc/details/ssl_helper.h
+++ b/src/brpc/details/ssl_helper.h
@@ -19,6 +19,7 @@
#ifndef BRPC_SSL_HELPER_H
#define BRPC_SSL_HELPER_H

+#include <new>
#include <string.h>
#ifndef USE_MESALINK
#include <openssl/ssl.h>
diff --git a/src/brpc/ssl_options.cpp b/src/brpc/ssl_options.cpp
index e3b8f5b184fb83f1d036b44d6a0c1365490373a7..0c952a7b68f249a914bc55084b9771a0737538f3 100644
--- a/src/brpc/ssl_options.cpp
+++ b/src/brpc/ssl_options.cpp
@@ -20,7 +20,10 @@

namespace brpc {

-VerifyOptions::VerifyOptions() : verify_depth(0) {}
+VerifyOptions::VerifyOptions()
+ : verify_depth(0)
+ , verify_callback(NULL)
+ , verify_userdata(NULL) {}

ChannelSSLOptions::ChannelSSLOptions()
: ciphers("DEFAULT")
diff --git a/src/brpc/ssl_options.h b/src/brpc/ssl_options.h
index 4e5d19c0c0fa2c3ddabbb7c987f7d60673090894..ce43ad2e1d68f162e819cb30ebfb2406eaae95b8 100644
--- a/src/brpc/ssl_options.h
+++ b/src/brpc/ssl_options.h
@@ -22,8 +22,14 @@
#include <string>
#include <vector>

+struct x509_store_ctx_st;
+
namespace brpc {

+typedef int (*SSLVerifyCallback)(int preverify_ok,
+ x509_store_ctx_st* store_ctx,
+ void* userdata);
+
struct CertInfo {
// Certificate in PEM format.
// Note that CN and alt subjects will be extracted from the certificate,
@@ -54,6 +60,13 @@ struct VerifyOptions {
// If empty, use the system default CA files
// Default: ""
std::string ca_file_path;
+
+ // Optional user verify callback invoked during handshake.
+ // Return 1 to continue, 0 to fail.
+ SSLVerifyCallback verify_callback;
+
+ // Opaque pointer passed to verify_callback.
+ void* verify_userdata;
};

// SSL options at client side
Loading