From 675972c373489c107e5a5dbf2efa3e545a91dc9c Mon Sep 17 00:00:00 2001 From: Rafal Krypa Date: Wed, 13 Apr 2016 16:55:51 +0200 Subject: [PATCH] Integrate with Cynara, clients must be privileged Several API functions now require the caller to hold appropriate privilege. Ultimately new internal privileges will be created and used by security-manager. For now, when appropriate privilege is missing, use "notexist" privilege placeholder. Privileges required per API: - security_manager_app_install * http://tizen.org/privilege/notexist (private installation) * http://tizen.org/privilege/notexist (global installation) - security_manager_app_uninstall * http://tizen.org/privilege/notexist (private uninstallation) * http://tizen.org/privilege/notexist (global uninstallation) - security_manager_private_sharing_apply * http://tizen.org/privilege/notexist - security_manager_private_sharing_drop * http://tizen.org/privilege/notexist - security_manager_policy_update_send * http://tizen.org/privilege/notexist (for setting own policy) * http://tizen.org/privilege/internal/usermanagement (for setting policy for other or all) - security_manager_get_configured_policy_for_admin * http://tizen.org/privilege/internal/usermanagement - security_manager_get_configured_policy_for_self * http://tizen.org/privilege/notexist - security_manager_get_policy * http://tizen.org/privilege/notexist (for fetching own policy) * http://tizen.org/privilege/internal/usermanagement (for fetching policy for other or all) - security_manager_user_add * http://tizen.org/privilege/internal/usermanagement - security_manager_user_delete * http://tizen.org/privilege/internal/usermanagement Change-Id: Id67473db434b13d977fbd2fa704db3ac1bd1c32b Signed-off-by: Rafal Krypa --- src/client/client-security-manager.cpp | 7 +- src/common/CMakeLists.txt | 1 + src/common/config.cpp | 10 +- src/common/credentials.cpp | 47 +++++ src/common/include/config.h | 10 +- src/common/include/credentials.h | 56 ++++++ src/common/include/service_impl.h | 59 +++--- src/common/include/smack-labels.h | 10 +- src/common/service_impl.cpp | 322 +++++++++++++++++------------- src/common/smack-labels.cpp | 13 +- src/include/app-manager.h | 8 + src/include/app-sharing.h | 6 + src/include/policy-manager.h | 24 ++- src/include/user-manager.h | 6 + src/server/service/base-service.cpp | 22 +- src/server/service/include/base-service.h | 14 +- src/server/service/include/service.h | 51 +++-- src/server/service/service.cpp | 79 ++++---- 18 files changed, 454 insertions(+), 291 deletions(-) create mode 100644 src/common/credentials.cpp create mode 100644 src/common/include/credentials.h diff --git a/src/client/client-security-manager.cpp b/src/client/client-security-manager.cpp index 1e0fbcf..3420e9a 100755 --- a/src/client/client-security-manager.cpp +++ b/src/client/client-security-manager.cpp @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -192,7 +193,8 @@ int security_manager_app_install(const app_inst_req *p_req) int retval; ClientOffline offlineMode; if (offlineMode.isOffline()) { - retval = SecurityManager::ServiceImpl().appInstall(*p_req, geteuid()); + Credentials creds = SecurityManager::Credentials::getCredentialsFromSelf(); + retval = SecurityManager::ServiceImpl().appInstall(creds, app_inst_req(*p_req)); } else { MessageBuffer send, recv; @@ -578,7 +580,8 @@ int security_manager_user_add(const user_req *p_req) int retval; ClientOffline offlineMode; if (offlineMode.isOffline()) { - retval = SecurityManager::ServiceImpl().userAdd(p_req->uid, p_req->utype, geteuid()); + Credentials creds = SecurityManager::Credentials::getCredentialsFromSelf(); + retval = SecurityManager::ServiceImpl().userAdd(creds, p_req->uid, p_req->utype); } else { MessageBuffer send, recv; //server is working diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 3a9d3c9..582f7db 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -44,6 +44,7 @@ SET(COMMON_SOURCES ${DPL_PATH}/db/src/sql_connection.cpp ${COMMON_PATH}/config.cpp ${COMMON_PATH}/connection.cpp + ${COMMON_PATH}/credentials.cpp ${COMMON_PATH}/cynara.cpp ${COMMON_PATH}/file-lock.cpp ${COMMON_PATH}/protocols.cpp diff --git a/src/common/config.cpp b/src/common/config.cpp index 445662b..8b15c21 100644 --- a/src/common/config.cpp +++ b/src/common/config.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2015-2016 Samsung Electronics Co., Ltd All Rights Reserved * * Contact: Rafal Krypa * @@ -35,6 +35,14 @@ const std::string PRIVILEGE_VERSION = "3.0" #endif ; + +const std::string PRIVILEGE_APPINST_USER = "http://tizen.org/privilege/notexist"; +const std::string PRIVILEGE_APPINST_ADMIN = "http://tizen.org/privilege/notexist"; +const std::string PRIVILEGE_USER_ADMIN = "http://tizen.org/privilege/internal/usermanagement"; +const std::string PRIVILEGE_POLICY_USER = "http://tizen.org/privilege/notexist"; +const std::string PRIVILEGE_POLICY_ADMIN = "http://tizen.org/privilege/internal/usermanagement"; +const std::string PRIVILEGE_APPSHARING_ADMIN = "http://tizen.org/privilege/notexist"; + }; } /* namespace SecurityManager */ diff --git a/src/common/credentials.cpp b/src/common/credentials.cpp new file mode 100644 index 0000000..171326e --- /dev/null +++ b/src/common/credentials.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2016 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 credentials.cpp + * @author Rafal Krypa + * @version 1.0 + */ + +#include +#include + +#include "smack-labels.h" +#include "credentials.h" + +namespace SecurityManager { + +Credentials Credentials::getCredentialsFromSelf(void) +{ + return Credentials(getpid(), geteuid(), getegid(), + SmackLabels::getSmackLabelFromSelf()); +} + +Credentials Credentials::getCredentialsFromSocket(int sock) +{ + struct ucred cr; + socklen_t len = sizeof(cr); + + if (getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &cr, &len) == -1) + ThrowMsg(Exception::SocketError, "Failed to read peer credentials for sockfd " << sock); + + return Credentials(cr.pid, cr.uid, cr.gid, SmackLabels::getSmackLabelFromSocket(sock)); +} + +} // namespace SecurityManager diff --git a/src/common/include/config.h b/src/common/include/config.h index 742b092..4bb655f 100644 --- a/src/common/include/config.h +++ b/src/common/include/config.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2015-2016 Samsung Electronics Co., Ltd All Rights Reserved * * Contact: Rafal Krypa * @@ -33,6 +33,14 @@ namespace Config { extern const std::string PRIVILEGE_VERSION; +/* Privileges required from users of our API */ +extern const std::string PRIVILEGE_APPINST_USER; +extern const std::string PRIVILEGE_APPINST_ADMIN; +extern const std::string PRIVILEGE_USER_ADMIN; +extern const std::string PRIVILEGE_POLICY_USER; +extern const std::string PRIVILEGE_POLICY_ADMIN; +extern const std::string PRIVILEGE_APPSHARING_ADMIN; + }; } /* namespace SecurityManager */ diff --git a/src/common/include/credentials.h b/src/common/include/credentials.h new file mode 100644 index 0000000..003a37e --- /dev/null +++ b/src/common/include/credentials.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2016 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 credentials.h + * @author Rafal Krypa + * @version 1.0 + */ + +#ifndef SECURITY_MANAGER_CREDENTIALS_ +#define SECURITY_MANAGER_CREDENTIALS_ + +#include +#include + +#include + +namespace SecurityManager { + +class Credentials { +public: + pid_t pid; /* process ID of the sending process */ + uid_t uid; /* user ID of the sending process */ + gid_t gid; /* group ID of the sending process */ + std::string label; /* security context of the sending process */ + + Credentials() = delete; + static Credentials getCredentialsFromSelf(void); + static Credentials getCredentialsFromSocket(int socket); + + class Exception { + public: + DECLARE_EXCEPTION_TYPE(SecurityManager::Exception, Base) + DECLARE_EXCEPTION_TYPE(Base, SocketError) + }; + +private: + Credentials(pid_t pid, uid_t uid, gid_t gid, std::string &&label) : + pid(pid), uid(uid), gid(gid), label(std::move(label)) {} +}; + +} // namespace SecurityManager + +#endif /* SECURITY_MANAGER_CREDENTIALS_ */ diff --git a/src/common/include/service_impl.h b/src/common/include/service_impl.h index 3eb25ae..b6ffc9b 100644 --- a/src/common/include/service_impl.h +++ b/src/common/include/service_impl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2014-2016 Samsung Electronics Co., Ltd All Rights Reserved * * Contact: Rafal Krypa * @@ -29,6 +29,7 @@ #include +#include "credentials.h" #include "security-manager.h" namespace SecurityManager { @@ -37,13 +38,15 @@ class ServiceImpl { private: static uid_t getGlobalUserId(void); - static void checkGlobalUser(uid_t &uid, std::string &cynaraUserStr); - static bool isSubDir(const char *parent, const char *subdir); static bool getUserAppDir(const uid_t &uid, std::string &userAppDir); - static bool installRequestAuthCheck(const app_inst_req &req, uid_t uid, std::string &appPath); + static void installRequestMangle(app_inst_req &req, std::string &cynaraUserStr); + + static bool installRequestAuthCheck(const Credentials &creds, const app_inst_req &req); + + static bool installRequestPathsCheck(const app_inst_req &req, std::string &appPath); static bool getZoneId(std::string &zoneId); @@ -60,22 +63,23 @@ public: /** * Process application installation request. * + * @param[in] creds credentials of the requesting process * @param[in] req installation request - * @param[in] uid id of the requesting user * * @return API return code, as defined in protocols.h */ - int appInstall(const app_inst_req &req, uid_t uid); + int appInstall(const Credentials &creds, app_inst_req &&req); /** * Process application uninstallation request. * - * @param[in] appName application identifier - * @param[in] uid id of the requesting user + * @param[in] creds credentials of the requesting process + * @param[in] req uninstallation request + * @param[in] authenticated whether the caller has been already checked against Cynara policy * * @return API return code, as defined in protocols.h */ - int appUninstall(const std::string &appName, uid_t uid); + int appUninstall(const Credentials &creds, app_inst_req &&req, bool authenticated = false); /** * Process package id query. @@ -95,49 +99,46 @@ public: * queried. * Returns set of group ids that are permitted. * + * @param[in] creds credentials of the requesting process * @param[in] appName 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 protocols.h */ - int getAppGroups(const std::string &appName, uid_t uid, pid_t pid, std::unordered_set &gids); + int getAppGroups(const Credentials &creds, const std::string &appName, std::unordered_set &gids); /** * Process user adding request. * + * @param[in] creds credentials of the requesting process * @param[in] uidAdded uid of newly created user * @param[in] userType type of newly created user - * @param[in] uid uid of requesting user * * @return API return code, as defined in protocols.h */ - int userAdd(uid_t uidAdded, int userType, uid_t uid); + int userAdd(const Credentials &creds, uid_t uidAdded, int userType); /** * Process user deletion request. * + * @param[in] creds credentials of the requesting process * @param[in] uidDeleted uid of removed user - * @param[in] uid uid of requesting user * * @return API return code, as defined in protocols.h */ - int userDelete(uid_t uidDeleted, uid_t uid); + int userDelete(const Credentials &creds, uid_t uidDeleted); /** * Update policy in Cynara - proper privilege: http://tizen.org/privilege/internal/usermanagement * is needed for this to succeed * + * @param[in] creds credentials of the requesting process * @param[in] policyEntries vector of policy chunks with instructions - * @param[in] uid identifier of requesting user - * @param[in] pid PID of requesting process - * @param[in] smackLabel smack label of requesting app * * @return API return code, as defined in protocols.h */ + int policyUpdate(const Credentials &creds, const std::vector &policyEntries); - int policyUpdate(const std::vector &policyEntries, uid_t uid, pid_t pid, const std::string &smackLabel); /** * Fetch all configured privileges from user configurable bucket. * Depending on forAdmin value: personal user policies or admin enforced @@ -145,26 +146,22 @@ public: * * @param[in] forAdmin determines if user is asking as ADMIN or not * @param[in] filter filter for limiting the query - * @param[in] uid identifier of queried user - * @param[in] pid PID of requesting process * @param[out] policyEntries vector of policy entries with result * * @return API return code, as defined in protocols.h */ - int getConfiguredPolicy(bool forAdmin, const policy_entry &filter, uid_t uid, pid_t pid, const std::string &smackLabel, std::vector &policyEntries); + int getConfiguredPolicy(const Credentials &creds, bool forAdmin, const policy_entry &filter, std::vector &policyEntries); /** * Fetch all privileges for all apps installed for specific user. * - * @param[in] forAdmin determines if user is asking as ADMIN or not + * @param[in] creds credentials of the requesting process * @param[in] filter filter for limiting the query - * @param[in] uid identifier of queried user - * @param[in] pid PID of requesting process * @param[out] policyEntries vector of policy entries with result * * @return API return code, as defined in protocols.h */ - int getPolicy(const policy_entry &filter, uid_t uid, pid_t pid, const std::string &smackLabel, std::vector &policyEntries); + int getPolicy(const Credentials &creds, const policy_entry &filter, std::vector &policyEntries); /** * Process getting policy descriptions list. @@ -199,25 +196,29 @@ public: /** * Process applying private path sharing between applications. * + * @param[in] creds credentials of the requesting process * @param[in] ownerAppName application owning paths * @param[in] targetAppName application which paths will be shared with * @param[in] paths vector of paths to be shared * * @return API return code, as defined in protocols.h */ - int applyPrivatePathSharing(const std::string &ownerAppName, + int applyPrivatePathSharing(const Credentials &creds, + const std::string &ownerAppName, const std::string &targetAppName, const std::vector &paths); /** * Process droping private path sharing between applications. * + * @param[in] creds credentials of the requesting process * @param[in] ownerAppName application owning paths * @param[in] targetAppName application which paths won't be anymore shared with * @param[in] paths vector of paths to be stopped being shared * @return API return code, as defined in protocols.h */ - int dropPrivatePathSharing(const std::string &ownerAppName, + int dropPrivatePathSharing(const Credentials &creds, + const std::string &ownerAppName, const std::string &targetAppName, const std::vector &paths); }; diff --git a/src/common/include/smack-labels.h b/src/common/include/smack-labels.h index d9138d9..fd3921c 100644 --- a/src/common/include/smack-labels.h +++ b/src/common/include/smack-labels.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2014-2016 Samsung Electronics Co., Ltd All Rights Reserved * * Contact: Rafal Krypa * @@ -147,6 +147,14 @@ std::string getSmackLabelFromPid(pid_t pid); */ std::string getSmackLabelFromPath(const std::string &path); +/** + * Returns smack label for current process + * + * @param[in] sock socket file descriptor + * @return resulting Smack label + */ +std::string getSmackLabelFromSelf(void); + } // namespace SmackLabels } // namespace SecurityManager diff --git a/src/common/service_impl.cpp b/src/common/service_impl.cpp index 0186323..66b0b1c 100755 --- a/src/common/service_impl.cpp +++ b/src/common/service_impl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2014-2016 Samsung Electronics Co., Ltd All Rights Reserved * * Contact: Rafal Krypa * @@ -48,9 +48,6 @@ namespace SecurityManager { -static const std::string ADMIN_PRIVILEGE = "http://tizen.org/privilege/internal/usermanagement"; -static const std::string SELF_PRIVILEGE = "http://tizen.org/privilege/notexist"; - namespace { static inline int validatePolicy(policy_entry &policyEntry, std::string uidStr, bool &forAdmin, CynaraAdminPolicy &cyap) @@ -183,22 +180,6 @@ uid_t ServiceImpl::getGlobalUserId(void) 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 - */ -void ServiceImpl::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)); - } -} - bool ServiceImpl::isSubDir(const char *parent, const char *subdir) { while (*parent && *subdir) @@ -244,26 +225,51 @@ bool ServiceImpl::getUserAppDir(const uid_t &uid, std::string &userAppDir) return true; } -bool ServiceImpl::installRequestAuthCheck(const app_inst_req &req, uid_t uid, std::string &appPath) +void ServiceImpl::installRequestMangle(app_inst_req &req, std::string &cynaraUserStr) { - std::string userHome; - std::string userAppDir; - std::stringstream correctPath; + uid_t globalUid = getGlobalUserId(); - if (uid != getGlobalUserId()) - LogDebug("Installation type: single user"); - else + if (req.uid == 0) + req.uid = globalUid; + + if (req.uid == globalUid) { LogDebug("Installation type: global installation"); + cynaraUserStr = CYNARA_ADMIN_WILDCARD; + } else { + LogDebug("Installation type: local installation"); + cynaraUserStr = std::to_string(static_cast(req.uid)); + } +} + +bool ServiceImpl::installRequestAuthCheck(const Credentials &creds, const app_inst_req &req) +{ + if (req.uid == getGlobalUserId() || req.uid != creds.uid) { + if (!Cynara::getInstance().check(creds.label, Config::PRIVILEGE_APPINST_ADMIN, + std::to_string(creds.uid), std::to_string(creds.pid))) { + LogError("Caller is not permitted to install applications globally"); + return false; + } + } else { + if (!Cynara::getInstance().check(creds.label, Config::PRIVILEGE_APPINST_USER, + std::to_string(creds.uid), std::to_string(creds.pid))) { + LogError("Caller is not permitted to install applications"); + return false; + } + } - if (!getUserAppDir(uid, userAppDir)) { - LogError("Failed getting app dir for user uid: " << uid); + return true; +} + +bool ServiceImpl::installRequestPathsCheck(const app_inst_req &req, std::string &appPath) +{ + if (!getUserAppDir(req.uid, appPath)) { + LogError("Failed getting app dir for user uid: " << req.uid); return false; } - appPath = userAppDir; - correctPath.clear(); - correctPath << userAppDir << "/" << req.pkgName; - LogDebug("correctPath: " << correctPath.str()); + std::string correctPath{appPath}; + correctPath.append("/").append(req.pkgName); + LogDebug("correctPath: " << correctPath); for (const auto &path : req.appPaths) { std::unique_ptr> real_path( @@ -274,41 +280,41 @@ bool ServiceImpl::installRequestAuthCheck(const app_inst_req &req, uid_t uid, st return false; } LogDebug("Requested path is '" << path.first.c_str() - << "'. User's APPS_DIR is '" << userAppDir << "'"); - if (!isSubDir(correctPath.str().c_str(), real_path.get())) { - LogWarning("Installation is outside correct path: " << correctPath.str() << "," << real_path.get()); + << "'. User's APPS_DIR is '" << appPath << "'"); + if (!isSubDir(correctPath.c_str(), real_path.get())) { + LogWarning("Installation is outside correct path: " << correctPath << "," << real_path.get()); return false; } } return true; } -int ServiceImpl::appInstall(const app_inst_req &req, uid_t uid) +int ServiceImpl::appInstall(const Credentials &creds, app_inst_req &&req) { std::vector addedPermissions; std::vector removedPermissions; std::vector pkgContents; - std::string uidstr; + std::string cynaraUserStr; std::string appPath; std::string appLabel; std::string pkgLabel; std::vector allTizen2XApps, allTizen2XPackages; int authorId; - if (uid) { - if (uid != req.uid) { - LogError("User " << uid << - " is denied to install application for user " << req.uid); - return SECURITY_MANAGER_ERROR_ACCESS_DENIED; - } - } else { - if (req.uid) - uid = req.uid; + installRequestMangle(req, cynaraUserStr); + + LogDebug("Install parameters: appName: " << req.appName << ", pkgName: " << req.pkgName + << ", uid: " << req.uid << ", target Tizen API ver: " + << (req.tizenVersion.empty() ? "unknown" : req.tizenVersion)); + + if (!installRequestAuthCheck(creds, req)) { + LogError("Request from uid=" << creds.uid << ", Smack=" << creds.label << + " for app installation denied"); + return SECURITY_MANAGER_ERROR_AUTHENTICATION_FAILED; } - checkGlobalUser(uid, uidstr); - if (!installRequestAuthCheck(req, uid, appPath)) { - LogError("Request from uid " << uid << " for app installation denied"); + if (!installRequestPathsCheck(req, appPath)) { + LogError("Installation request with paths outside expected application path"); return SECURITY_MANAGER_ERROR_AUTHENTICATION_FAILED; } @@ -317,10 +323,8 @@ int ServiceImpl::appInstall(const app_inst_req &req, uid_t uid) /* NOTE: we don't use pkgLabel here, but generate it for pkgName validation */ pkgLabel = SmackLabels::generatePkgLabel(req.pkgName); - LogDebug("Install parameters: appName: " << req.appName << ", pkgName: " << req.pkgName - << ", uidstr " << uidstr - << ", app label: " << appLabel << ", pkg label: " << pkgLabel - << ", target Tizen API ver: " << (req.tizenVersion.empty()?"unknown":req.tizenVersion)); + LogDebug("Generated install parameters: " + << "app label: " << appLabel << ", pkg label: " << pkgLabel); PrivilegeDb::getInstance().BeginTransaction(); std::string pkg; @@ -331,12 +335,12 @@ int ServiceImpl::appInstall(const app_inst_req &req, uid_t uid) return SECURITY_MANAGER_ERROR_INPUT_PARAM; } - PrivilegeDb::getInstance().AddApplication(req.appName, req.pkgName, uid, req.tizenVersion, req.authorName); - PrivilegeDb::getInstance().UpdateAppPrivileges(req.appName, uid, req.privileges); + PrivilegeDb::getInstance().AddApplication(req.appName, req.pkgName, req.uid, req.tizenVersion, req.authorName); + PrivilegeDb::getInstance().UpdateAppPrivileges(req.appName, req.uid, req.privileges); /* Get all application ids in the package to generate rules withing the package */ PrivilegeDb::getInstance().GetPkgApps(req.pkgName, pkgContents); PrivilegeDb::getInstance().GetAppAuthorId(req.appName, authorId); - CynaraAdmin::getInstance().UpdateAppPolicy(appLabel, uidstr, req.privileges); + CynaraAdmin::getInstance().UpdateAppPolicy(appLabel, cynaraUserStr, req.privileges); // if app is targetted to Tizen 2.X, give other 2.X apps RO rules to it's shared dir if(isTizen2XVersion(req.tizenVersion)) @@ -401,49 +405,59 @@ int ServiceImpl::appInstall(const app_inst_req &req, uid_t uid) return SECURITY_MANAGER_SUCCESS; } -int ServiceImpl::appUninstall(const std::string &appName, uid_t uid) +int ServiceImpl::appUninstall(const Credentials &creds, app_inst_req &&req, + bool authenticated) { - std::string pkgName; std::string tizenVersion; std::string smackLabel; std::vector pkgContents; bool removeApp = false; bool removePkg = false; bool removeAuthor = false; - std::string uidstr; + std::string cynaraUserStr; std::vector allTizen2XApps; int authorId; - checkGlobalUser(uid, uidstr); + installRequestMangle(req, cynaraUserStr); + + LogDebug("Uninstall parameters: appName=" << req.appName << ", uid=" << req.uid); + + if (!authenticated && !installRequestAuthCheck(creds, req)) { + LogError("Request from uid=" << creds.uid << ", Smack=" << creds.label << + " for app uninstallation denied"); + return SECURITY_MANAGER_ERROR_AUTHENTICATION_FAILED; + } try { PrivilegeDb::getInstance().BeginTransaction(); - PrivilegeDb::getInstance().GetAppPkgName(appName, pkgName); - if (pkgName.empty()) { - LogWarning("Application " << appName << + if (req.pkgName.empty()) + PrivilegeDb::getInstance().GetAppPkgName(req.appName, req.pkgName); + + if (req.pkgName.empty()) { + LogWarning("Application " << req.appName << " not found in database while uninstalling"); PrivilegeDb::getInstance().RollbackTransaction(); return SECURITY_MANAGER_SUCCESS; } - smackLabel = SmackLabels::generateAppLabel(appName); - LogDebug("Uninstall parameters: appName: " << appName << ", pkgName: " << pkgName - << ", uidstr " << uidstr << ", generated smack label: " << smackLabel); + smackLabel = SmackLabels::generateAppLabel(req.appName); + LogDebug("Generated uninstall parameters: pkgName=" << req.pkgName + << " Smack label=" << smackLabel); /* Before we remove the app from the database, let's fetch all apps in the package that this app belongs to, this will allow us to remove all rules withing the package that the app appears in */ - PrivilegeDb::getInstance().GetAppAuthorId(appName, authorId); - PrivilegeDb::getInstance().GetPkgApps(pkgName, pkgContents); - PrivilegeDb::getInstance().UpdateAppPrivileges(appName, uid, std::vector()); - PrivilegeDb::getInstance().RemoveApplication(appName, uid, removeApp, removePkg, removeAuthor); + PrivilegeDb::getInstance().GetAppAuthorId(req.appName, authorId); + PrivilegeDb::getInstance().GetPkgApps(req.pkgName, pkgContents); + PrivilegeDb::getInstance().UpdateAppPrivileges(req.appName, req.uid, std::vector()); + PrivilegeDb::getInstance().RemoveApplication(req.appName, req.uid, removeApp, removePkg, removeAuthor); // if uninstalled app is targetted to Tizen 2.X, remove other 2.X apps RO rules it's shared dir - PrivilegeDb::getInstance().GetAppVersion(appName, tizenVersion); + PrivilegeDb::getInstance().GetAppVersion(req.appName, tizenVersion); if (isTizen2XVersion(tizenVersion)) - PrivilegeDb::getInstance().GetTizen2XApps(appName, allTizen2XApps); + PrivilegeDb::getInstance().GetTizen2XApps(req.appName, allTizen2XApps); - CynaraAdmin::getInstance().UpdateAppPolicy(smackLabel, uidstr, std::vector()); + CynaraAdmin::getInstance().UpdateAppPolicy(smackLabel, cynaraUserStr, std::vector()); PrivilegeDb::getInstance().CommitTransaction(); LogDebug("Application uninstallation commited to database"); @@ -470,13 +484,13 @@ int ServiceImpl::appUninstall(const std::string &appName, uid_t uid) try { if (removeApp) { - LogDebug("Removing smack rules for deleted appName " << appName); - SmackRules::uninstallApplicationRules(appName); - LogDebug("Pkg rules are deprecated. We must uninstall them. pkgName " << pkgName); - SmackRules::uninstallPackageRules(pkgName); + LogDebug("Removing Smack rules for appName " << req.appName); + SmackRules::uninstallApplicationRules(req.appName); + LogDebug("Removing Smack rules for pkgName " << req.pkgName); + SmackRules::uninstallPackageRules(req.pkgName); if (!removePkg) { - LogDebug("Creating new rules for pkgName " << pkgName); - SmackRules::updatePackageRules(pkgName, pkgContents, allTizen2XApps); + LogDebug("Recreating Smack rules for pkgName " << req.pkgName); + SmackRules::updatePackageRules(req.pkgName, pkgContents, allTizen2XApps); } } @@ -515,17 +529,14 @@ int ServiceImpl::getPkgName(const std::string &appName, std::string &pkgName) return SECURITY_MANAGER_SUCCESS; } -int ServiceImpl::getAppGroups( - const std::string &appName, - uid_t uid, - pid_t pid, - std::unordered_set &gids) +int ServiceImpl::getAppGroups(const Credentials &creds, const std::string &appName, + std::unordered_set &gids) { try { std::string pkgName; std::string smackLabel; - std::string uidStr = std::to_string(uid); - std::string pidStr = std::to_string(pid); + std::string uidStr = std::to_string(creds.uid); + std::string pidStr = std::to_string(creds.pid); LogDebug("appName: " << appName); @@ -540,7 +551,7 @@ int ServiceImpl::getAppGroups( LogDebug("smack label: " << smackLabel); std::vector privileges; - PrivilegeDb::getInstance().GetPkgPrivileges(pkgName, uid, privileges); + PrivilegeDb::getInstance().GetPkgPrivileges(pkgName, creds.uid, privileges); /*there is also a need of checking, if privilege is granted to all users*/ size_t tmp = privileges.size(); PrivilegeDb::getInstance().GetPkgPrivileges(pkgName, getGlobalUserId(), privileges); @@ -586,10 +597,14 @@ int ServiceImpl::getAppGroups( return SECURITY_MANAGER_SUCCESS; } -int ServiceImpl::userAdd(uid_t uidAdded, int userType, uid_t uid) +int ServiceImpl::userAdd(const Credentials &creds, uid_t uidAdded, int userType) { - if (uid != 0) + if (!Cynara::getInstance().check(creds.label, Config::PRIVILEGE_USER_ADMIN, + std::to_string(creds.uid), std::to_string(creds.pid))) { + + LogError("Caller is not permitted to manage users"); return SECURITY_MANAGER_ERROR_AUTHENTICATION_FAILED; + } try { CynaraAdmin::getInstance().UserInit(uidAdded, static_cast(userType)); @@ -599,11 +614,16 @@ int ServiceImpl::userAdd(uid_t uidAdded, int userType, uid_t uid) return SECURITY_MANAGER_SUCCESS; } -int ServiceImpl::userDelete(uid_t uidDeleted, uid_t uid) +int ServiceImpl::userDelete(const Credentials &creds, uid_t uidDeleted) { int ret = SECURITY_MANAGER_SUCCESS; - if (uid != 0) + + if (!Cynara::getInstance().check(creds.label, Config::PRIVILEGE_USER_ADMIN, + std::to_string(creds.uid), std::to_string(creds.pid))) { + + LogError("Caller is not permitted to manage users"); return SECURITY_MANAGER_ERROR_AUTHENTICATION_FAILED; + } /*Uninstall all user apps*/ std::vector userApps; @@ -614,8 +634,11 @@ int ServiceImpl::userDelete(uid_t uidDeleted, uid_t uid) return SECURITY_MANAGER_ERROR_SERVER_ERROR; } - for (auto &app: userApps) { - if (appUninstall(app, uidDeleted) != SECURITY_MANAGER_SUCCESS) { + for (const auto &app : userApps) { + app_inst_req req; + req.uid = uidDeleted; + req.appName = app; + if (appUninstall(creds, std::move(req), true) != SECURITY_MANAGER_SUCCESS) { /*if uninstallation of this app fails, just go on trying to uninstall another ones. we do not have anything special to do about that matter - user will be deleted anyway.*/ ret = SECURITY_MANAGER_ERROR_SERVER_ERROR; @@ -627,28 +650,20 @@ int ServiceImpl::userDelete(uid_t uidDeleted, uid_t uid) return ret; } -int ServiceImpl::policyUpdate(const std::vector &policyEntries, uid_t uid, pid_t pid, const std::string &smackLabel) +int ServiceImpl::policyUpdate(const Credentials &creds, const std::vector &policyEntries) { - enum { - NOT_CHECKED, - IS_NOT_ADMIN, - IS_ADMIN - } isAdmin = NOT_CHECKED; + bool permAdminRequired = false; + bool permUserRequired = false; try { - std::string uidStr = std::to_string(uid); - std::string pidStr = std::to_string(pid); + std::string uidStr = std::to_string(creds.uid); + std::string pidStr = std::to_string(creds.pid); if (policyEntries.size() == 0) { LogError("Validation failed: policy update request is empty"); return SECURITY_MANAGER_ERROR_BAD_REQUEST; }; - if (!Cynara::getInstance().check(smackLabel, SELF_PRIVILEGE, uidStr, pidStr)) { - LogError("Not enough permission to call: " << __FUNCTION__); - return SECURITY_MANAGER_ERROR_ACCESS_DENIED; - }; - std::vector validatedPolicies; for (auto &entry : const_cast&>(policyEntries)) { @@ -656,24 +671,31 @@ int ServiceImpl::policyUpdate(const std::vector &policyEntries, ui CynaraAdminPolicy cyap("", "", "", CYNARA_ADMIN_NONE, ""); int ret = validatePolicy(entry, uidStr, forAdmin, cyap); - if (forAdmin && (isAdmin == NOT_CHECKED)) { - isAdmin = Cynara::getInstance().check(smackLabel, ADMIN_PRIVILEGE, uidStr, pidStr)?IS_ADMIN:IS_NOT_ADMIN; - }; + if (ret != SECURITY_MANAGER_SUCCESS) + return ret; - if (ret == SECURITY_MANAGER_SUCCESS) { - if (!forAdmin - || (forAdmin && (isAdmin == IS_ADMIN))) { - validatedPolicies.push_back(std::move(cyap)); - } else { - LogError("Not enough privilege to enforce admin policy"); - return SECURITY_MANAGER_ERROR_ACCESS_DENIED; - }; + if (forAdmin) + permAdminRequired = true; + else + permUserRequired = true; - } else - return ret; + validatedPolicies.push_back(std::move(cyap)); }; - // Apply updates + // Check privileges + if (permUserRequired && !Cynara::getInstance().check(creds.label, + Config::PRIVILEGE_POLICY_USER, uidStr, pidStr)) { + LogError("Not enough privilege to enforce user policy"); + return SECURITY_MANAGER_ERROR_ACCESS_DENIED; + } + + if (permAdminRequired && !Cynara::getInstance().check(creds.label, + Config::PRIVILEGE_POLICY_ADMIN, uidStr, pidStr)) { + LogError("Not enough privilege to enforce admin policy"); + return SECURITY_MANAGER_ERROR_ACCESS_DENIED; + } + + // Apply updates CynaraAdmin::getInstance().SetPolicies(validatedPolicies); } catch (const CynaraException::Base &e) { @@ -687,17 +709,12 @@ int ServiceImpl::policyUpdate(const std::vector &policyEntries, ui return SECURITY_MANAGER_SUCCESS; } -int ServiceImpl::getConfiguredPolicy(bool forAdmin, const policy_entry &filter, uid_t uid, pid_t pid, - const std::string &smackLabel, std::vector &policyEntries) +int ServiceImpl::getConfiguredPolicy(const Credentials &creds, bool forAdmin, + const policy_entry &filter, std::vector &policyEntries) { try { - std::string uidStr = std::to_string(uid); - std::string pidStr = std::to_string(pid); - - if (!Cynara::getInstance().check(smackLabel, SELF_PRIVILEGE, uidStr, pidStr)) { - LogError("Not enough permission to call: " << __FUNCTION__); - return SECURITY_MANAGER_ERROR_ACCESS_DENIED; - }; + std::string uidStr = std::to_string(creds.uid); + std::string pidStr = std::to_string(creds.pid); LogDebug("Filter is: C: " << filter.appName << ", U: " << filter.user @@ -716,10 +733,10 @@ int ServiceImpl::getConfiguredPolicy(bool forAdmin, const policy_entry &filter, LogDebug("App: " << filter.appName << ", Label: " << appLabel); if (forAdmin) { - if (!Cynara::getInstance().check(smackLabel, ADMIN_PRIVILEGE, uidStr, pidStr)) { - LogError("Not enough privilege to access admin enforced policies: " << __FUNCTION__); + if (!Cynara::getInstance().check(creds.label, Config::PRIVILEGE_POLICY_ADMIN, uidStr, pidStr)) { + LogError("Not enough privilege to access admin enforced policies"); return SECURITY_MANAGER_ERROR_ACCESS_DENIED; - }; + } //Fetch privileges from ADMIN bucket CynaraAdmin::getInstance().ListPolicies( @@ -731,8 +748,13 @@ int ServiceImpl::getConfiguredPolicy(bool forAdmin, const policy_entry &filter, ); LogDebug("ADMIN - number of policies matched: " << listOfPolicies.size()); } else { + if (!Cynara::getInstance().check(creds.label, Config::PRIVILEGE_POLICY_USER, uidStr, pidStr)) { + LogError("Not enough privilege to access user enforced policies"); + return SECURITY_MANAGER_ERROR_ACCESS_DENIED; + } + if (uidStr.compare(user)) { - if (!Cynara::getInstance().check(smackLabel, ADMIN_PRIVILEGE, uidStr, pidStr)) { + if (!Cynara::getInstance().check(creds.label, Config::PRIVILEGE_POLICY_ADMIN, uidStr, pidStr)) { LogWarning("Not enough privilege to access other user's personal policies. Limiting query to personal privileges."); user = uidStr; }; @@ -797,13 +819,14 @@ int ServiceImpl::getConfiguredPolicy(bool forAdmin, const policy_entry &filter, return SECURITY_MANAGER_SUCCESS; } -int ServiceImpl::getPolicy(const policy_entry &filter, uid_t uid, pid_t pid, const std::string &smackLabel, std::vector &policyEntries) +int ServiceImpl::getPolicy(const Credentials &creds, const policy_entry &filter, + std::vector &policyEntries) { try { - std::string uidStr = std::to_string(uid); - std::string pidStr = std::to_string(pid); + std::string uidStr = std::to_string(creds.uid); + std::string pidStr = std::to_string(creds.pid); - if (!Cynara::getInstance().check(smackLabel, SELF_PRIVILEGE, uidStr, pidStr)) { + if (!Cynara::getInstance().check(creds.label, Config::PRIVILEGE_POLICY_USER, uidStr, pidStr)) { LogWarning("Not enough permission to call: " << __FUNCTION__); return SECURITY_MANAGER_ERROR_ACCESS_DENIED; }; @@ -817,7 +840,7 @@ int ServiceImpl::getPolicy(const policy_entry &filter, uid_t uid, pid_t pid, con std::vector listOfUsers; - if (Cynara::getInstance().check(smackLabel, ADMIN_PRIVILEGE, uidStr, pidStr)) { + if (Cynara::getInstance().check(creds.label, Config::PRIVILEGE_POLICY_ADMIN, uidStr, pidStr)) { LogDebug("User is privileged"); if (filter.user.compare(SECURITY_MANAGER_ANY)) { LogDebug("Limitting Cynara query to user: " << filter.user); @@ -829,9 +852,9 @@ int ServiceImpl::getPolicy(const policy_entry &filter, uid_t uid, pid_t pid, con } else CynaraAdmin::getInstance().ListUsers(listOfUsers); } else { - LogWarning("Not enough privilege to fetch user policy for all users by user: " << uid); - LogDebug("Fetching personal policy for user: " << uid); - listOfUsers.push_back(uid); + LogWarning("Not enough privilege to fetch user policy for all users by user: " << creds.uid); + LogDebug("Fetching personal policy for user: " << creds.uid); + listOfUsers.push_back(creds.uid); }; LogDebug("Fetching policy for " << listOfUsers.size() << " users"); @@ -1027,6 +1050,7 @@ int ServiceImpl::dropOnePrivateSharing( } int ServiceImpl::applyPrivatePathSharing( + const Credentials &creds, const std::string &ownerAppName, const std::string &targetAppName, const std::vector &paths) @@ -1038,6 +1062,12 @@ int ServiceImpl::applyPrivatePathSharing( std::vector pkgContents; try { + if (!Cynara::getInstance().check(creds.label, Config::PRIVILEGE_APPSHARING_ADMIN, + std::to_string(creds.uid), std::to_string(creds.pid))) { + LogError("Caller is not permitted to manage file sharing"); + return SECURITY_MANAGER_ERROR_ACCESS_DENIED; + } + PrivilegeDb::getInstance().GetAppPkgName(ownerAppName, ownerPkgName); if (ownerPkgName.empty()) { LogError(ownerAppName << " is not an installed application"); @@ -1119,12 +1149,19 @@ int ServiceImpl::applyPrivatePathSharing( } int ServiceImpl::dropPrivatePathSharing( + const Credentials &creds, const std::string &ownerAppName, const std::string &targetAppName, const std::vector &paths) { int errorRet; try { + if (!Cynara::getInstance().check(creds.label, Config::PRIVILEGE_APPSHARING_ADMIN, + std::to_string(creds.uid), std::to_string(creds.pid))) { + LogError("Caller is not permitted to manage file sharing"); + return SECURITY_MANAGER_ERROR_ACCESS_DENIED; + } + std::string ownerPkgName; PrivilegeDb::getInstance().GetAppPkgName(ownerAppName, ownerPkgName); if (ownerPkgName.empty()) { @@ -1193,4 +1230,3 @@ int ServiceImpl::dropPrivatePathSharing( } } /* namespace SecurityManager */ - diff --git a/src/common/smack-labels.cpp b/src/common/smack-labels.cpp index 4d6dc47..6674589 100755 --- a/src/common/smack-labels.cpp +++ b/src/common/smack-labels.cpp @@ -300,11 +300,22 @@ std::string getSmackLabelFromPid(pid_t pid) "/attr/current file read error for pid: " << pid); if (smack_label_length(result.c_str()) <= 0) - ThrowMsg(SmackException::InvalidLabel, "Invalid Smack label for process " << pid); + ThrowMsg(SmackException::InvalidLabel, "Error while fetching Smack label for process " << pid); return result; } +std::string getSmackLabelFromSelf(void) +{ + char *label = nullptr; + ssize_t labelSize = smack_new_label_from_self(&label); + if (labelSize <= 0) + ThrowMsg(SmackException::InvalidLabel, "Error while fetching Smack label for current process"); + + std::unique_ptr labelPtr(label, free); + return std::string(labelPtr.get(), labelSize); +} + std::string generateAuthorLabel(const int authorId) { if (authorId < 0) { diff --git a/src/include/app-manager.h b/src/include/app-manager.h index 1d90b6a..f58ff65 100644 --- a/src/include/app-manager.h +++ b/src/include/app-manager.h @@ -115,6 +115,10 @@ int security_manager_app_inst_req_set_author_id(app_inst_req *p_req, const char * This function is used to install application based on * using filled up app_inst_req data structure * + * Required privileges: + * - http://tizen.org/privilege/notexist (local installation) + * - http://tizen.org/privilege/notexist (global installation) + * * \param[in] Pointer handling app_inst_req structure * \return API return code or error code: it would be * - SECURITY_MANAGER_SUCCESS on success, @@ -128,6 +132,10 @@ int security_manager_app_install(const app_inst_req *p_req); * This function is used to uninstall application based on * using filled up app_inst_req data structure * + * Required privileges: + * - http://tizen.org/privilege/notexist (private uninstallation) + * - http://tizen.org/privilege/notexist (global uninstallation) + * * \param[in] Pointer handling app_inst_req structure * \return API return code or error code */ diff --git a/src/include/app-sharing.h b/src/include/app-sharing.h index 9528c88..ad510e7 100644 --- a/src/include/app-sharing.h +++ b/src/include/app-sharing.h @@ -85,6 +85,9 @@ int security_manager_private_sharing_req_add_paths(private_sharing_req *p_req, * This function is used to apply private sharing based on given private_sharing_req. * One path can be shared with multiple applications at the same time. * + * Required privileges: + * - http://tizen.org/privilege/notexist + * * \param[in] Pointer handling private_sharing_req structure * \return API return code or error code: it would be * - SECURITY_MANAGER_SUCCESS on success, @@ -96,6 +99,9 @@ int security_manager_private_sharing_apply(const private_sharing_req *p_req); /* * This function is used to drop private sharing based on given private_sharing_req. * + * Required privileges: + * - http://tizen.org/privilege/notexist + * * \param[in] Pointer handling private_sharing_req structure * \return API return code or error code: it would be * - SECURITY_MANAGER_SUCCESS on success, diff --git a/src/include/policy-manager.h b/src/include/policy-manager.h index b703e18..98a0587 100644 --- a/src/include/policy-manager.h +++ b/src/include/policy-manager.h @@ -136,8 +136,6 @@ int security_manager_policy_entry_set_level(policy_entry *p_entry, const char *p * in p_entry structure. * * This function is intended to be used by admin to change level of privilege. - * If it is used by user that has no http://tizen.org/privilege/internal/usermanagement - * privilege, then security_manager_policy_update_send will return error code. * * \param[in] p_entry Pointer handling policy_entry structure * \param[in] policy_level Policy level to be set. This may be one of strings @@ -249,6 +247,10 @@ const char *security_manager_policy_entry_get_max_level(policy_entry *p_entry); * 3. For user's personal policy: wildcards usage in application or privilege field of policy_entry * is not allowed * + * Required privileges: + * - http://tizen.org/privilege/notexist (for setting own policy) + * - http://tizen.org/privilege/internal/usermanagement (for setting policy for other or all) + * * \param[in] p_req Pointer handling allocated policy_update_req structure * \return API return code or error code * @@ -339,13 +341,12 @@ int security_manager_policy_update_send(policy_update_req *p_req); * \brief Function fetches all privileges enforced by admin user. * The result is stored in the policy_entry structures array. * - * \note It should be called by user with http://tizen.org/privilege/internal/usermanagement privilege. - * Normal users may list their personal policy entries using - * security_manager_get_configured_policy_for_self() API function. - * * \attention Developer is responsible for calling security_manager_policy_entries_free() * for freeing allocated resources. * + * Required privileges: + * - http://tizen.org/privilege/internal/usermanagement + * * \param[in] p_filter Pointer to filter struct * \param[out] ppp_privs_policy Pointer handling allocated policy_entry structures array * \param[out] p_size Pointer where the size of allocated array will be stored @@ -363,6 +364,9 @@ int security_manager_get_configured_policy_for_admin( * * \attention Developer is responsible for calling security_manager_policy_entries_free() * for freeing allocated resources. + + * Required privileges: + * - http://tizen.org/privilege/notexist * * \param[in] p_filter Pointer to filter struct * \param[out] ppp_privs_policy Pointer handling allocated policy_entry structures array @@ -378,13 +382,13 @@ int security_manager_get_configured_policy_for_self( * \brief Function gets the whole policy for all users, their applications and privileges * based on the provided filter. The result is stored in the policy_entry array. * - * \note If this call is performed by user with http://tizen.org/privilege/internal/usermanagement - * privilege, then it's possible to list policies for all users. - * Normal users may only list privileges for their own UID. - * * \attention Developer is responsible for calling security_manager_policy_entries_free() * for freeing allocated resources. * + * Required privileges: + * - http://tizen.org/privilege/notexist (for fetching own policy) + * - http://tizen.org/privilege/internal/usermanagement (for fetching policy for other or all) + * * \param[in] p_filter Pointer to filter struct * \param[out] ppp_privs_policy Pointer handling allocated policy_entry structures array * \param[out] p_size Pointer where the size of allocated array will be stored diff --git a/src/include/user-manager.h b/src/include/user-manager.h index e577fd0..69dc38e 100644 --- a/src/include/user-manager.h +++ b/src/include/user-manager.h @@ -67,6 +67,9 @@ int security_manager_user_req_set_user_type(user_req *p_req, security_manager_us * This function succeeds only when is called by privileged user. * Otherwise it just returns SECURITY_MANAGER_ERROR_AUTHENTICATION_FAILED and does nothing. * + * Required privileges: + * - http://tizen.org/privilege/internal/usermanagement + * * It adds all required privileges to a newly created user. * User data are passed through pointer 'p_req'. * @param p_req Structure containing user data filled before calling this @@ -81,6 +84,9 @@ int security_manager_user_add(const user_req *p_req); * This function succeeds only when is called by privileged user. * Otherwise it just returns SECURITY_MANAGER_ERROR_AUTHENTICATION_FAILED and does nothing. * + * Required privileges: + * - http://tizen.org/privilege/internal/usermanagement + * * It removes all privileges granted to a user that has been granted previously by * security_manager_user_add. * diff --git a/src/server/service/base-service.cpp b/src/server/service/base-service.cpp index 32360cb..865284b 100644 --- a/src/server/service/base-service.cpp +++ b/src/server/service/base-service.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd All Rights Reserved * * Contact: Rafal Krypa * @@ -39,26 +39,6 @@ BaseService::BaseService() { } -bool BaseService::getPeerID(int sock, uid_t &uid, pid_t &pid, std::string &smackLabel) -{ - struct ucred cr; - socklen_t len = sizeof(cr); - - if (!getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &cr, &len)) { - char *smk; - ssize_t ret = smack_new_label_from_socket(sock, &smk); - if (ret < 0) - return false; - smackLabel = smk; - uid = cr.uid; - pid = cr.pid; - free(smk); - return true; - } - - return false; -} - void BaseService::accept(const AcceptEvent &event) { LogDebug("Accept event. ConnectionID.sock: " << event.connectionID.sock << diff --git a/src/server/service/include/base-service.h b/src/server/service/include/base-service.h index 5acb212..ca2753e 100644 --- a/src/server/service/include/base-service.h +++ b/src/server/service/include/base-service.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd All Rights Reserved * * Contact: Rafal Krypa * @@ -64,18 +64,6 @@ protected: ConnectionInfoMap m_connectionInfoMap; /** - * Retrieves ID (UID and PID) of peer connected to socket - * - * @param[in] sock Socket file descriptor - * @param[out] uid PID of connected peer. - * @param[out] pid PID of connected peer. - * @param[out] smackLabel Smack label of connected peer. - * - * @return True if peer ID was successfully retrieved, false otherwise. - */ - bool getPeerID(int sock, uid_t &uid, pid_t &pid, std::string &smackLabel); - - /** * Handle request from a client * * @param conn Socket connection information diff --git a/src/server/service/include/service.h b/src/server/service/include/service.h index 3940340..5b4aa8d 100644 --- a/src/server/service/include/service.h +++ b/src/server/service/include/service.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd All Rights Reserved * * Contact: Rafal Krypa * @@ -26,6 +26,7 @@ #define _SECURITY_MANAGER_SERVICE_ #include "base-service.h" +#include "credentials.h" #include "service_impl.h" namespace SecurityManager { @@ -62,18 +63,18 @@ 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 + * @param creds credentials of the requesting process */ - void processAppInstall(MessageBuffer &buffer, MessageBuffer &send, uid_t uid); + void processAppInstall(MessageBuffer &buffer, MessageBuffer &send, const Credentials &creds); /** * Process application uninstallation * * @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 + * @param creds credentials of the requesting process */ - void processAppUninstall(MessageBuffer &buffer, MessageBuffer &send, uid_t uid); + void processAppUninstall(MessageBuffer &buffer, MessageBuffer &send, const Credentials &creds); /** * Process getting package identifier from an app identifier @@ -88,25 +89,22 @@ 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 launched - * @param pid Process id in which application will be launched + * @param creds credentials of the requesting process */ - void processGetAppGroups(MessageBuffer &buffer, MessageBuffer &send, uid_t uid, pid_t pid); + void processGetAppGroups(MessageBuffer &buffer, MessageBuffer &send, const Credentials &creds); - void processUserAdd(MessageBuffer &buffer, MessageBuffer &send, uid_t uid); + void processUserAdd(MessageBuffer &buffer, MessageBuffer &send, const Credentials &creds); - void processUserDelete(MessageBuffer &buffer, MessageBuffer &send, uid_t uid); + void processUserDelete(MessageBuffer &buffer, MessageBuffer &send, const Credentials &creds); /** * Process policy update request * * @param buffer Raw received data buffer * @param send Raw data buffer to be sent - * @param uid Identifier of the user who sent the request - * @param pid PID of the process which sent the request - * @param smackLabel smack label of requesting app + * @param creds credentials of the requesting process */ - void processPolicyUpdate(MessageBuffer &buffer, MessageBuffer &send, uid_t uid, pid_t pid, const std::string &smackLabel); + void processPolicyUpdate(MessageBuffer &buffer, MessageBuffer &send, const Credentials &creds); /** * List all privileges for specific user, placed in Cynara's PRIVACY_MANAGER @@ -114,26 +112,24 @@ private: * * @param buffer Raw received data buffer * @param send Raw data buffer to be sent - * @param uid Identifier of the user who sent the request - * @param pid PID of the process which sent the request - * @param smackLabel smack label of requesting app + * @param creds credentials of the requesting process * @param forAdmin determines internal type of request */ - void processGetConfiguredPolicy(MessageBuffer &buffer, MessageBuffer &send, uid_t uid, pid_t pid, const std::string &smackLabel, bool forAdmin); + void processGetConfiguredPolicy(MessageBuffer &buffer, MessageBuffer &send, const Credentials &creds, bool forAdmin); /** * Get whole policy for specific user. Whole policy is a list of all apps, * and their permissions (based on what they've stated in their manifests). - * If uid is unprivileged, then only privileges for the caller uid will be - * listed. If uid is privileged, then apps for all the users will be listed. + * + * If calling user is unprivileged, then only privileges for the caller uid + * will be listed. If caller is privileged, then apps for all the users will + * be listed. * * @param buffer Raw received data buffer * @param send Raw data buffer to be sent - * @param uid Identifier of the user who sent the request - * @param pid PID of the process which sent the request - * @param smackLabel smack label of requesting app + * @param creds credentials of the requesting process */ - void processGetPolicy(MessageBuffer &buffer, MessageBuffer &send, uid_t uid, pid_t pid, const std::string &smackLabel); + void processGetPolicy(MessageBuffer &buffer, MessageBuffer &send, const Credentials &creds); /** * Process getting policies descriptions as strings from Cynara @@ -163,15 +159,18 @@ private: * * @param recv Raw received data buffer * @param send Raw data buffer to be sent + * @param creds credentials of the requesting process */ - void processApplyPrivateSharing(MessageBuffer &recv, MessageBuffer &send); + void processApplyPrivateSharing(MessageBuffer &recv, MessageBuffer &send, const Credentials &creds); + /** * Process drop private path sharing between applications. * * @param recv Raw received data buffer * @param send Raw data buffer to be sent + * @param creds credentials of the requesting process */ - void processDropPrivateSharing(MessageBuffer &recv, MessageBuffer &send); + void processDropPrivateSharing(MessageBuffer &recv, MessageBuffer &send, const Credentials &creds); }; } // namespace SecurityManager diff --git a/src/server/service/service.cpp b/src/server/service/service.cpp index 50e5635..e361737 100644 --- a/src/server/service/service.cpp +++ b/src/server/service/service.cpp @@ -64,18 +64,10 @@ bool Service::processOne(const ConnectionID &conn, MessageBuffer &buffer, MessageBuffer send; bool retval = false; - uid_t uid; - pid_t pid; - std::string smackLabel; - - if (!getPeerID(conn.sock, uid, pid, smackLabel)) { - LogError("Closing socket because of error: unable to get peer's uid, pid or smack label"); - m_serviceManager->Close(conn); - return false; - } - if (IFACE == interfaceID) { Try { + Credentials creds = Credentials::getCredentialsFromSocket(conn.sock); + // deserialize API call type int call_type_int; Deserialization::Deserialize(buffer, call_type_int); @@ -88,35 +80,35 @@ bool Service::processOne(const ConnectionID &conn, MessageBuffer &buffer, break; case SecurityModuleCall::APP_INSTALL: LogDebug("call_type: SecurityModuleCall::APP_INSTALL"); - processAppInstall(buffer, send, uid); + processAppInstall(buffer, send, creds); break; case SecurityModuleCall::APP_UNINSTALL: LogDebug("call_type: SecurityModuleCall::APP_UNINSTALL"); - processAppUninstall(buffer, send, uid); + processAppUninstall(buffer, send, creds); break; case SecurityModuleCall::APP_GET_PKG_NAME: processGetPkgName(buffer, send); break; case SecurityModuleCall::APP_GET_GROUPS: - processGetAppGroups(buffer, send, uid, pid); + processGetAppGroups(buffer, send, creds); break; case SecurityModuleCall::USER_ADD: - processUserAdd(buffer, send, uid); + processUserAdd(buffer, send, creds); break; case SecurityModuleCall::USER_DELETE: - processUserDelete(buffer, send, uid); + processUserDelete(buffer, send, creds); break; case SecurityModuleCall::POLICY_UPDATE: - processPolicyUpdate(buffer, send, uid, pid, smackLabel); + processPolicyUpdate(buffer, send, creds); break; case SecurityModuleCall::GET_CONF_POLICY_ADMIN: - processGetConfiguredPolicy(buffer, send, uid, pid, smackLabel, true); + processGetConfiguredPolicy(buffer, send, creds, true); break; case SecurityModuleCall::GET_CONF_POLICY_SELF: - processGetConfiguredPolicy(buffer, send, uid, pid, smackLabel, false); + processGetConfiguredPolicy(buffer, send, creds, false); break; case SecurityModuleCall::GET_POLICY: - processGetPolicy(buffer, send, uid, pid, smackLabel); + processGetPolicy(buffer, send, creds); break; case SecurityModuleCall::POLICY_GET_DESCRIPTIONS: processPolicyGetDesc(send); @@ -128,10 +120,10 @@ bool Service::processOne(const ConnectionID &conn, MessageBuffer &buffer, processAppHasPrivilege(buffer, send); break; case SecurityModuleCall::APP_APPLY_PRIVATE_SHARING: - processApplyPrivateSharing(buffer, send); + processApplyPrivateSharing(buffer, send, creds); break; case SecurityModuleCall::APP_DROP_PRIVATE_SHARING: - processDropPrivateSharing(buffer, send); + processDropPrivateSharing(buffer, send, creds); break; default: LogError("Invalid call: " << call_type_int); @@ -164,7 +156,7 @@ bool Service::processOne(const ConnectionID &conn, MessageBuffer &buffer, return retval; } -void Service::processAppInstall(MessageBuffer &buffer, MessageBuffer &send, uid_t uid) +void Service::processAppInstall(MessageBuffer &buffer, MessageBuffer &send, const Credentials &creds) { app_inst_req req; @@ -175,15 +167,16 @@ void Service::processAppInstall(MessageBuffer &buffer, MessageBuffer &send, uid_ Deserialization::Deserialize(buffer, req.uid); Deserialization::Deserialize(buffer, req.tizenVersion); Deserialization::Deserialize(buffer, req.authorName); - Serialization::Serialize(send, serviceImpl.appInstall(req, uid)); + Serialization::Serialize(send, serviceImpl.appInstall(creds, std::move(req))); } -void Service::processAppUninstall(MessageBuffer &buffer, MessageBuffer &send, uid_t uid) +void Service::processAppUninstall(MessageBuffer &buffer, MessageBuffer &send, const Credentials &creds) { - std::string appName; + app_inst_req req; - Deserialization::Deserialize(buffer, appName); - Serialization::Serialize(send, serviceImpl.appUninstall(appName, uid)); + req.uid = creds.uid; + Deserialization::Deserialize(buffer, req.appName); + Serialization::Serialize(send, serviceImpl.appUninstall(creds, std::move(req))); } void Service::processGetPkgName(MessageBuffer &buffer, MessageBuffer &send) @@ -199,14 +192,14 @@ void Service::processGetPkgName(MessageBuffer &buffer, MessageBuffer &send) Serialization::Serialize(send, pkgName); } -void Service::processGetAppGroups(MessageBuffer &buffer, MessageBuffer &send, uid_t uid, pid_t pid) +void Service::processGetAppGroups(MessageBuffer &buffer, MessageBuffer &send, const Credentials &creds) { std::string appName; std::unordered_set gids; int ret; Deserialization::Deserialize(buffer, appName); - ret = serviceImpl.getAppGroups(appName, uid, pid, gids); + ret = serviceImpl.getAppGroups(creds, appName, gids); Serialization::Serialize(send, ret); if (ret == SECURITY_MANAGER_SUCCESS) { Serialization::Serialize(send, static_cast(gids.size())); @@ -216,7 +209,7 @@ void Service::processGetAppGroups(MessageBuffer &buffer, MessageBuffer &send, ui } } -void Service::processUserAdd(MessageBuffer &buffer, MessageBuffer &send, uid_t uid) +void Service::processUserAdd(MessageBuffer &buffer, MessageBuffer &send, const Credentials &creds) { int ret; uid_t uidAdded; @@ -225,40 +218,40 @@ void Service::processUserAdd(MessageBuffer &buffer, MessageBuffer &send, uid_t u Deserialization::Deserialize(buffer, uidAdded); Deserialization::Deserialize(buffer, userType); - ret = serviceImpl.userAdd(uidAdded, userType, uid); + ret = serviceImpl.userAdd(creds, uidAdded, userType); Serialization::Serialize(send, ret); } -void Service::processUserDelete(MessageBuffer &buffer, MessageBuffer &send, uid_t uid) +void Service::processUserDelete(MessageBuffer &buffer, MessageBuffer &send, const Credentials &creds) { int ret; uid_t uidRemoved; Deserialization::Deserialize(buffer, uidRemoved); - ret = serviceImpl.userDelete(uidRemoved, uid); + ret = serviceImpl.userDelete(creds, uidRemoved); Serialization::Serialize(send, ret); } -void Service::processPolicyUpdate(MessageBuffer &buffer, MessageBuffer &send, uid_t uid, pid_t pid, const std::string &smackLabel) +void Service::processPolicyUpdate(MessageBuffer &buffer, MessageBuffer &send, const Credentials &creds) { int ret; std::vector policyEntries; Deserialization::Deserialize(buffer, policyEntries); - ret = serviceImpl.policyUpdate(policyEntries, uid, pid, smackLabel); + ret = serviceImpl.policyUpdate(creds, policyEntries); Serialization::Serialize(send, ret); } -void Service::processGetConfiguredPolicy(MessageBuffer &buffer, MessageBuffer &send, uid_t uid, pid_t pid, const std::string &smackLabel, bool forAdmin) +void Service::processGetConfiguredPolicy(MessageBuffer &buffer, MessageBuffer &send, const Credentials &creds, bool forAdmin) { int ret; policy_entry filter; Deserialization::Deserialize(buffer, filter); std::vector policyEntries; - ret = serviceImpl.getConfiguredPolicy(forAdmin, filter, uid, pid, smackLabel, policyEntries); + ret = serviceImpl.getConfiguredPolicy(creds, forAdmin, filter, policyEntries); Serialization::Serialize(send, ret); Serialization::Serialize(send, static_cast(policyEntries.size())); @@ -267,14 +260,14 @@ void Service::processGetConfiguredPolicy(MessageBuffer &buffer, MessageBuffer &s }; } -void Service::processGetPolicy(MessageBuffer &buffer, MessageBuffer &send, uid_t uid, pid_t pid, const std::string &smackLabel) +void Service::processGetPolicy(MessageBuffer &buffer, MessageBuffer &send, const Credentials &creds) { int ret; policy_entry filter; Deserialization::Deserialize(buffer, filter); std::vector policyEntries; - ret = serviceImpl.getPolicy(filter, uid, pid, smackLabel, policyEntries); + ret = serviceImpl.getPolicy(creds, filter, policyEntries); Serialization::Serialize(send, ret); Serialization::Serialize(send, static_cast(policyEntries.size())); @@ -329,25 +322,25 @@ void Service::processAppHasPrivilege(MessageBuffer &recv, MessageBuffer &send) Serialization::Serialize(send, static_cast(result)); } -void Service::processApplyPrivateSharing(MessageBuffer &recv, MessageBuffer &send) +void Service::processApplyPrivateSharing(MessageBuffer &recv, MessageBuffer &send, const Credentials &creds) { std::string ownerAppName, targetAppName; std::vector paths; Deserialization::Deserialize(recv, ownerAppName); Deserialization::Deserialize(recv, targetAppName); Deserialization::Deserialize(recv, paths); - int ret = serviceImpl.applyPrivatePathSharing(ownerAppName, targetAppName, paths); + int ret = serviceImpl.applyPrivatePathSharing(creds, ownerAppName, targetAppName, paths); Serialization::Serialize(send, ret); } -void Service::processDropPrivateSharing(MessageBuffer &recv, MessageBuffer &send) +void Service::processDropPrivateSharing(MessageBuffer &recv, MessageBuffer &send, const Credentials &creds) { std::string ownerAppName, targetAppName; std::vector paths; Deserialization::Deserialize(recv, ownerAppName); Deserialization::Deserialize(recv, targetAppName); Deserialization::Deserialize(recv, paths); - int ret = serviceImpl.dropPrivatePathSharing(ownerAppName, targetAppName, paths); + int ret = serviceImpl.dropPrivatePathSharing(creds, ownerAppName, targetAppName, paths); Serialization::Serialize(send, ret); } } // namespace SecurityManager -- 2.7.4