]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
auth/cephx: add authorizer challenge
authorSage Weil <sage@redhat.com>
Thu, 24 May 2018 18:57:17 +0000 (13:57 -0500)
committerSage Weil <sage@redhat.com>
Thu, 24 May 2018 19:17:43 +0000 (14:17 -0500)
Allow the accepting side of a connection to reject an initial authorizer
with a random challenge.  The connecting side then has to respond with an
updated authorizer proving they are able to decrypt the service's challenge
and that the new authorizer was produced for this specific connection
instance.

The accepting side requires this challenge and response unconditionally
if the client side advertises they have the feature bit.  Servers wishing
to require this improved level of authentication simply have to require
the appropriate feature.

Signed-off-by: Sage Weil <sage@redhat.com>
34 files changed:
src/auth/Auth.h
src/auth/AuthAuthorizeHandler.h
src/auth/cephx/CephxAuthorizeHandler.cc
src/auth/cephx/CephxAuthorizeHandler.h
src/auth/cephx/CephxProtocol.cc
src/auth/cephx/CephxProtocol.h
src/auth/cephx/CephxServiceHandler.cc
src/auth/none/AuthNoneAuthorizeHandler.cc
src/auth/none/AuthNoneAuthorizeHandler.h
src/auth/none/AuthNoneProtocol.h
src/auth/unknown/AuthUnknownAuthorizeHandler.cc
src/auth/unknown/AuthUnknownAuthorizeHandler.h
src/include/msgr.h
src/mds/MDSDaemon.cc
src/mds/MDSDaemon.h
src/mgr/DaemonServer.cc
src/mgr/DaemonServer.h
src/mon/Monitor.cc
src/mon/Monitor.h
src/msg/Dispatcher.h
src/msg/Messenger.h
src/msg/async/AsyncConnection.cc
src/msg/async/AsyncConnection.h
src/msg/async/AsyncMessenger.h
src/msg/simple/Pipe.cc
src/msg/simple/SimpleMessenger.cc
src/msg/simple/SimpleMessenger.h
src/osd/OSD.cc
src/osd/OSD.h
src/test/messenger/simple_dispatcher.h
src/test/messenger/xio_dispatcher.h
src/test/msgr/perf_msgr_client.cc
src/test/msgr/perf_msgr_server.cc
src/test/msgr/test_msgr.cc

index 9b8601192b759701c08cc0331e67b9729dd13318..672f0fda1e45be80a459250943cf955f0a4b47f0 100644 (file)
@@ -142,6 +142,11 @@ struct AuthAuthorizer {
   explicit AuthAuthorizer(__u32 p) : protocol(p) {}
   virtual ~AuthAuthorizer() {}
   virtual bool verify_reply(bufferlist::const_iterator& reply) = 0;
+  virtual bool add_challenge(CephContext *cct, bufferlist& challenge) = 0;
+};
+
+struct AuthAuthorizerChallenge {
+  virtual ~AuthAuthorizerChallenge() {}
 };
 
 
index c53d049fa0a2cdca1ac77caa8fafe26e7d6995f1..f6a0e68c95989db07766466c6c0ea7e6cbdad35c 100644 (file)
@@ -34,7 +34,9 @@ struct AuthAuthorizeHandler {
   virtual bool verify_authorizer(CephContext *cct, KeyStore *keys,
                                 bufferlist& authorizer_data, bufferlist& authorizer_reply,
                                  EntityName& entity_name, uint64_t& global_id,
-                                AuthCapsInfo& caps_info, CryptoKey& session_key, uint64_t *auid = NULL) = 0;
+                                AuthCapsInfo& caps_info, CryptoKey& session_key,
+                                uint64_t *auid,
+                                std::unique_ptr<AuthAuthorizerChallenge> *challenge) = 0;
   virtual int authorizer_session_crypto() = 0;
 };
 
index ced50fddda6043e39995030e18700407a1693747..e589ff4ee7e991a98a2b2516423f74b0a5346178 100644 (file)
@@ -6,9 +6,12 @@
 
 
 
