Use Cynara for access control 76/163276/1
authorJaroslaw Pelczar <j.pelczar@samsung.com>
Tue, 5 Dec 2017 07:35:42 +0000 (08:35 +0100)
committerJaroslaw Pelczar <j.pelczar@samsung.com>
Tue, 5 Dec 2017 09:03:36 +0000 (10:03 +0100)
Change-Id: I42e7aebfd0369301877e023ad5721547098b20df
Signed-off-by: Jaroslaw Pelczar <j.pelczar@samsung.com>
cmake/CheckFrameworks.cmake
dcm-daemon/CMakeLists.txt
dcm-daemon/cryptobackendroster.h
dcm-daemon/dcmsession.cpp
dcm-daemon/dcmsession.h
dcm-daemon/main.cpp
packaging/device-certificate-manager-tests.manifest.in
packaging/device-certificate-manager.spec

index 34ed41b..ef52463 100644 (file)
@@ -28,8 +28,6 @@ ENDIF()
 
 PKG_CHECK_MODULES(DLOG dlog)
 
-PKG_CHECK_MODULES(SECURITY_MANAGER security-manager)
-
 CHECK_FUNCTION_EXISTS(fork HAVE_FORK)
 
 find_package(Protobuf REQUIRED)
@@ -65,4 +63,6 @@ ENDIF()
 
 PKG_CHECK_MODULES(SYSTEMD libsystemd)
 
-PKG_CHECK_MODULES(SMACK libsmack)
+#### Cynara ####
+
+PKG_CHECK_MODULES(CYNARA cynara-client cynara-creds-socket cynara-session)
index 90f64a4..2c50e1c 100644 (file)
@@ -21,13 +21,6 @@ IF(DLOG_FOUND)
        add_definitions(-DUSE_DLOG_LOGGING=1)
 ENDIF(DLOG_FOUND)
 
-IF(SECURITY_MANAGER_FOUND)
-       include_directories(${SECURITY_MANAGER_INCLUDE_DIRS})
-       link_directories(${SECURITY_MANAGER_LIBRARY_DIRS})
-       add_definitions(${SECURITY_MANAGER_CFLAGS_OTHER})
-       add_definitions(-DUSE_SECURITY_MANAGER=1)
-ENDIF(SECURITY_MANAGER_FOUND)
-
 IF(ENABLE_SYSTEMD_SUPPORT)
        include_directories(${SYSTEMD_INCLUDE_DIRS})
        link_directories(${SYSTEMD_LIBRARY_DIRS})
@@ -41,12 +34,12 @@ IF(ARTIK_SECURITY_FOUND)
        add_definitions(-DUSE_ARTIK_SECURITY_HEADERS=1)
 ENDIF(ARTIK_SECURITY_FOUND)
 
-IF(SMACK_FOUND)
-       include_directories(${SMACK_INCLUDE_DIRS})
-       link_directories(${SMACK_LIBRARY_DIRS})
-       add_definitions(${SMACK_CFLAGS_OTHER})
-       add_definitions(-DUSE_SMACK=1)
-ENDIF(SMACK_FOUND)
+IF(CYNARA_FOUND)
+       include_directories(${CYNARA_INCLUDE_DIRS})
+       link_directories(${CYNARA_LIBRARY_DIRS})
+       add_definitions(${CYNARA_CFLAGS_OTHER})
+       add_definitions(-DUSE_CYNARA=1)
+ENDIF(CYNARA_FOUND)
 
 include_directories(${Boost_INCLUDE_DIRS})
 link_directories(${Boost_LIBRARY_DIRS})
@@ -60,11 +53,10 @@ add_subdirectory(see-backend)
 
 IF(ENABLE_DUMMY_BACKEND)
        SET(DUMMY_BACKEND_OBJECTS $<TARGET_OBJECTS:dummy_backend_objects>)
+       add_definitions(-DENABLE_DUMMY_BACKEND=1)
 ENDIF(ENABLE_DUMMY_BACKEND)
 
