You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kudu.apache.org by al...@apache.org on 2022/10/22 15:58:30 UTC
[kudu] 02/02: [rpc] avoid crashes on malicious negotiation attempts
This is an automated email from the ASF dual-hosted git repository.
alexey pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/kudu.git
commit 64d033d58a5f8bbcaf0f7d7afa37c53d67872170
Author: Alexey Serbin <al...@apache.org>
AuthorDate: Wed Oct 19 16:20:34 2022 -0700
[rpc] avoid crashes on malicious negotiation attempts
This patch updates the code for RPC connection negotiation to change
from CHECK() to LOG(DFATAL) and Status::IllegalState() when checking on
some security constraint. This narrows the attack vector of potential
DOS attacks for Kudu servers.
Change-Id: I416e3e952a3ee928ed6c51389227184c73a96b0b
Reviewed-on: http://gerrit.cloudera.org:8080/19158
Tested-by: Kudu Jenkins
Reviewed-by: Yuqi Du <sh...@gmail.com>
Reviewed-by: Yingchun Lai <ac...@gmail.com>
---
src/kudu/rpc/client_negotiation.cc | 7 ++++++-
src/kudu/rpc/client_negotiation.h | 2 +-
src/kudu/rpc/server_negotiation.cc | 30 ++++++++++++++++++++++++------
3 files changed, 31 insertions(+), 8 deletions(-)
diff --git a/src/kudu/rpc/client_negotiation.cc b/src/kudu/rpc/client_negotiation.cc
index 6dcc26ab2..09c5357f6 100644
--- a/src/kudu/rpc/client_negotiation.cc
+++ b/src/kudu/rpc/client_negotiation.cc
@@ -545,7 +545,12 @@ Status ClientNegotiation::AuthenticateByToken(faststring* recv_buf,
unique_ptr<ErrorStatusPB>* rpc_error) {
// Sanity check that TLS has been negotiated. Sending the token on an
// unencrypted channel is a big no-no.
- CHECK(tls_negotiated_);
+ if (PREDICT_FALSE(!tls_negotiated_)) {
+ constexpr const char* const kErrMsg =
+ "received authn token over an unencrypted channel";
+ LOG(DFATAL) << kErrMsg;
+ return Status::IllegalState(kErrMsg);
+ }
// Send the token to the server.
NegotiatePB pb;
diff --git a/src/kudu/rpc/client_negotiation.h b/src/kudu/rpc/client_negotiation.h
index afaf7f068..4481bb59f 100644
--- a/src/kudu/rpc/client_negotiation.h
+++ b/src/kudu/rpc/client_negotiation.h
@@ -36,6 +36,7 @@
#include "kudu/rpc/sasl_helper.h"
#include "kudu/security/security_flags.h"
#include "kudu/security/tls_handshake.h"
+#include "kudu/security/token.pb.h"
#include "kudu/util/monotime.h"
#include "kudu/util/net/socket.h"
#include "kudu/util/status.h"
@@ -46,7 +47,6 @@ class Slice;
class faststring;
namespace security {
-class SignedTokenPB;
class TlsContext;
}
diff --git a/src/kudu/rpc/server_negotiation.cc b/src/kudu/rpc/server_negotiation.cc
index 6e5c5f929..332a30534 100644
--- a/src/kudu/rpc/server_negotiation.cc
+++ b/src/kudu/rpc/server_negotiation.cc
@@ -654,10 +654,15 @@ Status ServerNegotiation::AuthenticateBySasl(faststring* recv_buf) {
RETURN_NOT_OK(s);
const char* c_username = nullptr;
- int rc = sasl_getprop(sasl_conn_.get(), SASL_USERNAME,
- reinterpret_cast<const void**>(&c_username));
+ const int rc = sasl_getprop(sasl_conn_.get(), SASL_USERNAME,
+ reinterpret_cast<const void**>(&c_username));
// We expect that SASL_USERNAME will always get set.
- CHECK(rc == SASL_OK && c_username != nullptr) << "No username on authenticated connection";
+ if (PREDICT_FALSE(rc != SASL_OK || c_username == nullptr)) {
+ constexpr const char* const kErrMsg =
+ "no username on authenticated connection";
+ LOG(DFATAL) << kErrMsg;
+ return Status::IllegalState(kErrMsg);
+ }
if (negotiated_mech_ == SaslMechanism::GSSAPI) {
// The SASL library doesn't include the user's realm in the username if it's the
// same realm as the default realm of the server. So, we pass it back through the
@@ -683,7 +688,12 @@ Status ServerNegotiation::AuthenticateBySasl(faststring* recv_buf) {
Status ServerNegotiation::AuthenticateByToken(faststring* recv_buf) {
// Sanity check that TLS has been negotiated. Receiving the token on an
// unencrypted channel is a big no-no.
- CHECK(tls_negotiated_);
+ if (PREDICT_FALSE(!tls_negotiated_)) {
+ constexpr const char* const kErrMsg =
+ "received authn token over an unencrypted channel";
+ LOG(DFATAL) << kErrMsg;
+ return Status::IllegalState(kErrMsg);
+ }
// Receive the token from the client.
NegotiatePB pb;
@@ -765,7 +775,12 @@ Status ServerNegotiation::AuthenticateByToken(faststring* recv_buf) {
Status ServerNegotiation::AuthenticateByCertificate() {
// Sanity check that TLS has been negotiated. Cert-based authentication is
// only possible with TLS.
- CHECK(tls_negotiated_);
+ if (PREDICT_FALSE(!tls_negotiated_)) {
+ constexpr const char* const kErrMsg =
+ "received client certificate over an unencrypted channel";
+ LOG(DFATAL) << kErrMsg;
+ return Status::IllegalState(kErrMsg);
+ }
// Grab the subject from the client's cert.
security::Cert cert;
@@ -1012,7 +1027,10 @@ int ServerNegotiation::PlainAuthCb(sasl_conn_t* /*conn*/,
}
bool ServerNegotiation::IsTrustedConnection(const Sockaddr& addr) {
- if (addr.family() == AF_UNIX) return true;
+ if (addr.family() == AF_UNIX) {
+ return true;
+ }
+
static std::once_flag once;
std::call_once(once, [] {
g_trusted_subnets = new vector<Network>();