]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
auth,msg/async/ProtocolV2: negotiate connection modes
authorSage Weil <sage@redhat.com>
Tue, 22 Jan 2019 22:59:22 +0000 (16:59 -0600)
committerSage Weil <sage@redhat.com>
Thu, 7 Feb 2019 18:10:33 +0000 (12:10 -0600)
The modes are:

- crc: crc32c checksums to protect against bit errors.  No secrecy or
  authenticity guarantees, so a MITM could alter traffic in flight.
- secure: cryptographic secrecy and authenticity proection (i.e, encrypted
  and signed).

We do not include a 'signed' mode that provides authenticity without
secrecy because the cryptographic protocols appear to be faster than
SHA-2.

New settings:

- ms_cluster_mode  : mode(s list) for intra-cluster connections
- ms_service_mode  : mode(s list) for daemons to allow
- ms_client_mode   : mode(s list) for clients to allow

Also,

- ms_mon_cluster_mode  : mon <-> mon connections
- ms_mon_service_mode  : mon <-> daemon or client connections

The msgr2 protocol is expanded slightly to negotiate a mode.  Client
shares it's allowed/preferred modes, and server picks one as auth finishes.
Negotiation is independent of the authentication, except that the
authentiction mode may precluse certain choices. Specifically, AUTH_NONE
does not support 'secure', only 'crc'.

Signed-off-by: Sage Weil <sage@redhat.com>
14 files changed:
doc/dev/msgr2.rst
src/auth/Auth.h
src/auth/AuthClient.h
src/auth/AuthRegistry.cc
src/auth/AuthRegistry.h
src/auth/AuthServer.h
src/common/options.cc
src/include/ceph_fs.h
src/mon/MonClient.cc
src/mon/MonClient.h
src/mon/Monitor.cc
src/mon/Monitor.h
src/msg/async/ProtocolV2.cc
src/msg/async/ProtocolV2.h

index b71e0d0593fdff694f9c0efb53a39792aaa96e95..7cbfe8acefa23f44d0c87438691ad400817c35bd 100644 (file)
@@ -108,6 +108,8 @@ Authentication
 * TAG_AUTH_REQUEST: client->server::
 
     __le32 method;  // CEPH_AUTH_{NONE, CEPHX, ...}
+    __le32 num_preferred_modes;
+    list<__le32> mode  // CEPH_CON_MODE_*
     method specific payload
 
 * TAG_AUTH_BAD_METHOD server -> client: reject client-selected auth method::
@@ -115,7 +117,9 @@ Authentication
     __le32 method
     __le32 negative error result code
     __le32 num_methods
-    __le32 allowed_methods[num_methods] // CEPH_AUTH_{NONE, CEPHX, ...}
+    list<__le32> allowed_methods // CEPH_AUTH_{NONE, CEPHX, ...}
+    __le32 num_modes
+    list<__le32> allowed_modes   // CEPH_CON_MODE_*
 
   - Returns the attempted auth method, and error code (-EOPNOTSUPP if
     the method is unsupported), and the list of allowed authentication
@@ -134,9 +138,11 @@ Authentication
 * TAG_AUTH_DONE: (server->client)::
 
     __le64 global_id
+    __le32 connection mode // CEPH_CON_MODE_*
     method specific payload
 
-  - The server is the one to decide authentication has completed.
+  - The server is the one to decide authentication has completed and what
+    the final connection mode will be.
 
 
 Example of authentication phase interaction when the client uses an
index 465d6d8471a2ea6c9c82a07ba61a009fa3ad9e97..2716a3ddb40df572ba45210a6bc75c9a204eb4b1 100644 (file)
@@ -162,21 +162,16 @@ struct AuthConnectionMeta {
 
   int auth_mode = 0;  ///< AUTH_MODE_*
 
-  enum {
-    CON_MODE_INTEGRITY,     // crc: protect against bit errors
-    CON_MODE_AUTHENTICITY,  // secure hash: protect against MITM
-    CON_MODE_SECRECY,       // encrypted
-  };
-  int con_mode = CON_MODE_INTEGRITY;
-
-  bool is_integrity_mode() {
-    return con_mode == CON_MODE_INTEGRITY;
-  }
-  bool is_authenticity_mode() {
-    return con_mode == CON_MODE_AUTHENTICITY;
+  /// server: client's preferred con_modes
+  std::vector<uint32_t> preferred_con_modes;
+
+  int con_mode = 0;  ///< negotiated mode
+
+  bool is_mode_crc() {
+    return con_mode == CEPH_CON_MODE_CRC;
   }
-  bool is_secrecy_mode() {
-    return con_mode == CON_MODE_SECRECY;
+  bool is_mode_secure() {
+    return con_mode == CEPH_CON_MODE_SECURE;
   }
 
   CryptoKey session_key;         ///< per-ticket key
index aa11e3c29a5c1a8dfbc16e91c5c69935292cc2f2..28eae6decce7fe2e9d792e374a7e16f2cb1ff88d 100644 (file)
@@ -14,7 +14,9 @@ public:
 
   virtual int get_auth_request(
     Connection *con,
-    uint32_t *method, bufferlist *out) = 0;
+    uint32_t *method,
+    std::vector<uint32_t> *preferred_modes,
+    bufferlist *out) = 0;
   virtual int handle_auth_reply_more(
     Connection *con,
     const bufferlist& bl,
@@ -22,6 +24,7 @@ public:
   virtual int handle_auth_done(
     Connection *con,
     uint64_t global_id,
+    uint32_t con_mode,
     const bufferlist& bl,
     CryptoKey *session_key,
     CryptoKey *connection_key) = 0;
@@ -29,5 +32,6 @@ public:
     Connection *con,
     uint32_t old_auth_method,
     int result,
-    const std::vector<uint32_t>& allowed_methods) = 0;
+    const std::vector<uint32_t>& allowed_methods,
+    const std::vector<uint32_t>& allowed_modes) = 0;
 };