-IF(SECURITY_MANAGER_FOUND)
-       SET(SEE_BACKEND_OBJECTS $<TARGET_OBJECTS:see-backend>)
-ENDIF(SECURITY_MANAGER_FOUND)
+SET(SEE_BACKEND_OBJECTS $<TARGET_OBJECTS:see-backend>)
 
 ###### Main executable #######
 
@@ -107,17 +99,13 @@ IF(DLOG_FOUND)
        target_link_libraries(device-certificate-managerd ${DLOG_LIBRARIES})
 ENDIF(DLOG_FOUND)
 
-IF(SECURITY_MANAGER_FOUND)
-       target_link_libraries(device-certificate-managerd ${SECURITY_MANAGER_LIBRARIES})
-ENDIF(SECURITY_MANAGER_FOUND)  
-
 IF(ENABLE_SYSTEMD_SUPPORT)
        target_link_libraries(device-certificate-managerd ${SYSTEMD_LIBRARIES})
 ENDIF(ENABLE_SYSTEMD_SUPPORT)  
 
-IF(SMACK_FOUND)
-       target_link_libraries(device-certificate-managerd ${SMACK_LIBRARIES})
-ENDIF(SMACK_FOUND)
+IF(CYNARA_FOUND)
+       target_link_libraries(device-certificate-managerd ${CYNARA_LIBRARIES})
+ENDIF(CYNARA_FOUND)
 
 ###### Installation #######
 
index 2514412..3117136 100644 (file)
@@ -43,6 +43,9 @@ template<typename Klass> struct crypto_backend_registration {
        crypto_backend_registration() {
                crypto_backend_roster::instance().register_backend(std::make_shared<Klass>());
        }
+
+       void ensure_inited() {
+       }
 };
 
 #endif /* DCM_DAEMON_CRYPTOBACKENDROSTER_H_ */
index 9bdd07d..ad09839 100644 (file)
 #include <map>
 #include <mutex>
 
-#ifdef USE_SMACK
-#include <sys/smack.h>
+#ifdef USE_CYNARA
+#include <cynara-client.h>
+#include <cynara-creds-socket.h>
+#include <cynara-session.h>
 #endif
 
-#ifdef USE_SECURITY_MANAGER
-#include <security-manager.h>
-#endif
-
-#ifdef USE_SMACK
-static char const *const OWNER_ID_SYSTEM = "/System";
-#endif
+#ifdef USE_CYNARA
+extern cynara * gGlobalCynaraInstance;
 
-#if defined(USE_SECURITY_MANAGER) && defined(USE_SMACK)
-static std::map<std::string, std::string> sPackageIdMapping;
-static std::mutex sPackageIdMappingMutex;
+static inline std::string cynara_error_to_string(int error) {
+       char buffer[256];
+       int ret = cynara_strerror(error, buffer, sizeof(buffer));
+       if(ret == CYNARA_API_SUCCESS)
+               return std::string(buffer);
+       return std::string("Can't translate error");
+}
 #endif
 
 dcm_session::dcm_session(boost::asio::io_service& io_service, const std::shared_ptr<dcm_server>& server) :
@@ -61,136 +62,79 @@ dcm_session::~dcm_session()
        BOOST_LOG_SEV(dcm_logger::get(), log_severity::debug) << "Destroy session object " << this;
 }
 
