Seperate cynara module with runner
authorChanggyu Choi <changyu.choi@samsung.com>
Wed, 28 Apr 2021 01:21:48 +0000 (10:21 +0900)
committer최창규/Tizen Platform Lab(SR)/Engineer/삼성전자 <changyu.choi@samsung.com>
Fri, 30 Apr 2021 04:17:23 +0000 (13:17 +0900)
Change-Id: I94eb7601d86e4bc14403fb898f724a6002e5e7e6
Signed-off-by: Changgyu Choi <changyu.choi@samsung.com>
CMakeLists.txt
packaging/pkgmgr-info.spec
src/common/socket/abstract_socket.cc
src/common/socket/abstract_socket.hh
src/server/CMakeLists.txt
src/server/cynara_checker/cynara_checker.cc [new file with mode: 0644]
src/server/cynara_checker/cynara_checker.hh [new file with mode: 0644]
src/server/runner.cc

index fe98ba5b6679e4ae6c7c5a1601f52a8b5535932d..f24f8adcd35701b3746f992e47d5ec60c62a5e98 100644 (file)
@@ -18,6 +18,7 @@ INCLUDE_DIRECTORIES(
   ${CMAKE_SOURCE_DIR}/src/common/socket
   ${CMAKE_SOURCE_DIR}/src/common/parcel
   ${CMAKE_SOURCE_DIR}/src/server
+  ${CMAKE_SOURCE_DIR}/src/server/cynara_checker
   ${CMAKE_SOURCE_DIR}/src/server/database
   ${CMAKE_SOURCE_DIR}/src/server/request_handler
 )
