]> 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 21:55:26 +0000 (16:55 -0500)
committerSage Weil <sage@redhat.com>
Fri, 25 May 2018 01:38:16 +0000 (20:38 -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>
(cherry picked from commit f80b848d3f830eb6dba50123e04385173fa4540b)

# Conflicts:
# src/auth/Auth.h
# src/auth/cephx/CephxProtocol.cc
# src/auth/cephx/CephxProtocol.h
# src/auth/none/AuthNoneProtocol.h
# src/msg/Dispatcher.h
# src/msg/async/AsyncConnection.cc

- const_iterator
- ::decode vs decode
- AsyncConnection ctor arg noise
- get_random_bytes(), not cct->random()

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 c5bda0ccaf49f11b763842870afc37898ccb0923..f40296e1a0375f2694503bcaa39b5c8d50f4c530 100644 (file)
@@ -136,6 +136,11 @@ struct AuthAuthorizer {
   explicit AuthAuthorizer(__u32 p) : protocol(p) {}
   virtual ~AuthAuthorizer() {}
   virtual bool verify_reply(bufferlist::iterator& reply) = 0;
+  virtual bool add_challenge(CephContext *cct, bufferlist& challenge) = 0;
+};
+
+struct AuthAuthorizerChallenge {
+  virtual ~AuthAuthorizerChallenge() {}
 };
 
 
index 2e81f14abde6462c14968419d8353760cbb588af..d824ed4e14387bf01715f098da85944fe506b5c6 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 d455b190a997eb291f99205983d10718381f81cb..1a6164a0f0ad21640449b0d3f9be5211ec6dd2ac 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)
 {
   bufferlist::iterator iter = authorizer_data.begin();
 
@@ -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 5836a33bd531e7a31e662d6d93a5098150a4625b..98a0511eeb0cb7cb8c159cf1e478d0402c965768 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::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);
+      get_random_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::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 c82206989906155ba8400187ee87535dbc2ff627..b5ec897f35b9ab447e3d29f2ba1435adb5aad4c3 100644 (file)
@@ -273,12 +273,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::iterator& reply) override;
+  bool add_challenge(CephContext *cct, bufferlist& challenge) override;
 };
 
 
@@ -384,17 +386,41 @@ struct CephXServiceTicketInfo {
 };
 WRITE_CLASS_ENCODER(CephXServiceTicketInfo)
 
