Apply plugin architecture 68/172668/3
authorsangwan.kwon <sangwan.kwon@samsung.com>
Tue, 13 Mar 2018 08:47:45 +0000 (17:47 +0900)
committersangwan kwon <sangwan.kwon@samsung.com>
Wed, 4 Apr 2018 02:08:31 +0000 (02:08 +0000)
Rule #1. Default sw-backend is supported.
Rule #2. tz-backend's priority is higher than sw-backend.
Rule #3. For support tz-backend, install tz-backend to plugin path.

Change-Id: I0e5ad3abf0ad437bb5b5a75e55b71d899530895d
Signed-off-by: sangwan.kwon <sangwan.kwon@samsung.com>
15 files changed:
CMakeLists.txt
packaging/auth-fw.spec
src/dpl/core/include/dpl/singleton.h
src/server/CMakeLists.txt
src/server/plugin/CMakeLists.txt
src/server/plugin/generic-backend/ipassword-file.h
src/server/plugin/sw-backend/password-file.cpp
src/server/service/include/password-manager.h
src/server/service/include/plugin-loader.h [new file with mode: 0644]
src/server/service/include/plugin-manager.h [new file with mode: 0644]
src/server/service/password-manager.cpp
src/server/service/plugin-loader.cpp [new file with mode: 0644]
src/server/service/plugin-manager.cpp [new file with mode: 0644]
tests/CMakeLists.txt
tests/test-sw-backend.cpp [new file with mode: 0644]

index 28250e3673f4e8b833358edea1afc5f1da1e10d8..3ac53dd9a7e3124f7bf6b494221b8f65fdb12be1 100644 (file)
@@ -58,6 +58,8 @@ ADD_DEFINITIONS("-DSOCK_PASSWD_CHECK=\"${SOCK_PASSWD_CHECK}\"")
 ADD_DEFINITIONS("-DSOCK_PASSWD_SET=\"${SOCK_PASSWD_SET}\"")
 ADD_DEFINITIONS("-DSOCK_PASSWD_RESET=\"${SOCK_PASSWD_RESET}\"")
 ADD_DEFINITIONS("-DSOCK_PASSWD_POLICY=\"${SOCK_PASSWD_POLICY}\"")
+ADD_DEFINITIONS("-DPLUGIN_SW_BACKEND_PATH=\"${PLUGIN_SW_BACKEND_PATH}\"")
+ADD_DEFINITIONS("-DPLUGIN_TZ_BACKEND_PATH=\"${PLUGIN_TZ_BACKEND_PATH}\"")
 
 IF (CMAKE_BUILD_TYPE MATCHES "DEBUG")
     ADD_DEFINITIONS("-DBUILD_TYPE_DEBUG")
index ac6eba0d4d8702276394a10d15b38fa98a211961..c340614f31c3688da1290fc76f7de39e05af5aeb 100644 (file)
@@ -28,6 +28,7 @@ Authentication framework which is consist of client library and server daemon
 # image creation error occured if /usr/sbin used for ldconfig
 #%global sbin_dir %{?TZ_SYS_SBIN:%TZ_SYS_SBIN}%{!?TZ_SYS_SBIN:%_sbindir}
 %global sbin_dir /sbin
+%global plugin_dir %{_datadir}/auth-fw
 %global rw_data_dir %{?TZ_SYS_DATA:%TZ_SYS_DATA/%name}%{!?TZ_SYS_DATA:/opt/data/%name}
 %global sock_passwd_check %{name}-passwd-check.socket
 %global sock_passwd_set %{name}-passwd-set.socket
@@ -82,6 +83,9 @@ export LDFLAGS+="-Wl,--rpath=%{_libdir}"
         -DSYS_CONFIG_DIR:PATH=%{_sysconfdir} \
         -DRUN_DIR:PATH=%{run_dir} \
         -DRW_DATA_DIR:PATH=%{rw_data_dir} \