@@ -25,41 +26,43 @@ INCLUDE_DIRECTORIES(
 ### Required packages
 INCLUDE(FindPkgConfig)
 pkg_check_modules(pkgs REQUIRED
-       glib-2.0
-       gio-2.0
-       gio-unix-2.0
-       dlog
-       vconf
-       sqlite3
-       libxml-2.0
-       libtzplatform-config
-       libsmack
-       bundle
-       cynara-client
-       cynara-session
-       cynara-creds-socket
+  glib-2.0
+  gio-2.0
+  gio-unix-2.0
+  dlog
+  vconf
+  libtzplatform-config
+  libsmack
+  bundle
+  capi-system-info
+  minizip
+  libsystemd
+  parcel
+  cynara-client-async
+  cynara-session
+  cynara-creds-socket
 )
 FOREACH(flag ${pkgs_CFLAGS})
        SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
 ENDFOREACH(flag)
 
 pkg_check_modules(libpkgs REQUIRED
-       glib-2.0
-       gio-2.0
-       gio-unix-2.0
-       dlog
-       vconf
-       sqlite3
-       libtzplatform-config
-       libsmack
-       bundle
-       capi-system-info
-       minizip
-       libsystemd
-       parcel
-       cynara-client-async
-       cynara-session
-       cynara-creds-socket
+  glib-2.0
+  gio-2.0
+  gio-unix-2.0
+  dlog
+  vconf
+  sqlite3
+  libtzplatform-config
+  libsmack
+  bundle
+  capi-system-info
+  minizip
+  libsystemd
+  parcel
+  cynara-client-async
+  cynara-session
+  cynara-creds-socket
 )
 
 FOREACH(flag ${libpkgs_CFLAGS})
index 5ea4ccba2c3ba8eaeab316f343738b38db015fa2..a66ffb4531995307c995b02a49ef70792392ad04 100755 (executable)
@@ -26,6 +26,7 @@ BuildRequires: pkgconfig(gmock)
 BuildRequires: pkgconfig(parcel)
 BuildRequires: pkgconfig(cynara-client-async)
 BuildRequires: pkgconfig(cynara-session)
+BuildRequires: pkgconfig(cynara-creds-socket)
 
 %if 0%{?gcov:1}
 BuildRequires:  lcov
index 506bbe1459a566a0b8bc9bba2be93b7456eb9924..594df3a201237d821991346dc30232f5b9837f48 100644 (file)
@@ -28,9 +28,9 @@ namespace pkgmgr_common {
 namespace socket {
 
 AbstractSocket::AbstractSocket(std::string path)
-    : path_(std::move(path)), fd_(-1), pid_(-1), uid_(-1), addr_{} {}
+    : path_(std::move(path)), fd_(-1), addr_{} {}
 
-AbstractSocket::AbstractSocket(int fd) : fd_(fd), pid_(-1), uid_(-1), addr_{} {}
+AbstractSocket::AbstractSocket(int fd) : fd_(fd), addr_{} {}
 
 AbstractSocket::~AbstractSocket() {
   Disconnect();
@@ -136,6 +136,7 @@ void AbstractSocket::GetFdInfo() {
   pid_ = cred.pid;
   uid_ = cred.uid;
 }
+
 void AbstractSocket::Disconnect() {
   if (fd_ > 0)
     close(fd_);
index fecd9ba84ad24dbd69e8ca6cda39a5c186d17d91..e04b6388f44cb278947877126c4b54741983b7fe 100644 (file)
@@ -52,8 +52,8 @@ class EXPORT_API AbstractSocket {
  protected:
   std::string path_;
   int fd_;
-  pid_t pid_;
-  uid_t uid_;
+  pid_t pid_ = -1;
+  uid_t uid_ = -1;
   struct sockaddr_un addr_;
 };
 
index 2ce0d2bbae152745ad39954aa59e60746a866dce..5704da04e9a816dfa08dbcd52cb124e51b72f16c 100644 (file)
@@ -2,10 +2,12 @@
 SET(PKGINFO_SERVER "pkginfo-server")
 
 AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} SERVER_SRCS)
+AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/cynara_checker CYNARA_CHECKER_SRCS)
 AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/database DATABASE_SRCS)
 AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/request_handler REQUEST_HANDLER_SRCS)
 
 ADD_LIBRARY(pkgmgr-info-server SHARED
+  ${CYNARA_CHECKER_SRCS}
   ${SERVER_SRCS}
   ${DATABASE_SRCS}
   ${REQUEST_HANDLER_SRCS}
diff --git a/src/server/cynara_checker/cynara_checker.cc b/src/server/cynara_checker/cynara_checker.cc
new file mode 100644 (file)
index 0000000..4a01cc5
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 <cynara-creds-socket.h>
+#include <cynara-session.h>
+#include <dlog.h>
+#include <glib-unix.h>
+
+#include <cstdlib>
+#include <memory>
+#include <mutex>
+
+#include "cynara_checker.hh"
+#include "pkgmgrinfo_private.h"
+
+namespace pkgmgr_server {
+
+void CynaraChecker::Init() {
+  cynara_async_initialize(&cynara_, nullptr, StatusCb, nullptr);
+}
+
+void CynaraChecker::Fini() {
+  if (cynara_sid_)
+    g_source_remove(cynara_sid_);
+
+  if (cynara_ != nullptr)
+    cynara_async_finish(cynara_);
+}
+
+CynaraChecker& CynaraChecker::GetInst() {
+  static CynaraChecker inst;
+  return inst;
+}
+
+void CynaraChecker::ReplyCb(cynara_check_id id, cynara_async_call_cause cause,
+    int resp, void* data) {
+  auto runner = static_cast<Runner*>(data);
+  auto& inst = CynaraChecker::GetInst();
+  switch (cause) {
+  case CYNARA_CALL_CAUSE_ANSWER:
+    if (resp == CYNARA_API_ACCESS_ALLOWED) {
+      auto it = inst.cynara_id_map_.find(id);
+      if (it == inst.cynara_id_map_.end()) {
+        LOGE("Invalid request");
+        break;
+      }
+      LOGD("Allowed request");
+      runner->QueueRequest(it->second);
+      inst.cynara_id_map_.erase(it);
+    }
+    break;
+  case CYNARA_CALL_CAUSE_CANCEL:
+  case CYNARA_CALL_CAUSE_FINISH:
+  case CYNARA_CALL_CAUSE_SERVICE_NOT_AVAILABLE:
+  default:
+    LOGE("Cynara: resp: not answer");
+    break;
+  }
+}
+
+gboolean CynaraChecker::ProcessCb(gint fd, GIOCondition cond, gpointer data) {
+  auto& inst = CynaraChecker::GetInst();
+  if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) {
+    inst.cynara_sid_ = 0;
+    return G_SOURCE_REMOVE;
+  }
+
+  int ret = cynara_async_process(inst.cynara_);
+  if (ret != CYNARA_API_SUCCESS)
+    LOGE("process error %d", ret);
+
+  return G_SOURCE_CONTINUE;
+}
+
+void CynaraChecker::StatusCb(int old_fd, int new_fd,
+    cynara_async_status status, void* data) {
+  auto& inst = CynaraChecker::GetInst();
+  if (old_fd != -1) {
+    if (inst.cynara_sid_) {
+      g_source_remove(inst.cynara_sid_);
+      inst.cynara_sid_ = 0;
+    }
+  }
+  if (new_fd != -1) {
+    auto cond = G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
+    if (status == CYNARA_STATUS_FOR_RW)
+      cond |= G_IO_OUT;
+
+    inst.cynara_sid_ = g_unix_fd_add(new_fd, static_cast<GIOCondition>(cond),
+        ProcessCb, data);
+  }
+}
+
+void CynaraChecker::CheckPrivilege(Runner* runner,
+    const std::shared_ptr<PkgRequest>& req,
+    const std::vector<std::string>& privileges) {
+  if (privileges.empty() || req->GetSenderUID() < REGULAR_USER) {
+    LOGD("Allowed request");
+    runner->QueueRequest(req);
+    return;
+  }
+
+  int ret;
+  if (cynara_ == nullptr) {
+    ret = cynara_async_initialize(&cynara_, nullptr, StatusCb, nullptr);
+    if (ret != CYNARA_API_SUCCESS) {
+      LOGE("Failed to initialize cynara_");
+      return;
+    }
+  }
+  char* smack_label;
+  ret = cynara_creds_socket_get_client(req->GetFd(), CLIENT_METHOD_SMACK,
+      &smack_label);
+  if (ret != CYNARA_API_SUCCESS) {
+    LOGE("Failed to get smack label");
+    return;
+  }
+  std::unique_ptr<char, decltype(std::free)*> lblPtr(smack_label, std::free);
+  char* session = cynara_session_from_pid(req->GetSenderPID());
+  if (session == nullptr) {
+    LOGE("Failed to get client session (pid:%d)", req->GetSenderPID());
+    return;
+  }
+  std::unique_ptr<char, decltype(std::free)*> sessPtr(session, std::free);
+  cynara_check_id id;
+  bool check = false;
+  for (auto& priv : privileges) {
+    ret = cynara_async_create_request(cynara_, smack_label, session,
+        std::to_string(req->GetSenderUID()).c_str(), priv.c_str(),
+        &id, ReplyCb, runner);
+    if (check == false) {
+      cynara_id_map_[id] = req;
+      check = true;
+    }
+  }
+}
+
+}  // namespace pkgmgr_server
\ No newline at end of file
diff --git a/src/server/cynara_checker/cynara_checker.hh b/src/server/cynara_checker/cynara_checker.hh
new file mode 100644 (file)
index 0000000..3231142
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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.
+ */
+
+#ifndef CYNARA_CHECKER_HH_
+#define CYNARA_CHECKER_HH_
+
+#include <glib.h>
+#include <cynara-client-async.h>
+
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include "pkg_request.hh"
+#include "runner.hh"
+
+namespace pkgmgr_server {
+
+#ifndef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+#endif
+
+class EXPORT_API CynaraChecker {
+ public:
+  static CynaraChecker& GetInst();
+  void Init();
+  void Fini();
+  void CheckPrivilege(Runner* runner,
+      const std::shared_ptr<PkgRequest>& req,
+      const std::vector<std::string>& privileges);
+
+ private:
+  CynaraChecker() = default;
+  ~CynaraChecker() = default;
+  static void ReplyCb(cynara_check_id id, cynara_async_call_cause cause,
+      int resp, void* data);
+  static gboolean ProcessCb(gint fd, GIOCondition cond, gpointer data);
+  static void StatusCb(int old_fd, int new_fd,
+      cynara_async_status status, void* data);
+
+ private:
+  cynara_async* cynara_ = nullptr;
+  guint cynara_sid_ = 0;
+  std::unordered_map<cynara_check_id, std::shared_ptr<PkgRequest>> cynara_id_map_;
+};
+
+}  // namespace pkgmgr_server
+
+#endif  // CYNARA_CHECKER_HH_
+
index 9be085949a611b42383d95ab0059a2768470de0f..6bcfd8741a1673ccbabc94ed854f3763707a55b3 100644 (file)
@@ -14,9 +14,6 @@
  * limitations under the License.
  */
 
