redo security (aka. access control)

Break up monolithic SecurityPlugin API into three parts.

1. Authentication.
2. Authorization.
3. Access Control decision.  Left to ChannelProviders
This commit is contained in:
Michael Davidsaver
2019-01-12 15:14:19 -08:00
parent 13cac5f4cc
commit fa484a883a
19 changed files with 665 additions and 670 deletions
+3 -3
View File
@@ -201,14 +201,15 @@ public:
protected:
ServerChannelRequesterImpl(Transport::shared_pointer const & transport,
const std::string channelName,
const pvAccessID cid, ChannelSecuritySession::shared_pointer const & css);
const pvAccessID cid);
public:
virtual ~ServerChannelRequesterImpl() {}
static ChannelRequester::shared_pointer create(ChannelProvider::shared_pointer const & provider,
Transport::shared_pointer const & transport, const std::string channelName,
const pvAccessID cid, ChannelSecuritySession::shared_pointer const & css);
const pvAccessID cid);
virtual void channelCreated(const epics::pvData::Status& status, Channel::shared_pointer const & channel) OVERRIDE FINAL;
virtual void channelStateChange(Channel::shared_pointer const & c, const Channel::ConnectionState isConnected) OVERRIDE FINAL;
virtual std::tr1::shared_ptr<const PeerInfo> getPeerInfo() OVERRIDE FINAL;
virtual std::string getRequesterName() OVERRIDE FINAL;
virtual void message(std::string const & message, epics::pvData::MessageType messageType) OVERRIDE FINAL;
virtual void send(epics::pvData::ByteBuffer* buffer, TransportSendControl* control) OVERRIDE FINAL;
@@ -217,7 +218,6 @@ private:
std::tr1::weak_ptr<detail::BlockingServerTCPTransportCodec> _transport;
const std::string _channelName;
const pvAccessID _cid;
ChannelSecuritySession::shared_pointer const & _css;
epics::pvData::Status _status;
epics::pvData::Mutex _mutex;
};
+1 -7
View File
@@ -33,8 +33,7 @@ public:
*/
ServerChannel(Channel::shared_pointer const & channel,
const ChannelRequester::shared_pointer& requester,
pvAccessID cid, pvAccessID sid,
ChannelSecuritySession::shared_pointer const & css);
pvAccessID cid, pvAccessID sid);
~ServerChannel();
const Channel::shared_pointer& getChannel() const { return _channel; }
@@ -43,9 +42,6 @@ public:
pvAccessID getSID() const { return _sid; }
ChannelSecuritySession::shared_pointer getChannelSecuritySession() const
{ return _channelSecuritySession; }
void registerRequest(pvAccessID id, const std::tr1::shared_ptr<BaseChannelRequester>& request);
void unregisterRequest(pvAccessID id);
@@ -77,8 +73,6 @@ private:
bool _destroyed;
mutable epics::pvData::Mutex _mutex;
const ChannelSecuritySession::shared_pointer _channelSecuritySession;
};
}
-1
View File
@@ -51,7 +51,6 @@ public:
Transport::shared_pointer getSearchTransport() OVERRIDE FINAL;
Configuration::const_shared_pointer getConfiguration() OVERRIDE FINAL;
TransportRegistry* getTransportRegistry() OVERRIDE FINAL;
const securityPlugins_t& getSecurityPlugins() OVERRIDE FINAL;
virtual void newServerDetected() OVERRIDE FINAL;
+37 -40
View File
@@ -194,15 +194,30 @@ void ServerConnectionValidationHandler::handleResponse(
std::string securityPluginName = SerializeHelper::deserializeString(payloadBuffer, transport.get());
// optional authNZ plug-in initialization data
PVField::shared_pointer data;
if (payloadBuffer->getRemaining())
data = SerializationHelper::deserializeFull(payloadBuffer, transport.get());
PVStructure::shared_pointer data;
if (payloadBuffer->getRemaining()) {
PVField::shared_pointer raw(SerializationHelper::deserializeFull(payloadBuffer, transport.get()));
if(raw && raw->getField()->getType()==structure) {
data = std::tr1::static_pointer_cast<PVStructure>(raw);
} else {
// was originally allowed, but never used
}
}
detail::BlockingServerTCPTransportCodec* casTransport(static_cast<detail::BlockingServerTCPTransportCodec*>(transport.get()));
//TODO: simplify byzantine class heirarchy...
assert(casTransport);
casTransport->authNZInitialize(securityPluginName, data);
try {
casTransport->authNZInitialize(securityPluginName, data);
}catch(std::exception& e){
if (IS_LOGGABLE(logLevelDebug))
{
LOG(logLevelDebug, "Security plug-in '%s' failed to create a session for PVA client: %s.", securityPluginName.c_str(), casTransport->getRemoteName().c_str());
}
casTransport->verified(pvData::Status::error(e.what()));
throw;
}
}
@@ -732,30 +747,13 @@ void ServerCreateChannelHandler::handleResponse(osiSockAddr* responseFrom,
return;
}
SecuritySession::shared_pointer securitySession = transport->getSecuritySession();
ChannelSecuritySession::shared_pointer css;
try {
css = securitySession->createChannelSession(channelName);
if (!css)
throw SecurityException("null channelSecuritySession");
} catch (SecurityException& se) {
// TODO use std::make_shared
std::tr1::shared_ptr<ServerChannelRequesterImpl> tp(new ServerChannelRequesterImpl(transport, channelName, cid, css));
ChannelRequester::shared_pointer cr = tp;
Status asStatus(Status::STATUSTYPE_ERROR,
string("Insufficient rights to create a channel: ") + se.what());
cr->channelCreated(asStatus, Channel::shared_pointer());
return;
}
if (channelName == SERVER_CHANNEL_NAME)
{
// TODO singleton!!!
ServerRPCService::shared_pointer serverRPCService(new ServerRPCService(_context));
// TODO use std::make_shared
std::tr1::shared_ptr<ServerChannelRequesterImpl> tp(new ServerChannelRequesterImpl(transport, channelName, cid, css));
std::tr1::shared_ptr<ServerChannelRequesterImpl> tp(new ServerChannelRequesterImpl(transport, channelName, cid));
ChannelRequester::shared_pointer cr = tp;
Channel::shared_pointer serverChannel = createRPCChannel(ChannelProvider::shared_pointer(), channelName, cr, serverRPCService);
cr->channelCreated(Status::Ok, serverChannel);
@@ -766,7 +764,7 @@ void ServerCreateChannelHandler::handleResponse(osiSockAddr* responseFrom,
ServerContextImpl::s_channelNameToProvider_t::const_iterator it;
if (_providers.size() == 1)
ServerChannelRequesterImpl::create(_providers[0], transport, channelName, cid, css);
ServerChannelRequesterImpl::create(_providers[0], transport, channelName, cid);
else {
ChannelProvider::shared_pointer prov;
{
@@ -775,7 +773,7 @@ void ServerCreateChannelHandler::handleResponse(osiSockAddr* responseFrom,
prov = it->second.lock();
}
if(prov)
ServerChannelRequesterImpl::create(prov, transport, channelName, cid, css);
ServerChannelRequesterImpl::create(prov, transport, channelName, cid);
}
}
}
@@ -786,12 +784,11 @@ void ServerCreateChannelHandler::disconnect(Transport::shared_pointer const & tr
}
ServerChannelRequesterImpl::ServerChannelRequesterImpl(const Transport::shared_pointer &transport,
const string channelName, const pvAccessID cid, ChannelSecuritySession::shared_pointer const & css) :
const string channelName, const pvAccessID cid) :
_serverChannel(),
_transport(std::tr1::static_pointer_cast<detail::BlockingServerTCPTransportCodec>(transport)),
_channelName(channelName),
_cid(cid),
_css(css),
_status(),
_mutex()
{
@@ -799,10 +796,10 @@ ServerChannelRequesterImpl::ServerChannelRequesterImpl(const Transport::shared_p
ChannelRequester::shared_pointer ServerChannelRequesterImpl::create(
ChannelProvider::shared_pointer const & provider, Transport::shared_pointer const & transport,
const string channelName, const pvAccessID cid, ChannelSecuritySession::shared_pointer const & css)
const string channelName, const pvAccessID cid)
{
// TODO use std::make_shared
std::tr1::shared_ptr<ServerChannelRequesterImpl> tp(new ServerChannelRequesterImpl(transport, channelName, cid, css));
std::tr1::shared_ptr<ServerChannelRequesterImpl> tp(new ServerChannelRequesterImpl(transport, channelName, cid));
ChannelRequester::shared_pointer cr = tp;
// TODO exception guard and report error back
provider->createChannel(channelName, cr, transport->getPriority());
@@ -824,7 +821,7 @@ void ServerChannelRequesterImpl::channelCreated(const Status& status, Channel::s
pvAccessID sid = transport->preallocateChannelSID();
try
{
serverChannel.reset(new ServerChannel(channel, shared_from_this(), _cid, sid, _css));
serverChannel.reset(new ServerChannel(channel, shared_from_this(), _cid, sid));
// ack allocation and register
transport->registerChannel(sid, serverChannel);
@@ -836,11 +833,6 @@ void ServerChannelRequesterImpl::channelCreated(const Status& status, Channel::s
throw;
}
}
else
{
if (_css)
_css->close();
}
{
@@ -861,9 +853,6 @@ void ServerChannelRequesterImpl::channelCreated(const Status& status, Channel::s
}
TransportSender::shared_pointer thisSender = shared_from_this();
transport->enqueueSendRequest(thisSender);
// TODO make sure that serverChannel gets destroyed
if (_css)
_css->close();
}
catch (...)
{
@@ -874,9 +863,6 @@ void ServerChannelRequesterImpl::channelCreated(const Status& status, Channel::s
}
TransportSender::shared_pointer thisSender = shared_from_this();
transport->enqueueSendRequest(thisSender);
// TODO make sure that serverChannel gets destroyed
if (_css)
_css->close();
}
}
}
@@ -909,6 +895,17 @@ void ServerChannelRequesterImpl::channelStateChange(Channel::shared_pointer cons
}
}
std::tr1::shared_ptr<const PeerInfo> ServerChannelRequesterImpl::getPeerInfo()
{
if(detail::BlockingServerTCPTransportCodec::shared_pointer transport = _transport.lock()) {
epicsGuard<epicsMutex> G(transport->_mutex);
return transport->_peerInfo;
} else {
return std::tr1::shared_ptr<const PeerInfo>();
}
}
string ServerChannelRequesterImpl::getRequesterName()
{
detail::BlockingServerTCPTransportCodec::shared_pointer transport = _transport.lock();
+2 -8
View File
@@ -18,14 +18,12 @@ size_t ServerChannel::num_instances;
ServerChannel::ServerChannel(Channel::shared_pointer const & channel,
const ChannelRequester::shared_pointer &requester,
pvAccessID cid, pvAccessID sid,
ChannelSecuritySession::shared_pointer const & css):
pvAccessID cid, pvAccessID sid):
_channel(channel),
_requester(requester),
_cid(cid),
_sid(sid),
_destroyed(false),
_channelSecuritySession(css)
_destroyed(false)
{
REFTRACE_INCREMENT(num_instances);
if (!channel.get())
@@ -76,10 +74,6 @@ void ServerChannel::destroy()
// removal via unregisterRequest() during iteration
_requests.swap(reqs);
// close channel security session
// TODO try catch
_channelSecuritySession->close();
// ... and the channel
// TODO try catch
_channel->destroy();
-6
View File
@@ -533,12 +533,6 @@ epicsTimeStamp& ServerContextImpl::getStartTime()
return _startTime;
}
const Context::securityPlugins_t& ServerContextImpl::getSecurityPlugins()
{
return SecurityPluginRegistry::instance().getServerSecurityPlugins();
}
ServerContext::shared_pointer startPVAServer(std::string const & providerNames, int timeToRun, bool runInSeparateThread, bool printInfo)
{
ServerContext::shared_pointer ret(ServerContext::create(ServerContext::Config()