From: Rafal Krypa Date: Fri, 21 Nov 2014 10:55:07 +0000 (+0100) Subject: Split service implementation logic away from the Service class X-Git-Tag: accepted/tizen/tv/20150217.004257~50 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fsecurity%2Fsecurity-manager.git;a=commitdiff_plain;h=82abc7e44098a63300ecc2c4d9d40daf354a1a32 Split service implementation logic away from the Service class The code implementing logic of Service methods is now available as separate functions. They will be available to both Service class and to the upcoming offline client implementation. Change-Id: Ib86af8c0f28dd7a1333e67ad0f2a4c968ff181cf Signed-off-by: Rafal Krypa --- diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 68120d1..13bac8e 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -50,6 +50,7 @@ SET(COMMON_SOURCES ${COMMON_PATH}/smack-labels.cpp ${COMMON_PATH}/smack-rules.cpp ${COMMON_PATH}/smack-check.cpp + ${COMMON_PATH}/service_impl.cpp ) ADD_LIBRARY(${TARGET_COMMON} SHARED ${COMMON_SOURCES}) diff --git a/src/common/include/service_impl.h b/src/common/include/service_impl.h new file mode 100644 index 0000000..ba6a580 --- /dev/null +++ b/src/common/include/service_impl.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Rafal Krypa + * + * 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 service_impl.h + * @author Rafal Krypa + * @brief Implementation of the service methods + */ + +#ifndef _SECURITY_MANAGER_SERVICE_IMPL_ +#define _SECURITY_MANAGER_SERVICE_IMPL_ + +#include +#include + +#include + +#include "security-manager.h" + +namespace SecurityManager { +namespace ServiceImpl { + +/** + * Process application installation request. + * + * @param[in] req installation request + * @param[in] uid id of the requesting user + * + * @return API return code, as defined in security-manager.h + */ +int appInstall(const app_inst_req &req, uid_t uid); + +/** + * Process application uninstallation request. + * + * @param[in] req uninstallation request + * @param[in] uid id of the requesting user + * + * @return API return code, as defined in security-manager.h + */ +int appUninstall(const std::string &appId, uid_t uid); + +/** + * Process package id query. + * Retrieves the package id associated with given application id. + * + * @param[in] appId application identifier + * @param[out] pkgId returned package identifier + * + * @return API return code, as defined in security-manager.h + */ +int getPkgId(const std::string &appId, std::string &pkgId); + +/** + * Process query for supplementary groups allowed for the application. + * For given appId and uid, calculate allowed privileges that give + * direct access to file system resources. For each permission Cynara will be + * queried. + * Returns set of group ids that are permitted. + * + * @param[in] appId application identifier + * @param[in] uid id of the requesting user + * @param[in] pid id of the requesting process (to construct Cynara session id) + * @param[out] gids returned set of allowed group ids + * + * @return API return code, as defined in security-manager.h + */ +int getAppGroups(const std::string &appId, uid_t uid, pid_t pid, std::unordered_set &gids); + +} /* namespace ServiceImpl */ +} /* namespace SecurityManager */ + +#endif /* _SECURITY_MANAGER_SERVICE_IMPL_ */ diff --git a/src/common/service_impl.cpp b/src/common/service_impl.cpp new file mode 100644 index 0000000..360196f --- /dev/null +++ b/src/common/service_impl.cpp @@ -0,0 +1,365 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Rafal Krypa + * + * 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 service_impl.cpp + * @author Michal Witanowski + * @author Jacek Bukarewicz + * @author Rafal Krypa + * @brief Implementation of the service methods + */ + +#include +#include +#include + +#include +#include + +#include +#include + +#include "protocols.h" +#include "privilege_db.h" +#include "cynara.h" +#include "smack-common.h" +#include "smack-rules.h" +#include "smack-labels.h" + +#include "service_impl.h" + +namespace SecurityManager { +namespace ServiceImpl { + +static uid_t getGlobalUserId(void) +{ + static uid_t globaluid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER); + return globaluid; +} + +/** + * Unifies user data of apps installed for all users + * @param uid peer's uid - may be changed during process + * @param cynaraUserStr string to which cynara user parameter will be put + */ +static void checkGlobalUser(uid_t &uid, std::string &cynaraUserStr) +{ + static uid_t globaluid = getGlobalUserId(); + if (uid == 0 || uid == globaluid) { + uid = globaluid; + cynaraUserStr = CYNARA_ADMIN_WILDCARD; + } else { + cynaraUserStr = std::to_string(static_cast(uid)); + } +} +static inline bool isSubDir(const char *parent, const char *subdir) +{ + while (*parent && *subdir) + if (*parent++ != *subdir++) + return false; + + return (*subdir == '/'); +} + +static inline bool installRequestAuthCheck(const app_inst_req &req, uid_t uid) +{ + struct passwd *pwd; + do { + errno = 0; + pwd = getpwuid(uid); + if (!pwd && errno != EINTR) { + LogError("getpwuid failed with '" << uid + << "' as paramter: " << strerror(errno)); + return false; + } + } while (!pwd); + + std::unique_ptr> home( + realpath(pwd->pw_dir, NULL), free); + if (!home.get()) { + LogError("realpath failed with '" << pwd->pw_dir + << "' as paramter: " << strerror(errno)); + return false; + } + + for (const auto &appPath : req.appPaths) { + std::unique_ptr> real_path( + realpath(appPath.first.c_str(), NULL), free); + if (!real_path.get()) { + LogError("realpath failed with '" << appPath.first.c_str() + << "' as paramter: " << strerror(errno)); + return false; + } + LogDebug("Requested path is '" << appPath.first.c_str() + << "'. User's HOME is '" << pwd->pw_dir << "'"); + if (!isSubDir(home.get(), real_path.get())) { + LogWarning("User's apps may have registered folders only in user's home dir"); + return false; + } + + app_install_path_type pathType = static_cast(appPath.second); + if (pathType == SECURITY_MANAGER_PATH_PUBLIC) { + LogWarning("Only root can register SECURITY_MANAGER_PATH_PUBLIC path"); + return false; + } + } + return true; +} + +int appInstall(const app_inst_req &req, uid_t uid) +{ + bool pkgIdIsNew = false; + std::vector addedPermissions; + std::vector removedPermissions; + + std::string uidstr; + if ((!uid) && (req.uid)) + uid = req.uid; + checkGlobalUser(uid, uidstr); + + if (!installRequestAuthCheck(req, uid)) { + LogError("Request from uid " << uid << " for app installation denied"); + return SECURITY_MANAGER_API_ERROR_AUTHENTICATION_FAILED; + } + + std::string smackLabel; + if (!generateAppLabel(req.pkgId, smackLabel)) { + LogError("Cannot generate Smack label for package: " << req.pkgId); + return SECURITY_MANAGER_API_ERROR_SERVER_ERROR; + } + + LogDebug("Install parameters: appId: " << req.appId << ", pkgId: " << req.pkgId + << ", generated smack label: " << smackLabel); + + // create null terminated array of strings for permissions + std::unique_ptr pp_permissions(new const char* [req.privileges.size() + 1]); + for (size_t i = 0; i < req.privileges.size(); ++i) { + LogDebug(" Permission = " << req.privileges[i]); + pp_permissions[i] = req.privileges[i].c_str(); + } + pp_permissions[req.privileges.size()] = nullptr; + + try { + std::vector oldPkgPrivileges, newPkgPrivileges; + + LogDebug("Install parameters: appId: " << req.appId << ", pkgId: " << req.pkgId + << ", uidstr " << uidstr << ", generated smack label: " << smackLabel); + + PrivilegeDb::getInstance().BeginTransaction(); + PrivilegeDb::getInstance().GetPkgPrivileges(req.pkgId, uid, oldPkgPrivileges); + PrivilegeDb::getInstance().AddApplication(req.appId, req.pkgId, uid, pkgIdIsNew); + PrivilegeDb::getInstance().UpdateAppPrivileges(req.appId, uid, req.privileges); + PrivilegeDb::getInstance().GetPkgPrivileges(req.pkgId, uid, newPkgPrivileges); + CynaraAdmin::UpdatePackagePolicy(smackLabel, uidstr, oldPkgPrivileges, + newPkgPrivileges); + PrivilegeDb::getInstance().CommitTransaction(); + LogDebug("Application installation commited to database"); + } catch (const PrivilegeDb::Exception::IOError &e) { + LogError("Cannot access application database: " << e.DumpToString()); + return SECURITY_MANAGER_API_ERROR_SERVER_ERROR; + } catch (const PrivilegeDb::Exception::InternalError &e) { + PrivilegeDb::getInstance().RollbackTransaction(); + LogError("Error while saving application info to database: " << e.DumpToString()); + return SECURITY_MANAGER_API_ERROR_SERVER_ERROR; + } catch (const CynaraException::Base &e) { + PrivilegeDb::getInstance().RollbackTransaction(); + LogError("Error while setting Cynara rules for application: " << e.DumpToString()); + return SECURITY_MANAGER_API_ERROR_SERVER_ERROR; + } catch (const std::bad_alloc &e) { + PrivilegeDb::getInstance().RollbackTransaction(); + LogError("Memory allocation while setting Cynara rules for application: " << e.what()); + return SECURITY_MANAGER_API_ERROR_SERVER_ERROR; + } + + // register paths + for (const auto &appPath : req.appPaths) { + const std::string &path = appPath.first; + app_install_path_type pathType = static_cast(appPath.second); + int result = setupPath(req.pkgId, path, pathType); + + if (!result) { + LogError("setupPath() failed"); + return SECURITY_MANAGER_API_ERROR_SERVER_ERROR; + } + } + + if (pkgIdIsNew) { + LogDebug("Adding Smack rules for new pkgId " << req.pkgId); + if (!SmackRules::installPackageRules(req.pkgId)) { + LogError("Failed to apply package-specific smack rules"); + return SECURITY_MANAGER_API_ERROR_SERVER_ERROR; + } + } + + return SECURITY_MANAGER_API_SUCCESS; +} + +int appUninstall(const std::string &appId, uid_t uid) +{ + std::string pkgId; + std::string smackLabel; + bool appExists = true; + bool removePkg = false; + std::string uidstr; + checkGlobalUser(uid, uidstr); + + try { + std::vector oldPkgPrivileges, newPkgPrivileges; + + PrivilegeDb::getInstance().BeginTransaction(); + if (!PrivilegeDb::getInstance().GetAppPkgId(appId, pkgId)) { + LogWarning("Application " << appId << + " not found in database while uninstalling"); + PrivilegeDb::getInstance().RollbackTransaction(); + appExists = false; + } else { + + LogDebug("Uninstall parameters: appId: " << appId << ", pkgId: " << pkgId + << ", uidstr " << uidstr << ", generated smack label: " << smackLabel); + + if (!generateAppLabel(pkgId, smackLabel)) { + LogError("Cannot generate Smack label for package: " << pkgId); + return SECURITY_MANAGER_API_ERROR_SERVER_ERROR; + } + + PrivilegeDb::getInstance().GetPkgPrivileges(pkgId, uid, oldPkgPrivileges); + PrivilegeDb::getInstance().UpdateAppPrivileges(appId, uid, std::vector()); + PrivilegeDb::getInstance().RemoveApplication(appId, uid, removePkg); + PrivilegeDb::getInstance().GetPkgPrivileges(pkgId, uid, newPkgPrivileges); + CynaraAdmin::UpdatePackagePolicy(smackLabel, uidstr, oldPkgPrivileges, + newPkgPrivileges); + PrivilegeDb::getInstance().CommitTransaction(); + LogDebug("Application uninstallation commited to database"); + } + } catch (const PrivilegeDb::Exception::IOError &e) { + LogError("Cannot access application database: " << e.DumpToString()); + return SECURITY_MANAGER_API_ERROR_SERVER_ERROR; + } catch (const PrivilegeDb::Exception::InternalError &e) { + PrivilegeDb::getInstance().RollbackTransaction(); + LogError("Error while removing application info from database: " << e.DumpToString()); + return SECURITY_MANAGER_API_ERROR_SERVER_ERROR; + } catch (const CynaraException::Base &e) { + PrivilegeDb::getInstance().RollbackTransaction(); + LogError("Error while setting Cynara rules for application: " << e.DumpToString()); + return SECURITY_MANAGER_API_ERROR_SERVER_ERROR; + } catch (const std::bad_alloc &e) { + PrivilegeDb::getInstance().RollbackTransaction(); + LogError("Memory allocation while setting Cynara rules for application: " << e.what()); + return SECURITY_MANAGER_API_ERROR_SERVER_ERROR; + } + + if (appExists) { + + if (removePkg) { + LogDebug("Removing Smack rules for deleted pkgId " << pkgId); + if (!SmackRules::uninstallPackageRules(pkgId)) { + LogError("Error on uninstallation of package-specific smack rules"); + return SECURITY_MANAGER_API_ERROR_SERVER_ERROR; + } + } + } + + return SECURITY_MANAGER_API_SUCCESS; +} + +int getPkgId(const std::string &appId, std::string &pkgId) +{ + LogDebug("appId: " << appId); + + try { + if (!PrivilegeDb::getInstance().GetAppPkgId(appId, pkgId)) { + LogWarning("Application " << appId << " not found in database"); + return SECURITY_MANAGER_API_ERROR_NO_SUCH_OBJECT; + } else { + LogDebug("pkgId: " << pkgId); + } + } catch (const PrivilegeDb::Exception::Base &e) { + LogError("Error while getting pkgId from database: " << e.DumpToString()); + return SECURITY_MANAGER_API_ERROR_SERVER_ERROR; + } + + return SECURITY_MANAGER_API_SUCCESS; +} + +int getAppGroups(const std::string &appId, uid_t uid, pid_t pid, std::unordered_set &gids) +{ + try { + std::string pkgId; + std::string smackLabel; + std::string uidStr = std::to_string(uid); + std::string pidStr = std::to_string(pid); + + LogDebug("appId: " << appId); + + if (!PrivilegeDb::getInstance().GetAppPkgId(appId, pkgId)) { + LogWarning("Application " << appId << " not found in database"); + return SECURITY_MANAGER_API_ERROR_NO_SUCH_OBJECT; + } + LogDebug("pkgId: " << pkgId); + + if (!generateAppLabel(pkgId, smackLabel)) { + LogError("Cannot generate Smack label for package: " << pkgId); + return SECURITY_MANAGER_API_ERROR_NO_SUCH_OBJECT; + } + LogDebug("smack label: " << smackLabel); + + std::vector privileges; + PrivilegeDb::getInstance().GetPkgPrivileges(pkgId, uid, privileges); + /*there is also a need of checking, if privilege is granted to all users*/ + size_t tmp = privileges.size(); + PrivilegeDb::getInstance().GetPkgPrivileges(pkgId, getGlobalUserId(), privileges); + /*privileges needs to be sorted and with no duplications - for cynara sake*/ + std::inplace_merge(privileges.begin(), privileges.begin() + tmp, privileges.end()); + privileges.erase( unique( privileges.begin(), privileges.end() ), privileges.end() ); + + for (const auto &privilege : privileges) { + std::vector gidsTmp; + PrivilegeDb::getInstance().GetPrivilegeGroups(privilege, gidsTmp); + if (!gidsTmp.empty()) { + LogDebug("Considering privilege " << privilege << " with " << + gidsTmp.size() << " groups assigned"); + if (Cynara::getInstance().check(smackLabel, privilege, uidStr, pidStr)) { + for_each(gidsTmp.begin(), gidsTmp.end(), [&] (std::string group) + { + struct group *grp = getgrnam(group.c_str()); + if (grp == NULL) { + LogError("No such group: " << group.c_str()); + return; + } + gids.insert(grp->gr_gid); + }); + LogDebug("Cynara allowed, adding groups"); + } else + LogDebug("Cynara denied, not adding groups"); + } + } + } catch (const PrivilegeDb::Exception::Base &e) { + LogError("Database error: " << e.DumpToString()); + return SECURITY_MANAGER_API_ERROR_SERVER_ERROR; + } catch (const CynaraException::Base &e) { + LogError("Error while querying Cynara for permissions: " << e.DumpToString()); + return SECURITY_MANAGER_API_ERROR_SERVER_ERROR; + } catch (const std::bad_alloc &e) { + LogError("Memory allocation failed: " << e.what()); + return SECURITY_MANAGER_API_ERROR_OUT_OF_MEMORY; + } + + return SECURITY_MANAGER_API_SUCCESS; +} + +} /* namespace ServiceImpl */ +} /* namespace SecurityManager */ diff --git a/src/server/service/include/service.h b/src/server/service/include/service.h index 21bc19c..88b4870 100644 --- a/src/server/service/include/service.h +++ b/src/server/service/include/service.h @@ -78,9 +78,8 @@ private: * @param buffer Raw received data buffer * @param send Raw data buffer to be sent * @param uid User's identifier for whom application will be installed - * @return true on success */ - bool processAppInstall(MessageBuffer &buffer, MessageBuffer &send, uid_t uid); + void processAppInstall(MessageBuffer &buffer, MessageBuffer &send, uid_t uid); /** * Process application uninstallation @@ -88,18 +87,16 @@ private: * @param buffer Raw received data buffer * @param send Raw data buffer to be sent * @param uid User's identifier for whom application will be uninstalled - * @return true on success */ - bool processAppUninstall(MessageBuffer &buffer, MessageBuffer &send, uid_t uid); + void processAppUninstall(MessageBuffer &buffer, MessageBuffer &send, uid_t uid); /** * Process getting package id from app id * * @param buffer Raw received data buffer * @param send Raw data buffer to be sent - * @return true on success */ - bool processGetPkgId(MessageBuffer &buffer, MessageBuffer &send); + void processGetPkgId(MessageBuffer &buffer, MessageBuffer &send); /** * Process getting permitted group ids for app id @@ -108,9 +105,8 @@ private: * @param send Raw data buffer to be sent * @param uid User's identifier for whom application will be launched * @param pid Process id in which application will be launched - * @return true on success */ - bool processGetAppGroups(MessageBuffer &buffer, MessageBuffer &send, uid_t uid, pid_t pid); + void processGetAppGroups(MessageBuffer &buffer, MessageBuffer &send, uid_t uid, pid_t pid); }; } // namespace SecurityManager diff --git a/src/server/service/service.cpp b/src/server/service/service.cpp index d4b27ca..5b83421 100644 --- a/src/server/service/service.cpp +++ b/src/server/service/service.cpp @@ -23,55 +23,19 @@ * @brief Implementation of security-manager service. */ -#include -#include -#include #include -#include - -#include -#include -#include #include #include -#include -#include "privilege_db.h" #include "protocols.h" -#include "security-manager.h" #include "service.h" -#include "smack-common.h" -#include "smack-rules.h" -#include "smack-labels.h" +#include "service_impl.h" namespace SecurityManager { const InterfaceID IFACE = 1; - - -static uid_t getGlobalUserId(void) { - static uid_t globaluid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER); - return globaluid; -} - -/** - * Unifies user data of apps installed for all users - * @param uid peer's uid - may be changed during process - * @param cynaraUserStr string to which cynara user parameter will be put - */ -static void checkGlobalUser(uid_t &uid, std::string &cynaraUserStr) -{ - static uid_t globaluid = getGlobalUserId(); - if (uid == 0 || uid == globaluid) { - uid = globaluid; - cynaraUserStr = CYNARA_ADMIN_WILDCARD; - } else { - cynaraUserStr = std::to_string(static_cast(uid)); - } -} - Service::Service() { } @@ -208,350 +172,54 @@ bool Service::processOne(const ConnectionID &conn, MessageBuffer &buffer, return retval; } -static inline bool isSubDir(const char *parent, const char *subdir) -{ - while (*parent && *subdir) - if (*parent++ != *subdir++) - return false; - - return (*subdir == '/'); -} - -static inline bool installRequestAuthCheck(const app_inst_req &req, uid_t uid) -{ - struct passwd *pwd; - do { - errno = 0; - pwd = getpwuid(uid); - if (!pwd && errno != EINTR) { - LogError("getpwuid failed with '" << uid - << "' as paramter: " << strerror(errno)); - return false; - } - } while (!pwd); - - std::unique_ptr> home( - realpath(pwd->pw_dir, NULL), free); - if (!home.get()) { - LogError("realpath failed with '" << pwd->pw_dir - << "' as paramter: " << strerror(errno)); - return false; - } - - for (const auto &appPath : req.appPaths) { - std::unique_ptr> real_path( - realpath(appPath.first.c_str(), NULL), free); - if (!real_path.get()) { - LogError("realpath failed with '" << appPath.first.c_str() - << "' as paramter: " << strerror(errno)); - return false; - } - LogDebug("Requested path is '" << appPath.first.c_str() - << "'. User's HOME is '" << pwd->pw_dir << "'"); - if (!isSubDir(home.get(), real_path.get())) { - LogWarning("User's apps may have registered folders only in user's home dir"); - return false; - } - - app_install_path_type pathType = static_cast(appPath.second); - if (pathType == SECURITY_MANAGER_PATH_PUBLIC) { - LogWarning("Only root can register SECURITY_MANAGER_PATH_PUBLIC path"); - return false; - } - } - return true; -} - -bool Service::processAppInstall(MessageBuffer &buffer, MessageBuffer &send, uid_t uid) +void Service::processAppInstall(MessageBuffer &buffer, MessageBuffer &send, uid_t uid) { - bool pkgIdIsNew = false; - std::vector addedPermissions; - std::vector removedPermissions; - - // deserialize request data app_inst_req req; + Deserialization::Deserialize(buffer, req.appId); Deserialization::Deserialize(buffer, req.pkgId); Deserialization::Deserialize(buffer, req.privileges); Deserialization::Deserialize(buffer, req.appPaths); Deserialization::Deserialize(buffer, req.uid); - - std::string uidstr; - if ((!uid) && (req.uid)) - uid = req.uid; - checkGlobalUser(uid, uidstr); - - if(!installRequestAuthCheck(req, uid)) { - LogError("Request from uid " << uid << " for app installation denied"); - Serialization::Serialize(send, SECURITY_MANAGER_API_ERROR_AUTHENTICATION_FAILED); - return false; - } - - std::string smackLabel; - if (!generateAppLabel(req.pkgId, smackLabel)) { - LogError("Cannot generate Smack label for package: " << req.pkgId); - Serialization::Serialize(send, SECURITY_MANAGER_API_ERROR_SERVER_ERROR); - return false; - } - - LogDebug("Install parameters: appId: " << req.appId << ", pkgId: " << req.pkgId - << ", generated smack label: " << smackLabel); - - // create null terminated array of strings for permissions - std::unique_ptr pp_permissions(new const char* [req.privileges.size() + 1]); - for (size_t i = 0; i < req.privileges.size(); ++i) { - LogDebug(" Permission = " << req.privileges[i]); - pp_permissions[i] = req.privileges[i].c_str(); - } - pp_permissions[req.privileges.size()] = nullptr; - - try { - std::vector oldPkgPrivileges, newPkgPrivileges; - - LogDebug("Install parameters: appId: " << req.appId << ", pkgId: " << req.pkgId - << ", uidstr " << uidstr << ", generated smack label: " << smackLabel); - - PrivilegeDb::getInstance().BeginTransaction(); - PrivilegeDb::getInstance().GetPkgPrivileges(req.pkgId, uid, oldPkgPrivileges); - PrivilegeDb::getInstance().AddApplication(req.appId, req.pkgId, uid, pkgIdIsNew); - PrivilegeDb::getInstance().UpdateAppPrivileges(req.appId, uid, req.privileges); - PrivilegeDb::getInstance().GetPkgPrivileges(req.pkgId, uid, newPkgPrivileges); - CynaraAdmin::UpdatePackagePolicy(smackLabel, uidstr, oldPkgPrivileges, - newPkgPrivileges); - PrivilegeDb::getInstance().CommitTransaction(); - LogDebug("Application installation commited to database"); - } catch (const PrivilegeDb::Exception::IOError &e) { - LogError("Cannot access application database: " << e.DumpToString()); - goto error_label; - } catch (const PrivilegeDb::Exception::InternalError &e) { - PrivilegeDb::getInstance().RollbackTransaction(); - LogError("Error while saving application info to database: " << e.DumpToString()); - goto error_label; - } catch (const CynaraException::Base &e) { - PrivilegeDb::getInstance().RollbackTransaction(); - LogError("Error while setting Cynara rules for application: " << e.DumpToString()); - goto error_label; - } catch (const std::bad_alloc &e) { - PrivilegeDb::getInstance().RollbackTransaction(); - LogError("Memory allocation while setting Cynara rules for application: " << e.what()); - goto error_label; - } - - // register paths - for (const auto &appPath : req.appPaths) { - const std::string &path = appPath.first; - app_install_path_type pathType = static_cast(appPath.second); - int result = setupPath(req.pkgId, path, pathType); - - if (!result) { - LogError("setupPath() failed"); - goto error_label; - } - } - - if (pkgIdIsNew) { - LogDebug("Adding Smack rules for new pkgId " << req.pkgId); - if (!SmackRules::installPackageRules(req.pkgId)) { - LogError("Failed to apply package-specific smack rules"); - goto error_label; - } - } - - // success - Serialization::Serialize(send, SECURITY_MANAGER_API_SUCCESS); - return true; - -error_label: - Serialization::Serialize(send, SECURITY_MANAGER_API_ERROR_SERVER_ERROR); - return false; + Serialization::Serialize(send, ServiceImpl::appInstall(req, uid)); } -bool Service::processAppUninstall(MessageBuffer &buffer, MessageBuffer &send, uid_t uid) +void Service::processAppUninstall(MessageBuffer &buffer, MessageBuffer &send, uid_t uid) { - // deserialize request data std::string appId; - std::string pkgId; - std::string smackLabel; - bool appExists = true; - bool removePkg = false; Deserialization::Deserialize(buffer, appId); - std::string uidstr; - checkGlobalUser(uid, uidstr); - - try { - std::vector oldPkgPrivileges, newPkgPrivileges; - - PrivilegeDb::getInstance().BeginTransaction(); - if (!PrivilegeDb::getInstance().GetAppPkgId(appId, pkgId)) { - LogWarning("Application " << appId << - " not found in database while uninstalling"); - PrivilegeDb::getInstance().RollbackTransaction(); - appExists = false; - } else { - - LogDebug("Uninstall parameters: appId: " << appId << ", pkgId: " << pkgId - << ", uidstr " << uidstr << ", generated smack label: " << smackLabel); - - if (!generateAppLabel(pkgId, smackLabel)) { - LogError("Cannot generate Smack label for package: " << pkgId); - goto error_label; - } - - PrivilegeDb::getInstance().GetPkgPrivileges(pkgId, uid, oldPkgPrivileges); - PrivilegeDb::getInstance().UpdateAppPrivileges(appId, uid, std::vector()); - PrivilegeDb::getInstance().RemoveApplication(appId, uid, removePkg); - PrivilegeDb::getInstance().GetPkgPrivileges(pkgId, uid, newPkgPrivileges); - CynaraAdmin::UpdatePackagePolicy(smackLabel, uidstr, oldPkgPrivileges, - newPkgPrivileges); - PrivilegeDb::getInstance().CommitTransaction(); - LogDebug("Application uninstallation commited to database"); - } - } catch (const PrivilegeDb::Exception::IOError &e) { - LogError("Cannot access application database: " << e.DumpToString()); - goto error_label; - } catch (const PrivilegeDb::Exception::InternalError &e) { - PrivilegeDb::getInstance().RollbackTransaction(); - LogError("Error while removing application info from database: " << e.DumpToString()); - goto error_label; - } catch (const CynaraException::Base &e) { - PrivilegeDb::getInstance().RollbackTransaction(); - LogError("Error while setting Cynara rules for application: " << e.DumpToString()); - goto error_label; - } catch (const std::bad_alloc &e) { - PrivilegeDb::getInstance().RollbackTransaction(); - LogError("Memory allocation while setting Cynara rules for application: " << e.what()); - goto error_label; - } - - if (appExists) { - - if (removePkg) { - LogDebug("Removing Smack rules for deleted pkgId " << pkgId); - if (!SmackRules::uninstallPackageRules(pkgId)) { - LogError("Error on uninstallation of package-specific smack rules"); - goto error_label; - } - } - } - - // success - Serialization::Serialize(send, SECURITY_MANAGER_API_SUCCESS); - return true; - -error_label: - Serialization::Serialize(send, SECURITY_MANAGER_API_ERROR_SERVER_ERROR); - return false; + Serialization::Serialize(send, ServiceImpl::appUninstall(appId, uid)); } -bool Service::processGetPkgId(MessageBuffer &buffer, MessageBuffer &send) +void Service::processGetPkgId(MessageBuffer &buffer, MessageBuffer &send) { - // deserialize request data std::string appId; std::string pkgId; + int ret; Deserialization::Deserialize(buffer, appId); - LogDebug("appId: " << appId); - - try { - if (!PrivilegeDb::getInstance().GetAppPkgId(appId, pkgId)) { - LogWarning("Application " << appId << " not found in database"); - Serialization::Serialize(send, SECURITY_MANAGER_API_ERROR_NO_SUCH_OBJECT); - return false; - } else { - LogDebug("pkgId: " << pkgId); - } - } catch (const PrivilegeDb::Exception::Base &e) { - LogError("Error while getting pkgId from database: " << e.DumpToString()); - Serialization::Serialize(send, SECURITY_MANAGER_API_ERROR_SERVER_ERROR); - return false; - } - - // success - Serialization::Serialize(send, SECURITY_MANAGER_API_SUCCESS); - Serialization::Serialize(send, pkgId); - return true; + ret = ServiceImpl::getPkgId(appId, pkgId); + Serialization::Serialize(send, ret); + if (ret == SECURITY_MANAGER_API_SUCCESS) + Serialization::Serialize(send, pkgId); } -bool Service::processGetAppGroups(MessageBuffer &buffer, MessageBuffer &send, uid_t uid, pid_t pid) +void Service::processGetAppGroups(MessageBuffer &buffer, MessageBuffer &send, uid_t uid, pid_t pid) { + std::string appId; std::unordered_set gids; + int ret; - try { - std::string appId; - std::string pkgId; - std::string smackLabel; - std::string uidStr = std::to_string(uid); - std::string pidStr = std::to_string(pid); - - Deserialization::Deserialize(buffer, appId); - LogDebug("appId: " << appId); - - if (!PrivilegeDb::getInstance().GetAppPkgId(appId, pkgId)) { - LogWarning("Application " << appId << " not found in database"); - Serialization::Serialize(send, SECURITY_MANAGER_API_ERROR_NO_SUCH_OBJECT); - return false; - } - LogDebug("pkgId: " << pkgId); - - if (!generateAppLabel(pkgId, smackLabel)) { - LogError("Cannot generate Smack label for package: " << pkgId); - Serialization::Serialize(send, SECURITY_MANAGER_API_ERROR_NO_SUCH_OBJECT); - return false; - } - LogDebug("smack label: " << smackLabel); - - std::vector privileges; - PrivilegeDb::getInstance().GetPkgPrivileges(pkgId, uid, privileges); - /*there is also a need of checking, if privilege is granted to all users*/ - size_t tmp = privileges.size(); - PrivilegeDb::getInstance().GetPkgPrivileges(pkgId, getGlobalUserId(), privileges); - /*privileges needs to be sorted and with no duplications - for cynara sake*/ - std::inplace_merge(privileges.begin(), privileges.begin() + tmp, privileges.end()); - privileges.erase( unique( privileges.begin(), privileges.end() ), privileges.end() ); - - for (const auto &privilege : privileges) { - std::vector gidsTmp; - PrivilegeDb::getInstance().GetPrivilegeGroups(privilege, gidsTmp); - if (!gidsTmp.empty()) { - LogDebug("Considering privilege " << privilege << " with " << - gidsTmp.size() << " groups assigned"); - if (Cynara::getInstance().check(smackLabel, privilege, uidStr, pidStr)) { - for_each(gidsTmp.begin(), gidsTmp.end(), [&] (std::string group) - { - struct group *grp = getgrnam(group.c_str()); - if (grp == NULL) { - LogError("No such group: " << group.c_str()); - return; - } - gids.insert(grp->gr_gid); - }); - LogDebug("Cynara allowed, adding groups"); - } else - LogDebug("Cynara denied, not adding groups"); - } + Deserialization::Deserialize(buffer, appId); + ret = ServiceImpl::getAppGroups(appId, uid, pid, gids); + Serialization::Serialize(send, ret); + if (ret == SECURITY_MANAGER_API_SUCCESS) { + Serialization::Serialize(send, static_cast(gids.size())); + for (const auto &gid : gids) { + Serialization::Serialize(send, gid); } - } catch (const PrivilegeDb::Exception::Base &e) { - LogError("Database error: " << e.DumpToString()); - Serialization::Serialize(send, SECURITY_MANAGER_API_ERROR_SERVER_ERROR); - return false; - } catch (const CynaraException::Base &e) { - LogError("Error while querying Cynara for permissions: " << e.DumpToString()); - Serialization::Serialize(send, SECURITY_MANAGER_API_ERROR_SERVER_ERROR); - return false; - } catch (const std::bad_alloc &e) { - LogError("Memory allocation failed: " << e.what()); - Serialization::Serialize(send, SECURITY_MANAGER_API_ERROR_OUT_OF_MEMORY); - return false; - } - - // success - Serialization::Serialize(send, SECURITY_MANAGER_API_SUCCESS); - Serialization::Serialize(send, static_cast(gids.size())); - for (const auto &gid : gids) { - Serialization::Serialize(send, gid); } - return true; }