Support method privilege check for C++ Generator 61/297261/7
authorHwankyu Jhun <h.jhun@samsung.com>
Wed, 16 Aug 2023 05:12:18 +0000 (14:12 +0900)
committerHwanKyu Jhun <h.jhun@samsung.com>
Fri, 25 Aug 2023 07:06:11 +0000 (07:06 +0000)
This patch supports the method privilege check feature. The developer
can set the privilege for each methods.

Change-Id: I9991b3554712878580700127b17ea969617c3e65
Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
idlc/gen/version2/cpp_generator_base_cb.hh
idlc/gen/version2/cpp_stub_body_generator.cc
idlc/gen/version2/cpp_stub_body_generator.hh
idlc/gen/version2/cpp_stub_body_generator_cb.hh
idlc/gen/version2/cpp_stub_header_generator_cb.hh

index b33a373c27193fbfa99095212cb26258618421ac..88875de7a2cb165dc25524266f5b8c51008441bc 100644 (file)
@@ -68,6 +68,7 @@ R"__cpp_cb(
 #include <string>
 #include <vector>
 #include <unordered_map>
+#include <unordered_set>
 )__cpp_cb";
 
 /**
index 927ecde36855d5654cf1c2748da9ba6e1e021437..78de08d2b9af352b895623c360ad8d982d2f27c1 100644 (file)
@@ -94,7 +94,9 @@ std::string CppStubBodyGenerator::GenInterface(const Interface& iface) {
           .Change("<IMPL_SERVICE_BASE_DISPATCH>",
               GenInterfaceImplServiceBaseDispatch())
           .Change("<IMPL_SERVICE_BASE_DISPATCH_FUNCS>",
-              GenInterfaceImplServiceBaseDispatchFuncs(iface)));
+              GenInterfaceImplServiceBaseDispatchFuncs(iface))
+          .Change("<IMPL_SERVICE_BASE_SET_PRIVILEGE_MAP>",
+              GenInterfaceImplServiceBaseSetPrivilegeMap(iface)));
 }
 
 std::string CppStubBodyGenerator::GenInterfaceCallbacks(
@@ -265,5 +267,28 @@ std::string CppStubBodyGenerator::GenInterfaceServiceBaseSerialize(
   return RemoveLine(code);
 }
 
+std::string CppStubBodyGenerator::GenInterfaceImplServiceBaseSetPrivilegeMap(
+    const Interface& iface) {
+  std::string code;
+  for (auto& decl : iface.GetDeclarations()) {
+    std::string privileges;
+    for (auto& attr : decl->GetAttributes()) {
+      if (attr->GetKey() != "privilege")
+        continue;
+
+      privileges += "\"" + attr->GetValue() + "\"," + NLine(1);
+    }
+
+    if (privileges.empty())
+      continue;
+
+    code += ReplaceAll(CB_INTERFACE_SERVICE_BASE_SET_PRIVILEGE_MAP)
+        .Change("<PRIVILEGES>", privileges)
+        .Change("<METHOD>", decl->GetID());
+  }
+
+  return RemoveLine(code);
+}
+
 }  // namespace version2
 }  // namespace tidl
index 1727d389d3118f68266c686690db4e415b31e9ef..ba3a54ec821f72aee608937150c80103bf78465a 100644 (file)
@@ -29,7 +29,7 @@ namespace version2 {
 class CppStubBodyGenerator : public CppGeneratorBase {
  public:
   explicit CppStubBodyGenerator(std::shared_ptr<Document> doc,
-      std::shared_ptr<Options> options);
+                                std::shared_ptr<Options> options);
   virtual ~CppStubBodyGenerator() = default;
 
   void OnInitGen(std::ofstream& stream) override;
@@ -49,9 +49,11 @@ class CppStubBodyGenerator : public CppGeneratorBase {
   std::string GenInterfaceImplServiceBaseDispatch();
   std::string GenInterfaceImplServiceBaseDispatchFuncs(const Interface& iface);
   std::string GenInterfaceImplServiceBaseDispatchFunc(const Interface& iface,
-      const Declaration& decl);
+                                                      const Declaration& decl);
   std::string GenInterfaceServiceBaseDeserialize(const Declaration& decl);
   std::string GenInterfaceServiceBaseSerialize(const Declaration& decl);
+  std::string GenInterfaceImplServiceBaseSetPrivilegeMap(
+      const Interface& iface);
 
  private:
   std::shared_ptr<Options> options_;
index e44426ecb0a9774590b0c65795620906aebf0487..b0c375b81d4fc5edf20634fd5c11212e61aadbd4 100644 (file)
@@ -27,9 +27,11 @@ constexpr const char CB_STUB_BODY_HEADER[] =
 R"__cpp_cb(
 #include "<FILENAME>"
 
-#include <stdlib.h>
+#include <app_manager.h>
 #include <assert.h>
 #include <dlog.h>
+#include <package_manager.h>
+#include <stdlib.h>
 )__cpp_cb";
 
 /**
@@ -137,12 +139,15 @@ void <IFACE_NAME>::PendingJob::OnRun() {
  * <IMPL_SERVICE_BASE_THREAD_MEMBER_INIT> The implementation of the initialization of thread member variable of the service base.
  * <IMPL_SERVICE_BASE_DISPATCH> The implementation of the dispatch method of the service base.
  * <IMPL_SERVICE_BASE_DISPATCH_FUNCS> The implementation of the dispatch functions of the service base.
+ * <IMPL_SERVICE_BASE_SET_PRIVILEGE_MAP> The implementation of setting privilege map of the service base.
  */
 constexpr const char CB_INTERFACE_BASE[] =
 R"__cpp_cb(
 <CALLBACKS>
 
 <CLS_NAME>::ServiceBase::ServiceBase(std::string sender, std::string instance) : sender_(std::move(sender)), instance_(std::move(instance)) {
+  LoadPrivileges();
+  SetPrivilegeMap();
   <IMPL_SERVICE_BASE_THREAD_MEMBER_INIT>
   dispatch_funcs_ = {
     <IMPL_SERVICE_BASE_DISPATCH_FUNC_INIT>
@@ -191,6 +196,62 @@ void <CLS_NAME>::ServiceBase::Dispatch(rpc_port_h port, rpc_port_h callback_port
   func(port, callback_port, seq_num, unit_map_);
 }
 
+bool <CLS_NAME>::ServiceBase::PrivilegeInfoCb(const char* privilege_name, void *user_data) {
+  auto* service_base = static_cast<<CLS_NAME>::ServiceBase*>(user_data);
+  _D("appid: %s, privilege: %s", service_base->GetSender().c_str(), privilege_name);
+  service_base->privileges_.insert(privilege_name);
+  return true;
+}
+
+void <CLS_NAME>::ServiceBase::LoadPrivileges() {
+  app_info_h app_info = nullptr;
+  int ret = app_info_create(GetSender().c_str(), &app_info);
+  if (ret != APP_MANAGER_ERROR_NONE) {
+    if (ret == APP_MANAGER_ERROR_NO_SUCH_APP)
+      _W("%s is not an application", GetSender().c_str());
+
+    return;
+  }
+
+  char* package = nullptr;
+  ret = app_info_get_package(app_info, &package);
+  app_info_destroy(app_info);
+  if (ret != APP_MANAGER_ERROR_NONE) {
+    _E("Failed to get package. error(%d)", ret);
+    return;
+  }
+
+  package_info_h package_info = nullptr;
+  ret = package_info_create(package, &package_info);
+  free(package);
+  if (ret != PACKAGE_MANAGER_ERROR_NONE) {
+    _E("Failed to create package info. error(%d)", ret);
+    return;
+  }
+
+  package_info_foreach_privilege_info(package_info, PrivilegeInfoCb, this);
+  package_info_destroy(package_info);
+}
+
+void <CLS_NAME>::ServiceBase::SetPrivilegeMap() {
+  <IMPL_SERVICE_BASE_SET_PRIVILEGE_MAP>
+}
+
+bool <CLS_NAME>::ServiceBase::CheckPrivileges(int method_id) {
+  auto found = privilege_map_.find(method_id);
+  if (found == privilege_map_.end())
+    return true;
+
+  for (const auto& privilege : found->second) {
+    if (privileges_.find(privilege) == privileges_.end()) {
+      _E("%s does not exist", privilege.c_str());
+      return false;
+    }
+  }
+
+  return true;
+}
+
 <IMPL_SERVICE_BASE_DISPATCH_FUNCS>
 
 <CLS_NAME>::<CLS_NAME>() {
@@ -323,6 +384,11 @@ active_object_->Send(std::make_shared<Job>(port, callback_port, parcel, std::mov
 constexpr const char CB_INTERFACE_SERVICE_BASE_DISPATCH_FUNC_ASYNC[] =
 R"__cpp_cb(
 void <IFACE_NAME>::ServiceBase::Dispatch<NAME>(rpc_port_h port, rpc_port_h callback_port, int seq_num, const UnitMap& unit_map) {
+  if (!CheckPrivileges(static_cast<int>(MethodId::<NAME>))) {
+    _E("Permission denied");
+    return;
+  }
+
   <DESERIALIZE>
   <NAME>(<PARAMS>);
 }
@@ -338,15 +404,21 @@ void <IFACE_NAME>::ServiceBase::Dispatch<NAME>(rpc_port_h port, rpc_port_h callb
 constexpr const char CB_INTERFACE_SERVICE_BASE_DISPATCH_FUNC[] =
 R"__cpp_cb(
 void <IFACE_NAME>::ServiceBase::Dispatch<NAME>(rpc_port_h port, rpc_port_h callback_port, int seq_num, const UnitMap& unit_map) {
-  <DESERIALIZE>
   UnitMap map_;
-  try {
-    auto ret_ = <NAME>(<PARAMS>);
-    map_.Write("[RESULT]", ret_);
-    <SERIALIZE>
-  } catch (const RemoteException& e) {
-    _E("Exception occurs. cause(%d), message(%s)", e.GetCause(), e.GetMessage().c_str());
-    map_.Write("[REMOTE_EXCEPTION]", e);
+  if (!CheckPrivileges(static_cast<int>(MethodId::<NAME>))) {
+    _E("Permission denied");
+    RemoteException remote_except(RPC_PORT_ERROR_PERMISSION_DENIED, "Permission denied");
+    map_.Write("[REMOTE_EXCEPTION]", remote_except);
+  } else {
+    <DESERIALIZE>
+    try {
+      auto ret_ = <NAME>(<PARAMS>);
+      map_.Write("[RESULT]", ret_);
+      <SERIALIZE>
+    } catch (const RemoteException& e) {
+      _E("Exception occurs. cause(%d), message(%s)", e.GetCause(), e.GetMessage().c_str());
+      map_.Write("[REMOTE_EXCEPTION]", e);
+    }
   }
 
   map_.Write("[METHOD]", static_cast<int>(MethodId::__Result));
@@ -399,6 +471,20 @@ R"__cpp_cb(
 unit_map.Read("<NAME>", <NAME>);
 )__cpp_cb";
 
+/**
+ * <PRIVILEGES> The privileges of the method.
+ * <METHOD> The method name.
+ */
+constexpr const char CB_INTERFACE_SERVICE_BASE_SET_PRIVILEGE_MAP[] =
+R"__cpp_cb(
+{
+  std::vector<std::string> privileges = {
+    <PRIVILEGES>
+  };
+  privilege_map_[static_cast<int>(MethodId::<METHOD>)] = std::move(privileges);
+}
+)__cpp_cb";
+
 }  // namespace version2
 }  // namespace tidl
 
index 127510dc88b6d289e2d5db061fa4e0b922936f3b..ee4b63b8bcf3ba1f666eb4fa06d8b72068aa49bd 100644 (file)
@@ -176,10 +176,8 @@ class CallbackBase {
 
   int GetId() const;
   void SetId(int id);
-
   int GetSeqId() const;
   void SetSeqId(int seq_id);
-
   bool IsOnce() const;
   void SetOnce(bool once);
 
@@ -311,6 +309,10 @@ class <CLS_NAME> {
    private:
     using DispatchFunc = std::function<void(rpc_port_h, rpc_port_h, int, const UnitMap&)>;
 
+    static bool PrivilegeInfoCb(const char* privilege_name, void* user_data);
+    void LoadPrivileges();
+    void SetPrivilegeMap();
+    bool CheckPrivileges(int method_id);
     <SERVICE_BASE_DISPATCH_FUNCS>
 
     <SERVICE_BASE_IMPL_THREAD_MEMBER>
@@ -320,6 +322,8 @@ class <CLS_NAME> {
     std::string instance_;
     rpc_port_h port_ = nullptr;
     std::unordered_map<int, DispatchFunc> dispatch_funcs_;
+    std::unordered_map<int, std::vector<std::string>> privilege_map_;
+    std::unordered_set<std::string> privileges_;
   };
 
   <CLS_NAME>();