${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
)
### 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})
BuildRequires: pkgconfig(parcel)
BuildRequires: pkgconfig(cynara-client-async)
BuildRequires: pkgconfig(cynara-session)
+BuildRequires: pkgconfig(cynara-creds-socket)
%if 0%{?gcov:1}
BuildRequires: lcov
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();
pid_ = cred.pid;
uid_ = cred.uid;
}
+
void AbstractSocket::Disconnect() {
if (fd_ > 0)
close(fd_);
protected:
std::string path_;
int fd_;
- pid_t pid_;
- uid_t uid_;
+ pid_t pid_ = -1;
+ uid_t uid_ = -1;
struct sockaddr_un addr_;
};
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}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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_
+
* 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>
#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) {
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);
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) {
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;