+        -DPLUGIN_DIR:PATH=%{plugin_dir} \
+        -DPLUGIN_SW_BACKEND_PATH=%{plugin_dir}/lib%{name}-sw-backend.so.%{version} \
+        -DPLUGIN_TZ_BACKEND_PATH=%{plugin_dir}/lib%{name}-tz-backend.so.%{version} \
         -DSYSTEMD_UNIT_DIR:PATH=%{_unitdir} \
         -DINCLUDE_DIR:PATH=%{_includedir} \
         -DSOCK_PASSWD_CHECK=%{sock_passwd_check} \
@@ -170,7 +174,6 @@ fi
 %files -n lib%{name}-client-devel
 %{_libdir}/lib%{name}-client.so
 %{_libdir}/lib%{name}-client-admin.so
-%{_libdir}/lib%{name}-sw-backend.so
 %{_libdir}/lib%{name}-commons.so
 %{_includedir}/%{name}/auth-passwd.h
 %{_includedir}/%{name}/auth-passwd-admin.h
@@ -193,7 +196,8 @@ SW-Backend for authentication framework
 %files -n lib%{name}-sw-backend
 %manifest lib%{name}-sw-backend.manifest
 %license LICENSE
-%{_libdir}/lib%{name}-sw-backend.so.*
+%{plugin_dir}/lib%{name}-sw-backend.so
+%{plugin_dir}/lib%{name}-sw-backend.so.*
 
 ## Test Package ##############################################################
 %package test
index d3e17bf98a2d9a401a8205ec4047eb6c71865414..941d3a68a7ebb3bb11221bc48d53dc599c5c4429 100644 (file)
 #ifndef AUTHPASSWD_SINGLETON_H
 #define AUTHPASSWD_SINGLETON_H
 
