From a70a3563b05cf9e3445f2137c53545567d6a98d2 Mon Sep 17 00:00:00 2001 From: Radoslaw Zarzynski Date: Sat, 9 Mar 2019 03:47:21 +0100 Subject: [PATCH] msg/async, v2: introduce pre_auth exchanges with CRC32. CRC32 is just scaffolding and will be replaced with HMAC-SHA256 or other msg auth code. Signed-off-by: Radoslaw Zarzynski --- src/msg/async/ProtocolV2.cc | 68 +++++++++++++++++++++++++++++++++++-- src/msg/async/ProtocolV2.h | 6 ++++ src/msg/async/frames_v2.h | 15 ++++++++ 3 files changed, 87 insertions(+), 2 deletions(-) diff --git a/src/msg/async/ProtocolV2.cc b/src/msg/async/ProtocolV2.cc index 7dbf4d7a993..3880c598672 100644 --- a/src/msg/async/ProtocolV2.cc +++ b/src/msg/async/ProtocolV2.cc @@ -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__ diff --git a/src/msg/async/ProtocolV2.h b/src/msg/async/ProtocolV2.h index 825f873e0dd..9ea40de8459 100644 --- a/src/msg/async/ProtocolV2.h +++ b/src/msg/async/ProtocolV2.h @@ -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 *read_frame(); Ct *finish_auth(); + Ct *finish_client_auth(); Ct *handle_read_frame_preamble_main(rx_buffer_t &&buffer, int r); Ct *read_frame_segment(); Ct *handle_read_frame_segment(rx_buffer_t &&rx_buffer, int r); @@ -212,6 +217,7 @@ private: Ct *handle_auth_bad_method(ceph::bufferlist &payload); Ct *handle_auth_reply_more(ceph::bufferlist &payload); Ct *handle_auth_done(ceph::bufferlist &payload); + Ct *handle_auth_signature(ceph::bufferlist &payload); Ct *send_client_ident(); Ct *send_reconnect(); Ct *handle_ident_missing_features(ceph::bufferlist &payload); diff --git a/src/msg/async/frames_v2.h b/src/msg/async/frames_v2.h index e979743dc24..f58358f8993 100644 --- a/src/msg/async/frames_v2.h +++ b/src/msg/async/frames_v2.h @@ -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 { + 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