server: change how operation credentials are presented

This commit is contained in:
Michael Davidsaver
2020-12-26 13:14:07 -08:00
parent dbed32309e
commit 9ec69c784a
9 changed files with 94 additions and 111 deletions
+3
View File
@@ -64,3 +64,6 @@ API
.. doxygenstruct:: pvxs::server::MonitorStat
:members:
.. doxygenstruct:: pvxs::server::ClientCredentials
:members:
+43 -8
View File
@@ -5,7 +5,9 @@
# error Include <pvxs/sharedpv.h> or <pvxs/source.h> Do not include srvcommon.h directly
#endif
#include <iosfwd>
#include <string>
#include <set>
#include <functional>
#include <pvxs/version.h>
@@ -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<std::string> 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<const ClientCredentials> _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<const ClientCredentials>& 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<std::string, Value> rawCredentials() const=0;
};
//! Handle when an operation is being executed
+2 -2
View File
@@ -268,9 +268,9 @@ std::ostream& operator<<(std::ostream& strm, const Server& serv)
strm<<indent{}<<"Peer"<<conn->peerName
<<" backlog="<<conn->backlog.size()
<<" auth="<<conn->autoMethod<<"\n";
<<" auth="<<conn->cred->method<<"\n";
if(detail>2)
strm<<conn->credentials;
strm<<*conn->cred;
if(detail<=2)
continue;
+1 -15
View File
@@ -41,8 +41,7 @@ ServerChannelControl::ServerChannelControl(const std::shared_ptr<ServerConn> &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<std::string, Value> ServerChannelControl::rawCredentials() const
{
std::pair<std::string, Value> 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);
+39 -2
View File
@@ -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<std::string> ClientCredentials::roles() const
{
std::set<std::string> ret;
osdGetRoles(account, ret);
return ret;
}
std::ostream& operator<<(std::ostream& strm, const ClientCredentials& cred)
{
strm<<cred.method<<"/"<<cred.account<<"@"<<cred.peer;
return strm;
}
}} // namespace pvxs::server
namespace pvxs {namespace impl {
// message related to client state and errors
@@ -35,6 +51,15 @@ ServerConn::ServerConn(ServIface* iface, evutil_socket_t sock, struct sockaddr *
{
log_debug_printf(connio, "Client %s connects\n", peerName.c_str());
{
auto cred(std::make_shared<server::ClientCredentials>());
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()<<auth).c_str());
autoMethod = selected;
credentials = auth;
auto C(std::make_shared<server::ClientCredentials>(*cred));
if(selected=="ca") {
auth["user"].as<std::string>([&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);
}
}
+1 -4
View File
@@ -66,8 +66,6 @@ struct ServerChannelControl : public server::ChannelControl
virtual void onClose(std::function<void(const std::string&)>&& fn) override final;
virtual void close() override final;
virtual std::pair<std::string, Value> rawCredentials() const override final;
const std::weak_ptr<server::Server::Pvt> server;
const std::weak_ptr<ServerChan> chan;
@@ -106,8 +104,7 @@ struct ServerConn : public ConnBase, public std::enable_shared_from_this<ServerC
{
ServIface* const iface;
std::string autoMethod;
Value credentials;
std::shared_ptr<const server::ClientCredentials> cred;
uint32_t nextSID=0x07050301;
std::map<uint32_t, std::shared_ptr<ServerChan> > chanBySID;
+2 -32
View File
@@ -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<std::string, Value> rawCredentials() const override final
{
std::pair<std::string, Value> 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::Server::Pvt> server;
const std::weak_ptr<ServerGPR> 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<std::string, Value> rawCredentials() const override final
{
std::pair<std::string, Value> 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::Server::Pvt> server;
const std::weak_ptr<ServerGPR> op;
+1 -16
View File
@@ -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<std::string, Value> rawCredentials() const override final
{
std::pair<std::string, Value> 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<void(std::unique_ptr<server::ExecOp>&& fn)>&& fn) override final {}
virtual void onPut(std::function<void(std::unique_ptr<server::ExecOp>&& fn, Value&&)>&& fn) override final {}
+2 -32
View File
@@ -315,20 +315,6 @@ struct ServerMonitorControl : public server::MonitorControlOp
});
}
virtual std::pair<std::string, Value> rawCredentials() const override final
{
std::pair<std::string, Value> 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::Server::Pvt> server;
const std::weak_ptr<MonitorOp> 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<std::string, Value> rawCredentials() const override final
{
std::pair<std::string, Value> 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::Server::Pvt> server;
const std::weak_ptr<MonitorOp> op;
@@ -439,8 +410,7 @@ ServerMonitorControl::ServerMonitorControl(ServerMonitorSetup* setup,
{
_op = Info;
_name = name;
_peerName = setup->peerName();
_ifaceName = setup->name();
_cred = setup->credentials();
}
} // namespace