--- /dev/null
+/*
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd. All rights reserved
+ *
+ * This file is licensed under the terms of MIT License or the Apache License
+ * Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
+ * See the LICENSE file or the notice below for Apache License Version 2.0
+ * details.
+ *
+ * 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.
+ */
+
+#include "acl.h"
+
+namespace SecurityManager {
+
+Acl Acl::Make(acl_perm_t ownerPerms,
+ acl_perm_t groupPerms,
+ acl_perm_t otherPerms,
+ std::vector<EntryPtr> _entries)
+{
+ auto entries = std::move(_entries);
+
+ // Acl requires exactly one ACL_USER_OBJ, ACL_GROUP_OBJ and ACL_OTHER entry
+ entries.reserve(entries.size() + 3);
+ entries.emplace_back(new Acl::Entry(ownerPerms, ACL_USER_OBJ));
+ entries.emplace_back(new Acl::Entry(groupPerms, ACL_GROUP_OBJ));
+ entries.emplace_back(new Acl::Entry(otherPerms, ACL_OTHER));
+
+ return Acl(entries);
+}
+
+Acl::Acl(const std::vector<EntryPtr> &entries)
+{
+ auto freeAcl = [](acl_t *toFree) {acl_free(*toFree);};
+ m_acl = acl_init(entries.size());
+ if (m_acl == nullptr) {
+ LogErrno("acl_init");
+ Throw(Exception::Base);
+ }
+ std::unique_ptr<acl_t, decltype(freeAcl)> deleter(&m_acl, freeAcl);
+
+ acl_entry_t entry;
+ for (const auto &e : entries) {
+ if (0 != acl_create_entry(&m_acl, &entry)) {
+ LogErrno("acl_create_entry");
+ Throw(Exception::Base);
+ }
+
+ acl_permset_t permset = nullptr;
+ if (0 != acl_get_permset(entry, &permset)) {
+ LogErrno("acl_get_permset");
+ Throw(Exception::Base);
+ }
+
+ if (0 != acl_clear_perms(permset)) {
+ LogErrno("acl_clear_perms");
+ Throw(Exception::Base);
+ }
+
+ for (auto &p : { ACL_READ, ACL_WRITE, ACL_EXECUTE }) {
+ if (e->permissions & p) {
+ if (0 != acl_add_perm(permset, p)) {
+ LogErrno("acl_add_perm");
+ Throw(Exception::Base);
+ }
+ }
+ }
+ if (0 != acl_set_permset(entry, permset)) {
+ LogErrno("acl_set_permset");
+ Throw(Exception::Base);
+ }
+
+ if (0 != acl_set_tag_type(entry, e->tag)) {
+ LogErrno("acl_set_tag_type");
+ Throw(Exception::Base);
+ }
+
+ e->setQualifier(entry);
+ }
+
+ // Acl requires one ACL_MASK entry if there are ACL_USER or ACL_GROUP entries present.
+ if (0 != acl_calc_mask(&m_acl)) {
+ LogErrno("acl_calc_mask");
+ Throw(Exception::Base);
+ }
+ deleter.release();
+}
+
+void Acl::apply(const std::string &path, acl_type_t type) const
+{
+ if (m_acl == nullptr) {
+ LogError("ACL object is not initialized");
+ Throw(Exception::Base);
+ }
+
+ int last;
+ int ret = acl_check(m_acl, &last);
+ if (ret != 0) {
+ if (ret > 0)
+ LogError("Check failed for entry " << last << ": " << acl_error(ret));
+ else
+ LogErrno("acl_check");
+ Throw(Exception::Base);
+ }
+
+ if (0 != acl_set_file(path.c_str(), type, m_acl)) {
+ LogErrno("acl_set_file");
+ Throw(Exception::Base);
+ }
+}
+
+Acl::Acl(Acl&& other)
+{
+ m_acl = other.m_acl;
+ other.m_acl = nullptr;
+}
+
+Acl& Acl::operator=(Acl&& other)
+{
+ if (&other != this)
+ {
+ m_acl = other.m_acl;
+ other.m_acl = nullptr;
+ }
+ return *this;
+}
+
+Acl::~Acl()
+{
+ acl_free(m_acl);
+}
+
+} // namespace SecurityManager
--- /dev/null
+/*
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd. All rights reserved
+ *
+ * This file is licensed under the terms of MIT License or the Apache License
+ * Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
+ * See the LICENSE file or the notice below for Apache License Version 2.0
+ * details.
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <acl/libacl.h>
+#include <vector>
+#include <memory>
+
+#include "dpl/exception.h"
+#include "dpl/log/log.h"
+#include "dpl/errno_string.h"
+
+namespace SecurityManager {
+
+class Acl
+{
+private:
+ struct Entry
+ {
+ virtual void setQualifier(acl_entry_t&) const
+ {
+ }
+
+ Entry(acl_perm_t _permissions, acl_tag_t _tag) :
+ permissions(_permissions), tag(_tag)
+ {
+ }
+
+ acl_perm_t permissions;
+ acl_tag_t tag;
+ };
+
+public:
+ static constexpr inline acl_perm_t R = ACL_READ;
+ static constexpr inline acl_perm_t W = ACL_WRITE;
+ static constexpr inline acl_perm_t X = ACL_EXECUTE;
+ static constexpr inline acl_perm_t RW = ACL_READ | ACL_WRITE;
+ static constexpr inline acl_perm_t RX = ACL_READ | ACL_EXECUTE;
+ static constexpr inline acl_perm_t RWX = ACL_READ | ACL_WRITE | ACL_EXECUTE;
+
+ using EntryPtr = std::unique_ptr<Entry>;
+
+ template<typename Id, acl_tag_t Tag>
+ class IdEntry: public Entry
+ {
+ public:
+ IdEntry(acl_perm_t permissions, Id id) :
+ Entry(permissions, Tag), m_qualifier(id)
+ {
+ }
+
+ private:
+ void setQualifier(acl_entry_t &entry) const override
+ {
+ if (0 != acl_set_qualifier(entry, &m_qualifier)) {
+ LogErrno("acl_set_qualifier");
+ Throw(Exception::Base);
+ }
+ }
+
+ Id m_qualifier;
+ };
+
+ using UidEntry = IdEntry<uid_t, ACL_USER>;
+ using GidEntry = IdEntry<gid_t, ACL_GROUP>;
+
+ class Exception
+ {
+ public:
+ DECLARE_EXCEPTION_TYPE(SecurityManager::Exception, Base)
+ };
+
+ Acl(Acl&& other);
+ Acl& operator=(Acl&& other);
+
+ Acl() : Acl(std::vector<EntryPtr>())
+ {
+ }
+ ~Acl();
+
+ static Acl Make(acl_perm_t ownerPerms,
+ acl_perm_t groupPerms,
+ acl_perm_t otherPerms,
+ std::vector<EntryPtr> entries = {});
+
+ void apply(const std::string &path, acl_type_t type) const;
+
+private:
+ explicit Acl(const std::vector<EntryPtr> &entries);
+
+ mutable acl_t m_acl = nullptr;
+};
+
+} // namespace SecurityManager