server: change how operation credentials are presented
This commit is contained in:
@@ -64,3 +64,6 @@ API
|
||||
|
||||
.. doxygenstruct:: pvxs::server::MonitorStat
|
||||
:members:
|
||||
|
||||
.. doxygenstruct:: pvxs::server::ClientCredentials
|
||||
:members:
|
||||
|
||||
+43
-8
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user