PageRenderTime 26ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 0ms

/src/client/logic/Logic.cpp

https://gitlab.com/github-cloud-corporation/cynara
C++ | 213 lines | 154 code | 35 blank | 24 comment | 28 complexity | efb61d1ab94fc2273f5c9b9ae4a0c1a6 MD5 | raw file
  1. /*
  2. * Copyright (c) 2014-2016 Samsung Electronics Co., Ltd All Rights Reserved
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License
  15. */
  16. /**
  17. * @file src/client/logic/Logic.cpp
  18. * @author Lukasz Wojciechowski <l.wojciechow@partner.samsung.com>
  19. * @author Zofia Abramowska <z.abramowska@samsung.com>
  20. * @author Aleksander Zdyb <a.zdyb@samsung.com>
  21. * @version 1.0
  22. * @brief This file contains implementation of Logic class - main libcynara-client class
  23. */
  24. #include <cinttypes>
  25. #include <memory>
  26. #include <cache/CapacityCache.h>
  27. #include <common.h>
  28. #include <config/PathConfig.h>
  29. #include <cynara-error.h>
  30. #include <exceptions/Exception.h>
  31. #include <exceptions/UnexpectedErrorException.h>
  32. #include <log/log.h>
  33. #include <plugins/NaiveInterpreter.h>
  34. #include <protocol/Protocol.h>
  35. #include <protocol/ProtocolClient.h>
  36. #include <request/MonitorEntriesPutRequest.h>
  37. #include <request/CheckRequest.h>
  38. #include <request/pointers.h>
  39. #include <request/SimpleCheckRequest.h>
  40. #include <response/CheckResponse.h>
  41. #include <response/pointers.h>
  42. #include <response/SimpleCheckResponse.h>
  43. #include <sockets/SocketClient.h>
  44. #include <logic/Logic.h>
  45. namespace Cynara {
  46. static ProtocolFrameSequenceNumber generateSequenceNumber(void) {
  47. static ProtocolFrameSequenceNumber sequenceNumber = 0;
  48. return ++sequenceNumber;
  49. }
  50. Logic::Logic(const Configuration &conf) :
  51. m_socketClient(PathConfig::SocketPath::client, std::make_shared<ProtocolClient>()),
  52. m_cache(conf.getCacheSize()), m_monitoringEnabled(conf.monitoringEnabled()) {
  53. auto naiveInterpreter = std::make_shared<NaiveInterpreter>();
  54. for (auto &descr : naiveInterpreter->getSupportedPolicyDescr()) {
  55. m_cache.registerPlugin(descr, naiveInterpreter);
  56. }
  57. }
  58. Logic::~Logic() {
  59. flushMonitor();
  60. }
  61. int Logic::check(const std::string &client, const ClientSession &session, const std::string &user,
  62. const std::string &privilege) {
  63. if (!ensureConnection())
  64. return CYNARA_API_SERVICE_NOT_AVAILABLE;
  65. PolicyKey key(client, user, privilege);
  66. int ret = m_cache.get(session, key);
  67. if (ret != CYNARA_API_CACHE_MISS) {
  68. updateMonitor(key, ret);
  69. return ret;
  70. }
  71. PolicyResult result;
  72. ret = requestResult(key, result);
  73. if (ret != CYNARA_API_SUCCESS) {
  74. LOGE("Error fetching new entry.");
  75. return ret;
  76. }
  77. updateMonitor(key, ret);
  78. return m_cache.update(session, key, result);
  79. }
  80. int Logic::simpleCheck(const std::string &client, const ClientSession &session,
  81. const std::string &user, const std::string &privilege) {
  82. if (!ensureConnection())
  83. return CYNARA_API_SERVICE_NOT_AVAILABLE;
  84. PolicyKey key(client, user, privilege);
  85. int ret = m_cache.get(session, key);
  86. if (ret != CYNARA_API_CACHE_MISS) {
  87. return ret;
  88. }
  89. PolicyResult result;
  90. ret = requestSimpleResult(key, result);
  91. if (ret != CYNARA_API_SUCCESS) {
  92. if (ret != CYNARA_API_ACCESS_NOT_RESOLVED) {
  93. LOGE("Error fetching response for simpleCheck.");
  94. }
  95. return ret;
  96. }
  97. return m_cache.update(session, key, result);
  98. }
  99. bool Logic::ensureConnection(void) {
  100. if (m_socketClient.isConnected())
  101. return true;
  102. onDisconnected();
  103. if (m_socketClient.connect())
  104. return true;
  105. LOGW("Cannot connect to cynara. Service not available.");
  106. return false;
  107. }
  108. template <typename Req, typename Res>
  109. std::shared_ptr<Res> Logic::requestResponse(const PolicyKey &key) {
  110. ProtocolFrameSequenceNumber sequenceNumber = generateSequenceNumber();
  111. //Ask cynara service
  112. std::shared_ptr<Res> reqResponse;
  113. Req request(key, sequenceNumber);
  114. ResponsePtr response;
  115. while (!(response = m_socketClient.askCynaraServer(request))) {
  116. onDisconnected();
  117. if (!m_socketClient.connect())
  118. return nullptr;
  119. }
  120. reqResponse = std::dynamic_pointer_cast<Res>(response);
  121. return reqResponse;
  122. }
  123. int Logic::requestResult(const PolicyKey &key, PolicyResult &result) {
  124. auto checkResponse = requestResponse<CheckRequest, CheckResponse>(key);
  125. if (!checkResponse) {
  126. LOGC("Critical error. Requesting CheckResponse failed.");
  127. return CYNARA_API_SERVICE_NOT_AVAILABLE;
  128. }
  129. LOGD("checkResponse: policyType = %" PRIu16 ", metadata = %s",
  130. checkResponse->m_resultRef.policyType(),
  131. checkResponse->m_resultRef.metadata().c_str());
  132. result = checkResponse->m_resultRef;
  133. return CYNARA_API_SUCCESS;
  134. }
  135. int Logic::requestSimpleResult(const PolicyKey &key, PolicyResult &result) {
  136. auto simpleCheckResponse = requestResponse<SimpleCheckRequest, SimpleCheckResponse>(key);
  137. if (!simpleCheckResponse) {
  138. LOGC("Critical error. Requesting SimpleCheckResponse failed.");
  139. return CYNARA_API_SERVICE_NOT_AVAILABLE;
  140. }
  141. if (simpleCheckResponse->getReturnValue() != CYNARA_API_SUCCESS)
  142. return simpleCheckResponse->getReturnValue();
  143. LOGD("SimpleCheckResponse: policyType = %" PRIu16 ", metadata = %s",
  144. simpleCheckResponse->getResult().policyType(),
  145. simpleCheckResponse->getResult().metadata().c_str());
  146. result = simpleCheckResponse->getResult();
  147. return CYNARA_API_SUCCESS;
  148. }
  149. bool Logic::requestMonitorEntriesPut() {
  150. ProtocolFrameSequenceNumber sequenceNumber = generateSequenceNumber();
  151. MonitorEntriesPutRequest request(m_monitorCache.entries(), sequenceNumber);
  152. return m_socketClient.sendAndForget(request);
  153. }
  154. void Logic::onDisconnected(void) {
  155. m_cache.clear();
  156. }
  157. void Logic::updateMonitor(const PolicyKey &policyKey, int result) {
  158. if (!m_monitoringEnabled)
  159. return;
  160. m_monitorCache.update(policyKey, result);
  161. if (m_monitorCache.shouldFlush())
  162. flushMonitor();
  163. }
  164. void Logic::flushMonitor() {
  165. if (!m_monitoringEnabled)
  166. return;
  167. if (m_monitorCache.entries().size() == 0)
  168. return;
  169. if (!ensureConnection()) {
  170. LOGE("Could not flush monitor entries: connection lost");
  171. return;
  172. }
  173. auto flushSuccess = requestMonitorEntriesPut();
  174. if (flushSuccess) {
  175. m_monitorCache.clear();
  176. }
  177. }
  178. } // namespace Cynara