Refactoring: put code operating on Smack labels in a separate file 46/23846/6
authorRafał Krypa <rafal@krypa.net>
Fri, 11 Jul 2014 19:28:21 +0000 (21:28 +0200)
committerRafał Krypa <rafal@krypa.net>
Sun, 13 Jul 2014 21:11:10 +0000 (23:11 +0200)
Create smack-labels.cpp, containing code for label assignment and file
labeling. Avoid clutter in installer.cpp.

Change-Id: I97f5251e1bfcd53e242cd0117d48539a378fefde
Signed-off-by: Rafal Krypa <r.krypa@samsung.com>
src/server/CMakeLists.txt
src/server/service/include/installer.h
src/server/service/include/smack-labels.h [new file with mode: 0644]
src/server/service/include/smack-rules.h
src/server/service/installer.cpp
src/server/service/smack-labels.cpp [new file with mode: 0644]
src/server/service/smack-rules.cpp

index 5fc4c39..3894888 100644 (file)
@@ -38,6 +38,7 @@ SET(SERVER_SOURCES
     ${SERVER_PATH}/main/socket-manager.cpp
     ${SERVER_PATH}/main/server-main.cpp
     ${SERVER_PATH}/service/smack-rules.cpp
+    ${SERVER_PATH}/service/smack-labels.cpp
     ${SERVER_PATH}/service/installer.cpp
     ${SERVER_PATH}/db/privilege_db.cpp
     ${DPL_PATH}/core/src/errno_string.cpp
index 8e240ae..c73f93a 100644 (file)
@@ -58,8 +58,6 @@ public:
     void process(const ReadEvent &event);
     void close(const CloseEvent &event);
 
-    static const char *const LABEL_FOR_PUBLIC_APP_PATH;
-
 private:
     ConnectionInfoMap m_connectionInfoMap;
     PrivilegeDb m_privilegeDb;
diff --git a/src/server/service/include/smack-labels.h b/src/server/service/include/smack-labels.h
new file mode 100644 (file)
index 0000000..a017991
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ *  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-labels.h
+ * @author      Jan Cybulski <j.cybulski@samsung.com>
+ * @author      Rafal Krypa <r.krypa@samsung.com>
+ * @version     1.0
+ * @brief       Header file of functions managing smack labels
+ *
+ */
+#ifndef _SMACK_LABELS_H_
+#define _SMACK_LABELS_H_
+
+#include <string>
+#include <utility>
+
+#include "security-manager.h"
+
+namespace SecurityManager {
+
+/**
+ * Generates label for application with package identifier
+ * read from @ref pkgId and assigns it to @ref label.
+ * @param[in] pkgId application's package identifier.
+ * @param[out] label string into which application's label will be stored into.
+ *
+ * @return true on success, false on error.
+*/
+bool generateAppLabel(const std::string &pkgId, std::string &label);
+
+/**
+ * Sets Smack labels on a directory and its contents, recursively.
+ *
+ * @param pkgId[in] application's package identifier
+ * @param path[in] path to a file or directory to setup
+ * @param pathType[in] type of path to setup. See description of
+ *         app_install_path_type in security-manager.h for details
+ *
+ * @return true on success, false on error.
+ */
+bool setupPath(const std::string &pkgId, const std::string &path,
+    app_install_path_type pathType);
+
+} // namespace SecurityManager
+
+#endif /* _SMACK_LABELS_H_ */
index 6aa6775..db81631 100644 (file)
@@ -70,15 +70,6 @@ public:
      */
     static bool uninstallPackageRules(const std::string &pkgId);
 
-    /**
-    * Generates label for application with package identifier
-    * read from @ref appPkgId and assigns it to @ref label.
-    * @param[in] appPkgId application's package identifier.
-    * @param[out] label string into which application's label will be stored into.
-    * @return true on success, false on error.
-    */
-    static bool generateAppLabel(const std::string &appPkgId, std::string &label);
-
 private:
     static std::string getPackageRulesFilePath(const std::string &pkgId);
 
index fc993e0..d7810a9 100644 (file)
 
 #include <privilege-control.h>
 
-#include <sys/stat.h>
-#include <sys/smack.h>
-#include <sys/xattr.h>
-#include <linux/xattr.h>
-#include <memory>
-#include <fts.h>
-#include <cstring>
-
 #include "installer.h"
 #include "protocols.h"
 #include "security-manager.h"
 #include "smack-rules.h"
+#include "smack-labels.h"
 #include "privilege_db.h"
 
 namespace SecurityManager {
 
-namespace {
-
 const InterfaceID INSTALLER_IFACE = 0;
 
-/* Const defined below is used to label links to executables */
-const char *const XATTR_NAME_TIZENEXEC =  XATTR_SECURITY_PREFIX "TIZEN_EXEC_LABEL";
-
-/**
- * Return values
- * -1 - error
- * 0 - skip
- * 1 - label
- */
-enum class FileDecision {
-    SKIP = 0,
-    LABEL = 1,
-    ERROR = -1
-};
-
-typedef std::function<FileDecision(const FTSENT*)> LabelDecisionFn;
-
-
-FileDecision labelAll(const FTSENT *ftsent __attribute__((unused)))
-{
-    LogDebug("Entering function: " << __func__);
-
-    return FileDecision::LABEL;
-}
-
-FileDecision labelDirs(const FTSENT *ftsent)
-{
-    LogDebug("Entering function: " << __func__);
-
-    // label only directories
-    if (S_ISDIR(ftsent->fts_statp->st_mode))
-        return FileDecision::LABEL;
-    return FileDecision::SKIP;
-}
-
-FileDecision labelExecs(const FTSENT *ftsent)
-{
-    LogDebug("Entering function: " << __func__);
-
-    LogDebug("Mode = " << ftsent->fts_statp->st_mode);
-    // label only regular executable files
-    if (S_ISREG(ftsent->fts_statp->st_mode) && (ftsent->fts_statp->st_mode & S_IXUSR))
-        return FileDecision::LABEL;
-    return FileDecision::SKIP;
-}
-
-
-FileDecision labelLinksToExecs(const FTSENT *ftsent)
-{
-    LogDebug("Entering function: " << __func__);
-
-    struct stat buf;
-
-    // check if it's a link
-    if ( !S_ISLNK(ftsent->fts_statp->st_mode))
-        return FileDecision::SKIP;
-
-    std::unique_ptr<char, std::function<void(void*)>> target(realpath(ftsent->fts_path, NULL), free);
-
-    if (!target.get()) {
-        LogError("Getting link target for " << ftsent->fts_path << " failed (Error = " << strerror(errno) << ")");
-        return FileDecision::ERROR;
-    }
-
-    if (-1 == stat(target.get(), &buf)) {
-        LogError("stat failed for " << target.get() << " (Error = " << strerror(errno) << ")");
-        return FileDecision::ERROR;
-    }
-    // skip if link target is not a regular executable file
-    if (buf.st_mode != (buf.st_mode | S_IXUSR | S_IFREG)) {
-        LogDebug(target.get() << "is not a regular executable file. Skipping.");
-        return FileDecision::SKIP;
-    }
-
-    return FileDecision::LABEL;
-}
-
-bool dirSetSmack(const std::string &path, const std::string &label,
-        const char *xattr_name, LabelDecisionFn fn)
-{
-    LogDebug("Entering function: "<< __func__ <<". Params:"
-            " path=" << path << ", label=" << label << ", xattr=" << xattr_name);
-
-
-    char *const path_argv[] = {const_cast<char *>(path.c_str()), NULL};
-    FTSENT *ftsent;
-    FileDecision ret;
-
-    std::unique_ptr<FTS, std::function<void(FTS*)> > fts(
-            fts_open(path_argv, FTS_PHYSICAL | FTS_NOCHDIR, NULL),
-            fts_close);
-
-    if (fts.get() == NULL) {
-        LogError("fts_open failed.");
-        return false;
-    }
-
-    while ((ftsent = fts_read(fts.get())) != NULL) {
-        /* Check for error (FTS_ERR) or failed stat(2) (FTS_NS) */
-        if (ftsent->fts_info == FTS_ERR || ftsent->fts_info == FTS_NS) {
-            LogError("FTS_ERR error or failed stat(2) (FTS_NS)");
-            return false;
-        }
-
-        ret = fn(ftsent);
-        if (ret == FileDecision::ERROR) {
-            LogError("fn(ftsent) failed.");
-            return false;
-        }
-
-        if (ret == FileDecision::LABEL) {
-            if (lsetxattr(ftsent->fts_path, xattr_name, label.c_str(), label.length(), 0) != 0) {
-                LogError("lsetxattr failed.");
-                return false;
-            }
-        }
-
-    }
-
-    /* If last call to fts_read() set errno, we need to return error. */
-    if ((errno != 0) && (ftsent == NULL)) {
-        LogError("Last errno from fts_read: " << strerror(errno));
-        return false;
-    }
-    return true;
-}
-
-
-bool labelDir(const std::string &path, const std::string &label,
-        bool set_transmutable, bool set_executables)
-{
-    LogDebug("Entering function: "<< __func__ <<". Params:"
-            " path=" << path << " label= " << label
-            << " set_transmutable= " << set_transmutable
-            << " set_executables= " << set_executables);
-    bool ret = true;
-
-    // setting access label on everything in given directory and below
-    ret = dirSetSmack(path, label, XATTR_NAME_SMACK, labelAll);
-    if (!ret) {
-        LogError("dirSetSmack failed (access label)");
-        return ret;
-    }
-
-    if (set_transmutable) {
-        // setting transmute on dirs
-        ret = dirSetSmack(path, "TRUE", XATTR_NAME_SMACKTRANSMUTE, labelDirs);
-        if (!ret) {
-            LogError("dirSetSmack failed (transmute)");
-            return ret;
-        }
-    }
-
-    if (set_executables) {
-        ret = dirSetSmack(path, label, XATTR_NAME_SMACKEXEC, &labelExecs);
-        if (!ret)
-        {
-            LogError("dirSetSmack failed (execs).");
-            return ret;
-        }
-
-        //setting execute label for everything with permission to execute
-        ret = dirSetSmack(path, label, XATTR_NAME_TIZENEXEC, &labelLinksToExecs);
-        if (!ret)
-        {
-            LogError("dirSetSmack failed (link to execs).");
-            return ret;
-        }
-    }
-
-    return ret;
-}
-
-
-bool setupPath(const std::string &pkgId, const std::pair<std::string, int> &appPath)
-{
-    using namespace SecurityManager;
-
-    app_install_path_type pathType = static_cast<app_install_path_type>(appPath.second);
-    std::string label;
-    bool label_executables, label_transmute;
-
-
-    switch (pathType) {
-    case SECURITY_MANAGER_PATH_PRIVATE:
-        if (!SmackRules::generateAppLabel(pkgId, label))
-            return false;
-        label_executables = true;
-        label_transmute = false;
-        break;
-    case SECURITY_MANAGER_PATH_PUBLIC:
-        label.assign(InstallerService::LABEL_FOR_PUBLIC_APP_PATH);
-        label_executables = false;
-        label_transmute = true;
-        break;
-    case SECURITY_MANAGER_PATH_PUBLIC_RO:
-        label.assign("_");
-        label_executables = false;
-        label_transmute = false;
-        break;
-    default:
-        LogError("Path type not known.");
-        return false;
-    }
-    return labelDir(appPath.first, label, label_transmute, label_executables);
-}
-
-} // namespace anonymous
-
-/* Const defined below is used to label links to executables */
-const char *const InstallerService::LABEL_FOR_PUBLIC_APP_PATH = "User";
 
 InstallerService::InstallerService()
 {
@@ -383,7 +163,7 @@ bool InstallerService::processAppInstall(MessageBuffer &buffer, MessageBuffer &s
     LogDebug("pkgId: " << req.pkgId);
 
     std::string smackLabel;
-    if (!SmackRules::generateAppLabel(req.pkgId, smackLabel)) {
+    if (!generateAppLabel(req.pkgId, smackLabel)) {
         LogError("Cannot generate Smack label for package");
         Serialization::Serialize(send, SECURITY_MANAGER_API_ERROR_SERVER_ERROR);
         return false;
@@ -440,8 +220,11 @@ bool InstallerService::processAppInstall(MessageBuffer &buffer, MessageBuffer &s
     }
 
     // register paths
-    for (const auto& appPath : req.appPaths) {
-        result = setupPath(req.pkgId, appPath);
+    for (const auto &appPath : req.appPaths) {
+        const std::string &path = appPath.first;
+        app_install_path_type pathType = static_cast<app_install_path_type>(appPath.second);
+        result = setupPath(req.pkgId, path, pathType);
+
         if (!result) {
             LogDebug("setupPath() failed ");
             goto error_label;
@@ -512,7 +295,7 @@ bool InstallerService::processAppUninstall(MessageBuffer &buffer, MessageBuffer
         } else {
             LogDebug("pkgId: " << pkgId);
 
-            if (!SmackRules::generateAppLabel(pkgId, smackLabel)) {
+            if (!generateAppLabel(pkgId, smackLabel)) {
                 LogError("Cannot generate Smack label for package");
                 goto error_label;
             }
diff --git a/src/server/service/smack-labels.cpp b/src/server/service/smack-labels.cpp
new file mode 100644 (file)
index 0000000..3b88c73
--- /dev/null
@@ -0,0 +1,249 @@
+/*
+ *  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-labels.cpp
+ * @author      Jan Cybulski <j.cybulski@samsung.com>
+ * @author      Rafal Krypa <r.krypa@samsung.com>
+ * @version     1.0
+ * @brief       Implementation of functions managing smack labels
+ *
+ */
+
+#include <sys/stat.h>
+#include <sys/smack.h>
+#include <sys/xattr.h>
+#include <linux/xattr.h>
+#include <memory>
+#include <fts.h>
+#include <cstring>
+#include <string>
+
+#include <dpl/log/log.h>
+
+#include "security-manager.h"
+#include "smack-labels.h"
+
+namespace SecurityManager {
+
+/* Const defined below is used to label links to executables */
+const char *const XATTR_NAME_TIZENEXEC = XATTR_SECURITY_PREFIX "TIZEN_EXEC_LABEL";
+
+/* Const defined below is used to label links to executables */
+const char *const LABEL_FOR_PUBLIC_APP_PATH = "User";
+
+enum class FileDecision {
+    SKIP = 0,
+    LABEL = 1,
+    ERROR = -1
+};
+
+typedef std::function<FileDecision(const FTSENT*)> LabelDecisionFn;
+
+
+bool generateAppLabel(const std::string &appPkgId, std::string &label)
+{
+    (void) appPkgId; // TODO use pkgId to generate label
+    label = "User";
+    return true;
+}
+
+static FileDecision labelAll(const FTSENT *ftsent __attribute__((unused)))
+{
+    LogDebug("Entering function: " << __func__);
+
+    return FileDecision::LABEL;
+}
+
+static FileDecision labelDirs(const FTSENT *ftsent)
+{
+    LogDebug("Entering function: " << __func__);
+
+    // label only directories
+    if (S_ISDIR(ftsent->fts_statp->st_mode))
+        return FileDecision::LABEL;
+    return FileDecision::SKIP;
+}
+
+static FileDecision labelExecs(const FTSENT *ftsent)
+{
+    LogDebug("Entering function: " << __func__);
+
+    LogDebug("Mode = " << ftsent->fts_statp->st_mode);
+    // label only regular executable files
+    if (S_ISREG(ftsent->fts_statp->st_mode) && (ftsent->fts_statp->st_mode & S_IXUSR))
+        return FileDecision::LABEL;
+    return FileDecision::SKIP;
+}
+
+static FileDecision labelLinksToExecs(const FTSENT *ftsent)
+{
+    LogDebug("Entering function: " << __func__);
+
+    struct stat buf;
+
+    // check if it's a link
+    if ( !S_ISLNK(ftsent->fts_statp->st_mode))
+        return FileDecision::SKIP;
+
+    std::unique_ptr<char, std::function<void(void*)>> target(realpath(ftsent->fts_path, NULL), free);
+
+    if (!target.get()) {
+        LogError("Getting link target for " << ftsent->fts_path << " failed (Error = " << strerror(errno) << ")");
+        return FileDecision::ERROR;
+    }
+
+    if (-1 == stat(target.get(), &buf)) {
+        LogError("stat failed for " << target.get() << " (Error = " << strerror(errno) << ")");
+        return FileDecision::ERROR;
+    }
+    // skip if link target is not a regular executable file
+    if (buf.st_mode != (buf.st_mode | S_IXUSR | S_IFREG)) {
+        LogDebug(target.get() << "is not a regular executable file. Skipping.");
+        return FileDecision::SKIP;
+    }
+
+    return FileDecision::LABEL;
+}
+
+static bool dirSetSmack(const std::string &path, const std::string &label,
+        const char *xattr_name, LabelDecisionFn fn)
+{
+    LogDebug("Entering function: "<< __func__ <<". Params:"
+            " path=" << path << ", label=" << label << ", xattr=" << xattr_name);
+
+
+    char *const path_argv[] = {const_cast<char *>(path.c_str()), NULL};
+    FTSENT *ftsent;
+    FileDecision ret;
+
+    std::unique_ptr<FTS, std::function<void(FTS*)> > fts(
+            fts_open(path_argv, FTS_PHYSICAL | FTS_NOCHDIR, NULL),
+            fts_close);
+
+    if (fts.get() == NULL) {
+        LogError("fts_open failed.");
+        return false;
+    }
+
+    while ((ftsent = fts_read(fts.get())) != NULL) {
+        /* Check for error (FTS_ERR) or failed stat(2) (FTS_NS) */
+        if (ftsent->fts_info == FTS_ERR || ftsent->fts_info == FTS_NS) {
+            LogError("FTS_ERR error or failed stat(2) (FTS_NS)");
+            return false;
+        }
+
+        ret = fn(ftsent);
+        if (ret == FileDecision::ERROR) {
+            LogError("fn(ftsent) failed.");
+            return false;
+        }
+
+        if (ret == FileDecision::LABEL) {
+            if (lsetxattr(ftsent->fts_path, xattr_name, label.c_str(), label.length(), 0) != 0) {
+                LogError("lsetxattr failed.");
+                return false;
+            }
+        }
+
+    }
+
+    /* If last call to fts_read() set errno, we need to return error. */
+    if ((errno != 0) && (ftsent == NULL)) {
+        LogError("Last errno from fts_read: " << strerror(errno));
+        return false;
+    }
+    return true;
+}
+
+
+static bool labelDir(const std::string &path, const std::string &label,
+        bool set_transmutable, bool set_executables)
+{
+    LogDebug("Entering function: "<< __func__ <<". Params:"
+            " path=" << path << " label= " << label
+            << " set_transmutable= " << set_transmutable
+            << " set_executables= " << set_executables);
+    bool ret = true;
+
+    // setting access label on everything in given directory and below
+    ret = dirSetSmack(path, label, XATTR_NAME_SMACK, labelAll);
+    if (!ret) {
+        LogError("dirSetSmack failed (access label)");
+        return ret;
+    }
+
+    if (set_transmutable) {
+        // setting transmute on dirs
+        ret = dirSetSmack(path, "TRUE", XATTR_NAME_SMACKTRANSMUTE, labelDirs);
+        if (!ret) {
+            LogError("dirSetSmack failed (transmute)");
+            return ret;
+        }
+    }
+
+    if (set_executables) {
+        ret = dirSetSmack(path, label, XATTR_NAME_SMACKEXEC, &labelExecs);
+        if (!ret)
+        {
+            LogError("dirSetSmack failed (execs).");
+            return ret;
+        }
+
+        //setting execute label for everything with permission to execute
+        ret = dirSetSmack(path, label, XATTR_NAME_TIZENEXEC, &labelLinksToExecs);
+        if (!ret)
+        {
+            LogError("dirSetSmack failed (link to execs).");
+            return ret;
+        }
+    }
+
+    return ret;
+}
+
+bool setupPath(const std::string &pkgId, const std::string &path,
+    app_install_path_type pathType)
+{
+    std::string label;
+    bool label_executables, label_transmute;
+
+    switch (pathType) {
+    case SECURITY_MANAGER_PATH_PRIVATE:
+        if (!generateAppLabel(pkgId, label))
+            return false;
+        label_executables = true;
+        label_transmute = false;
+        break;
+    case SECURITY_MANAGER_PATH_PUBLIC:
+        label.assign(LABEL_FOR_PUBLIC_APP_PATH);
+        label_executables = false;
+        label_transmute = true;
+        break;
+    case SECURITY_MANAGER_PATH_PUBLIC_RO:
+        label.assign("_");
+        label_executables = false;
+        label_transmute = false;
+        break;
+    default:
+        LogError("Path type not known.");
+        return false;
+    }
+    return labelDir(path, label, label_transmute, label_executables);
+}
+
+} // namespace SecurityManager
index 32b83c9..f8d4f09 100644 (file)
@@ -35,6 +35,7 @@
 #include <dpl/log/log.h>
 #include <tzplatform_config.h>
 
+#include "smack-labels.h"
 #include "smack-rules.h"
 
 namespace SecurityManager {
@@ -42,13 +43,6 @@ namespace SecurityManager {
 const char *const SMACK_APP_LABEL_TEMPLATE     = "~APP~";
 const char *const APP_RULES_TEMPLATE_FILE_PATH = tzplatform_mkpath(TZ_SYS_SMACK, "app-rules-template.smack");
 
-bool SmackRules::generateAppLabel(const std::string &appPkgId, std::string &label)
-{
-    (void) appPkgId; //todo use pkgId to generate label
-    label = "User";
-    return true;
-}
-
 SmackRules::SmackRules()
 {
     if (smack_accesses_new(&m_handle) < 0) {