+#include <symbol-visibility.h>
+
 namespace AuthPasswd {
 template<typename Class>
-class Singleton :
+class COMMON_API Singleton :
        private Class {
        //
        // Note:
index 5a26071891729bd1a7b6e2d03be35cfb4d666175..71060528d4a0d189d4d6e6f551867e82c313f1e0 100644 (file)
@@ -2,7 +2,6 @@ PKG_CHECK_MODULES(SERVER_DEP
     REQUIRED
     libsmack
     libsystemd-daemon
-    openssl
     )
 
 FIND_PACKAGE(Threads REQUIRED)
@@ -29,10 +28,9 @@ SET(SERVER_SOURCES
     service/password-manager.cpp
     service/policy-file.cpp
     service/policy-manager.cpp
+    service/plugin-loader.cpp
+    service/plugin-manager.cpp
     plugin/generic-backend/password-file-buffer.cpp
-
-    # TODO: Replace with dynamic load. (Temporary included for TDD)
-    plugin/sw-backend/password-file.cpp
     )
 
 SET_SOURCE_FILES_PROPERTIES(${SERVER_SOURCES}
index cd06ced0ac97369788b8afb4d0dffcde6c577ca3..9047e90055171654cbdda7b0c1cbad4eea772565 100644 (file)
@@ -3,8 +3,6 @@ PKG_CHECK_MODULES(SW_BACKEND_DEP
     openssl
     )
 
-FIND_PACKAGE(Threads REQUIRED)
-
 INCLUDE_DIRECTORIES(
     SYSTEM
     ${SW_BACKEND_DEP_INCLUDE_DIRS}
@@ -32,4 +30,4 @@ SET_TARGET_PROPERTIES(
 
 TARGET_LINK_LIBRARIES(${TARGET_SW_BACKEND} ${SW_BACKEND_DEP_LIBRARIES} ${TARGET_COMMON})
 
-INSTALL(TARGETS ${TARGET_SW_BACKEND} DESTINATION ${LIB_INSTALL_DIR})
+INSTALL(TARGETS ${TARGET_SW_BACKEND} DESTINATION ${PLUGIN_DIR})
index 466d23bca880d6e49695ebdd50f6a632f1337bc0..e9c70c2bd3df3cc38c357a16d755412fe09eea00 100644 (file)
@@ -61,7 +61,7 @@ struct IPasswordFile {
        virtual bool isHistoryActive() const = 0;
 };
 
-using PasswordFileFactory = IPasswordFile* (*)(unsigned int);
+using PasswordFileFactory = AuthPasswd::IPasswordFile* (*)(unsigned int);
 
 } //namespace AuthPasswd
 
index e92a3b2660df31c6acd2080d477a9141d467544d..22a30f054d1a6d5c1b5b068ff571ff8e5daa84b8 100644 (file)
 #include <password-exception.h>
 #include <generic-backend/password-file-buffer.h>
 
+extern "C" {
+
+AuthPasswd::IPasswordFile* PasswordFileFactory(unsigned int user)
+{
+       return new AuthPasswd::SWBackend::PasswordFile(user);
+}
+
+} // extern "C"
+
 namespace {
 const std::string PASSWORD_FILE = "/password";
 const std::string OLD_VERSION_PASSWORD_FILE = "/password.old";
index edb45f4f34180d63c136ea5382987bf132b36fd3..b0b604aaac8b1ce02ee34bf7f6d36faafe5f8e82 100644 (file)
 #include <map>
 #include <memory>
 
+#include <plugin-manager.h>
+
 #include <generic-backend/ipassword-file.h>
 
 namespace AuthPasswd {
-class PasswordManager {
+class PasswordManager final {
 public:
        typedef std::map<unsigned int, std::shared_ptr<IPasswordFile>> PasswordFileMap;
 
+       PasswordManager();
+       ~PasswordManager() = default;
+
        //checking functions
        //no const in checkPassword, attempts are update
        int checkPassword(unsigned int passwdType, const std::string &challenge,
@@ -70,6 +75,9 @@ private:
        void existPassword(unsigned int user);
 
        PasswordFileMap m_pwdFile;
+       PasswordFileFactory m_factory = nullptr;
+
+       PluginManager m_pluginManager;
 };
 } //namespace AuthPasswd
 
diff --git a/src/server/service/include/plugin-loader.h b/src/server/service/include/plugin-loader.h
new file mode 100644 (file)
index 0000000..d5f1491
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ *  Copyright (c) 2018 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        plugin-loader.h
+ * @author      Sangwan Kwon(sangwan.kwon@samsung.com)
+ * @version     1.0
+ * @brief       Plugin loader for loading backend.
+ */
+#pragma once
+
+#include <string>
+#include <stdexcept>
+
+#include <dlfcn.h>
+
+namespace AuthPasswd {
+
+class PluginLoader final {
+public:
+       explicit PluginLoader(const std::string& path, int flag = RTLD_LAZY);
+       ~PluginLoader();
+
+       PluginLoader(const PluginLoader&) = delete;
+       PluginLoader& operator=(const PluginLoader&) = delete;
+
+       PluginLoader(PluginLoader&&) = delete;
+       PluginLoader& operator=(PluginLoader&&) = delete;
+
+       template<typename T>
+       void load(const std::string& name, T& symbol);
+
+private:
+       void* m_handle;
+};
+
+template<typename T>
+void PluginLoader::load(const std::string& name, T& symbol)
+{
+       symbol = reinterpret_cast<T>(::dlsym(m_handle, name.c_str()));
+       if (symbol == nullptr)
+               throw std::runtime_error("Failed to load: " + name);
+}
+
+} //namespace AuthPasswd
diff --git a/src/server/service/include/plugin-manager.h b/src/server/service/include/plugin-manager.h
new file mode 100644 (file)
index 0000000..a0e59d9
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ *  Copyright (c) 2018 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        plugin-manager.h
+ * @author      Sangwan Kwon(sangwan.kwon@samsung.com)
+ * @version     1.0
+ * @brief       Plugin manager for binding backend.
+ */
+#pragma once
+
+#include <string>
+#include <memory>
+
+#include <plugin-loader.h>
+
+namespace AuthPasswd {
+
+enum class BackendType {
+       SW,
+       TZ
+};
+
+class PluginManager final {
+public:
+       explicit PluginManager() noexcept = default;
+       ~PluginManager() = default;
+
+       PluginManager(const PluginManager&) = delete;
+       PluginManager& operator=(const PluginManager&) = delete;
+
+       PluginManager(PluginManager&&) = delete;
+       PluginManager& operator=(PluginManager&&) = delete;
+
+       bool isSupport(BackendType type) const noexcept;
+
+       void setBackend(BackendType type);
+
+       template<typename T>
+       void loadFactory(const std::string& name, T& factory);
+
+private:
+       std::string getPluginPath(BackendType type) const noexcept;
+
+       std::shared_ptr<PluginLoader> m_loader = nullptr;
+};
+
+template<typename T>
+void PluginManager::loadFactory(const std::string& name, T& factory)
+{
+       m_loader->load(name, factory);
+}
+
+} //namespace AuthPasswd
index 4cd403a3506b77681cb324bf69c8e1055b1c0509..73dbcc185b71d722d288d898a6d3fb0a45fb6243 100644 (file)
@@ -39,9 +39,6 @@
 
 #include <policy.h>
 
-// TODO(sangwan.kwon): Replace with dynamic load.
-#include <sw-backend/password-file.h>
-
 namespace {
 void calculateExpiredTime(unsigned int receivedDays, time_t &validSecs)
 {
@@ -55,19 +52,26 @@ void calculateExpiredTime(unsigned int receivedDays, time_t &validSecs)
        validSecs = (curTime + (receivedDays * 86400));
        return;
 }
+} //namespace
 
-AuthPasswd::IPasswordFile* CreatePasswordFile(unsigned int user)
+namespace AuthPasswd {
+
+PasswordManager::PasswordManager()
 {
-       return new AuthPasswd::SWBackend::PasswordFile(user);
-}
+       if (m_pluginManager.isSupport(BackendType::TZ)) {
+               m_pluginManager.setBackend(BackendType::TZ);
+               LogDebug("Success to set TZ-Backend.");
+       } else {
+               m_pluginManager.setBackend(BackendType::SW);
+               LogDebug("Success to set SW-Backend.");
+       }
 
-} //namespace
+       m_pluginManager.loadFactory("PasswordFileFactory", m_factory);
+}
 
-namespace AuthPasswd {
 void PasswordManager::addPassword(unsigned int user)
 {
-       PasswordFileFactory factory = &CreatePasswordFile;
-       std::shared_ptr<IPasswordFile> passwordFile((*factory)(user));
+       std::shared_ptr<IPasswordFile> passwordFile((*m_factory)(user));
        m_pwdFile.insert(PasswordFileMap::value_type(user, passwordFile));
 }
 
diff --git a/src/server/service/plugin-loader.cpp b/src/server/service/plugin-loader.cpp
new file mode 100644 (file)
index 0000000..8face74
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ *  Copyright (c) 2018 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        plugin-loader.cpp
+ * @author      Sangwan Kwon(sangwan.kwon@samsung.com)
+ * @version     1.0
+ * @brief       Implementation of plugin loader.
+ */
+#include <plugin-loader.h>
+
+namespace AuthPasswd {
+
+PluginLoader::PluginLoader(const std::string& path, int flag)
+       : m_handle(::dlopen(path.c_str(), flag))
+{
+       if (m_handle == nullptr)
+               throw std::invalid_argument("Failed to open: " + path);
+}
+
+PluginLoader::~PluginLoader()
+{
+       ::dlclose(m_handle);
+}
+
+} // namespace AuthPasswd
diff --git a/src/server/service/plugin-manager.cpp b/src/server/service/plugin-manager.cpp
new file mode 100644 (file)
index 0000000..1a50fc5
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ *  Copyright (c) 2018 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        plugin-manager.cpp
+ * @author      Sangwan Kwon(sangwan.kwon@samsung.com)
+ * @version     1.0
+ * @brief       Implementation of plugin manager.
+ */
+#include <plugin-manager.h>
+
+#include <fstream>
+
+namespace AuthPasswd {
+
+bool PluginManager::isSupport(BackendType type) const noexcept
+{
+       if (std::ifstream(this->getPluginPath(type)))
+               return true;
+       else
+               return false;
+}
+
+void PluginManager::setBackend(BackendType type)
+{
+       m_loader = std::make_shared<PluginLoader>(this->getPluginPath(type));
+}
+
+std::string PluginManager::getPluginPath(BackendType type) const noexcept
+{
+       if (type == BackendType::SW)
+               return PLUGIN_SW_BACKEND_PATH;
+       else
+               return PLUGIN_TZ_BACKEND_PATH;
+}
+
+} //namespace AuthPasswd
index 99566fec69e1f82411c2af19991ed9baa7819adb..64746c6cd3fea589ee9d499d66dafe9956ff7dae 100644 (file)
 SET(TEST_SRCS main.cpp
                          test-util.cpp
                          test-client.cpp
-                         test-admin.cpp)
+                         test-admin.cpp
+                         test-sw-backend.cpp
+
+                         ${SERVER_PATH}/service/plugin-loader.cpp
+                         ${SERVER_PATH}/service/plugin-manager.cpp)
 
 PKG_CHECK_MODULES(${TARGET_TEST}_DEP REQUIRED klay)
 
 INCLUDE_DIRECTORIES(SYSTEM ${${TARGET_TEST}_DEP_INCLUDE_DIRS}
-                                                  ${INCLUDE_PATH})
+                                                  ${INCLUDE_PATH}
+                                                  ${SERVER_PATH}/service/include
+                                                  ${DPL_PATH}/core/include
+                                                  ${DPL_PATH}/log/include
+                                                  ${PLUGIN_PATH})
 
 ADD_EXECUTABLE(${TARGET_TEST} ${TEST_SRCS})
 
 TARGET_LINK_LIBRARIES(${TARGET_TEST} ${${TARGET_TEST}_DEP_LIBRARIES}
                                                                         ${TARGET_CLIENT}
-                                                                        ${TARGET_CLIENT_ADMIN})
+                                                                        ${TARGET_CLIENT_ADMIN}
+                                                                        ${TARGET_SW_BACKEND}
+                                                                        -ldl)
 
 SET_TARGET_PROPERTIES(${TARGET_TEST} PROPERTIES COMPILE_FLAGS "-fPIE")
 SET_TARGET_PROPERTIES(${TARGET_TEST} PROPERTIES LINK_FLAGS "-pie")
diff --git a/tests/test-sw-backend.cpp b/tests/test-sw-backend.cpp
new file mode 100644 (file)
index 0000000..605bbc5
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ *  Copyright (c) 2018 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        test-sw-backend.cpp
+ * @author      Sangwan Kwon (sangwan.kwon@samsung.com)
+ * @version     1.0
+ * @brief       Testcases of PasswordFile(SW-Backend)
+ */
+
+#include <klay/testbench.h>
+
+#include <plugin-manager.h>
+
+#include <generic-backend/ipassword-file.h>
+#include <sw-backend/password-file.h>
+
+using namespace AuthPasswd;
+
+TESTCASE(T00300_is_support)
+{
+       PluginManager pm;
+
+       TEST_EXPECT(true, pm.isSupport(BackendType::SW));
+       TEST_EXPECT(false, pm.isSupport(BackendType::TZ));
+}
+
+TESTCASE(T00301_bind_backend)
+{
+       PluginManager pm;
+       pm.setBackend(BackendType::SW);
+
+       PasswordFileFactory factory = nullptr;
+       pm.loadFactory("PasswordFileFactory", factory);
+
+       TEST_EXPECT(true, factory != nullptr);
+
+       std::shared_ptr<IPasswordFile> passwdFile((*factory)(5001));
+       TEST_EXPECT(true, passwdFile != nullptr);
+}