]> git.ipfire.org Git - thirdparty/snapper.git/commitdiff
selinux: introduce helper classes
authorOndrej Kozina <okozina@redhat.com>
Mon, 11 Apr 2016 15:10:28 +0000 (17:10 +0200)
committerOndrej Kozina <okozina@redhat.com>
Mon, 11 Apr 2016 15:10:28 +0000 (17:10 +0200)
snapper/Selinux.cc [new file with mode: 0644]
snapper/Selinux.h [new file with mode: 0644]

diff --git a/snapper/Selinux.cc b/snapper/Selinux.cc
new file mode 100644 (file)
index 0000000..ed059b8
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) [2016] Red Hat, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, contact Novell, Inc.
+ *
+ * To contact Novell about this file by physical or electronic mail, you may
+ * find current contact information at www.novell.com.
+ */
+
+#include <cerrno>
+#include <map>
+
+#include <boost/algorithm/string.hpp>
+
+#include "snapper/AppUtil.h"
+#include "snapper/AsciiFile.h"
+#include "snapper/Log.h"
+#include "snapper/Selinux.h"
+
+namespace snapper
+{
+
+    SnapperContexts::SnapperContexts()
+       : subvolume_ctx(NULL)
+    {
+       std::map<string,string> snapperd_contexts;
+
+       try
+       {
+           AsciiFileReader asciifile(selinux_snapperd_contexts_path());
+
+           string line;
+           while (asciifile.getline(line))
+           {
+               // commented line
+               if (line[0] == '#')
+                   continue;
+
+               // do not parse lines w/o '=' symbol
+               string::size_type pos = line.find('=');
+               if (pos == string::npos)
+                   continue;
+
+               if (!snapperd_contexts.insert(make_pair(boost::trim_copy(line.substr(0, pos)), boost::trim_copy(line.substr(pos + 1)))).second)
+               {
+                   SN_THROW(SelinuxException("Duplicate key in contexts file"));
+               }
+           }
+       }
+       catch (const FileNotFoundException& e)
+       {
+           SN_CAUGHT(e);
+           SN_THROW(SelinuxException("Failed to parse contexts file"));
+       }
+
+       std::map<string,string>::const_iterator cit = snapperd_contexts.find(selinux_snapperd_data);
+       if (cit == snapperd_contexts.end())
+       {
+           SN_THROW(SelinuxException("Snapperd data context not found"));
+       }
+
+       subvolume_ctx = context_new(cit->second.c_str());
+       if (!subvolume_ctx)
+       {
+           SN_THROW(SelinuxException());
+       }
+    }
+
+
+    DefaultSelinuxFileContext::DefaultSelinuxFileContext(char* context)
+    {
+       if (setfscreatecon(context) < 0)
+       {
+           SN_THROW(SelinuxException(string("setfscreatecon(") + context + ") failed"));
+       }
+    }
+
+
+    DefaultSelinuxFileContext::~DefaultSelinuxFileContext()
+    {
+       if (setfscreatecon(NULL))
+           y2err("Failed to reset default file system objects context");
+    }
+
+
+    SelinuxLabelHandle::SelinuxLabelHandle()
+       : handle(selabel_open(SELABEL_CTX_FILE, NULL, 0))
+    {
+       if (!handle)
+       {
+           SN_THROW(SelinuxException("Failed to open SELinux labeling handle: " + stringerror(errno)));
+       }
+    }
+
+
+    char*
+    SelinuxLabelHandle::selabel_lookup(const string& path, int mode)
+    {
+       char *con;
+
+       if (!::selabel_lookup(handle, &con, path.c_str(), mode))
+       {
+           y2deb("found label for path " << path << ": " << con);
+           return con;
+       }
+       else
+       {
+           if (errno == ENOENT)
+               y2deb("Selinux context not defined for path " << path);
+
+           return NULL;
+       }
+    }
+
+
+    int
+    _is_selinux_enabled()
+    {
+       static int selinux_checked = 0, selinux_enabled = 0;
+
+       if (!selinux_checked)
+       {
+           selinux_enabled = is_selinux_enabled();
+           selinux_checked = 1;
+           y2mil("Selinux support " << (selinux_enabled ? "en" : "dis") << "abled");
+       }
+
+       return selinux_enabled;
+    }
+
+
+    SelinuxLabelHandle*
+    SelinuxLabelHandle::get_selinux_handle()
+    {
+       if (_is_selinux_enabled())
+       {
+           static SelinuxLabelHandle handle;
+           return &handle;
+       }
+
+       return NULL;
+    }
+
+}
diff --git a/snapper/Selinux.h b/snapper/Selinux.h
new file mode 100644 (file)
index 0000000..8698cd5
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) [2016] Red Hat, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, contact Novell, Inc.
+ *
+ * To contact Novell about this file by physical or electronic mail, you may
+ * find current contact information at www.novell.com.
+ */
+
+
+#ifndef SNAPPER_SELINUX_H
+#define SNAPPER_SELINUX_H
+
+#include <string>
+#include <selinux/context.h>
+#include <selinux/label.h>
+#include <selinux/selinux.h>
+
+#include <boost/noncopyable.hpp>
+
+#include "snapper/Exception.h"
+
+
+namespace snapper {
+
+    struct SelinuxException : public Exception
+    {
+       explicit SelinuxException() : Exception("SELinux error") {}
+       explicit SelinuxException(const std::string& msg) : Exception(msg) {}
+    };
+
+    using std::string;
+
+    const static string selinux_snapperd_data = "snapperd_data";
+
+    int _is_selinux_enabled();
+
+    class SnapperContexts
+    {
+    public:
+       char* subvolume_context() const { return context_str(subvolume_ctx); }
+       SnapperContexts();
+       ~SnapperContexts() { context_free(subvolume_ctx); }
+    private:
+       context_t subvolume_ctx;
+    };
+
+    class DefaultSelinuxFileContext : private boost::noncopyable
+    {
+    public:
+       DefaultSelinuxFileContext(char* context);
+       ~DefaultSelinuxFileContext();
+    };
+
+
+    class SelinuxLabelHandle : public boost::noncopyable
+    {
+    public:
+       static SelinuxLabelHandle* get_selinux_handle();
+
+       char* selabel_lookup(const string& path, int mode);
+
+       ~SelinuxLabelHandle() { selabel_close(handle); }
+    private:
+       SelinuxLabelHandle();
+
+       struct selabel_handle* handle;
+    };
+
+}
+
+#endif