+struct CephXAuthorizeChallenge : public AuthAuthorizerChallenge {
+  uint64_t server_challenge;
+  void encode(bufferlist& bl) const {
+    __u8 struct_v = 1;
+    ::encode(struct_v, bl);
+    ::encode(server_challenge, bl);
+  }
+  void decode(bufferlist::iterator& bl) {
+    __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 {
-    __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::iterator& bl) {
     __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)
@@ -409,9 +435,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::iterator& indata,
-                                   CephXServiceTicketInfo& ticket_info, bufferlist& reply_bl);
+extern bool cephx_verify_authorizer(
+  CephContext *cct, KeyStore *keys,
+  bufferlist::iterator& indata,
+  CephXServiceTicketInfo& ticket_info,
+  std::unique_ptr<AuthAuthorizerChallenge> *challenge,
+  bufferlist& reply_bl);
 
 
 
index 3184835a14dcf14c9dd90de5a21e6bf07dda316b..b06e0080ba8fe51ab23b1b678d679c734049a13b 100644 (file)
@@ -152,7 +152,9 @@ int CephxServiceHandler::handle_request(bufferlist::iterator& indata, bufferlist
 
       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 8b55e9e9ba8b44eed8101fcde13635fb3ea00407..5767eacffd105ec0c9062fb645e675628886aaf4 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)
 {
   bufferlist::iterator iter = authorizer_data.begin();
 
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 8683c567416e7af4db397af4c765ea83cf3e7fe5..662fdb51648f643ae7c06e2ce3bde22cb01950cd 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::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 d1a22df71ab9ef7d49ab4fe013560d491d9ac043..fe3bed6109148e46b5a18e39257ef72bbf098b8e 100644 (file)
@@ -1262,7 +1262,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) {
@@ -1294,7 +1295,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 8dac42c1b6263b80bb96504b751092f8e3561c11..119b22b2d913c6ef3ec5385af82bbcc16cf773af 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 29f380ca5a6b5d398ca6d613c27062a939f6a65e..013b5fec622ad25e6cc97200979afa96ea732a7f 100644 (file)
@@ -141,13 +141,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 ||
@@ -175,7 +177,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 1dcc24b2778683c2a2021ff10bcedb294a932bd5..3b11843425a0d6579929040aaed92e2d1c7c0122 100644 (file)
@@ -123,13 +123,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_report(MMgrReport *m);
index 4be4cd78b209b308c51543ba8e48cac9438741e8..6348f44c97b8cdc6fac8cb486f951492d74f9e6f 100644 (file)
@@ -5898,7 +5898,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)
@@ -5917,7 +5918,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 4ff8706455163ff599d66ccfd139acc5f3c08dbf..008947e85be34d2203421f8d12f80e9bc00fd2cd 100644 (file)
@@ -906,7 +906,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 5af27ea17f389ed62ac7e0d2959c16dd0f1212e3..64adefbd3f28cbb695a5dbdc4d7fc754ffe54ebc 100644 (file)
@@ -17,6 +17,7 @@
 #define CEPH_DISPATCHER_H
 
 #include "include/assert.h"
+#include <memory>
 #include "include/buffer_fwd.h"
 #include "include/assert.h"
 
@@ -26,6 +27,7 @@ class Connection;
 class AuthAuthorizer;
 class CryptoKey;
 class CephContext;
+class AuthAuthorizerChallenge;
 
 class Dispatcher {
 public:
@@ -204,7 +206,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 c6dbcc17694d4e4ea594b4612313f753885bda55..5975c583d3a4ca5c6112fe173f71116dc9bd298f 100644 (file)
@@ -806,11 +806,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 37c9697004b060b8345def16819d809d7c7fd35e..80231cccf4b9b3a1f8e832eb8af3538f02b753a5 100644 (file)
@@ -1026,8 +1026,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;
@@ -1107,7 +1106,15 @@ ssize_t AsyncConnection::_process_connection()
           }
 
           authorizer_reply.append(state_buffer, connect_reply.authorizer_len);
-          bufferlist::iterator iter = authorizer_reply.begin();
+
+         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.begin();
           if (authorizer && !authorizer->verify_reply(iter)) {
             ldout(async_msgr->cct, 0) << __func__ << " failed verifying authorize reply" << dendl;
             goto fail;
@@ -1521,12 +1528,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
@@ -1720,6 +1741,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 ab2ff2c4ab05054a8a2b579d0eed26c33a97f9ad..64a7502403bb12f9a1471ff9bd3b7f24f3b375be 100644 (file)
@@ -371,6 +371,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 7ebc7777c93e611f1ca49efa78f5edc4654a0b61..6659cf29004f60b89b67ce9dbc775043ad1f9a61 100644 (file)
@@ -384,9 +384,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 d2d425f12cf69506692e1bef05edbf5928a1b832..2c1415ebc694a23d741ec959f4f912008003da6a 100644 (file)
@@ -354,6 +354,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();
@@ -514,14 +518,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;
     } 
@@ -1127,8 +1144,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;
@@ -1195,6 +1213,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) {
       bufferlist::iterator iter = authorizer_reply.begin();
       if (!authorizer->verify_reply(iter)) {
index 78e190d027e1c65c34792face5597938a285a41d..d75804b531787b12e382961f24c0c2629e8aaf8b 100644 (file)
@@ -415,9 +415,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 0a0512382eb3c337e2b8fb473fed3a6bde712466..aebc190e14e38fc8ffe3f6a495dbee1dae3e9eb6 100644 (file)
@@ -346,8 +346,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 4bcce677b83d87c24efc3c315c49d4b25f909ee2..772b9d94f8eb09047ab225bbd950e4d8529fde15 100644 (file)
@@ -7236,9 +7236,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) {
@@ -7270,7 +7272,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 ea611cbae1cb7010d09dc8c431bf6e94c07dcbc0..4523fb2807f2e62db2fc3532ed65e13f88492976 100644 (file)
@@ -1582,7 +1582,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;
     }
@@ -2359,7 +2360,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 5774c593974d27d46feb2c19ad358bbf40202d7c..b57a9c02f9da1d3b71abeaa2bf2da44a3ec81b2c 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 79e36721aa843f3e9659b13555a6c6cf789ac00c..d9bf20727b20df1aab0d0080cdadde3b6b6850d0 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 3a9397be9a689bb88500a7b6d56bfaef540ca5ff..6c56600787e16137530ae0c34462983ff6618709 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;
   }