-#include <cynara-client-async.h>
-#include <cynara-creds-socket.h>
-#include <cynara-session.h>
 #include <fcntl.h>
 #include <glib-unix.h>
 #include <stdlib.h>
@@ -27,6 +24,7 @@
 #include <unordered_map>
 #include <vector>
 
+#include "cynara_checker.hh"
 #include "pkg_request.hh"
 #include "runner.hh"
 #include "pkgmgrinfo_debug.h"
 namespace pkgmgr_server {
 namespace {
 
-cynara_async* cynara = nullptr;
-guint cynara_sid;
 static const std::string SOCK_PATH = "/run/pkgmgr-info-server";
 const char PRIVILEGE_PACKAGE_MANAGER_ADMIN[] = "http://tizen.org/privilege/packagemanager.admin";
-std::unordered_map<std::string, std::shared_ptr<PkgRequest>> req_map;
-std::unordered_map<cynara_check_id, std::shared_ptr<PkgRequest>> cynara_id_map;
 
-/* cynara methods */
 std::vector<std::string> GetPrivileges(pkgmgr_common::ReqType type) {
   std::vector<std::string> ret;
   if (type == pkgmgr_common::SET_CERT_INFO) {
@@ -59,113 +52,13 @@ std::vector<std::string> GetPrivileges(pkgmgr_common::ReqType type) {
   return ret;
 }
 
-void ReplyCb(cynara_check_id id, cynara_async_call_cause cause,
-    int resp, void* data) {
-  auto runner = static_cast<Runner*>(data);
-  switch (cause) {
-  case CYNARA_CALL_CAUSE_ANSWER:
-    if (resp == CYNARA_API_ACCESS_ALLOWED) {
-      auto it = cynara_id_map.find(id);
-      if (it == cynara_id_map.end()) {
-        LOGE("Invalid request");
-        break;
-      }
-      LOGD("Allowed request");
-      runner->QueueRequest(it->second);
-      cynara_id_map.erase(it);
-    }
-    break;
-  case CYNARA_CALL_CAUSE_CANCEL:
-  case CYNARA_CALL_CAUSE_FINISH:
-  case CYNARA_CALL_CAUSE_SERVICE_NOT_AVAILABLE:
-  default:
-    LOGE("Cynara: resp: not answer");
-    break;
-  }
-}
-
-gboolean ProcessCb(gint fd, GIOCondition cond, gpointer data) {
-  if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) {
-    cynara_sid = 0;
-    return G_SOURCE_REMOVE;
-  }
-
-  int ret = cynara_async_process(cynara);
-  if (ret != CYNARA_API_SUCCESS)
-    LOGE("process error %d", ret);
-
-  return G_SOURCE_CONTINUE;
-}
-
-void StatusCb(int old_fd, int new_fd, cynara_async_status status, void* data) {
-  if (old_fd != -1) {
-    if (cynara_sid) {
-      g_source_remove(cynara_sid);
-      cynara_sid = 0;
-    }
-  }
-  if (new_fd != -1) {
-    auto cond = G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
-    if (status == CYNARA_STATUS_FOR_RW)
-      cond |= G_IO_OUT;
-
-    cynara_sid = g_unix_fd_add(new_fd, static_cast<GIOCondition>(cond),
-        ProcessCb, data);
-  }
-}
-
-void CheckPrivilege(Runner* runner,
-    const std::shared_ptr<PkgRequest>& req,
-    const std::vector<std::string>& privileges) {
-  if (privileges.empty() || req->GetSenderUID() < REGULAR_USER) {
-    LOGD("Allowed request");
-    runner->QueueRequest(req);
-    return;
-  }
-
-  int ret;
-  if (cynara == nullptr) {
-    ret = cynara_async_initialize(&cynara, NULL, StatusCb, nullptr);
-    if (ret != CYNARA_API_SUCCESS) {
-      LOGE("Failed to initialize cynara");
-      return;
-    }
-  }
-  char* smack_label;
-  ret = cynara_creds_socket_get_client(req->GetFd(), CLIENT_METHOD_SMACK,
-      &smack_label);
-  if (ret != CYNARA_API_SUCCESS) {
-    LOGE("Failed to get smack label");
-    return;
-  }
-  std::unique_ptr<char, decltype(std::free)*> lblPtr(smack_label, std::free);
-  char* session = cynara_session_from_pid(req->GetSenderPID());
-  if (session == nullptr) {
-    LOGE("Failed to get client session (pid:%d)", req->GetSenderPID());
-    return;
-  }
-  std::unique_ptr<char, decltype(std::free)*> sessPtr(session, std::free);
-  cynara_check_id id;
-  bool check = false;
-  for (auto& priv : privileges) {
-    ret = cynara_async_create_request(cynara, smack_label, session,
-        std::to_string(req->GetSenderUID()).c_str(), priv.c_str(),
-        &id, ReplyCb, runner);
-    if (check == false) {
-      cynara_id_map[id] = req;
-      check = true;
-    }
-  }
-}
-
 }  // namespace
 
 Runner::Runner(unsigned int thread_num) {
   /* thread_num_ <= hardware_concurrency */
   thread_num_ = std::min(thread_num, std::thread::hardware_concurrency());
-
+  CynaraChecker::GetInst().Init();
   server_ = std::make_unique<pkgmgr_common::socket::ServerSocket>(SOCK_PATH);
-  cynara_async_initialize(&cynara, nullptr, StatusCb, nullptr);
   thread_pool_ = std::make_unique<WorkerThread>(thread_num_);
   auto condition = static_cast<GIOCondition>(
       G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL);
@@ -182,16 +75,8 @@ Runner::Runner(unsigned int thread_num) {
 
 Runner::~Runner() {
   g_source_remove(sid_);
-  if (cynara_sid) {
-    g_source_remove(cynara_sid);
-    cynara_sid = 0;
-  }
-
-  if (cynara != nullptr) {
-    cynara_async_finish(cynara);
-    cynara = nullptr;
-  }
   vconf_ignore_key_changed(VCONFKEY_LANGSET, OnLanguageChange);
+  CynaraChecker::GetInst().Fini();
 }
 
 int Runner::OnReceiveRequest(int fd, GIOCondition cond, void* user_data) {
@@ -212,7 +97,7 @@ int Runner::OnReceiveRequest(int fd, GIOCondition cond, void* user_data) {
   if (req->ReceiveData()) {
     pkgmgr_common::ReqType type = req->GetRequestType();
     std::vector<std::string>&& privileges = GetPrivileges(type);
-    CheckPrivilege(runner, req, privileges);
+    CynaraChecker::GetInst().CheckPrivilege(runner, req, privileges);
   }
 
   return G_SOURCE_CONTINUE;