-#if defined(USE_SMACK) && defined(USE_SECURITY_MANAGER)
-static int assignToString(std::vector<char> &vec, socklen_t len, std::string &res)
-{
-       if (vec.size() <= len)
-               return -1;
-       vec[len] = 0;    // old implementation getsockopt returns cstring without 0
-       if (vec[len - 1] == 0) --len;// new implementation of getsockopt returns cstring size+1
-       res.assign(vec.data(), len);
-       return 0;
-}
-
-static int getCredentialsFromSocket(int sock, std::string &res)
-{
-       std::vector<char> result(SMACK_LABEL_LEN + 1);
-       socklen_t length = SMACK_LABEL_LEN;
-
-       if (0 == getsockopt(sock, SOL_SOCKET, SO_PEERSEC, result.data(), &length)) {
-               return assignToString(result, length, res);
-       }
-
-       if (errno != ERANGE) {
-               BOOST_LOG_SEV(dcm_logger::get(), log_severity::error) << "getsockopt failed";
-               return -1;
+struct string_free_deleter {
+       void operator()(char * p) const {
+               free(p);
        }
+};
 
-       result.resize(length + 1);
-
-       if (0 > getsockopt(sock, SOL_SOCKET, SO_PEERSEC, result.data(), &length)) {
-               BOOST_LOG_SEV(dcm_logger::get(), log_severity::error)  << "getsockopt failed with errno: " << errno;
-               return -1;
-       }
-
-       return assignToString(result, length, res);
-}
-
-static int getPkgIdFromSocket(int sock, std::string &pkgId)
+bool dcm_session::verify_privileges(int handle)
 {
-       char *pkg = nullptr;
+#ifdef USE_CYNARA
+       BOOST_LOG_FUNCTION();
 
-       int ret = security_manager_identify_app_from_socket(sock, &pkg, nullptr);
+       int ret = 0;
+       char * tmp_str;
+       pid_t pid = 0;
 
-       if (ret == SECURITY_MANAGER_ERROR_NO_SUCH_OBJECT) {
-               BOOST_LOG_SEV(dcm_logger::get(), log_severity::error) << "Owner of socket is not connected with pkgid. "
-                               "This case must be special-labled client. e.g. User, System";
-               return 1;
-       }
+       std::unique_ptr<char, string_free_deleter> user;
+       std::unique_ptr<char, string_free_deleter> client;
+       std::unique_ptr<char, string_free_deleter> client_session;
 
-       if (ret != SECURITY_MANAGER_SUCCESS) {
-               BOOST_LOG_SEV(dcm_logger::get(), log_severity::error) << "security_manager_identify_app_from_socket failed with error: "
-                                << ret;
-               return -1;
+       /* Get user info */
+       tmp_str = nullptr;
+       ret = cynara_creds_socket_get_user(handle, USER_METHOD_DEFAULT, &tmp_str);
+       if(ret != CYNARA_API_SUCCESS) {
+               BOOST_LOG_SEV(dcm_logger::get(), log_severity::error) << "Can't get user from socket : " << ret << " - " << cynara_error_to_string(ret);
+               return false;
        }
+       user.reset(tmp_str);
 
-       try {
-               pkgId = pkg;
-       } catch(...) {
-               free(pkg);
-               throw;
+       /* Get client info */
+       tmp_str = nullptr;
+       ret = cynara_creds_socket_get_client(handle, CLIENT_METHOD_DEFAULT, &tmp_str);
+       if(ret != CYNARA_API_SUCCESS) {
+               BOOST_LOG_SEV(dcm_logger::get(), log_severity::error) << "Can't get client from socket : " << ret << " - " << cynara_error_to_string(ret);
+               return false;
        }
+       client.reset(tmp_str);
 
-       free(pkg);
-       BOOST_LOG_SEV(dcm_logger::get(), log_severity::debug) << "Socket: " << sock << " Was translated to owner id: " << pkgId;
-       return 0;
-}
-
-static void mapToDomainLabel(std::string &label)
-{
-       static const std::string subdomainSep = "::";
-       static const auto systemLabelLen = strlen(OWNER_ID_SYSTEM);
 
-       if (label.length() > systemLabelLen + subdomainSep.length() &&
-               label.compare(0, systemLabelLen, OWNER_ID_SYSTEM) == 0 &&
-               label.compare(systemLabelLen, subdomainSep.length(), subdomainSep) == 0) {
-               label = OWNER_ID_SYSTEM;
+       /* Get client PID from socket */
+       ret = cynara_creds_socket_get_pid(handle, &pid);
+       if(ret != CYNARA_API_SUCCESS) {
+               BOOST_LOG_SEV(dcm_logger::get(), log_severity::error) << "Can't get PID from socket : " << ret << " - " << cynara_error_to_string(ret);
+               return false;
        }
-}
-#endif
-
-bool dcm_session::get_client_id(int handle, std::string& result)
-{
-       BOOST_LOG_FUNCTION();
-
-#if defined(USE_SMACK) && defined(USE_SECURITY_MANAGER)
-       try {
-               std::string smackLabel;
-               int error = getCredentialsFromSocket(handle, smackLabel);
-
-               if(error < 0) {
-                       BOOST_LOG_SEV(dcm_logger::get(), log_severity::error) << "Socket access failure. Disconnecting";
-                       return false;
-               }
-
-               BOOST_LOG_SEV(dcm_logger::get(), log_severity::debug) << "Client credential is " << smackLabel;
-
-               std::unique_lock<std::mutex> locker(sPackageIdMappingMutex);
-
-               auto it = sPackageIdMapping.find(smackLabel);
 
-               if(it != sPackageIdMapping.end()) {
-                       result = it->second;
-                       return true;
-               }
-
-               std::string pkgId;
-               int retCode = getPkgIdFromSocket(handle, pkgId);
-
-               if (retCode < 0) {
-                       return false;
-               }
-
-               if (retCode == 1) {
-                       BOOST_LOG_SEV(dcm_logger::get(), log_severity::debug) << "Special smack label case. label: " << smackLabel;
-                       pkgId = "/" + smackLabel;
-               }
+       client_session.reset(cynara_session_from_pid(pid));
+       if(!client_session) {
+               BOOST_LOG_SEV(dcm_logger::get(), log_severity::error) << "Can't get session identifier from PID";
+               return false;
+       }
 
-               mapToDomainLabel(pkgId);
+       BOOST_LOG_SEV(dcm_logger::get(), log_severity::debug) << "Got new session from " << pid << " with user " <<
+                       user.get() << ", client ID " << client.get() << " and session ID " << client_session.get();
 
-               BOOST_LOG_SEV(dcm_logger::get(), log_severity::debug) << smackLabel << " mapped to " << pkgId;
+       ret = cynara_check(gGlobalCynaraInstance,
+                       client.get(),
+                       client_session.get(),
+                       user.get(),
+                       "http://tizen.org/privilege/internet");
 
-               result = pkgId;
-               sPackageIdMapping.emplace(std::move(smackLabel), std::move(pkgId));
+       if(ret != CYNARA_API_ACCESS_ALLOWED) {
+               BOOST_LOG_SEV(dcm_logger::get(), log_severity::error) <<
+                               "Application access denied - no internet permission for " <<
+                               pid <<
+                               " - " <<
+                               cynara_error_to_string(ret);
 
-               return true;
-       } catch(std::exception& ex) {
-               BOOST_LOG_SEV(dcm_logger::get(), log_severity::error) << "Caught exception when translating socket: " << ex.what();
-               return false;
-       } catch(...) {
-               BOOST_LOG_SEV(dcm_logger::get(), log_severity::error) << "Caught unknown exception when translating socket";
                return false;
        }
+
+       BOOST_LOG_SEV(dcm_logger::get(), log_severity::debug) << "Access granted for " << pid;
+#else
+       (void)handle;
 #endif
 
        return true;
@@ -204,8 +148,10 @@ void dcm_session::start()
        BOOST_LOG_SEV(dcm_logger::get(), log_severity::debug) << "Accepted connection with socket " << fSocket.native_handle();
 
        std::string label;
-       if(get_client_id(handle, label)) {
+       if(verify_privileges(handle)) {
                do_receive();
+       } else {
+               BOOST_LOG_SEV(dcm_logger::get(), log_severity::error) << "Client privilege check failure. Disconnect";
        }
 }
 
index a2458cf..7124247 100644 (file)
@@ -51,7 +51,7 @@ private:
        void decode_message() noexcept;
        void reply(const ResponseMessage& resp) noexcept;
 
-       bool get_client_id(int handle, std::string& result);
+       bool verify_privileges(int handle);
 
        void handle_context_association(const AssociateKeyContext& message);
        void handle_cert_chain(const RequestCertificateChain& message);
index e1f8fd2..e4ec56e 100644 (file)
 
 #include <boost_log_dlog_sink.h>
 
+#ifdef USE_CYNARA
+#include <cynara-client.h>
+#endif
+
 namespace po = boost::program_options;
 
 struct OptionContext {
@@ -124,8 +128,14 @@ void init_logging()
        boost::log::core::get()->add_thread_attribute("Scope", boost::log::attributes::named_scope());
 }
 
+#ifdef USE_CYNARA
+cynara * gGlobalCynaraInstance;
+#endif
+
 int main(int argc, char ** argv)
 {
+       int error = 0;
+
        init_logging();
 
        BOOST_LOG_FUNCTION();
@@ -150,6 +160,26 @@ int main(int argc, char ** argv)
 
        service_adapter serviceAdapter(options.fSocketName);
 
+#ifdef USE_CYNARA
+       cynara_configuration * cynara_conf = nullptr;
+       error = cynara_configuration_create(&cynara_conf);
+       if(error != CYNARA_API_SUCCESS) {
+               BOOST_LOG_SEV(dcm_logger::get(), log_severity::error) << "Can't initialize Cynara configuration: " << error;
+               serviceAdapter.notify_start_failure(error);
+               return EXIT_FAILURE;
+       }
+
+       error = cynara_initialize(&gGlobalCynaraInstance, cynara_conf);
+
+       cynara_configuration_destroy(cynara_conf);
+
+       if(error != CYNARA_API_SUCCESS) {
+               BOOST_LOG_SEV(dcm_logger::get(), log_severity::error) << "Can't initialize Cynara instance: " << error;
+               serviceAdapter.notify_start_failure(error);
+               return EXIT_FAILURE;
+       }
+#endif
+
        try {
                boost::asio::io_service io_service;
 
@@ -165,7 +195,7 @@ int main(int argc, char ** argv)
                (void)umask(0);
 
                /* Use root directory as working directory */
-               int error = chdir("/");
+               error = chdir("/");
                (void)error; // Don't care
 
                BOOST_LOG_SEV(dcm_logger::get(), log_severity::debug) << "Create platform socket";
@@ -198,6 +228,11 @@ int main(int argc, char ** argv)
                return EXIT_FAILURE;
        }
 
+#ifdef USE_CYNARA
+       cynara_finish(gGlobalCynaraInstance);
+       gGlobalCynaraInstance = nullptr;
+#endif
+
        BOOST_LOG_SEV(dcm_logger::get(), log_severity::normal) << "Server terminated";
 
        return 0;
index 3b8c320..9bd7968 100644 (file)
@@ -1,9 +1,14 @@
 <manifest>
+       <define>
+               <domain name="device-certificate-managert-test" />
+               <permit>
+                       <smack permit="system::use_internet" type="w" />
+               </permit>
+               <request>
+                       <smack request="system::use_internet" type="w" />
+               </request>
+       </define>
        <request>
-               <domain name="_" />
+               <domain name="device-certificate-managert-test" />
        </request>
-       <assign>
-               <filesystem path="@CMAKE_INSTALL_FULL_BINDIR@/dcm_example_client" exec_label="@SMACK_DOMAIN_NAME@" />
-               <filesystem path="@CMAKE_INSTALL_FULL_BINDIR@/dcm_hw_api_test" exec_label="@SMACK_DOMAIN_NAME@" />
-       </assign>
 </manifest>
index deafc29..0689971 100644 (file)
@@ -10,11 +10,12 @@ Source1002: device-certificate-manager-devel.manifest
 BuildRequires: cmake
 BuildRequires: pkgconfig(dlog)
 BuildRequires: pkgconfig(libsystemd-daemon)
-BuildRequires: pkgconfig(security-manager)
-BuildRequires: pkgconfig(libsmack)
 BuildRequires: pkgconfig(libtzplatform-config)
 BuildRequires: pkgconfig(iotivity)
 BuildRequires: pkgconfig(protobuf)
+BuildRequires: pkgconfig(cynara-client)
+BuildRequires: pkgconfig(cynara-creds-socket)
+BuildRequires: pkgconfig(cynara-session)
 BuildRequires: boost-devel
 BuildRequires: openssl
 Summary:       Device Certificate Manager