From: Marcin Niesluchowski Date: Fri, 14 Nov 2014 12:18:32 +0000 (+0100) Subject: Forbid some operations in asynchronous callbacks X-Git-Tag: submit/R4/20141115.054144~15 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F22%2F30322%2F8;p=platform%2Fcore%2Fsecurity%2Fcynara.git Forbid some operations in asynchronous callbacks In following cases cynara api operations regarding same cynara_async structure called from within callbacks will return CYNARA_API_OPERATION_NOT_ALLOWED: - always within cynara_status_callback - within cynara_response_callback called with CYNARA_CALL_CAUSE_SERVICE_NOT_AVAILABLE or CYNARA_CALL_CAUSE_FINISH cause. It regards following api funtions: - cynara_async_check_cache() - cynara_async_create_request() - cynara_async_process() - cynara_async_cancel_request() Change-Id: I1db22e0735e1905c4709c7f4c650cc8ca3f9b454 --- diff --git a/src/client-async/logic/Logic.cpp b/src/client-async/logic/Logic.cpp index 9725d64..5e0157d 100644 --- a/src/client-async/logic/Logic.cpp +++ b/src/client-async/logic/Logic.cpp @@ -43,7 +43,7 @@ namespace Cynara { Logic::Logic(cynara_status_callback callback, void *userStatusData) - : m_statusCallback(callback, userStatusData) { + : m_statusCallback(callback, userStatusData), m_operationPermitted(true) { m_socketClient = std::make_shared( PathConfig::SocketPath::client, std::make_shared()); @@ -55,6 +55,7 @@ Logic::Logic(cynara_status_callback callback, void *userStatusData) } Logic::~Logic() { + m_operationPermitted = false; for (auto &kv : m_checks) { if (!kv.second.cancelled()) kv.second.callback().onFinish(kv.first); @@ -64,6 +65,9 @@ Logic::~Logic() { int Logic::checkCache(const std::string &client, const std::string &session, const std::string &user, const std::string &privilege) { + if (!m_operationPermitted) + return CYNARA_API_OPERATION_NOT_ALLOWED; + if (!checkCacheValid()) return CYNARA_API_CACHE_MISS; @@ -74,6 +78,9 @@ int Logic::createRequest(const std::string &client, const std::string &session, const std::string &user, const std::string &privilege, cynara_check_id &checkId, cynara_response_callback callback, void *userResponseData) { + if (!m_operationPermitted) + return CYNARA_API_OPERATION_NOT_ALLOWED; + if (!ensureConnection()) return CYNARA_API_SERVICE_NOT_AVAILABLE; @@ -86,14 +93,16 @@ int Logic::createRequest(const std::string &client, const std::string &session, m_checks.insert(CheckPair(sequenceNumber, CheckData(key, session, responseCallback))); m_socketClient->appendRequest(std::make_shared(key, sequenceNumber)); - m_statusCallback.onStatusChange(m_socketClient->getSockFd(), - cynara_async_status::CYNARA_STATUS_FOR_RW); + onStatusChange(m_socketClient->getSockFd(), cynara_async_status::CYNARA_STATUS_FOR_RW); checkId = static_cast(sequenceNumber); return CYNARA_API_SUCCESS; } int Logic::process(void) { + if (!m_operationPermitted) + return CYNARA_API_OPERATION_NOT_ALLOWED; + bool completed; while (true) { int ret = completeConnection(completed); @@ -108,6 +117,9 @@ int Logic::process(void) { } int Logic::cancelRequest(cynara_check_id checkId) { + if (!m_operationPermitted) + return CYNARA_API_OPERATION_NOT_ALLOWED; + if (!ensureConnection()) return CYNARA_API_SERVICE_NOT_AVAILABLE; @@ -119,8 +131,7 @@ int Logic::cancelRequest(cynara_check_id checkId) { it->second.cancel(); it->second.callback().onCancel(it->first); - m_statusCallback.onStatusChange(m_socketClient->getSockFd(), - cynara_async_status::CYNARA_STATUS_FOR_RW); + onStatusChange(m_socketClient->getSockFd(), cynara_async_status::CYNARA_STATUS_FOR_RW); return CYNARA_API_SUCCESS; } @@ -144,8 +155,8 @@ void Logic::prepareRequestsToSend(void) { bool Logic::processOut(void) { switch (m_socketClient->sendToCynara()) { case Socket::SendStatus::ALL_DATA_SENT: - m_statusCallback.onStatusChange(m_socketClient->getSockFd(), - cynara_async_status::CYNARA_STATUS_FOR_READ); + onStatusChange(m_socketClient->getSockFd(), + cynara_async_status::CYNARA_STATUS_FOR_READ); case Socket::SendStatus::PARTIAL_DATA_SENT: return true; default: @@ -238,12 +249,11 @@ bool Logic::connect(void) { switch (m_socketClient->connect()) { case Socket::ConnectionStatus::CONNECTION_SUCCEEDED: prepareRequestsToSend(); - m_statusCallback.onStatusChange(m_socketClient->getSockFd(), socketDataStatus()); + onStatusChange(m_socketClient->getSockFd(), socketDataStatus()); return true; case Socket::ConnectionStatus::CONNECTION_IN_PROGRESS: prepareRequestsToSend(); - m_statusCallback.onStatusChange(m_socketClient->getSockFd(), - cynara_async_status::CYNARA_STATUS_FOR_RW); + onStatusChange(m_socketClient->getSockFd(), cynara_async_status::CYNARA_STATUS_FOR_RW); return true; default: onServiceNotAvailable(); @@ -257,7 +267,7 @@ int Logic::completeConnection(bool &completed) { completed = true; return CYNARA_API_SUCCESS; case Socket::ConnectionStatus::CONNECTION_SUCCEEDED: - m_statusCallback.onStatusChange(m_socketClient->getSockFd(), socketDataStatus()); + onStatusChange(m_socketClient->getSockFd(), socketDataStatus()); completed = true; return CYNARA_API_SUCCESS; case Socket::ConnectionStatus::CONNECTION_IN_PROGRESS: @@ -271,19 +281,29 @@ int Logic::completeConnection(bool &completed) { } } +void Logic::onStatusChange(int sock, cynara_async_status status) { + m_operationPermitted = false; + m_statusCallback.onStatusChange(sock, status); + m_operationPermitted = true; +} + void Logic::onServiceNotAvailable(void) { + m_operationPermitted = false; for (auto &kv : m_checks) { if (!kv.second.cancelled()) kv.second.callback().onDisconnected(kv.first); } m_checks.clear(); m_sequenceContainer.clear(); + m_operationPermitted = true; } void Logic::onDisconnected(void) { + m_operationPermitted = false; m_cache->clear(); m_statusCallback.onDisconnected(); + m_operationPermitted = true; } } // namespace Cynara diff --git a/src/client-async/logic/Logic.h b/src/client-async/logic/Logic.h index 0bca98e..6f30fdb 100644 --- a/src/client-async/logic/Logic.h +++ b/src/client-async/logic/Logic.h @@ -59,6 +59,7 @@ private: SocketClientAsyncPtr m_socketClient; CheckMap m_checks; SequenceContainer m_sequenceContainer; + bool m_operationPermitted; bool checkCacheValid(void); void prepareRequestsToSend(void); @@ -71,6 +72,7 @@ private: bool ensureConnection(void); bool connect(void); int completeConnection(bool &completed); + void onStatusChange(int sock, cynara_async_status status); void onServiceNotAvailable(void); void onDisconnected(void); }; diff --git a/src/include/cynara-client-async.h b/src/include/cynara-client-async.h index 536e5d7..b9675f1 100644 --- a/src/include/cynara-client-async.h +++ b/src/include/cynara-client-async.h @@ -84,6 +84,8 @@ typedef enum { * (CYNARA_CALL_CAUSE_FINISH) * 4) when connection to cynara service was broken and cannot be established again * - probably cynara is unoperational (CYNARA_CALL_CAUSE_SERVICE_NOT_AVAILABLE) + * Api functions called during this callback with CYNARA_CALL_CAUSE_SERVICE_NOT_AVAILABLE + * or CYNARA_CALL_CAUSE_FINISH cause will return CYNARA_API_OPERATION_NOT_ALLOWED. * * \param[in] check_id Number identifying check request. Number is generated in * cynara_async_create_request() and returned to user. It can be used to match @@ -113,6 +115,7 @@ typedef void (*cynara_response_callback) (cynara_check_id check_id, cynara_async * Note, that provided file descriptor is used internally by libcynara * so user should not use it in other way than waiting on it in event loop. * In particular user should not write to, read from or close this fd. + * CYNARA_API_OPERATION_NOT_ALLOWED will be returned for every api function called in this callback. * * \param[in] old_fd Old descriptor which should be unregistered from event loop, * Special value -1 is used when callback is called after first @@ -240,7 +243,10 @@ void cynara_async_finish(cynara_async *p_cynara); * * \par Important notes: * Call to cynara_async_check_cache() needs cynara_async structure to be created first. - * Use cynara_async_initialize() before calling this function. + * Use cynara_async_initialize() before calling this function. cynara_async_check_cache() called + * from within cynara_status_callback or cynara_response_callback with + * CYNARA_CALL_CAUSE_SERVICE_NOT_AVAILABLE or CYNARA_CALL_CAUSE_FINISH cause will return + * CYNARA_API_OPERATION_NOT_ALLOWED. * * \param[in] p_cynara cynara_async structure. * \param[in] client Application or process identifier. @@ -306,6 +312,9 @@ int cynara_async_check_cache(cynara_async *p_cynara, const char *client, const c * If function fails (returns negative error code) request won't be generated and won't be pending, * callback function won't be ever called and user_response_data won't be remembered by library. * Also no check_id will be generated and *p_check_id value should be ignored. + * cynara_async_create_request() called from within cynara_status_callback or + * cynara_response_callback with CYNARA_CALL_CAUSE_SERVICE_NOT_AVAILABLE or CYNARA_CALL_CAUSE_FINISH + * cause will return CYNARA_API_OPERATION_NOT_ALLOWED. * * \param[in] p_cynara cynara_async structure. * \param[in] client Application or process identifier. @@ -359,7 +368,9 @@ int cynara_async_create_request(cynara_async *p_cynara, const char *client, * * \par Important notes: * Call to cynara_async_process() requires initialized cynara_async structure. For this use - * cynara_async_initialize(). + * cynara_async_initialize(). cynara_async_process() called from within cynara_status_callback or + * cynara_response_callback with CYNARA_CALL_CAUSE_SERVICE_NOT_AVAILABLE or CYNARA_CALL_CAUSE_FINISH + * cause will return CYNARA_API_OPERATION_NOT_ALLOWED. * * \param[in] p_cynara cynara_async structure. * @@ -398,7 +409,9 @@ int cynara_async_process(cynara_async *p_cynara); * * \par Important notes: * Call to cynara_async_cancel_request() needs cynara_async structure to be created first. For this - * use cynara_async_initialize(). + * use cynara_async_initialize(). cynara_async_cancel_request() called from within + * cynara_status_callback or cynara_response_callback with CYNARA_CALL_CAUSE_SERVICE_NOT_AVAILABLE + * or CYNARA_CALL_CAUSE_FINISH cause will return CYNARA_API_OPERATION_NOT_ALLOWED. * * \param[in] p_cynara cynara_async structure. * \param[in] check_id Check id to be cancelled