diff --git a/src/remote/security.h b/src/remote/security.h index ea19691..e8eb872 100644 --- a/src/remote/security.h +++ b/src/remote/security.h @@ -60,18 +60,18 @@ namespace epics { // bitSet w/ one bit virtual epics::pvData::Status authorizeCreateChannelProcess( - pvAccessID ioid, epics::pvData::PVStructure const & pvRequest) = 0; + pvAccessID ioid, epics::pvData::PVStructure::shared_pointer 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; + pvAccessID ioid, epics::pvData::PVStructure::shared_pointer 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; + pvAccessID ioid, epics::pvData::PVStructure::shared_pointer const & pvRequest) = 0; virtual epics::pvData::Status authorizePut( pvAccessID ioid, epics::pvData::PVStructure::shared_pointer const & dataToPut, @@ -81,7 +81,7 @@ namespace epics { // 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; + pvAccessID ioid, epics::pvData::PVStructure::shared_pointer const & pvRequest) = 0; virtual epics::pvData::Status authorizePutGet( pvAccessID ioid, epics::pvData::PVStructure::shared_pointer const & dataToPut, @@ -89,19 +89,19 @@ namespace epics { // bitSet w/ one bit virtual epics::pvData::Status authorizeCreateChannelRPC( - pvAccessID ioid, epics::pvData::PVStructure const & pvRequest) = 0; + pvAccessID ioid, epics::pvData::PVStructure::shared_pointer 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; + pvAccessID ioid, epics::pvData::PVStructure::shared_pointer 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; + pvAccessID ioid, epics::pvData::PVStructure::shared_pointer 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; @@ -296,7 +296,7 @@ namespace epics { // bitSet w/ one bit virtual epics::pvData::Status authorizeCreateChannelProcess( - pvAccessID ioid, epics::pvData::PVStructure const & /*pvRequest*/) { + pvAccessID ioid, epics::pvData::PVStructure::shared_pointer const & /*pvRequest*/) { return epics::pvData::Status::Ok; } @@ -306,7 +306,7 @@ namespace epics { // 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*/) { + pvAccessID /*ioid*/, epics::pvData::PVStructure::shared_pointer const & /*pvRequest*/) { return epics::pvData::Status::Ok; } @@ -317,7 +317,7 @@ namespace epics { // 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*/) { + pvAccessID /*ioid*/, epics::pvData::PVStructure::shared_pointer const & /*pvRequest*/) { return epics::pvData::Status::Ok; } @@ -332,7 +332,7 @@ namespace epics { // 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*/) { + pvAccessID /*ioid*/, epics::pvData::PVStructure::shared_pointer const & /*pvRequest*/) { return epics::pvData::Status::Ok; } @@ -345,7 +345,7 @@ namespace epics { // bitSet w/ one bit virtual epics::pvData::Status authorizeCreateChannelRPC( - pvAccessID /*ioid*/, epics::pvData::PVStructure const & /*pvRequest*/) { + pvAccessID /*ioid*/, epics::pvData::PVStructure::shared_pointer const & /*pvRequest*/) { return epics::pvData::Status::Ok; } @@ -357,7 +357,7 @@ namespace epics { // 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*/) { + pvAccessID /*ioid*/, epics::pvData::PVStructure::shared_pointer const & /*pvRequest*/) { return epics::pvData::Status::Ok; } @@ -367,7 +367,7 @@ namespace epics { // 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*/) { + pvAccessID /*ioid*/, epics::pvData::PVStructure::shared_pointer const & /*pvRequest*/) { return epics::pvData::Status::Ok; } diff --git a/src/server/responseHandlers.cpp b/src/server/responseHandlers.cpp index 27b51f6..f8ec9f4 100644 --- a/src/server/responseHandlers.cpp +++ b/src/server/responseHandlers.cpp @@ -578,13 +578,30 @@ 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 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 tp(new ServerChannelRequesterImpl(transport, channelName, cid)); + std::tr1::shared_ptr tp(new ServerChannelRequesterImpl(transport, channelName, cid, css)); ChannelRequester::shared_pointer cr = tp; Channel::shared_pointer serverChannel = createRPCChannel(ChannelProvider::shared_pointer(), channelName, cr, serverRPCService); cr->channelCreated(Status::Ok, serverChannel); @@ -592,9 +609,9 @@ void ServerCreateChannelHandler::handleResponse(osiSockAddr* responseFrom, else { if (_providers.size() == 1) - ServerChannelRequesterImpl::create(_providers[0], transport, channelName, cid); + ServerChannelRequesterImpl::create(_providers[0], transport, channelName, cid, css); else - ServerChannelRequesterImpl::create(ServerSearchHandler::s_channelNameToProvider[channelName].lock(), transport, channelName, cid); // TODO !!!! + ServerChannelRequesterImpl::create(ServerSearchHandler::s_channelNameToProvider[channelName].lock(), transport, channelName, cid, css); // TODO !!!! } } @@ -604,11 +621,12 @@ void ServerCreateChannelHandler::disconnect(Transport::shared_pointer const & tr } ServerChannelRequesterImpl::ServerChannelRequesterImpl(Transport::shared_pointer const & transport, - const string channelName, const pvAccessID cid) : + const string channelName, const pvAccessID cid, ChannelSecuritySession::shared_pointer const & css) : _serverChannel(), _transport(transport), _channelName(channelName), _cid(cid), + _css(css), _status(), _mutex() { @@ -616,10 +634,10 @@ ServerChannelRequesterImpl::ServerChannelRequesterImpl(Transport::shared_pointer ChannelRequester::shared_pointer ServerChannelRequesterImpl::create( ChannelProvider::shared_pointer const & provider, Transport::shared_pointer const & transport, - const string channelName, const pvAccessID cid) + const string channelName, const pvAccessID cid, ChannelSecuritySession::shared_pointer const & css) { // TODO use std::make_shared - std::tr1::shared_ptr tp(new ServerChannelRequesterImpl(transport, channelName, cid)); + std::tr1::shared_ptr tp(new ServerChannelRequesterImpl(transport, channelName, cid, css)); ChannelRequester::shared_pointer cr = tp; // TODO exception guard and report error back provider->createChannel(channelName, cr, transport->getPriority()); @@ -646,8 +664,7 @@ void ServerChannelRequesterImpl::channelCreated(const Status& status, Channel::s pvAccessID sid = casTransport->preallocateChannelSID(); try { - epics::pvData::PVField::shared_pointer securityToken; // TODO replace with security session - serverChannel.reset(new ServerChannelImpl(channel, _cid, sid, securityToken)); + serverChannel.reset(new ServerChannelImpl(channel, _cid, sid, _css)); // ack allocation and register casTransport->registerChannel(sid, serverChannel); @@ -659,6 +676,12 @@ void ServerChannelRequesterImpl::channelCreated(const Status& status, Channel::s throw; } } + else + { + if (_css) + _css->close(); + } + { Lock guard(_mutex); @@ -679,7 +702,9 @@ 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 (...) { LOG(logLevelDebug, "Exception caught when creating channel: %s", _channelName.c_str()); @@ -690,7 +715,9 @@ 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(); + } } } @@ -832,7 +859,15 @@ void ServerGetHandler::handleResponse(osiSockAddr* responseFrom, // pvRequest PVStructure::shared_pointer pvRequest(SerializationHelper::deserializePVRequest(payloadBuffer, transport.get())); - // create... + // asCheck + Status asStatus = channel->getChannelSecuritySession()->authorizeCreateChannelGet(ioid, pvRequest); + if (!asStatus.isSuccess()) + { + BaseChannelRequester::sendFailureMessage((int8)CMD_GET, transport, ioid, qosCode, asStatus); + return; + } + + // create... ServerChannelGetRequesterImpl::create(_context, channel, ioid, transport, pvRequest); } else @@ -855,6 +890,14 @@ void ServerGetHandler::handleResponse(osiSockAddr* responseFrom, return; } + // asCheck + Status asStatus = channel->getChannelSecuritySession()->authorizeGet(ioid); + if (!asStatus.isSuccess()) + { + BaseChannelRequester::sendFailureMessage((int8)CMD_GET, transport, ioid, qosCode, asStatus); + return; + } + MB_POINT(channelGet, 4, "server channelGet->deserialize request (end)"); ChannelGet::shared_pointer channelGet = request->getChannelGet(); @@ -964,6 +1007,10 @@ void ServerChannelGetRequesterImpl::destroy() { Lock guard(_mutex); _channel->unregisterRequest(_ioid); + + // asCheck + _channel->getChannelSecuritySession()->release(_ioid); + if (_channelGet) { _channelGet->destroy(); @@ -1078,7 +1125,15 @@ void ServerPutHandler::handleResponse(osiSockAddr* responseFrom, // pvRequest PVStructure::shared_pointer pvRequest(SerializationHelper::deserializePVRequest(payloadBuffer, transport.get())); - // create... + // asCheck + Status asStatus = channel->getChannelSecuritySession()->authorizeCreateChannelPut(ioid, pvRequest); + if (!asStatus.isSuccess()) + { + BaseChannelRequester::sendFailureMessage((int8)CMD_PUT, transport, ioid, qosCode, asStatus); + return; + } + + // create... ServerChannelPutRequesterImpl::create(_context, channel, ioid, transport, pvRequest); } else @@ -1106,8 +1161,15 @@ void ServerPutHandler::handleResponse(osiSockAddr* responseFrom, if (get) { - // no destroy w/ get - channelPut->get(); + // asCheck + Status asStatus = channel->getChannelSecuritySession()->authorizeGet(ioid); + if (!asStatus.isSuccess()) + { + BaseChannelRequester::sendFailureMessage((int8)CMD_PUT, transport, ioid, qosCode, asStatus); + return; + } + + channelPut->get(); } else { @@ -1124,7 +1186,16 @@ void ServerPutHandler::handleResponse(osiSockAddr* responseFrom, ); lock.unlock(); - channelPut->put(putPVStructure, putBitSet); + + // asCheck + Status asStatus = channel->getChannelSecuritySession()->authorizePut(ioid, putPVStructure, putBitSet); + if (!asStatus.isSuccess()) + { + BaseChannelRequester::sendFailureMessage((int8)CMD_PUT, transport, ioid, qosCode, asStatus); + return; + } + + channelPut->put(putPVStructure, putBitSet); } } } @@ -1225,6 +1296,9 @@ void ServerChannelPutRequesterImpl::destroy() { Lock guard(_mutex); _channel->unregisterRequest(_ioid); + + _channel->getChannelSecuritySession()->release(_ioid); + if (_channelPut) { _channelPut->destroy(); diff --git a/src/server/responseHandlers.h b/src/server/responseHandlers.h index 41f0deb..35b21d6 100644 --- a/src/server/responseHandlers.h +++ b/src/server/responseHandlers.h @@ -222,10 +222,14 @@ namespace pvAccess { typedef std::tr1::shared_ptr shared_pointer; typedef std::tr1::shared_ptr const_shared_pointer; protected: - ServerChannelRequesterImpl(Transport::shared_pointer const & transport, const std::string channelName, const pvAccessID cid); + ServerChannelRequesterImpl(Transport::shared_pointer const & transport, + const std::string channelName, + const pvAccessID cid, ChannelSecuritySession::shared_pointer const & css); 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); + 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); void channelCreated(const epics::pvData::Status& status, Channel::shared_pointer const & channel); void channelStateChange(Channel::shared_pointer const & c, const Channel::ConnectionState isConnected); std::string getRequesterName(); @@ -238,6 +242,7 @@ namespace pvAccess { Transport::weak_pointer _transport; const std::string _channelName; const pvAccessID _cid; + ChannelSecuritySession::shared_pointer const & _css; epics::pvData::Status _status; epics::pvData::Mutex _mutex; void createChannelFailedResponse(epics::pvData::ByteBuffer* buffer, TransportSendControl* control, const epics::pvData::Status& status); diff --git a/src/server/serverChannelImpl.cpp b/src/server/serverChannelImpl.cpp index 09c4b41..259a796 100644 --- a/src/server/serverChannelImpl.cpp +++ b/src/server/serverChannelImpl.cpp @@ -11,11 +11,14 @@ using namespace epics::pvData; namespace epics { namespace pvAccess { -ServerChannelImpl::ServerChannelImpl(Channel::shared_pointer const & channel, pvAccessID cid, pvAccessID sid, epics::pvData::PVField::shared_pointer const & /*securityToken*/): +ServerChannelImpl::ServerChannelImpl(Channel::shared_pointer const & channel, + pvAccessID cid, pvAccessID sid, + ChannelSecuritySession::shared_pointer const & css): _channel(channel), _cid(cid), _sid(sid), - _destroyed(false) + _destroyed(false), + _channelSecuritySession(css) { if (!channel.get()) { @@ -38,10 +41,9 @@ pvAccessID ServerChannelImpl::getSID() const return _sid; } -int16 ServerChannelImpl::getAccessRights() +ChannelSecuritySession::shared_pointer ServerChannelImpl::getChannelSecuritySession() const { - //TODO implement - return 0; + return _channelSecuritySession; } void ServerChannelImpl::registerRequest(const pvAccessID id, Destroyable::shared_pointer const & request) @@ -80,6 +82,10 @@ void ServerChannelImpl::destroy() // destroy all requests destroyAllRequests(); + // close channel security session + // TODO try catch + _channelSecuritySession->close(); + // ... and the channel // TODO try catch _channel->destroy(); diff --git a/src/server/serverChannelImpl.h b/src/server/serverChannelImpl.h index 366e8b8..7760bd5 100644 --- a/src/server/serverChannelImpl.h +++ b/src/server/serverChannelImpl.h @@ -21,7 +21,7 @@ #include #include - +#include namespace epics { namespace pvAccess { @@ -36,9 +36,9 @@ public: * @param channel local channel. * @param cid channel CID. * @param sid channel SID. - * @param securityToken security token. + * @param css channel security session. */ - ServerChannelImpl(Channel::shared_pointer const & channel, pvAccessID cid, pvAccessID sid, epics::pvData::PVField::shared_pointer const & securityToken); + ServerChannelImpl(Channel::shared_pointer const & channel, pvAccessID cid, pvAccessID sid, ChannelSecuritySession::shared_pointer const & css); /* * Destructor. */ @@ -62,12 +62,11 @@ public: */ pvAccessID getSID() const; - /** - * Get access rights (bit-mask encoded). - * @see AccessRights - * @return bit-mask encoded access rights. - */ - epics::pvData::int16 getAccessRights(); + /** + * Get ChannelSecuritySession instance. + * @return the ChannelSecuritySession instance. + */ + ChannelSecuritySession::shared_pointer getChannelSecuritySession() const; /** * Register request @@ -136,6 +135,11 @@ private: */ epics::pvData::Mutex _mutex; + /** + * Channel security session. + */ + ChannelSecuritySession::shared_pointer _channelSecuritySession; + /** * Destroy all registered requests. */