2 * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
4 * Contact: Rafal Krypa <r.krypa@samsung.com>
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License
19 * @file service_impl.cpp
20 * @author Michal Witanowski <m.witanowski@samsung.com>
21 * @author Jacek Bukarewicz <j.bukarewicz@samsung.com>
22 * @author Rafal Krypa <r.krypa@samsung.com>
23 * @author Krzysztof Sasiak <k.sasiak@samsung.com>
24 * @brief Implementation of the service methods
34 #include <dpl/log/log.h>
35 #include <tzplatform_config.h>
37 #include "protocols.h"
38 #include "privilege_db.h"
40 #include "smack-rules.h"
41 #include "smack-labels.h"
42 #include "security-manager.h"
44 #include "service_impl.h"
46 namespace SecurityManager {
47 namespace ServiceImpl {
49 static const std::string ADMIN_PRIVILEGE = "http://tizen.org/privilege/systemsettings.admin";
50 static const std::string SELF_PRIVILEGE = "http://tizen.org/privilege/systemsettings";
54 static inline int validatePolicy(policy_entry &policyEntry, std::string uidStr, bool &forAdmin, CynaraAdminPolicy &cyap)
56 LogDebug("Authenticating and validating policy update request for user with id: " << uidStr);
57 LogDebug("[policy_entry] app: " << policyEntry.appId
58 << " user: " << policyEntry.user
59 << " privilege: " << policyEntry.privilege
60 << " current: " << policyEntry.currentLevel
61 << " max: " << policyEntry.maxLevel);
62 //automagically fill missing fields:
63 if (policyEntry.user.empty()) {
64 policyEntry.user = uidStr;
70 if (policyEntry.currentLevel.empty()) { //for admin
71 if (policyEntry.appId.empty()
72 || policyEntry.privilege.empty()) {
73 LogError("Bad admin update request");
74 return SECURITY_MANAGER_API_ERROR_BAD_REQUEST;
77 if (!policyEntry.maxLevel.compare(SECURITY_MANAGER_DELETE)) {
78 level = CYNARA_ADMIN_DELETE;
81 level = CynaraAdmin::getInstance().convertToPolicyType(policyEntry.maxLevel);
82 } catch (const std::out_of_range& e) {
83 LogError("policy max level cannot be: " << policyEntry.maxLevel);
84 return SECURITY_MANAGER_API_ERROR_INPUT_PARAM;
89 } else if (policyEntry.maxLevel.empty()) { //for self
90 if (policyEntry.user.compare(uidStr)
91 || !policyEntry.appId.compare(SECURITY_MANAGER_ANY)
92 || !policyEntry.privilege.compare(SECURITY_MANAGER_ANY)
93 || policyEntry.appId.empty()
94 || policyEntry.privilege.empty()) {
95 LogError("Bad privacy manager update request");
96 return SECURITY_MANAGER_API_ERROR_BAD_REQUEST;
99 if (!policyEntry.currentLevel.compare(SECURITY_MANAGER_DELETE)) {
100 level = CYNARA_ADMIN_DELETE;
103 level = CynaraAdmin::getInstance().convertToPolicyType(policyEntry.currentLevel);
104 } catch (const std::out_of_range& e) {
105 LogError("policy current level cannot be: " << policyEntry.currentLevel);
106 return SECURITY_MANAGER_API_ERROR_INPUT_PARAM;
111 } else { //neither => bad request
112 return SECURITY_MANAGER_API_ERROR_BAD_REQUEST;
115 if (!policyEntry.user.compare(SECURITY_MANAGER_ANY))
116 policyEntry.user = CYNARA_ADMIN_WILDCARD;
117 if (!policyEntry.privilege.compare(SECURITY_MANAGER_ANY))
118 policyEntry.privilege = CYNARA_ADMIN_WILDCARD;
119 if (policyEntry.appId.compare(SECURITY_MANAGER_ANY))
120 generateAppLabel(policyEntry.appId, client);
122 client = CYNARA_ADMIN_WILDCARD;
124 cyap = std::move(CynaraAdminPolicy(
127 policyEntry.privilege,
129 (forAdmin)?CynaraAdmin::Buckets.at(Bucket::ADMIN):CynaraAdmin::Buckets.at(Bucket::PRIVACY_MANAGER)));
131 LogDebug("Policy update request authenticated and validated successfully");
132 return SECURITY_MANAGER_API_SUCCESS;
134 } // end of anonymous namespace
136 static uid_t getGlobalUserId(void)
138 static uid_t globaluid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
143 * Unifies user data of apps installed for all users
144 * @param uid peer's uid - may be changed during process
145 * @param cynaraUserStr string to which cynara user parameter will be put
147 static void checkGlobalUser(uid_t &uid, std::string &cynaraUserStr)
149 static uid_t globaluid = getGlobalUserId();
150 if (uid == 0 || uid == globaluid) {
152 cynaraUserStr = CYNARA_ADMIN_WILDCARD;
154 cynaraUserStr = std::to_string(static_cast<unsigned int>(uid));
157 static inline bool isSubDir(const char *parent, const char *subdir)
159 while (*parent && *subdir)
160 if (*parent++ != *subdir++)
163 return (*subdir == '/');
166 static bool getUserAppDir(const uid_t &uid, std::string &userAppDir)
168 struct tzplatform_context *tz_ctx = nullptr;
170 if (tzplatform_context_create(&tz_ctx))
173 if (tzplatform_context_set_user(tz_ctx, uid)) {
174 tzplatform_context_destroy(tz_ctx);
179 enum tzplatform_variable id =
180 (uid == getGlobalUserId()) ? TZ_SYS_RW_APP : TZ_USER_APP;
181 const char *appDir = tzplatform_context_getenv(tz_ctx, id);
183 tzplatform_context_destroy(tz_ctx);
190 tzplatform_context_destroy(tz_ctx);
196 static inline bool installRequestAuthCheck(const app_inst_req &req, uid_t uid, bool &isCorrectPath, std::string &appPath)
198 std::string userHome;
199 std::string userAppDir;
200 std::stringstream correctPath;
202 if (uid != getGlobalUserId())
203 LogDebug("Installation type: single user");
205 LogDebug("Installation type: global installation");
207 if (!getUserAppDir(uid, userAppDir)) {
208 LogError("Failed getting app dir for user uid: " << uid);
212 appPath = userAppDir;
214 correctPath << userAppDir << "/" << req.pkgId << "/" << req.appId;
215 LogDebug("correctPath: " << correctPath.str());
217 for (const auto &appPath : req.appPaths) {
218 std::unique_ptr<char, std::function<void(void*)>> real_path(
219 realpath(appPath.first.c_str(), NULL), free);
220 if (!real_path.get()) {
221 LogError("realpath failed with '" << appPath.first.c_str()
222 << "' as parameter: " << strerror(errno));
225 LogDebug("Requested path is '" << appPath.first.c_str()
226 << "'. User's APPS_DIR is '" << userAppDir << "'");
227 if (!isSubDir(userAppDir.c_str(), real_path.get())) {
228 LogWarning("User's apps may have registered folders only in user's APPS_DIR");
232 if (!isSubDir(correctPath.str().c_str(), real_path.get())) {
233 LogWarning("Installation is outside correct path: " << correctPath.str());
236 isCorrectPath = true;
238 app_install_path_type pathType = static_cast<app_install_path_type>(appPath.second);
239 if (pathType == SECURITY_MANAGER_PATH_PUBLIC) {
240 LogWarning("Only root can register SECURITY_MANAGER_PATH_PUBLIC path");
247 int appInstall(const app_inst_req &req, uid_t uid)
249 std::vector<std::string> addedPermissions;
250 std::vector<std::string> removedPermissions;
251 std::vector<std::string> pkgContents;
253 bool isCorrectPath = false;
256 if (uid != req.uid) {
257 LogError("User " << uid <<
258 " is denied to install application for user " << req.uid);
259 return SECURITY_MANAGER_API_ERROR_ACCESS_DENIED;
265 checkGlobalUser(uid, uidstr);
267 if (!installRequestAuthCheck(req, uid, isCorrectPath, appPath)) {
268 LogError("Request from uid " << uid << " for app installation denied");
269 return SECURITY_MANAGER_API_ERROR_AUTHENTICATION_FAILED;
272 std::string smackLabel;
273 if (!generateAppLabel(req.appId, smackLabel)) {
274 LogError("Cannot generate Smack label for application: " << req.appId);
275 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
278 LogDebug("Install parameters: appId: " << req.appId << ", pkgId: " << req.pkgId
279 << ", generated smack label: " << smackLabel);
281 // create null terminated array of strings for permissions
282 std::unique_ptr<const char *[]> pp_permissions(new const char* [req.privileges.size() + 1]);
283 for (size_t i = 0; i < req.privileges.size(); ++i) {
284 LogDebug(" Permission = " << req.privileges[i]);
285 pp_permissions[i] = req.privileges[i].c_str();
287 pp_permissions[req.privileges.size()] = nullptr;
290 std::vector<std::string> oldAppPrivileges;
291 LogDebug("Install parameters: appId: " << req.appId << ", pkgId: " << req.pkgId
292 << ", uidstr " << uidstr << ", generated smack label: " << smackLabel);
294 PrivilegeDb::getInstance().BeginTransaction();
296 bool ret = PrivilegeDb::getInstance().GetAppPkgId(req.appId, pkg);
297 if (ret == true && pkg != req.pkgId) {
298 LogError("Application already installed with different package id");
299 PrivilegeDb::getInstance().RollbackTransaction();
300 return SECURITY_MANAGER_API_ERROR_INPUT_PARAM;
302 PrivilegeDb::getInstance().GetAppPrivileges(req.appId, uid, oldAppPrivileges);
303 PrivilegeDb::getInstance().AddApplication(req.appId, req.pkgId, uid);
304 PrivilegeDb::getInstance().UpdateAppPrivileges(req.appId, uid, req.privileges);
305 /* Get all application ids in the package to generate rules withing the package */
306 PrivilegeDb::getInstance().GetAppIdsForPkgId(req.pkgId, pkgContents);
307 CynaraAdmin::getInstance().UpdateAppPolicy(smackLabel, uidstr, oldAppPrivileges,
309 PrivilegeDb::getInstance().CommitTransaction();
310 LogDebug("Application installation commited to database");
311 } catch (const PrivilegeDb::Exception::IOError &e) {
312 LogError("Cannot access application database: " << e.DumpToString());
313 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
314 } catch (const PrivilegeDb::Exception::InternalError &e) {
315 PrivilegeDb::getInstance().RollbackTransaction();
316 LogError("Error while saving application info to database: " << e.DumpToString());
317 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
318 } catch (const CynaraException::Base &e) {
319 PrivilegeDb::getInstance().RollbackTransaction();
320 LogError("Error while setting Cynara rules for application: " << e.DumpToString());
321 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
322 } catch (const std::bad_alloc &e) {
323 PrivilegeDb::getInstance().RollbackTransaction();
324 LogError("Memory allocation while setting Cynara rules for application: " << e.what());
325 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
329 if (!setupCorrectPath(req.pkgId, req.appId, appPath)) {
330 LogError("Can't setup <APP_ROOT> dirs");
335 for (const auto &appPath : req.appPaths) {
336 const std::string &path = appPath.first;
337 app_install_path_type pathType = static_cast<app_install_path_type>(appPath.second);
338 int result = setupPath(req.appId, path, pathType);
341 LogError("setupPath() failed");
342 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
346 LogDebug("Adding Smack rules for new appId: " << req.appId << " with pkgId: "
347 << req.pkgId << ". Applications in package: " << pkgContents.size());
348 if (!SmackRules::installApplicationRules(req.appId, req.pkgId, pkgContents)) {
349 LogError("Failed to apply package-specific smack rules");
350 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
353 return SECURITY_MANAGER_API_SUCCESS;
356 int appUninstall(const std::string &appId, uid_t uid)
359 std::string smackLabel;
360 std::vector<std::string> pkgContents;
361 bool appExists = true;
362 bool removePkg = false;
364 checkGlobalUser(uid, uidstr);
367 std::vector<std::string> oldAppPrivileges;
369 PrivilegeDb::getInstance().BeginTransaction();
370 if (!PrivilegeDb::getInstance().GetAppPkgId(appId, pkgId)) {
371 LogWarning("Application " << appId <<
372 " not found in database while uninstalling");
373 PrivilegeDb::getInstance().RollbackTransaction();
377 LogDebug("Uninstall parameters: appId: " << appId << ", pkgId: " << pkgId
378 << ", uidstr " << uidstr << ", generated smack label: " << smackLabel);
380 if (!generateAppLabel(appId, smackLabel)) {
381 LogError("Cannot generate Smack label for package: " << pkgId);
382 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
385 /* Before we remove the app from the database, let's fetch all apps in the package
386 that this app belongs to, this will allow us to remove all rules withing the
387 package that the app appears in */
388 PrivilegeDb::getInstance().GetAppIdsForPkgId(pkgId, pkgContents);
389 PrivilegeDb::getInstance().GetAppPrivileges(appId, uid, oldAppPrivileges);
390 PrivilegeDb::getInstance().UpdateAppPrivileges(appId, uid, std::vector<std::string>());
391 PrivilegeDb::getInstance().RemoveApplication(appId, uid, removePkg);
392 CynaraAdmin::getInstance().UpdateAppPolicy(smackLabel, uidstr, oldAppPrivileges,
393 std::vector<std::string>());
394 PrivilegeDb::getInstance().CommitTransaction();
395 LogDebug("Application uninstallation commited to database");
397 } catch (const PrivilegeDb::Exception::IOError &e) {
398 LogError("Cannot access application database: " << e.DumpToString());
399 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
400 } catch (const PrivilegeDb::Exception::InternalError &e) {
401 PrivilegeDb::getInstance().RollbackTransaction();
402 LogError("Error while removing application info from database: " << e.DumpToString());
403 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
404 } catch (const CynaraException::Base &e) {
405 PrivilegeDb::getInstance().RollbackTransaction();
406 LogError("Error while setting Cynara rules for application: " << e.DumpToString());
407 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
408 } catch (const std::bad_alloc &e) {
409 PrivilegeDb::getInstance().RollbackTransaction();
410 LogError("Memory allocation while setting Cynara rules for application: " << e.what());
411 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
417 LogDebug("Removing Smack rules for deleted pkgId " << pkgId);
418 if (!SmackRules::uninstallPackageRules(pkgId)) {
419 LogError("Error on uninstallation of package-specific smack rules");
420 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
423 LogDebug ("Removing smack rules for deleted appId " << appId);
424 if (!SmackRules::uninstallApplicationRules(appId, pkgId, pkgContents)) {
425 LogError("Error during uninstallation of application-specific smack rules");
426 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
430 return SECURITY_MANAGER_API_SUCCESS;
433 int getPkgId(const std::string &appId, std::string &pkgId)
435 LogDebug("appId: " << appId);
438 if (!PrivilegeDb::getInstance().GetAppPkgId(appId, pkgId)) {
439 LogWarning("Application " << appId << " not found in database");
440 return SECURITY_MANAGER_API_ERROR_NO_SUCH_OBJECT;
442 LogDebug("pkgId: " << pkgId);
444 } catch (const PrivilegeDb::Exception::Base &e) {
445 LogError("Error while getting pkgId from database: " << e.DumpToString());
446 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
449 return SECURITY_MANAGER_API_SUCCESS;
452 int getAppGroups(const std::string &appId, uid_t uid, pid_t pid, std::unordered_set<gid_t> &gids)
456 std::string smackLabel;
457 std::string uidStr = std::to_string(uid);
458 std::string pidStr = std::to_string(pid);
460 LogDebug("appId: " << appId);
462 if (!PrivilegeDb::getInstance().GetAppPkgId(appId, pkgId)) {
463 LogWarning("Application " << appId << " not found in database");
464 return SECURITY_MANAGER_API_ERROR_NO_SUCH_OBJECT;
466 LogDebug("pkgId: " << pkgId);
467 if (!generatePkgLabel(pkgId, smackLabel)) {
468 LogError("Cannot generate Smack label for pkgId: " << pkgId);
469 return SECURITY_MANAGER_API_ERROR_NO_SUCH_OBJECT;
471 LogDebug("smack label: " << smackLabel);
473 std::vector<std::string> privileges;
474 PrivilegeDb::getInstance().GetPkgPrivileges(pkgId, uid, privileges);
475 /*there is also a need of checking, if privilege is granted to all users*/
476 size_t tmp = privileges.size();
477 PrivilegeDb::getInstance().GetPkgPrivileges(pkgId, getGlobalUserId(), privileges);
478 /*privileges needs to be sorted and with no duplications - for cynara sake*/
479 std::inplace_merge(privileges.begin(), privileges.begin() + tmp, privileges.end());
480 privileges.erase( unique( privileges.begin(), privileges.end() ), privileges.end() );
482 for (const auto &privilege : privileges) {
483 std::vector<std::string> gidsTmp;
484 PrivilegeDb::getInstance().GetPrivilegeGroups(privilege, gidsTmp);
485 if (!gidsTmp.empty()) {
486 LogDebug("Considering privilege " << privilege << " with " <<
487 gidsTmp.size() << " groups assigned");
488 if (Cynara::getInstance().check(smackLabel, privilege, uidStr, pidStr)) {
489 for_each(gidsTmp.begin(), gidsTmp.end(), [&] (std::string group)
491 struct group *grp = getgrnam(group.c_str());
493 LogError("No such group: " << group.c_str());
496 gids.insert(grp->gr_gid);
498 LogDebug("Cynara allowed, adding groups");
500 LogDebug("Cynara denied, not adding groups");
503 } catch (const PrivilegeDb::Exception::Base &e) {
504 LogError("Database error: " << e.DumpToString());
505 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
506 } catch (const CynaraException::Base &e) {
507 LogError("Error while querying Cynara for permissions: " << e.DumpToString());
508 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
509 } catch (const std::bad_alloc &e) {
510 LogError("Memory allocation failed: " << e.what());
511 return SECURITY_MANAGER_API_ERROR_OUT_OF_MEMORY;
514 return SECURITY_MANAGER_API_SUCCESS;
517 int userAdd(uid_t uidAdded, int userType, uid_t uid)
520 return SECURITY_MANAGER_API_ERROR_AUTHENTICATION_FAILED;
523 CynaraAdmin::getInstance().UserInit(uidAdded, static_cast<security_manager_user_type>(userType));
524 } catch (CynaraException::InvalidParam &e) {
525 return SECURITY_MANAGER_API_ERROR_INPUT_PARAM;
527 return SECURITY_MANAGER_API_SUCCESS;
530 int userDelete(uid_t uidDeleted, uid_t uid)
532 int ret = SECURITY_MANAGER_API_SUCCESS;
534 return SECURITY_MANAGER_API_ERROR_AUTHENTICATION_FAILED;
536 /*Uninstall all user apps*/
537 std::vector<std::string> userApps;
539 PrivilegeDb::getInstance().GetUserApps(uidDeleted, userApps);
540 } catch (const PrivilegeDb::Exception::Base &e) {
541 LogError("Error while getting user apps from database: " << e.DumpToString());
542 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
545 for (auto &app: userApps) {
546 if (appUninstall(app, uidDeleted) != SECURITY_MANAGER_API_SUCCESS) {
547 /*if uninstallation of this app fails, just go on trying to uninstall another ones.
548 we do not have anything special to do about that matter - user will be deleted anyway.*/
549 ret = SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
553 CynaraAdmin::getInstance().UserRemove(uidDeleted);
558 int policyUpdate(const std::vector<policy_entry> &policyEntries, uid_t uid, pid_t pid, const std::string &smackLabel)
564 } isAdmin = NOT_CHECKED;
567 std::string uidStr = std::to_string(uid);
568 std::string pidStr = std::to_string(pid);
570 if (policyEntries.size() == 0) {
571 LogError("Validation failed: policy update request is empty");
572 return SECURITY_MANAGER_API_ERROR_BAD_REQUEST;
575 if (!Cynara::getInstance().check(smackLabel, SELF_PRIVILEGE, uidStr, pidStr)) {
576 LogError("Not enough permission to call: " << __FUNCTION__);
577 return SECURITY_MANAGER_API_ERROR_ACCESS_DENIED;
580 std::vector<CynaraAdminPolicy> validatedPolicies;
582 for (auto &entry : const_cast<std::vector<policy_entry>&>(policyEntries)) {
583 bool forAdmin = false;
584 CynaraAdminPolicy cyap("", "", "", CYNARA_ADMIN_NONE, "");
585 int ret = validatePolicy(entry, uidStr, forAdmin, cyap);
587 if (forAdmin && (isAdmin == NOT_CHECKED)) {
588 isAdmin = Cynara::getInstance().check(smackLabel, ADMIN_PRIVILEGE, uidStr, pidStr)?IS_ADMIN:IS_NOT_ADMIN;
591 if (ret == SECURITY_MANAGER_API_SUCCESS) {
593 || (forAdmin && (isAdmin == IS_ADMIN))) {
594 validatedPolicies.push_back(std::move(cyap));
596 LogError("Not enough privilege to enforce admin policy");
597 return SECURITY_MANAGER_API_ERROR_ACCESS_DENIED;
605 CynaraAdmin::getInstance().SetPolicies(validatedPolicies);
607 } catch (const CynaraException::Base &e) {
608 LogError("Error while updating Cynara rules: " << e.DumpToString());
609 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
610 } catch (const std::bad_alloc &e) {
611 LogError("Memory allocation error while updating Cynara rules: " << e.what());
612 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
615 return SECURITY_MANAGER_API_SUCCESS;
618 int getConfiguredPolicy(bool forAdmin, const policy_entry &filter, uid_t uid, pid_t pid,
619 const std::string &smackLabel, std::vector<policy_entry> &policyEntries)
622 std::string uidStr = std::to_string(uid);
623 std::string pidStr = std::to_string(pid);
625 if (!Cynara::getInstance().check(smackLabel, SELF_PRIVILEGE, uidStr, pidStr)) {
626 LogError("Not enough permission to call: " << __FUNCTION__);
627 return SECURITY_MANAGER_API_ERROR_ACCESS_DENIED;
630 LogDebug("Filter is: C: " << filter.appId
631 << ", U: " << filter.user
632 << ", P: " << filter.privilege
633 << ", current: " << filter.currentLevel
634 << ", max: " << filter.maxLevel
637 std::vector<CynaraAdminPolicy> listOfPolicies;
639 //convert appId to smack label
640 std::string appLabel;
641 if (!filter.appId.compare(SECURITY_MANAGER_ANY))
642 appLabel = CYNARA_ADMIN_ANY;
644 generateAppLabel(filter.appId, appLabel);
646 std::string user = (!filter.user.compare(SECURITY_MANAGER_ANY))? CYNARA_ADMIN_ANY: filter.user;
647 std::string privilege = (!filter.privilege.compare(SECURITY_MANAGER_ANY))? CYNARA_ADMIN_ANY: filter.privilege;
649 LogDebug("App: " << filter.appId << ", Label: " << appLabel);
652 if (!Cynara::getInstance().check(smackLabel, ADMIN_PRIVILEGE, uidStr, pidStr)) {
653 LogError("Not enough privilege to access admin enforced policies: " << __FUNCTION__);
654 return SECURITY_MANAGER_API_ERROR_ACCESS_DENIED;
657 //Fetch privileges from ADMIN bucket
658 CynaraAdmin::getInstance().ListPolicies(
659 CynaraAdmin::Buckets.at(Bucket::ADMIN),
665 LogDebug("ADMIN - number of policies matched: " << listOfPolicies.size());
667 if (uidStr.compare(user)) {
668 if (!Cynara::getInstance().check(smackLabel, ADMIN_PRIVILEGE, uidStr, pidStr)) {
669 LogWarning("Not enough privilege to access other user's personal policies. Limiting query to personal privileges.");
673 //Fetch privileges from PRIVACY_MANAGER bucket
674 CynaraAdmin::getInstance().ListPolicies(
675 CynaraAdmin::Buckets.at(Bucket::PRIVACY_MANAGER),
681 LogDebug("PRIVACY MANAGER - number of policies matched: " << listOfPolicies.size());
684 for (const auto &policy : listOfPolicies) {
685 //ignore "jump to bucket" entries
686 if (policy.result == CYNARA_ADMIN_BUCKET)
691 pe.appId = strcmp(policy.client, CYNARA_ADMIN_WILDCARD) ? generateAppNameFromLabel(policy.client) : SECURITY_MANAGER_ANY;
692 pe.user = strcmp(policy.user, CYNARA_ADMIN_WILDCARD) ? policy.user : SECURITY_MANAGER_ANY;
693 pe.privilege = strcmp(policy.privilege, CYNARA_ADMIN_WILDCARD) ? policy.privilege : pe.privilege = SECURITY_MANAGER_ANY;
694 pe.currentLevel = CynaraAdmin::getInstance().convertToPolicyDescription(policy.result);
697 // All policy entries in PRIVACY_MANAGER should be fully-qualified
698 pe.maxLevel = CynaraAdmin::getInstance().convertToPolicyDescription(
699 CynaraAdmin::getInstance().GetPrivilegeManagerMaxLevel(
700 policy.client, policy.user, policy.privilege));
702 // Cannot reliably calculate maxLavel for policies from ADMIN bucket
703 pe.maxLevel = CynaraAdmin::getInstance().convertToPolicyDescription(CYNARA_ADMIN_ALLOW);
708 "[policy_entry] app: " << pe.appId
709 << " user: " << pe.user
710 << " privilege: " << pe.privilege
711 << " current: " << pe.currentLevel
712 << " max: " << pe.maxLevel
715 policyEntries.push_back(pe);
718 } catch (const CynaraException::Base &e) {
719 LogError("Error while listing Cynara rules: " << e.DumpToString());
720 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
721 } catch (const std::bad_alloc &e) {
722 LogError("Memory allocation error while listing Cynara rules: " << e.what());
723 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
727 return SECURITY_MANAGER_API_SUCCESS;
730 int getPolicy(const policy_entry &filter, uid_t uid, pid_t pid, const std::string &smackLabel, std::vector<policy_entry> &policyEntries)
733 std::string uidStr = std::to_string(uid);
734 std::string pidStr = std::to_string(pid);
736 if (!Cynara::getInstance().check(smackLabel, SELF_PRIVILEGE, uidStr, pidStr)) {
737 LogWarning("Not enough permission to call: " << __FUNCTION__);
738 return SECURITY_MANAGER_API_ERROR_ACCESS_DENIED;
741 LogDebug("Filter is: C: " << filter.appId
742 << ", U: " << filter.user
743 << ", P: " << filter.privilege
744 << ", current: " << filter.currentLevel
745 << ", max: " << filter.maxLevel
748 std::vector<uid_t> listOfUsers;
750 if (Cynara::getInstance().check(smackLabel, ADMIN_PRIVILEGE, uidStr, pidStr)) {
751 LogDebug("User is privileged");
752 if (filter.user.compare(SECURITY_MANAGER_ANY)) {
753 LogDebug("Limitting Cynara query to user: " << filter.user);
755 listOfUsers.push_back(static_cast<uid_t>(std::stoul(filter.user)));
756 } catch (std::invalid_argument &e) {
757 LogError("Invalid UID: " << e.what());
760 CynaraAdmin::getInstance().ListUsers(listOfUsers);
762 LogWarning("Not enough privilege to fetch user policy for all users by user: " << uid);
763 LogDebug("Fetching personal policy for user: " << uid);
764 listOfUsers.push_back(uid);
766 LogDebug("Fetching policy for " << listOfUsers.size() << " users");
768 for (const uid_t &uid : listOfUsers) {
769 LogDebug("User: " << uid);
770 std::string userStr = std::to_string(uid);
771 std::vector<std::string> listOfApps;
773 if (filter.appId.compare(SECURITY_MANAGER_ANY)) {
774 LogDebug("Limitting Cynara query to app: " << filter.appId);
775 listOfApps.push_back(filter.appId);
777 PrivilegeDb::getInstance().GetUserApps(uid, listOfApps);
778 LogDebug("Found apps: " << listOfApps.size());
781 for (const std::string &appId : listOfApps) {
782 LogDebug("App: " << appId);
783 std::string smackLabelForApp;
784 std::vector<std::string> listOfPrivileges;
786 generateAppLabel(appId, smackLabelForApp);
787 // FIXME: also fetch privileges of global applications
788 PrivilegeDb::getInstance().GetAppPrivileges(appId, uid, listOfPrivileges);
790 if (filter.privilege.compare(SECURITY_MANAGER_ANY)) {
791 LogDebug("Limitting Cynara query to privilege: " << filter.privilege);
792 // FIXME: this filtering should be already performed by method fetching the privileges
793 if (std::find(listOfPrivileges.begin(), listOfPrivileges.end(),
794 filter.privilege) == listOfPrivileges.end()) {
795 LogDebug("Application " << appId <<
796 " doesn't have the filteres privilege " << filter.privilege);
799 listOfPrivileges.clear();
800 listOfPrivileges.push_back(filter.privilege);
803 LogDebug("Privileges matching filter - " << filter.privilege << ": " << listOfPrivileges.size());
805 for (const std::string &privilege : listOfPrivileges) {
806 LogDebug("Privilege: " << privilege);
811 pe.privilege = privilege;
813 pe.currentLevel = CynaraAdmin::getInstance().convertToPolicyDescription(
814 CynaraAdmin::getInstance().GetPrivilegeManagerCurrLevel(
815 smackLabelForApp, userStr, privilege));
817 pe.maxLevel = CynaraAdmin::getInstance().convertToPolicyDescription(
818 CynaraAdmin::getInstance().GetPrivilegeManagerMaxLevel(
819 smackLabelForApp, userStr, privilege));
822 "[policy_entry] app: " << pe.appId
823 << " user: " << pe.user
824 << " privilege: " << pe.privilege
825 << " current: " << pe.currentLevel
826 << " max: " << pe.maxLevel
829 policyEntries.push_back(pe);
834 } catch (const CynaraException::Base &e) {
835 LogError("Error while listing Cynara rules: " << e.DumpToString());
836 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
837 } catch (const std::bad_alloc &e) {
838 LogError("Memory allocation error while listing Cynara rules: " << e.what());
839 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
842 return SECURITY_MANAGER_API_SUCCESS;
845 int policyGetDesc(std::vector<std::string> &levels)
847 int ret = SECURITY_MANAGER_API_SUCCESS;
850 CynaraAdmin::getInstance().ListPoliciesDescriptions(levels);
851 } catch (const CynaraException::OutOfMemory &e) {
852 LogError("Error - out of memory while querying Cynara for policy descriptions list: " << e.DumpToString());
853 return SECURITY_MANAGER_API_ERROR_OUT_OF_MEMORY;
854 } catch (const CynaraException::InvalidParam &e) {
855 LogError("Error - invalid parameter while querying Cynara for policy descriptions list: " << e.DumpToString());
856 return SECURITY_MANAGER_API_ERROR_INPUT_PARAM;
857 } catch (const CynaraException::ServiceNotAvailable &e) {
858 LogError("Error - service not available while querying Cynara for policy descriptions list: " << e.DumpToString());
859 return SECURITY_MANAGER_API_ERROR_NO_SUCH_SERVICE;
860 } catch (const CynaraException::Base &e) {
861 LogError("Error while getting policy descriptions list from Cynara: " << e.DumpToString());
862 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
868 } /* namespace ServiceImpl */
869 } /* namespace SecurityManager */