]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
msg/async, v2: introduce pre_auth exchanges with CRC32.
authorRadoslaw Zarzynski <rzarzyns@redhat.com>
Sat, 9 Mar 2019 02:47:21 +0000 (03:47 +0100)
committerRadoslaw Zarzynski <rzarzyns@redhat.com>
Wed, 13 Mar 2019 00:23:08 +0000 (01:23 +0100)
CRC32 is just scaffolding and will be replaced with
HMAC-SHA256 or other msg auth code.

Signed-off-by: Radoslaw Zarzynski <rzarzyns@redhat.com>
src/msg/async/ProtocolV2.cc
src/msg/async/ProtocolV2.h
src/msg/async/frames_v2.h

index 7dbf4d7a9937a7a2db306cee14c0eafbcaf37e85..3880c59867269d4f281720ea2375534a1ae0dbbb 100644 (file)
@@ -224,6 +224,9 @@ void ProtocolV2::reset_recv_state() {
     auth_meta.reset(new AuthConnectionMeta);
     session_stream_handlers.tx.reset(nullptr);
     session_stream_handlers.rx.reset(nullptr);
+    pre_auth.enabled = true;
+    pre_auth.txbuf.clear();
+    pre_auth.rxbuf.clear();
   }
 
   // clean read and write callbacks
