return DescriptionToType.at(policy);
}
-void CynaraAdmin::Check(const std::string &label, const std::string &privilege, const std::string &user,
+void CynaraAdmin::Check(const std::string &label, const std::string &user, const std::string &privilege,
const std::string &bucket, int &result, std::string &resultExtra, const bool recursive)
{
char *resultExtraCstr = nullptr;
}
}
+int CynaraAdmin::GetPrivilegeManagerCurrLevel(const std::string &label, const std::string &user,
+ const std::string &privilege)
+{
+ int result;
+ std::string resultExtra;
+
+ Check(label, user, privilege, Buckets.at(Bucket::PRIVACY_MANAGER), result, resultExtra, true);
+
+ return result;
+}
+
+int CynaraAdmin::GetPrivilegeManagerMaxLevel(const std::string &label, const std::string &user,
+ const std::string &privilege)
+{
+ int result;
+ std::string resultExtra;
+
+ Check(label, user, privilege, Buckets.at(Bucket::MAIN), result, resultExtra, true);
+
+ return result;
+}
+
Cynara::Cynara()
{
checkCynaraError(
* all buckets linked with bucket provided
*/
void Check(const std::string &label,
- const std::string &privilege,
const std::string &user,
+ const std::string &privilege,
const std::string &bucket,
int &result,
std::string &resultExtra,
const bool recursive);
+ /**
+ * Get current policy level for privilege-manager functionality
+ * Returns current policy value for given application, user and privilege
+ * identifiers.
+ *
+ * @param label application Smack label
+ * @param user user identifier (uid)
+ * @param privilege privilege identifier
+ * @return current policy value
+ */
+ int GetPrivilegeManagerCurrLevel(const std::string &label, const std::string &user,
+ const std::string &privilege);
+
+ /**
+ * Get maximum policy level for privilege-manager functionality
+ * Returns maximum possible policy value for given application, user and privilege
+ * identifiers. The maximum limit is imposed by other policy settings that are
+ * currently in place.
+ *
+ * @param label application Smack label
+ * @param user user identifier (uid)
+ * @param privilege privilege identifier
+ * @return maximum policy value for PRIVACY_MANAGER bucket
+ */
+ int GetPrivilegeManagerMaxLevel(const std::string &label, const std::string &user,
+ const std::string &privilege);
+
private:
CynaraAdmin();
*
* @return API return code, as defined in protocols.h
*/
+
int policyUpdate(const std::vector<policy_entry> &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
+ * policies are returned.
+ *
+ * @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<policy_entry> &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] 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<policy_entry> &policyEntries);
+
} /* namespace ServiceImpl */
} /* namespace SecurityManager */
app_install_path_type pathType);
/**
+ * Generates application name for a label fetched from Cynara
+ *
+ * @param[in] label string to fetch application name for
+ * @return application name on success, empty string on error.
+*/
+std::string generateAppNameFromLabel(const std::string &label);
+
+/**
* Generates label for an application with a specific application ID
* read from @ref appId and assigns it to @ref label.
*
return SECURITY_MANAGER_API_SUCCESS;
}
+int getConfiguredPolicy(bool forAdmin, const policy_entry &filter, uid_t uid, pid_t pid,
+ const std::string &smackLabel, std::vector<policy_entry> &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_API_ERROR_ACCESS_DENIED;
+ };
+
+ LogDebug("Filter is: C: " << filter.appId
+ << ", U: " << filter.user
+ << ", P: " << filter.privilege
+ << ", current: " << filter.currentLevel
+ << ", max: " << filter.maxLevel
+ );
+
+ std::vector<CynaraAdminPolicy> listOfPolicies;
+
+ //convert appId to smack label
+ std::string appLabel;
+ if (!filter.appId.compare(SECURITY_MANAGER_ANY))
+ appLabel = CYNARA_ADMIN_ANY;
+ else
+ generateAppLabel(filter.appId, appLabel);
+
+ std::string user = (!filter.user.compare(SECURITY_MANAGER_ANY))? CYNARA_ADMIN_ANY: filter.user;
+ std::string privilege = (!filter.privilege.compare(SECURITY_MANAGER_ANY))? CYNARA_ADMIN_ANY: filter.privilege;
+
+ LogDebug("App: " << filter.appId << ", Label: " << appLabel);
+
+ if (forAdmin) {
+ if (!Cynara::getInstance().check(smackLabel, ADMIN_PRIVILEGE, uidStr, pidStr)) {
+ LogError("Not enough privilege to access admin enforced policies: " << __FUNCTION__);
+ return SECURITY_MANAGER_API_ERROR_ACCESS_DENIED;
+ };
+
+ //Fetch privileges from ADMIN bucket
+ CynaraAdmin::getInstance().ListPolicies(
+ CynaraAdmin::Buckets.at(Bucket::ADMIN),
+ appLabel,
+ user,
+ privilege,
+ listOfPolicies
+ );
+ LogDebug("ADMIN - number of policies matched: " << listOfPolicies.size());
+ } else {
+ if (uidStr.compare(user)) {
+ if (!Cynara::getInstance().check(smackLabel, ADMIN_PRIVILEGE, uidStr, pidStr)) {
+ LogWarning("Not enough privilege to access other user's personal policies. Limiting query to personal privileges.");
+ user = uidStr;
+ };
+ };
+ //Fetch privileges from PRIVACY_MANAGER bucket
+ CynaraAdmin::getInstance().ListPolicies(
+ CynaraAdmin::Buckets.at(Bucket::PRIVACY_MANAGER),
+ appLabel,
+ user,
+ privilege,
+ listOfPolicies
+ );
+ LogDebug("PRIVACY MANAGER - number of policies matched: " << listOfPolicies.size());
+ };
+
+ for (const auto &policy : listOfPolicies) {
+ //ignore "jump to bucket" entries
+ if (policy.result == CYNARA_ADMIN_BUCKET)
+ continue;
+
+ policy_entry pe;
+
+ pe.appId = strcmp(policy.client, CYNARA_ADMIN_WILDCARD) ? generateAppNameFromLabel(policy.client) : SECURITY_MANAGER_ANY;
+ pe.user = strcmp(policy.user, CYNARA_ADMIN_WILDCARD) ? policy.user : SECURITY_MANAGER_ANY;
+ pe.privilege = strcmp(policy.privilege, CYNARA_ADMIN_WILDCARD) ? policy.privilege : pe.privilege = SECURITY_MANAGER_ANY;
+ pe.currentLevel = CynaraAdmin::getInstance().convertToPolicyDescription(policy.result);
+
+ if (!forAdmin) {
+ // All policy entries in PRIVACY_MANAGER should be fully-qualified
+ pe.maxLevel = CynaraAdmin::getInstance().convertToPolicyDescription(
+ CynaraAdmin::getInstance().GetPrivilegeManagerMaxLevel(
+ policy.client, policy.user, policy.privilege));
+ } else {
+ // Cannot reliably calculate maxLavel for policies from ADMIN bucket
+ pe.maxLevel = CynaraAdmin::getInstance().convertToPolicyDescription(CYNARA_ADMIN_ALLOW);
+ }
+
+
+ LogDebug(
+ "[policy_entry] app: " << pe.appId
+ << " user: " << pe.user
+ << " privilege: " << pe.privilege
+ << " current: " << pe.currentLevel
+ << " max: " << pe.maxLevel
+ );
+
+ policyEntries.push_back(pe);
+ };
+
+ } catch (const CynaraException::Base &e) {
+ LogError("Error while listing Cynara rules: " << e.DumpToString());
+ return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
+ } catch (const std::bad_alloc &e) {
+ LogError("Memory allocation error while listing Cynara rules: " << e.what());
+ return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
+ }
+
+
+ return SECURITY_MANAGER_API_SUCCESS;
+}
+
+int getPolicy(const policy_entry &filter, uid_t uid, pid_t pid, const std::string &smackLabel, std::vector<policy_entry> &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)) {
+ LogWarning("Not enough permission to call: " << __FUNCTION__);
+ return SECURITY_MANAGER_API_ERROR_ACCESS_DENIED;
+ };
+
+ LogDebug("Filter is: C: " << filter.appId
+ << ", U: " << filter.user
+ << ", P: " << filter.privilege
+ << ", current: " << filter.currentLevel
+ << ", max: " << filter.maxLevel
+ );
+
+ std::vector<uid_t> listOfUsers;
+
+ if (Cynara::getInstance().check(smackLabel, ADMIN_PRIVILEGE, uidStr, pidStr)) {
+ LogDebug("User is privileged");
+ if (filter.user.compare(SECURITY_MANAGER_ANY)) {
+ LogDebug("Limitting Cynara query to user: " << filter.user);
+ try {
+ listOfUsers.push_back(static_cast<uid_t>(std::stoul(filter.user)));
+ } catch (std::invalid_argument &e) {
+ LogError("Invalid UID: " << e.what());
+ };
+ } 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);
+ };
+ LogDebug("Fetching policy for " << listOfUsers.size() << " users");
+
+ for (const uid_t &uid : listOfUsers) {
+ LogDebug("User: " << uid);
+ std::string userStr = std::to_string(uid);
+ std::vector<std::string> listOfApps;
+
+ if (filter.appId.compare(SECURITY_MANAGER_ANY)) {
+ LogDebug("Limitting Cynara query to app: " << filter.appId);
+ listOfApps.push_back(filter.appId);
+ } else {
+ PrivilegeDb::getInstance().GetUserApps(uid, listOfApps);
+ LogDebug("Found apps: " << listOfApps.size());
+ };
+
+ for (const std::string &appId : listOfApps) {
+ LogDebug("App: " << appId);
+ std::string smackLabelForApp;
+ std::vector<std::string> listOfPrivileges;
+
+ generateAppLabel(appId, smackLabelForApp);
+ // FIXME: also fetch privileges of global applications
+ PrivilegeDb::getInstance().GetAppPrivileges(appId, uid, listOfPrivileges);
+
+ if (filter.privilege.compare(SECURITY_MANAGER_ANY)) {
+ LogDebug("Limitting Cynara query to privilege: " << filter.privilege);
+ // FIXME: this filtering should be already performed by method fetching the privileges
+ if (std::find(listOfPrivileges.begin(), listOfPrivileges.end(),
+ filter.privilege) == listOfPrivileges.end()) {
+ LogDebug("Application " << appId <<
+ " doesn't have the filteres privilege " << filter.privilege);
+ continue;
+ }
+ listOfPrivileges.clear();
+ listOfPrivileges.push_back(filter.privilege);
+ }
+
+ LogDebug("Privileges matching filter - " << filter.privilege << ": " << listOfPrivileges.size());
+
+ for (const std::string &privilege : listOfPrivileges) {
+ LogDebug("Privilege: " << privilege);
+ policy_entry pe;
+
+ pe.appId = appId;
+ pe.user = userStr;
+ pe.privilege = privilege;
+
+ pe.currentLevel = CynaraAdmin::getInstance().convertToPolicyDescription(
+ CynaraAdmin::getInstance().GetPrivilegeManagerCurrLevel(
+ smackLabelForApp, userStr, privilege));
+
+ pe.maxLevel = CynaraAdmin::getInstance().convertToPolicyDescription(
+ CynaraAdmin::getInstance().GetPrivilegeManagerMaxLevel(
+ smackLabelForApp, userStr, privilege));
+
+ LogDebug(
+ "[policy_entry] app: " << pe.appId
+ << " user: " << pe.user
+ << " privilege: " << pe.privilege
+ << " current: " << pe.currentLevel
+ << " max: " << pe.maxLevel
+ );
+
+ policyEntries.push_back(pe);
+ };
+ };
+ };
+
+ } catch (const CynaraException::Base &e) {
+ LogError("Error while listing Cynara rules: " << e.DumpToString());
+ return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
+ } catch (const std::bad_alloc &e) {
+ LogError("Memory allocation error while listing Cynara rules: " << e.what());
+ return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
+ }
+
+ return SECURITY_MANAGER_API_SUCCESS;
+}
+
} /* namespace ServiceImpl */
} /* namespace SecurityManager */
return labelDir(path, label, label_transmute, label_executables);
}
+std::string generateAppNameFromLabel(const std::string &label)
+{
+ //TODO: Fix when a label generating mechanism is ready
+ return label;
+}
+
bool generateAppLabel(const std::string &appId, std::string &label)
{
(void) appId;
void processUserDelete(MessageBuffer &buffer, MessageBuffer &send, uid_t uid);
-
/**
* Process policy update request
*
* @param smackLabel smack label of requesting app
*/
void processPolicyUpdate(MessageBuffer &buffer, MessageBuffer &send, uid_t uid, pid_t pid, const std::string &smackLabel);
+
+ /**
+ * List all privileges for specific user, placed in Cynara's PRIVACY_MANAGER
+ * or ADMIN's bucket - choice based on forAdmin parameter
+ *
+ * @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 forAdmin determines internal type of request
+ */
+ void processGetConfiguredPolicy(MessageBuffer &buffer, MessageBuffer &send, uid_t uid, pid_t pid, const std::string &smackLabel, 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.
+ *
+ * @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
+ */
+ void processGetPolicy(MessageBuffer &buffer, MessageBuffer &send, uid_t uid, pid_t pid, const std::string &smackLabel);
+
};
} // namespace SecurityManager
case SecurityModuleCall::POLICY_UPDATE:
processPolicyUpdate(buffer, send, uid, pid, smackLabel);
break;
+ case SecurityModuleCall::GET_CONF_POLICY_ADMIN:
+ processGetConfiguredPolicy(buffer, send, uid, pid, smackLabel, true);
+ break;
+ case SecurityModuleCall::GET_CONF_POLICY_SELF:
+ processGetConfiguredPolicy(buffer, send, uid, pid, smackLabel, false);
+ break;
+ case SecurityModuleCall::GET_POLICY:
+ processGetPolicy(buffer, send, uid, pid, smackLabel);
+ break;
default:
LogError("Invalid call: " << call_type_int);
Throw(ServiceException::InvalidAction);
Serialization::Serialize(send, ret);
}
-
void Service::processPolicyUpdate(MessageBuffer &buffer, MessageBuffer &send, uid_t uid, pid_t pid, const std::string &smackLabel)
{
int ret;
Serialization::Serialize(send, ret);
}
+void Service::processGetConfiguredPolicy(MessageBuffer &buffer, MessageBuffer &send, uid_t uid, pid_t pid, const std::string &smackLabel, bool forAdmin)
+{
+ int ret;
+ policy_entry filter;
+ Deserialization::Deserialize(buffer, filter);
+ std::vector<policy_entry> policyEntries;
+ ret = ServiceImpl::getConfiguredPolicy(forAdmin, filter, uid, pid, smackLabel, policyEntries);
+ Serialization::Serialize(send, ret);
+ Serialization::Serialize(send, static_cast<int>(policyEntries.size()));
+ for (const auto &policyEntry : policyEntries) {
+ Serialization::Serialize(send, policyEntry);
+ };
+}
+
+void Service::processGetPolicy(MessageBuffer &buffer, MessageBuffer &send, uid_t uid, pid_t pid, const std::string &smackLabel)
+{
+ int ret;
+ policy_entry filter;
+ Deserialization::Deserialize(buffer, filter);
+ std::vector<policy_entry> policyEntries;
+ ret = ServiceImpl::getPolicy(filter, uid, pid, smackLabel, policyEntries);
+ Serialization::Serialize(send, ret);
+ Serialization::Serialize(send, static_cast<int>(policyEntries.size()));
+ for (const auto &policyEntry : policyEntries) {
+ Serialization::Serialize(send, policyEntry);
+ };
+}
+
} // namespace SecurityManager