-bool CephxAuthorizeHandler::verify_authorizer(CephContext *cct, KeyStore *keys,
-                                             bufferlist& authorizer_data, bufferlist& authorizer_reply,
-                                              EntityName& entity_name, uint64_t& global_id, AuthCapsInfo& caps_info, CryptoKey& session_key,  uint64_t *auid)
+bool CephxAuthorizeHandler::verify_authorizer(
+  CephContext *cct, KeyStore *keys,
+  bufferlist& authorizer_data, bufferlist& authorizer_reply,
+  EntityName& entity_name, uint64_t& global_id, AuthCapsInfo& caps_info,
+  CryptoKey& session_key, uint64_t *auid,
+  std::unique_ptr<AuthAuthorizerChallenge> *challenge)
 {
   auto iter = authorizer_data.cbegin();
 
@@ -19,7 +22,8 @@ bool CephxAuthorizeHandler::verify_authorizer(CephContext *cct, KeyStore *keys,
 
   CephXServiceTicketInfo auth_ticket_info;
 
-  bool isvalid = cephx_verify_authorizer(cct, keys, iter, auth_ticket_info, authorizer_reply);
+  bool isvalid = cephx_verify_authorizer(cct, keys, iter, auth_ticket_info, challenge,
+                                        authorizer_reply);
 
   if (isvalid) {
     caps_info = auth_ticket_info.ticket.caps;
index 7246b80c71da5312ac083c9ea6d5376201faebac..8fa40aa71275312d88077203ff7a1d405eccc485 100644 (file)
@@ -23,7 +23,8 @@ struct CephxAuthorizeHandler : public AuthAuthorizeHandler {
   bool verify_authorizer(CephContext *cct, KeyStore *keys,
                         bufferlist& authorizer_data, bufferlist& authorizer_reply,
                          EntityName& entity_name, uint64_t& global_id,
-                        AuthCapsInfo& caps_info, CryptoKey& session_key, uint64_t *auid = NULL) override;
+                        AuthCapsInfo& caps_info, CryptoKey& session_key, uint64_t *auid,
+                        std::unique_ptr<AuthAuthorizerChallenge> *challenge) override;
   int authorizer_session_crypto() override;
 };
 
index cf103e9f2940d0fca1d2dbe1d0b9dacdde60a38f..b8a62dbb732cfb577f4978f86ce9c8db72604875 100644 (file)
@@ -304,6 +304,7 @@ CephXAuthorizer *CephXTicketHandler::build_authorizer(uint64_t global_id) const
   encode(service_id, a->bl);
 
   encode(ticket, a->bl);
+  a->base_bl = a->bl;
 
   CephXAuthorize msg;
   msg.nonce = a->nonce;
@@ -390,7 +391,9 @@ bool cephx_decode_ticket(CephContext *cct, KeyStore *keys, uint32_t service_id,
  */
 bool cephx_verify_authorizer(CephContext *cct, KeyStore *keys,
                             bufferlist::const_iterator& indata,
-                            CephXServiceTicketInfo& ticket_info, bufferlist& reply_bl)
+                            CephXServiceTicketInfo& ticket_info,
+                            std::unique_ptr<AuthAuthorizerChallenge> *challenge,
+                            bufferlist& reply_bl)
 {
   __u8 authorizer_v;
   uint32_t service_id;
@@ -457,6 +460,30 @@ bool cephx_verify_authorizer(CephContext *cct, KeyStore *keys,
     return false;
   }
 
+  if (challenge) {
+    auto *c = static_cast<CephXAuthorizeChallenge*>(challenge->get());
+    if (!auth_msg.have_challenge || !c) {
+      c = new CephXAuthorizeChallenge;
+      challenge->reset(c);
+      cct->random()->get_bytes((char*)&c->server_challenge, sizeof(c->server_challenge));
+      ldout(cct,10) << __func__ << " adding server_challenge " << c->server_challenge
+                   << dendl;
+
+      encode_encrypt_enc_bl(cct, *c, ticket_info.session_key, reply_bl, error);
+      if (!error.empty()) {
+       ldout(cct, 10) << "verify_authorizer: encode_encrypt error: " << error << dendl;
+       return false;
+      }
+      return false;
+    }
+    ldout(cct, 10) << __func__ << " got server_challenge+1 "
+                  << auth_msg.server_challenge_plus_one
+                  << " expecting " << c->server_challenge + 1 << dendl;
+    if (c->server_challenge + 1 != auth_msg.server_challenge_plus_one) {
+      return false;
+    }
+  }
+
   /*
    * Reply authorizer:
    *  {timestamp + 1}^session_key
@@ -493,3 +520,31 @@ bool CephXAuthorizer::verify_reply(bufferlist::const_iterator& indata)
   return true;
 }
 
+bool CephXAuthorizer::add_challenge(CephContext *cct, bufferlist& challenge)
+{
+  bl = base_bl;
+
+  CephXAuthorize msg;
+  msg.nonce = nonce;
+
+  auto p = challenge.begin();
+  if (!p.end()) {
+    std::string error;
+    CephXAuthorizeChallenge ch;
+    decode_decrypt_enc_bl(cct, ch, session_key, challenge, error);
+    if (!error.empty()) {
+      ldout(cct, 0) << "failed to decrypt challenge (" << challenge.length() << " bytes): "
+                   << error << dendl;
+      return false;
+    }
+    msg.have_challenge = true;
+    msg.server_challenge_plus_one = ch.server_challenge + 1;
+  }
+
+  std::string error;
+  if (encode_encrypt(cct, msg, session_key, bl, error)) {
+    ldout(cct, 0) << __func__ << " failed to encrypt authorizer: " << error << dendl;
+    return false;
+  }
+  return true;
+}
index 055a233cba3b10b5a720fd5de5ea697d39079c0d..16135ec11f31ad6220560e3ccda8d32802d3cb6f 100644 (file)
@@ -289,12 +289,14 @@ private:
   CephContext *cct;
 public:
   uint64_t nonce;
+  bufferlist base_bl;
 
   explicit CephXAuthorizer(CephContext *cct_)
     : AuthAuthorizer(CEPH_AUTH_CEPHX), cct(cct_), nonce(0) {}
 
   bool build_authorizer();
   bool verify_reply(bufferlist::const_iterator& reply) override;
+  bool add_challenge(CephContext *cct, bufferlist& challenge) override;
 };
 
 
@@ -404,19 +406,44 @@ struct CephXServiceTicketInfo {
 };
 WRITE_CLASS_ENCODER(CephXServiceTicketInfo)
 
+struct CephXAuthorizeChallenge : public AuthAuthorizerChallenge {
+  uint64_t server_challenge;
+  void encode(bufferlist& bl) const {
+    using ceph::encode;
+    __u8 struct_v = 1;
+    encode(struct_v, bl);
+    encode(server_challenge, bl);
+  }
+  void decode(bufferlist::const_iterator& bl) {
+    using ceph::decode;
+    __u8 struct_v;
+    decode(struct_v, bl);
+    decode(server_challenge, bl);
+  }
+};
+WRITE_CLASS_ENCODER(CephXAuthorizeChallenge)
+
 struct CephXAuthorize {
   uint64_t nonce;
+  bool have_challenge = false;
+  uint64_t server_challenge_plus_one = 0;
   void encode(bufferlist& bl) const {
     using ceph::encode;
-    __u8 struct_v = 1;
+    __u8 struct_v = 2;
     encode(struct_v, bl);
     encode(nonce, bl);
+    encode(have_challenge, bl);
+    encode(server_challenge_plus_one, bl);
   }
   void decode(bufferlist::const_iterator& bl) {
     using ceph::decode;
     __u8 struct_v;
     decode(struct_v, bl);
     decode(nonce, bl);
+    if (struct_v >= 2) {
+      decode(have_challenge, bl);
+      decode(server_challenge_plus_one, bl);
+    }
   }
 };
 WRITE_CLASS_ENCODER(CephXAuthorize)
@@ -431,9 +458,12 @@ bool cephx_decode_ticket(CephContext *cct, KeyStore *keys,
 /*
  * Verify authorizer and generate reply authorizer
  */
-extern bool cephx_verify_authorizer(CephContext *cct, KeyStore *keys,
-                                   bufferlist::const_iterator& indata,
-                                   CephXServiceTicketInfo& ticket_info, bufferlist& reply_bl);
+extern bool cephx_verify_authorizer(
+  CephContext *cct, KeyStore *keys,
+  bufferlist::const_iterator& indata,
+  CephXServiceTicketInfo& ticket_info,
+  std::unique_ptr<AuthAuthorizerChallenge> *challenge,
+  bufferlist& reply_bl);
 
 
 
index acd9fa64b724aea91f41fa4b07f92ca2d2feb621..ea2d852cae1b90b85d469fda7ab1d7f7de980215 100644 (file)
@@ -153,7 +153,9 @@ int CephxServiceHandler::handle_request(bufferlist::const_iterator& indata, buff
 
       bufferlist tmp_bl;
       CephXServiceTicketInfo auth_ticket_info;
-      if (!cephx_verify_authorizer(cct, key_server, indata, auth_ticket_info, tmp_bl)) {
+      // note: no challenge here.
+      if (!cephx_verify_authorizer(cct, key_server, indata, auth_ticket_info, nullptr,
+                                  tmp_bl)) {
         ret = -EPERM;
        break;
       }
index 298d21bd2a2b7ec2cdbd3abeee57acf823999b52..d7e42c1b9ac76a2ab8147c44ef009ab5a9a19271 100644 (file)
 
 #define dout_subsys ceph_subsys_auth
 
-bool AuthNoneAuthorizeHandler::verify_authorizer(CephContext *cct, KeyStore *keys,
-                                                bufferlist& authorizer_data, bufferlist& authorizer_reply,
-                                                EntityName& entity_name, uint64_t& global_id, AuthCapsInfo& caps_info, CryptoKey& session_key,
-uint64_t *auid)
+bool AuthNoneAuthorizeHandler::verify_authorizer(
+  CephContext *cct, KeyStore *keys,
+  bufferlist& authorizer_data, bufferlist& authorizer_reply,
+  EntityName& entity_name, uint64_t& global_id, AuthCapsInfo& caps_info,
+  CryptoKey& session_key,
+  uint64_t *auid,
+  std::unique_ptr<AuthAuthorizerChallenge> *challenge)
 {
   auto iter = authorizer_data.cbegin();
 
index b531cfb77360160614b3fe310aa6b2cd89beac17..0ce542bf678e2b061ea5fcb756f1df8de1a9701e 100644 (file)
@@ -23,7 +23,8 @@ struct AuthNoneAuthorizeHandler : public AuthAuthorizeHandler {
   bool verify_authorizer(CephContext *cct, KeyStore *keys,
                         bufferlist& authorizer_data, bufferlist& authorizer_reply,
                          EntityName& entity_name, uint64_t& global_id,
-                        AuthCapsInfo& caps_info, CryptoKey& session_key, uint64_t *auid=NULL) override;
+                        AuthCapsInfo& caps_info, CryptoKey& session_key, uint64_t *auid,
+                        std::unique_ptr<AuthAuthorizerChallenge> *challenge) override;
   int authorizer_session_crypto() override;
 };
 
index 9664422a6c7e178ecd4af59ee74e83d0f18dec97..64865355eae9cfb2ba8e49700fe14376523ea24f 100644 (file)
@@ -17,6 +17,8 @@
 
 #include "auth/Auth.h"
 
+class CephContext;
+
 struct AuthNoneAuthorizer : public AuthAuthorizer {
   AuthNoneAuthorizer() : AuthAuthorizer(CEPH_AUTH_NONE) { }
   bool build_authorizer(const EntityName &ename, uint64_t global_id) {
@@ -27,6 +29,7 @@ struct AuthNoneAuthorizer : public AuthAuthorizer {
     return 0;
   }
   bool verify_reply(bufferlist::const_iterator& reply) override { return true; }
+  bool add_challenge(CephContext *cct, bufferlist& ch) override { return true; }
 };
 
 #endif
index 62cb638874e2bc9c1c2f2e9f96dbae599034bb82..90e00ef579a584201554e82f2061740cfd6b3aec 100644 (file)
 
 #include "AuthUnknownAuthorizeHandler.h"
 
-bool AuthUnknownAuthorizeHandler::verify_authorizer(CephContext *cct, KeyStore *keys,
-                                                bufferlist& authorizer_data, bufferlist& authorizer_reply,
-                                                EntityName& entity_name, uint64_t& global_id, AuthCapsInfo& caps_info, CryptoKey& session_key,
-uint64_t *auid)
+bool AuthUnknownAuthorizeHandler::verify_authorizer(
+  CephContext *cct, KeyStore *keys,
+  bufferlist& authorizer_data, bufferlist& authorizer_reply,
+  EntityName& entity_name, uint64_t& global_id, AuthCapsInfo& caps_info,
+  CryptoKey& session_key,
+  uint64_t *auid,
+  std::unique_ptr<AuthAuthorizerChallenge> *challenge)
 {
   // For unknown authorizers, there's nothing to verify.  They're "OK" by definition.  PLR
 
index 9795ebfe9bf66ba93d04824d40635d4b31754293..e052af5def7dff1a62710a8e3a4b9283f37483a8 100644 (file)
@@ -23,7 +23,8 @@ struct AuthUnknownAuthorizeHandler : public AuthAuthorizeHandler {
   bool verify_authorizer(CephContext *cct, KeyStore *keys,
                         bufferlist& authorizer_data, bufferlist& authorizer_reply,
                          EntityName& entity_name, uint64_t& global_id,
-                        AuthCapsInfo& caps_info, CryptoKey& session_key, uint64_t *auid=NULL) override;
+                        AuthCapsInfo& caps_info, CryptoKey& session_key, uint64_t *auid,
+                        std::unique_ptr<AuthAuthorizerChallenge> *challenge) override;
   int authorizer_session_crypto() override;
 };
 
index 1953eb28b40b44d2515259049c86f36c632ec08b..62582b0bca7b7405871b00cc296d6b4a1465f86d 100644 (file)
@@ -93,7 +93,7 @@ struct ceph_entity_inst {
 #define CEPH_MSGR_TAG_SEQ           13 /* 64-bit int follows with seen seq number */
 #define CEPH_MSGR_TAG_KEEPALIVE2     14
 #define CEPH_MSGR_TAG_KEEPALIVE2_ACK 15  /* keepalive reply */
-
+#define CEPH_MSGR_TAG_CHALLENGE_AUTHORIZER 16  /* ceph v2 doing server challenge */
 
 /*
  * connection negotiation
index 847a9ea716fbf43051345fccd33f75b3a1b9a308..d1021afb64d6c72482e7bc0a374b8356c837d484 100644 (file)
@@ -1295,7 +1295,8 @@ bool MDSDaemon::ms_handle_refused(Connection *con)
 
 bool MDSDaemon::ms_verify_authorizer(Connection *con, int peer_type,
                               int protocol, bufferlist& authorizer_data, bufferlist& authorizer_reply,
-                              bool& is_valid, CryptoKey& session_key)
+                                    bool& is_valid, CryptoKey& session_key,
+                                    std::unique_ptr<AuthAuthorizerChallenge> *challenge)
 {
   Mutex::Locker l(mds_lock);
   if (stopping) {
@@ -1327,7 +1328,7 @@ bool MDSDaemon::ms_verify_authorizer(Connection *con, int peer_type,
     is_valid = authorize_handler->verify_authorizer(
       cct, keys,
       authorizer_data, authorizer_reply, name, global_id, caps_info,
-      session_key);
+      session_key, nullptr, challenge);
   } else {
     dout(10) << __func__ << " no rotating_keys (yet), denied" << dendl;
     is_valid = false;
index b9d331971c9bf3b4a8482acf904e265c2b47e6c7..75cb176698a42d82d82dde7fab4da43162211a92 100644 (file)
@@ -108,7 +108,8 @@ class MDSDaemon : public Dispatcher, public md_config_obs_t {
   bool ms_get_authorizer(int dest_type, AuthAuthorizer **authorizer, bool force_new) override;
   bool ms_verify_authorizer(Connection *con, int peer_type,
                               int protocol, bufferlist& authorizer_data, bufferlist& authorizer_reply,
-                              bool& isvalid, CryptoKey& session_key) override;
+                           bool& isvalid, CryptoKey& session_key,
+                           std::unique_ptr<AuthAuthorizerChallenge> *challenge) override;
   void ms_handle_accept(Connection *con) override;
   void ms_handle_connect(Connection *con) override;
   bool ms_handle_reset(Connection *con) override;
index 8337b34d90d1fdeb4c735fb907ecfadd3b685180..322e7d6e3a8900cc5f717ae1315d2c5a7bc46a5c 100644 (file)
@@ -144,13 +144,15 @@ entity_addr_t DaemonServer::get_myaddr() const
 }
 
 
-bool DaemonServer::ms_verify_authorizer(Connection *con,
-    int peer_type,
-    int protocol,
-    ceph::bufferlist& authorizer_data,
-    ceph::bufferlist& authorizer_reply,
-    bool& is_valid,
-    CryptoKey& session_key)
+bool DaemonServer::ms_verify_authorizer(
+  Connection *con,
+  int peer_type,
+  int protocol,
+  ceph::bufferlist& authorizer_data,
+  ceph::bufferlist& authorizer_reply,
+  bool& is_valid,
+  CryptoKey& session_key,
+  std::unique_ptr<AuthAuthorizerChallenge> *challenge)
 {
   AuthAuthorizeHandler *handler = nullptr;
   if (peer_type == CEPH_ENTITY_TYPE_OSD ||
@@ -178,7 +180,9 @@ bool DaemonServer::ms_verify_authorizer(Connection *con,
       authorizer_data,
       authorizer_reply, s->entity_name,
       s->global_id, caps_info,
-      session_key);
+      session_key,
+      nullptr,
+      challenge);
   } else {
     dout(10) << __func__ << " no rotating_keys (yet), denied" << dendl;
     is_valid = false;
index 7972a1d84763bfa07b3c631eecbb4a28ddfd772e..9fb4cca71d43d560d62f7a1a31ae9e89b6044c50 100644 (file)
@@ -124,13 +124,15 @@ public:
   bool ms_handle_refused(Connection *con) override;
   bool ms_get_authorizer(int dest_type, AuthAuthorizer **authorizer,
                          bool force_new) override;
-  bool ms_verify_authorizer(Connection *con,
-      int peer_type,
-      int protocol,
-      ceph::bufferlist& authorizer,
-      ceph::bufferlist& authorizer_reply,
-      bool& isvalid,
-      CryptoKey& session_key) override;
+  bool ms_verify_authorizer(
+    Connection *con,
+    int peer_type,
+    int protocol,
+    ceph::bufferlist& authorizer,
+    ceph::bufferlist& authorizer_reply,
+    bool& isvalid,
+    CryptoKey& session_key,
+    std::unique_ptr<AuthAuthorizerChallenge> *challenge) override;
 
   bool handle_open(MMgrOpen *m);
   bool handle_close(MMgrClose *m);
index a8ecb2eebf4b7810a14e2d7e8021efc77685ddd3..9d31e19031b3ef72ff8f6e7a84d335a7b9d4bd84 100644 (file)
@@ -5780,7 +5780,8 @@ bool Monitor::ms_get_authorizer(int service_id, AuthAuthorizer **authorizer,
 bool Monitor::ms_verify_authorizer(Connection *con, int peer_type,
                                   int protocol, bufferlist& authorizer_data,
                                   bufferlist& authorizer_reply,
-                                  bool& isvalid, CryptoKey& session_key)
+                                  bool& isvalid, CryptoKey& session_key,
+                                  std::unique_ptr<AuthAuthorizerChallenge> *challenge)
 {
   dout(10) << "ms_verify_authorizer " << con->get_peer_addr()
           << " " << ceph_entity_type_name(peer_type)
@@ -5799,7 +5800,7 @@ bool Monitor::ms_verify_authorizer(Connection *con, int peer_type,
       
       if (authorizer_data.length()) {
        bool ret = cephx_verify_authorizer(g_ceph_context, &keyring, iter,
-                                         auth_ticket_info, authorizer_reply);
+                                          auth_ticket_info, challenge, authorizer_reply);
        if (ret) {
          session_key = auth_ticket_info.session_key;
          isvalid = true;
index 1acf69cc31a85aa64d0728fc870ea46f4761a43e..d4b11830e42c7c52704746ae847077ca6c427d16 100644 (file)
@@ -887,7 +887,8 @@ public:
   bool ms_get_authorizer(int dest_type, AuthAuthorizer **authorizer, bool force_new) override;
   bool ms_verify_authorizer(Connection *con, int peer_type,
                            int protocol, bufferlist& authorizer_data, bufferlist& authorizer_reply,
-                           bool& isvalid, CryptoKey& session_key) override;
+                           bool& isvalid, CryptoKey& session_key,
+                           std::unique_ptr<AuthAuthorizerChallenge> *challenge) override;
   bool ms_handle_reset(Connection *con) override;
   void ms_handle_remote_reset(Connection *con) override {}
   bool ms_handle_refused(Connection *con) override;
index 774ca405134a7bcf1e12cd1085e17e13b77fb5e6..faab248d60ffa796b2f54ab86cd500a60c3159fd 100644 (file)
@@ -16,6 +16,7 @@
 #ifndef CEPH_DISPATCHER_H
 #define CEPH_DISPATCHER_H
 
+#include <memory>
 #include "include/buffer_fwd.h"
 #include "include/assert.h"
 
@@ -25,6 +26,7 @@ class Connection;
 class AuthAuthorizer;
 class CryptoKey;
 class CephContext;
+class AuthAuthorizerChallenge;
 
 class Dispatcher {
 public:
@@ -203,7 +205,10 @@ public:
                                    ceph::bufferlist& authorizer,
                                    ceph::bufferlist& authorizer_reply,
                                    bool& isvalid,
-                                   CryptoKey& session_key) { return false; }
+                                   CryptoKey& session_key,
+                                   std::unique_ptr<AuthAuthorizerChallenge> *challenge) {
+    return false;
+  }
   /**
    * @} //Authentication
    */
index eb3541780364b4e240662c55eb4cf1e3918957f0..1feb0adc016e92b27d62b76eba8bee67e4025220 100644 (file)
@@ -805,11 +805,13 @@ public:
    */
   bool ms_deliver_verify_authorizer(Connection *con, int peer_type,
                                    int protocol, bufferlist& authorizer, bufferlist& authorizer_reply,
-                                   bool& isvalid, CryptoKey& session_key) {
+                                   bool& isvalid, CryptoKey& session_key,
+                                   std::unique_ptr<AuthAuthorizerChallenge> *challenge) {
     for (list<Dispatcher*>::iterator p = dispatchers.begin();
         p != dispatchers.end();
         ++p) {
-      if ((*p)->ms_verify_authorizer(con, peer_type, protocol, authorizer, authorizer_reply, isvalid, session_key))
+      if ((*p)->ms_verify_authorizer(con, peer_type, protocol, authorizer, authorizer_reply,
+                                    isvalid, session_key, challenge))
        return true;
     }
     return false;
index 4036fba9b9adf793cbe47bf35a5b225492adea18..77955af23fa1909eed0fe6df248e1b3ac506cb5c 100644 (file)
@@ -128,7 +128,8 @@ AsyncConnection::AsyncConnection(CephContext *cct, AsyncMessenger *m, DispatchQu
     recv_start(0), recv_end(0),
     last_active(ceph::coarse_mono_clock::now()),
     inactive_timeout_us(cct->_conf->ms_tcp_read_timeout*1000*1000),
-    msg_left(0), cur_msg_size(0), got_bad_auth(false), authorizer(NULL), replacing(false),
+    msg_left(0), cur_msg_size(0), got_bad_auth(false),
+    authorizer(NULL), replacing(false),
     is_reset_from_peer(false), once_ready(false), state_buffer(NULL), state_offset(0),
     worker(w), center(&w->center)
 {
@@ -1010,8 +1011,7 @@ ssize_t AsyncConnection::_process_connection()
 
     case STATE_CONNECTING_SEND_CONNECT_MSG:
       {
-        if (!got_bad_auth) {
-          delete authorizer;
+        if (!authorizer) {
           authorizer = async_msgr->get_authorizer(peer_type, false);
         }
         bufferlist bl;
@@ -1091,6 +1091,14 @@ ssize_t AsyncConnection::_process_connection()
           }
 
           authorizer_reply.append(state_buffer, connect_reply.authorizer_len);
+
+         if (connect_reply.tag == CEPH_MSGR_TAG_CHALLENGE_AUTHORIZER) {
+           ldout(async_msgr->cct,10) << __func__ << " connect got auth challenge" << dendl;
+           authorizer->add_challenge(async_msgr->cct, authorizer_reply);
+           state = STATE_CONNECTING_SEND_CONNECT_MSG;
+           break;
+         }
+
           auto iter = authorizer_reply.cbegin();
           if (authorizer && !authorizer->verify_reply(iter)) {
             ldout(async_msgr->cct, 0) << __func__ << " failed verifying authorize reply" << dendl;
@@ -1508,12 +1516,26 @@ ssize_t AsyncConnection::handle_connect_msg(ceph_msg_connect &connect, bufferlis
   lock.unlock();
 
   bool authorizer_valid;
-  if (!async_msgr->verify_authorizer(this, peer_type, connect.authorizer_protocol, authorizer_bl,
-                               authorizer_reply, authorizer_valid, session_key) || !authorizer_valid) {
+  bool need_challenge = HAVE_FEATURE(connect.features, CEPHX_V2);
+  bool had_challenge = (bool)authorizer_challenge;
+  if (!async_msgr->verify_authorizer(
+       this, peer_type, connect.authorizer_protocol, authorizer_bl,
+       authorizer_reply, authorizer_valid, session_key,
+       need_challenge ? &authorizer_challenge : nullptr) ||
+      !authorizer_valid) {
     lock.lock();
-    ldout(async_msgr->cct,0) << __func__ << ": got bad authorizer" << dendl;
+    char tag;
+    if (need_challenge && !had_challenge && authorizer_challenge) {
+      ldout(async_msgr->cct,0) << __func__ << ": challenging authorizer"
+                              << dendl;
+      assert(authorizer_reply.length());
+      tag = CEPH_MSGR_TAG_CHALLENGE_AUTHORIZER;
+    } else {
+      ldout(async_msgr->cct,0) << __func__ << ": got bad authorizer" << dendl;
+      tag = CEPH_MSGR_TAG_BADAUTHORIZER;
+    }
     session_security.reset();
-    return _reply_accept(CEPH_MSGR_TAG_BADAUTHORIZER, connect, reply, authorizer_reply);
+    return _reply_accept(tag, connect, reply, authorizer_reply);
   }
 
   // We've verified the authorizer for this AsyncConnection, so set up the session security structure.  PLR
@@ -1711,6 +1733,8 @@ ssize_t AsyncConnection::handle_connect_msg(ceph_msg_connect &connect, bufferlis
     // there shouldn't exist any buffer
     assert(recv_start == recv_end);
 
+    existing->authorizer_challenge.reset();
+
     auto deactivate_existing = std::bind(
         [existing, new_worker, new_center, connect, reply, authorizer_reply](ConnectedSocket &cs) mutable {
       // we need to delete time event in original thread
index 0a3da9ddccac82508986cdf3c3b36f6517e673c1..a8455853bf36cfb3a11e72a9b8095dfdf4cb9091 100644 (file)
@@ -368,6 +368,7 @@ class AsyncConnection : public Connection {
   Worker *worker;
   EventCenter *center;
   ceph::shared_ptr<AuthSessionHandler> session_security;
+  std::unique_ptr<AuthAuthorizerChallenge> authorizer_challenge; // accept side
 
  public:
   // used by eventcallback
index a07ed4c69c3b26b997bc2cd3a145b0ede3b1d9c4..64f2e610ab7f8db2f02ee53179975479cd2eda20 100644 (file)
@@ -383,9 +383,10 @@ public:
    * This wraps ms_deliver_verify_authorizer; we use it for AsyncConnection.
    */
   bool verify_authorizer(Connection *con, int peer_type, int protocol, bufferlist& auth, bufferlist& auth_reply,
-                         bool& isvalid, CryptoKey& session_key) {
+                         bool& isvalid, CryptoKey& session_key,
+                        std::unique_ptr<AuthAuthorizerChallenge> *challenge) {
     return ms_deliver_verify_authorizer(con, peer_type, protocol, auth,
-                                        auth_reply, isvalid, session_key);
+                                        auth_reply, isvalid, session_key, challenge);
   }
   /**
    * Increment the global sequence for this AsyncMessenger and return it.
index ff35b038bd53f299e39b4ddf403bfeff88a60530..6ae12eef896f7e2595dde8ef5fcd2412cd6459ec 100644 (file)
@@ -351,6 +351,10 @@ int Pipe::accept()
   // used for reading in the remote acked seq on connect
   uint64_t newly_acked_seq = 0;
 
+  bool need_challenge = false;
+  bool had_challenge = false;
+  std::unique_ptr<AuthAuthorizerChallenge> authorizer_challenge;
+
   recv_reset();
 
   set_socket_options();
@@ -515,14 +519,27 @@ int Pipe::accept()
 
     pipe_lock.Unlock();
 
-    if (!msgr->verify_authorizer(connection_state.get(), peer_type, connect.authorizer_protocol, authorizer,
-                                authorizer_reply, authorizer_valid, session_key) ||
+    need_challenge = HAVE_FEATURE(connect.features, CEPHX_V2);
+    had_challenge = (bool)authorizer_challenge;
+    authorizer_reply.clear();
+    if (!msgr->verify_authorizer(
+         connection_state.get(), peer_type, connect.authorizer_protocol, authorizer,
+         authorizer_reply, authorizer_valid, session_key,
+         need_challenge ? &authorizer_challenge : nullptr) ||
        !authorizer_valid) {
-      ldout(msgr->cct,0) << "accept: got bad authorizer" << dendl;
       pipe_lock.Lock();
       if (state != STATE_ACCEPTING)
        goto shutting_down_msgr_unlocked;
-      reply.tag = CEPH_MSGR_TAG_BADAUTHORIZER;
+      if (!had_challenge && need_challenge && authorizer_challenge) {
+       ldout(msgr->cct,0) << "accept: challenging authorizer "
+                          << authorizer_reply.length()
+                          << " bytes" << dendl;
+       assert(authorizer_reply.length());
+       reply.tag = CEPH_MSGR_TAG_CHALLENGE_AUTHORIZER;
+      } else {
+       ldout(msgr->cct,0) << "accept: got bad authorizer" << dendl;
+       reply.tag = CEPH_MSGR_TAG_BADAUTHORIZER;
+      }
       session_security.reset();
       goto reply;
     } 
@@ -1128,8 +1145,9 @@ int Pipe::connect()
 
 
   while (1) {
-    delete authorizer;
-    authorizer = msgr->get_authorizer(peer_type, false);
+    if (!authorizer) {
+      authorizer = msgr->get_authorizer(peer_type, false);
+    }
     bufferlist authorizer_reply;
 
     ceph_msg_connect connect;
@@ -1196,6 +1214,13 @@ int Pipe::connect()
       authorizer_reply.push_back(bp);
     }
 
+    if (reply.tag == CEPH_MSGR_TAG_CHALLENGE_AUTHORIZER) {
+      authorizer->add_challenge(msgr->cct, authorizer_reply);
+      ldout(msgr->cct,10) << " got authorizer challenge, " << authorizer_reply.length()
+                         << " bytes" << dendl;
+      continue;
+    }
+
     if (authorizer) {
       auto iter = authorizer_reply.cbegin();
       if (!authorizer->verify_reply(iter)) {
index 4918c52a7af49d00073154996402e53aa7795bcb..18fbd7e218c7448c875ebd45124571a5732291bd 100644 (file)
@@ -413,9 +413,12 @@ AuthAuthorizer *SimpleMessenger::get_authorizer(int peer_type, bool force_new)
 
 bool SimpleMessenger::verify_authorizer(Connection *con, int peer_type,
                                        int protocol, bufferlist& authorizer, bufferlist& authorizer_reply,
-                                       bool& isvalid,CryptoKey& session_key)
+                                       bool& isvalid,CryptoKey& session_key,
+                                       std::unique_ptr<AuthAuthorizerChallenge> *challenge)
 {
-  return ms_deliver_verify_authorizer(con, peer_type, protocol, authorizer, authorizer_reply, isvalid,session_key);
+  return ms_deliver_verify_authorizer(con, peer_type, protocol, authorizer, authorizer_reply,
+                                     isvalid, session_key,
+                                     challenge);
 }
 
 ConnectionRef SimpleMessenger::get_connection(const entity_inst_t& dest)
index 93597a70a5b887a6532eea132a52d339cec1468e..cbde2207655ebe1bf9720b0610df3706050b55ac 100644 (file)
@@ -347,8 +347,10 @@ public:
   /**
    * This wraps ms_deliver_verify_authorizer; we use it for Pipe.
    */
-  bool verify_authorizer(Connection *con, int peer_type, int protocol, bufferlist& auth, bufferlist& auth_reply,
-                         bool& isvalid,CryptoKey& session_key);
+  bool verify_authorizer(Connection *con, int peer_type, int protocol, bufferlist& auth,
+                        bufferlist& auth_reply,
+                         bool& isvalid,CryptoKey& session_key,
+                        std::unique_ptr<AuthAuthorizerChallenge> *challenge);
   /**
    * Increment the global sequence for this SimpleMessenger and return it.
    * This is for the connect protocol, although it doesn't hurt if somebody
index 53318b2663d9371ceae9a0742b25d423958a37a6..a9a2f42f891b3a1d414a86b251ee7da8bbd1ee16 100644 (file)
@@ -6539,9 +6539,11 @@ bool OSD::ms_get_authorizer(int dest_type, AuthAuthorizer **authorizer, bool for
 }
 
 
-bool OSD::ms_verify_authorizer(Connection *con, int peer_type,
-                              int protocol, bufferlist& authorizer_data, bufferlist& authorizer_reply,
-                              bool& isvalid, CryptoKey& session_key)
+bool OSD::ms_verify_authorizer(
+  Connection *con, int peer_type,
+  int protocol, bufferlist& authorizer_data, bufferlist& authorizer_reply,
+  bool& isvalid, CryptoKey& session_key,
+  std::unique_ptr<AuthAuthorizerChallenge> *challenge)
 {
   AuthAuthorizeHandler *authorize_handler = 0;
   switch (peer_type) {
@@ -6573,7 +6575,7 @@ bool OSD::ms_verify_authorizer(Connection *con, int peer_type,
     isvalid = authorize_handler->verify_authorizer(
       cct, keys,
       authorizer_data, authorizer_reply, name, global_id, caps_info, session_key,
-      &auid);
+      &auid, challenge);
   } else {
     dout(10) << __func__ << " no rotating_keys (yet), denied" << dendl;
     isvalid = false;
index 0ebe5ecd2eb8e143b7179195d078c7df392de875..17988685f7a949420957187c63ba23e116b02a17 100644 (file)
@@ -1622,7 +1622,8 @@ public:
     }
     bool ms_verify_authorizer(Connection *con, int peer_type,
                              int protocol, bufferlist& authorizer_data, bufferlist& authorizer_reply,
-                             bool& isvalid, CryptoKey& session_key) override {
+                             bool& isvalid, CryptoKey& session_key,
+                             std::unique_ptr<AuthAuthorizerChallenge> *challenge) override {
       isvalid = true;
       return true;
     }
@@ -2130,7 +2131,8 @@ private:
   bool ms_get_authorizer(int dest_type, AuthAuthorizer **authorizer, bool force_new) override;
   bool ms_verify_authorizer(Connection *con, int peer_type,
                            int protocol, bufferlist& authorizer, bufferlist& authorizer_reply,
-                           bool& isvalid, CryptoKey& session_key) override;
+                           bool& isvalid, CryptoKey& session_key,
+                           std::unique_ptr<AuthAuthorizerChallenge> *challenge) override;
   void ms_handle_connect(Connection *con) override;
   void ms_handle_fast_connect(Connection *con) override;
   void ms_handle_fast_accept(Connection *con) override;
index c5345d662d1a379d0d0d22dbf4f9aa68e8cd04af..8b84ff4b6d2f0dba2038372087ea4520404c8fec 100644 (file)
@@ -113,9 +113,10 @@ public:
    * authorizer, false otherwise.
    */
   bool ms_verify_authorizer(Connection *con, int peer_type,
-                                   int protocol, bufferlist& authorizer,
-                                   bufferlist& authorizer_reply,
-                                   bool& isvalid, CryptoKey& session_key) override {
+                           int protocol, bufferlist& authorizer,
+                           bufferlist& authorizer_reply,
+                           bool& isvalid, CryptoKey& session_key,
+                           std::unique_ptr<AuthAuthorizerChallenge> *challenge) override {
     /* always succeed */
     isvalid = true;
     return true;
index 3b59108071fb0b1405467b0801f1bed2fa2b8009..495fa3a7521669c354cfd1d01b74cea73fe8526d 100644 (file)
@@ -115,7 +115,8 @@ public:
   virtual bool ms_verify_authorizer(Connection *con, int peer_type,
                                    int protocol, bufferlist& authorizer,
                                    bufferlist& authorizer_reply,
-                                   bool& isvalid, CryptoKey& session_key) {
+                                   bool& isvalid, CryptoKey& session_key,
+                                   std::unique_ptr<AuthAuthorizerChallenge> *challenge) {
     /* always succeed */
     isvalid = true;
     return true;
index b7c66ea793870dda59c0d652b0fb3a20319ea554..1442b05784a522d6f67a9490c6195d16e9278cc1 100644 (file)
@@ -58,7 +58,8 @@ class MessengerClient {
     bool ms_handle_refused(Connection *con) override { return false; }
     bool ms_verify_authorizer(Connection *con, int peer_type, int protocol,
                               bufferlist& authorizer, bufferlist& authorizer_reply,
-                              bool& isvalid, CryptoKey& session_key) override {
+                              bool& isvalid, CryptoKey& session_key,
+                             std::unique_ptr<AuthAuthorizerChallenge> *challenge) override {
       isvalid = true;
       return true;
     }
index 87ebb6116aaabdc904b60a763f6217253e3006c7..7df732853daf6a5c873bb590744373a499461e10 100644 (file)
@@ -100,7 +100,8 @@ class ServerDispatcher : public Dispatcher {
   }
   bool ms_verify_authorizer(Connection *con, int peer_type, int protocol,
                             bufferlist& authorizer, bufferlist& authorizer_reply,
-                            bool& isvalid, CryptoKey& session_key) override {
+                            bool& isvalid, CryptoKey& session_key,
+                           std::unique_ptr<AuthAuthorizerChallenge> *challenge) override {
     isvalid = true;
     return true;
   }
index a027aa6fcc9a17e2a0f5159af4a62a11affa1130..07887717b39c3756a9af09de10712fd1d7770d0e 100644 (file)
@@ -203,7 +203,8 @@ class FakeDispatcher : public Dispatcher {
 
   bool ms_verify_authorizer(Connection *con, int peer_type, int protocol,
                             bufferlist& authorizer, bufferlist& authorizer_reply,
-                            bool& isvalid, CryptoKey& session_key) override {
+                            bool& isvalid, CryptoKey& session_key,
+                           std::unique_ptr<AuthAuthorizerChallenge> *challenge) override {
     isvalid = true;
     return true;
   }
@@ -893,7 +894,8 @@ class SyntheticDispatcher : public Dispatcher {
 
   bool ms_verify_authorizer(Connection *con, int peer_type, int protocol,
                             bufferlist& authorizer, bufferlist& authorizer_reply,
-                            bool& isvalid, CryptoKey& session_key) override {
+                            bool& isvalid, CryptoKey& session_key,
+                           std::unique_ptr<AuthAuthorizerChallenge> *challenge) override {
     isvalid = true;
     return true;
   }
@@ -1436,7 +1438,8 @@ class MarkdownDispatcher : public Dispatcher {
   }
   bool ms_verify_authorizer(Connection *con, int peer_type, int protocol,
                             bufferlist& authorizer, bufferlist& authorizer_reply,
-                            bool& isvalid, CryptoKey& session_key) override {
+                            bool& isvalid, CryptoKey& session_key,
+                           std::unique_ptr<AuthAuthorizerChallenge> *challenge) override {
     isvalid = true;
     return true;
   }