cp LICENSE %{buildroot}/usr/share/license/libsecurity-manager-client
mkdir -p %{buildroot}/etc/security/
cp security-server-audit.conf %{buildroot}/etc/security/
+mkdir -p %{buildroot}/etc/smack/
+cp app-rules-template.smack %{buildroot}/etc/smack/
%make_install
mkdir -p %{buildroot}/usr/lib/systemd/system/multi-user.target.wants
%attr(-,root,root) /usr/lib/systemd/system/security-server-cookie-check.socket
%attr(-,root,root) /usr/lib/systemd/system/sockets.target.wants/security-server-app-privilege-by-name.socket
%attr(-,root,root) /usr/lib/systemd/system/security-server-app-privilege-by-name.socket
-%attr(-,root,root) /etc/security/security-server-audit.conf
%attr(-,root,root) /usr/lib/systemd/system/sockets.target.wants/security-server-password-check.socket
%attr(-,root,root) /usr/lib/systemd/system/security-server-password-check.socket
%attr(-,root,root) /usr/lib/systemd/system/sockets.target.wants/security-server-password-set.socket
%attr(-,root,root) /usr/lib/systemd/system/security-server-password-reset.socket
%attr(-,root,root) /usr/lib/systemd/system/sockets.target.wants/security-manager-installer.socket
%attr(-,root,root) /usr/lib/systemd/system/security-manager-installer.socket
-
+%attr(-,root,root) /etc/security/security-server-audit.conf
+%attr(-,root,root) /etc/smack/app-rules-template.smack
%{_datadir}/license/%{name}
%files -n libsecurity-server-client
*/
/*
* @file installer.cpp
- * @author Michal Witanowski (m.witanowski@samsung.com)
+ * @author Michal Witanowski <m.witanowski@samsung.com>
+ * @author Jacek Bukarewicz <j.bukarewicz@samsung.com>
* @brief Implementation of installer service for libprivilege-control encapsulation.
*/
#include "protocols.h"
#include "security-server.h"
#include "security-manager.h"
+#include "smack-rules.h"
namespace SecurityServer {
}
}
+ // TODO: This should be done only for the first application in the package
+ if (!SecurityManager::SmackRules::installPackageRules(req.pkgId)) {
+ LogError("Failed to apply package-specific smack rules");
+ goto error_label;
+ }
+
// finish database transaction
result = perm_end();
LogDebug("perm_end() returned " << result);
if (PC_OPERATION_SUCCESS != result) {
+ // TODO: Uncomment once proper pkgId -> smack label mapping is implemented (currently all
+ // applications are mapped to user label and removal of such rules would be harmful)
+ //SecurityManager::SmackRules::uninstallPackageRules(req.pkgId);
+
// error in libprivilege-control
Serialization::Serialize(send, SECURITY_SERVER_API_ERROR_SERVER_ERROR);
return false;
return false;
}
+ // TODO: Uncomment once proper pkgId -> smack label mapping is implemented (currently all
+ // applications are mapped to user label and removal of such rules would be harmful)
+ // TODO: This should be performed only for the last application in the package
+ // TODO: retrieve pkgId as it's not available in the request
+ //if (!SecurityManager::SmackRules::uninstallPackageRules(pkgId)) {
+ // LogError("Error on uninstallation of package-specific smack rules");
+ // result = perm_rollback();
+ // LogDebug("perm_rollback() returned " << result);
+ // Serialization::Serialize(send, SECURITY_SERVER_API_ERROR_SERVER_ERROR);
+ // return false;
+ //}
+
// finish database transaction
result = perm_end();
LogDebug("perm_end() returned " << result);
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Rafal Krypa <r.krypa@samsung.com>
+ *
+ * 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 smack-rules.cpp
+ * @author Jacek Bukarewicz <j.bukarewicz@samsung.com>
+ * @version 1.0
+ * @brief Implementation of a class managing smack rules
+ *
+ */
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/smack.h>
+#include <fcntl.h>
+#include <fstream>
+
+#include <dpl/log/log.h>
+
+#include "smack-rules.h"
+#include "security-manager-common.h"
+
+namespace SecurityManager {
+
+const char *const SMACK_APP_LABEL_TEMPLATE = "~APP~";
+const char *const APP_RULES_TEMPLATE_FILE_PATH = "/etc/smack/app-rules-template.smack";
+const char *const APP_RULES_DIRECTORY = "/etc/smack/accesses.d/";
+
+SmackRules::SmackRules()
+{
+ if (smack_accesses_new(&m_handle) < 0) {
+ LogError("Failed to create smack_accesses handle");
+ throw std::bad_alloc();
+ }
+}
+
+SmackRules::~SmackRules() {
+ smack_accesses_free(m_handle);
+}
+
+bool SmackRules::add(const std::string &subject, const std::string &object,
+ const std::string &permissions)
+{
+ return 0 == smack_accesses_add(m_handle, subject.c_str(), object.c_str(), permissions.c_str());
+}
+
+bool SmackRules::clear() const
+{
+ return 0 == smack_accesses_clear(m_handle);
+}
+
+bool SmackRules::apply() const
+{
+ return 0 == smack_accesses_apply(m_handle);
+}
+
+bool SmackRules::loadFromFile(const std::string &path)
+{
+ int fd;
+ bool ret = true;
+
+ fd = open(path.c_str(), O_RDONLY);
+ if (fd == -1) {
+ LogError("Failed to open file: %s" << path);
+ return false;
+ }
+
+ if (smack_accesses_add_from_file(m_handle, fd)) {
+ LogError("Failed to load smack rules from file: %s" << path);
+ ret = false;
+ }
+
+ close(fd);
+ return ret;
+}
+
+bool SmackRules::saveToFile(const std::string &path) const
+{
+ int fd;
+ bool ret = true;
+
+ fd = open(path.c_str(), O_CREAT | O_WRONLY | O_TRUNC, 0644);
+ if (fd == -1) {
+ LogError("Failed to create file: %s" << path);
+ return false;
+ }
+
+ if (smack_accesses_save(m_handle, fd)) {
+ LogError("Failed to save rules to file: %s" << path);
+ unlink(path.c_str());
+ ret = false;
+ }
+
+ close(fd);
+ return ret;
+}
+
+
+bool SmackRules::addFromTemplateFile(const std::string &pkgId)
+{
+ std::vector<std::string> templateRules;
+ std::string line;
+ std::ifstream templateRulesFile(APP_RULES_TEMPLATE_FILE_PATH);
+
+ if (!templateRulesFile.is_open()) {
+ LogError("Cannot open rules template file: " << APP_RULES_TEMPLATE_FILE_PATH);
+ return false;
+ }
+
+ while (std::getline(templateRulesFile, line)) {
+ templateRules.push_back(line);
+ }
+
+ if (templateRulesFile.bad()) {
+ LogError("Error reading template file: " << APP_RULES_TEMPLATE_FILE_PATH);
+ return false;
+ }
+
+ return addFromTemplate(templateRules, pkgId);
+}
+
+bool SmackRules::addFromTemplate(const std::vector<std::string> &templateRules,
+ const std::string &pkgId)
+{
+ std::string tokens[3];
+ std::string &subject = tokens[0];
+ std::string &object = tokens[1];
+ std::string &permissions = tokens[2];
+
+ for (auto rule = templateRules.begin(); rule != templateRules.end(); ++rule) {
+ if (rule->length() == 0)
+ continue;
+
+ if (!tokenizeRule(*rule, tokens, sizeof(tokens) / sizeof(*tokens))) {
+ return false;
+ }
+
+ bool subjectIsTemplate = (subject == SMACK_APP_LABEL_TEMPLATE);
+ bool objectIsTemplate = (object == SMACK_APP_LABEL_TEMPLATE);
+
+ if (objectIsTemplate == subjectIsTemplate) {
+ LogError("Invalid rule template. Exactly one app label template expected: " << *rule);
+ return false;
+ }
+
+ if (subjectIsTemplate) {
+ if (!SecurityManager::generateAppLabel(pkgId, subject)) {
+ LogError("Failed to generate app label from pkgid: " << pkgId);
+ return false;
+ }
+ }
+
+ if (objectIsTemplate) {
+ if (!SecurityManager::generateAppLabel(pkgId, object)) {
+ LogError("Failed to generate app label from pkgid: " << pkgId);
+ return false;
+ }
+ }
+
+ if (!add(subject, object, permissions)) {
+ LogError("Failed to add rule: " << subject << " " << object << " " << permissions);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+bool SmackRules::tokenizeRule(const std::string &rule, std::string tokens[], int size)
+{
+ size_t startPos;
+ size_t endPos = 0;
+ const char delimiters[] = " \t\n\r";
+
+ for (int i = 0; i < size; i++) {
+ startPos = rule.find_first_not_of(delimiters, endPos);
+ if (startPos == std::string::npos) {
+ LogError("Unexpected end of rule: " << rule);
+ return false;
+ }
+
+ endPos = rule.find_first_of(delimiters, startPos);
+ tokens[i] = rule.substr(startPos, endPos - startPos);
+ }
+
+ if (endPos != std::string::npos &&
+ rule.find_first_not_of(delimiters, endPos) != std::string::npos) {
+ LogError("Too many tokens found in rule: " << rule);
+ return false;
+ }
+
+ return true;
+}
+
+std::string SmackRules::getPackageRulesFilePath(const std::string &pkgId)
+{
+ std::string path(APP_RULES_DIRECTORY);
+ path.append(pkgId);
+ path.append(".smack");
+ return path;
+}
+
+bool SmackRules::installPackageRules(const std::string &pkgId) {
+ try {
+ SmackRules smackRules;
+ std::string path = getPackageRulesFilePath(pkgId);
+
+ if (!smackRules.addFromTemplateFile(pkgId)) {
+ LogError("Failed to load smack rules for pkgId " << pkgId);
+ return false;
+ }
+
+ if (!smackRules.apply()) {
+ LogError("Failed to apply application rules to kernel");
+ return false;
+ }
+
+ if (!smackRules.saveToFile(path)) {
+ smackRules.clear();
+ return false;
+ }
+
+ return true;
+ } catch (const std::bad_alloc &e) {
+ LogError("Out of memory while trying to install smack rules for pkgId " << pkgId);
+ return false;
+ }
+}
+
+bool SmackRules::uninstallPackageRules(const std::string &pkgId) {
+ std::string path = getPackageRulesFilePath(pkgId);
+ if (access(path.c_str(), F_OK) == -1) {
+ if (errno == ENOENT) {
+ LogWarning("Smack rules were not installed for pkgId: " << pkgId);
+ return true;
+ }
+
+ LogWarning("Cannot access smack rules path: " << path);
+ return false;
+ }
+
+ try {
+ SmackRules rules;
+ if (rules.loadFromFile(path)) {
+ if (!rules.clear()) {
+ LogWarning("Failed to clear smack kernel rules for pkgId: " << pkgId);
+ // don't stop uninstallation
+ }
+ } else {
+ LogWarning("Failed to load rules from file: " << path);
+ // don't stop uninstallation
+ }
+
+ if (unlink(path.c_str()) == -1) {
+ LogError("Failed to remove smack rules file: " << path);
+ return false;
+ }
+
+ return true;
+ } catch (const std::bad_alloc &e) {
+ LogError("Out of memory while trying to uninstall smack rules for pkgId: " << pkgId);
+ return false;
+ }
+}
+
+} // namespace SecurityManager
+
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Rafal Krypa <r.krypa@samsung.com>
+ *
+ * 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 smack-rules.h
+ * @author Jacek Bukarewicz <j.bukarewicz@samsung.com>
+ * @version 1.0
+ * @brief Header file of a class managing smack rules
+ *
+ */
+#ifndef _SMACK_RULES_H_
+#define _SMACK_RULES_H_
+
+#include <vector>
+#include <string>
+
+struct smack_accesses;
+
+namespace SecurityManager {
+
+class SmackRules
+{
+public:
+ SmackRules();
+ virtual ~SmackRules();
+
+ bool add(const std::string &subject, const std::string &object,
+ const std::string &permissions);
+ bool loadFromFile(const std::string &path);
+ bool addFromTemplate(const std::vector<std::string> &templateRules, const std::string &pkgId);
+ bool addFromTemplateFile(const std::string &pkgId);
+
+ bool apply() const;
+ bool clear() const;
+ bool saveToFile(const std::string &path) const;
+
+ /**
+ * Install package-specific smack rules.
+ *
+ * Function creates smack rules using predefined template. Rules are applied
+ * to the kernel and saved on persistent storage so they are loaded on system boot.
+ *
+ * @param[in] pkgId - package identifier
+ * @return true on success, false on error
+ */
+ static bool installPackageRules(const std::string &pkgId);
+ /**
+ * Uninstall package-specific smack rules.
+ *
+ * Function loads package-specific smack rules, revokes them from the kernel
+ * and removes from persistent storage.
+ *
+ * @param[in] pkgId - package identifier
+ * @return true if smack rule file has been uninstalled or didn't exist
+ * false otherwise
+ */
+ static bool uninstallPackageRules(const std::string &pkgId);
+private:
+ static bool tokenizeRule(const std::string &rule, std::string tokens[], int size);
+ static std::string getPackageRulesFilePath(const std::string &pkgId);
+
+ smack_accesses *m_handle;
+};
+
+} // namespace SecurityManager
+
+#endif /* _SMACK_RULES_H_ */