From: Pawel Andruszkiewicz Date: Tue, 17 Mar 2015 15:08:45 +0000 (+0100) Subject: [Common] Implementation of security access checks. X-Git-Tag: submit/tizen_tv/20150603.064601~1^2~279 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b976d7d508d27a9bec53ff35915d71d7c245e36f;p=platform%2Fcore%2Fapi%2Fwebapi-plugins.git [Common] Implementation of security access checks. Change-Id: I7d0460d274e957487a6fa54a21f4caa73525f311 --- diff --git a/packaging/webapi-plugins.spec b/packaging/webapi-plugins.spec index eadd7c3d..01d1a7f3 100755 --- a/packaging/webapi-plugins.spec +++ b/packaging/webapi-plugins.spec @@ -308,7 +308,7 @@ Tizen Web APIs implemented. %build export GYP_GENERATORS='ninja' -GYP_OPTIONS="--depth=. -Dtizen=1 -Dextension_build_type=Debug -Dextension_host_os=%{profile}" +GYP_OPTIONS="--depth=. -Dtizen=1 -Dextension_build_type=Debug -Dextension_host_os=%{profile} -Dprivilege_engine=DB" GYP_OPTIONS="$GYP_OPTIONS -Ddisplay_type=x11" # feature flags diff --git a/src/common/common.gypi b/src/common/common.gypi index d7698dff..a8ac6188 100644 --- a/src/common/common.gypi +++ b/src/common/common.gypi @@ -26,9 +26,35 @@ 'dlog', 'glib-2.0', 'capi-appfw-app-manager', - 'capi-appfw-package-manager' + 'capi-appfw-package-manager', ] }, + 'conditions': [ + ['privilege_engine == "DB"', { + 'defines': ['PRIVILEGE_USE_DB'], + 'variables': { + 'packages': [ + 'sqlite3', + ], + }, + }], + ['privilege_engine == "ACE"', { + 'defines': ['PRIVILEGE_USE_ACE'], + 'variables': { + 'packages': [ + 'sqlite3', + 'security-client', + ], + }, + }], + ['privilege_engine == "CYNARA"', { + 'defines': ['PRIVILEGE_USE_CYNARA'], + 'variables': { + 'packages': [ + ], + }, + }], + ], }, { 'sources/': [['exclude', '_tizen\\.cc$|tizen/']], 'includes/': [['exclude', '_tizen\\.gypi$|tizen/']], diff --git a/src/common/extension.cc b/src/common/extension.cc index de14fd8e..abd4cfb7 100644 --- a/src/common/extension.cc +++ b/src/common/extension.cc @@ -10,7 +10,18 @@ #include #include +#ifdef PRIVILEGE_USE_DB +#include +#elif PRIVILEGE_USE_ACE +#include +#include +#include +#elif PRIVILEGE_USE_CYNARA +// TODO +#endif + #include "common/logger.h" +#include "common/scope_exit.h" namespace { @@ -342,6 +353,255 @@ void ReportError(const PlatformResult& error, picojson::object* out) { out->insert(std::make_pair("status", picojson::value("error"))); out->insert(std::make_pair("error", error.ToJSON())); } + +namespace { + +#ifdef PRIVILEGE_USE_DB + +class AccessControlImpl { + public: + AccessControlImpl() + : initialized_(false) { + LoggerD("Privilege access checked using DB."); + + const char* kWrtDBPath = "/opt/dbspace/.wrt.db"; + sqlite3* db = nullptr; + + int ret = sqlite3_open(kWrtDBPath, &db); + if (SQLITE_OK != ret) { + LoggerE("Failed to access WRT database"); + return; + } + + const char* kQuery = "select name from WidgetFeature where app_id = " + "(select app_id from WidgetInfo where tizen_appid = ?)" + " and rejected = 0"; + const std::string app_id = common::Extension::GetRuntimeVariable("app_id", 64); + sqlite3_stmt* stmt = nullptr; + + ret = sqlite3_prepare_v2(db, kQuery, -1, &stmt, nullptr); + ret |= sqlite3_bind_text(stmt, 1, app_id.c_str(), -1, SQLITE_TRANSIENT); + + SCOPE_EXIT { + sqlite3_finalize(stmt); + sqlite3_close(db); + }; + + if (SQLITE_OK != ret) { + LoggerE("Failed to query WRT database"); + return; + } + + while (sqlite3_step(stmt) == SQLITE_ROW) { + const char* privilege = reinterpret_cast(sqlite3_column_text(stmt, 0)); + SLoggerD("Granted: %s", privilege); + granted_privileges_.push_back(privilege); + } + + initialized_ = true; + } + + ~AccessControlImpl() {} + + bool CheckAccess(const std::vector& privileges) { + if (!initialized_) { + return false; + } + + for (const auto& privilege : privileges) { + if (std::find(granted_privileges_.begin(), granted_privileges_.end(), privilege) == granted_privileges_.end()) { + return false; + } + } + + return true; + } + + private: + bool initialized_; + std::vector granted_privileges_; +}; + +#elif PRIVILEGE_USE_ACE + +class AccessControlImpl { + public: + AccessControlImpl() + : initialized_(false), + widget_id_(-1) { + LoggerD("Privilege access checked using ACE."); + // get widget ID + const char* kWrtDBPath = "/opt/dbspace/.wrt.db"; + sqlite3* db = nullptr; + + int ret = sqlite3_open(kWrtDBPath, &db); + if (SQLITE_OK != ret) { + LoggerE("Failed to access WRT database"); + return; + } + + const char* kQuery = "select app_id from WidgetInfo where tizen_appid = ?"; + const std::string app_id = common::Extension::GetRuntimeVariable("app_id", 64); + sqlite3_stmt* stmt = nullptr; + + ret = sqlite3_prepare_v2(db, kQuery, -1, &stmt, nullptr); + ret |= sqlite3_bind_text(stmt, 1, app_id.c_str(), -1, SQLITE_TRANSIENT); + + SCOPE_EXIT { + sqlite3_finalize(stmt); + sqlite3_close(db); + }; + + if (SQLITE_OK != ret) { + LoggerE("Failed to query WRT database"); + return; + } + + if (sqlite3_step(stmt) == SQLITE_ROW) { + widget_id_ = sqlite3_column_int(stmt, 0); + } else { + LoggerE("Application %s not found.", app_id.c_str()); + return; + } + + // start ACE + if (ACE_OK != ace_client_initialize(AlwaysDeny)) { + LoggerE("Failed to initialize ACE."); + } else { + // in order to work, WrtDatabase needs to be bound to thread + // which is going to check the WrtAccess + WrtDB::WrtDatabase::attachToThreadRO(); + // set the session ID + session_id_ = app_id + std::to_string(widget_id_); + // we're ready + initialized_ = true; + } + } + + ~AccessControlImpl() { + if (initialized_) { + WrtDB::WrtDatabase::detachFromThread(); + ace_client_shutdown(); + } + } + + bool CheckAccess(const std::vector& privileges) { + if (!initialized_) { + return false; + } + + ace_check_result_t result = ACE_PRIVILEGE_DENIED; + ace_request_t request; + const auto count = privileges.size(); + + request.session_id = const_cast(session_id_.c_str()); + request.widget_handle = widget_id_; + request.feature_list = { 0, 0 }; + request.dev_cap_list = { 0, 0 }; + + request.feature_list.count = count; + request.feature_list.items = new char*[count]; + + SCOPE_EXIT { + delete [] request.feature_list.items; + }; + + for (size_t i = 0; i < count; ++i) { + request.feature_list.items[i] = const_cast(privileges[i].c_str()); + } + + if (ACE_OK != ace_check_access_ex(&request, &result)) { + LoggerE("Failed to check privilege."); + return false; + } else { + return (result == ACE_ACCESS_GRANTED); + } + } + + private: + static ace_return_t AlwaysDeny(ace_popup_t popup_type, + const ace_resource_t resource_name, + const ace_session_id_t session_id, + const ace_param_list_t* param_list, + ace_widget_handle_t handle, + ace_bool_t* validation_result) { + if (validation_result) { + *validation_result = ACE_TRUE; + } + return ACE_OK; + } + + bool initialized_; + int widget_id_; + std::string session_id_; +}; + +#elif PRIVILEGE_USE_CYNARA + +class AccessControlImpl { + public: + AccessControlImpl() { + LoggerD("Privilege access checked using Cynara."); + // TODO + } + + ~AccessControlImpl() { + // TODO + } + + bool CheckAccess(const std::vector& privileges) { + // TODO + return false; + } +}; + +#else + +class AccessControlImpl { + public: + AccessControlImpl() { + LoggerD("Privilege access - deny all."); + } + + bool CheckAccess(const std::vector& privileges) { + return false; + } +}; + +#endif + +class AccessControl { + public: + static AccessControl& GetInstance() { + static AccessControl instance; + return instance; + } + + bool CheckAccess(const std::string& privilege) { + return CheckAccess(std::vector{privilege}); + } + + bool CheckAccess(const std::vector& privileges) { + return impl_.CheckAccess(privileges); + } + + private: + AccessControl() {} + ~AccessControl() {} + AccessControlImpl impl_; +}; + +} // namespace + +PlatformResult CheckAccess(const std::string& privilege) { + if (AccessControl::GetInstance().CheckAccess(privilege)) { + return PlatformResult(ErrorCode::NO_ERROR); + } else { + LoggerD("Access to privilege: %s has been denied.", privilege.c_str()); + return PlatformResult(ErrorCode::SECURITY_ERR, "Permission denied"); + } +} + } // namespace tools } // namespace common diff --git a/src/common/extension.h b/src/common/extension.h index 2396b6ad..607a791c 100644 --- a/src/common/extension.h +++ b/src/common/extension.h @@ -130,6 +130,18 @@ void ReportSuccess(const picojson::value& result, picojson::object& out); void ReportError(picojson::object& out); void ReportError(const PlatformException& ex, picojson::object& out); void ReportError(const PlatformResult& error, picojson::object* out); + +common::PlatformResult CheckAccess(const std::string& privilege); + +#define CHECK_PRIVILEGE_ACCESS(privilege, out) \ +do { \ + auto r = common::tools::CheckAccess(privilege); \ + if (!r) { \ + common::tools::ReportError(r, out); \ + return; \ + } \ +} while (0) + } // namespace tools } // namespace common