index 0f2752cf55c5548ac247d907415a1d0ef1a0adcb..a6be5e7b41130fd569f635cf11a4a93608d2b751 100644 (file)
@@ -67,6 +67,33 @@ void AuthRegistry::_parse_method_list(const string& s,
   ldout(cct,20) << __func__ << " " << s << " -> " << *v << dendl;
 }
 
+void AuthRegistry::_parse_mode_list(const string& s,
+                                   std::vector<uint32_t> *v)
+{
+  std::list<std::string> sup_list;
+  get_str_list(s, sup_list);
+  if (sup_list.empty()) {
+    lderr(cct) << "WARNING: empty auth protocol list" << dendl;
+  }
+  for (auto& i : sup_list) {
+    ldout(cct, 5) << "adding con mode: " << i << dendl;
+    if (i == "crc") {
+      v->push_back(CEPH_CON_MODE_CRC);
+    } else if (i == "secure") {
+      v->push_back(CEPH_CON_MODE_SECURE);
+    } else {
+      v->push_back(CEPH_CON_MODE_UNKNOWN);
+      lderr(cct) << "WARNING: unknown connection mode " << i << dendl;
+    }
+  }
+  if (v->empty()) {
+    lderr(cct) << "WARNING: no connection modes defined, use 'crc' by default"
+              << dendl;
+    v->push_back(CEPH_CON_MODE_CRC);
+  }
+  ldout(cct,20) << __func__ << " " << s << " -> " << *v << dendl;
+}
+
 void AuthRegistry::_refresh_config()
 {
   if (cct->_conf->auth_supported.size()) {
@@ -78,6 +105,16 @@ void AuthRegistry::_refresh_config()
     _parse_method_list(cct->_conf->auth_service_required, &service_methods);
     _parse_method_list(cct->_conf->auth_client_required, &client_methods);
   }
+  _parse_mode_list(cct->_conf.get_val<string>("ms_mon_cluster_mode"),
+                  &mon_cluster_modes);
+  _parse_mode_list(cct->_conf.get_val<string>("ms_mon_service_mode"),
+                  &mon_service_modes);
+  _parse_mode_list(cct->_conf.get_val<string>("ms_cluster_mode"),
+                  &cluster_modes);
+  _parse_mode_list(cct->_conf.get_val<string>("ms_service_mode"),
+                  &service_modes);
+  _parse_mode_list(cct->_conf.get_val<string>("ms_client_mode"),
+                  &client_modes);
 
   ldout(cct,10) << __func__ << " cluster_methods " << cluster_methods
                << " service_methods " << service_methods
@@ -103,23 +140,68 @@ void AuthRegistry::_refresh_config()
   }
 }
 
-void AuthRegistry::get_supported_methods(int peer_type,
-                                        std::vector<uint32_t> *v)
+void AuthRegistry::get_supported_methods(
+  int peer_type,
+  std::vector<uint32_t> *methods,
+  std::vector<uint32_t> *modes)
 {
-  if (cct->get_module_type() == CEPH_ENTITY_TYPE_CLIENT) {
-    *v = client_methods;
+  switch (cct->get_module_type()) {
+  case CEPH_ENTITY_TYPE_CLIENT:
+    // i am client
+    if (methods) {
+      *methods = client_methods;
+    }
+    if (modes) {
+      *modes = client_modes;
+    }
     return;
-  }
-  switch (peer_type) {
   case CEPH_ENTITY_TYPE_MON:
-  case CEPH_ENTITY_TYPE_MGR:
-  case CEPH_ENTITY_TYPE_MDS:
-  case CEPH_ENTITY_TYPE_OSD:
-    *v = cluster_methods;
-    break;
+    // i am mon
+    switch (peer_type) {
+    case CEPH_ENTITY_TYPE_MON:
+      // they are mon
+      if (methods) {
+       *methods = cluster_methods;
+      }
+      if (modes) {
+       *modes = mon_cluster_modes;
+      }
+      break;
+    default:
+      // they are anything but mons
+      if (methods) {
+       *methods = service_methods;
+      }
+      if (modes) {
+       *modes = mon_service_modes;
+      }
+    }
+    return;
   default:
-    *v = service_methods;
-    break;
+    // i am a non-mon daemon
+    switch (peer_type) {
+    case CEPH_ENTITY_TYPE_MON:
+    case CEPH_ENTITY_TYPE_MGR:
+    case CEPH_ENTITY_TYPE_MDS:
+    case CEPH_ENTITY_TYPE_OSD:
+      // they are another daemon
+      if (methods) {
+       *methods = cluster_methods;
+      }
+      if (modes) {
+       *modes = cluster_modes;
+      }
+      break;
+    default:
+      // they are a client
+      if (methods) {
+       *methods = service_methods;
+      }
+      if (modes) {
+       *modes = service_modes;
+      }
+      break;
+    }
   }
 }
 
@@ -137,6 +219,25 @@ bool AuthRegistry::any_supported_methods(int peer_type)
   return !s.empty();
 }
 
