From c6e45cd6ad826f5ed174435c3edc9c25295749cd Mon Sep 17 00:00:00 2001 From: Aleksander Zdyb Date: Thu, 17 Jul 2014 14:29:53 +0200 Subject: [PATCH 01/16] Add loading database in Cynara::init Change-Id: Ie0d0774e4bc539ee4a33d87fb57afe33a5045952 --- packaging/cynara.spec | 3 ++ src/common/exceptions/FileNotFoundException.h | 55 ++++++++++++++++++++++++++ src/service/CMakeLists.txt | 3 ++ src/service/main/Cynara.cpp | 18 ++++++++- src/service/main/Cynara.h | 2 + src/service/main/main.cpp | 9 ----- src/service/storage/InMemoryStorageBackend.cpp | 55 +++++++++++++++++++++++--- src/service/storage/InMemoryStorageBackend.h | 30 +++++++++----- src/service/storage/Storage.cpp | 4 ++ src/service/storage/Storage.h | 3 ++ src/service/storage/StorageBackend.h | 2 + 11 files changed, 160 insertions(+), 24 deletions(-) create mode 100644 src/common/exceptions/FileNotFoundException.h diff --git a/packaging/cynara.spec b/packaging/cynara.spec index 4b68a35..aeca477 100644 --- a/packaging/cynara.spec +++ b/packaging/cynara.spec @@ -17,6 +17,8 @@ BuildRequires: pkgconfig(libsystemd-journal) %global user_name %{name} %global group_name %{name} +%global db_path %{_localstatedir}/%{name}/db/ + %global build_type %{?build_type:%build_type}%{!?build_type:RELEASE} %if %{?build_type} == "DEBUG" @@ -84,6 +86,7 @@ export CXXFLAGS="$CXXFLAGS -DTIZEN_DEBUG_ENABLE" export FFLAGS="$FFLAGS -DTIZEN_DEBUG_ENABLE" %endif +export CXXFLAGS="$CXXFLAGS -DCYNARA_DB_PATH=\\\"%{db_path}\\\"" export LDFLAGS+="-Wl,--rpath=%{_libdir}" %cmake . -DVERSION=%{version} \ diff --git a/src/common/exceptions/FileNotFoundException.h b/src/common/exceptions/FileNotFoundException.h new file mode 100644 index 0000000..e353c19 --- /dev/null +++ b/src/common/exceptions/FileNotFoundException.h @@ -0,0 +1,55 @@ +/* + * 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 FileNotFoundException.h + * @author Aleksander Zdyb + * @version 1.0 + * @brief This file defines exception thrown when database file is not found + */ + +#ifndef SRC_COMMON_EXCEPTIONS_FILENOTFOUNDEXCEPTION_H_ +#define SRC_COMMON_EXCEPTIONS_FILENOTFOUNDEXCEPTION_H_ + +#include + +#include + +namespace Cynara { + +class FileNotFoundException : public DatabaseException { +public: + FileNotFoundException(const std::string &filename) : m_filename(filename) {}; + virtual ~FileNotFoundException() = default; + + const std::string message(void) const { + if (m_message.empty()) { + m_message = "File " + filename() + " not found or corrupted badly"; + } + return m_message; + } + + const std::string &filename(void) const { + return m_filename; + } + +private: + mutable std::string m_message; + std::string m_filename; +}; + +} /* namespace Cynara */ + +#endif /* SRC_COMMON_EXCEPTIONS_FILENOTFOUNDEXCEPTION_H_ */ diff --git a/src/service/CMakeLists.txt b/src/service/CMakeLists.txt index 915cc00..9f11ab8 100644 --- a/src/service/CMakeLists.txt +++ b/src/service/CMakeLists.txt @@ -24,8 +24,11 @@ SET(CYNARA_SOURCES ${CYNARA_SERVICE_PATH}/main/main.cpp ${CYNARA_SERVICE_PATH}/sockets/Descriptor.cpp ${CYNARA_SERVICE_PATH}/sockets/SocketManager.cpp + ${CYNARA_SERVICE_PATH}/storage/BucketDeserializer.cpp ${CYNARA_SERVICE_PATH}/storage/InMemoryStorageBackend.cpp ${CYNARA_SERVICE_PATH}/storage/Storage.cpp + ${CYNARA_SERVICE_PATH}/storage/StorageDeserializer.cpp + ${CYNARA_SERVICE_PATH}/storage/StorageSerializer.cpp ) SET_SOURCE_FILES_PROPERTIES( diff --git a/src/service/main/Cynara.cpp b/src/service/main/Cynara.cpp index c99bbe4..20bb0ab 100644 --- a/src/service/main/Cynara.cpp +++ b/src/service/main/Cynara.cpp @@ -23,6 +23,7 @@ #include #include +#include #include #include @@ -43,16 +44,31 @@ Cynara::~Cynara() { finalize(); } +const std::string Cynara::storageDir(void) const { + std::string dir("/var/lib/cynara/db/"); + +#ifdef CYNARA_DB_PATH + dir = CYNARA_DB_PATH; +#else + LOGW("Cynara compiled without CYNARA_DB_PATH flag. Using default database directory."); +#endif + + LOGI("Cynara database path = <%s>", dir.c_str()); + return dir; +} + void Cynara::init(void) { m_logic = std::make_shared(); m_socketManager = std::make_shared(); - m_storageBackend = std::make_shared(); + m_storageBackend = std::make_shared(storageDir()); m_storage = std::make_shared(*m_storageBackend); m_logic->bindStorage(m_storage); m_logic->bindSocketManager(m_socketManager); m_socketManager->bindLogic(m_logic); + + m_storage->load(); } void Cynara::run(void) { diff --git a/src/service/main/Cynara.h b/src/service/main/Cynara.h index 207e1b0..2e962c5 100644 --- a/src/service/main/Cynara.h +++ b/src/service/main/Cynara.h @@ -34,6 +34,8 @@ private: StoragePtr m_storage; StorageBackendPtr m_storageBackend; + const std::string storageDir(void) const; + public: Cynara(); ~Cynara(); diff --git a/src/service/main/main.cpp b/src/service/main/main.cpp index 766a422..ce7b07b 100644 --- a/src/service/main/main.cpp +++ b/src/service/main/main.cpp @@ -23,17 +23,8 @@ * @brief Main Cynara daemon file */ -//#include #include -//#include -//#include -//#include #include -//#include -//#include -//#include -//#include -//#include #include #include diff --git a/src/service/storage/InMemoryStorageBackend.cpp b/src/service/storage/InMemoryStorageBackend.cpp index b213111..1b7ae44 100644 --- a/src/service/storage/InMemoryStorageBackend.cpp +++ b/src/service/storage/InMemoryStorageBackend.cpp @@ -20,16 +20,40 @@ * @brief Implementation of InMemoryStorageBackend */ +#include +#include + +#include +#include +#include +#include +#include + #include "InMemoryStorageBackend.h" namespace Cynara { -InMemoryStorageBackend::InMemoryStorageBackend() { - // Make sure, there's always default bucket - this->buckets().insert({ defaultPolicyBucketId, PolicyBucket() }); -} +void InMemoryStorageBackend::load(void) { + std::string indexFilename = m_dbPath + "buckets"; + + try { + std::ifstream indexStream; + openFileStream(indexStream, indexFilename); -InMemoryStorageBackend::~InMemoryStorageBackend() {} + StorageDeserializer storageDeserializer(indexStream, + std::bind(&InMemoryStorageBackend::bucketStreamOpener, this, std::placeholders::_1)); + + storageDeserializer.initBuckets(buckets()); + storageDeserializer.loadBuckets(buckets()); + } catch (const FileNotFoundException &) { + LOGE("Reading cynara database failed."); + } + + if(!hasBucket(defaultPolicyBucketId)) { + LOGN("Creating defaultBucket."); + this->buckets().insert({ defaultPolicyBucketId, PolicyBucket() }); + } +} PolicyBucket InMemoryStorageBackend::searchDefaultBucket(const PolicyKey &key) { return searchBucket(defaultPolicyBucketId, key); @@ -118,4 +142,25 @@ void InMemoryStorageBackend::deleteLinking(const PolicyBucketId &bucketId) { } } +void InMemoryStorageBackend::openFileStream(std::ifstream &stream, const std::string &filename) { + // TODO: Consider adding exceptions to streams and handling them: + // stream.exceptions(std::ifstream::failbit | std::ifstream::badbit); + stream.open(filename); + + if (!stream.is_open()) + throw FileNotFoundException(filename); +} + +std::shared_ptr InMemoryStorageBackend::bucketStreamOpener( + const PolicyBucketId &bucketId) { + std::string bucketFilename = m_dbPath + "_" + bucketId; + std::ifstream bucketStream; + try { + openFileStream(bucketStream, bucketFilename); + return std::make_shared(bucketStream); + } catch (const FileNotFoundException &) { + return nullptr; + } +} + } /* namespace Cynara */ diff --git a/src/service/storage/InMemoryStorageBackend.h b/src/service/storage/InMemoryStorageBackend.h index 409a84c..1791b00 100644 --- a/src/service/storage/InMemoryStorageBackend.h +++ b/src/service/storage/InMemoryStorageBackend.h @@ -23,24 +23,31 @@ #ifndef INMEMORYSTORAGEBACKEND_H_ #define INMEMORYSTORAGEBACKEND_H_ -#include "StorageBackend.h" -#include -#include -#include - -#include #include +#include #include #include +#include + +#include +#include +#include +#include + +#include "StorageBackend.h" namespace Cynara { -class InMemoryStorageBackend: public StorageBackend { +class InMemoryStorageBackend : public StorageBackend { public: typedef std::unordered_map Buckets; - InMemoryStorageBackend(); - virtual ~InMemoryStorageBackend(); + InMemoryStorageBackend(const std::string &path) : m_dbPath(path) { + } + + virtual ~InMemoryStorageBackend() = default; + + virtual void load(void); virtual PolicyBucket searchDefaultBucket(const PolicyKey &key); virtual PolicyBucket searchBucket(const PolicyBucketId &bucketId, const PolicyKey &key); @@ -52,7 +59,12 @@ public: virtual void deletePolicy(const PolicyBucketId &bucketId, const PolicyKey &key); virtual void deleteLinking(const PolicyBucketId &bucketId); +protected: + void openFileStream(std::ifstream &stream, const std::string &filename); + std::shared_ptr bucketStreamOpener(const PolicyBucketId &bucketId); + private: + std::string m_dbPath; Buckets m_buckets; protected: diff --git a/src/service/storage/Storage.cpp b/src/service/storage/Storage.cpp index 60de8ff..319dbda 100644 --- a/src/service/storage/Storage.cpp +++ b/src/service/storage/Storage.cpp @@ -121,4 +121,8 @@ void Storage::deletePolicies(const std::map #include +#include #include #include @@ -52,6 +53,8 @@ public: void addOrUpdateBucket(const PolicyBucketId &bucketId, const PolicyResult &defaultBucketPolicy); void deleteBucket(const PolicyBucketId &bucketId); + void load(void); + protected: PolicyResult minimalPolicy(const PolicyBucket &bucket, const PolicyKey &key); diff --git a/src/service/storage/StorageBackend.h b/src/service/storage/StorageBackend.h index 6689bae..97e0fd7 100644 --- a/src/service/storage/StorageBackend.h +++ b/src/service/storage/StorageBackend.h @@ -50,6 +50,8 @@ public: virtual void deletePolicy(const PolicyBucketId &bucketId, const PolicyKey &key) = 0; virtual void deleteLinking(const PolicyBucketId &bucket) = 0; + + virtual void load(void) = 0; }; } /* namespace Cynara */ -- 2.7.4 From 5a516224642907b556f7cc6aec3b3f396ecf3219 Mon Sep 17 00:00:00 2001 From: Adam Malinowski Date: Fri, 18 Jul 2014 18:22:05 +0200 Subject: [PATCH 02/16] Create local state directory for cynara service Change-Id: I5b5ca2323916fe9a8763949ba17051d46e59a16f --- packaging/cynara.spec | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packaging/cynara.spec b/packaging/cynara.spec index aeca477..59ef5e2 100644 --- a/packaging/cynara.spec +++ b/packaging/cynara.spec @@ -17,7 +17,7 @@ BuildRequires: pkgconfig(libsystemd-journal) %global user_name %{name} %global group_name %{name} -%global db_path %{_localstatedir}/%{name}/db/ +%global state_path %{_localstatedir}/%{name}/ %global build_type %{?build_type:%build_type}%{!?build_type:RELEASE} @@ -86,7 +86,7 @@ export CXXFLAGS="$CXXFLAGS -DTIZEN_DEBUG_ENABLE" export FFLAGS="$FFLAGS -DTIZEN_DEBUG_ENABLE" %endif -export CXXFLAGS="$CXXFLAGS -DCYNARA_DB_PATH=\\\"%{db_path}\\\"" +export CXXFLAGS="$CXXFLAGS -DCYNARA_DB_PATH=\\\"%{state_path}\\\"" export LDFLAGS+="-Wl,--rpath=%{_libdir}" %cmake . -DVERSION=%{version} \ @@ -100,6 +100,7 @@ rm -rf %{buildroot} %make_install mkdir -p %{buildroot}/usr/lib/systemd/system/sockets.target.wants +mkdir -p %{buildroot}/%{state_path} 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 @@ -170,6 +171,7 @@ fi %attr(-,root,root) /usr/lib/systemd/system/cynara.socket %attr(-,root,root) /usr/lib/systemd/system/sockets.target.wants/cynara-admin.socket %attr(-,root,root) /usr/lib/systemd/system/cynara-admin.socket +%dir %attr(700,cynara,cynara) %{state_path} %files -n libcynara-client %manifest libcynara-client.manifest -- 2.7.4 From d669d4295d02dde4691aef628547139c0a587e26 Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Fri, 18 Jul 2014 21:58:32 +0200 Subject: [PATCH 03/16] Fix usage of local state directory in Cynara service Change-Id: I66f60b919edf7f36a1de3d21db81bef5b9245485 --- packaging/cynara.spec | 2 +- src/service/main/Cynara.cpp | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/packaging/cynara.spec b/packaging/cynara.spec index 59ef5e2..11c630b 100644 --- a/packaging/cynara.spec +++ b/packaging/cynara.spec @@ -86,7 +86,7 @@ export CXXFLAGS="$CXXFLAGS -DTIZEN_DEBUG_ENABLE" export FFLAGS="$FFLAGS -DTIZEN_DEBUG_ENABLE" %endif -export CXXFLAGS="$CXXFLAGS -DCYNARA_DB_PATH=\\\"%{state_path}\\\"" +export CXXFLAGS="$CXXFLAGS -DCYNARA_STATE_PATH=\\\"%{state_path}\\\"" export LDFLAGS+="-Wl,--rpath=%{_libdir}" %cmake . -DVERSION=%{version} \ diff --git a/src/service/main/Cynara.cpp b/src/service/main/Cynara.cpp index 20bb0ab..8ad22e2 100644 --- a/src/service/main/Cynara.cpp +++ b/src/service/main/Cynara.cpp @@ -45,15 +45,16 @@ Cynara::~Cynara() { } const std::string Cynara::storageDir(void) const { - std::string dir("/var/lib/cynara/db/"); + std::string dir("/var/lib/cynara/"); -#ifdef CYNARA_DB_PATH - dir = CYNARA_DB_PATH; +#ifdef CYNARA_STATE_PATH + dir = CYNARA_STATE_PATH; #else - LOGW("Cynara compiled without CYNARA_DB_PATH flag. Using default database directory."); + LOGW("Cynara compiled without CYNARA_STATE_PATH flag. Using default database directory."); #endif - LOGI("Cynara database path = <%s>", dir.c_str()); + dir += "db/"; + LOGI("Cynara database path <%s>", dir.c_str()); return dir; } -- 2.7.4 From d614bd7ab9eec3c7757649bb9e9f73a0b4acb92a Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Fri, 18 Jul 2014 21:34:49 +0200 Subject: [PATCH 04/16] Implement Storage::save() using StorageSerializer and clean up There was a lot of mess in #includes directives and forward declarations of classes. It was cleaned out. InMemoryStorageBackend::Buckets were moved to separate file in order not to make a cyclic dependency. New exception class CannotCreateFile was added. Change-Id: I32b234ba0f4872791a9f931690c58e623de7096f --- src/common/exceptions/CannotCreateFileException.h | 55 ++++++++++++++++++++ src/service/storage/BucketDeserializer.cpp | 19 ++++--- src/service/storage/BucketDeserializer.h | 7 ++- src/service/storage/Buckets.h | 38 ++++++++++++++ src/service/storage/InMemoryStorageBackend.cpp | 63 +++++++++++++++++++++-- src/service/storage/InMemoryStorageBackend.h | 37 +++++++------ src/service/storage/Storage.cpp | 47 +++++++++-------- src/service/storage/Storage.h | 23 ++++----- src/service/storage/StorageBackend.h | 27 +++++----- src/service/storage/StorageDeserializer.cpp | 15 +++--- src/service/storage/StorageDeserializer.h | 20 ++++--- src/service/storage/StorageSerializer.cpp | 12 +++-- src/service/storage/StorageSerializer.h | 21 ++++---- 13 files changed, 280 insertions(+), 104 deletions(-) create mode 100644 src/common/exceptions/CannotCreateFileException.h create mode 100644 src/service/storage/Buckets.h diff --git a/src/common/exceptions/CannotCreateFileException.h b/src/common/exceptions/CannotCreateFileException.h new file mode 100644 index 0000000..bb3f937 --- /dev/null +++ b/src/common/exceptions/CannotCreateFileException.h @@ -0,0 +1,55 @@ +/* + * 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 CannotCreateFileException.h + * @author Lukasz Wojciechowski + * @version 1.0 + * @brief This file defines exception thrown when database file cannot be created + */ + +#ifndef SRC_COMMON_EXCEPTIONS_CANNOTCREATEFILEEXCEPTION_H_ +#define SRC_COMMON_EXCEPTIONS_CANNOTCREATEFILEEXCEPTION_H_ + +#include + +#include + +namespace Cynara { + +class CannotCreateFileException : public DatabaseException { +public: + CannotCreateFileException(const std::string &filename) : m_filename(filename) {}; + virtual ~CannotCreateFileException() = default; + + const std::string message(void) const { + if (m_message.empty()) { + m_message = "File " + filename() + " cannot be created"; + } + return m_message; + } + + const std::string &filename(void) const { + return m_filename; + } + +private: + mutable std::string m_message; + std::string m_filename; +}; + +} /* namespace Cynara */ + +#endif /* SRC_COMMON_EXCEPTIONS_CANNOTCREATEFILEEXCEPTION_H_ */ diff --git a/src/service/storage/BucketDeserializer.cpp b/src/service/storage/BucketDeserializer.cpp index 914f766..1bfac50 100644 --- a/src/service/storage/BucketDeserializer.cpp +++ b/src/service/storage/BucketDeserializer.cpp @@ -20,15 +20,20 @@ * @brief Methods implementation of Cynara::BucketDeserializer */ +#include +#include +#include +#include + #include -#include +#include +#include +#include + #include #include -#include -#include -#include -#include +#include "BucketDeserializer.h" namespace Cynara { @@ -36,7 +41,7 @@ PolicyCollection BucketDeserializer::loadPolicies(void) { PolicyCollection policies; // TODO: Get someone smart to do error checking on stream - for(std::size_t lineNum = 1; !m_inStream.eof(); ++lineNum) { + for (std::size_t lineNum = 1; !m_inStream.eof(); ++lineNum) { std::string line; std::getline(m_inStream, line, StorageSerializer::recordSeparator()); @@ -61,7 +66,7 @@ PolicyCollection BucketDeserializer::loadPolicies(void) { PolicyKey BucketDeserializer::parseKey(const std::string &line, std::size_t &beginToken) { std::array keyFeatures; - for(std::size_t tokenNum = 0; tokenNum < keyFeatures.size(); ++tokenNum) { + for (std::size_t tokenNum = 0; tokenNum < keyFeatures.size(); ++tokenNum) { auto endToken = line.find(StorageSerializer::fieldSeparator(), beginToken); if (endToken != std::string::npos) { keyFeatures[tokenNum] = line.substr(beginToken, endToken - beginToken); diff --git a/src/service/storage/BucketDeserializer.h b/src/service/storage/BucketDeserializer.h index a9b7b8c..393991e 100644 --- a/src/service/storage/BucketDeserializer.h +++ b/src/service/storage/BucketDeserializer.h @@ -22,12 +22,11 @@ #ifndef SRC_SERVICE_STORAGE_BUCKETDESERIALIZER_H_ #define SRC_SERVICE_STORAGE_BUCKETDESERIALIZER_H_ +#include +#include + #include #include -#include -#include - -#include namespace Cynara { diff --git a/src/service/storage/Buckets.h b/src/service/storage/Buckets.h new file mode 100644 index 0000000..1fdc249 --- /dev/null +++ b/src/service/storage/Buckets.h @@ -0,0 +1,38 @@ +/* + * 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 Buckets.h + * @author Aleksander Zdyb + * @author Lukasz Wojciechowski + * @version 1.0 + * @brief Headers for Buckets + */ + +#ifndef SRC_SERVICE_STORAGE_BUCKETS_H_ +#define SRC_SERVICE_STORAGE_BUCKETS_H_ + +#include + +#include +#include + +namespace Cynara { + +typedef std::unordered_map Buckets; + +} /* namespace Cynara */ + +#endif /* SRC_SERVICE_STORAGE_BUCKETS_H_ */ diff --git a/src/service/storage/InMemoryStorageBackend.cpp b/src/service/storage/InMemoryStorageBackend.cpp index 1b7ae44..5d18219 100644 --- a/src/service/storage/InMemoryStorageBackend.cpp +++ b/src/service/storage/InMemoryStorageBackend.cpp @@ -20,21 +20,34 @@ * @brief Implementation of InMemoryStorageBackend */ +#include #include #include +#include +#include +#include +#include +#include #include +#include +#include #include +#include +#include +#include +#include + #include #include -#include +#include #include "InMemoryStorageBackend.h" namespace Cynara { void InMemoryStorageBackend::load(void) { - std::string indexFilename = m_dbPath + "buckets"; + std::string indexFilename = m_dbPath + m_indexFileName; try { std::ifstream indexStream; @@ -49,12 +62,33 @@ void InMemoryStorageBackend::load(void) { LOGE("Reading cynara database failed."); } - if(!hasBucket(defaultPolicyBucketId)) { + if (!hasBucket(defaultPolicyBucketId)) { LOGN("Creating defaultBucket."); this->buckets().insert({ defaultPolicyBucketId, PolicyBucket() }); } } +void InMemoryStorageBackend::save(void) { + + //create directory + int ret = mkdir(m_dbPath.c_str(), S_IRWXU); + if (ret < 0) { + int err = errno; + if (err != EEXIST) { + LOGE("Cannot create directory <%s>. Error [%d] : <%s>.", + m_dbPath.c_str(), err, strerror(err)); + throw UnexpectedErrorException(err, strerror(err)); + } + } + + std::ofstream indexStream; + openDumpFileStream(indexStream, m_dbPath + m_indexFileName); + + StorageSerializer storageSerializer(indexStream); + storageSerializer.dump(buckets(), std::bind(&InMemoryStorageBackend::bucketDumpStreamOpener, + this, std::placeholders::_1)); +} + PolicyBucket InMemoryStorageBackend::searchDefaultBucket(const PolicyKey &key) { return searchBucket(defaultPolicyBucketId, key); } @@ -116,7 +150,7 @@ void InMemoryStorageBackend::deletePolicy(const PolicyBucketId &bucketId, const [key](PolicyPtr policy) -> bool { return policy->key() == key; }), policies.end()); - } catch(const std::out_of_range &) { + } catch (const std::out_of_range &) { throw BucketNotExistsException(bucketId); } } @@ -133,7 +167,7 @@ void InMemoryStorageBackend::deleteLinking(const PolicyBucketId &bucketId) { return false; }; - for(auto &bucketIter : buckets()) { + for (auto &bucketIter : buckets()) { // TODO: Move the erase code to PolicyCollection maybe? auto &bucket = bucketIter.second; auto &policies = bucket.policyCollection(); @@ -151,6 +185,16 @@ void InMemoryStorageBackend::openFileStream(std::ifstream &stream, const std::st throw FileNotFoundException(filename); } +void InMemoryStorageBackend::openDumpFileStream(std::ofstream &stream, + const std::string &filename) { + stream.open(filename, std::ofstream::out | std::ofstream::trunc); + + if (!stream.is_open()) { + throw CannotCreateFileException(filename); + return; + } +} + std::shared_ptr InMemoryStorageBackend::bucketStreamOpener( const PolicyBucketId &bucketId) { std::string bucketFilename = m_dbPath + "_" + bucketId; @@ -163,4 +207,13 @@ std::shared_ptr InMemoryStorageBackend::bucketStreamOpener( } } +std::shared_ptr InMemoryStorageBackend::bucketDumpStreamOpener( + const PolicyBucketId &bucketId) { + std::string bucketFilename = m_dbPath + "_" + bucketId; + std::ofstream bucketStream; + + openDumpFileStream(bucketStream, bucketFilename); + return std::make_shared(bucketStream); +} + } /* namespace Cynara */ diff --git a/src/service/storage/InMemoryStorageBackend.h b/src/service/storage/InMemoryStorageBackend.h index 1791b00..5127bc6 100644 --- a/src/service/storage/InMemoryStorageBackend.h +++ b/src/service/storage/InMemoryStorageBackend.h @@ -20,34 +20,34 @@ * @brief Headers for InMemoryStorageBackend */ -#ifndef INMEMORYSTORAGEBACKEND_H_ -#define INMEMORYSTORAGEBACKEND_H_ +#ifndef SRC_SERVICE_STORAGE_INMEMORYSTORAGEBACKEND_H_ +#define SRC_SERVICE_STORAGE_INMEMORYSTORAGEBACKEND_H_ -#include #include -#include -#include -#include +#include +#include -#include -#include -#include -#include +#include +#include +#include +#include +#include -#include "StorageBackend.h" +#include +#include +#include +#include namespace Cynara { class InMemoryStorageBackend : public StorageBackend { public: - typedef std::unordered_map Buckets; - InMemoryStorageBackend(const std::string &path) : m_dbPath(path) { } - virtual ~InMemoryStorageBackend() = default; virtual void load(void); + virtual void save(void); virtual PolicyBucket searchDefaultBucket(const PolicyKey &key); virtual PolicyBucket searchBucket(const PolicyBucketId &bucketId, const PolicyKey &key); @@ -63,15 +63,20 @@ protected: void openFileStream(std::ifstream &stream, const std::string &filename); std::shared_ptr bucketStreamOpener(const PolicyBucketId &bucketId); + void openDumpFileStream(std::ofstream &stream, const std::string &filename); + std::shared_ptr bucketDumpStreamOpener(const PolicyBucketId &bucketId); + private: std::string m_dbPath; Buckets m_buckets; + const std::string m_indexFileName = "buckets"; protected: - virtual Buckets &buckets() { + virtual Buckets &buckets(void) { return m_buckets; } }; } /* namespace Cynara */ -#endif /* INMEMORYSTORAGEBACKEND_H_ */ + +#endif /* SRC_SERVICE_STORAGE_INMEMORYSTORAGEBACKEND_H_ */ diff --git a/src/service/storage/Storage.cpp b/src/service/storage/Storage.cpp index 319dbda..cfbd82d 100644 --- a/src/service/storage/Storage.cpp +++ b/src/service/storage/Storage.cpp @@ -21,16 +21,19 @@ * @brief This file implements policy rules storage procedures */ -#include "Storage.h" -#include "StorageBackend.h" -#include "types/pointers.h" -#include "types/PolicyType.h" -#include "exceptions/NotImplementedException.h" -#include "exceptions/DefaultBucketDeletionException.h" - -#include #include +#include +#include "exceptions/DefaultBucketDeletionException.h" +#include +#include +#include +#include +#include +#include +#include + +#include "Storage.h" namespace Cynara { @@ -58,19 +61,17 @@ PolicyResult Storage::minimalPolicy(const PolicyBucket &bucket, const PolicyKey const auto &policyResult = policyRecord->result(); switch (policyResult.policyType()) { - case PredefinedPolicyType::DENY: - return policyResult; // Do not expect lower value than DENY - break; - case PredefinedPolicyType::BUCKET: { - auto bucketResults = m_backend.searchBucket(policyResult.metadata(), key); - auto minimumOfBucket = minimalPolicy(bucketResults, key); - proposeMinimal(minimumOfBucket); - continue; - } - break; - case PredefinedPolicyType::ALLOW: - default: - break; + 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); + continue; + } + case PredefinedPolicyType::ALLOW: + default: + break; } proposeMinimal(policyResult); @@ -125,4 +126,8 @@ void Storage::load(void) { m_backend.load(); } +void Storage::save(void) { + m_backend.save(); +} + } // namespace Cynara diff --git a/src/service/storage/Storage.h b/src/service/storage/Storage.h index b1c7cb3..23955ff 100644 --- a/src/service/storage/Storage.h +++ b/src/service/storage/Storage.h @@ -21,24 +21,22 @@ * @brief This file is the implementation file of log system */ -#ifndef CYNARA_SERVICE_STORAGE_STORAGE_H -#define CYNARA_SERVICE_STORAGE_STORAGE_H +#ifndef SRC_SERVICE_STORAGE_STORAGE_H_ +#define SRC_SERVICE_STORAGE_STORAGE_H_ #include -#include #include -#include #include -#include "types/pointers.h" -#include "types/PolicyBucketId.h" -#include "types/PolicyResult.h" -#include "types/PolicyKey.h" +#include +#include +#include +#include +#include -namespace Cynara { +#include -class StorageBackend; -class PolicyBucket; +namespace Cynara { class Storage { @@ -54,6 +52,7 @@ public: void deleteBucket(const PolicyBucketId &bucketId); void load(void); + void save(void); protected: PolicyResult minimalPolicy(const PolicyBucket &bucket, const PolicyKey &key); @@ -64,4 +63,4 @@ private: } // namespace Cynara -#endif /* CYNARA_SERVICE_STORAGE_STORAGE_H */ +#endif /* SRC_SERVICE_STORAGE_STORAGE_H_ */ diff --git a/src/service/storage/StorageBackend.h b/src/service/storage/StorageBackend.h index 97e0fd7..cc711f9 100644 --- a/src/service/storage/StorageBackend.h +++ b/src/service/storage/StorageBackend.h @@ -20,20 +20,19 @@ * @brief Headers for StorageBackend base class */ -#ifndef STORAGEBACKEND_H_ -#define STORAGEBACKEND_H_ +#ifndef SRC_SERVICE_STORAGE_STORAGEBACKEND_H_ +#define SRC_SERVICE_STORAGE_STORAGEBACKEND_H_ +#include -#include "types/pointers.h" -#include "types/PolicyBucket.h" -#include "types/PolicyBucketId.h" - -#include +#include +#include +#include +#include +#include namespace Cynara { -class PolicyKey; - class StorageBackend { public: virtual ~StorageBackend() {} @@ -43,8 +42,10 @@ public: virtual void insertPolicy(const PolicyBucketId &bucket, PolicyPtr policy) = 0; - virtual void createBucket(const PolicyBucketId &bucketId, const PolicyResult &defaultPolicy) = 0; - virtual void updateBucket(const PolicyBucketId &bucketId, const PolicyResult &defaultPolicy) = 0; + virtual void createBucket(const PolicyBucketId &bucketId, + const PolicyResult &defaultPolicy) = 0; + virtual void updateBucket(const PolicyBucketId &bucketId, + const PolicyResult &defaultPolicy) = 0; virtual void deleteBucket(const PolicyBucketId &bucketId) = 0; virtual bool hasBucket(const PolicyBucketId &bucketId) = 0; @@ -52,7 +53,9 @@ public: virtual void deleteLinking(const PolicyBucketId &bucket) = 0; virtual void load(void) = 0; + virtual void save(void) = 0; }; } /* namespace Cynara */ -#endif /* STORAGEBACKEND_H_ */ + +#endif /* SRC_SERVICE_STORAGE_STORAGEBACKEND_H_ */ diff --git a/src/service/storage/StorageDeserializer.cpp b/src/service/storage/StorageDeserializer.cpp index 0510670..66c8ff0 100644 --- a/src/service/storage/StorageDeserializer.cpp +++ b/src/service/storage/StorageDeserializer.cpp @@ -20,15 +20,18 @@ * @brief Implementation for Cynara::StorageDeserializer */ -#include +#include #include #include #include +#include + #include +#include #include -#include +#include "StorageDeserializer.h" namespace Cynara { @@ -36,10 +39,10 @@ StorageDeserializer::StorageDeserializer(std::istream &inStream, BucketStreamOpener bucketStreamOpener) : m_inStream(inStream), m_bucketStreamOpener(bucketStreamOpener) {} -void StorageDeserializer::initBuckets(InMemoryStorageBackend::Buckets &buckets) { +void StorageDeserializer::initBuckets(Buckets &buckets) { buckets.clear(); - for(std::size_t lineNum = 1; !m_inStream.eof(); ++lineNum) { + for (std::size_t lineNum = 1; !m_inStream.eof(); ++lineNum) { std::string line; std::getline(m_inStream, line, StorageSerializer::recordSeparator()); @@ -55,7 +58,7 @@ void StorageDeserializer::initBuckets(InMemoryStorageBackend::Buckets &buckets) } } -void StorageDeserializer::loadBuckets(InMemoryStorageBackend::Buckets &buckets) { +void StorageDeserializer::loadBuckets(Buckets &buckets) { for (auto &bucketIter : buckets) { const auto &bucketId = bucketIter.first; auto &bucket = bucketIter.second; @@ -88,7 +91,7 @@ PolicyType StorageDeserializer::parsePolicyType(const std::string &line, std::si std::size_t newBegin = 0; policyType = std::stoi(line.substr(beginToken), &newBegin, 16); beginToken += newBegin; - } catch(...) { + } catch (...) { throw BucketRecordCorruptedException(line); } diff --git a/src/service/storage/StorageDeserializer.h b/src/service/storage/StorageDeserializer.h index 2fd0341..c3680c4 100644 --- a/src/service/storage/StorageDeserializer.h +++ b/src/service/storage/StorageDeserializer.h @@ -22,21 +22,27 @@ #ifndef SRC_SERVICE_STORAGE_STORAGEDESERIALIZER_H_ #define SRC_SERVICE_STORAGE_STORAGEDESERIALIZER_H_ -#include -#include - +#include #include #include -#include +#include + +#include +#include +#include + +#include +#include namespace Cynara { class StorageDeserializer { public: - typedef std::function(const std::string &)> BucketStreamOpener; + typedef std::function(const std::string &)> + BucketStreamOpener; StorageDeserializer(std::istream &inStream, BucketStreamOpener m_bucketStreamOpener); - void initBuckets(InMemoryStorageBackend::Buckets &buckets); - void loadBuckets(InMemoryStorageBackend::Buckets &buckets); + void initBuckets(Buckets &buckets); + void loadBuckets(Buckets &buckets); static PolicyBucketId parseBucketId(const std::string &line, std::size_t &beginToken); static PolicyType parsePolicyType(const std::string &line, std::size_t &beginToken); diff --git a/src/service/storage/StorageSerializer.cpp b/src/service/storage/StorageSerializer.cpp index be8b9d4..f46d48e 100644 --- a/src/service/storage/StorageSerializer.cpp +++ b/src/service/storage/StorageSerializer.cpp @@ -20,13 +20,15 @@ * @brief Implementation of Cynara::StorageSerializer methods */ -#include #include -#include +#include #include -#include "types/PolicyBucket.h" -#include "types/PolicyCollection.h" +#include +#include +#include +#include +#include #include "StorageSerializer.h" @@ -37,7 +39,7 @@ char StorageSerializer::m_recordSeparator = '\n'; StorageSerializer::StorageSerializer(std::ostream &os) : m_outStream(os) {} -void StorageSerializer::dump(const InMemoryStorageBackend::Buckets &buckets, +void StorageSerializer::dump(const Buckets &buckets, BucketStreamOpener streamOpener) { for (const auto bucketIter : buckets) { diff --git a/src/service/storage/StorageSerializer.h b/src/service/storage/StorageSerializer.h index 789f263..80966e9 100644 --- a/src/service/storage/StorageSerializer.h +++ b/src/service/storage/StorageSerializer.h @@ -23,17 +23,20 @@ #ifndef SRC_SERVICE_STORAGE_STORAGESERIALIZER_H_ #define SRC_SERVICE_STORAGE_STORAGESERIALIZER_H_ -#include "InMemoryStorageBackend.h" -#include "types/PolicyBucketId.h" -#include "types/PolicyCollection.h" -#include "types/PolicyResult.h" - +#include +#include #include -namespace Cynara { +#include +#include +#include +#include +#include +#include -class PolicyBucket; -class PolicyKey; +#include + +namespace Cynara { class StorageSerializer { @@ -44,7 +47,7 @@ public: StorageSerializer(std::ostream &os); virtual ~StorageSerializer() = default; - virtual void dump(const InMemoryStorageBackend::Buckets &buckets, + virtual void dump(const Buckets &buckets, BucketStreamOpener streamOpener); virtual void dump(const PolicyBucket &bucket); -- 2.7.4 From 85dbfa23a922169211eaac3dd039466351a45490 Mon Sep 17 00:00:00 2001 From: Adam Malinowski Date: Fri, 18 Jul 2014 17:28:25 +0200 Subject: [PATCH 05/16] Add admin protocol (de)serialization Change-Id: I59f279c45125ea049d762201f779ecadada136b4 --- src/common/protocol/ProtocolAdmin.cpp | 235 +++++++++++++++++++++++++++++++++- src/common/protocol/ProtocolAdmin.h | 14 ++ src/common/protocol/ProtocolOpCode.h | 9 +- src/common/types/ProtocolFields.h | 4 +- 4 files changed, 251 insertions(+), 11 deletions(-) diff --git a/src/common/protocol/ProtocolAdmin.cpp b/src/common/protocol/ProtocolAdmin.cpp index d40dcf6..1a6ff67 100644 --- a/src/common/protocol/ProtocolAdmin.cpp +++ b/src/common/protocol/ProtocolAdmin.cpp @@ -16,12 +16,23 @@ /* * @file ProtocolAdmin.cpp * @author Lukasz Wojciechowski + * @author Adam Malinowski * @version 1.0 * @brief This file implements protocol class for administration */ -#include #include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include "ProtocolAdmin.h" namespace Cynara { @@ -36,14 +47,228 @@ ProtocolPtr ProtocolAdmin::clone(void) { return std::make_shared(); } +RequestPtr ProtocolAdmin::deserializeInsertOrUpdateBucketRequest(ProtocolFrameHeader &frame) { + PolicyBucketId policyBucketId; + PolicyType policyType; + PolicyResult::PolicyMetadata policyMetaData; + + ProtocolDeserialization::deserialize(frame, policyBucketId); + ProtocolDeserialization::deserialize(frame, policyType); + ProtocolDeserialization::deserialize(frame, policyMetaData); + + LOGD("Deserialized InsertOrUpdateBucketRequest: bucketId <%s>, " + "result.type [%u], result.meta <%s>", policyBucketId.c_str(), + static_cast(policyType), policyMetaData.c_str()); + + return std::make_shared(policyBucketId, + PolicyResult(policyType, policyMetaData), frame.sequenceNumber()); +} + +RequestPtr ProtocolAdmin::deserializeRemoveBucketRequest(ProtocolFrameHeader &frame) { + PolicyBucketId policyBucketId; + + ProtocolDeserialization::deserialize(frame, policyBucketId); + + LOGD("Deserialized RemoveBucketRequest: bucketId <%s>", policyBucketId.c_str()); + + return std::make_shared(policyBucketId, frame.sequenceNumber()); +} + +RequestPtr ProtocolAdmin::deserializeSetPoliciesRequest(ProtocolFrameHeader &frame) { + ProtocolFrameFieldsCount toBeInsertedOrUpdatedCount, toBeRemovedCount; + ProtocolFrameFieldsCount policyCount; + PolicyKeyFeature::ValueType clientId, user, privilege; + PolicyType policyType; + PolicyResult::PolicyMetadata metadata; + std::map> toBeInsertedOrUpdatedPolicies; + std::map> toBeRemovedPolicies; + + ProtocolDeserialization::deserialize(frame, toBeInsertedOrUpdatedCount); + for (ProtocolFrameFieldsCount b = 0; b < toBeInsertedOrUpdatedCount; ++b) { + PolicyBucketId policyBucketId; + ProtocolDeserialization::deserialize(frame, policyBucketId); + ProtocolDeserialization::deserialize(frame, policyCount); + for (ProtocolFrameFieldsCount p = 0; p < policyCount; ++p) { + // PolicyKey + ProtocolDeserialization::deserialize(frame, clientId); + ProtocolDeserialization::deserialize(frame, user); + ProtocolDeserialization::deserialize(frame, privilege); + // PolicyResult + ProtocolDeserialization::deserialize(frame, policyType); + ProtocolDeserialization::deserialize(frame, metadata); + + toBeInsertedOrUpdatedPolicies[policyBucketId].push_back( + Policy(PolicyKey(clientId, user, privilege), + PolicyResult(policyType, metadata))); + } + } + + ProtocolDeserialization::deserialize(frame, toBeRemovedCount); + for (ProtocolFrameFieldsCount b = 0; b < toBeRemovedCount; ++b) { + PolicyBucketId policyBucketId; + ProtocolDeserialization::deserialize(frame, policyBucketId); + ProtocolDeserialization::deserialize(frame, policyCount); + for (ProtocolFrameFieldsCount p = 0; p < policyCount; ++p) { + // PolicyKey + ProtocolDeserialization::deserialize(frame, clientId); + ProtocolDeserialization::deserialize(frame, user); + ProtocolDeserialization::deserialize(frame, privilege); + + toBeRemovedPolicies[policyBucketId].push_back(PolicyKey(clientId, user, privilege)); + } + } + + LOGD("Deserialized SetPoliciesRequestPtr: insertOrUpdate count [%u], remove count [%u]", + static_cast(toBeInsertedOrUpdatedCount), + static_cast(toBeRemovedCount)); + + return std::make_shared(toBeInsertedOrUpdatedPolicies, + toBeRemovedPolicies, frame.sequenceNumber()); +} + RequestPtr ProtocolAdmin::extractRequestFromBuffer(BinaryQueue &bufferQueue) { - TODO_USE_ME(bufferQueue); - return RequestPtr(nullptr); + ProtocolFrameSerializer::deserializeHeader(m_frameHeader, bufferQueue); + + if (m_frameHeader.isFrameComplete()) { + ProtocolOpCode opCode; + + m_frameHeader.resetState(); + ProtocolDeserialization::deserialize(m_frameHeader, opCode); + LOGD("Deserialized opCode [%u]", static_cast(opCode)); + switch (opCode) { + case OpInsertOrUpdateBucket: + return deserializeInsertOrUpdateBucketRequest(m_frameHeader); + case OpRemoveBucket: + return deserializeRemoveBucketRequest(m_frameHeader); + case OpSetPolicies: + return deserializeSetPoliciesRequest(m_frameHeader); + default: + throw InvalidProtocolException(InvalidProtocolException::WrongOpCode); + break; + } + } + + return nullptr; +} + +ResponsePtr ProtocolAdmin::deserializeCodeResponse(ProtocolFrameHeader &frame) { + ProtocolResponseCode responseCode; + ProtocolDeserialization::deserialize(frame, responseCode); + + LOGD("Deserialized CodeResponse: code [%u], ", static_cast(responseCode)); + + return std::make_shared(static_cast(responseCode), + frame.sequenceNumber()); } ResponsePtr ProtocolAdmin::extractResponseFromBuffer(BinaryQueue &bufferQueue) { - TODO_USE_ME(bufferQueue); - return ResponsePtr(nullptr); + ProtocolFrameSerializer::deserializeHeader(m_frameHeader, bufferQueue); + + if (m_frameHeader.isFrameComplete()) { + ProtocolOpCode opCode; + + m_frameHeader.resetState(); + ProtocolDeserialization::deserialize(m_frameHeader, opCode); + LOGD("Deserialized opCode [%u]", static_cast(opCode)); + switch (opCode) { + case OpCodeResponse: + return deserializeCodeResponse(m_frameHeader); + default: + throw InvalidProtocolException(InvalidProtocolException::WrongOpCode); + break; + } + } + + return nullptr; +} + +void ProtocolAdmin::execute(RequestContextPtr context, InsertOrUpdateBucketRequestPtr request) { + LOGD("Serializing InsertOrUpdateBucketRequest: sequenceNumber [%u], bucketId <%s>, " + "result.type [%u], result.meta <%s>", + static_cast(request->sequenceNumber()), + request->bucketId().c_str(), + static_cast(request->result().policyType()), + request->result().metadata().c_str()); + + ProtocolFramePtr frame = ProtocolFrameSerializer::startSerialization(request->sequenceNumber()); + + ProtocolSerialization::serialize(*frame, OpInsertOrUpdateBucket); + ProtocolSerialization::serialize(*frame, request->bucketId()); + ProtocolSerialization::serialize(*frame, request->result().policyType()); + ProtocolSerialization::serialize(*frame, request->result().metadata()); + + ProtocolFrameSerializer::finishSerialization(frame, context->responseQueue()); +} + +void ProtocolAdmin::execute(RequestContextPtr context, RemoveBucketRequestPtr request) { + LOGD("Serializing RemoveBucketRequest: sequenceNumber [%u], bucketId <%s>", + static_cast(request->sequenceNumber()), request->bucketId().c_str()); + + ProtocolFramePtr frame = ProtocolFrameSerializer::startSerialization(request->sequenceNumber()); + + ProtocolSerialization::serialize(*frame, OpRemoveBucket); + ProtocolSerialization::serialize(*frame, request->bucketId()); + + ProtocolFrameSerializer::finishSerialization(frame, context->responseQueue()); +} + +void ProtocolAdmin::execute(RequestContextPtr context, SetPoliciesRequestPtr request) { + LOGD("Serializing SetPoliciesRequestPtr: sequenceNumber [%u], insertOrUpdate count [%zu]", + "remove count [%zu]", static_cast(request->sequenceNumber()), + request->policiesToBeInsertedOrUpdated().size(), + request->policiesToBeRemoved().size()); + + ProtocolFramePtr frame = + ProtocolFrameSerializer::startSerialization(request->sequenceNumber()); + + ProtocolSerialization::serialize(*frame, OpSetPolicies); + + ProtocolSerialization::serialize(*frame, + static_cast(request->policiesToBeInsertedOrUpdated().size())); + for (auto policyBucket : request->policiesToBeInsertedOrUpdated()) { + ProtocolSerialization::serialize(*frame, policyBucket.first); + ProtocolSerialization::serialize(*frame, + static_cast(policyBucket.second.size())); + for (auto policy : policyBucket.second) { + // PolicyKey + ProtocolSerialization::serialize(*frame, policy.key().client().value()); + ProtocolSerialization::serialize(*frame, policy.key().user().value()); + ProtocolSerialization::serialize(*frame, policy.key().privilege().value()); + // PolicyResult + ProtocolSerialization::serialize(*frame, policy.result().policyType()); + ProtocolSerialization::serialize(*frame, policy.result().metadata()); + } + } + + ProtocolSerialization::serialize(*frame, + static_cast(request->policiesToBeRemoved().size())); + for (auto policyBucket : request->policiesToBeRemoved()) { + ProtocolSerialization::serialize(*frame, policyBucket.first); + ProtocolSerialization::serialize(*frame, + static_cast(policyBucket.second.size())); + for (auto policyKey : policyBucket.second) { + // PolicyKey + ProtocolSerialization::serialize(*frame, policyKey.client().value()); + ProtocolSerialization::serialize(*frame, policyKey.user().value()); + ProtocolSerialization::serialize(*frame, policyKey.privilege().value()); + } + } + + ProtocolFrameSerializer::finishSerialization(frame, context->responseQueue()); +} + +void ProtocolAdmin::execute(RequestContextPtr context, CodeResponsePtr response) { + LOGD("Serializing CodeResponse: sequenceNumber [%u], code [%u]", + static_cast(response->sequenceNumber()), + static_cast(response->m_code)); + + ProtocolFramePtr frame = ProtocolFrameSerializer::startSerialization( + response->sequenceNumber()); + + ProtocolSerialization::serialize(*frame, OpCodeResponse); + ProtocolSerialization::serialize(*frame, static_cast(response->m_code)); + + ProtocolFrameSerializer::finishSerialization(frame, context->responseQueue()); } } // namespace Cynara diff --git a/src/common/protocol/ProtocolAdmin.h b/src/common/protocol/ProtocolAdmin.h index ccd2843..00dd67a 100644 --- a/src/common/protocol/ProtocolAdmin.h +++ b/src/common/protocol/ProtocolAdmin.h @@ -16,6 +16,7 @@ /* * @file ProtocolAdmin.h * @author Lukasz Wojciechowski + * @author Adam Malinowski * @version 1.0 * @brief This file defines protocol class for administration */ @@ -36,6 +37,19 @@ public: virtual RequestPtr extractRequestFromBuffer(BinaryQueue &bufferQueue); virtual ResponsePtr extractResponseFromBuffer(BinaryQueue &bufferQueue); + + virtual void execute(RequestContextPtr context, InsertOrUpdateBucketRequestPtr request); + virtual void execute(RequestContextPtr context, RemoveBucketRequestPtr request); + virtual void execute(RequestContextPtr context, SetPoliciesRequestPtr request); + + virtual void execute(RequestContextPtr context, CodeResponsePtr response); + +private: + RequestPtr deserializeInsertOrUpdateBucketRequest(ProtocolFrameHeader &frame); + RequestPtr deserializeRemoveBucketRequest(ProtocolFrameHeader &frame); + RequestPtr deserializeSetPoliciesRequest(ProtocolFrameHeader &frame); + + ResponsePtr deserializeCodeResponse(ProtocolFrameHeader &frame); }; } // namespace Cynara diff --git a/src/common/protocol/ProtocolOpCode.h b/src/common/protocol/ProtocolOpCode.h index d797fee..dcbdff0 100644 --- a/src/common/protocol/ProtocolOpCode.h +++ b/src/common/protocol/ProtocolOpCode.h @@ -36,11 +36,10 @@ enum ProtocolOpCode : uint8_t { /** Opcodes 1 - 19 are reserved for future use */ /** Admin operations */ - OpInsertPolicy = 20, - OpDeletePolicy, - OpListPolicies, - OpBeginTransaction, - OpEndTransaction + OpInsertOrUpdateBucket = 20, + OpRemoveBucket, + OpSetPolicies, + OpCodeResponse }; } /* namespace Cynara */ diff --git a/src/common/types/ProtocolFields.h b/src/common/types/ProtocolFields.h index e370ba4..efeb59a 100644 --- a/src/common/types/ProtocolFields.h +++ b/src/common/types/ProtocolFields.h @@ -30,9 +30,11 @@ namespace Cynara { -typedef std::string ProtocolFrameSignature; +typedef uint16_t ProtocolFrameFieldsCount; typedef uint32_t ProtocolFrameLength; typedef uint16_t ProtocolFrameSequenceNumber; +typedef std::string ProtocolFrameSignature; +typedef uint16_t ProtocolResponseCode; } /* namespace Cynara */ -- 2.7.4 From 4cfb74dc334ad0f1177e5caba9636ec6313960e9 Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Mon, 21 Jul 2014 13:57:31 +0200 Subject: [PATCH 06/16] Use save() from Storage to save changes to database Save is needed after operations that change state of database: * setting policies; * updating or inserting a bucket; * removing bucket. Change-Id: If1eea5cbbc0b8144d3ce9786fa4cbe8c858b9893 --- src/service/logic/Logic.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/service/logic/Logic.cpp b/src/service/logic/Logic.cpp index cd6e410..739add2 100644 --- a/src/service/logic/Logic.cpp +++ b/src/service/logic/Logic.cpp @@ -91,7 +91,8 @@ bool Logic::check(RequestContextPtr context UNUSED, const PolicyKey &key, void Logic::execute(RequestContextPtr context, InsertOrUpdateBucketRequestPtr request) { m_storage->addOrUpdateBucket(request->bucketId(), request->result()); -//todo add saving to database + m_storage->save(); + context->returnResponse(context, std::make_shared(CodeResponse::Code::OK, request->sequenceNumber())); } @@ -100,7 +101,7 @@ void Logic::execute(RequestContextPtr context, RemoveBucketRequestPtr request) { auto code = CodeResponse::Code::OK; try { m_storage->deleteBucket(request->bucketId()); -//todo add saving to database + m_storage->save(); } catch (const BucketNotExistsException &ex) { code = CodeResponse::Code::NO_BUCKET; } catch (const DefaultBucketDeletionException &ex) { @@ -115,7 +116,7 @@ void Logic::execute(RequestContextPtr context, SetPoliciesRequestPtr request) { try { m_storage->insertPolicies(request->policiesToBeInsertedOrUpdated()); m_storage->deletePolicies(request->policiesToBeRemoved()); -//todo add saving to database + m_storage->save(); } catch (const BucketNotExistsException &ex) { code = CodeResponse::Code::NO_BUCKET; } -- 2.7.4 From f5c2d36446b40ed9dca8a3ef4c30161ca3545b5c Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Mon, 21 Jul 2014 14:26:23 +0200 Subject: [PATCH 07/16] Fix badly inceremented pointers Change-Id: I40790d15f973a6e7bfacefb39b307b2a7bd77510 --- src/admin/api/admin-api.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/admin/api/admin-api.cpp b/src/admin/api/admin-api.cpp index 5c2e2e6..70c5283 100644 --- a/src/admin/api/admin-api.cpp +++ b/src/admin/api/admin-api.cpp @@ -93,27 +93,28 @@ int cynara_admin_set_policies(struct cynara_admin *p_cynara_admin, }); try { - for (auto i = policies[0]; i; i++) { - if(!i->bucket || !i->client || !i->user || !i->privilege) + for (auto i = policies; *i; i++) { + if(!(*i)->bucket || !(*i)->client || !(*i)->user || !(*i)->privilege) return CYNARA_ADMIN_API_INVALID_PARAM; - switch (i->result) { + switch ((*i)->result) { case CYNARA_ADMIN_DELETE: - remove[i->bucket].push_back(key(i)); + remove[(*i)->bucket].push_back(key(*i)); break; case CYNARA_ADMIN_DENY: - insertOrUpdate[i->bucket].push_back(Cynara::Policy(key(i), + insertOrUpdate[(*i)->bucket].push_back(Cynara::Policy(key(*i), Cynara::PredefinedPolicyType::DENY)); break; case CYNARA_ADMIN_ALLOW: - insertOrUpdate[i->bucket].push_back(Cynara::Policy(key(i), + insertOrUpdate[(*i)->bucket].push_back(Cynara::Policy(key(*i), Cynara::PredefinedPolicyType::ALLOW)); break; case CYNARA_ADMIN_BUCKET: - insertOrUpdate[i->bucket].push_back(Cynara::Policy(key(i), + insertOrUpdate[(*i)->bucket].push_back(Cynara::Policy(key(*i), Cynara::PolicyResult( Cynara::PredefinedPolicyType::BUCKET, - i->result_extra ? i->result_extra : ""))); + (*i)->result_extra ? (*i)->result_extra + : ""))); break; default: return CYNARA_ADMIN_API_INVALID_PARAM; -- 2.7.4 From fbb418d58e87c59d9948d8058c3447365b4f27cb Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Mon, 21 Jul 2014 16:38:26 +0200 Subject: [PATCH 08/16] Fix problem with passing references to local objects References are changed to shared pointers. Change-Id: I8bdd52e1ba04ce6625cf42810c68d19cdf006ecd --- src/service/storage/BucketDeserializer.cpp | 4 ++-- src/service/storage/BucketDeserializer.h | 9 ++++++--- src/service/storage/InMemoryStorageBackend.cpp | 22 ++++++++++++---------- src/service/storage/InMemoryStorageBackend.h | 4 ++-- src/service/storage/StorageDeserializer.cpp | 10 ++++++---- src/service/storage/StorageDeserializer.h | 7 ++++--- src/service/storage/StorageSerializer.cpp | 16 +++++++++------- src/service/storage/StorageSerializer.h | 15 +++++---------- 8 files changed, 46 insertions(+), 41 deletions(-) diff --git a/src/service/storage/BucketDeserializer.cpp b/src/service/storage/BucketDeserializer.cpp index 1bfac50..7ba7d4b 100644 --- a/src/service/storage/BucketDeserializer.cpp +++ b/src/service/storage/BucketDeserializer.cpp @@ -41,9 +41,9 @@ PolicyCollection BucketDeserializer::loadPolicies(void) { PolicyCollection policies; // TODO: Get someone smart to do error checking on stream - for (std::size_t lineNum = 1; !m_inStream.eof(); ++lineNum) { + for (std::size_t lineNum = 1; !m_inStream->eof(); ++lineNum) { std::string line; - std::getline(m_inStream, line, StorageSerializer::recordSeparator()); + std::getline(*m_inStream, line, StorageSerializer::recordSeparator()); if (line.empty()) break; diff --git a/src/service/storage/BucketDeserializer.h b/src/service/storage/BucketDeserializer.h index 393991e..ad54100 100644 --- a/src/service/storage/BucketDeserializer.h +++ b/src/service/storage/BucketDeserializer.h @@ -22,7 +22,8 @@ #ifndef SRC_SERVICE_STORAGE_BUCKETDESERIALIZER_H_ #define SRC_SERVICE_STORAGE_BUCKETDESERIALIZER_H_ -#include +#include +#include #include #include @@ -33,14 +34,16 @@ namespace Cynara { class BucketDeserializer { public: - BucketDeserializer(std::istream &inStream) : m_inStream(inStream) {} + BucketDeserializer(std::shared_ptr inStream) : m_inStream(inStream) { + } + PolicyCollection loadPolicies(void); protected: static PolicyKey parseKey(const std::string &line, std::size_t &beginToken); private: - std::istream &m_inStream; + std::shared_ptr m_inStream; }; } /* namespace Cynara */ diff --git a/src/service/storage/InMemoryStorageBackend.cpp b/src/service/storage/InMemoryStorageBackend.cpp index 5d18219..d04a6ff 100644 --- a/src/service/storage/InMemoryStorageBackend.cpp +++ b/src/service/storage/InMemoryStorageBackend.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -50,7 +51,7 @@ void InMemoryStorageBackend::load(void) { std::string indexFilename = m_dbPath + m_indexFileName; try { - std::ifstream indexStream; + std::shared_ptr indexStream = std::make_shared(); openFileStream(indexStream, indexFilename); StorageDeserializer storageDeserializer(indexStream, @@ -81,7 +82,7 @@ void InMemoryStorageBackend::save(void) { } } - std::ofstream indexStream; + std::shared_ptr indexStream = std::make_shared(); openDumpFileStream(indexStream, m_dbPath + m_indexFileName); StorageSerializer storageSerializer(indexStream); @@ -176,20 +177,21 @@ void InMemoryStorageBackend::deleteLinking(const PolicyBucketId &bucketId) { } } -void InMemoryStorageBackend::openFileStream(std::ifstream &stream, const std::string &filename) { +void InMemoryStorageBackend::openFileStream(std::shared_ptr stream, + const std::string &filename) { // TODO: Consider adding exceptions to streams and handling them: // stream.exceptions(std::ifstream::failbit | std::ifstream::badbit); - stream.open(filename); + stream->open(filename); - if (!stream.is_open()) + if (!stream->is_open()) throw FileNotFoundException(filename); } -void InMemoryStorageBackend::openDumpFileStream(std::ofstream &stream, +void InMemoryStorageBackend::openDumpFileStream(std::shared_ptr stream, const std::string &filename) { - stream.open(filename, std::ofstream::out | std::ofstream::trunc); + stream->open(filename, std::ofstream::out | std::ofstream::trunc); - if (!stream.is_open()) { + if (!stream->is_open()) { throw CannotCreateFileException(filename); return; } @@ -198,7 +200,7 @@ void InMemoryStorageBackend::openDumpFileStream(std::ofstream &stream, std::shared_ptr InMemoryStorageBackend::bucketStreamOpener( const PolicyBucketId &bucketId) { std::string bucketFilename = m_dbPath + "_" + bucketId; - std::ifstream bucketStream; + std::shared_ptr bucketStream = std::make_shared(); try { openFileStream(bucketStream, bucketFilename); return std::make_shared(bucketStream); @@ -210,7 +212,7 @@ std::shared_ptr InMemoryStorageBackend::bucketStreamOpener( std::shared_ptr InMemoryStorageBackend::bucketDumpStreamOpener( const PolicyBucketId &bucketId) { std::string bucketFilename = m_dbPath + "_" + bucketId; - std::ofstream bucketStream; + std::shared_ptr bucketStream = std::make_shared(); openDumpFileStream(bucketStream, bucketFilename); return std::make_shared(bucketStream); diff --git a/src/service/storage/InMemoryStorageBackend.h b/src/service/storage/InMemoryStorageBackend.h index 5127bc6..be2ba54 100644 --- a/src/service/storage/InMemoryStorageBackend.h +++ b/src/service/storage/InMemoryStorageBackend.h @@ -60,10 +60,10 @@ public: virtual void deleteLinking(const PolicyBucketId &bucketId); protected: - void openFileStream(std::ifstream &stream, const std::string &filename); + void openFileStream(std::shared_ptr stream, const std::string &filename); std::shared_ptr bucketStreamOpener(const PolicyBucketId &bucketId); - void openDumpFileStream(std::ofstream &stream, const std::string &filename); + void openDumpFileStream(std::shared_ptr stream, const std::string &filename); std::shared_ptr bucketDumpStreamOpener(const PolicyBucketId &bucketId); private: diff --git a/src/service/storage/StorageDeserializer.cpp b/src/service/storage/StorageDeserializer.cpp index 66c8ff0..9b34e5f 100644 --- a/src/service/storage/StorageDeserializer.cpp +++ b/src/service/storage/StorageDeserializer.cpp @@ -21,6 +21,7 @@ */ #include +#include #include #include @@ -35,16 +36,17 @@ namespace Cynara { -StorageDeserializer::StorageDeserializer(std::istream &inStream, +StorageDeserializer::StorageDeserializer(std::shared_ptr inStream, BucketStreamOpener bucketStreamOpener) - : m_inStream(inStream), m_bucketStreamOpener(bucketStreamOpener) {} + : m_inStream(inStream), m_bucketStreamOpener(bucketStreamOpener) { +} void StorageDeserializer::initBuckets(Buckets &buckets) { buckets.clear(); - for (std::size_t lineNum = 1; !m_inStream.eof(); ++lineNum) { + for (std::size_t lineNum = 1; !m_inStream->eof(); ++lineNum) { std::string line; - std::getline(m_inStream, line, StorageSerializer::recordSeparator()); + std::getline(*m_inStream, line, StorageSerializer::recordSeparator()); if (line.empty()) break; diff --git a/src/service/storage/StorageDeserializer.h b/src/service/storage/StorageDeserializer.h index c3680c4..d186ff7 100644 --- a/src/service/storage/StorageDeserializer.h +++ b/src/service/storage/StorageDeserializer.h @@ -23,7 +23,7 @@ #define SRC_SERVICE_STORAGE_STORAGEDESERIALIZER_H_ #include -#include +#include #include #include @@ -40,7 +40,8 @@ class StorageDeserializer { public: typedef std::function(const std::string &)> BucketStreamOpener; - StorageDeserializer(std::istream &inStream, BucketStreamOpener m_bucketStreamOpener); + StorageDeserializer(std::shared_ptr inStream, + BucketStreamOpener m_bucketStreamOpener); void initBuckets(Buckets &buckets); void loadBuckets(Buckets &buckets); @@ -50,7 +51,7 @@ public: std::size_t &beginToken); private: - std::istream &m_inStream; + std::shared_ptr m_inStream; BucketStreamOpener m_bucketStreamOpener; }; diff --git a/src/service/storage/StorageSerializer.cpp b/src/service/storage/StorageSerializer.cpp index f46d48e..2572a3b 100644 --- a/src/service/storage/StorageSerializer.cpp +++ b/src/service/storage/StorageSerializer.cpp @@ -20,8 +20,9 @@ * @brief Implementation of Cynara::StorageSerializer methods */ +#include +#include #include -#include #include #include @@ -37,7 +38,8 @@ namespace Cynara { char StorageSerializer::m_fieldSeparator = ';'; char StorageSerializer::m_recordSeparator = '\n'; -StorageSerializer::StorageSerializer(std::ostream &os) : m_outStream(os) {} +StorageSerializer::StorageSerializer(std::shared_ptr os) : m_outStream(os) { +} void StorageSerializer::dump(const Buckets &buckets, BucketStreamOpener streamOpener) { @@ -72,17 +74,17 @@ void StorageSerializer::dump(const PolicyBucket& bucket) { } void StorageSerializer::dump(const PolicyKey &key) { - outStream() << key.toString(); + *m_outStream << key.toString(); } void StorageSerializer::dump(const PolicyType &policyType) { - auto oldFormat = m_outStream.flags(); - outStream() << "0x" << std::uppercase << std::hex << policyType; - m_outStream.flags(oldFormat); + auto oldFormat = m_outStream->flags(); + *m_outStream << "0x" << std::uppercase << std::hex << policyType; + m_outStream->flags(oldFormat); } void StorageSerializer::dump(const PolicyResult::PolicyMetadata &metadata) { - outStream() << metadata; + *m_outStream << metadata; } void StorageSerializer::dump(const PolicyCollection::value_type &policy) { diff --git a/src/service/storage/StorageSerializer.h b/src/service/storage/StorageSerializer.h index 80966e9..f4397ba 100644 --- a/src/service/storage/StorageSerializer.h +++ b/src/service/storage/StorageSerializer.h @@ -24,8 +24,8 @@ #define SRC_SERVICE_STORAGE_STORAGESERIALIZER_H_ #include +#include #include -#include #include #include @@ -44,7 +44,7 @@ public: typedef std::function(const PolicyBucketId &)> BucketStreamOpener; - StorageSerializer(std::ostream &os); + StorageSerializer(std::shared_ptr os); virtual ~StorageSerializer() = default; virtual void dump(const Buckets &buckets, @@ -56,13 +56,13 @@ protected: inline void dumpFields(const Arg1 &arg1, const Args&... args) { dump(arg1); if (sizeof...(Args) > 0) { - outStream() << fieldSeparator(); + *m_outStream << fieldSeparator(); } dumpFields(args...); } inline void dumpFields(void) { - outStream() << recordSeparator(); + *m_outStream << recordSeparator(); } void dump(const PolicyKey &key); @@ -70,13 +70,8 @@ protected: void dump(const PolicyResult::PolicyMetadata &metadata); void dump(const PolicyCollection::value_type &policy); -protected: - std::ostream &outStream(void) { - return m_outStream; - } - private: - std::ostream &m_outStream; + std::shared_ptr m_outStream; static char m_fieldSeparator; static char m_recordSeparator; -- 2.7.4 From 9c59afbf788423139b359948874ced64ee314ccc Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Mon, 21 Jul 2014 17:54:03 +0200 Subject: [PATCH 09/16] Fix bug - change reference to object in CheckResponse Change-Id: I1a7754669db74e747c069be70d5593b478e9b28d --- src/common/response/CheckResponse.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/response/CheckResponse.h b/src/common/response/CheckResponse.h index 7d3ebc4..1f49648 100644 --- a/src/common/response/CheckResponse.h +++ b/src/common/response/CheckResponse.h @@ -33,7 +33,7 @@ namespace Cynara { class CheckResponse : public Response { public: - const PolicyResult &m_resultRef; + const PolicyResult m_resultRef; CheckResponse(const PolicyResult &result, ProtocolFrameSequenceNumber sequenceNumber) : Response(sequenceNumber), m_resultRef(result) { -- 2.7.4 From 50837dad71bab7fc4582749bf5ce35bed4788149 Mon Sep 17 00:00:00 2001 From: Adam Malinowski Date: Mon, 21 Jul 2014 18:23:50 +0200 Subject: [PATCH 10/16] Fix cynara service and local state directory labeling with smack Change-Id: I08c3fdbc118d566a3e9fb4b4b340ba3c2323d71a --- packaging/cynara.manifest | 2 +- packaging/cynara.spec | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packaging/cynara.manifest b/packaging/cynara.manifest index a76fdba..f31de52 100644 --- a/packaging/cynara.manifest +++ b/packaging/cynara.manifest @@ -1,5 +1,5 @@ - + diff --git a/packaging/cynara.spec b/packaging/cynara.spec index 11c630b..0b02d91 100644 --- a/packaging/cynara.spec +++ b/packaging/cynara.spec @@ -125,6 +125,8 @@ if [ $1 = 1 ]; then systemctl enable %{name}.service fi +chsmack -a System %{state_path} + systemctl restart %{name}.service /sbin/ldconfig -- 2.7.4 From 17d3725ca897beb78ddc9d2a9bac576e91c01240 Mon Sep 17 00:00:00 2001 From: Adam Malinowski Date: Mon, 21 Jul 2014 18:25:49 +0200 Subject: [PATCH 11/16] Release version 0.1.0 Change-Id: I5b4cc3fe87e4ea0af46e7a73a58e9b20b760f8d6 --- packaging/cynara.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/cynara.spec b/packaging/cynara.spec index 0b02d91..fce3588 100644 --- a/packaging/cynara.spec +++ b/packaging/cynara.spec @@ -1,6 +1,6 @@ Name: cynara Summary: Cynara service with client libraries -Version: 0.0.1 +Version: 0.1.0 Release: 1 Group: Security/Access Control License: Apache-2.0 -- 2.7.4 From 26e7c427a80ab231d15b683d21fec305ef412605 Mon Sep 17 00:00:00 2001 From: Adam Malinowski Date: Tue, 22 Jul 2014 10:52:36 +0200 Subject: [PATCH 12/16] Add 'default-ac-domains' package dependency in spec file This dependency is needed for using System domain for cynara service. Change-Id: Ib0c21e3375309f25c893289fd1271b84798fdb85 --- packaging/cynara.spec | 1 + 1 file changed, 1 insertion(+) diff --git a/packaging/cynara.spec b/packaging/cynara.spec index fce3588..b68e6dc 100644 --- a/packaging/cynara.spec +++ b/packaging/cynara.spec @@ -8,6 +8,7 @@ Source0: %{name}-%{version}.tar.gz Source1001: cynara.manifest Source1002: libcynara-client.manifest Source1003: libcynara-admin.manifest +Requires: default-ac-domains BuildRequires: cmake BuildRequires: zip BuildRequires: pkgconfig(libsystemd-daemon) -- 2.7.4 From c1f8603272ec4083fbe3f4fb267d1bd7654c7b36 Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Tue, 22 Jul 2014 08:48:55 +0200 Subject: [PATCH 13/16] Fix parameter checking when setting bucket-pointing policy Field result_extra in cynara_admin_policy structure should contain another bucket's name in case of insertion or update of a policy pointing to another bucket. There was no check for that. In case a nullptr was passed, it was converted to an empty string "". Now cynara_admin_set_policies returns CYNARA_ADMIN_API_INVALID_PARAM when result is set to CYNARA_ADMIN_BUCKET and result_extra is nullptr. Change-Id: I24ff5ab662e88b7bc538368385e13d78f48f9e9a --- src/admin/api/admin-api.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/admin/api/admin-api.cpp b/src/admin/api/admin-api.cpp index 70c5283..4087e40 100644 --- a/src/admin/api/admin-api.cpp +++ b/src/admin/api/admin-api.cpp @@ -110,11 +110,12 @@ int cynara_admin_set_policies(struct cynara_admin *p_cynara_admin, Cynara::PredefinedPolicyType::ALLOW)); break; case CYNARA_ADMIN_BUCKET: + if (!(*i)->result_extra) + return CYNARA_ADMIN_API_INVALID_PARAM; insertOrUpdate[(*i)->bucket].push_back(Cynara::Policy(key(*i), Cynara::PolicyResult( Cynara::PredefinedPolicyType::BUCKET, - (*i)->result_extra ? (*i)->result_extra - : ""))); + (*i)->result_extra))); break; default: return CYNARA_ADMIN_API_INVALID_PARAM; -- 2.7.4 From ea25549b696469d62378a2334a06ffc12a934952 Mon Sep 17 00:00:00 2001 From: Adam Malinowski Date: Fri, 25 Jul 2014 11:01:14 +0200 Subject: [PATCH 14/16] Correct exception catching Exception should be caught by reference. Change-Id: I19e906aa892956b783f174f6d40c63b4320cda93 --- src/admin/api/admin-api.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/admin/api/admin-api.cpp b/src/admin/api/admin-api.cpp index 4087e40..ac10e26 100644 --- a/src/admin/api/admin-api.cpp +++ b/src/admin/api/admin-api.cpp @@ -121,7 +121,7 @@ int cynara_admin_set_policies(struct cynara_admin *p_cynara_admin, return CYNARA_ADMIN_API_INVALID_PARAM; } } - } catch (std::bad_alloc ex) { + } catch (const std::bad_alloc &ex) { return CYNARA_ADMIN_API_OUT_OF_MEMORY; } @@ -139,7 +139,7 @@ int cynara_admin_set_bucket(struct cynara_admin *p_cynara_admin, const char *buc std::string extraStr; try { extraStr = extra ? extra : ""; - } catch (std::bad_alloc ex) { + } catch (const std::bad_alloc &ex) { return CYNARA_ADMIN_API_OUT_OF_MEMORY; } switch (operation) { -- 2.7.4 From cea2cf9937ab5b8c6de3ec373f361bc805c12c21 Mon Sep 17 00:00:00 2001 From: Adam Malinowski Date: Fri, 25 Jul 2014 14:56:46 +0200 Subject: [PATCH 15/16] Fix implementation of what() method in Exception class Change-Id: Ib0259dbd85bc5526b474396ac82b819f0b03b54d --- src/common/exceptions/Exception.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/common/exceptions/Exception.h b/src/common/exceptions/Exception.h index 92546b2..b709060 100644 --- a/src/common/exceptions/Exception.h +++ b/src/common/exceptions/Exception.h @@ -36,13 +36,17 @@ public: virtual ~Exception() = default; virtual const char *what(void) const noexcept { - return (message() + " From: " + m_backtrace).c_str(); + if(m_whatMessage.empty()) { + m_whatMessage = message() + " From: " + m_backtrace; + } + return m_whatMessage.c_str(); } virtual const std::string message(void) const = 0; private: std::string m_backtrace; + mutable std::string m_whatMessage; }; } /* namespace Cynara */ -- 2.7.4 From 0b53fd2b841d05d0f588a60ae160385ed1d21f59 Mon Sep 17 00:00:00 2001 From: Adam Malinowski Date: Fri, 25 Jul 2014 11:17:36 +0200 Subject: [PATCH 16/16] Remove unneeded return statement Change-Id: Ib500dd5249cbe37adbab441bb6700fb8554e3c18 --- src/service/storage/InMemoryStorageBackend.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/service/storage/InMemoryStorageBackend.cpp b/src/service/storage/InMemoryStorageBackend.cpp index d04a6ff..bf1c1c9 100644 --- a/src/service/storage/InMemoryStorageBackend.cpp +++ b/src/service/storage/InMemoryStorageBackend.cpp @@ -193,7 +193,6 @@ void InMemoryStorageBackend::openDumpFileStream(std::shared_ptr s if (!stream->is_open()) { throw CannotCreateFileException(filename); - return; } } -- 2.7.4