From ecbd4a8aa8e6c1c72af4e0be15e0340629bfdc3a Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Tue, 11 Sep 2018 14:38:05 -0500 Subject: [PATCH] mds: move session setup into ms_handle_authentication Signed-off-by: Sage Weil --- src/mds/MDSDaemon.cc | 167 ++++++++++++++++++++++--------------------- src/mds/MDSDaemon.h | 1 + 2 files changed, 88 insertions(+), 80 deletions(-) diff --git a/src/mds/MDSDaemon.cc b/src/mds/MDSDaemon.cc index 99f12fc7eda..cd6bc4e032e 100644 --- a/src/mds/MDSDaemon.cc +++ b/src/mds/MDSDaemon.cc @@ -1323,14 +1323,12 @@ bool MDSDaemon::ms_verify_authorizer(Connection *con, int peer_type, return true; } - AuthCapsInfo caps_info; - EntityName name; - uint64_t global_id; - if (auto keys = monc->rotating_secrets.get(); keys) { is_valid = authorize_handler->verify_authorizer( cct, keys, - authorizer_data, authorizer_reply, name, global_id, caps_info, + authorizer_data, authorizer_reply, + con->peer_name, con->peer_global_id, + con->peer_caps_info, session_key, challenge); } else { dout(10) << __func__ << " no rotating_keys (yet), denied" << dendl; @@ -1338,84 +1336,93 @@ bool MDSDaemon::ms_verify_authorizer(Connection *con, int peer_type, } if (is_valid) { - entity_name_t n(con->get_peer_type(), global_id); - - // We allow connections and assign Session instances to connections - // even if we have not been assigned a rank, because clients with - // "allow *" are allowed to connect and do 'tell' operations before - // we have a rank. - Session *s = NULL; - if (mds_rank) { - // If we do hold a rank, see if this is an existing client establishing - // a new connection, rather than a new client - s = mds_rank->sessionmap.get_session(n); - } - - // Wire up a Session* to this connection - // It doesn't go into a SessionMap instance until it sends an explicit - // request to open a session (initial state of Session is `closed`) - if (!s) { - s = new Session(con); - s->info.auth_name = name; - s->info.inst.addr = con->get_peer_addr(); - s->info.inst.name = n; - dout(10) << " new session " << s << " for " << s->info.inst << " con " << con << dendl; - con->set_priv(RefCountedPtr{s, false}); - if (mds_rank) { - mds_rank->kick_waiters_for_any_client_connection(); - } - } else { - dout(10) << " existing session " << s << " for " << s->info.inst - << " existing con " << s->get_connection() - << ", new/authorizing con " << con << dendl; - con->set_priv(RefCountedPtr{s}); - - - - // Wait until we fully accept the connection before setting - // s->connection. In particular, if there are multiple incoming - // connection attempts, they will all get their authorizer - // validated, but some of them may "lose the race" and get - // dropped. We only want to consider the winner(s). See - // ms_handle_accept(). This is important for Sessions we replay - // from the journal on recovery that don't have established - // messenger state; we want the con from only the winning - // connect attempt(s). (Normal reconnects that don't follow MDS - // recovery are reconnected to the existing con by the - // messenger.) - } - - if (caps_info.allow_all) { - // Flag for auth providers that don't provide cap strings - s->auth_caps.set_allow_all(); - } else { - auto p = caps_info.caps.cbegin(); - string auth_cap_str; - try { - decode(auth_cap_str, p); - - dout(10) << __func__ << ": parsing auth_cap_str='" << auth_cap_str << "'" << dendl; - std::ostringstream errstr; - if (!s->auth_caps.parse(g_ceph_context, auth_cap_str, &errstr)) { - dout(1) << __func__ << ": auth cap parse error: " << errstr.str() - << " parsing '" << auth_cap_str << "'" << dendl; - clog->warn() << name << " mds cap '" << auth_cap_str - << "' does not parse: " << errstr.str(); - is_valid = false; - } - } catch (buffer::error& e) { - // Assume legacy auth, defaults to: - // * permit all filesystem ops - // * permit no `tell` ops - dout(1) << __func__ << ": cannot decode auth caps bl of length " << caps_info.caps.length() << dendl; - is_valid = false; - } - } + ms_handle_authentication(con); } - - return true; // we made a decision (see is_valid) + return true; } +int MDSDaemon::ms_handle_authentication(Connection *con) +{ + int ret = 0; + entity_name_t n(con->get_peer_type(), con->get_peer_global_id()); + + // We allow connections and assign Session instances to connections + // even if we have not been assigned a rank, because clients with + // "allow *" are allowed to connect and do 'tell' operations before + // we have a rank. + Session *s = NULL; + if (mds_rank) { + // If we do hold a rank, see if this is an existing client establishing + // a new connection, rather than a new client + s = mds_rank->sessionmap.get_session(n); + } + + // Wire up a Session* to this connection + // It doesn't go into a SessionMap instance until it sends an explicit + // request to open a session (initial state of Session is `closed`) + if (!s) { + s = new Session(con); + s->info.auth_name = con->get_peer_entity_name(); + s->info.inst.addr = con->get_peer_addr(); + s->info.inst.name = n; + dout(10) << " new session " << s << " for " << s->info.inst + << " con " << con << dendl; + con->set_priv(RefCountedPtr{s, false}); + if (mds_rank) { + mds_rank->kick_waiters_for_any_client_connection(); + } + } else { + dout(10) << " existing session " << s << " for " << s->info.inst + << " existing con " << s->get_connection() + << ", new/authorizing con " << con << dendl; + con->set_priv(RefCountedPtr{s}); + + // Wait until we fully accept the connection before setting + // s->connection. In particular, if there are multiple incoming + // connection attempts, they will all get their authorizer + // validated, but some of them may "lose the race" and get + // dropped. We only want to consider the winner(s). See + // ms_handle_accept(). This is important for Sessions we replay + // from the journal on recovery that don't have established + // messenger state; we want the con from only the winning + // connect attempt(s). (Normal reconnects that don't follow MDS + // recovery are reconnected to the existing con by the + // messenger.) + } + + AuthCapsInfo &caps_info = con->get_peer_caps_info(); + if (caps_info.allow_all) { + // Flag for auth providers that don't provide cap strings + s->auth_caps.set_allow_all(); + } else { + auto p = caps_info.caps.cbegin(); + string auth_cap_str; + try { + decode(auth_cap_str, p); + + dout(10) << __func__ << ": parsing auth_cap_str='" << auth_cap_str << "'" + << dendl; + std::ostringstream errstr; + if (!s->auth_caps.parse(g_ceph_context, auth_cap_str, &errstr)) { + dout(1) << __func__ << ": auth cap parse error: " << errstr.str() + << " parsing '" << auth_cap_str << "'" << dendl; + clog->warn() << name << " mds cap '" << auth_cap_str + << "' does not parse: " << errstr.str(); + ret = -EPERM; + } else { + ret = 1; + } + } catch (buffer::error& e) { + // Assume legacy auth, defaults to: + // * permit all filesystem ops + // * permit no `tell` ops + dout(1) << __func__ << ": cannot decode auth caps bl of length " + << caps_info.caps.length() << dendl; + ret = -EPERM; + } + } + return ret; +} void MDSDaemon::ms_handle_accept(Connection *con) { diff --git a/src/mds/MDSDaemon.h b/src/mds/MDSDaemon.h index 745b4042816..bd8f89e619b 100644 --- a/src/mds/MDSDaemon.h +++ b/src/mds/MDSDaemon.h @@ -115,6 +115,7 @@ class MDSDaemon : public Dispatcher, public md_config_obs_t { int protocol, bufferlist& authorizer_data, bufferlist& authorizer_reply, bool& isvalid, CryptoKey& session_key, std::unique_ptr *challenge) override; + int ms_handle_authentication(Connection *con) override; void ms_handle_accept(Connection *con) override; void ms_handle_connect(Connection *con) override; bool ms_handle_reset(Connection *con) override;