@@ -1052,6 +1055,7 @@ CtPtr ProtocolV2::handle_read_frame_dispatch() {
     case Tag::AUTH_REPLY_MORE:
     case Tag::AUTH_REQUEST_MORE:
     case Tag::AUTH_DONE:
+    case Tag::AUTH_SIGNATURE:
     case Tag::CLIENT_IDENT:
     case Tag::SERVER_IDENT:
     case Tag::IDENT_MISSING_FEATURES:
@@ -1161,6 +1165,8 @@ CtPtr ProtocolV2::handle_frame_payload() {
       return handle_auth_request_more(payload);
     case Tag::AUTH_DONE:
       return handle_auth_done(payload);
+    case Tag::AUTH_SIGNATURE:
+      return handle_auth_signature(payload);
     case Tag::CLIENT_IDENT:
       return handle_client_ident(payload);
     case Tag::SERVER_IDENT:
@@ -1771,6 +1777,16 @@ CtPtr ProtocolV2::handle_auth_done(ceph::bufferlist &payload)
   session_stream_handlers = \
     ceph::crypto::onwire::rxtx_t::create_handler_pair(cct, *auth_meta, false);
 
+  state = AUTH_CONNECTING_SIGN;
+
+  // FIXME, WIP: crc32 is just scaffolding
+  auto sig_frame = AuthSignatureFrame::Encode(pre_auth.rxbuf.crc32c(-1));
+  pre_auth.enabled = false;
+  pre_auth.rxbuf.clear();
+  return WRITE(sig_frame, "auth signature", read_frame);
+}
+
+CtPtr ProtocolV2::finish_client_auth() {
   if (!server_cookie) {
     ceph_assert(connect_seq == 0);
     state = SESSION_CONNECTING;
@@ -2145,7 +2161,7 @@ CtPtr ProtocolV2::_handle_auth_request(bufferlist& auth_payload, bool more)
   }
   if (r == 1) {
     INTERCEPT(10);
-    state = SESSION_ACCEPTING;
+    state = AUTH_ACCEPTING_SIGN;
 
     auto auth_done = AuthDoneFrame::Encode(connection->peer_global_id,
                                            auth_meta->con_mode,
@@ -2167,9 +2183,16 @@ CtPtr ProtocolV2::_handle_auth_request(bufferlist& auth_payload, bool more)
 CtPtr ProtocolV2::finish_auth()
 {
   ceph_assert(auth_meta);
+  // TODO: having a possibility to check whether we're server or client could
+  // allow reusing finish_auth().
   session_stream_handlers = \
     ceph::crypto::onwire::rxtx_t::create_handler_pair(cct, *auth_meta, true);
-  return CONTINUE(read_frame);
+
+  // FIXME, WIP: crc32 is just scaffolding
+  auto sig_frame = AuthSignatureFrame::Encode(pre_auth.rxbuf.crc32c(-1));
+  pre_auth.enabled = false;
+  pre_auth.rxbuf.clear();
+  return WRITE(sig_frame, "auth signature", read_frame);
 }
 
 CtPtr ProtocolV2::handle_auth_request_more(ceph::bufferlist &payload)
@@ -2186,6 +2209,47 @@ CtPtr ProtocolV2::handle_auth_request_more(ceph::bufferlist &payload)
   return _handle_auth_request(auth_more.auth_payload(), true);
 }
 
+CtPtr ProtocolV2::handle_auth_signature(ceph::bufferlist &payload)
+{
+  ldout(cct, 20) << __func__
+                << " payload.length()=" << payload.length() << dendl;
+
+  if (state != AUTH_ACCEPTING_SIGN && state != AUTH_CONNECTING_SIGN) {
+    lderr(cct) << __func__
+               << " pre-auth verification signature seen in wrong state!"
+               << dendl;
+    return _fault();
+  }
+
+  auto sig_frame = AuthSignatureFrame::Decode(payload);
+
+  const auto actual_tx_sig = pre_auth.txbuf.crc32c(-1);
+  if (sig_frame.signature() != actual_tx_sig) {
+    ldout(cct, 2) << __func__ << " pre-auth signature mismatch"
+                  << " actual_tx_sig=" << actual_tx_sig
+                  << " sig_frame.signature()=" << sig_frame.signature()
+                  << dendl;
+    return _fault();
+  } else {
+    ldout(cct, 20) << __func__ << " pre-auth signature success"
+                   << " sig_frame.signature()=" << sig_frame.signature()
+                   << dendl;
+    pre_auth.txbuf.clear();
+  }
+
+  if (state == AUTH_ACCEPTING_SIGN) {
+    // server had sent AuthDone and client responded with correct pre-auth
+    // signature. we can start accepting new sessions/reconnects.
+    state = SESSION_ACCEPTING;
+    return CONTINUE(read_frame);
+  } else if (state == AUTH_CONNECTING_SIGN) {
+    // this happened at client side
+    return finish_client_auth();
+  } else {
+    ceph_assert_always("state corruption" == nullptr);
+  }
+}
+
 CtPtr ProtocolV2::handle_client_ident(ceph::bufferlist &payload)
 {
   ldout(cct, 20) << __func__
index 825f873e0dd5ac8a4503c853b5d5ed56dafbdf47..9ea40de8459e4391ca48c8e7d3339974c2cf6b11 100644 (file)
@@ -18,6 +18,7 @@ private:
     BANNER_CONNECTING,
     HELLO_CONNECTING,
     AUTH_CONNECTING,
+    AUTH_CONNECTING_SIGN,
     SESSION_CONNECTING,
     SESSION_RECONNECTING,
     START_ACCEPT,
@@ -25,6 +26,7 @@ private:
     HELLO_ACCEPTING,
     AUTH_ACCEPTING,
     AUTH_ACCEPTING_MORE,
+    AUTH_ACCEPTING_SIGN,
     SESSION_ACCEPTING,
     READY,
     THROTTLE_MESSAGE,
@@ -43,6 +45,7 @@ private:
                                       "BANNER_CONNECTING",
                                       "HELLO_CONNECTING",
                                       "AUTH_CONNECTING",
+                                      "AUTH_CONNECTING_SIGN",
                                       "SESSION_CONNECTING",
                                       "SESSION_RECONNECTING",
                                       "START_ACCEPT",
@@ -50,6 +53,7 @@ private:
                                       "HELLO_ACCEPTING",
                                       "AUTH_ACCEPTING",
                                       "AUTH_ACCEPTING_MORE",
+                                      "AUTH_ACCEPTING_SIGN",
                                       "SESSION_ACCEPTING",
                                       "READY",
                                       "THROTTLE_MESSAGE",
@@ -159,6 +163,7 @@ private:
 
   Ct<ProtocolV2> *read_frame();
   Ct<ProtocolV2> *finish_auth();
+  Ct<ProtocolV2> *finish_client_auth();
   Ct<ProtocolV2> *handle_read_frame_preamble_main(rx_buffer_t &&buffer, int r);
   Ct<ProtocolV2> *read_frame_segment();
   Ct<ProtocolV2> *handle_read_frame_segment(rx_buffer_t &&rx_buffer, int r);
@@ -212,6 +217,7 @@ private:
   Ct<ProtocolV2> *handle_auth_bad_method(ceph::bufferlist &payload);
   Ct<ProtocolV2> *handle_auth_reply_more(ceph::bufferlist &payload);
   Ct<ProtocolV2> *handle_auth_done(ceph::bufferlist &payload);
+  Ct<ProtocolV2> *handle_auth_signature(ceph::bufferlist &payload);
   Ct<ProtocolV2> *send_client_ident();
   Ct<ProtocolV2> *send_reconnect();
   Ct<ProtocolV2> *handle_ident_missing_features(ceph::bufferlist &payload);
index e979743dc2480887c31ba9c4823804594798f1ba..f58358f8993cd593f118ab072189f77d74550e81 100644 (file)
@@ -39,6 +39,7 @@ enum class Tag : __u8 {
   AUTH_REPLY_MORE,
   AUTH_REQUEST_MORE,
   AUTH_DONE,
+  AUTH_SIGNATURE,
   CLIENT_IDENT,
   SERVER_IDENT,
   IDENT_MISSING_FEATURES,
@@ -471,6 +472,20 @@ protected:
   using ControlFrame::ControlFrame;
 };
 
+struct AuthSignatureFrame
+    : public ControlFrame<AuthSignatureFrame,
+                          // FIXME: using crc32 as scaffolding
+                          uint32_t> {
+  static const Tag tag = Tag::AUTH_SIGNATURE;
+  using ControlFrame::Encode;
+  using ControlFrame::Decode;
+
+  inline uint32_t &signature() { return get_val<0>(); }
+
+protected:
+  using ControlFrame::ControlFrame;
+};
+
 struct ClientIdentFrame
     : public ControlFrame<ClientIdentFrame,
                           entity_addrvec_t,  // my addresses