+void AuthRegistry::get_supported_modes(
+  int peer_type,
+  uint32_t auth_method,
+  std::vector<uint32_t> *modes)
+{
+  std::vector<uint32_t> s;
+  get_supported_methods(peer_type, nullptr, &s);
+  if (auth_method == CEPH_AUTH_NONE) {
+    // filter out all but crc for AUTH_NONE
+    for (auto mode : s) {
+      if (mode == CEPH_CON_MODE_CRC) {
+       modes->push_back(mode);
+      }
+    }
+  } else {
+    *modes = s;
+  }
+}
+
 AuthAuthorizeHandler *AuthRegistry::get_handler(int peer_type, int method)
 {
   std::scoped_lock l{lock};
index 190b615592c28d723d591c4226414572ba82a4ab..5474355110de9fc7a4ade5b03d46033afdac81d3 100644 (file)
@@ -20,11 +20,20 @@ class AuthRegistry : public md_config_obs_t {
 
   bool _no_keyring_disabled_cephx = false;
 
-  std::vector<uint32_t> cluster_methods; // CEPH_AUTH_*
-  std::vector<uint32_t> service_methods; // CEPH_AUTH_*
-  std::vector<uint32_t> client_methods;  // CEPH_AUTH_*
+  // CEPH_AUTH_*
+  std::vector<uint32_t> cluster_methods;
+  std::vector<uint32_t> service_methods;
+  std::vector<uint32_t> client_methods;
+
+  // CEPH_CON_MODE_*
+  std::vector<uint32_t> mon_cluster_modes;
+  std::vector<uint32_t> mon_service_modes;
+  std::vector<uint32_t> cluster_modes;
+  std::vector<uint32_t> service_modes;
+  std::vector<uint32_t> client_modes;
 
   void _parse_method_list(const string& str, std::vector<uint32_t> *v);
+  void _parse_mode_list(const string& str, std::vector<uint32_t> *v);
   void _refresh_config();
 
 public:
@@ -37,10 +46,16 @@ public:
     _refresh_config();
   }
 
-  void get_supported_methods(int peer_type, std::vector<uint32_t> *v);
+  void get_supported_methods(int peer_type,
+                            std::vector<uint32_t> *methods,
+                            std::vector<uint32_t> *modes=nullptr);
   bool is_supported_method(int peer_type, int method);
   bool any_supported_methods(int peer_type);
 
+  void get_supported_modes(int peer_type,
+                          uint32_t auth_method,
+                          std::vector<uint32_t> *modes);
+
   AuthAuthorizeHandler *get_handler(int peer_type, int method);
 
   const char** get_tracked_conf_keys() const override;
index d80c1b0d81109ccb2797a4f69ea00798f1e519c0..a762dfb2110142a2ad43a60f882344c44da7d313 100644 (file)
@@ -19,8 +19,15 @@ public:
 
   virtual void get_supported_auth_methods(
     int peer_type,
-    std::vector<uint32_t> *methods) {
-    auth_registry.get_supported_methods(peer_type, methods);
+    std::vector<uint32_t> *methods,
+    std::vector<uint32_t> *modes = nullptr) {
+    auth_registry.get_supported_methods(peer_type, methods, modes);
+  }
+  virtual void get_supported_con_modes(
+    int peer_type,
+    uint32_t auth_method,
+    std::vector<uint32_t> *modes) {
+    auth_registry.get_supported_modes(peer_type, auth_method, modes);
   }
 
   AuthAuthorizeHandler *get_auth_authorize_handler(
index 8b3ef4d38e156450943afc97072c434842e13c87..1449abf9d51d00b82bf503de1e50dad222790ed2 100644 (file)
@@ -840,6 +840,40 @@ std::vector<Option> get_global_options() {
     .set_long_description("If not specified, use ms_type")
     .add_see_also("ms_type"),
 
+    Option("ms_mon_cluster_mode", Option::TYPE_STR, Option::LEVEL_BASIC)
+    .set_default("crc secure")
+    .set_description("Connection modes (crc, secure) for intra-mon connections in order of preference")
+    .add_see_also("ms_mon_service_mode")
+    .add_see_also("ms_service_mode")
+    .add_see_also("ms_cluster_mode")
+    .add_see_also("ms_client_mode"),
+
+    Option("ms_mon_service_mode", Option::TYPE_STR, Option::LEVEL_BASIC)
+    .set_default("crc secure")
+    .set_description("Connection modes (crc, secure) for connections to mons in order of preference")
+    .add_see_also("ms_service_mode")
+    .add_see_also("ms_mon_cluster_mode")
+    .add_see_also("ms_cluster_mode")
+    .add_see_also("ms_client_mode"),
+
+    Option("ms_cluster_mode", Option::TYPE_STR, Option::LEVEL_BASIC)
+    .set_default("crc secure")
+    .set_description("Connection modes (crc, secure) for intra-cluster connections in order of preference")
+    .add_see_also("ms_service_mode")
+    .add_see_also("ms_client_mode"),
+
+    Option("ms_service_mode", Option::TYPE_STR, Option::LEVEL_BASIC)
+    .set_default("crc secure")
+    .set_description("Connection modes (crc, secure) for connections to daemons in order of preference")
+    .add_see_also("ms_cluster_mode")
+    .add_see_also("ms_client_mode"),
+
+    Option("ms_client_mode", Option::TYPE_STR, Option::LEVEL_BASIC)
+    .set_default("crc secure")
+    .set_description("Connection modes (crc, secure) for connections from clients in order of preference")
+    .add_see_also("ms_cluster_mode")
+    .add_see_also("ms_service_mode"),
+
     Option("ms_tcp_nodelay", Option::TYPE_BOOL, Option::LEVEL_ADVANCED)
     .set_default(true)
     .set_description("Disable Nagle's algorithm and send queued network traffic immediately"),
index 84708338c2c7a14428a6a5530581798d5d4f10d6..4b0d3ed75f4b6ba2f7192cc95daf4ee3a61d76a5 100644 (file)
@@ -73,6 +73,11 @@ struct ceph_dir_layout {
 #define CEPH_AUTH_NONE         0x1
 #define CEPH_AUTH_CEPHX                0x2
 
+/* msgr2 protocol modes */
+#define CEPH_CON_MODE_UNKNOWN 0x0
+#define CEPH_CON_MODE_CRC     0x1
+#define CEPH_CON_MODE_SECURE  0x2
+
 /*  For options with "_", like: GSS_GSS
     which means: Mode/Protocol to validate "authentication_authorization",
     where:
index 6727434fead943b810f5f94ce77f91a94781521c..c67724ffb42353d2bf2de74295acfc10aa298400 100644 (file)
@@ -1213,6 +1213,7 @@ void MonClient::handle_get_version_reply(MMonGetVersionReply* m)
 int MonClient::get_auth_request(
   Connection *con,
   uint32_t *auth_method,
+  std::vector<uint32_t> *preferred_modes,
   bufferlist *bl)
 {
   std::lock_guard l(monc_lock);
@@ -1225,7 +1226,7 @@ int MonClient::get_auth_request(
     for (auto& i : pending_cons) {
       if (i.second.is_con(con)) {
        return i.second.get_auth_request(
-         auth_method, bl,
+         auth_method, preferred_modes, bl,
          entity_name, want_keys, rotating_secrets.get());
       }
     }
@@ -1240,6 +1241,9 @@ int MonClient::get_auth_request(
   }
   auth_meta->authorizer.reset(auth->build_authorizer(con->get_peer_type()));
   auth_meta->auth_method = auth_meta->authorizer->protocol;
+  auth_registry.get_supported_modes(con->get_peer_type(),
+                                   auth_meta->auth_method,
+                                   preferred_modes);
   *bl = auth_meta->authorizer->bl;
   return 0;
 }
@@ -1274,6 +1278,7 @@ int MonClient::handle_auth_reply_more(
 int MonClient::handle_auth_done(
   Connection *con,
   uint64_t global_id,
+  uint32_t con_mode,
   const bufferlist& bl,
   CryptoKey *session_key,
   CryptoKey *connection_key)
@@ -1319,7 +1324,8 @@ int MonClient::handle_auth_bad_method(
   Connection *con,
   uint32_t old_auth_method,
   int result,
-  const std::vector<uint32_t>& allowed_methods)
+  const std::vector<uint32_t>& allowed_methods,
+  const std::vector<uint32_t>& allowed_modes)
 {
   con->get_auth_meta()->allowed_methods = allowed_methods;
 
@@ -1329,7 +1335,8 @@ int MonClient::handle_auth_bad_method(
       if (i.second.is_con(con)) {
        int r = i.second.handle_auth_bad_method(old_auth_method,
                                                result,
-                                               allowed_methods);
+                                               allowed_methods,
+                                               allowed_modes);
        if (r == 0) {
          return r; // try another method on this con
        }
@@ -1462,7 +1469,9 @@ void MonConnection::start(epoch_t epoch,
 }
 
 int MonConnection::get_auth_request(
-  uint32_t *method, bufferlist *bl,
+  uint32_t *method,
+  std::vector<uint32_t> *preferred_modes,
+  bufferlist *bl,
   const EntityName& entity_name,
   uint32_t want_keys,
   RotatingKeyRing* keyring)
@@ -1474,7 +1483,10 @@ int MonConnection::get_auth_request(
     auth_method = as.front();
   }
   *method = auth_method;
-  ldout(cct,10) << __func__ << " method " << *method << dendl;
+  auth_registry->get_supported_modes(con->get_peer_type(), auth_method,
+                                    preferred_modes);
+  ldout(cct,10) << __func__ << " method " << *method
+               << " preferred_modes " << *preferred_modes << dendl;
 
   if (auth) {
     auth.reset();
@@ -1547,7 +1559,8 @@ int MonConnection::handle_auth_done(
 int MonConnection::handle_auth_bad_method(
   uint32_t old_auth_method,
   int result,
-  const std::vector<uint32_t>& allowed_methods)
+  const std::vector<uint32_t>& allowed_methods,
+  const std::vector<uint32_t>& allowed_modes)
 {
   ldout(cct,10) << __func__ << " old_auth_method " << old_auth_method
                << " result " << cpp_strerror(result)
index be73a2f68ef2030a052d0e6c019098dc011d37c7..b2838d9c80689659400c537b39f81cc2f73e865e 100644 (file)
@@ -128,7 +128,9 @@ public:
   }
 
   int get_auth_request(
-    uint32_t *method, bufferlist *out,
+    uint32_t *method,
+    std::vector<uint32_t> *preferred_modes,
+    bufferlist *out,
     const EntityName& entity_name,
     uint32_t want_keys,
     RotatingKeyRing* keyring);
@@ -143,7 +145,8 @@ public:
   int handle_auth_bad_method(
     uint32_t old_auth_method,
     int result,
-    const std::vector<uint32_t>& allowed_methods);
+    const std::vector<uint32_t>& allowed_methods,
+    const std::vector<uint32_t>& allowed_modes);
 
   bool is_con(Connection *c) const {
     return con.get() == c;
@@ -269,6 +272,7 @@ public:
   int get_auth_request(
     Connection *con,
     uint32_t *method,
+    std::vector<uint32_t> *preferred_modes,
     bufferlist *bl) override;
   int handle_auth_reply_more(
     Connection *con,
@@ -277,6 +281,7 @@ public:
   int handle_auth_done(
     Connection *con,
     uint64_t global_id,
+    uint32_t con_mode,
     const bufferlist& bl,
     CryptoKey *session_key,
     CryptoKey *connection_key) override;
@@ -284,7 +289,8 @@ public:
     Connection *con,
     uint32_t old_auth_method,
     int result,
-    const std::vector<uint32_t>& allowed_methods) override;
+    const std::vector<uint32_t>& allowed_methods,
+    const std::vector<uint32_t>& allowed_modes) override;
   // AuthServer
   int handle_auth_request(
     Connection *con,
index 724feb68f4fb42790ec23a5ba0c9f7ec3217b040..777f3822c4dfe9951d0346420f61b943efe1487f 100644 (file)
@@ -5867,15 +5867,22 @@ void Monitor::extract_save_mon_key(KeyRing& keyring)
 // AuthClient methods -- for mon <-> mon communication
 int Monitor::get_auth_request(
   Connection *con,
-  uint32_t *method, bufferlist *out)
+  uint32_t *method,
+  vector<uint32_t> *preferred_modes,
+  bufferlist *out)
 {
   AuthAuthorizer *auth;
   if (!ms_get_authorizer(con->get_peer_type(), &auth)) {
     return -EACCES;
   }
+  if (con->get_peer_type() != CEPH_ENTITY_TYPE_MON) {
+    return -EACCES;
+  }
   auto auth_meta = con->get_auth_meta();
   auth_meta->authorizer.reset(auth);
   *method = auth->protocol;
+  auth_registry.get_supported_modes(CEPH_ENTITY_TYPE_MON, auth->protocol,
+                                   preferred_modes);
   *out = auth->bl;
   return 0;
 }
@@ -5898,6 +5905,7 @@ int Monitor::handle_auth_reply_more(
 int Monitor::handle_auth_done(
   Connection *con,
   uint64_t global_id,
+  uint32_t con_mode,
   const bufferlist& bl,
   CryptoKey *session_key,
   CryptoKey *connection_key)
@@ -5917,7 +5925,8 @@ int Monitor::handle_auth_bad_method(
   Connection *con,
   uint32_t old_auth_method,
   int result,
-  const std::vector<uint32_t>& allowed_methods)
+  const std::vector<uint32_t>& allowed_methods,
+  const std::vector<uint32_t>& allowed_modes)
 {
   derr << __func__ << " hmm, they didn't like " << old_auth_method
        << " result " << cpp_strerror(result) << dendl;
index 7aa912c8dafb8838b72f4c1dd179b43025c5604e..5d674124ed65b15f24cb96468879421545cbea5b 100644 (file)
@@ -909,7 +909,9 @@ private:
   // AuthClient
   int get_auth_request(
     Connection *con,
-    uint32_t *method, bufferlist *out) override;
+    uint32_t *method,
+    vector<uint32_t> *preferred_modes,
+    bufferlist *out) override;
   int handle_auth_reply_more(
     Connection *con,
     const bufferlist& bl,
@@ -917,6 +919,7 @@ private:
   int handle_auth_done(
     Connection *con,
     uint64_t global_id,
+    uint32_t con_mode,
     const bufferlist& bl,
     CryptoKey *session_key,
     CryptoKey *connection_key) override;
@@ -924,7 +927,8 @@ private:
     Connection *con,
     uint32_t old_auth_method,
     int result,
-    const std::vector<uint32_t>& allowed_methods) override;
+    const std::vector<uint32_t>& allowed_methods,
+    const std::vector<uint32_t>& allowed_modes) override;
   // /AuthClient
   // AuthServer
   int handle_auth_request(
index 8e0c979fc094c229757d5f1aa545854c6537d690..6b3516db47178a06973537b8a51007a2861e6b17 100644 (file)
@@ -255,25 +255,29 @@ struct HelloFrame : public PayloadFrame<HelloFrame,
 };
 
 struct AuthRequestFrame
-    : public PayloadFrame<AuthRequestFrame, uint32_t, bufferlist> {
+  : public PayloadFrame<AuthRequestFrame,
+                       uint32_t, vector<uint32_t>, bufferlist> {
   const ProtocolV2::Tag tag = ProtocolV2::Tag::AUTH_REQUEST;
   using PayloadFrame::PayloadFrame;
 
-  AuthRequestFrame(uint32_t method) : AuthRequestFrame(method, bufferlist()) {}
-
   inline uint32_t &method() { return get_val<0>(); }
-  inline bufferlist &auth_payload() { return get_val<1>(); }
+  inline vector<uint32_t> &preferred_modes() { return get_val<1>(); }
+  inline bufferlist &auth_payload() { return get_val<2>(); }
 };
 
 struct AuthBadMethodFrame
   : public PayloadFrame<AuthBadMethodFrame,
-                       uint32_t, int32_t, std::vector<uint32_t>> {
+                       uint32_t, // method
+                       int32_t,  // result
+                       std::vector<uint32_t>,   // allowed_methods
+                       std::vector<uint32_t>> { // allowed_modes
   const ProtocolV2::Tag tag = ProtocolV2::Tag::AUTH_BAD_METHOD;
   using PayloadFrame::PayloadFrame;
 
   inline uint32_t &method() { return get_val<0>(); }
   inline int32_t &result() { return get_val<1>(); }
   inline std::vector<uint32_t> &allowed_methods() { return get_val<2>(); }
+  inline std::vector<uint32_t> &allowed_modes() { return get_val<3>(); }
 };
 
 struct AuthReplyMoreFrame
@@ -293,12 +297,16 @@ struct AuthRequestMoreFrame
 };
 
 struct AuthDoneFrame
-  : public PayloadFrame<AuthDoneFrame, uint64_t, bufferlist> {
+  : public PayloadFrame<AuthDoneFrame,
+                       uint64_t, // global_id
+                       uint32_t, // con_mode
+                       bufferlist> { // auth method payload
   const ProtocolV2::Tag tag = ProtocolV2::Tag::AUTH_DONE;
   using PayloadFrame::PayloadFrame;
 
   inline uint64_t &global_id() { return get_val<0>(); }
-  inline bufferlist &auth_payload() { return get_val<1>(); }
+  inline uint32_t &con_mode() { return get_val<1>(); }
+  inline bufferlist &auth_payload() { return get_val<2>(); }
 };
 
 template <class T, typename... Args>
@@ -1060,7 +1068,7 @@ bool ProtocolV2::is_queued() {
 void ProtocolV2::sign_payload(bufferlist &payload) {
   ldout(cct, 21) << __func__ << " len=" << payload.length() << dendl;
 
-  if (auth_meta.is_authenticity_mode() && session_security) {
+  if (false && session_security) {
     uint32_t pad_len;
     calculate_payload_size(payload.length(), nullptr, &pad_len);
     auto padding = bufferptr(buffer::create(pad_len));
@@ -1086,7 +1094,7 @@ void ProtocolV2::sign_payload(bufferlist &payload) {
 void ProtocolV2::verify_signature(char *payload, uint32_t length) {
   ldout(cct, 21) << __func__ << " len=" << length << dendl;
 
-  if (auth_meta.is_authenticity_mode() && session_security) {
+  if (false && session_security) {
     uint32_t payload_len = length - CEPH_CRYPTO_HMACSHA256_DIGESTSIZE;
     const char *p = payload + payload_len;
     char signature[CEPH_CRYPTO_HMACSHA256_DIGESTSIZE];
@@ -1103,7 +1111,7 @@ void ProtocolV2::verify_signature(char *payload, uint32_t length) {
 
 void ProtocolV2::encrypt_payload(bufferlist &payload) {
   ldout(cct, 21) << __func__ << " len=" << payload.length() << dendl;
-  if (auth_meta.is_secrecy_mode() && session_security) {
+  if (auth_meta.is_mode_secure()) {
     uint32_t pad_len;
     calculate_payload_size(payload.length(), nullptr, nullptr, &pad_len);
     if (pad_len) {
@@ -1120,7 +1128,7 @@ void ProtocolV2::encrypt_payload(bufferlist &payload) {
 
 void ProtocolV2::decrypt_payload(char *payload, uint32_t &length) {
   ldout(cct, 21) << __func__ << " len=" << length << dendl;
-  if (auth_meta.is_secrecy_mode() && session_security) {
+  if (auth_meta.is_mode_secure() && session_security) {
     bufferlist in;
     in.push_back(buffer::create_static(length, payload));
     bufferlist out;
@@ -1136,8 +1144,8 @@ void ProtocolV2::decrypt_payload(char *payload, uint32_t &length) {
 void ProtocolV2::calculate_payload_size(uint32_t length, uint32_t *total_len,
                                         uint32_t *sig_pad_len,
                                         uint32_t *enc_pad_len) {
-  bool is_signed = auth_meta.is_authenticity_mode();
-  bool is_encrypted = auth_meta.is_secrecy_mode();
+  bool is_signed = auth_meta.is_mode_secure(); // REMOVE ME
+  bool is_encrypted = auth_meta.is_mode_secure();
 
   uint32_t sig_pad_l = 0;
   uint32_t enc_pad_l = 0;
@@ -1801,8 +1809,7 @@ CtPtr ProtocolV2::read_message_data() {
     // the message payload
     ldout(cct, 1) << __func__ << " reading message payload extra bytes left="
                   << next_payload_len << dendl;
-    ceph_assert(session_security && (auth_meta.is_authenticity_mode() ||
-                                    auth_meta.is_secrecy_mode()));
+    ceph_assert(session_security && (auth_meta.is_mode_secure()));
     extra.push_back(buffer::create(next_payload_len));
     return READB(next_payload_len, extra.c_str(), handle_message_extra_bytes);
   }
@@ -1864,7 +1871,7 @@ CtPtr ProtocolV2::handle_message_complete() {
   ceph_msg_footer footer{current_header.front_crc, current_header.middle_crc,
                          current_header.data_crc, 0, current_header.flags};
 
-  if (auth_meta.is_authenticity_mode() || auth_meta.is_secrecy_mode()) {
+  if (auth_meta.is_mode_secure()) {
     bufferlist msg_payload;
     msg_payload.claim_append(front);
     msg_payload.claim_append(middle);
@@ -2089,9 +2096,10 @@ CtPtr ProtocolV2::send_auth_request(std::vector<uint32_t> &allowed_methods) {
   ceph_assert(messenger->auth_client);
 
   bufferlist bl;
+  vector<uint32_t> preferred_modes;
   connection->lock.unlock();
   int r = messenger->auth_client->get_auth_request(
-    connection, &auth_meta.auth_method, &bl);
+    connection, &auth_meta.auth_method, &preferred_modes, &bl);
   connection->lock.lock();
   if (state != State::CONNECTING) {
     return _fault();
@@ -2103,7 +2111,7 @@ CtPtr ProtocolV2::send_auth_request(std::vector<uint32_t> &allowed_methods) {
     connection->dispatch_queue->queue_reset(connection);
     return nullptr;
   }
-  AuthRequestFrame frame(auth_meta.auth_method, bl);
+  AuthRequestFrame frame(auth_meta.auth_method, preferred_modes, bl);
   return WRITE(frame.get_buffer(), "auth request", read_frame);
 }
 
@@ -2114,12 +2122,14 @@ CtPtr ProtocolV2::handle_auth_bad_method(char *payload, uint32_t length) {
   ldout(cct, 1) << __func__ << " method=" << bad_method.method()
                << " result " << cpp_strerror(bad_method.result())
                 << ", allowed methods=" << bad_method.allowed_methods()
+               << ", allowed modes=" << bad_method.allowed_modes()
                 << dendl;
   ceph_assert(messenger->auth_client);
   connection->lock.unlock();
   int r = messenger->auth_client->handle_auth_bad_method(
     connection, bad_method.method(), bad_method.result(),
-    bad_method.allowed_methods());
+    bad_method.allowed_methods(),
+    bad_method.allowed_modes());
   connection->lock.lock();
   if (state != State::CONNECTING || r < 0) {
     return _fault();
@@ -2164,6 +2174,7 @@ CtPtr ProtocolV2::handle_auth_done(char *payload, uint32_t length) {
   int r = messenger->auth_client->handle_auth_done(
     connection,
     auth_done.global_id(),
+    auth_done.con_mode(),
     auth_done.auth_payload(),
     &auth_meta.session_key,
     &auth_meta.connection_secret);
@@ -2406,12 +2417,31 @@ CtPtr ProtocolV2::post_server_banner_exchange() {
 }
 
 CtPtr ProtocolV2::handle_auth_request(char *payload, uint32_t length) {
-  AuthRequestFrame auth_request(payload, length);
-  ldout(cct, 10) << __func__ << " AuthRequest(method=" << auth_request.method()
-                 << ", auth_len=" << auth_request.auth_payload().length() << ")"
+  AuthRequestFrame request(payload, length);
+  ldout(cct, 10) << __func__ << " AuthRequest(method=" << request.method()
+                << ", preferred_modes=" << request.preferred_modes()
+                 << ", payload_len=" << request.auth_payload().length() << ")"
                  << dendl;
-  auth_meta.auth_method = auth_request.method();
-  return _handle_auth_request(auth_request.auth_payload(), false);
+  auth_meta.auth_method = request.method();
+  auth_meta.preferred_con_modes = request.preferred_modes();
+  return _handle_auth_request(request.auth_payload(), false);
+}
+
+CtPtr ProtocolV2::_auth_bad_method(int r)
+{
+  ceph_assert(r < 0);
+  std::vector<uint32_t> allowed_methods;
+  std::vector<uint32_t> allowed_modes;
+  messenger->auth_server->get_supported_auth_methods(
+    connection->get_peer_type(), &allowed_methods, &allowed_modes);
+  ldout(cct, 1) << __func__ << " auth_method " << auth_meta.auth_method
+               << " r " << cpp_strerror(r)
+               << ", allowed_methods " << allowed_methods
+               << ", allowed_modes " << allowed_modes
+               << dendl;
+  AuthBadMethodFrame bad_method(auth_meta.auth_method, r, allowed_methods,
+                               allowed_modes);
+  return WRITE(bad_method.get_buffer(), "bad auth method", read_frame);
 }
 
 CtPtr ProtocolV2::_handle_auth_request(bufferlist& auth_payload, bool more)
@@ -2433,8 +2463,29 @@ CtPtr ProtocolV2::_handle_auth_request(bufferlist& auth_payload, bool more)
     return _fault();
   }
   if (r == 1) {
-    AuthDoneFrame auth_done(connection->peer_global_id, reply);
-    return WRITE(auth_done.get_buffer(), "auth done", read_frame);
+    // select a connection mode
+    std::vector<uint32_t> allowed_modes;
+    messenger->auth_server->get_supported_con_modes(
+      connection->get_peer_type(), auth_meta.auth_method, &allowed_modes);
+    for (auto mode : allowed_modes) {
+      if (std::find(auth_meta.preferred_con_modes.begin(),
+                   auth_meta.preferred_con_modes.end(),
+                   mode) != auth_meta.preferred_con_modes.end()) {
+       auth_meta.con_mode = mode;
+       break;
+      }
+    }
+    if (auth_meta.con_mode == 0) {
+      ldout(cct, 1) << __func__ << " failed to select connection mode, i allow "
+                   << allowed_modes
+                   << ", client prefers " << auth_meta.preferred_con_modes
+                   << dendl;
+      return _auth_bad_method(-EOPNOTSUPP);
+    } else {
+      AuthDoneFrame auth_done(connection->peer_global_id, auth_meta.con_mode,
+                             reply);
+      return WRITE(auth_done.get_buffer(), "auth done", read_frame);
+    }
   } else if (r == 0) {
     AuthReplyMoreFrame more(reply);
     return WRITE(more.get_buffer(), "auth reply more", read_frame);
@@ -2442,16 +2493,7 @@ CtPtr ProtocolV2::_handle_auth_request(bufferlist& auth_payload, bool more)
     // kick the client and maybe they'll come back later
     return _fault();
   } else {
-    ceph_assert(r < 0);
-    std::vector<uint32_t> allowed_methods;
-    messenger->auth_server->get_supported_auth_methods(
-      connection->get_peer_type(), &allowed_methods);
-    ldout(cct, 1) << __func__ << " auth_method " << auth_meta.auth_method
-                 << " r " << cpp_strerror(r)
-                  << ", allowed_methods " << allowed_methods
-                 << dendl;
-    AuthBadMethodFrame bad_method(auth_meta.auth_method, r, allowed_methods);
-    return WRITE(bad_method.get_buffer(), "bad auth method", read_frame);
+    return _auth_bad_method(r);
   }
 }
 
index 8e31aeb21dd1f2fffa0f47c126fd96dc29b75fab..4599b09ce401d7fdddc96d485f3e2e1b811f6fc9 100644 (file)
@@ -243,6 +243,7 @@ private:
   Ct<ProtocolV2> *handle_auth_request(char *payload, uint32_t length);
   Ct<ProtocolV2> *handle_auth_request_more(char *payload, uint32_t length);
   Ct<ProtocolV2> *_handle_auth_request(bufferlist& auth_payload, bool more);
+  Ct<ProtocolV2> *_auth_bad_method(int r);
   Ct<ProtocolV2> *handle_client_ident(char *payload, uint32_t length);
   Ct<ProtocolV2> *handle_ident_missing_features_write(int r);
   Ct<ProtocolV2> *handle_reconnect(char *payload, uint32_t length);