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 inline bool installRequestAuthCheck(const app_inst_req &req, uid_t uid)
172 if (!pwd && errno != EINTR) {
173 LogError("getpwuid failed with '" << uid
174 << "' as parameter: " << strerror(errno));
179 std::unique_ptr<char, std::function<void(void*)>> home(
180 realpath(pwd->pw_dir, NULL), free);
182 LogError("realpath failed with '" << pwd->pw_dir
183 << "' as parameter: " << strerror(errno));
187 for (const auto &appPath : req.appPaths) {
188 std::unique_ptr<char, std::function<void(void*)>> real_path(
189 realpath(appPath.first.c_str(), NULL), free);
190 if (!real_path.get()) {
191 LogError("realpath failed with '" << appPath.first.c_str()
192 << "' as parameter: " << strerror(errno));
195 LogDebug("Requested path is '" << appPath.first.c_str()
196 << "'. User's HOME is '" << pwd->pw_dir << "'");
197 if (!isSubDir(home.get(), real_path.get())) {
198 LogWarning("User's apps may have registered folders only in user's home dir");
202 app_install_path_type pathType = static_cast<app_install_path_type>(appPath.second);
203 if (pathType == SECURITY_MANAGER_PATH_PUBLIC) {
204 LogWarning("Only root can register SECURITY_MANAGER_PATH_PUBLIC path");
211 int appInstall(const app_inst_req &req, uid_t uid)
213 std::vector<std::string> addedPermissions;
214 std::vector<std::string> removedPermissions;
215 std::vector<std::string> pkgContents;
218 if (uid != req.uid) {
219 LogError("User " << uid <<
220 " is denied to install application for user " << req.uid);
221 return SECURITY_MANAGER_API_ERROR_ACCESS_DENIED;
227 checkGlobalUser(uid, uidstr);
229 if (!installRequestAuthCheck(req, uid)) {
230 LogError("Request from uid " << uid << " for app installation denied");
231 return SECURITY_MANAGER_API_ERROR_AUTHENTICATION_FAILED;
234 std::string smackLabel;
235 if (!generateAppLabel(req.appId, smackLabel)) {
236 LogError("Cannot generate Smack label for application: " << req.appId);
237 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
240 LogDebug("Install parameters: appId: " << req.appId << ", pkgId: " << req.pkgId
241 << ", generated smack label: " << smackLabel);
243 // create null terminated array of strings for permissions
244 std::unique_ptr<const char *[]> pp_permissions(new const char* [req.privileges.size() + 1]);
245 for (size_t i = 0; i < req.privileges.size(); ++i) {
246 LogDebug(" Permission = " << req.privileges[i]);
247 pp_permissions[i] = req.privileges[i].c_str();
249 pp_permissions[req.privileges.size()] = nullptr;
252 std::vector<std::string> oldAppPrivileges;
253 LogDebug("Install parameters: appId: " << req.appId << ", pkgId: " << req.pkgId
254 << ", uidstr " << uidstr << ", generated smack label: " << smackLabel);
256 PrivilegeDb::getInstance().BeginTransaction();
258 bool ret = PrivilegeDb::getInstance().GetAppPkgId(req.appId, pkg);
259 if (ret == true && pkg != req.pkgId) {
260 LogError("Application already installed with different package id");
261 PrivilegeDb::getInstance().RollbackTransaction();
262 return SECURITY_MANAGER_API_ERROR_INPUT_PARAM;
264 PrivilegeDb::getInstance().GetAppPrivileges(req.appId, uid, oldAppPrivileges);
265 PrivilegeDb::getInstance().AddApplication(req.appId, req.pkgId, uid);
266 PrivilegeDb::getInstance().UpdateAppPrivileges(req.appId, uid, req.privileges);
267 /* Get all application ids in the package to generate rules withing the package */
268 PrivilegeDb::getInstance().GetAppIdsForPkgId(req.pkgId, pkgContents);
269 CynaraAdmin::getInstance().UpdateAppPolicy(smackLabel, uidstr, oldAppPrivileges,
271 PrivilegeDb::getInstance().CommitTransaction();
272 LogDebug("Application installation commited to database");
273 } catch (const PrivilegeDb::Exception::IOError &e) {
274 LogError("Cannot access application database: " << e.DumpToString());
275 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
276 } catch (const PrivilegeDb::Exception::InternalError &e) {
277 PrivilegeDb::getInstance().RollbackTransaction();
278 LogError("Error while saving application info to database: " << e.DumpToString());
279 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
280 } catch (const CynaraException::Base &e) {
281 PrivilegeDb::getInstance().RollbackTransaction();
282 LogError("Error while setting Cynara rules for application: " << e.DumpToString());
283 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
284 } catch (const std::bad_alloc &e) {
285 PrivilegeDb::getInstance().RollbackTransaction();
286 LogError("Memory allocation while setting Cynara rules for application: " << e.what());
287 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
291 for (const auto &appPath : req.appPaths) {
292 const std::string &path = appPath.first;
293 app_install_path_type pathType = static_cast<app_install_path_type>(appPath.second);
294 int result = setupPath(req.pkgId, path, pathType);
297 LogError("setupPath() failed");
298 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
302 LogDebug("Adding Smack rules for new appId: " << req.appId << " with pkgId: "
303 << req.pkgId << ". Applications in package: " << pkgContents.size());
304 if (!SmackRules::installApplicationRules(req.appId, req.pkgId, pkgContents)) {
305 LogError("Failed to apply package-specific smack rules");
306 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
309 return SECURITY_MANAGER_API_SUCCESS;
312 int appUninstall(const std::string &appId, uid_t uid)
315 std::string smackLabel;
316 std::vector<std::string> pkgContents;
317 bool appExists = true;
318 bool removePkg = false;
320 checkGlobalUser(uid, uidstr);
323 std::vector<std::string> oldAppPrivileges;
325 PrivilegeDb::getInstance().BeginTransaction();
326 if (!PrivilegeDb::getInstance().GetAppPkgId(appId, pkgId)) {
327 LogWarning("Application " << appId <<
328 " not found in database while uninstalling");
329 PrivilegeDb::getInstance().RollbackTransaction();
333 LogDebug("Uninstall parameters: appId: " << appId << ", pkgId: " << pkgId
334 << ", uidstr " << uidstr << ", generated smack label: " << smackLabel);
336 if (!generateAppLabel(appId, smackLabel)) {
337 LogError("Cannot generate Smack label for package: " << pkgId);
338 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
341 /* Before we remove the app from the database, let's fetch all apps in the package
342 that this app belongs to, this will allow us to remove all rules withing the
343 package that the app appears in */
344 PrivilegeDb::getInstance().GetAppIdsForPkgId(pkgId, pkgContents);
345 PrivilegeDb::getInstance().GetAppPrivileges(appId, uid, oldAppPrivileges);
346 PrivilegeDb::getInstance().UpdateAppPrivileges(appId, uid, std::vector<std::string>());
347 PrivilegeDb::getInstance().RemoveApplication(appId, uid, removePkg);
348 CynaraAdmin::getInstance().UpdateAppPolicy(smackLabel, uidstr, oldAppPrivileges,
349 std::vector<std::string>());
350 PrivilegeDb::getInstance().CommitTransaction();
351 LogDebug("Application uninstallation commited to database");
353 } catch (const PrivilegeDb::Exception::IOError &e) {
354 LogError("Cannot access application database: " << e.DumpToString());
355 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
356 } catch (const PrivilegeDb::Exception::InternalError &e) {
357 PrivilegeDb::getInstance().RollbackTransaction();
358 LogError("Error while removing application info from database: " << e.DumpToString());
359 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
360 } catch (const CynaraException::Base &e) {
361 PrivilegeDb::getInstance().RollbackTransaction();
362 LogError("Error while setting Cynara rules for application: " << e.DumpToString());
363 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
364 } catch (const std::bad_alloc &e) {
365 PrivilegeDb::getInstance().RollbackTransaction();
366 LogError("Memory allocation while setting Cynara rules for application: " << e.what());
367 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
373 LogDebug("Removing Smack rules for deleted pkgId " << pkgId);
374 if (!SmackRules::uninstallPackageRules(pkgId)) {
375 LogError("Error on uninstallation of package-specific smack rules");
376 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
379 LogDebug ("Removing smack rules for deleted appId " << appId);
380 if (!SmackRules::uninstallApplicationRules(appId, pkgId, pkgContents)) {
381 LogError("Error during uninstallation of application-specific smack rules");
382 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
386 return SECURITY_MANAGER_API_SUCCESS;
389 int getPkgId(const std::string &appId, std::string &pkgId)
391 LogDebug("appId: " << appId);
394 if (!PrivilegeDb::getInstance().GetAppPkgId(appId, pkgId)) {
395 LogWarning("Application " << appId << " not found in database");
396 return SECURITY_MANAGER_API_ERROR_NO_SUCH_OBJECT;
398 LogDebug("pkgId: " << pkgId);
400 } catch (const PrivilegeDb::Exception::Base &e) {
401 LogError("Error while getting pkgId from database: " << e.DumpToString());
402 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
405 return SECURITY_MANAGER_API_SUCCESS;
408 int getAppGroups(const std::string &appId, uid_t uid, pid_t pid, std::unordered_set<gid_t> &gids)
412 std::string smackLabel;
413 std::string uidStr = std::to_string(uid);
414 std::string pidStr = std::to_string(pid);
416 LogDebug("appId: " << appId);
418 if (!PrivilegeDb::getInstance().GetAppPkgId(appId, pkgId)) {
419 LogWarning("Application " << appId << " not found in database");
420 return SECURITY_MANAGER_API_ERROR_NO_SUCH_OBJECT;
422 LogDebug("pkgId: " << pkgId);
423 if (!generatePkgLabel(pkgId, smackLabel)) {
424 LogError("Cannot generate Smack label for pkgId: " << pkgId);
425 return SECURITY_MANAGER_API_ERROR_NO_SUCH_OBJECT;
427 LogDebug("smack label: " << smackLabel);
429 std::vector<std::string> privileges;
430 PrivilegeDb::getInstance().GetPkgPrivileges(pkgId, uid, privileges);
431 /*there is also a need of checking, if privilege is granted to all users*/
432 size_t tmp = privileges.size();
433 PrivilegeDb::getInstance().GetPkgPrivileges(pkgId, getGlobalUserId(), privileges);
434 /*privileges needs to be sorted and with no duplications - for cynara sake*/
435 std::inplace_merge(privileges.begin(), privileges.begin() + tmp, privileges.end());
436 privileges.erase( unique( privileges.begin(), privileges.end() ), privileges.end() );
438 for (const auto &privilege : privileges) {
439 std::vector<std::string> gidsTmp;
440 PrivilegeDb::getInstance().GetPrivilegeGroups(privilege, gidsTmp);
441 if (!gidsTmp.empty()) {
442 LogDebug("Considering privilege " << privilege << " with " <<
443 gidsTmp.size() << " groups assigned");
444 if (Cynara::getInstance().check(smackLabel, privilege, uidStr, pidStr)) {
445 for_each(gidsTmp.begin(), gidsTmp.end(), [&] (std::string group)
447 struct group *grp = getgrnam(group.c_str());
449 LogError("No such group: " << group.c_str());
452 gids.insert(grp->gr_gid);
454 LogDebug("Cynara allowed, adding groups");
456 LogDebug("Cynara denied, not adding groups");
459 } catch (const PrivilegeDb::Exception::Base &e) {
460 LogError("Database error: " << e.DumpToString());
461 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
462 } catch (const CynaraException::Base &e) {
463 LogError("Error while querying Cynara for permissions: " << e.DumpToString());
464 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
465 } catch (const std::bad_alloc &e) {
466 LogError("Memory allocation failed: " << e.what());
467 return SECURITY_MANAGER_API_ERROR_OUT_OF_MEMORY;
470 return SECURITY_MANAGER_API_SUCCESS;
473 int userAdd(uid_t uidAdded, int userType, uid_t uid)
476 return SECURITY_MANAGER_API_ERROR_AUTHENTICATION_FAILED;
479 CynaraAdmin::getInstance().UserInit(uidAdded, static_cast<security_manager_user_type>(userType));
480 } catch (CynaraException::InvalidParam &e) {
481 return SECURITY_MANAGER_API_ERROR_INPUT_PARAM;
483 return SECURITY_MANAGER_API_SUCCESS;
486 int userDelete(uid_t uidDeleted, uid_t uid)
488 int ret = SECURITY_MANAGER_API_SUCCESS;
490 return SECURITY_MANAGER_API_ERROR_AUTHENTICATION_FAILED;
492 /*Uninstall all user apps*/
493 std::vector<std::string> userApps;
495 PrivilegeDb::getInstance().GetUserApps(uidDeleted, userApps);
496 } catch (const PrivilegeDb::Exception::Base &e) {
497 LogError("Error while getting user apps from database: " << e.DumpToString());
498 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
501 for (auto &app: userApps) {
502 if (appUninstall(app, uidDeleted) != SECURITY_MANAGER_API_SUCCESS) {
503 /*if uninstallation of this app fails, just go on trying to uninstall another ones.
504 we do not have anything special to do about that matter - user will be deleted anyway.*/
505 ret = SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
509 CynaraAdmin::getInstance().UserRemove(uidDeleted);
514 int policyUpdate(const std::vector<policy_entry> &policyEntries, uid_t uid, pid_t pid, const std::string &smackLabel)
520 } isAdmin = NOT_CHECKED;
523 std::string uidStr = std::to_string(uid);
524 std::string pidStr = std::to_string(pid);
526 if (policyEntries.size() == 0) {
527 LogError("Validation failed: policy update request is empty");
528 return SECURITY_MANAGER_API_ERROR_BAD_REQUEST;
531 if (!Cynara::getInstance().check(smackLabel, SELF_PRIVILEGE, uidStr, pidStr)) {
532 LogError("Not enough permission to call: " << __FUNCTION__);
533 return SECURITY_MANAGER_API_ERROR_ACCESS_DENIED;
536 std::vector<CynaraAdminPolicy> validatedPolicies;
538 for (auto &entry : const_cast<std::vector<policy_entry>&>(policyEntries)) {
539 bool forAdmin = false;
540 CynaraAdminPolicy cyap("", "", "", CYNARA_ADMIN_NONE, "");
541 int ret = validatePolicy(entry, uidStr, forAdmin, cyap);
543 if (forAdmin && (isAdmin == NOT_CHECKED)) {
544 isAdmin = Cynara::getInstance().check(smackLabel, ADMIN_PRIVILEGE, uidStr, pidStr)?IS_ADMIN:IS_NOT_ADMIN;
547 if (ret == SECURITY_MANAGER_API_SUCCESS) {
549 || (forAdmin && (isAdmin == IS_ADMIN))) {
550 validatedPolicies.push_back(std::move(cyap));
552 LogError("Not enough privilege to enforce admin policy");
553 return SECURITY_MANAGER_API_ERROR_ACCESS_DENIED;
561 CynaraAdmin::getInstance().SetPolicies(validatedPolicies);
563 } catch (const CynaraException::Base &e) {
564 LogError("Error while updating Cynara rules: " << e.DumpToString());
565 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
566 } catch (const std::bad_alloc &e) {
567 LogError("Memory allocation error while updating Cynara rules: " << e.what());
568 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
571 return SECURITY_MANAGER_API_SUCCESS;
574 int getConfiguredPolicy(bool forAdmin, const policy_entry &filter, uid_t uid, pid_t pid,
575 const std::string &smackLabel, std::vector<policy_entry> &policyEntries)
578 std::string uidStr = std::to_string(uid);
579 std::string pidStr = std::to_string(pid);
581 if (!Cynara::getInstance().check(smackLabel, SELF_PRIVILEGE, uidStr, pidStr)) {
582 LogError("Not enough permission to call: " << __FUNCTION__);
583 return SECURITY_MANAGER_API_ERROR_ACCESS_DENIED;
586 LogDebug("Filter is: C: " << filter.appId
587 << ", U: " << filter.user
588 << ", P: " << filter.privilege
589 << ", current: " << filter.currentLevel
590 << ", max: " << filter.maxLevel
593 std::vector<CynaraAdminPolicy> listOfPolicies;
595 //convert appId to smack label
596 std::string appLabel;
597 if (!filter.appId.compare(SECURITY_MANAGER_ANY))
598 appLabel = CYNARA_ADMIN_ANY;
600 generateAppLabel(filter.appId, appLabel);
602 std::string user = (!filter.user.compare(SECURITY_MANAGER_ANY))? CYNARA_ADMIN_ANY: filter.user;
603 std::string privilege = (!filter.privilege.compare(SECURITY_MANAGER_ANY))? CYNARA_ADMIN_ANY: filter.privilege;
605 LogDebug("App: " << filter.appId << ", Label: " << appLabel);
608 if (!Cynara::getInstance().check(smackLabel, ADMIN_PRIVILEGE, uidStr, pidStr)) {
609 LogError("Not enough privilege to access admin enforced policies: " << __FUNCTION__);
610 return SECURITY_MANAGER_API_ERROR_ACCESS_DENIED;
613 //Fetch privileges from ADMIN bucket
614 CynaraAdmin::getInstance().ListPolicies(
615 CynaraAdmin::Buckets.at(Bucket::ADMIN),
621 LogDebug("ADMIN - number of policies matched: " << listOfPolicies.size());
623 if (uidStr.compare(user)) {
624 if (!Cynara::getInstance().check(smackLabel, ADMIN_PRIVILEGE, uidStr, pidStr)) {
625 LogWarning("Not enough privilege to access other user's personal policies. Limiting query to personal privileges.");
629 //Fetch privileges from PRIVACY_MANAGER bucket
630 CynaraAdmin::getInstance().ListPolicies(
631 CynaraAdmin::Buckets.at(Bucket::PRIVACY_MANAGER),
637 LogDebug("PRIVACY MANAGER - number of policies matched: " << listOfPolicies.size());
640 for (const auto &policy : listOfPolicies) {
641 //ignore "jump to bucket" entries
642 if (policy.result == CYNARA_ADMIN_BUCKET)
647 pe.appId = strcmp(policy.client, CYNARA_ADMIN_WILDCARD) ? generateAppNameFromLabel(policy.client) : SECURITY_MANAGER_ANY;
648 pe.user = strcmp(policy.user, CYNARA_ADMIN_WILDCARD) ? policy.user : SECURITY_MANAGER_ANY;
649 pe.privilege = strcmp(policy.privilege, CYNARA_ADMIN_WILDCARD) ? policy.privilege : pe.privilege = SECURITY_MANAGER_ANY;
650 pe.currentLevel = CynaraAdmin::getInstance().convertToPolicyDescription(policy.result);
653 // All policy entries in PRIVACY_MANAGER should be fully-qualified
654 pe.maxLevel = CynaraAdmin::getInstance().convertToPolicyDescription(
655 CynaraAdmin::getInstance().GetPrivilegeManagerMaxLevel(
656 policy.client, policy.user, policy.privilege));
658 // Cannot reliably calculate maxLavel for policies from ADMIN bucket
659 pe.maxLevel = CynaraAdmin::getInstance().convertToPolicyDescription(CYNARA_ADMIN_ALLOW);
664 "[policy_entry] app: " << pe.appId
665 << " user: " << pe.user
666 << " privilege: " << pe.privilege
667 << " current: " << pe.currentLevel
668 << " max: " << pe.maxLevel
671 policyEntries.push_back(pe);
674 } catch (const CynaraException::Base &e) {
675 LogError("Error while listing Cynara rules: " << e.DumpToString());
676 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
677 } catch (const std::bad_alloc &e) {
678 LogError("Memory allocation error while listing Cynara rules: " << e.what());
679 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
683 return SECURITY_MANAGER_API_SUCCESS;
686 int getPolicy(const policy_entry &filter, uid_t uid, pid_t pid, const std::string &smackLabel, std::vector<policy_entry> &policyEntries)
689 std::string uidStr = std::to_string(uid);
690 std::string pidStr = std::to_string(pid);
692 if (!Cynara::getInstance().check(smackLabel, SELF_PRIVILEGE, uidStr, pidStr)) {
693 LogWarning("Not enough permission to call: " << __FUNCTION__);
694 return SECURITY_MANAGER_API_ERROR_ACCESS_DENIED;
697 LogDebug("Filter is: C: " << filter.appId
698 << ", U: " << filter.user
699 << ", P: " << filter.privilege
700 << ", current: " << filter.currentLevel
701 << ", max: " << filter.maxLevel
704 std::vector<uid_t> listOfUsers;
706 if (Cynara::getInstance().check(smackLabel, ADMIN_PRIVILEGE, uidStr, pidStr)) {
707 LogDebug("User is privileged");
708 if (filter.user.compare(SECURITY_MANAGER_ANY)) {
709 LogDebug("Limitting Cynara query to user: " << filter.user);
711 listOfUsers.push_back(static_cast<uid_t>(std::stoul(filter.user)));
712 } catch (std::invalid_argument &e) {
713 LogError("Invalid UID: " << e.what());
716 CynaraAdmin::getInstance().ListUsers(listOfUsers);
718 LogWarning("Not enough privilege to fetch user policy for all users by user: " << uid);
719 LogDebug("Fetching personal policy for user: " << uid);
720 listOfUsers.push_back(uid);
722 LogDebug("Fetching policy for " << listOfUsers.size() << " users");
724 for (const uid_t &uid : listOfUsers) {
725 LogDebug("User: " << uid);
726 std::string userStr = std::to_string(uid);
727 std::vector<std::string> listOfApps;
729 if (filter.appId.compare(SECURITY_MANAGER_ANY)) {
730 LogDebug("Limitting Cynara query to app: " << filter.appId);
731 listOfApps.push_back(filter.appId);
733 PrivilegeDb::getInstance().GetUserApps(uid, listOfApps);
734 LogDebug("Found apps: " << listOfApps.size());
737 for (const std::string &appId : listOfApps) {
738 LogDebug("App: " << appId);
739 std::string smackLabelForApp;
740 std::vector<std::string> listOfPrivileges;
742 generateAppLabel(appId, smackLabelForApp);
743 // FIXME: also fetch privileges of global applications
744 PrivilegeDb::getInstance().GetAppPrivileges(appId, uid, listOfPrivileges);
746 if (filter.privilege.compare(SECURITY_MANAGER_ANY)) {
747 LogDebug("Limitting Cynara query to privilege: " << filter.privilege);
748 // FIXME: this filtering should be already performed by method fetching the privileges
749 if (std::find(listOfPrivileges.begin(), listOfPrivileges.end(),
750 filter.privilege) == listOfPrivileges.end()) {
751 LogDebug("Application " << appId <<
752 " doesn't have the filteres privilege " << filter.privilege);
755 listOfPrivileges.clear();
756 listOfPrivileges.push_back(filter.privilege);
759 LogDebug("Privileges matching filter - " << filter.privilege << ": " << listOfPrivileges.size());
761 for (const std::string &privilege : listOfPrivileges) {
762 LogDebug("Privilege: " << privilege);
767 pe.privilege = privilege;
769 pe.currentLevel = CynaraAdmin::getInstance().convertToPolicyDescription(
770 CynaraAdmin::getInstance().GetPrivilegeManagerCurrLevel(
771 smackLabelForApp, userStr, privilege));
773 pe.maxLevel = CynaraAdmin::getInstance().convertToPolicyDescription(
774 CynaraAdmin::getInstance().GetPrivilegeManagerMaxLevel(
775 smackLabelForApp, userStr, privilege));
778 "[policy_entry] app: " << pe.appId
779 << " user: " << pe.user
780 << " privilege: " << pe.privilege
781 << " current: " << pe.currentLevel
782 << " max: " << pe.maxLevel
785 policyEntries.push_back(pe);
790 } catch (const CynaraException::Base &e) {
791 LogError("Error while listing Cynara rules: " << e.DumpToString());
792 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
793 } catch (const std::bad_alloc &e) {
794 LogError("Memory allocation error while listing Cynara rules: " << e.what());
795 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
798 return SECURITY_MANAGER_API_SUCCESS;
801 int policyGetDesc(std::vector<std::string> &levels)
803 int ret = SECURITY_MANAGER_API_SUCCESS;
806 CynaraAdmin::getInstance().ListPoliciesDescriptions(levels);
807 } catch (const CynaraException::OutOfMemory &e) {
808 LogError("Error - out of memory while querying Cynara for policy descriptions list: " << e.DumpToString());
809 return SECURITY_MANAGER_API_ERROR_OUT_OF_MEMORY;
810 } catch (const CynaraException::InvalidParam &e) {
811 LogError("Error - invalid parameter while querying Cynara for policy descriptions list: " << e.DumpToString());
812 return SECURITY_MANAGER_API_ERROR_INPUT_PARAM;
813 } catch (const CynaraException::ServiceNotAvailable &e) {
814 LogError("Error - service not available while querying Cynara for policy descriptions list: " << e.DumpToString());
815 return SECURITY_MANAGER_API_ERROR_NO_SUCH_SERVICE;
816 } catch (const CynaraException::Base &e) {
817 LogError("Error while getting policy descriptions list from Cynara: " << e.DumpToString());
818 return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
824 } /* namespace ServiceImpl */
825 } /* namespace SecurityManager */