From 9ec69c784a5bfd5e2c2264da2e0a6cef5ff7c792 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Sat, 26 Dec 2020 13:14:07 -0800 Subject: [PATCH] server: change how operation credentials are presented --- documentation/source.rst | 3 +++ src/pvxs/srvcommon.h | 51 +++++++++++++++++++++++++++++++++------- src/server.cpp | 4 ++-- src/serverchan.cpp | 16 +------------ src/serverconn.cpp | 41 ++++++++++++++++++++++++++++++-- src/serverconn.h | 5 +--- src/serverget.cpp | 34 ++------------------------- src/serverintrospect.cpp | 17 +------------- src/servermon.cpp | 34 ++------------------------- 9 files changed, 94 insertions(+), 111 deletions(-) diff --git a/documentation/source.rst b/documentation/source.rst index 838d192..77e8737 100644 --- a/documentation/source.rst +++ b/documentation/source.rst @@ -64,3 +64,6 @@ API .. doxygenstruct:: pvxs::server::MonitorStat :members: + +.. doxygenstruct:: pvxs::server::ClientCredentials + :members: diff --git a/src/pvxs/srvcommon.h b/src/pvxs/srvcommon.h index 65323a3..dde17a2 100644 --- a/src/pvxs/srvcommon.h +++ b/src/pvxs/srvcommon.h @@ -5,7 +5,9 @@ # error Include or Do not include srvcommon.h directly #endif +#include #include +#include #include #include @@ -14,6 +16,41 @@ namespace pvxs { namespace server { +/** Credentials presented by a client. + * + * Primarily a way of presenting peer address and a remote user account name. + * The method gives the authentication sub-protocol used and is presently one of: + * + * - "ca" - Client provided account name. + * - "anonymous" - Client provided no credentials. account will also be "anonymous". + * + * @since UNRELEASED + */ +struct PVXS_API ClientCredentials { + //! Peer address (eg. numeric IPv4) + std::string peer; + //! The local interface address (eg. numeric IPv4) through which this client is connected. + //! May be a wildcard address (eg. 0.0.0.0) if the receiving socket is so bound. + std::string iface; + //! Authentication "method" + std::string method; + //! Remote user account name. Meaning depends upon method. + std::string account; + //! (Copy of) Credentials blob as presented by the client. + Value raw; + /** Lookup (locally) roles associated with the account. + * + * On *nix targets this is the list of primary and secondary groups + * in with the account is a member. + * On Windows targets this returns the list of local groups for the account. + * On other targets, an empty list is returned. + */ + std::set roles() const; +}; + +PVXS_API +std::ostream& operator<<(std::ostream&, const ClientCredentials&); + //! Base for all operation classes struct PVXS_API OpBase { enum op_t { @@ -24,23 +61,21 @@ struct PVXS_API OpBase { RPC, //!< A RPC operation }; protected: - std::string _peerName; - std::string _ifaceName; std::string _name; + std::shared_ptr _cred; op_t _op; public: //! The Client endpoint address in "X.X.X.X:Y" format. - const std::string& peerName() const { return _peerName; } - //! The local endpoint address in "X.X.X.X:Y" format. - const std::string& ifaceName() const { return _ifaceName; } + const std::string& peerName() const { return _cred->peer; } //! The Channel name const std::string& name() const { return _name; } + //! Client credentials. Never NULL. + //! @since UNRELEASED + const std::shared_ptr& credentials() const { return _cred; } + //! Operation type op_t op() const { return _op; } virtual ~OpBase() =0; - - //! Return authentication method name (eg. "ca") and raw client credentials - virtual std::pair rawCredentials() const=0; }; //! Handle when an operation is being executed diff --git a/src/server.cpp b/src/server.cpp index 5de5379..23e0727 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -268,9 +268,9 @@ std::ostream& operator<<(std::ostream& strm, const Server& serv) strm<peerName <<" backlog="<backlog.size() - <<" auth="<autoMethod<<"\n"; + <<" auth="<cred->method<<"\n"; if(detail>2) - strm<credentials; + strm<<*conn->cred; if(detail<=2) continue; diff --git a/src/serverchan.cpp b/src/serverchan.cpp index db6d969..ed4197c 100644 --- a/src/serverchan.cpp +++ b/src/serverchan.cpp @@ -41,8 +41,7 @@ ServerChannelControl::ServerChannelControl(const std::shared_ptr &co { _op = None; _name = channel->name; - _peerName = conn->peerName; - _ifaceName = conn->iface->name; + _cred = conn->cred; } ServerChannelControl::~ServerChannelControl() {} @@ -171,19 +170,6 @@ void ServerChannelControl::close() }); } -std::pair ServerChannelControl::rawCredentials() const -{ - std::pair ret; - auto serv = server.lock(); - if(serv) - serv->acceptor_loop.call([this, &ret](){ - if(auto chan = this->chan.lock()) - if(auto conn = chan->conn.lock()) - ret = std::make_pair(conn->autoMethod, conn->credentials.clone()); - }); - return ret; -} - void ServerConn::handle_SEARCH() { EvInBuf M(peerBE, segBuf.get(), 16); diff --git a/src/serverconn.cpp b/src/serverconn.cpp index 4fccbab..95b8f49 100644 --- a/src/serverconn.cpp +++ b/src/serverconn.cpp @@ -18,6 +18,22 @@ // limit on size of TX buffer above which we suspend RX static constexpr size_t tcp_tx_limit = 0x100000; +namespace pvxs { +namespace server { +std::set ClientCredentials::roles() const +{ + std::set ret; + osdGetRoles(account, ret); + return ret; +} + +std::ostream& operator<<(std::ostream& strm, const ClientCredentials& cred) +{ + strm<()); + cred->peer = peerName; + cred->iface = iface->name; + // paranoia placeholder prior to handle_CONNECTION_VALIDATION() + cred->method = cred->account = "anonymous"; + this->cred = std::move(cred); + } + bufferevent_setcb(bev.get(), &bevReadS, &bevWriteS, &bevEventS, this); timeval tmo(totv(iface->server->effective.tcpTimeout)); @@ -145,8 +170,20 @@ void ServerConn::handle_CONNECTION_VALIDATION() peerName.c_str(), selected.c_str(), std::string(SB()<(*cred)); + + if(selected=="ca") { + auth["user"].as([&C, &selected](const std::string& user) { + C->method = selected; + C->account = user; + }); + } + if(C->method.empty()) { + C->account = C->method = "anonymous"; + } + C->raw = auth; + + cred = std::move(C); } } diff --git a/src/serverconn.h b/src/serverconn.h index 3635fc2..74977b3 100644 --- a/src/serverconn.h +++ b/src/serverconn.h @@ -66,8 +66,6 @@ struct ServerChannelControl : public server::ChannelControl virtual void onClose(std::function&& fn) override final; virtual void close() override final; - virtual std::pair rawCredentials() const override final; - const std::weak_ptr server; const std::weak_ptr chan; @@ -106,8 +104,7 @@ struct ServerConn : public ConnBase, public std::enable_shared_from_this cred; uint32_t nextSID=0x07050301; std::map > chanBySID; diff --git a/src/serverget.cpp b/src/serverget.cpp index 0404483..0bda837 100644 --- a/src/serverget.cpp +++ b/src/serverget.cpp @@ -172,8 +172,7 @@ struct ServerGPRConnect : public server::ConnectOp default: _op = None; break; // should never be reached } _name = name; - _peerName = conn->peerName; - _ifaceName = conn->iface->name; + _cred = conn->cred; _pvRequest = request; } virtual ~ServerGPRConnect() { @@ -251,20 +250,6 @@ struct ServerGPRConnect : public server::ConnectOp }); } - virtual std::pair rawCredentials() const override final - { - std::pair ret; - auto serv = server.lock(); - if(serv) - serv->acceptor_loop.call([this, &ret](){ - if(auto oper = op.lock()) - if(auto chan = oper->chan.lock()) - if(auto conn = chan->conn.lock()) - ret = std::make_pair(conn->autoMethod, conn->credentials.clone()); - }); - return ret; - } - const std::weak_ptr server; const std::weak_ptr op; @@ -289,8 +274,7 @@ struct ServerGPRExec : public server::ExecOp default: _op = None; break; // should never be reached } _name = name; - _peerName = conn->peerName; - _ifaceName = conn->iface->name; + _cred = conn->cred; } virtual ~ServerGPRExec() {} @@ -336,20 +320,6 @@ struct ServerGPRExec : public server::ExecOp }); } - virtual std::pair rawCredentials() const override final - { - std::pair ret; - auto serv = server.lock(); - if(serv) - serv->acceptor_loop.call([this, &ret](){ - if(auto oper = op.lock()) - if(auto chan = oper->chan.lock()) - if(auto conn = chan->conn.lock()) - ret = std::make_pair(conn->autoMethod, conn->credentials.clone()); - }); - return ret; - } - const std::weak_ptr server; const std::weak_ptr op; diff --git a/src/serverintrospect.cpp b/src/serverintrospect.cpp index 26f531c..b2ddb72 100644 --- a/src/serverintrospect.cpp +++ b/src/serverintrospect.cpp @@ -67,8 +67,7 @@ struct ServerIntrospectControl : public server::ConnectOp { _op = Info; _name = chan->name; - _peerName = conn->peerName; - _ifaceName = conn->iface->name; + _cred = conn->cred; } virtual ~ServerIntrospectControl() { error("Implict Cancel"); @@ -112,20 +111,6 @@ struct ServerIntrospectControl : public server::ConnectOp }); } - virtual std::pair rawCredentials() const override final - { - std::pair ret; - auto serv = server.lock(); - if(serv) - serv->acceptor_loop.call([this, &ret](){ - if(auto oper = op.lock()) - if(auto chan = oper->chan.lock()) - if(auto conn = chan->conn.lock()) - ret = std::make_pair(conn->autoMethod, conn->credentials.clone()); - }); - return ret; - } - // we'll never use these, so no reason to store virtual void onGet(std::function&& fn)>&& fn) override final {} virtual void onPut(std::function&& fn, Value&&)>&& fn) override final {} diff --git a/src/servermon.cpp b/src/servermon.cpp index 51046b5..c35f4a3 100644 --- a/src/servermon.cpp +++ b/src/servermon.cpp @@ -315,20 +315,6 @@ struct ServerMonitorControl : public server::MonitorControlOp }); } - virtual std::pair rawCredentials() const override final - { - std::pair ret; - auto serv = server.lock(); - if(serv) - serv->acceptor_loop.call([this, &ret](){ - if(auto oper = op.lock()) - if(auto chan = oper->chan.lock()) - if(auto conn = chan->conn.lock()) - ret = std::make_pair(conn->autoMethod, conn->credentials.clone()); - }); - return ret; - } - const std::weak_ptr server; const std::weak_ptr op; @@ -347,8 +333,7 @@ struct ServerMonitorSetup : public server::MonitorSetupOp { _op = Info; _name = name; - _peerName = conn->peerName; - _ifaceName = conn->iface->name; + _cred = conn->cred; _pvRequest = request; } virtual ~ServerMonitorSetup() { @@ -409,20 +394,6 @@ struct ServerMonitorSetup : public server::MonitorSetupOp }); } - virtual std::pair rawCredentials() const override final - { - std::pair ret; - auto serv = server.lock(); - if(serv) - serv->acceptor_loop.call([this, &ret](){ - if(auto oper = op.lock()) - if(auto chan = oper->chan.lock()) - if(auto conn = chan->conn.lock()) - ret = std::make_pair(conn->autoMethod, conn->credentials.clone()); - }); - return ret; - } - const std::weak_ptr server; const std::weak_ptr op; @@ -439,8 +410,7 @@ ServerMonitorControl::ServerMonitorControl(ServerMonitorSetup* setup, { _op = Info; _name = name; - _peerName = setup->peerName(); - _ifaceName = setup->name(); + _cred = setup->credentials(); } } // namespace