access security

This commit is contained in:
Matej Sekoranja
2014-09-09 14:28:43 +02:00
parent b14333f720
commit 8a2abf09b2
18 changed files with 863 additions and 73 deletions
+2
View File
@@ -3,6 +3,7 @@
SRC_DIRS += $(PVACCESS_SRC)/remote
INC += remote.h
INC += security.h
INC += blockingUDP.h
INC += beaconHandler.h
INC += blockingTCP.h
@@ -22,3 +23,4 @@ LIBSRCS += blockingTCPAcceptor.cpp
LIBSRCS += transportRegistry.cpp
LIBSRCS += serializationHelper.cpp
LIBSRCS += codec.cpp
LIBSRCS += security.cpp
-2
View File
@@ -166,8 +166,6 @@ namespace epics {
THROW_BASE_EXCEPTION(temp.str().c_str());
}
// TODO send security token
LOG(logLevelDebug, "Connected to PVA server: %s.", ipAddrStr);
_namedLocker.releaseSynchronizationObject(&address);
+12
View File
@@ -121,6 +121,18 @@ namespace epics {
// noop
}
virtual void authNZInitialize(void*) {
// noop
}
virtual void authNZMessage(epics::pvData::PVField::shared_pointer const & data) {
// noop
}
virtual std::tr1::shared_ptr<SecuritySession> getSecuritySession() const {
return std::tr1::shared_ptr<SecuritySession>();
}
// NOTE: this is not yet used for UDP
virtual void setByteOrder(int byteOrder) {
// called from receive thread... or before processing
+202 -8
View File
@@ -15,6 +15,9 @@
#include <sstream>
#include <stdexcept>
#include <limits>
#include <vector>
#include <string>
#include <map>
#define epicsExportSharedSymbols
#include <pv/blockingTCP.h>
@@ -23,7 +26,9 @@
#include <pv/hexDump.h>
#include <pv/logger.h>
#include <pv/codec.h>
#include <pv/serializationHelper.h>
using namespace std;
using namespace epics::pvData;
using namespace epics::pvAccess;
@@ -1433,6 +1438,11 @@ namespace epics {
void BlockingTCPTransportCodec::internalClose(bool force) {
BlockingSocketAbstractCodec::internalClose(force);
// TODO sync
if (_securitySession)
_securitySession->close();
if (IS_LOGGABLE(logLevelDebug))
{
LOG(logLevelDebug,
@@ -1461,9 +1471,47 @@ namespace epics {
_verifiedEvent.signal();
}
void BlockingTCPTransportCodec::authNZMessage(epics::pvData::PVField::shared_pointer const & data) {
// TODO sync
if (_securitySession)
_securitySession->messageReceived(data);
else
{
char ipAddrStr[48];
ipAddrToDottedIP(&_socketAddress.ia, ipAddrStr, sizeof(ipAddrStr));
LOG(logLevelWarn, "authNZ message received from '%s' but no security plug-in session active.", ipAddrStr);
}
}
class SecurityPluginMessageTransportSender : public TransportSender {
public:
POINTER_DEFINITIONS(SecurityPluginMessageTransportSender);
SecurityPluginMessageTransportSender(PVField::shared_pointer const & data) :
m_data(data)
{
}
void send(ByteBuffer* buffer, TransportSendControl* control) {
control->startMessage((int8)5, 0);
SerializationHelper::serializeFull(buffer, control, m_data);
// send immediately
control->flush(true);
}
void lock() {}
void unlock() {}
private:
PVField::shared_pointer m_data;
};
void BlockingTCPTransportCodec::sendSecurityPluginMessage(epics::pvData::PVField::shared_pointer const & data) {
// TODO not optimal since it allocates a new object every time
SecurityPluginMessageTransportSender::shared_pointer spmts(new SecurityPluginMessageTransportSender(data));
enqueueSendRequest(spmts);
}
@@ -1477,7 +1525,7 @@ namespace epics {
int32_t receiveBufferSize) :
BlockingTCPTransportCodec(true, context, channel, responseHandler,
sendBufferSize, receiveBufferSize, PVA_DEFAULT_PRIORITY),
_lastChannelSID(0), _verifyOrVerified(false)
_lastChannelSID(0), _verifyOrVerified(false), _securityRequired(false)
{
// NOTE: priority not yet known, default priority is used to
@@ -1574,8 +1622,29 @@ namespace epics {
buffer->putShort(0x7FFF);
// list of authNZ plugin names
// TODO
buffer->putByte(0);
map<string, SecurityPlugin::shared_pointer> securityPlugins;
vector<string> validSPNames;
validSPNames.reserve(securityPlugins.size());
for (map<string, SecurityPlugin::shared_pointer>::const_iterator iter =
securityPlugins.begin();
iter != securityPlugins.end(); iter++)
{
SecurityPlugin::shared_pointer securityPlugin = iter->second;
if (securityPlugin->isValidFor(_socketAddress))
validSPNames.push_back(securityPlugin->getId());
}
size_t validSPCount = validSPNames.size();
SerializeHelper::writeSize(validSPCount, buffer, this);
for (vector<string>::const_iterator iter =
validSPNames.begin();
iter != validSPNames.end(); iter++)
SerializeHelper::serializeString(*iter, buffer, this);
// TODO sync
_securityRequired = (validSPCount > 0);
// send immediately
control->flush(true);
@@ -1625,7 +1694,82 @@ namespace epics {
destroyAllChannels();
}
void BlockingServerTCPTransportCodec::authenticationCompleted(epics::pvData::Status const & status)
{
if (IS_LOGGABLE(logLevelDebug))
{
char ipAddrStr[48];
ipAddrToDottedIP(&_socketAddress.ia, ipAddrStr, sizeof(ipAddrStr));
LOG(logLevelDebug, "Authentication completed with status '%s' for PVA client: %s.", Status::StatusTypeName[status.getType()], ipAddrStr);
}
if (!isVerified()) // TODO sync
verified(status);
else if (!status.isSuccess())
{
string errorMessage = "Re-authentication failed: " + status.getMessage();
if (!status.getStackDump().empty())
errorMessage += "\n" + status.getStackDump();
LOG(logLevelInfo, errorMessage.c_str());
close();
}
}
epics::pvData::Status BlockingServerTCPTransportCodec::invalidSecurityPluginNameStatus(Status::STATUSTYPE_ERROR, "invalid security plug-in name");
void BlockingServerTCPTransportCodec::authNZInitialize(void *arg)
{
struct InitData {
std::string securityPluginName;
PVField::shared_pointer data;
};
InitData* initData = static_cast<InitData*>(arg);
// check if plug-in name is valid
SecurityPlugin::shared_pointer securityPlugin;
map<string, SecurityPlugin::shared_pointer>::iterator spIter =
_context->getSecurityPlugins().find(initData->securityPluginName);
if (spIter != _context->getSecurityPlugins().end())
securityPlugin = spIter->second;
if (!securityPlugin)
{
if (_securityRequired)
{
verified(invalidSecurityPluginNameStatus);
return;
}
else
{
securityPlugin = NoSecurityPlugin::INSTANCE;
if (IS_LOGGABLE(logLevelDebug))
{
char ipAddrStr[48];
ipAddrToDottedIP(&_socketAddress.ia, ipAddrStr, sizeof(ipAddrStr));
LOG(logLevelDebug, "No security plug-in installed, selecting default plug-in '%s' for PVA client: %s.", securityPlugin->getId().c_str(), ipAddrStr);
}
}
}
if (!securityPlugin->isValidFor(_socketAddress))
verified(invalidSecurityPluginNameStatus);
if (IS_LOGGABLE(logLevelDebug))
{
char ipAddrStr[48];
ipAddrToDottedIP(&_socketAddress.ia, ipAddrStr, sizeof(ipAddrStr));
LOG(logLevelDebug, "Accepted security plug-in '%s' for PVA client: %s.", initData->securityPluginName.c_str(), ipAddrStr);
}
// create session
SecurityPluginControl::shared_pointer spc = std::tr1::dynamic_pointer_cast<SecurityPluginControl>(shared_from_this());
// TODO sync
_securitySession = securityPlugin->createSession(_socketAddress, spc, initData->data);
}
@@ -1858,9 +2002,23 @@ namespace epics {
// QoS (aka connection priority)
buffer->putShort(getPriority());
// authNZ plugin name
// TODO
SerializeHelper::serializeString("", buffer, control);
// TODO sync
if (_securitySession)
{
// selected authNZ plug-in name
SerializeHelper::serializeString(_securitySession->getSecurityPlugin()->getId(), buffer, control);
// optional authNZ plug-in initialization data
SerializationHelper::serializeFull(buffer, control, _securitySession->initializationData());
}
else
{
// emptry authNZ plug-in name
SerializeHelper::serializeString("", buffer, control);
// no authNZ plug-in initialization data
SerializationHelper::serializeNullField(buffer, control);
}
// send immediately
control->flush(true);
@@ -1872,8 +2030,44 @@ namespace epics {
}
}
void BlockingClientTCPTransportCodec::authNZInitialize(void *arg)
{
vector<string>* offeredSecurityPlugins = static_cast< vector<string>* >(arg);
if (!offeredSecurityPlugins->empty())
{
map<string, SecurityPlugin::shared_pointer>& availableSecurityPlugins =
_context->getSecurityPlugins();
for (vector<string>::const_iterator offeredSP = offeredSecurityPlugins->begin();
offeredSP != offeredSecurityPlugins->end(); offeredSP++)
{
map<string, SecurityPlugin::shared_pointer>::iterator spi = availableSecurityPlugins.find(*offeredSP);
if (spi != availableSecurityPlugins.end())
{
SecurityPlugin::shared_pointer securityPlugin = spi->second;
if (securityPlugin->isValidFor(_socketAddress))
{
// create session
SecurityPluginControl::shared_pointer spc = std::tr1::dynamic_pointer_cast<SecurityPluginControl>(shared_from_this());
// TODO sync
_securitySession = securityPlugin->createSession(_socketAddress, spc, PVField::shared_pointer());
}
}
}
}
TransportSender::shared_pointer transportSender = std::tr1::dynamic_pointer_cast<TransportSender>(shared_from_this());
enqueueSendRequest(transportSender);
}
void BlockingClientTCPTransportCodec::authenticationCompleted(epics::pvData::Status const & status)
{
// noop for client side (server will send ConnectionValidation message)
}
}
}
}
+30 -6
View File
@@ -36,6 +36,7 @@
#include <pv/pvaConstants.h>
#include <pv/remote.h>
#include <pv/security.h>
#include <pv/transportRegistry.h>
#include <pv/introspectionRegistry.h>
#include <pv/namedLockPattern.h>
@@ -415,7 +416,8 @@ namespace epics {
class BlockingTCPTransportCodec :
public BlockingSocketAbstractCodec
public BlockingSocketAbstractCodec,
public SecurityPluginControl
{
@@ -522,6 +524,17 @@ namespace epics {
void verified(epics::pvData::Status const & status);
bool isVerified() const { return _verified; } // TODO sync
std::tr1::shared_ptr<SecuritySession> getSecuritySession() const {
// TODO sync
return _securitySession;
}
void authNZMessage(epics::pvData::PVField::shared_pointer const & data);
void sendSecurityPluginMessage(epics::pvData::PVField::shared_pointer const & data);
protected:
BlockingTCPTransportCodec(
@@ -548,6 +561,8 @@ namespace epics {
IntrospectionRegistry _incomingIR;
IntrospectionRegistry _outgoingIR;
SecuritySession::shared_pointer _securitySession;
private:
std::auto_ptr<ResponseHandler> _responseHandler;
@@ -558,6 +573,7 @@ namespace epics {
bool _verified;
epics::pvData::Mutex _verifiedMutex;
epics::pvData::Event _verifiedEvent;
};
@@ -619,10 +635,6 @@ namespace epics {
int getChannelCount();
epics::pvData::PVField::shared_pointer getSecurityToken() {
return epics::pvData::PVField::shared_pointer();
}
void lock() {
// noop
}
@@ -655,6 +667,10 @@ namespace epics {
// noop on server-side
}
void authNZInitialize(void *);
void authenticationCompleted(epics::pvData::Status const & status);
void send(epics::pvData::ByteBuffer* buffer,
TransportSendControl* control);
@@ -684,6 +700,10 @@ namespace epics {
bool _verifyOrVerified;
bool _securityRequired;
static epics::pvData::Status invalidSecurityPluginNameStatus;
};
class epicsShareClass BlockingClientTCPTransportCodec :
@@ -759,7 +779,11 @@ namespace epics {
void send(epics::pvData::ByteBuffer* buffer,
TransportSendControl* control);
void authNZInitialize(void *);
void authenticationCompleted(epics::pvData::Status const & status);
protected:
virtual void internalClose(bool force);
+24 -6
View File
@@ -12,6 +12,9 @@
# undef epicsExportSharedSymbols
#endif
#include <map>
#include <string>
#include <osiSock.h>
#include <osdSock.h>
@@ -157,6 +160,7 @@ namespace epics {
};
class TransportClient;
class SecuritySession;
/**
* Interface defining transport (connection).
@@ -288,9 +292,24 @@ namespace epics {
* @return <code>true</code> if connected.
*/
virtual bool isClosed() = 0;
/**
* Used to initialize authNZ (select security plug-in).
* @param data
*/
virtual void authNZInitialize(void*) = 0;
/**
* Pass data to the active security plug-in session.
* @param data the data (any data), can be <code>null</code>.
*/
virtual void authNZMessage(epics::pvData::PVField::shared_pointer const & data) = 0;
virtual std::tr1::shared_ptr<SecuritySession> getSecuritySession() const = 0;
};
class Channel;
class SecurityPlugin;
/**
* Not public IF, used by Transports, etc.
@@ -311,6 +330,11 @@ namespace epics {
virtual Configuration::shared_pointer getConfiguration() = 0;
/**
* Get map of available security plug-ins.
* @return the map of available security plug-ins
*/
virtual std::map<std::string, std::tr1::shared_ptr<SecurityPlugin> >& getSecurityPlugins() = 0;
///
@@ -465,12 +489,6 @@ namespace epics {
virtual ~ChannelHostingTransport() {}
/**
* Get security token.
* @return security token, can be <code>null</code>.
*/
virtual epics::pvData::PVField::shared_pointer getSecurityToken() = 0;
/**
* Preallocate new channel SID.
* @return new channel server id (SID).
+13
View File
@@ -0,0 +1,13 @@
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* pvAccessCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#define epicsExportSharedSymbols
#include <pv/security.h>
using namespace epics::pvAccess;
NoSecurityPlugin::shared_pointer NoSecurityPlugin::INSTANCE(new NoSecurityPlugin());
+458
View File
@@ -0,0 +1,458 @@
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* pvAccessCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#ifndef SECURITY_H
#define SECURITY_H
#ifdef epicsExportSharedSymbols
# define securityEpicsExportSharedSymbols
# undef epicsExportSharedSymbols
#endif
#include <string>
#include <osiSock.h>
#include <osdSock.h>
#include <pv/status.h>
#include <pv/pvData.h>
#include <pv/sharedPtr.h>
#ifdef securityEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# undef securityEpicsExportSharedSymbols
#endif
#include <pv/remote.h>
#include <pv/serializationHelper.h>
#include <shareLib.h>
namespace epics {
namespace pvAccess {
// notify client only on demand, configurable via pvRequest
// add the following method to ChannelRequest:
// void credentialsChanged(std::vector<BitSet> credentials);
// pvAccess message: channel client id, ioid (if invalid then it's for channel) and array of bitSets
// or leave to the plugin?
// when clients gets initial credentialsChanged call before create is called
// and then on each change
class ChannelSecuritySession {
public:
POINTER_DEFINITIONS(ChannelSecuritySession);
virtual ~ChannelSecuritySession() {}
/// closes this session
virtual void close() = 0;
// for every authroizeCreate... a release() must be called
virtual void release(pvAccessID ioid) = 0;
// bitSet w/ one bit
virtual epics::pvData::Status authorizeCreateChannelProcess(
pvAccessID ioid, epics::pvData::PVStructure const & pvRequest) = 0;
virtual epics::pvData::Status authorizeProcess(pvAccessID ioid) = 0;
// bitSet w/ one bit (allowed, not allowed) and rest of the bit per field
virtual epics::pvData::Status authorizeCreateChannelGet(
pvAccessID ioid, epics::pvData::PVStructure const & pvRequest) = 0;
virtual epics::pvData::Status authorizeGet(pvAccessID ioid) = 0;
// read: bitSet w/ one bit (allowed, not allowed) and rest of the bit per field
// write: bitSet w/ one bit (allowed, not allowed) and rest of the bit per field
virtual epics::pvData::Status authorizeCreateChannelPut(
pvAccessID ioid, epics::pvData::PVStructure const & pvRequest) = 0;
virtual epics::pvData::Status authorizePut(
pvAccessID ioid,
epics::pvData::PVStructure::shared_pointer const & dataToPut,
epics::pvData::BitSet::shared_pointer const & fieldsToPut) = 0;
// read: bitSet w/ one bit (allowed, not allowed) and rest of the bit per field
// write: bitSet w/ one bit (allowed, not allowed) and rest of the bit per field
// process: bitSet w/ one bit (allowed, not allowed)
virtual epics::pvData::Status authorizeCreateChannelPutGet(
pvAccessID ioid, epics::pvData::PVStructure const & pvRequest) = 0;
virtual epics::pvData::Status authorizePutGet(
pvAccessID ioid,
epics::pvData::PVStructure::shared_pointer const & dataToPut,
epics::pvData::BitSet::shared_pointer const & fieldsToPut) = 0;
// bitSet w/ one bit
virtual epics::pvData::Status authorizeCreateChannelRPC(
pvAccessID ioid, epics::pvData::PVStructure const & pvRequest) = 0;
// one could authorize per operation basis
virtual epics::pvData::Status authorizeRPC(
pvAccessID ioid, epics::pvData::PVStructure::shared_pointer const & arguments) = 0;
// read: bitSet w/ one bit (allowed, not allowed) and rest of the bit per field
virtual epics::pvData::Status authorizeCreateMonitor(
pvAccessID ioid, epics::pvData::PVStructure const & pvRequest) = 0;
virtual epics::pvData::Status authorizeMonitor(pvAccessID ioid) = 0;
// read: bitSet w/ one bit (allowed, not allowed) and rest put/get/set length
virtual epics::pvData::Status authorizeCreateChannelArray(
pvAccessID ioid, epics::pvData::PVStructure const & pvRequest) = 0;
// use authorizeGet
virtual epics::pvData::Status authorizePut(pvAccessID ioid, epics::pvData::PVArray::shared_pointer const & dataToPut) = 0;
virtual epics::pvData::Status authorizeSetLength(pvAccessID ioid) = 0;
// introspection authorization
virtual epics::pvData::Status authorizeGetField(pvAccessID ioid, std::string const & subField) = 0;
};
class SecurityPlugin;
class epicsShareClass SecurityException: public std::runtime_error {
public:
explicit SecurityException(std::string const & what): std::runtime_error(what) {}
};
class epicsShareClass SecuritySession {
public:
POINTER_DEFINITIONS(SecuritySession);
// optional (can be null) initialization data for the remote party
// client to server
virtual epics::pvData::PVField::shared_pointer initializationData() = 0;
// get parent
virtual std::tr1::shared_ptr<SecurityPlugin> getSecurityPlugin() = 0;
// can be called any time, for any reason
virtual void messageReceived(epics::pvData::PVField::shared_pointer const & data) = 0;
/// closes this session
virtual void close() = 0;
// notification to the client on allowed requests (bitSet, a bit per request)
virtual ChannelSecuritySession::shared_pointer createChannelSession(std::string const & channelName)
throw (SecurityException) = 0;
};
class epicsShareClass SecurityPluginControl {
public:
POINTER_DEFINITIONS(SecurityPluginControl);
virtual ~SecurityPluginControl() {}
// can be called any time, for any reason
virtual void sendSecurityPluginMessage(epics::pvData::PVField::shared_pointer const & data) = 0;
// if Status.isSuccess() == false,
// pvAccess will send status to the client and close the connection
// can be called more then once (in case of re-authentication process)
virtual void authenticationCompleted(epics::pvData::Status const & status) = 0;
};
class epicsShareClass SecurityPlugin {
public:
POINTER_DEFINITIONS(SecurityPlugin);
virtual ~SecurityPlugin() {}
/**
* Short, unique name for the plug-in, used to identify the plugin.
* @return the ID.
*/
virtual std::string getId() const = 0;
/**
* Description of the security plug-in.
* @return the description string.
*/
virtual std::string getDescription() const = 0;
/**
* Check whether the remote instance with given network address is
* valid to use this security plug-in to authNZ.
* @param remoteAddress
* @return <code>true</code> if this security plugin can be used for remote instance.
*/
virtual bool isValidFor(osiSockAddr const & remoteAddress) const = 0;
/**
* Create a security session (usually one per transport).
* @param remoteAddress
* @return a new session.
* @throws SecurityException
*/
// authentication must be done immediately when connection is established (timeout 3seconds),
// later on authentication process can be repeated
// the server and the client can exchange (arbitrary number) of messages using SecurityPluginControl.sendMessage()
// the process completion must be notified by calling AuthenticationControl.completed()
virtual SecuritySession::shared_pointer createSession(
osiSockAddr const & remoteAddress,
SecurityPluginControl::shared_pointer const & control,
epics::pvData::PVField::shared_pointer const & data) throw (SecurityException) = 0;
};
class epicsShareClass NoSecurityPlugin :
public SecurityPlugin,
public SecuritySession,
public ChannelSecuritySession,
public std::tr1::enable_shared_from_this<ChannelSecuritySession> {
protected:
NoSecurityPlugin() {}
public:
POINTER_DEFINITIONS(NoSecurityPlugin);
static NoSecurityPlugin::shared_pointer INSTANCE;
virtual ~NoSecurityPlugin() {}
// optional (can be null) initialization data for the remote party
// client to server
virtual epics::pvData::PVField::shared_pointer initializationData() {
return epics::pvData::PVField::shared_pointer();
}
// get parent
virtual std::tr1::shared_ptr<SecurityPlugin> getSecurityPlugin() {
return std::tr1::dynamic_pointer_cast<SecurityPlugin>(shared_from_this());
}
// can be called any time, for any reason
virtual void messageReceived(epics::pvData::PVField::shared_pointer const & data) {
// noop
}
/// closes this session
virtual void close() {
// noop
}
// notification to the client on allowed requests (bitSet, a bit per request)
virtual ChannelSecuritySession::shared_pointer createChannelSession(std::string const & /*channelName*/)
throw (SecurityException)
{
return shared_from_this();
}
/**
* Short, unique name for the plug-in, used to identify the plugin.
* @return the ID.
*/
virtual std::string getId() const {
return "none";
}
/**
* Description of the security plug-in.
* @return the description string.
*/
virtual std::string getDescription() const {
return "No security plug-in";
}
/**
* Check whether the remote instance with given network address is
* valid to use this security plug-in to authNZ.
* @param remoteAddress
* @return <code>true</code> if this security plugin can be used for remote instance.
*/
virtual bool isValidFor(osiSockAddr const & /*remoteAddress*/) const {
return true;
}
/**
* Create a security session (usually one per transport).
* @param remoteAddress
* @return a new session.
* @throws SecurityException
*/
// authentication must be done immediately when connection is established (timeout 3seconds),
// later on authentication process can be repeated
// the server and the client can exchange (arbitrary number) of messages using SecurityPluginControl.sendMessage()
// the process completion must be notified by calling AuthenticationControl.completed()
virtual SecuritySession::shared_pointer createSession(
osiSockAddr const & /*remoteAddress*/,
SecurityPluginControl::shared_pointer const & control,
epics::pvData::PVField::shared_pointer const & /*data*/) throw (SecurityException) {
control->authenticationCompleted(epics::pvData::Status::Ok);
return std::tr1::dynamic_pointer_cast<SecuritySession>(shared_from_this());
}
// for every authroizeCreate... a release() must be called
virtual void release(pvAccessID ioid) {
// noop
}
// bitSet w/ one bit
virtual epics::pvData::Status authorizeCreateChannelProcess(
pvAccessID ioid, epics::pvData::PVStructure const & /*pvRequest*/) {
return epics::pvData::Status::Ok;
}
virtual epics::pvData::Status authorizeProcess(pvAccessID /*ioid*/) {
return epics::pvData::Status::Ok;
}
// bitSet w/ one bit (allowed, not allowed) and rest of the bit per field
virtual epics::pvData::Status authorizeCreateChannelGet(
pvAccessID /*ioid*/, epics::pvData::PVStructure const & /*pvRequest*/) {
return epics::pvData::Status::Ok;
}
virtual epics::pvData::Status authorizeGet(pvAccessID /*ioid*/) {
return epics::pvData::Status::Ok;
}
// read: bitSet w/ one bit (allowed, not allowed) and rest of the bit per field
// write: bitSet w/ one bit (allowed, not allowed) and rest of the bit per field
virtual epics::pvData::Status authorizeCreateChannelPut(
pvAccessID /*ioid*/, epics::pvData::PVStructure const & /*pvRequest*/) {
return epics::pvData::Status::Ok;
}
virtual epics::pvData::Status authorizePut(
pvAccessID /*ioid*/,
epics::pvData::PVStructure::shared_pointer const & /*dataToPut*/,
epics::pvData::BitSet::shared_pointer const & /*fieldsToPut*/) {
return epics::pvData::Status::Ok;
}
// read: bitSet w/ one bit (allowed, not allowed) and rest of the bit per field
// write: bitSet w/ one bit (allowed, not allowed) and rest of the bit per field
// process: bitSet w/ one bit (allowed, not allowed)
virtual epics::pvData::Status authorizeCreateChannelPutGet(
pvAccessID /*ioid*/, epics::pvData::PVStructure const & /*pvRequest*/) {
return epics::pvData::Status::Ok;
}
virtual epics::pvData::Status authorizePutGet(
pvAccessID /*ioid*/,
epics::pvData::PVStructure::shared_pointer const & /*dataToPut*/,
epics::pvData::BitSet::shared_pointer const & /*fieldsToPut*/) {
return epics::pvData::Status::Ok;
}
// bitSet w/ one bit
virtual epics::pvData::Status authorizeCreateChannelRPC(
pvAccessID /*ioid*/, epics::pvData::PVStructure const & /*pvRequest*/) {
return epics::pvData::Status::Ok;
}
// one could authorize per operation basis
virtual epics::pvData::Status authorizeRPC(
pvAccessID /*ioid*/, epics::pvData::PVStructure::shared_pointer const & /*arguments*/) {
return epics::pvData::Status::Ok;
}
// read: bitSet w/ one bit (allowed, not allowed) and rest of the bit per field
virtual epics::pvData::Status authorizeCreateMonitor(
pvAccessID /*ioid*/, epics::pvData::PVStructure const & /*pvRequest*/) {
return epics::pvData::Status::Ok;
}
virtual epics::pvData::Status authorizeMonitor(pvAccessID /*ioid*/) {
return epics::pvData::Status::Ok;
}
// read: bitSet w/ one bit (allowed, not allowed) and rest put/get/set length
virtual epics::pvData::Status authorizeCreateChannelArray(
pvAccessID /*ioid*/, epics::pvData::PVStructure const & /*pvRequest*/) {
return epics::pvData::Status::Ok;
}
// use authorizeGet
virtual epics::pvData::Status authorizePut(
pvAccessID /*ioid*/, epics::pvData::PVArray::shared_pointer const & /*dataToPut*/) {
return epics::pvData::Status::Ok;
}
virtual epics::pvData::Status authorizeSetLength(pvAccessID /*ioid*/) {
return epics::pvData::Status::Ok;
}
// introspection authorization
virtual epics::pvData::Status authorizeGetField(pvAccessID /*ioid*/, std::string const & /*subField*/) {
return epics::pvData::Status::Ok;
}
};
class epicsShareClass AuthNZHandler :
public AbstractResponseHandler,
private epics::pvData::NoDefaultMethods
{
public:
AuthNZHandler(Context* context) :
AbstractResponseHandler(context, "authNZ message")
{
}
virtual ~AuthNZHandler() {}
virtual void handleResponse(osiSockAddr* responseFrom,
Transport::shared_pointer const & transport,
epics::pvData::int8 version,
epics::pvData::int8 command,
size_t payloadSize,
epics::pvData::ByteBuffer* payloadBuffer)
{
AbstractResponseHandler::handleResponse(responseFrom, transport, version, command, payloadSize, payloadBuffer);
epics::pvData::PVField::shared_pointer data =
SerializationHelper::deserializeFull(payloadBuffer, transport.get());
transport->authNZMessage(data);
}
};
class epicsShareClass SecurityPluginRegistry :
private epics::pvData::NoDefaultMethods
{
public:
static SecurityPluginRegistry& instance()
{
static SecurityPluginRegistry thisInstance;
return thisInstance;
}
std::map<std::string, std::tr1::shared_ptr<SecurityPlugin> >& getClientSecurityPlugins()
{
return m_clientSecurityPlugins;
}
std::map<std::string, std::tr1::shared_ptr<SecurityPlugin> >& getServerSecurityPlugins()
{
return m_serverSecurityPlugins;
}
void installClientSecurityPlugin(std::tr1::shared_ptr<SecurityPlugin> plugin)
{
m_clientSecurityPlugins[plugin->getId()] = plugin;
}
void installServerSecurityPlugin(std::tr1::shared_ptr<SecurityPlugin> plugin)
{
m_serverSecurityPlugins[plugin->getId()] = plugin;
}
private:
SecurityPluginRegistry() {}
std::map<std::string, std::tr1::shared_ptr<SecurityPlugin> > m_clientSecurityPlugins;
std::map<std::string, std::tr1::shared_ptr<SecurityPlugin> > m_serverSecurityPlugins;
};
}
}
#endif // SECURITY_H
+25 -15
View File
@@ -40,14 +40,19 @@ PVStructure::shared_pointer SerializationHelper::deserializeStructureAndCreatePV
PVStructure::shared_pointer SerializationHelper::deserializeStructureFull(ByteBuffer* buffer, DeserializableControl* control)
{
PVStructure::shared_pointer pvStructure;
FieldConstPtr structureField = control->cachedDeserialize(buffer);
if (structureField.get() != 0)
return std::tr1::static_pointer_cast<PVStructure>(deserializeFull(buffer, control));
}
PVField::shared_pointer SerializationHelper::deserializeFull(ByteBuffer* buffer, DeserializableControl* control)
{
PVField::shared_pointer pvField;
FieldConstPtr field = control->cachedDeserialize(buffer);
if (field.get() != 0)
{
pvStructure = _pvDataCreate->createPVStructure(std::tr1::static_pointer_cast<const Structure>(structureField));
pvStructure->deserialize(buffer, control);
pvField = _pvDataCreate->createPVField(field);
pvField->deserialize(buffer, control);
}
return pvStructure;
return pvField;
}
void SerializationHelper::serializeNullField(ByteBuffer* buffer, SerializableControl* control)
@@ -64,15 +69,20 @@ void SerializationHelper::serializePVRequest(ByteBuffer* buffer, SerializableCon
void SerializationHelper::serializeStructureFull(ByteBuffer* buffer, SerializableControl* control, PVStructure::shared_pointer const & pvStructure)
{
if (pvStructure.get() == 0)
{
serializeNullField(buffer, control);
}
else
{
control->cachedSerialize(pvStructure->getField(), buffer);
pvStructure->serialize(buffer, control);
}
serializeFull(buffer, control, pvStructure);
}
void SerializationHelper::serializeFull(ByteBuffer* buffer, SerializableControl* control, PVField::shared_pointer const & pvField)
{
if (pvField.get() == 0)
{
serializeNullField(buffer, control);
}
else
{
control->cachedSerialize(pvField->getField(), buffer);
pvField->serialize(buffer, control);
}
}
}}
+18 -1
View File
@@ -67,7 +67,19 @@ namespace epics {
*/
static epics::pvData::PVStructure::shared_pointer deserializeStructureFull(epics::pvData::ByteBuffer* payloadBuffer, epics::pvData::DeserializableControl* control);
static void serializeNullField(epics::pvData::ByteBuffer* buffer, epics::pvData::SerializableControl* control);
/**
* Deserialize optional PVField.
* @param payloadBuffer data buffer.
* @return deserialized PVField, can be <code>null</code>.
*/
static epics::pvData::PVField::shared_pointer deserializeFull(epics::pvData::ByteBuffer* payloadBuffer, epics::pvData::DeserializableControl* control);
/**
* Serialize <code>null</code> PVField.
* @param buffer
* @param control
*/
static void serializeNullField(epics::pvData::ByteBuffer* buffer, epics::pvData::SerializableControl* control);
/**
* Serialize PVRequest.
@@ -81,6 +93,11 @@ namespace epics {
*/
static void serializeStructureFull(epics::pvData::ByteBuffer* buffer, epics::pvData::SerializableControl* control, epics::pvData::PVStructure::shared_pointer const & pvStructure);
/**
* Serialize optional PVField.
* @param buffer data buffer.
*/
static void serializeFull(epics::pvData::ByteBuffer* buffer, epics::pvData::SerializableControl* control, epics::pvData::PVField::shared_pointer const & pvField);
};
}