From bf0cba2645eb6ef05dc7be69d8e6972efdc85b8a Mon Sep 17 00:00:00 2001 From: Zofia Abramowska Date: Fri, 29 Jan 2016 11:06:31 +0100 Subject: [PATCH] Implement logic of apply/drop sharing in ServiceImpl Change-Id: I23ca6948cb523c336857f80ec0530f6cfebd25bc --- src/client/client-security-manager.cpp | 8 ++ src/common/include/privilege_db.h | 20 +-- src/common/include/protocols.h | 6 + src/common/include/service_impl.h | 4 + src/common/service_impl.cpp | 231 +++++++++++++++++++++++++++++++-- src/include/security-manager.h | 2 + 6 files changed, 251 insertions(+), 20 deletions(-) diff --git a/src/client/client-security-manager.cpp b/src/client/client-security-manager.cpp index 56130cd..1341cab 100644 --- a/src/client/client-security-manager.cpp +++ b/src/client/client-security-manager.cpp @@ -1373,6 +1373,10 @@ int security_manager_private_sharing_apply(const private_sharing_req *p_req) return SECURITY_MANAGER_ERROR_MEMORY; case SECURITY_MANAGER_API_ERROR_INPUT_PARAM: return SECURITY_MANAGER_ERROR_INPUT_PARAM; + case SECURITY_MANAGER_API_ERROR_APP_UNKNOWN: + return SECURITY_MANAGER_ERROR_APP_UNKNOWN; + case SECURITY_MANAGER_API_ERROR_APP_NOT_PATH_OWNER: + return SECURITY_MANAGER_ERROR_APP_NOT_PATH_OWNER; default: return SECURITY_MANAGER_ERROR_UNKNOWN; } @@ -1411,6 +1415,10 @@ int security_manager_private_sharing_drop(const private_sharing_req *p_req) return SECURITY_MANAGER_ERROR_MEMORY; case SECURITY_MANAGER_API_ERROR_INPUT_PARAM: return SECURITY_MANAGER_ERROR_INPUT_PARAM; + case SECURITY_MANAGER_API_ERROR_APP_UNKNOWN: + return SECURITY_MANAGER_ERROR_APP_UNKNOWN; + case SECURITY_MANAGER_API_ERROR_APP_NOT_PATH_OWNER: + return SECURITY_MANAGER_ERROR_APP_NOT_PATH_OWNER; default: return SECURITY_MANAGER_ERROR_UNKNOWN; } diff --git a/src/common/include/privilege_db.h b/src/common/include/privilege_db.h index a262abc..5a2a813 100644 --- a/src/common/include/privilege_db.h +++ b/src/common/include/privilege_db.h @@ -163,6 +163,16 @@ private: StatementWrapper getStatement(StmtType queryType); /** + * Check if appId is registered in database + * + * @param appId - package identifier + * @exception DB::SqlConnection::Exception::InternalError on internal error + * @return true if appId exists in the database + * + */ + bool AppIdExists(const std::string &appId); + + /** * Check if pkgId is already registered in database * * @param pkgId - package identifier @@ -207,16 +217,6 @@ public: void RollbackTransaction(void); /** - * Check if appId is registered in database - * - * @param appId - package identifier - * @exception DB::SqlConnection::Exception::InternalError on internal error - * @return true if appId exists in the database - * - */ - bool AppIdExists(const std::string &appId); - - /** * Return package id associated with a given application id * * @param appId - application identifier diff --git a/src/common/include/protocols.h b/src/common/include/protocols.h index 828eb89..a464318 100644 --- a/src/common/include/protocols.h +++ b/src/common/include/protocols.h @@ -99,6 +99,12 @@ /*! \brief indicating file deletion error */ #define SECURITY_MANAGER_API_ERROR_FILE_DELETION_FAILED -28 +/*! \brief indicating that application is not present in the database */ +#define SECURITY_MANAGER_API_ERROR_APP_UNKNOWN -29 + +/*! \brief indicating that application is not owner of path */ +#define SECURITY_MANAGER_API_ERROR_APP_NOT_PATH_OWNER -30 + /*! \brief indicating the error with unknown reason */ #define SECURITY_MANAGER_API_ERROR_UNKNOWN -255 /** @}*/ diff --git a/src/common/include/service_impl.h b/src/common/include/service_impl.h index d18e4e6..b3293c1 100644 --- a/src/common/include/service_impl.h +++ b/src/common/include/service_impl.h @@ -47,6 +47,10 @@ private: static bool getZoneId(std::string &zoneId); + int dropOnePrivateSharing(const std::string &ownerAppId, const std::string &ownerPkgId, + const std::vector &ownerPkgContents, const std::string &targetAppId, + const std::string &path, const std::string &zoneId, bool isSlave); + public: ServiceImpl(); virtual ~ServiceImpl(); diff --git a/src/common/service_impl.cpp b/src/common/service_impl.cpp index 321765c..e582a8d 100644 --- a/src/common/service_impl.cpp +++ b/src/common/service_impl.cpp @@ -141,6 +141,33 @@ bool isTizen2XVersion(const std::string &version) return false; } +class ScopedTransaction { +public: + ScopedTransaction() : m_isCommited(false) { + PrivilegeDb::getInstance().BeginTransaction(); + } + ScopedTransaction(const ScopedTransaction &other) = delete; + ScopedTransaction& operation(const ScopedTransaction &other) = delete; + + void commit() { + PrivilegeDb::getInstance().CommitTransaction(); + m_isCommited = true; + } + ~ScopedTransaction() { + if (!m_isCommited) { + try { + PrivilegeDb::getInstance().RollbackTransaction(); + } catch (const SecurityManager::Exception &e) { + LogError("Transaction rollback failed: " << e.GetMessage()); + } catch(...) { + LogError("Transaction rollback failed with unknown exception"); + } + } + } +private: + bool m_isCommited; +}; + } // end of anonymous namespace ServiceImpl::ServiceImpl() @@ -1093,17 +1120,141 @@ int ServiceImpl::appHasPrivilege(std::string appId, std::string privilege, return SECURITY_MANAGER_API_SUCCESS; } + +int ServiceImpl::dropOnePrivateSharing(const std::string &ownerAppId, const std::string &ownerPkgId, + const std::vector &ownerPkgContents, const std::string &targetAppId, + const std::string &path, const std::string &zoneId, bool isSlave) +{ + int errorRet; + try { + int targetPathCount, pathCount, ownerTargetCount; + PrivilegeDb::getInstance().DropPrivateSharing(ownerAppId, targetAppId, path); + PrivilegeDb::getInstance().GetTargetPathSharingCount(targetAppId, path, targetPathCount); + PrivilegeDb::getInstance().GetPathSharingCount(path, pathCount); + PrivilegeDb::getInstance().GetOwnerTargetSharingCount(ownerAppId, targetAppId, ownerTargetCount); + if (targetPathCount > 0) { + return SECURITY_MANAGER_API_SUCCESS; + } + if (pathCount < 1) { + SmackLabels::setupPath(ownerPkgId, path, SECURITY_MANAGER_PATH_RW, zoneId); + } + std::string pathLabel = zoneSmackLabelGenerate(SmackLabels::generateSharedPrivateLabel(ownerPkgId, path), zoneId); + if (isSlave) { + MasterReq::SmackDropPrivateSharingRules(ownerPkgId, ownerPkgContents, targetAppId, path, ownerTargetCount, pathCount); + } else { + SmackRules::dropPrivateSharingRules(ownerPkgId, ownerPkgContents, targetAppId, pathLabel, + pathCount < 1, ownerTargetCount < 1, zoneId); + } + return SECURITY_MANAGER_API_SUCCESS; + } catch (const SmackException::Base &e) { + LogError("Error performing smack operation: " << e.GetMessage()); + errorRet = SECURITY_MANAGER_API_ERROR_SERVER_ERROR; + } catch (const std::bad_alloc &e) { + LogError("Memory allocation failed: " << e.what()); + errorRet = SECURITY_MANAGER_API_ERROR_OUT_OF_MEMORY; + } catch (const std::exception &e) { + LogError("Some exception thrown : " << e.what()); + errorRet = SECURITY_MANAGER_API_ERROR_UNKNOWN; + } catch (...) { + LogError("Unknown exception thrown"); + errorRet = SECURITY_MANAGER_API_ERROR_UNKNOWN; + } + return errorRet; +} + int ServiceImpl::applyPrivatePathSharing(const std::string &ownerAppId, const std::string &targetAppId, const std::vector &paths, bool isSlave) { - (void)ownerAppId; - (void)targetAppId; - (void)paths; - (void)isSlave; + int errorRet; + int sharingAdded = 0; + std::string ownerPkgId; + std::vector pkgContents; + std::string zoneId; + if (isSlave) { + if (!getZoneId(zoneId)) { + LogError("Failed to get Zone ID."); + return SECURITY_MANAGER_API_ERROR_SERVER_ERROR; + } + } - return SECURITY_MANAGER_API_SUCCESS; + try { + std::string targetPkgId; + if (!PrivilegeDb::getInstance().GetAppPkgId(ownerAppId, ownerPkgId)) { + LogError(ownerAppId << " is not an installed application"); + return SECURITY_MANAGER_API_ERROR_APP_UNKNOWN; + } + if (!PrivilegeDb::getInstance().GetAppPkgId(targetAppId, targetPkgId)) { + LogError(targetAppId << " is not an installed application"); + return SECURITY_MANAGER_API_ERROR_APP_UNKNOWN; + } + + for(const auto &path : paths) { + std::string pathLabel = SmackLabels::getSmackLabelFromPath(path); + if (pathLabel != zoneSmackLabelGenerate(SmackLabels::generatePkgLabel(ownerPkgId), zoneId)) { + std::string generatedPathLabel = zoneSmackLabelGenerate(SmackLabels::generateSharedPrivateLabel(ownerPkgId, path), zoneId); + if (generatedPathLabel != pathLabel) { + LogError("Path " << path << " has label " << pathLabel << " and dosen't belong" + " to application " << ownerAppId); + return SECURITY_MANAGER_API_ERROR_APP_NOT_PATH_OWNER; + } + } + } + if (ownerAppId == targetAppId) { + LogDebug("Owner application is the same as target application"); + return SECURITY_MANAGER_API_SUCCESS; + } + + if (ownerPkgId == targetPkgId) { + LogDebug("Owner and target belong to the same package"); + return SECURITY_MANAGER_API_SUCCESS; + } + ScopedTransaction trans; + PrivilegeDb::getInstance().GetAppIdsForPkgId(ownerPkgId, pkgContents); + for (const auto &path : paths) { + int targetPathCount, pathCount, ownerTargetCount; + PrivilegeDb::getInstance().GetTargetPathSharingCount(targetAppId, path, targetPathCount); + PrivilegeDb::getInstance().GetPathSharingCount(path, pathCount); + PrivilegeDb::getInstance().GetOwnerTargetSharingCount(ownerAppId, targetAppId, ownerTargetCount); + std::string pathLabel = zoneSmackLabelGenerate(SmackLabels::generateSharedPrivateLabel(ownerPkgId, path), zoneId); + PrivilegeDb::getInstance().ApplyPrivateSharing(ownerAppId, targetAppId, path, pathLabel); + sharingAdded++; + if (targetPathCount > 0) { + //Nothing to do, only counter needed incrementing + continue; + } + if (pathCount <= 0) { + SmackLabels::setupSharedPrivatePath(ownerPkgId, path); + } + if (isSlave) { + MasterReq::SmackApplyPrivateSharingRules(ownerPkgId, + pkgContents, targetAppId, path, ownerTargetCount, pathCount); + } else { + SmackRules::applyPrivateSharingRules(ownerPkgId, pkgContents, targetAppId, + pathLabel, (pathCount > 0), (ownerTargetCount > 0), zoneId); + } + } + trans.commit(); + return SECURITY_MANAGER_API_SUCCESS; + } catch (const SmackException::Base &e) { + LogError("Error performing smack operation: " << e.GetMessage()); + errorRet = SECURITY_MANAGER_API_ERROR_SERVER_ERROR; + } catch (const std::bad_alloc &e) { + LogError("Memory allocation failed: " << e.what()); + errorRet = SECURITY_MANAGER_API_ERROR_OUT_OF_MEMORY; + } catch (const std::exception &e) { + LogError("Some exception thrown : " << e.what()); + errorRet = SECURITY_MANAGER_API_ERROR_UNKNOWN; + } catch (...) { + LogError("Unknown exception thrown"); + errorRet = SECURITY_MANAGER_API_ERROR_UNKNOWN; + } + for (int i = 0; i < sharingAdded; i++) { + const std::string &path = paths[i]; + dropOnePrivateSharing(ownerAppId, ownerPkgId, pkgContents, targetAppId, path, zoneId, isSlave); + } + return errorRet; } int ServiceImpl::dropPrivatePathSharing(const std::string &ownerAppId, @@ -1111,12 +1262,72 @@ int ServiceImpl::dropPrivatePathSharing(const std::string &ownerAppId, const std::vector &paths, bool isSlave) { - (void)ownerAppId; - (void)targetAppId; - (void)paths; - (void)isSlave; + int errorRet; + try { + std::string zoneId; + if (isSlave) { + if (!getZoneId(zoneId)) { + LogError("Failed to get Zone ID."); + return SECURITY_MANAGER_API_ERROR_SERVER_ERROR; + } + } + std::string ownerPkgId, targetPkgId; + if (!PrivilegeDb::getInstance().GetAppPkgId(ownerAppId, ownerPkgId)) { + LogError(ownerAppId << " is not an installed application"); + return SECURITY_MANAGER_API_ERROR_APP_UNKNOWN; + } + if (!PrivilegeDb::getInstance().GetAppPkgId(targetAppId, targetPkgId)) { + LogError(targetAppId << " is not an installed application"); + return SECURITY_MANAGER_API_ERROR_APP_UNKNOWN; + } - return SECURITY_MANAGER_API_SUCCESS; + for(const auto &path : paths) { + std::string pathLabel = SmackLabels::getSmackLabelFromPath(path); + if (pathLabel != zoneSmackLabelGenerate(SmackLabels::generatePkgLabel(ownerPkgId), zoneId)) { + std::string generatedPathLabel = zoneSmackLabelGenerate(SmackLabels::generateSharedPrivateLabel(ownerPkgId, path), zoneId); + if (generatedPathLabel != pathLabel) { + LogError("Path " << path << " has label " << pathLabel << " and dosen't belong" + " to application " << ownerAppId); + return SECURITY_MANAGER_API_ERROR_APP_NOT_PATH_OWNER; + } + } + } + if (ownerAppId == targetAppId) { + LogDebug("Owner application is the same as target application"); + return SECURITY_MANAGER_API_SUCCESS; + } + + if (ownerPkgId == targetPkgId) { + LogDebug("Owner and target belong to the same package"); + return SECURITY_MANAGER_API_SUCCESS; + } + + std::vector pkgContents; + PrivilegeDb::getInstance().GetAppIdsForPkgId(ownerPkgId, pkgContents); + ScopedTransaction trans; + for (const auto &path : paths) { + int ret = dropOnePrivateSharing(ownerAppId, ownerPkgId, pkgContents, targetAppId, path, zoneId, isSlave); + if (ret != SECURITY_MANAGER_API_SUCCESS) { + return ret; + } + } + trans.commit(); + return SECURITY_MANAGER_API_SUCCESS; + } catch (const SmackException::Base &e) { + LogError("Error performing smack operation: " << e.GetMessage()); + errorRet = SECURITY_MANAGER_API_ERROR_SERVER_ERROR; + } catch (const std::bad_alloc &e) { + LogError("Memory allocation failed: " << e.what()); + errorRet = SECURITY_MANAGER_API_ERROR_OUT_OF_MEMORY; + } catch (const std::exception &e) { + LogError("Some exception thrown : " << e.what()); + errorRet = SECURITY_MANAGER_API_ERROR_UNKNOWN; + } catch (...) { + LogError("Unknown exception thrown"); + errorRet = SECURITY_MANAGER_API_ERROR_UNKNOWN; + } + return errorRet; } + } /* namespace SecurityManager */ diff --git a/src/include/security-manager.h b/src/include/security-manager.h index 65175e0..64302a2 100644 --- a/src/include/security-manager.h +++ b/src/include/security-manager.h @@ -43,6 +43,8 @@ enum lib_retcode { SECURITY_MANAGER_ERROR_AUTHENTICATION_FAILED, SECURITY_MANAGER_ERROR_ACCESS_DENIED, SECURITY_MANAGER_ERROR_NO_SUCH_OBJECT, + SECURITY_MANAGER_ERROR_APP_UNKNOWN, + SECURITY_MANAGER_ERROR_APP_NOT_PATH_OWNER }; /*! \brief accesses types for application installation paths*/ -- 2.7.4