From 7f339a1e206f36e92139eb16de499ceba6b7cba6 Mon Sep 17 00:00:00 2001 From: Rafal Krypa Date: Wed, 3 Sep 2014 16:22:45 +0200 Subject: [PATCH 01/16] build: unbreak out-of-tree build of pkgconfig files Fix regression introduced recently in 21175a33. "Make install" fails on pkgconfig files when building out-of-tree. Change-Id: Ib544993ae4daa784ca93d9e115eeba9830957ecc Signed-off-by: Rafal Krypa --- pkgconfig/cynara-admin/CMakeLists.txt | 2 +- pkgconfig/cynara-client/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgconfig/cynara-admin/CMakeLists.txt b/pkgconfig/cynara-admin/CMakeLists.txt index 6adc6b9..c66ec5c 100644 --- a/pkgconfig/cynara-admin/CMakeLists.txt +++ b/pkgconfig/cynara-admin/CMakeLists.txt @@ -20,7 +20,7 @@ CONFIGURE_FILE(cynara-admin.pc.in cynara-admin.pc @ONLY) INSTALL(FILES - cynara-admin.pc + ${CMAKE_BINARY_DIR}/pkgconfig/cynara-admin/cynara-admin.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig ) diff --git a/pkgconfig/cynara-client/CMakeLists.txt b/pkgconfig/cynara-client/CMakeLists.txt index ecb78c7..03ee41e 100644 --- a/pkgconfig/cynara-client/CMakeLists.txt +++ b/pkgconfig/cynara-client/CMakeLists.txt @@ -20,7 +20,7 @@ CONFIGURE_FILE(cynara-client.pc.in cynara-client.pc @ONLY) INSTALL(FILES - cynara-client.pc + ${CMAKE_BINARY_DIR}/pkgconfig/cynara-client/cynara-client.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig ) -- 2.7.4 From fc366e4070b6a2696e4de4e42cbd4b740f7ade15 Mon Sep 17 00:00:00 2001 From: Rafal Krypa Date: Wed, 3 Sep 2014 16:04:26 +0200 Subject: [PATCH 02/16] build: allow conditional building of cynara-tests, turn it on in spec Change cmake to build cynara-tests only when enabled and enable it in spec file. This will enable cynara build outside of Tizen (without tests). Current setup for cynara-tests build depends on Tizen-specific packaging of gmock package. This dependency cannot be met outside of Tizen, which would break the whole build. It is not easy to apply a proper fix to have cynara-tests built outside of Tizen. Gmock is not meant to be used as dependency in such way. Most certainly we will have to handle gmock dependency differently in upstream and in Tizen. Change-Id: Id9fc8142979d1a2061c1c72c610520479d9e61a2 Signed-off-by: Rafal Krypa --- CMakeLists.txt | 5 ++++- packaging/cynara.spec | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 18b0dee..8c10a18 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -88,6 +88,9 @@ SET(TARGET_LIB_CREDS_SOCKET "cynara-creds-socket") SET(TARGET_LIB_SESSION "cynara-session") ADD_SUBDIRECTORY(src) -ADD_SUBDIRECTORY(test) ADD_SUBDIRECTORY(pkgconfig) ADD_SUBDIRECTORY(systemd) + +IF (BUILD_TESTS) +ADD_SUBDIRECTORY(test) +ENDIF() diff --git a/packaging/cynara.spec b/packaging/cynara.spec index a297c4f..ce6fe5c 100644 --- a/packaging/cynara.spec +++ b/packaging/cynara.spec @@ -209,6 +209,7 @@ export CXXFLAGS="$CXXFLAGS -DCYNARA_STATE_PATH=\\\"%{state_path}\\\"" export LDFLAGS+="-Wl,--rpath=%{_libdir}" %cmake . \ + -DBUILD_TESTS=ON \ -DCMAKE_BUILD_TYPE=%{?build_type} \ -DCMAKE_VERBOSE_MAKEFILE=ON make %{?jobs:-j%jobs} -- 2.7.4 From bb1f0f1ab80f9f02f04140f6da35f01902522508 Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Fri, 5 Sep 2014 16:31:43 +0200 Subject: [PATCH 03/16] Add changelog for keeping release history Changelog filled with historical data. Change-Id: Idf35e1024d19ac2e66699b2aea6555a5a37ae323 --- changelog | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 changelog diff --git a/changelog b/changelog new file mode 100644 index 0000000..5887ebc --- /dev/null +++ b/changelog @@ -0,0 +1,75 @@ +############################## + +Release: 0.2.2 +Date: 2014.08.08 +Name: Merge cynara and cynara-tests SRPMs + +Libraries: +libcynara-common.0.0.1 +libcynara-client.0.0.2 +libcynara-admin.0.0.2 + +Description: +Cynara's and cynara-tests spec files were merged. They are built together now. + +############################## + +Release: 0.2.1 +Date: 2014.08.06 +Name: "cynara" system user + +Libraries: +libcynara-common.0.0.1 +libcynara-client.0.0.2 +libcynara-admin.0.0.2 + +Description: +Cynara service runs as user cynara, created during package installation. +Minor bug fixing. + +############################## + +Release: 0.2.0 +Date: 2014.08.01 +Name: Client cache feature + +Libraries: +libcynara-common.0.0.1 +libcynara-client.0.0.2 +libcynara-admin.0.0.2 + +Description: +Policy responses cache added in libcynara-client. +Lots of code cleaning and bug fixing. + +############################## + +Release: 0.1.1 +Date: 2014.07.21 +Name: First version base on cynara service + +Libraries: +libcynara-common.0.0.1 +libcynara-client.0.0.2 +libcynara-admin.0.0.2 + +Description: +First version of cynara using own service and database. +API provided by 2 libraries - client for privilege checking +and admin for managing policies in database. + +############################## + +Release: 0.0.1 +Date: 2014.05.08 +Name: Cynara bootstrap version + +Libraries: +libcynara-client.0.0.1 + +Description: +First version of cynara client - using security-server API. +libprivilege-control database was used for holding privilege access policies. + +############################## + -- 2.7.4 From 9e1c068991d3f0673bf946651a5753986389be0d Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Fri, 5 Sep 2014 16:56:04 +0200 Subject: [PATCH 04/16] Release 0.3.0 Change-Id: I5e2b5d39b1a14dca7575dcfd8812087f401dc82a --- changelog | 21 +++++++++++++++++++++ packaging/cynara.spec | 2 +- src/admin/CMakeLists.txt | 2 +- src/client-common/CMakeLists.txt | 2 +- src/client/CMakeLists.txt | 2 +- src/common/CMakeLists.txt | 2 +- src/helpers/creds-commons/CMakeLists.txt | 2 +- src/helpers/creds-dbus/CMakeLists.txt | 2 +- src/helpers/creds-socket/CMakeLists.txt | 2 +- src/helpers/session/CMakeLists.txt | 2 +- 10 files changed, 30 insertions(+), 9 deletions(-) diff --git a/changelog b/changelog index 5887ebc..a2d08e3 100644 --- a/changelog +++ b/changelog @@ -1,5 +1,26 @@ ############################## +Release: 0.3.0 +Date: 2014.09.05 +Name: Helper libraries + +Libraries: +libcynara-common.0.3.0 +libcynara-client.0.3.0 +libcynara-client-common.0.3.0 +libcynara-admin.0.3.0 +libcynara-session.0.3.0 +libcynara-creds-commons.0.3.0 +libcynara-creds-dbus.0.3.0 +libcynara-creds-socket.0.3.0 + +Description: +Helper libraries for credentials and session. +Client-common library - common for all client libraries introduced. +Improve cache performance and move cache to client-common library. + +############################## + Release: 0.2.2 Date: 2014.08.08 Name: Merge cynara and cynara-tests SRPMs diff --git a/packaging/cynara.spec b/packaging/cynara.spec index ce6fe5c..677142b 100644 --- a/packaging/cynara.spec +++ b/packaging/cynara.spec @@ -1,6 +1,6 @@ Name: cynara Summary: Cynara service with client libraries -Version: 0.2.2 +Version: 0.3.0 Release: 1 Group: Security/Access Control License: Apache-2.0 diff --git a/src/admin/CMakeLists.txt b/src/admin/CMakeLists.txt index cc3d7ac..4918571 100644 --- a/src/admin/CMakeLists.txt +++ b/src/admin/CMakeLists.txt @@ -17,7 +17,7 @@ # SET(LIB_CYNARA_ADMIN_VERSION_MAJOR 0) -SET(LIB_CYNARA_ADMIN_VERSION ${LIB_CYNARA_ADMIN_VERSION_MAJOR}.0.2) +SET(LIB_CYNARA_ADMIN_VERSION ${LIB_CYNARA_ADMIN_VERSION_MAJOR}.3.0) SET(CYNARA_LIB_CYNARA_ADMIN_PATH ${CYNARA_PATH}/admin) diff --git a/src/client-common/CMakeLists.txt b/src/client-common/CMakeLists.txt index dd05c79..90e09d7 100644 --- a/src/client-common/CMakeLists.txt +++ b/src/client-common/CMakeLists.txt @@ -17,7 +17,7 @@ # SET(LIB_CYNARA_CLIENT_COMMON_VERSION_MAJOR 0) -SET(LIB_CYNARA_CLIENT_COMMON_VERSION ${LIB_CYNARA_CLIENT_COMMON_VERSION_MAJOR}.0.2) +SET(LIB_CYNARA_CLIENT_COMMON_VERSION ${LIB_CYNARA_CLIENT_COMMON_VERSION_MAJOR}.3.0) SET(LIB_CYNARA_COMMON_PATH ${CYNARA_PATH}/client-common) diff --git a/src/client/CMakeLists.txt b/src/client/CMakeLists.txt index d364e2d..db0622c 100644 --- a/src/client/CMakeLists.txt +++ b/src/client/CMakeLists.txt @@ -18,7 +18,7 @@ # SET(LIB_CYNARA_VERSION_MAJOR 0) -SET(LIB_CYNARA_VERSION ${LIB_CYNARA_VERSION_MAJOR}.0.2) +SET(LIB_CYNARA_VERSION ${LIB_CYNARA_VERSION_MAJOR}.3.0) SET(LIB_CYNARA_PATH ${CYNARA_PATH}/client) diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index f489b44..8f99d0e 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -17,7 +17,7 @@ # SET(CYNARA_COMMON_VERSION_MAJOR 0) -SET(CYNARA_COMMON_VERSION ${CYNARA_COMMON_VERSION_MAJOR}.0.1) +SET(CYNARA_COMMON_VERSION ${CYNARA_COMMON_VERSION_MAJOR}.3.0) SET(COMMON_PATH ${CYNARA_PATH}/common) diff --git a/src/helpers/creds-commons/CMakeLists.txt b/src/helpers/creds-commons/CMakeLists.txt index 00484b7..92b31bd 100644 --- a/src/helpers/creds-commons/CMakeLists.txt +++ b/src/helpers/creds-commons/CMakeLists.txt @@ -19,7 +19,7 @@ # SET(LIB_CREDS_COMMONS_VERSION_MAJOR 0) -SET(LIB_CREDS_COMMONS_VERSION ${LIB_CREDS_COMMONS_VERSION_MAJOR}.0.1) +SET(LIB_CREDS_COMMONS_VERSION ${LIB_CREDS_COMMONS_VERSION_MAJOR}.3.0) SET(LIB_CREDS_COMMONS_PATH ${CYNARA_PATH}/helpers/creds-commons) diff --git a/src/helpers/creds-dbus/CMakeLists.txt b/src/helpers/creds-dbus/CMakeLists.txt index c80d301..d4ea94c 100644 --- a/src/helpers/creds-dbus/CMakeLists.txt +++ b/src/helpers/creds-dbus/CMakeLists.txt @@ -19,7 +19,7 @@ # SET(LIB_CREDS_DBUS_VERSION_MAJOR 0) -SET(LIB_CREDS_DBUS_VERSION ${LIB_CREDS_DBUS_VERSION_MAJOR}.0.1) +SET(LIB_CREDS_DBUS_VERSION ${LIB_CREDS_DBUS_VERSION_MAJOR}.3.0) SET(LIB_CREDS_DBUS_PATH ${CYNARA_PATH}/helpers/creds-dbus) diff --git a/src/helpers/creds-socket/CMakeLists.txt b/src/helpers/creds-socket/CMakeLists.txt index a425c0b..0a05e10 100644 --- a/src/helpers/creds-socket/CMakeLists.txt +++ b/src/helpers/creds-socket/CMakeLists.txt @@ -19,7 +19,7 @@ # SET(LIB_CREDS_SOCKET_VERSION_MAJOR 0) -SET(LIB_CREDS_SOCKET_VERSION ${LIB_CREDS_SOCKET_VERSION_MAJOR}.0.1) +SET(LIB_CREDS_SOCKET_VERSION ${LIB_CREDS_SOCKET_VERSION_MAJOR}.3.0) SET(LIB_CREDS_SOCKET_PATH ${CYNARA_PATH}/helpers/creds-socket) diff --git a/src/helpers/session/CMakeLists.txt b/src/helpers/session/CMakeLists.txt index b019f4c..0de24c4 100644 --- a/src/helpers/session/CMakeLists.txt +++ b/src/helpers/session/CMakeLists.txt @@ -19,7 +19,7 @@ # SET(LIB_SESSION_VERSION_MAJOR 0) -SET(LIB_SESSION_VERSION ${LIB_SESSION_VERSION_MAJOR}.0.1) +SET(LIB_SESSION_VERSION ${LIB_SESSION_VERSION_MAJOR}.3.0) SET(LIB_SESSION_PATH ${CYNARA_PATH}/helpers/session) -- 2.7.4 From 2324fffe9befd04cc57d396265f12750216bfd5a Mon Sep 17 00:00:00 2001 From: Aleksander Zdyb Date: Mon, 18 Aug 2014 13:05:58 +0200 Subject: [PATCH 05/16] Add start point in Storage::checkPolicy() Storage::checkPolicy() now accepts id of bucket to start search with. Additional parameter (recursive) indicates, if search should go down into encountered buckets. Change-Id: I23ff8e044fc9ff0198183c335ffe845e75efe08b --- src/common/types/PolicyBucket.h | 7 +++++++ src/service/storage/Storage.cpp | 19 ++++++++++++------- src/service/storage/Storage.h | 6 ++++-- src/service/storage/StorageBackend.h | 1 + test/storage/storage/check.cpp | 32 +++++++++++++++++++++----------- 5 files changed, 45 insertions(+), 20 deletions(-) diff --git a/src/common/types/PolicyBucket.h b/src/common/types/PolicyBucket.h index b865d9e..c4675c2 100644 --- a/src/common/types/PolicyBucket.h +++ b/src/common/types/PolicyBucket.h @@ -48,12 +48,19 @@ public: typedef PolicyCollection::value_type value_type; typedef const_policy_iterator const_iterator; + // TODO: Review usefulness of ctors PolicyBucket() : m_defaultPolicy(PredefinedPolicyType::DENY) {} PolicyBucket(const PolicyBucketId &id, const PolicyResult &defaultPolicy) : m_defaultPolicy(defaultPolicy), m_id(id) {} PolicyBucket(const PolicyCollection &policies) : m_policyCollection(makePolicyMap(policies)), m_defaultPolicy(PredefinedPolicyType::DENY) {} + PolicyBucket(const PolicyBucketId &id, + const PolicyResult &defaultPolicy, + const PolicyCollection &policies) + : m_policyCollection(makePolicyMap(policies)), + m_defaultPolicy(defaultPolicy), + m_id(id) {} PolicyBucket filtered(const PolicyKey &key) const; void insertPolicy(PolicyPtr policy); diff --git a/src/service/storage/Storage.cpp b/src/service/storage/Storage.cpp index 7f92c34..8e81edc 100644 --- a/src/service/storage/Storage.cpp +++ b/src/service/storage/Storage.cpp @@ -38,12 +38,15 @@ namespace Cynara { -PolicyResult Storage::checkPolicy(const PolicyKey &key) { - auto policies = m_backend.searchDefaultBucket(key); - return minimalPolicy(policies, key); +PolicyResult Storage::checkPolicy(const PolicyKey &key, + const PolicyBucketId &startBucketId /*= defaultPolicyBucketId*/, + bool recursive /*= true*/) { + auto policies = m_backend.searchBucket(startBucketId, key); + return minimalPolicy(policies, key, recursive); }; -PolicyResult Storage::minimalPolicy(const PolicyBucket &bucket, const PolicyKey &key) { +PolicyResult Storage::minimalPolicy(const PolicyBucket &bucket, const PolicyKey &key, + bool recursive) { bool hasMinimal = false; PolicyResult minimal = bucket.defaultPolicy(); @@ -63,9 +66,11 @@ PolicyResult Storage::minimalPolicy(const PolicyBucket &bucket, const PolicyKey case PredefinedPolicyType::DENY: return policyResult; // Do not expect lower value than DENY case PredefinedPolicyType::BUCKET: { - auto bucketResults = m_backend.searchBucket(policyResult.metadata(), key); - auto minimumOfBucket = minimalPolicy(bucketResults, key); - proposeMinimal(minimumOfBucket); + if (recursive == true) { + auto bucketResults = m_backend.searchBucket(policyResult.metadata(), key); + auto minimumOfBucket = minimalPolicy(bucketResults, key, true); + proposeMinimal(minimumOfBucket); + } continue; } case PredefinedPolicyType::ALLOW: diff --git a/src/service/storage/Storage.h b/src/service/storage/Storage.h index adee6ec..82052d0 100644 --- a/src/service/storage/Storage.h +++ b/src/service/storage/Storage.h @@ -43,7 +43,9 @@ class Storage public: Storage(StorageBackend &backend) : m_backend(backend) {} - PolicyResult checkPolicy(const PolicyKey &key); + PolicyResult checkPolicy(const PolicyKey &key, + const PolicyBucketId &startBucketId = defaultPolicyBucketId, + bool recursive = true); void insertPolicies(const std::map> &policiesByBucketId); void deletePolicies(const std::map> &keysByBucketId); @@ -55,7 +57,7 @@ public: void save(void); protected: - PolicyResult minimalPolicy(const PolicyBucket &bucket, const PolicyKey &key); + PolicyResult minimalPolicy(const PolicyBucket &bucket, const PolicyKey &key, bool recursive); private: StorageBackend &m_backend; // backend strategy diff --git a/src/service/storage/StorageBackend.h b/src/service/storage/StorageBackend.h index cc711f9..b015bf0 100644 --- a/src/service/storage/StorageBackend.h +++ b/src/service/storage/StorageBackend.h @@ -37,6 +37,7 @@ class StorageBackend { public: virtual ~StorageBackend() {} + // TODO: Remove searchDefaultBucket() virtual PolicyBucket searchDefaultBucket(const PolicyKey &key) = 0; virtual PolicyBucket searchBucket(const PolicyBucketId &bucket, const PolicyKey &key) = 0; diff --git a/test/storage/storage/check.cpp b/test/storage/storage/check.cpp index e71e40f..f56e7fe 100644 --- a/test/storage/storage/check.cpp +++ b/test/storage/storage/check.cpp @@ -49,7 +49,7 @@ TEST(storage, checkEmpty) { Cynara::Storage storage(backend); PolicyKey pk = Helpers::generatePolicyKey(); - EXPECT_CALL(backend, searchDefaultBucket(pk)) + EXPECT_CALL(backend, searchBucket(defaultPolicyBucketId, pk)) .WillOnce(ReturnPointee(&emptyBucket)); // Default bucket empty -- return DENY @@ -66,7 +66,7 @@ TEST(storage, checkSimple) { Cynara::Storage storage(backend); PolicyKey pk = Helpers::generatePolicyKey(); - EXPECT_CALL(backend, searchDefaultBucket(pk)) + EXPECT_CALL(backend, searchBucket(defaultPolicyBucketId, pk)) .WillRepeatedly(ReturnPointee(&bucket)); // Default bucket empty -- return DENY @@ -81,6 +81,7 @@ TEST(storage, checkSimple) { ASSERT_EQ(PredefinedPolicyType::DENY, storage.checkPolicy(pk).policyType()); } +// TODO: Refactorize to resemble checkNonrecursive() TEST(storage, checkBucket) { using ::testing::ReturnPointee; @@ -97,9 +98,6 @@ TEST(storage, checkBucket) { PolicyBucket additionalBucket; - EXPECT_CALL(backend, searchDefaultBucket(pk)) - .WillRepeatedly(ReturnPointee(&defaultBucket)); - EXPECT_CALL(backend, searchBucket(defaultPolicyBucketId, pk)) .WillRepeatedly(ReturnPointee(&defaultBucket)); @@ -136,9 +134,6 @@ TEST(storage, checkBucketWildcard) { FakeStorageBackend backend; Cynara::Storage storage(backend); - EXPECT_CALL(backend, searchDefaultBucket(checkKey)) - .WillRepeatedly(ReturnPointee(&defaultBucket)); - EXPECT_CALL(backend, searchBucket(defaultPolicyBucketId, checkKey)) .WillRepeatedly(ReturnPointee(&defaultBucket)); @@ -166,9 +161,6 @@ TEST(storage, checkBucketWildcardOtherDefault) { FakeStorageBackend backend; Cynara::Storage storage(backend); - EXPECT_CALL(backend, searchDefaultBucket(checkKey)) - .WillRepeatedly(ReturnPointee(&defaultBucket)); - EXPECT_CALL(backend, searchBucket(defaultPolicyBucketId, checkKey)) .WillRepeatedly(ReturnPointee(&defaultBucket)); @@ -179,3 +171,21 @@ TEST(storage, checkBucketWildcardOtherDefault) { // Should return additional bucket's default policy ASSERT_EQ(PredefinedPolicyType::ALLOW, storage.checkPolicy(checkKey)); } + +TEST(storage, checkNonrecursive) { + using ::testing::ReturnPointee; + + PolicyKey pk = Helpers::generatePolicyKey(); + PolicyBucketId bucketId = "a-bucket"; + + PolicyBucket bucket(bucketId, PredefinedPolicyType::ALLOW, + { Policy::bucketWithKey(pk, "must-not-be-touched") }); + FakeStorageBackend backend; + + Cynara::Storage storage(backend); + + EXPECT_CALL(backend, searchBucket(bucketId, pk)) + .WillOnce(ReturnPointee(&bucket)); + + ASSERT_EQ(PredefinedPolicyType::ALLOW, storage.checkPolicy(pk, bucketId, false)); +} -- 2.7.4 From 88947829a167aa393f228433d903cd10586bd0cc Mon Sep 17 00:00:00 2001 From: Aleksander Zdyb Date: Wed, 20 Aug 2014 08:30:23 +0200 Subject: [PATCH 06/16] Support NONE policy in storage Change-Id: I80d28fee394c5e461bccf102b0d6f7b4ab243174 --- .../exceptions/DefaultBucketSetNoneException.h | 44 +++++++++++++ src/common/types/PolicyResult.h | 8 +++ src/common/types/PolicyType.cpp | 4 ++ src/common/types/PolicyType.h | 2 + src/service/storage/Storage.cpp | 14 ++++- test/storage/storage/check.cpp | 73 ++++++++++++++++++++++ test/storage/storage/fakestoragebackend.h | 2 + 7 files changed, 144 insertions(+), 3 deletions(-) create mode 100644 src/common/exceptions/DefaultBucketSetNoneException.h diff --git a/src/common/exceptions/DefaultBucketSetNoneException.h b/src/common/exceptions/DefaultBucketSetNoneException.h new file mode 100644 index 0000000..d9664b3 --- /dev/null +++ b/src/common/exceptions/DefaultBucketSetNoneException.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file DefaultBucketSetNoneException.h + * @author Aleksander Zdyb + * @version 1.0 + * @brief Implementation of DefaultBucketSetNoneException + */ + +#ifndef SRC_COMMON_EXCEPTIONS_DEFAULTBUCKETSETNONEEXCEPTION_H_ +#define SRC_COMMON_EXCEPTIONS_DEFAULTBUCKETSETNONEEXCEPTION_H_ + +#include + +#include "Exception.h" + +namespace Cynara { + +class DefaultBucketSetNoneException : public Exception { +public: + DefaultBucketSetNoneException() = default; + virtual ~DefaultBucketSetNoneException() noexcept {}; + + virtual const std::string message(void) const { + return "DefaultBucketSetNoneException"; + } +}; + +} /* namespace Cynara */ + +#endif // SRC_COMMON_EXCEPTIONS_DEFAULTBUCKETSETNONEEXCEPTION_H_ diff --git a/src/common/types/PolicyResult.h b/src/common/types/PolicyResult.h index a9369d8..0e0c716 100644 --- a/src/common/types/PolicyResult.h +++ b/src/common/types/PolicyResult.h @@ -60,9 +60,17 @@ public: return std::tie(m_type, m_metadata) == std::tie(other.m_type, other.m_metadata); } + bool operator !=(const PolicyResult &other) const { + return !(*this == other); + } + bool operator ==(const PolicyType &policyType) const { return (m_type == policyType) && m_metadata.empty(); } + + bool operator !=(const PolicyType &policyType) const { + return !(*this == policyType); + } }; } // namespace Cynara diff --git a/src/common/types/PolicyType.cpp b/src/common/types/PolicyType.cpp index bf022f5..9491f6c 100644 --- a/src/common/types/PolicyType.cpp +++ b/src/common/types/PolicyType.cpp @@ -29,4 +29,8 @@ bool operator ==(const PolicyType &policyType, const PolicyResult &policyResult) return policyResult == policyType; } +bool operator !=(const PolicyType &policyType, const PolicyResult &policyResult) { + return !(policyResult == policyType); +} + } // namespace Cynara diff --git a/src/common/types/PolicyType.h b/src/common/types/PolicyType.h index 9131b1b..e7ad60d 100644 --- a/src/common/types/PolicyType.h +++ b/src/common/types/PolicyType.h @@ -33,12 +33,14 @@ typedef std::uint16_t PolicyType; namespace PredefinedPolicyType { const PolicyType DENY = 0; + const PolicyType NONE = 1; const PolicyType BUCKET = 0xFFFE; const PolicyType ALLOW = 0xFFFF; }; class PolicyResult; bool operator ==(const PolicyType &policyType, const PolicyResult &policyResult); +bool operator !=(const PolicyType &policyType, const PolicyResult &policyResult); } // namespace Cynara diff --git a/src/service/storage/Storage.cpp b/src/service/storage/Storage.cpp index 8e81edc..108ebe8 100644 --- a/src/service/storage/Storage.cpp +++ b/src/service/storage/Storage.cpp @@ -25,7 +25,8 @@ #include #include -#include "exceptions/DefaultBucketDeletionException.h" +#include +#include #include #include #include @@ -69,7 +70,9 @@ PolicyResult Storage::minimalPolicy(const PolicyBucket &bucket, const PolicyKey if (recursive == true) { auto bucketResults = m_backend.searchBucket(policyResult.metadata(), key); auto minimumOfBucket = minimalPolicy(bucketResults, key, true); - proposeMinimal(minimumOfBucket); + if (minimumOfBucket != PredefinedPolicyType::NONE) { + proposeMinimal(minimumOfBucket); + } } continue; } @@ -112,7 +115,12 @@ void Storage::insertPolicies(const std::map> } } -void Storage::addOrUpdateBucket(const PolicyBucketId &bucketId, const PolicyResult &defaultBucketPolicy) { +void Storage::addOrUpdateBucket(const PolicyBucketId &bucketId, + const PolicyResult &defaultBucketPolicy) { + + if (bucketId == defaultPolicyBucketId && defaultBucketPolicy == PredefinedPolicyType::NONE) + throw DefaultBucketSetNoneException(); + if (m_backend.hasBucket(bucketId)) { m_backend.updateBucket(bucketId, defaultBucketPolicy); } else { diff --git a/test/storage/storage/check.cpp b/test/storage/storage/check.cpp index f56e7fe..e1f6505 100644 --- a/test/storage/storage/check.cpp +++ b/test/storage/storage/check.cpp @@ -189,3 +189,76 @@ TEST(storage, checkNonrecursive) { ASSERT_EQ(PredefinedPolicyType::ALLOW, storage.checkPolicy(pk, bucketId, false)); } + +/* + * bucket1 contains policy (with key pk) pointing to bucket2 + * bucket2 is empty and it's default policy is NONE + * Because NONE policy in bucket2, check should yield default policy of bucket1 and not of bucket2 + */ +TEST(storage, noneBucket) { + using ::testing::ReturnPointee; + using PredefinedPolicyType::ALLOW; + using PredefinedPolicyType::NONE; + + auto pk = Helpers::generatePolicyKey(); + + PolicyBucket bucket2("bucket-2", NONE); + PolicyBucket bucket1("bucket-1", ALLOW, { Policy::bucketWithKey(pk, bucket2.id()) }); + + FakeStorageBackend backend; + Cynara::Storage storage(backend); + + EXPECT_CALL(backend, searchBucket(bucket1.id(), pk)) + .WillOnce(ReturnPointee(&bucket1)); + EXPECT_CALL(backend, searchBucket(bucket2.id(), pk)) + .WillOnce(ReturnPointee(&bucket2)); + + ASSERT_EQ(ALLOW, storage.checkPolicy(pk, bucket1.id(), true)); +} + +/* + * Scenario similar to noneBucket, but bucket2 contains matching policy. + * In this case this policy should be returned. + */ +TEST(storage, noneBucketNotEmpty) { + using ::testing::ReturnPointee; + using PredefinedPolicyType::ALLOW; + using PredefinedPolicyType::DENY; + using PredefinedPolicyType::NONE; + + auto pk = Helpers::generatePolicyKey(); + + PolicyBucket bucket2("bucket-2", NONE, { Policy::simpleWithKey(pk, DENY) }); + PolicyBucket bucket1("bucket-1", ALLOW, { Policy::bucketWithKey(pk, bucket2.id()) }); + + FakeStorageBackend backend; + Cynara::Storage storage(backend); + + EXPECT_CALL(backend, searchBucket(bucket1.id(), pk)) + .WillOnce(ReturnPointee(&bucket1)); + EXPECT_CALL(backend, searchBucket(bucket2.id(), pk)) + .WillOnce(ReturnPointee(&bucket2)); + + ASSERT_EQ(DENY, storage.checkPolicy(pk, bucket1.id(), true)); +} + +/* + * Single empty bucket with default policy of NONE + * -- searching for any key should yield NONE + */ +TEST(storage, singleNoneBucket) { + using ::testing::ReturnPointee; + using PredefinedPolicyType::NONE; + + auto pk = Helpers::generatePolicyKey(); + + PolicyBucket bucket("bucket", NONE, {}); + + FakeStorageBackend backend; + Cynara::Storage storage(backend); + + EXPECT_CALL(backend, searchBucket(bucket.id(), pk)) + .WillOnce(ReturnPointee(&bucket)); + + ASSERT_EQ(NONE, storage.checkPolicy(pk, bucket.id(), true)); +} diff --git a/test/storage/storage/fakestoragebackend.h b/test/storage/storage/fakestoragebackend.h index b1e8b69..fa8898b 100644 --- a/test/storage/storage/fakestoragebackend.h +++ b/test/storage/storage/fakestoragebackend.h @@ -23,6 +23,8 @@ #ifndef FAKESTORAGEBACKEND_H_ #define FAKESTORAGEBACKEND_H_ +#include + using namespace Cynara; class FakeStorageBackend : public StorageBackend { -- 2.7.4 From 5504f5f71535309694ca2926b6fb5afc496990c4 Mon Sep 17 00:00:00 2001 From: Aleksander Zdyb Date: Wed, 20 Aug 2014 11:24:44 +0200 Subject: [PATCH 07/16] Support NONE policy in admin API Change-Id: I8a54f020f2d69f9c0ad71773b8d32b09f6519b9e --- src/admin/api/admin-api.cpp | 30 ++++++++++++++++++++---------- src/include/cynara-admin.h | 7 +++++-- src/service/logic/Logic.cpp | 13 ++++++++++--- 3 files changed, 35 insertions(+), 15 deletions(-) diff --git a/src/admin/api/admin-api.cpp b/src/admin/api/admin-api.cpp index 417baa3..ce7e241 100644 --- a/src/admin/api/admin-api.cpp +++ b/src/admin/api/admin-api.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -85,7 +86,7 @@ int cynara_admin_set_policies(struct cynara_admin *p_cynara_admin, std::map> insertOrUpdate; std::map> remove; - auto key = ([](const cynara_admin_policy *i)->Cynara::PolicyKey { + auto key = ([](const cynara_admin_policy *policy)->Cynara::PolicyKey { std::string wildcard(CYNARA_ADMIN_WILDCARD); auto feature = ([&wildcard] (const char *str)->Cynara::PolicyKeyFeature { @@ -95,34 +96,37 @@ int cynara_admin_set_policies(struct cynara_admin *p_cynara_admin, return Cynara::PolicyKeyFeature::createWildcard(); }); - return Cynara::PolicyKey(feature(i->client), feature(i->user), feature(i->privilege)); + return Cynara::PolicyKey(feature(policy->client), feature(policy->user), + feature(policy->privilege)); }); try { for (auto i = policies; *i; i++) { - if(!(*i)->bucket || !(*i)->client || !(*i)->user || !(*i)->privilege) + const cynara_admin_policy *policy = *i; + if(!policy->bucket || !policy->client || !policy->user || !policy->privilege) return CYNARA_ADMIN_API_INVALID_PARAM; - switch ((*i)->result) { + switch (policy->result) { case CYNARA_ADMIN_DELETE: - remove[(*i)->bucket].push_back(key(*i)); + remove[policy->bucket].push_back(key(policy)); break; case CYNARA_ADMIN_DENY: - insertOrUpdate[(*i)->bucket].push_back(Cynara::Policy(key(*i), + insertOrUpdate[policy->bucket].push_back(Cynara::Policy(key(policy), Cynara::PredefinedPolicyType::DENY)); break; case CYNARA_ADMIN_ALLOW: - insertOrUpdate[(*i)->bucket].push_back(Cynara::Policy(key(*i), + insertOrUpdate[policy->bucket].push_back(Cynara::Policy(key(policy), Cynara::PredefinedPolicyType::ALLOW)); break; case CYNARA_ADMIN_BUCKET: - if (!(*i)->result_extra) + if (!policy->result_extra) return CYNARA_ADMIN_API_INVALID_PARAM; - insertOrUpdate[(*i)->bucket].push_back(Cynara::Policy(key(*i), + insertOrUpdate[policy->bucket].push_back(Cynara::Policy(key(policy), Cynara::PolicyResult( Cynara::PredefinedPolicyType::BUCKET, - (*i)->result_extra))); + policy->result_extra))); break; + case CYNARA_ADMIN_NONE: default: return CYNARA_ADMIN_API_INVALID_PARAM; } @@ -157,6 +161,12 @@ int cynara_admin_set_bucket(struct cynara_admin *p_cynara_admin, const char *buc case CYNARA_ADMIN_ALLOW: return p_cynara_admin->impl->insertOrUpdateBucket(bucket, Cynara::PolicyResult(Cynara::PredefinedPolicyType::ALLOW, extraStr)); + case CYNARA_ADMIN_NONE: + if (bucket != Cynara::defaultPolicyBucketId) { + return p_cynara_admin->impl->insertOrUpdateBucket(bucket, + Cynara::PolicyResult(Cynara::PredefinedPolicyType::NONE)); + } + return CYNARA_ADMIN_API_OPERATION_NOT_ALLOWED; case CYNARA_ADMIN_BUCKET: default: return CYNARA_ADMIN_API_INVALID_PARAM; diff --git a/src/include/cynara-admin.h b/src/include/cynara-admin.h index b8aec4e..1e0a162 100644 --- a/src/include/cynara-admin.h +++ b/src/include/cynara-admin.h @@ -64,11 +64,14 @@ struct cynara_admin; /*! \brief set policy result or bucket's default policy to DENY */ #define CYNARA_ADMIN_DENY 0 +/*! \brief set bucket's default policy to NONE */ +#define CYNARA_ADMIN_NONE 1 + /*! \brief set policy result or bucket's default policy to ALLOW */ -#define CYNARA_ADMIN_ALLOW 1 +#define CYNARA_ADMIN_ALLOW 2 /*! \brief set policy to point into another bucket */ -#define CYNARA_ADMIN_BUCKET 2 +#define CYNARA_ADMIN_BUCKET 3 /** @}*/ /** diff --git a/src/service/logic/Logic.cpp b/src/service/logic/Logic.cpp index 377bcce..2701e86 100644 --- a/src/service/logic/Logic.cpp +++ b/src/service/logic/Logic.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include
@@ -90,10 +91,16 @@ bool Logic::check(RequestContextPtr context UNUSED, const PolicyKey &key, } void Logic::execute(RequestContextPtr context, InsertOrUpdateBucketRequestPtr request) { - m_storage->addOrUpdateBucket(request->bucketId(), request->result()); - onPoliciesChanged(); + auto code = CodeResponse::Code::OK; - context->returnResponse(context, std::make_shared(CodeResponse::Code::OK, + try { + m_storage->addOrUpdateBucket(request->bucketId(), request->result()); + onPoliciesChanged(); + } catch (const DefaultBucketSetNoneException &ex) { + code = CodeResponse::Code::NOT_ALLOWED; + } + + context->returnResponse(context, std::make_shared(code, request->sequenceNumber())); } -- 2.7.4 From 7ca84d1e7ee1845a936c49921c026de4e907336a Mon Sep 17 00:00:00 2001 From: Jacek Bukarewicz Date: Thu, 11 Sep 2014 15:37:41 +0200 Subject: [PATCH 08/16] Add missing 'struct' keyword in cynara-admin.h Change-Id: I48405d368fb8a95a86d6c94df5c50a490869f1e4 --- src/admin/api/admin-api.cpp | 2 +- src/include/cynara-admin.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/admin/api/admin-api.cpp b/src/admin/api/admin-api.cpp index ce7e241..3f6885d 100644 --- a/src/admin/api/admin-api.cpp +++ b/src/admin/api/admin-api.cpp @@ -77,7 +77,7 @@ int cynara_admin_finish(struct cynara_admin *p_cynara_admin) { CYNARA_API int cynara_admin_set_policies(struct cynara_admin *p_cynara_admin, - const cynara_admin_policy *const *policies) { + const struct cynara_admin_policy *const *policies) { if (!p_cynara_admin || !p_cynara_admin->impl) return CYNARA_ADMIN_API_INVALID_PARAM; if (!policies) diff --git a/src/include/cynara-admin.h b/src/include/cynara-admin.h index 1e0a162..8260676 100644 --- a/src/include/cynara-admin.h +++ b/src/include/cynara-admin.h @@ -206,7 +206,7 @@ int cynara_admin_finish(struct cynara_admin *p_cynara_admin); * \brief Insert, update or delete policies in cynara database. */ int cynara_admin_set_policies(struct cynara_admin *p_cynara_admin, - const cynara_admin_policy *const *policies); + const struct cynara_admin_policy *const *policies); /** * \par Description: -- 2.7.4 From 1c3bee02b5b66ebd389eec9b4fe35c760c170ec9 Mon Sep 17 00:00:00 2001 From: Aleksander Zdyb Date: Tue, 26 Aug 2014 10:41:33 +0200 Subject: [PATCH 09/16] Fix startup with half-populated db In some cases, Cynara could start with half-populated database. As this is potential security issue, we now make sure, that in case of any error, Cynara will start with empty database and return DENY for every request. There are added tests revealing these potential issues. Some test cases depend on specific state of Cynara's policy database directory. These are now provided in cynara-tests package and placed in /usr/share/cynara/tests/ during installation. Test execution does not affect real database -- it uses above tests path only, accessible by non-root users as well. Signed-off-by: Aleksander Zdyb Signed-off-by: Pawel Wieczorek Change-Id: Ia943f77a2a0c85f394c40dd10333a73df4d0c96a --- packaging/cynara.spec | 8 ++- .../exceptions/BucketRecordCorruptedException.h | 6 +- src/service/storage/InMemoryStorageBackend.cpp | 11 ++-- test/db/db2/buckets | 1 + test/db/db3/_ | 0 test/db/db3/buckets | 1 + test/db/db4/_ | 0 test/db/db4/_additional | 0 test/db/db4/buckets | 2 + test/db/db5/_ | 0 test/db/db5/_additional | 1 + test/db/db5/buckets | 2 + .../inmemeorystoragebackendfixture.h | 11 ++++ .../inmemorystoragebackend.cpp | 68 +++++++++++++++++++++- 14 files changed, 102 insertions(+), 9 deletions(-) create mode 100644 test/db/db2/buckets create mode 100644 test/db/db3/_ create mode 100644 test/db/db3/buckets create mode 100644 test/db/db4/_ create mode 100644 test/db/db4/_additional create mode 100644 test/db/db4/buckets create mode 100644 test/db/db5/_ create mode 100644 test/db/db5/_additional create mode 100644 test/db/db5/buckets diff --git a/packaging/cynara.spec b/packaging/cynara.spec index 677142b..f4e8d1a 100644 --- a/packaging/cynara.spec +++ b/packaging/cynara.spec @@ -29,6 +29,7 @@ BuildRequires: pkgconfig(libsystemd-journal) %global group_name %{name} %global state_path %{_localstatedir}/%{name}/ +%global tests_dir %{_datarootdir}/%{name}/tests %global build_type %{?build_type:%build_type}%{!?build_type:RELEASE} @@ -195,6 +196,7 @@ cp -a %{SOURCE1007} . cp -a %{SOURCE1008} . cp -a %{SOURCE1009} . cp -a %{SOURCE1010} . +cp -a test/db/db* . %build %if 0%{?sec_build_binary_debug_enable} @@ -205,7 +207,8 @@ export CXXFLAGS="$CXXFLAGS -DTIZEN_DEBUG_ENABLE" export CXXFLAGS="$CXXFLAGS -Wp,-U_FORTIFY_SOURCE" %endif -export CXXFLAGS="$CXXFLAGS -DCYNARA_STATE_PATH=\\\"%{state_path}\\\"" +export CXXFLAGS="$CXXFLAGS -DCYNARA_STATE_PATH=\\\"%{state_path}\\\" \ + -DCYNARA_TESTS_DIR=\\\"%{tests_dir}\\\"" export LDFLAGS+="-Wl,--rpath=%{_libdir}" %cmake . \ @@ -221,6 +224,8 @@ rm -rf %{buildroot} mkdir -p %{buildroot}/usr/lib/systemd/system/sockets.target.wants mkdir -p %{buildroot}/%{state_path} +mkdir -p %{buildroot}/%{tests_dir} +cp -a db* %{buildroot}/%{tests_dir} ln -s ../cynara.socket %{buildroot}/usr/lib/systemd/system/sockets.target.wants/cynara.socket ln -s ../cynara-admin.socket %{buildroot}/usr/lib/systemd/system/sockets.target.wants/cynara-admin.socket @@ -380,6 +385,7 @@ fi %files -n cynara-tests %manifest cynara-tests.manifest %attr(755,root,root) /usr/bin/cynara-tests +%attr(755,root,root) %{tests_dir}/db*/* %files -n libcynara-creds-commons %manifest libcynara-creds-commons.manifest diff --git a/src/common/exceptions/BucketRecordCorruptedException.h b/src/common/exceptions/BucketRecordCorruptedException.h index 8152a77..335fbc9 100644 --- a/src/common/exceptions/BucketRecordCorruptedException.h +++ b/src/common/exceptions/BucketRecordCorruptedException.h @@ -22,13 +22,13 @@ #ifndef SRC_COMMON_EXCEPTIONS_BUCKETRECORDCORRUPTEDEXCEPTION_H_ #define SRC_COMMON_EXCEPTIONS_BUCKETRECORDCORRUPTEDEXCEPTION_H_ -#include "Exception.h" - #include +#include + namespace Cynara { -class BucketRecordCorruptedException : public Exception { +class BucketRecordCorruptedException : public DatabaseException { public: BucketRecordCorruptedException(void) = delete; virtual ~BucketRecordCorruptedException() noexcept {}; diff --git a/src/service/storage/InMemoryStorageBackend.cpp b/src/service/storage/InMemoryStorageBackend.cpp index 9fee197..20c16cf 100644 --- a/src/service/storage/InMemoryStorageBackend.cpp +++ b/src/service/storage/InMemoryStorageBackend.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -63,13 +64,15 @@ void InMemoryStorageBackend::load(void) { storageDeserializer.initBuckets(buckets()); storageDeserializer.loadBuckets(buckets()); - } catch (const FileNotFoundException &) { - LOGE("Reading cynara database failed."); + } catch (const DatabaseException &) { + LOGC("Reading cynara database failed."); + buckets().clear(); + // TODO: Implement emergency mode toggle } if (!hasBucket(defaultPolicyBucketId)) { - LOGN("Creating defaultBucket."); - this->buckets().insert({ defaultPolicyBucketId, PolicyBucket() }); + LOGN("Creating defaultBucket."); + this->buckets().insert({ defaultPolicyBucketId, PolicyBucket() }); } } diff --git a/test/db/db2/buckets b/test/db/db2/buckets new file mode 100644 index 0000000..b6d719f --- /dev/null +++ b/test/db/db2/buckets @@ -0,0 +1 @@ +;0x0 diff --git a/test/db/db3/_ b/test/db/db3/_ new file mode 100644 index 0000000..e69de29 diff --git a/test/db/db3/buckets b/test/db/db3/buckets new file mode 100644 index 0000000..b6d719f --- /dev/null +++ b/test/db/db3/buckets @@ -0,0 +1 @@ +;0x0 diff --git a/test/db/db4/_ b/test/db/db4/_ new file mode 100644 index 0000000..e69de29 diff --git a/test/db/db4/_additional b/test/db/db4/_additional new file mode 100644 index 0000000..e69de29 diff --git a/test/db/db4/buckets b/test/db/db4/buckets new file mode 100644 index 0000000..19d7a93 --- /dev/null +++ b/test/db/db4/buckets @@ -0,0 +1,2 @@ +;0x0 +additional;0xFFFF diff --git a/test/db/db5/_ b/test/db/db5/_ new file mode 100644 index 0000000..e69de29 diff --git a/test/db/db5/_additional b/test/db/db5/_additional new file mode 100644 index 0000000..d30fa55 --- /dev/null +++ b/test/db/db5/_additional @@ -0,0 +1 @@ +INVALID \ No newline at end of file diff --git a/test/db/db5/buckets b/test/db/db5/buckets new file mode 100644 index 0000000..19d7a93 --- /dev/null +++ b/test/db/db5/buckets @@ -0,0 +1,2 @@ +;0x0 +additional;0xFFFF diff --git a/test/storage/inmemorystoragebackend/inmemeorystoragebackendfixture.h b/test/storage/inmemorystoragebackend/inmemeorystoragebackendfixture.h index 2c6e593..298732c 100644 --- a/test/storage/inmemorystoragebackend/inmemeorystoragebackendfixture.h +++ b/test/storage/inmemorystoragebackend/inmemeorystoragebackendfixture.h @@ -24,6 +24,7 @@ #define INMEMEORYSTORAGEBACKENDFIXTURE_H_ #include +#include #include #include @@ -52,6 +53,16 @@ protected: } } + static void ASSERT_DB_VIRGIN(Cynara::Buckets &buckets) { + using ::testing::IsEmpty; + ASSERT_EQ(1, buckets.size()); + auto defaultBucketIter = buckets.find(Cynara::defaultPolicyBucketId); + ASSERT_NE(buckets.end(), defaultBucketIter); + auto &defaultBucket = defaultBucketIter->second; + ASSERT_THAT(defaultBucket, IsEmpty()); + ASSERT_EQ(Cynara::PredefinedPolicyType::DENY, defaultBucket.defaultPolicy()); + } + virtual ~InMemeoryStorageBackendFixture() {} // TODO: consider defaulting accessor with ON_CALL diff --git a/test/storage/inmemorystoragebackend/inmemorystoragebackend.cpp b/test/storage/inmemorystoragebackend/inmemorystoragebackend.cpp index 6e84475..e81af8f 100644 --- a/test/storage/inmemorystoragebackend/inmemorystoragebackend.cpp +++ b/test/storage/inmemorystoragebackend/inmemorystoragebackend.cpp @@ -23,8 +23,10 @@ #include #include -#include "exceptions/DefaultBucketDeletionException.h" #include "exceptions/BucketNotExistsException.h" +#include "exceptions/BucketDeserializationException.h" +#include "exceptions/DefaultBucketDeletionException.h" +#include "exceptions/FileNotFoundException.h" #include "storage/InMemoryStorageBackend.h" #include "storage/StorageBackend.h" #include "types/PolicyCollection.h" @@ -186,3 +188,67 @@ TEST_F(InMemeoryStorageBackendFixture, deletePolicyFromNonexistentBucket) { EXPECT_THROW(backend.deletePolicy("non-existent", Helpers::generatePolicyKey()), BucketNotExistsException); } + +// Database dir is empty +TEST_F(InMemeoryStorageBackendFixture, load_no_db) { + using ::testing::ReturnRef; + auto testDbPath = std::string(CYNARA_TESTS_DIR) + "/db1/"; + FakeInMemoryStorageBackend backend(testDbPath); + EXPECT_CALL(backend, buckets()).WillRepeatedly(ReturnRef(m_buckets)); + backend.load(); + ASSERT_DB_VIRGIN(m_buckets); +} + +// Database dir contains index with default bucket, but no file for this bucket +TEST_F(InMemeoryStorageBackendFixture, load_no_default) { + using ::testing::ReturnRef; + auto testDbPath = std::string(CYNARA_TESTS_DIR) + "/db2/"; + FakeInMemoryStorageBackend backend(testDbPath); + EXPECT_CALL(backend, buckets()).WillRepeatedly(ReturnRef(m_buckets)); + backend.load(); + ASSERT_DB_VIRGIN(m_buckets); +} + +// Database contains index with default bucket and an empty bucket file +TEST_F(InMemeoryStorageBackendFixture, load_default_only) { + using ::testing::ReturnRef; + auto testDbPath = std::string(CYNARA_TESTS_DIR) + "/db3/"; + FakeInMemoryStorageBackend backend(testDbPath); + EXPECT_CALL(backend, buckets()).WillRepeatedly(ReturnRef(m_buckets)); + backend.load(); + ASSERT_DB_VIRGIN(m_buckets); +} + +// Database contains index with default bucket and an additional bucket +// There are files for both buckets present +TEST_F(InMemeoryStorageBackendFixture, load_2_buckets) { + using ::testing::ReturnRef; + using ::testing::IsEmpty; + + auto testDbPath = std::string(CYNARA_TESTS_DIR) + "/db4/"; + + FakeInMemoryStorageBackend backend(testDbPath); + EXPECT_CALL(backend, buckets()).WillRepeatedly(ReturnRef(m_buckets)); + backend.load(); + + std::vector bucketIds = { "", "additional" }; + + for(const auto &bucketId : bucketIds) { + SCOPED_TRACE(bucketId); + const auto bucketIter = m_buckets.find(bucketId); + ASSERT_NE(m_buckets.end(), bucketIter); + + const auto &bucketPolicies = bucketIter->second; + ASSERT_THAT(bucketPolicies, IsEmpty()); + } +} + +// Database contains index with 2 buckets; 1st bucket is valid, but second is corrupted +TEST_F(InMemeoryStorageBackendFixture, second_bucket_corrupted) { + using ::testing::ReturnRef; + auto testDbPath = std::string(CYNARA_TESTS_DIR) + "/db5/"; + FakeInMemoryStorageBackend backend(testDbPath); + EXPECT_CALL(backend, buckets()).WillRepeatedly(ReturnRef(m_buckets)); + backend.load(); + ASSERT_DB_VIRGIN(m_buckets); +} -- 2.7.4 From 731b2fb90ed8bc47244576f315ac114ad4f63efb Mon Sep 17 00:00:00 2001 From: Adam Malinowski Date: Thu, 11 Sep 2014 11:10:01 +0200 Subject: [PATCH 10/16] Add source info to backtrace This patch recovers putting source code information in backtrace. Previous solution was based on binutils but its license is not acceptable. This patch uses elfutils library licensed under LGPL3. Change-Id: I1df0a54ac0702f08d876728b535fd0e172efca17 --- packaging/cynara.spec | 1 + src/common/CMakeLists.txt | 1 + src/common/log/Backtrace.cpp | 78 ++++++++++++++++++++++++++++++++++++-------- src/common/log/Backtrace.h | 13 ++++---- 4 files changed, 74 insertions(+), 19 deletions(-) diff --git a/packaging/cynara.spec b/packaging/cynara.spec index f4e8d1a..3421fd9 100644 --- a/packaging/cynara.spec +++ b/packaging/cynara.spec @@ -35,6 +35,7 @@ BuildRequires: pkgconfig(libsystemd-journal) %if %{?build_type} == "DEBUG" +BuildRequires: libdw-devel BuildRequires: pkgconfig(libunwind) %endif diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 8f99d0e..3de3909 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -67,6 +67,7 @@ SET_TARGET_PROPERTIES( IF (CMAKE_BUILD_TYPE MATCHES "DEBUG") SET(CYNARA_DBG_LIBRARIES ${CYNARA_DEP_LIBRARIES} + dw ) ENDIF (CMAKE_BUILD_TYPE MATCHES "DEBUG") diff --git a/src/common/log/Backtrace.cpp b/src/common/log/Backtrace.cpp index ca413b7..2fe2566 100644 --- a/src/common/log/Backtrace.cpp +++ b/src/common/log/Backtrace.cpp @@ -23,13 +23,14 @@ */ #include +#include +#include +#include #include #include #include -#include #include -#include #include #include "Backtrace.h" @@ -41,19 +42,68 @@ Backtrace &Backtrace::getInstance(void) { return m_instance; } -Backtrace::Backtrace() : - m_fileName(NULL), - m_functionName(NULL), m_lineNumber(0) { +const Dwfl_Callbacks Backtrace::m_callbacks = { + dwfl_linux_proc_find_elf, + dwfl_standard_find_debuginfo, + nullptr, + nullptr, +}; + +Backtrace::Backtrace() { + init(); } Backtrace::~Backtrace() { + dwfl_end(m_dwfl); } -void Backtrace::getSourceInfo(unw_word_t proc_address UNUSED) { - // TODO: extract filename and line number for symbol at given address - m_fileName = "??"; - m_functionName = "??"; - m_lineNumber = 0; +void Backtrace::init(void) { + m_dwfl = dwfl_begin(&m_callbacks); + if (m_dwfl == nullptr) { + LOGE("dwfl_begin failed! Source info won't be available in backtrace!"); + return; + } + + if (dwfl_linux_proc_report(m_dwfl, getpid())) { + LOGE("dwfl_linux_proc_report failed! Source info won't be available in backtrace!"); + dwfl_end(m_dwfl); + m_dwfl = nullptr; + } +} + +void Backtrace::getSourceInfo(unw_word_t address, std::string &fileName, int &lineNumber) { + fileName = "??"; + lineNumber = 0; + + if (m_dwfl == nullptr) + return; + + Dwarf_Addr addr = static_cast(address); + + Dwfl_Module *module = dwfl_addrmodule(m_dwfl, addr); + if (module == nullptr) + return; + + Dwfl_Line *line = dwfl_module_getsrc(module, addr); + if (line == nullptr) + return; + + const char *src = dwfl_lineinfo(line, &addr, &lineNumber, nullptr, nullptr, nullptr); + if (src == nullptr) + return; + + const char *compilationDirectory = ""; + const char *compilationDirectorySeparator = ""; + + if (src[0] != '/') { + compilationDirectory = dwfl_line_comp_dir(line); + if (compilationDirectory != NULL) + compilationDirectorySeparator = "/"; + } + + std::ostringstream fileNameStream; + fileNameStream << compilationDirectory << compilationDirectorySeparator << src; + fileName = fileNameStream.str(); } const std::string Backtrace::buildBacktrace(void) { @@ -64,6 +114,8 @@ const std::string Backtrace::buildBacktrace(void) { char proc_name[BUFSIZ]; unw_word_t offp; int status; + std::string fileName; + int lineNumber; unw_getcontext(&uc); // get rid of previous function: Backtrace::getBacktrace @@ -74,12 +126,12 @@ const std::string Backtrace::buildBacktrace(void) { unw_get_reg(&cursor, UNW_REG_SP, &sp); unw_get_proc_name(&cursor, proc_name, sizeof(proc_name), &offp); char *realname = abi::__cxa_demangle(proc_name, 0, 0, &status); - getSourceInfo(ip); + getSourceInfo(ip, fileName, lineNumber); backtrace << std::hex << "ip = 0x" << ip << ", sp = 0x" << sp << ", " << (realname ? realname : proc_name) - << ", " << m_fileName - << ":" << std::dec << m_lineNumber << std::endl; + << ", " << fileName + << ":" << std::dec << lineNumber << std::endl; free(realname); } diff --git a/src/common/log/Backtrace.h b/src/common/log/Backtrace.h index c96f29d..55a0f48 100644 --- a/src/common/log/Backtrace.h +++ b/src/common/log/Backtrace.h @@ -26,6 +26,7 @@ #define SRC_COMMON_LOG_BACKTRACE_H_ #if defined(BUILD_TYPE_DEBUG) && !defined(CYNARA_NO_LOGS) +#include #define UNW_LOCAL_ONLY #include #endif @@ -52,15 +53,15 @@ private: void operator=(Backtrace const &) = delete; + void init(void); const std::string buildBacktrace(void); + #if defined(BUILD_TYPE_DEBUG) && !defined(CYNARA_NO_LOGS) - void getSourceInfo(unw_word_t proc_address); -#endif + void getSourceInfo(unw_word_t address, std::string &fileName, int &lineNumber); -private: - const char *m_fileName; - const char *m_functionName; - unsigned int m_lineNumber; + Dwfl *m_dwfl; + static const Dwfl_Callbacks m_callbacks; +#endif }; } /* namespace Cynara */ -- 2.7.4 From 40162761fa3d5e7fa42a9d6e1634dd7735df3f11 Mon Sep 17 00:00:00 2001 From: Adam Malinowski Date: Fri, 12 Sep 2014 21:29:30 +0200 Subject: [PATCH 11/16] Remove instruction & stack pointers from backtrace These pointers don't provide useful information but consumes a lot of space in backtrace lines. Change-Id: I063485334ad619d8bed6d617e5fb96673f3ce938 --- src/common/log/Backtrace.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/common/log/Backtrace.cpp b/src/common/log/Backtrace.cpp index 2fe2566..233e029 100644 --- a/src/common/log/Backtrace.cpp +++ b/src/common/log/Backtrace.cpp @@ -110,7 +110,7 @@ const std::string Backtrace::buildBacktrace(void) { std::ostringstream backtrace; unw_cursor_t cursor; unw_context_t uc; - unw_word_t ip, sp; + unw_word_t ip; char proc_name[BUFSIZ]; unw_word_t offp; int status; @@ -123,15 +123,12 @@ const std::string Backtrace::buildBacktrace(void) { unw_step(&cursor); while (unw_step(&cursor) > 0) { unw_get_reg(&cursor, UNW_REG_IP, &ip); - unw_get_reg(&cursor, UNW_REG_SP, &sp); unw_get_proc_name(&cursor, proc_name, sizeof(proc_name), &offp); char *realname = abi::__cxa_demangle(proc_name, 0, 0, &status); getSourceInfo(ip, fileName, lineNumber); - backtrace << std::hex << "ip = 0x" << ip << ", sp = 0x" << sp - << ", " << (realname ? realname : proc_name) - << ", " << fileName - << ":" << std::dec << lineNumber << std::endl; + backtrace << (realname ? realname : proc_name) << ", " << fileName << ":" + << std::dec << lineNumber << std::endl; free(realname); } -- 2.7.4 From 75a29f7e119fabbde477ad7453f13861b7c925b7 Mon Sep 17 00:00:00 2001 From: Aleksander Zdyb Date: Wed, 17 Sep 2014 08:20:44 +0200 Subject: [PATCH 12/16] Move some definitions outside of cynara-admin.h The consts and structs will be used by both cynara-admin and upcomming cynara-offline-admin APIs. Change-Id: I05e320e54ff9c6a16521318560de059c6928cbea --- packaging/cynara.spec | 1 + src/include/CMakeLists.txt | 1 + src/include/cynara-admin-types.h | 93 ++++++++++++++++++++++++++++++++++++++++ src/include/cynara-admin.h | 59 +------------------------ 4 files changed, 96 insertions(+), 58 deletions(-) create mode 100644 src/include/cynara-admin-types.h diff --git a/packaging/cynara.spec b/packaging/cynara.spec index 3421fd9..015737a 100644 --- a/packaging/cynara.spec +++ b/packaging/cynara.spec @@ -372,6 +372,7 @@ fi %files -n libcynara-admin-devel %{_includedir}/cynara/cynara-admin.h %{_includedir}/cynara/cynara-admin-error.h +%{_includedir}/cynara/cynara-admin-types.h %{_libdir}/libcynara-admin.so %{_libdir}/pkgconfig/cynara-admin.pc diff --git a/src/include/CMakeLists.txt b/src/include/CMakeLists.txt index 261c34d..e4c74a4 100644 --- a/src/include/CMakeLists.txt +++ b/src/include/CMakeLists.txt @@ -19,6 +19,7 @@ INSTALL(FILES ${CYNARA_PATH}/include/cynara-admin.h ${CYNARA_PATH}/include/cynara-admin-error.h + ${CYNARA_PATH}/include/cynara-admin-types.h ${CYNARA_PATH}/include/cynara-client.h ${CYNARA_PATH}/include/cynara-client-error.h ${CYNARA_PATH}/include/cynara-creds-commons.h diff --git a/src/include/cynara-admin-types.h b/src/include/cynara-admin-types.h new file mode 100644 index 0000000..61b3545 --- /dev/null +++ b/src/include/cynara-admin-types.h @@ -0,0 +1,93 @@ +/** + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +/** + * \file cynara-admin-types.h + * \author Lukasz Wojciechowski + * \author Aleksander Zdyb + * \version 1.0 + * \brief This file contains structs and consts for cynara admin. + */ + +#ifndef CYNARA_ADMIN_TYPES_H +#define CYNARA_ADMIN_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name cynara_admin_policy + * defines single policy + * bucket - is the name of bucket, in which policy is placed + * client, user, privilege - defines policy key + * result - defines result of policy + * result_extra - not always used, may contain some additional result data + * like e.g. name of bucket in case result == CYNARA_ADMIN_BUCKET + */ +struct cynara_admin_policy { + char *bucket; + + char *client; + char *user; + char *privilege; + + int result; + char *result_extra; +}; + +/** + * \name Wildcard + * definition of WILDCARD, that can replace client, user or privilege name. + * WILDCARD matches any string during check procedure from libcynara-client. + */ +#define CYNARA_ADMIN_WILDCARD "*" + +/** + * \name Name of Default Bucket + * definition of name for default bucket - the one that check starts in. + * default bucket cannot be removed, although its default policy + * (which originally is set to DENY) can be changed. + */ +#define CYNARA_ADMIN_DEFAULT_BUCKET "" + +/** + * \name Operation Codes + * operation codes that define action type to be taken in below defined functions + * they are used mostly to define policy result + * @{ + */ + +/*! \brief a policy or bucket should be removed */ +#define CYNARA_ADMIN_DELETE -1 + +/*! \brief set policy result or bucket's default policy to DENY */ +#define CYNARA_ADMIN_DENY 0 + +/*! \brief set bucket's default policy to NONE */ +#define CYNARA_ADMIN_NONE 1 + +/*! \brief set policy result or bucket's default policy to ALLOW */ +#define CYNARA_ADMIN_ALLOW 2 + +/*! \brief set policy to point into another bucket */ +#define CYNARA_ADMIN_BUCKET 3 +/** @}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* CYNARA_ADMIN_TYPES_H */ diff --git a/src/include/cynara-admin.h b/src/include/cynara-admin.h index 8260676..d93a232 100644 --- a/src/include/cynara-admin.h +++ b/src/include/cynara-admin.h @@ -24,6 +24,7 @@ #define CYNARA_ADMIN_H #include +#include #ifdef __cplusplus extern "C" { @@ -37,64 +38,6 @@ extern "C" { struct cynara_admin; /** - * \name Wildcard - * definition of WILDCARD, that can replace client, user or privilege name. - * WILDCARD matches any string during check procedure from libcynara-client. - */ -#define CYNARA_ADMIN_WILDCARD "*" - -/** - * \name Name of Default Bucket - * definition of name for default bucket - the one that check starts in. - * default bucket cannot be removed, although its default policy - * (which originaly is set to DENY) can be changed. - */ -#define CYNARA_ADMIN_DEFAULT_BUCKET "" - -/** - * \name Operation Codes - * operation codes that define action type to be taken in below defined functions - * they are used mosty to define policy result - * @{ - */ - -/*! \brief a policy or bucket should be removed */ -#define CYNARA_ADMIN_DELETE -1 - -/*! \brief set policy result or bucket's default policy to DENY */ -#define CYNARA_ADMIN_DENY 0 - -/*! \brief set bucket's default policy to NONE */ -#define CYNARA_ADMIN_NONE 1 - -/*! \brief set policy result or bucket's default policy to ALLOW */ -#define CYNARA_ADMIN_ALLOW 2 - -/*! \brief set policy to point into another bucket */ -#define CYNARA_ADMIN_BUCKET 3 -/** @}*/ - -/** - * \name cynara_admin_policy - * defines single policy - * bucket - is the name of bucket, in which policy is placed - * client, user, privilege - defines policy key - * result - defines result of policy - * result_extra - not always used, may contain some additional result data - * like e.g. name of bucket in case result == CYNARA_ADMIN_BUCKET - */ -struct cynara_admin_policy { - char *bucket; - - char *client; - char *user; - char *privilege; - - int result; - char *result_extra; -}; - -/** * \par Description: * Initialize cynara-admin library. * Creates structure used in following API calls. -- 2.7.4 From 93e89fb3c0cdc4ea847e4de6e0ebd91feef8dfb8 Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Mon, 15 Sep 2014 16:39:37 +0200 Subject: [PATCH 13/16] Add admin_check() prototype Change-Id: I650cf0748479ec1646d20cd2b767e26905770116 --- src/admin/api/admin-api.cpp | 18 +++++++++++++++++ src/include/cynara-admin.h | 49 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/src/admin/api/admin-api.cpp b/src/admin/api/admin-api.cpp index 3f6885d..00cae0b 100644 --- a/src/admin/api/admin-api.cpp +++ b/src/admin/api/admin-api.cpp @@ -172,3 +172,21 @@ int cynara_admin_set_bucket(struct cynara_admin *p_cynara_admin, const char *buc return CYNARA_ADMIN_API_INVALID_PARAM; } } + +CYNARA_API +int cynara_admin_check(struct cynara_admin *p_cynara_admin, + const char *start_bucket, const int recursive UNUSED, + const char *client, const char *user, const char *privilege, + int *result, char **result_extra) { + if (!p_cynara_admin || !p_cynara_admin->impl) + return CYNARA_ADMIN_API_INVALID_PARAM; + if (!start_bucket) + return CYNARA_ADMIN_API_INVALID_PARAM; + if (!client || !user || !privilege) + return CYNARA_ADMIN_API_INVALID_PARAM; + if (!result || !result_extra) + return CYNARA_ADMIN_API_INVALID_PARAM; + + //just mock-up + return CYNARA_ADMIN_API_SUCCESS; +} \ No newline at end of file diff --git a/src/include/cynara-admin.h b/src/include/cynara-admin.h index d93a232..0f1e04b 100644 --- a/src/include/cynara-admin.h +++ b/src/include/cynara-admin.h @@ -198,6 +198,55 @@ int cynara_admin_set_policies(struct cynara_admin *p_cynara_admin, int cynara_admin_set_bucket(struct cynara_admin *p_cynara_admin, const char *bucket, int operation, const char *extra); +/** + * \par Description: + * Raw check client and user access for given privilege without using plugins extensions. + * + * \par Purpose: + * This API should be used to check type of matching policy for check request + * + * \par Typical use case: + * Administrator of cynara want to know, what would cynara return to client, if asked about given + * access. + * + * \par Method of function operation: + * Function works almost the same way as cynara_check() client function. + * The differences are: + * - user must specify bucket, from which search would be started (in case of cynara_check() + * it is always the default bucket) + * - user can specify if search should be recursive: disabling recursive check will constrain search + * to single bucket only, ignoring all policies leading to other buckets (in case of + * cynara_check() search is always recursive) + * - when matching policy in cynara is found, its result is returned without being interpreted by + * plugin extensions. + * + * \par Sync (or) Async: + * This is a synchronous API. + * + * \par Important notes: + * (*result_extra) may be set to NULL, if extra data are not used in matched policy + * If (*result_extra) is not NULL, it contains a string allocated by cynara admin library + * with malloc(3) function and must be released with free(3) function. + * + * \param[in] p_cynara_admin cynara admin structure. + * \param[in] start_bucket name of bucket where search would start. + * \param[in] recursive FALSE (== 0) : search is not recursive (single bucket search); + * TRUE (!= 0) : search does not ignore policies leading to another buckets. + * \param[in] client application or process identifier. + * \param[in] user user running client. + * \param[in] privilege privilege that is a subject of a check. + * \param[out] result placeholder for matched policy type. + * \param[out] result_extra placeholder for matched policy additional data (see Important Notes!). + * + * \return CYNARA_ADMIN_API_SUCCESS on success, or error code otherwise. + * + * \brief Raw check client and user access for given privilege without using plugins extensions. + */ +int cynara_admin_check(struct cynara_admin *p_cynara_admin, + const char *start_bucket, const int recursive, + const char *client, const char *user, const char *privilege, + int *result, char **result_extra); + #ifdef __cplusplus } #endif -- 2.7.4 From 3ebcba1f31bf9d3b24ae9d5bea284427ff28fcb5 Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Mon, 15 Sep 2014 19:16:17 +0200 Subject: [PATCH 14/16] Add adminCheck() method prototype in admin Logic Implement external API using newly added method. Change-Id: If086d8e33caaec87da5cbb2c25e6dd4163c01048 --- src/admin/api/ApiInterface.h | 4 ++++ src/admin/api/admin-api.cpp | 30 +++++++++++++++++++++++++++--- src/admin/logic/Logic.cpp | 6 ++++++ src/admin/logic/Logic.h | 2 ++ 4 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/admin/api/ApiInterface.h b/src/admin/api/ApiInterface.h index eb2b17b..fa858a6 100644 --- a/src/admin/api/ApiInterface.h +++ b/src/admin/api/ApiInterface.h @@ -46,6 +46,10 @@ public: virtual int insertOrUpdateBucket(const PolicyBucketId &bucket, const PolicyResult &policyResult) noexcept = 0; virtual int removeBucket(const PolicyBucketId &bucket) noexcept = 0; + + virtual int adminCheck(const PolicyBucketId &startBucket, bool recursive, + const PolicyKey &key, PolicyResult &result) noexcept = 0; + }; } // namespace Cynara diff --git a/src/admin/api/admin-api.cpp b/src/admin/api/admin-api.cpp index 00cae0b..ce1c7b7 100644 --- a/src/admin/api/admin-api.cpp +++ b/src/admin/api/admin-api.cpp @@ -22,7 +22,9 @@ #include #include +#include #include +#include #include #include @@ -175,7 +177,7 @@ int cynara_admin_set_bucket(struct cynara_admin *p_cynara_admin, const char *buc CYNARA_API int cynara_admin_check(struct cynara_admin *p_cynara_admin, - const char *start_bucket, const int recursive UNUSED, + const char *start_bucket, const int recursive, const char *client, const char *user, const char *privilege, int *result, char **result_extra) { if (!p_cynara_admin || !p_cynara_admin->impl) @@ -187,6 +189,28 @@ int cynara_admin_check(struct cynara_admin *p_cynara_admin, if (!result || !result_extra) return CYNARA_ADMIN_API_INVALID_PARAM; - //just mock-up + Cynara::PolicyResult policyResult; + + try { + int ret = p_cynara_admin->impl->adminCheck(start_bucket, recursive != 0, + Cynara::PolicyKey(client, user, privilege), + policyResult); + if (ret != CYNARA_ADMIN_API_SUCCESS) + return ret; + } catch (const std::bad_alloc &ex) { + return CYNARA_ADMIN_API_OUT_OF_MEMORY; + } catch (const std::length_error &ex) { + return CYNARA_ADMIN_API_INVALID_PARAM; + } + + char *str = nullptr; + if (!policyResult.metadata().empty()) { + str = strdup(policyResult.metadata().c_str()); + if (!str) + return CYNARA_ADMIN_API_OUT_OF_MEMORY; + } + *result = static_cast(policyResult.policyType()); + *result_extra = str; + return CYNARA_ADMIN_API_SUCCESS; -} \ No newline at end of file +} diff --git a/src/admin/logic/Logic.cpp b/src/admin/logic/Logic.cpp index 0934729..93cc43f 100644 --- a/src/admin/logic/Logic.cpp +++ b/src/admin/logic/Logic.cpp @@ -114,4 +114,10 @@ int Logic::removeBucket(const PolicyBucketId &bucket) noexcept { return askCynaraAndInterpreteCodeResponse(bucket); } +int Logic::adminCheck(const PolicyBucketId &startBucket UNUSED, bool recursive UNUSED, + const PolicyKey &key UNUSED, PolicyResult &result UNUSED) noexcept { + //just mock-up + return CYNARA_ADMIN_API_SUCCESS; +} + } // namespace Cynara diff --git a/src/admin/logic/Logic.h b/src/admin/logic/Logic.h index 2d349f3..b31cbec 100644 --- a/src/admin/logic/Logic.h +++ b/src/admin/logic/Logic.h @@ -48,6 +48,8 @@ public: noexcept; virtual int removeBucket(const PolicyBucketId &bucket) noexcept; + virtual int adminCheck(const PolicyBucketId &startBucket, bool recursive, + const PolicyKey &key, PolicyResult &result) noexcept; }; } // namespace Cynara -- 2.7.4 From 7516f955020d8f1fa0ee7dcfceb0c9a25106c857 Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Mon, 15 Sep 2014 20:33:39 +0200 Subject: [PATCH 15/16] Add AdminCheckRequest class Change-Id: I7be5c10c6905a0c4f561731a40288095c6a5e4d4 --- src/common/CMakeLists.txt | 1 + src/common/request/AdminCheckRequest.cpp | 34 ++++++++++++++++ src/common/request/AdminCheckRequest.h | 66 ++++++++++++++++++++++++++++++++ src/common/request/RequestTaker.cpp | 4 ++ src/common/request/RequestTaker.h | 1 + src/common/request/pointers.h | 3 ++ 6 files changed, 109 insertions(+) create mode 100644 src/common/request/AdminCheckRequest.cpp create mode 100644 src/common/request/AdminCheckRequest.h diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 3de3909..0901962 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -31,6 +31,7 @@ SET(COMMON_SOURCES ${COMMON_PATH}/protocol/ProtocolFrameSerializer.cpp ${COMMON_PATH}/protocol/ProtocolSerialization.cpp ${COMMON_PATH}/protocol/ProtocolSignal.cpp + ${COMMON_PATH}/request/AdminCheckRequest.cpp ${COMMON_PATH}/request/CheckRequest.cpp ${COMMON_PATH}/request/InsertOrUpdateBucketRequest.cpp ${COMMON_PATH}/request/RemoveBucketRequest.cpp diff --git a/src/common/request/AdminCheckRequest.cpp b/src/common/request/AdminCheckRequest.cpp new file mode 100644 index 0000000..6449c79 --- /dev/null +++ b/src/common/request/AdminCheckRequest.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file AdminCheckRequest.cpp + * @author Lukasz Wojciechowski + * @version 1.0 + * @brief This file implements admin check request class + */ + +#include + +#include "AdminCheckRequest.h" + +namespace Cynara { + +void AdminCheckRequest::execute(RequestPtr self, RequestTakerPtr taker, + RequestContextPtr context) const { + taker->execute(context, std::dynamic_pointer_cast(self)); +} + +} // namespace Cynara diff --git a/src/common/request/AdminCheckRequest.h b/src/common/request/AdminCheckRequest.h new file mode 100644 index 0000000..73d544b --- /dev/null +++ b/src/common/request/AdminCheckRequest.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file AdminCheckRequest.h + * @author Lukasz Wojciechowski + * @version 1.0 + * @brief This file defines admin check request class + */ + +#ifndef SRC_COMMON_REQUEST_ADMINCHECKREQUEST_H_ +#define SRC_COMMON_REQUEST_ADMINCHECKREQUEST_H_ + +#include +#include + +#include +#include +#include + +namespace Cynara { + +class AdminCheckRequest : public Request { +private: + PolicyKey m_key; + PolicyBucketId m_startBucket; + bool m_recursive; + +public: + AdminCheckRequest(const PolicyKey &key, const PolicyBucketId &startBucket, bool recursive, + ProtocolFrameSequenceNumber sequenceNumber) : + Request(sequenceNumber), m_key(key), m_startBucket(startBucket), m_recursive(recursive) { + } + + virtual ~AdminCheckRequest() {}; + + const PolicyKey &key(void) const { + return m_key; + } + + const PolicyBucketId &startBucket(void) const { + return m_startBucket; + } + + bool recursive(void) const { + return m_recursive; + } + + virtual void execute(RequestPtr self, RequestTakerPtr taker, RequestContextPtr context) const; +}; + +} // namespace Cynara + +#endif /* SRC_COMMON_REQUEST_ADMINCHECKREQUEST_H_ */ diff --git a/src/common/request/RequestTaker.cpp b/src/common/request/RequestTaker.cpp index 843c80e..2493613 100644 --- a/src/common/request/RequestTaker.cpp +++ b/src/common/request/RequestTaker.cpp @@ -29,6 +29,10 @@ namespace Cynara { +void RequestTaker::execute(RequestContextPtr context UNUSED, AdminCheckRequestPtr request UNUSED) { + throw NotImplementedException(); +} + void RequestTaker::execute(RequestContextPtr context UNUSED, CheckRequestPtr request UNUSED) { throw NotImplementedException(); } diff --git a/src/common/request/RequestTaker.h b/src/common/request/RequestTaker.h index 9d0a10f..25d6b17 100644 --- a/src/common/request/RequestTaker.h +++ b/src/common/request/RequestTaker.h @@ -32,6 +32,7 @@ public: RequestTaker() = default; virtual ~RequestTaker() {}; + virtual void execute(RequestContextPtr context, AdminCheckRequestPtr request); virtual void execute(RequestContextPtr context, CheckRequestPtr request); virtual void execute(RequestContextPtr context, InsertOrUpdateBucketRequestPtr request); virtual void execute(RequestContextPtr context, RemoveBucketRequestPtr request); diff --git a/src/common/request/pointers.h b/src/common/request/pointers.h index e04603e..ee59ccb 100644 --- a/src/common/request/pointers.h +++ b/src/common/request/pointers.h @@ -27,6 +27,9 @@ namespace Cynara { +class AdminCheckRequest; +typedef std::shared_ptr AdminCheckRequestPtr; + class CheckRequest; typedef std::shared_ptr CheckRequestPtr; -- 2.7.4 From 1845bbbd969007393044cdac3941b6ae7a9193ab Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Mon, 15 Sep 2014 21:39:45 +0200 Subject: [PATCH 16/16] Split OpCheckPolicy into request and response codes Improve log formatting and casting arguments. Change-Id: I16f279b7fca61108f1627c9de2996dba84165ba6 --- src/common/protocol/ProtocolClient.cpp | 35 ++++++++++++++++++---------------- src/common/protocol/ProtocolOpCode.h | 5 +++-- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/src/common/protocol/ProtocolClient.cpp b/src/common/protocol/ProtocolClient.cpp index d706338..6d5b89c 100644 --- a/src/common/protocol/ProtocolClient.cpp +++ b/src/common/protocol/ProtocolClient.cpp @@ -21,9 +21,10 @@ * @brief This file implements protocol class for communication with client */ -#include +#include #include +#include #include #include #include @@ -58,7 +59,7 @@ RequestPtr ProtocolClient::deserializeCheckRequest(ProtocolFrameHeader &frame) { ProtocolDeserialization::deserialize(frame, userId); ProtocolDeserialization::deserialize(frame, privilegeId); - LOGD("Deserialized CheckRequest: client = %s, user = %s, privilege = %s", + LOGD("Deserialized CheckRequest: client <%s>, user <%s>, privilege <%s>", clientId.c_str(), userId.c_str(), privilegeId.c_str()); return std::make_shared(PolicyKey(clientId, userId, privilegeId), @@ -73,9 +74,10 @@ RequestPtr ProtocolClient::extractRequestFromBuffer(BinaryQueue &bufferQueue) { m_frameHeader.resetState(); ProtocolDeserialization::deserialize(m_frameHeader, opCode); - LOGD("Deserialized opCode = %d", (int)opCode); + + LOGD("Deserialized opCode [%" PRIu8 "]", opCode); switch (opCode) { - case OpCheckPolicy: + case OpCheckPolicyRequest: return deserializeCheckRequest(m_frameHeader); default: throw InvalidProtocolException(InvalidProtocolException::WrongOpCode); @@ -95,8 +97,8 @@ ResponsePtr ProtocolClient::deserializeCheckResponse(ProtocolFrameHeader &frame) const PolicyResult policyResult(result, additionalInfo); - LOGD("Deserialized CheckResponse: result = %d, metadata = %s", - (int)policyResult.policyType(), policyResult.metadata().c_str()); + LOGD("Deserialized CheckResponse: result [%" PRIu16 "], metadata <%s>", + policyResult.policyType(), policyResult.metadata().c_str()); return std::make_shared(policyResult, frame.sequenceNumber()); } @@ -109,9 +111,9 @@ ResponsePtr ProtocolClient::extractResponseFromBuffer(BinaryQueue &bufferQueue) m_frameHeader.resetState(); ProtocolDeserialization::deserialize(m_frameHeader, opCode); - LOGD("Deserialized opCode = %d", (int)opCode); + LOGD("Deserialized opCode [%" PRIu8 "]", opCode); switch (opCode) { - case OpCheckPolicy: + case OpCheckPolicyResponse: return deserializeCheckResponse(m_frameHeader); default: throw InvalidProtocolException(InvalidProtocolException::WrongOpCode); @@ -125,11 +127,11 @@ ResponsePtr ProtocolClient::extractResponseFromBuffer(BinaryQueue &bufferQueue) void ProtocolClient::execute(RequestContextPtr context, CheckRequestPtr request) { ProtocolFramePtr frame = ProtocolFrameSerializer::startSerialization(request->sequenceNumber()); - LOGD("Serializing CheckRequest: client = %s, user = %s, privilege = %s", - request->key().client().value().c_str(), - request->key().user().value().c_str(), request->key().privilege().value().c_str()); + LOGD("Serializing CheckRequest: client <%s>, user <%s>, privilege <%s>", + request->key().client().value().c_str(), request->key().user().value().c_str(), + request->key().privilege().value().c_str()); - ProtocolSerialization::serialize(*frame, OpCheckPolicy); + ProtocolSerialization::serialize(*frame, OpCheckPolicyRequest); ProtocolSerialization::serialize(*frame, request->key().client().value()); ProtocolSerialization::serialize(*frame, request->key().user().value()); ProtocolSerialization::serialize(*frame, request->key().privilege().value()); @@ -138,13 +140,14 @@ void ProtocolClient::execute(RequestContextPtr context, CheckRequestPtr request) } void ProtocolClient::execute(RequestContextPtr context, CheckResponsePtr response) { - ProtocolFramePtr frame = ProtocolFrameSerializer::startSerialization(response->sequenceNumber()); + ProtocolFramePtr frame = ProtocolFrameSerializer::startSerialization( + response->sequenceNumber()); - LOGD("Serializing CheckResponse: op [%d], policyType [%d], metadata <%s>", - (int)OpCheckPolicy, (int)response->m_resultRef.policyType(), + LOGD("Serializing CheckResponse: op [%" PRIu8 "], policyType [%" PRIu16 "], metadata <%s>", + OpCheckPolicyResponse, response->m_resultRef.policyType(), response->m_resultRef.metadata().c_str()); - ProtocolSerialization::serialize(*frame, OpCheckPolicy); + ProtocolSerialization::serialize(*frame, OpCheckPolicyResponse); ProtocolSerialization::serialize(*frame, response->m_resultRef.policyType()); ProtocolSerialization::serialize(*frame, response->m_resultRef.metadata()); diff --git a/src/common/protocol/ProtocolOpCode.h b/src/common/protocol/ProtocolOpCode.h index dcbdff0..3381cf2 100644 --- a/src/common/protocol/ProtocolOpCode.h +++ b/src/common/protocol/ProtocolOpCode.h @@ -31,9 +31,10 @@ namespace Cynara { enum ProtocolOpCode : uint8_t { /** Client operations */ - OpCheckPolicy = 0, + OpCheckPolicyRequest = 0, + OpCheckPolicyResponse, - /** Opcodes 1 - 19 are reserved for future use */ + /** Opcodes 2 - 19 are reserved for future use */ /** Admin operations */ OpInsertOrUpdateBucket = 20, -- 2.7.4