From 0e0c941196c0dc23eee6247a5182f6851e45ff48 Mon Sep 17 00:00:00 2001 From: "sangwan.kwon" Date: Mon, 4 Apr 2016 13:24:17 +0900 Subject: Implement on-demand style about server-side [AS-IS] * cert-checker was daemon. [TO-BE] * Change to on-demand style. * cert-svc call cert-checker. * Add common library. Change-Id: Idab160e6103cf62299b97a5485a767de9831d614 Signed-off-by: sangwan.kwon --- CMakeLists.txt | 53 ++- packaging/cert-checker-common.manifest.in | 5 + packaging/cert-checker.manifest | 5 - packaging/cert-checker.manifest.in | 5 + packaging/cert-checker.spec | 145 ++++--- pkgconfig/CMakeLists.txt | 11 + pkgconfig/cert-checker.pc.in | 11 + src/CMakeLists.txt | 103 +++-- src/app.cpp | 77 ---- src/cert-checker.cpp | 48 --- src/certs.cpp | 203 ---------- src/common/CMakeLists.txt | 58 +++ src/common/binary-queue.cpp | 117 ++++++ src/common/binary-queue.h | 96 +++++ src/common/connection.cpp | 66 +++ src/common/connection.h | 55 +++ src/common/mainloop.cpp | 147 +++++++ src/common/mainloop.h | 58 +++ src/common/serialization.h | 610 ++++++++++++++++++++++++++++ src/common/service.cpp | 141 +++++++ src/common/service.h | 66 +++ src/common/socket.cpp | 211 ++++++++++ src/common/socket.h | 56 +++ src/common/types.h | 30 ++ src/include/cchecker/UIBackend.h | 2 +- src/include/cchecker/app.h | 62 --- src/include/cchecker/certs.h | 65 --- src/include/cchecker/logic.h | 157 -------- src/include/cchecker/queue.h | 60 --- src/include/cchecker/sql_query.h | 2 +- src/logic.cpp | 624 ---------------------------- src/main/cert-checker.cpp | 55 +++ src/po/CMakeLists.txt | 2 +- src/queue.cpp | 62 --- src/service/app.cpp | 77 ++++ src/service/app.h | 62 +++ src/service/certs.cpp | 204 ++++++++++ src/service/certs.h | 65 +++ src/service/logic.cpp | 647 ++++++++++++++++++++++++++++++ src/service/logic.h | 170 ++++++++ src/service/ocsp-service.cpp | 70 ++++ src/service/ocsp-service.h | 44 ++ src/service/queue.cpp | 61 +++ src/service/queue.h | 60 +++ src/ui/popup-bin/CMakeLists.txt | 20 +- src/ui/popup-bin/popup.cpp | 12 +- src/ui/popup-runner.cpp | 4 +- systemd/CMakeLists.txt | 17 +- systemd/cert-checker.service | 15 - systemd/cert-checker.service.in | 13 + systemd/cert-checker.socket.in | 7 + tests/CMakeLists.txt | 63 +-- tests/app_event_operators.h | 4 +- tests/certs_.h | 2 +- tests/logic_.h | 2 +- tests/queue_test_thread.cpp | 4 +- tests/queue_test_thread.h | 2 +- tests/stubs_.cpp | 5 +- tests/test_logic.cpp | 5 +- 59 files changed, 3556 insertions(+), 1547 deletions(-) create mode 100644 packaging/cert-checker-common.manifest.in delete mode 100644 packaging/cert-checker.manifest create mode 100644 packaging/cert-checker.manifest.in create mode 100644 pkgconfig/CMakeLists.txt create mode 100644 pkgconfig/cert-checker.pc.in delete mode 100644 src/app.cpp delete mode 100644 src/cert-checker.cpp delete mode 100644 src/certs.cpp create mode 100644 src/common/CMakeLists.txt create mode 100644 src/common/binary-queue.cpp create mode 100644 src/common/binary-queue.h create mode 100644 src/common/connection.cpp create mode 100644 src/common/connection.h create mode 100644 src/common/mainloop.cpp create mode 100644 src/common/mainloop.h create mode 100644 src/common/serialization.h create mode 100644 src/common/service.cpp create mode 100644 src/common/service.h create mode 100644 src/common/socket.cpp create mode 100644 src/common/socket.h create mode 100644 src/common/types.h delete mode 100644 src/include/cchecker/app.h delete mode 100644 src/include/cchecker/certs.h delete mode 100644 src/include/cchecker/logic.h delete mode 100644 src/include/cchecker/queue.h delete mode 100644 src/logic.cpp create mode 100644 src/main/cert-checker.cpp delete mode 100644 src/queue.cpp create mode 100644 src/service/app.cpp create mode 100644 src/service/app.h create mode 100644 src/service/certs.cpp create mode 100644 src/service/certs.h create mode 100644 src/service/logic.cpp create mode 100644 src/service/logic.h create mode 100644 src/service/ocsp-service.cpp create mode 100644 src/service/ocsp-service.h create mode 100644 src/service/queue.cpp create mode 100644 src/service/queue.h delete mode 100644 systemd/cert-checker.service create mode 100644 systemd/cert-checker.service.in create mode 100644 systemd/cert-checker.socket.in diff --git a/CMakeLists.txt b/CMakeLists.txt index f5ba424..fd24809 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ # Copyright (c) 2015 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 @@ -14,13 +14,14 @@ # # @file CMakeLists.txt # @author Janusz Kozerski +# @author Sangwan Kwon # @brief # ############################# Check minimum CMake version ##################### CMAKE_MINIMUM_REQUIRED(VERSION 2.6) -PROJECT("cert-checker") +PROJECT(${SERVICE_NAME}) ############################# cmake packages ################################## @@ -29,7 +30,6 @@ INCLUDE(FindPkgConfig) ############################# defines ################################## SET(PREFIX ${CMAKE_INSTALL_PREFIX}) -SET(BINDIR "${PREFIX}/bin") SET(RESDIR "${PREFIX}/res") SET(LOCALEDIR "${RESDIR}/locale") @@ -48,12 +48,22 @@ ADD_DEFINITIONS("-Wall") # Generate all warnings ADD_DEFINITIONS("-Wextra") # Generate even more extra warnings ADD_DEFINITIONS("-fvisibility=hidden -fPIE") # Hide symbols by default +# Set library flag +ADD_DEFINITIONS("-fPIC") + # Set linker flag SET(CMAKE_SHARED_LINKER_FLAGS "-Wl,--as-needed") SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed") -# Pass project name to sources -ADD_DEFINITIONS("-DPROJECT_NAME=\"${PROJECT_NAME}\"") +# Pass macro to sources +ADD_DEFINITIONS("-DSERVICE_NAME=\"${SERVICE_NAME}\"") +ADD_DEFINITIONS("-DSERVICE_STREAM=\"${SERVICE_STREAM}\"") +ADD_DEFINITIONS("-DSERVICE_USER=\"${SERVICE_USER}\"") +ADD_DEFINITIONS("-DSERVICE_GROUP=\"${SERVICE_GROUP}\"") + +ADD_DEFINITIONS("-DINCLUDE_INSTALL_DIR=\"${INCLUDE_INSTALL_DIR}\"") + +STRING(REGEX MATCH "([^.]*)" API_VERSION "${VERSION}") IF (CMAKE_BUILD_TYPE MATCHES "DEBUG") ADD_DEFINITIONS("-DBUILD_TYPE_DEBUG") @@ -63,14 +73,37 @@ ENDIF (CMAKE_BUILD_TYPE MATCHES "DEBUG") ADD_DEFINITIONS("-DPOPUP=1") ADD_DEFINITIONS("-DDB_INSTALL_DIR=\"${DB_INSTALL_DIR}\"") -SET(TARGET_CERT_CHECKER "cert-checker") -SET(TARGET_CERT_CHECKER_POPUP "cert-checker-popup") +# Define global macro about TARGET +SET(TARGET_CERT_CHECKER "${SERVICE_NAME}") +SET(TARGET_CERT_CHECKER_COMMON "${SERVICE_NAME}-common") +SET(TARGET_CERT_CHECKER_POPUP "${SERVICE_NAME}-popup") + # Tests -SET(TARGET_CERT_CHECKER_TESTS "cert-checker-tests") -SET(TARGET_CERT_CHECKER_TESTS_LOGIC "cert-checker-tests-logic") -SET(TARGET_CERT_CHECKER_POPUP_TEST "cert-checker-popup-test") +SET(TARGET_CERT_CHECKER_TESTS "${SERVICE_NAME}-tests") +SET(TARGET_CERT_CHECKER_TESTS_LOGIC "${SERVICE_NAME}-tests-logic") +SET(TARGET_CERT_CHECKER_POPUP_TEST "${SERVICE_NAME}-popup-test") + +# Define global macro about PATH +SET(CERT_CHECKER_SRC_PATH ${PROJECT_SOURCE_DIR}/src) +SET(CERT_CHECKER_SERVICE_PATH ${CERT_CHECKER_SRC_PATH}/service) +SET(CERT_CHECKER_LOG_PATH ${CERT_CHECKER_SRC_PATH}/log) +SET(CERT_CHECKER_UI_PATH ${CERT_CHECKER_SRC_PATH}/ui) +SET(CERT_CHECKER_DB_PATH ${CERT_CHECKER_SRC_PATH}/db) + +SET(DPL_CORE_PATH ${CERT_CHECKER_SRC_PATH}/dpl/core) +SET(DPL_CORE_SRC_PATH ${DPL_CORE_PATH}/src) +SET(DPL_DB_PATH ${CERT_CHECKER_SRC_PATH}/dpl/db) +SET(DPL_DB_SRC_PATH ${DPL_DB_PATH}/src) + +CONFIGURE_FILE( + packaging/${SERVICE_NAME}.manifest.in + ${SERVICE_NAME}.manifest @ONLY) +CONFIGURE_FILE( + packaging/${SERVICE_NAME}-common.manifest.in + ${SERVICE_NAME}-common.manifest @ONLY) ADD_SUBDIRECTORY(src) ADD_SUBDIRECTORY(db) ADD_SUBDIRECTORY(tests) ADD_SUBDIRECTORY(systemd) +ADD_SUBDIRECTORY(pkgconfig) diff --git a/packaging/cert-checker-common.manifest.in b/packaging/cert-checker-common.manifest.in new file mode 100644 index 0000000..75b0fa5 --- /dev/null +++ b/packaging/cert-checker-common.manifest.in @@ -0,0 +1,5 @@ + + + + + diff --git a/packaging/cert-checker.manifest b/packaging/cert-checker.manifest deleted file mode 100644 index 75b0fa5..0000000 --- a/packaging/cert-checker.manifest +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/packaging/cert-checker.manifest.in b/packaging/cert-checker.manifest.in new file mode 100644 index 0000000..75b0fa5 --- /dev/null +++ b/packaging/cert-checker.manifest.in @@ -0,0 +1,5 @@ + + + + + diff --git a/packaging/cert-checker.spec b/packaging/cert-checker.spec index aef14a3..649a4a1 100644 --- a/packaging/cert-checker.spec +++ b/packaging/cert-checker.spec @@ -5,7 +5,6 @@ Release: 1 Group: Security/Certificate Management License: Apache-2.0 and BSL-1.0 Source0: %{name}-%{version}.tar.gz -Source1: %{name}.manifest BuildRequires: cmake BuildRequires: zip BuildRequires: gettext-tools @@ -24,24 +23,55 @@ BuildRequires: pkgconfig(pkgmgr) BuildRequires: pkgconfig(pkgmgr-info) BuildRequires: boost-devel Requires: security-config +Requires: lib%{name}-common = %{version}-%{release} +%description +Check OCSP validation at app install/uninstall time. + +%global SBIN_DIR /sbin %global TZ_SYS_DB %{?TZ_SYS_DB:%TZ_SYS_DB}%{!?TZ_SYS_DB:/opt/dbspace} %global TZ_SYS_ROOT %{?TZ_SYS_ROOT:%TZ_SYS_ROOT}%{!?TZ_SYS_ROOT:/root} %global TZ_SYS_RO_SHARE %{?TZ_SYS_RO_SHARE:%TZ_SYS_RO_SHARE}%{!?TZ_SYS_RO_SHARE:/usr/share} %global TZ_SYS_BIN %{?TZ_SYS_BIN:%TZ_SYS_BIN}%{!?TZ_SYS_BIN:/usr/bin} -%global DB_INST_DIR %{TZ_SYS_DB}/cert-checker - -%description -Cert-checker - -%package -n cert-checker-tests +%global DB_INST_DIR %{TZ_SYS_DB}/%{name} + +# service macro +%global service_name %{name} +%global service_stream /tmp/%{service_name}.socket +%global service_user security_fw +%global service_group security_fw + +# common lib package +%package -n lib%{name}-common +Summary: Common Library package for %{name} +License: Apache-2.0 +Group: Security/Libraries +Requires: %{SBIN_DIR}/ldconfig + +%description -n lib%{name}-common +cert-checker common library package. + +# devel package +%package devel +Summary: Development files for %{name} +License: Apache-2.0 +Group: Security/Development +BuildRequires: pkgconfig(capi-base-common) +Requires: %{name} = %{version}-%{release} + +%description devel +cert-checker development files. + +# test package +%package -n %{name}-tests Summary: Internal test for cert-checker -Group: Development +License: Apache-2.0 and BSL-1.0 +Group: Security/Testing Requires: boost-test -Requires: cert-checker = %{version}-%{release} +Requires: %{name} = %{version}-%{release} -%description -n cert-checker-tests +%description -n %{name}-tests Internal test for cert-checker implementation. %prep @@ -53,73 +83,86 @@ export CXXFLAGS="$CXXFLAGS" export FFLAGS="$FFLAGS" export LDFLAGS+="-Wl,--rpath=%{_libdir} " -%cmake . -DVERSION=%{version} \ - -DDB_INSTALL_DIR=%{DB_INST_DIR} \ - -DCMAKE_BUILD_TYPE=%{?build_type:%build_type}%{!?build_type:RELEASE} \ - -DCMAKE_VERBOSE_MAKEFILE=ON \ - -DTEST_APP_SIGNATURES_DIR="%{TZ_SYS_ROOT}/cert-checker-test" \ - -DSYSTEMD_UNIT_DIR=%{_unitdir} +%cmake . \ + -DVERSION=%{version} \ + -DCMAKE_BUILD_TYPE=%{?build_type:%build_type}%{!?build_type:RELEASE} \ + -DMAKE_VERBOSE_MAKEFILE=ON \ + -DSERVICE_NAME=%{service_name} \ + -DSERVICE_STREAM=%{service_stream} \ + -DSERVICE_USER=%{service_user} \ + -DSERVICE_GROUP=%{service_group} \ + -DINCLUDE_INSTALL_DIR:PATH=%{_includedir} \ + -DTEST_APP_SIGNATURES_DIR="%{TZ_SYS_ROOT}/cert-checker-test" \ + -DSYSTEMD_UNIT_DIR=%{_unitdir} \ + -DBIN_DIR=%{TZ_SYS_BIN} \ + -DDB_INSTALL_DIR=%{DB_INST_DIR} make %{?jobs:-j%jobs} %install -rm -rf %{buildroot} -mkdir -p %{buildroot}/%{DB_INST_DIR} -mkdir -p %{buildroot}/%{TZ_SYS_RO_SHARE}/license -cp LICENSE %{buildroot}/%{TZ_SYS_RO_SHARE}/license/%{name} %make_install -cp -a %{SOURCE1} %{buildroot}%{TZ_SYS_RO_SHARE}/ %find_lang %{name} -%make_install -mkdir -p %{buildroot}%{_unitdir}/multi-user.target.wants -ln -s ../cert-checker.service %{buildroot}%{_unitdir}/multi-user.target.wants/cert-checker.service - %clean rm -rf %{buildroot} %post systemctl daemon-reload + +# install if [ $1 = 1 ]; then - # installation - systemctl start cert-checker.service + systemctl start %{name}.socket fi - +# upgrade / reinstall if [ $1 = 2 ]; then - # update - systemctl restart cert-checker.service + systemctl stop %{name}.service + systemctl restart %{name}.socket fi + chsmack -a System %{DB_INST_DIR} -chsmack -a System %{DB_INST_DIR}/.cert-checker.db +chsmack -a System %{DB_INST_DIR}/.%{name}.db %preun +# uninstall if [ $1 = 0 ]; then - # unistall - systemctl stop cert-checker.service + systemctl stop %{name}.service + systemctl stop %{name}.socket fi %postun if [ $1 = 0 ]; then - # unistall systemctl daemon-reload fi +%post -n lib%{name}-common -p %{SBIN_DIR}/ldconfig +%postun -n lib%{name}-common -p %{SBIN_DIR}/ldconfig %files -f %{name}.lang -%{TZ_SYS_BIN}/cert-checker -%{TZ_SYS_BIN}/cert-checker-popup -%manifest %{TZ_SYS_RO_SHARE}/%{name}.manifest -%{TZ_SYS_RO_SHARE}/license/%{name} -%dir %attr(0700,security_fw,security_fw) %{DB_INST_DIR} -%config(noreplace) %attr(0600,security_fw,security_fw) %{DB_INST_DIR}/.cert-checker.db -%{_unitdir}/cert-checker.service -%{_unitdir}/multi-user.target.wants/cert-checker.service - -%files -n cert-checker-tests -%license LICENSE.BSL-1.0 -%defattr(-,security_fw,security_fw,-) -%{TZ_SYS_BIN}/cert-checker-tests -%{TZ_SYS_BIN}/cert-checker-tests-logic -%{TZ_SYS_BIN}/cert-checker-popup-test -%{DB_INST_DIR}/.cert-checker-test.db -%{TZ_SYS_ROOT}/cert-checker-test/*/*.xml +%manifest %{name}.manifest +%license LICENSE +%dir %attr(0700,%{service_user},%{service_group}) %{DB_INST_DIR} +%config(noreplace) %attr(0600,%{service_user},%{service_group}) %{DB_INST_DIR}/.%{name}.db +%{_unitdir}/%{name}.service +%{_unitdir}/%{name}.socket +%{TZ_SYS_BIN}/%{name} +%{TZ_SYS_BIN}/%{name}-popup + +%files -n lib%{name}-common +%defattr(-,root,root,-) +%manifest %{name}-common.manifest +%license LICENSE +%{_libdir}/lib%{name}-common.so.* + +%files devel +%defattr(-,root,root,-) +%{_libdir}/pkgconfig/%{name}.pc +%{_libdir}/lib%{name}-common.so + +%files -n %{name}-tests +%defattr(-,%{service_user},%{service_group},-) +%license LICENSE LICENSE.BSL-1.0 +%{TZ_SYS_BIN}/%{name}-tests +%{TZ_SYS_BIN}/%{name}-tests-logic +%{TZ_SYS_BIN}/%{name}-popup-test +%{DB_INST_DIR}/.%{name}-test.db +%{TZ_SYS_ROOT}/%{name}-test/*/*.xml diff --git a/pkgconfig/CMakeLists.txt b/pkgconfig/CMakeLists.txt new file mode 100644 index 0000000..a2d10a4 --- /dev/null +++ b/pkgconfig/CMakeLists.txt @@ -0,0 +1,11 @@ +CONFIGURE_FILE( + ${SERVICE_NAME}.pc.in + ${SERVICE_NAME}.pc + @ONLY +) + +INSTALL( + FILES + ${SERVICE_NAME}.pc + DESTINATION + ${LIB_INSTALL_DIR}/pkgconfig) diff --git a/pkgconfig/cert-checker.pc.in b/pkgconfig/cert-checker.pc.in new file mode 100644 index 0000000..f9dd91d --- /dev/null +++ b/pkgconfig/cert-checker.pc.in @@ -0,0 +1,11 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=%{prefix} +libdir=@LIB_INSTALL_DIR@ +includedir=@INCLUDE_INSTALL_DIR@ + +Name: @SERVICE_NAME@ +Description: @PACKAGE_DESCRIPTION@ +Version: @VERSION@ +Requires: +Libs: -L${libdir} -l@SERVICE_NAME@-common +Cflags: -I${includedir} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 568f553..36e35c4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,4 +1,25 @@ -PKG_CHECK_MODULES(CERT_CHECKER_DEP +# Copyright (c) 2015 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. +# +# @file CMakeLists.txt +# @author Janusz Kozerski +# @author Sangwan Kwon +# @brief +# + +############### CERT_CHECKER ############### +PKG_CHECK_MODULES(${TARGET_CERT_CHECKER}_DEP REQUIRED capi-appfw-application dbus-1 @@ -10,59 +31,61 @@ PKG_CHECK_MODULES(CERT_CHECKER_DEP icu-i18n key-manager libsystemd-journal + libsystemd-daemon sqlite3 pkgmgr pkgmgr-info - ) +) -SET(CERT_CHECKER_SRC_PATH ${PROJECT_SOURCE_DIR}/src) +SET(MAIN_PATH ${CERT_CHECKER_SRC_PATH}/main) -SET(CERT_CHECKER_SOURCES - ${CERT_CHECKER_SRC_PATH}/cert-checker.cpp - ${CERT_CHECKER_SRC_PATH}/app.cpp - ${CERT_CHECKER_SRC_PATH}/logic.cpp - ${CERT_CHECKER_SRC_PATH}/queue.cpp - ${CERT_CHECKER_SRC_PATH}/certs.cpp - # logs - ${CERT_CHECKER_SRC_PATH}/log/log.cpp - # dpl - ${CERT_CHECKER_SRC_PATH}/dpl/core/src/assert.cpp - ${CERT_CHECKER_SRC_PATH}/dpl/core/src/char_traits.cpp - ${CERT_CHECKER_SRC_PATH}/dpl/core/src/errno_string.cpp - ${CERT_CHECKER_SRC_PATH}/dpl/core/src/exception.cpp - ${CERT_CHECKER_SRC_PATH}/dpl/core/src/noncopyable.cpp - ${CERT_CHECKER_SRC_PATH}/dpl/core/src/string.cpp - ${CERT_CHECKER_SRC_PATH}/dpl/core/src/serialization.cpp - # dpl DB - ${CERT_CHECKER_SRC_PATH}/dpl/db/src/sql_connection.cpp - ${CERT_CHECKER_SRC_PATH}/dpl/db/src/naive_synchronization_object.cpp - # DB - ${CERT_CHECKER_SRC_PATH}/db/sql_query.cpp - # UI - ${CERT_CHECKER_SRC_PATH}/ui/UIBackend.cpp - ${CERT_CHECKER_SRC_PATH}/ui/popup-runner.cpp - ) +SET(${TARGET_CERT_CHECKER}_SRCS + ${MAIN_PATH}/cert-checker.cpp + ${CERT_CHECKER_SERVICE_PATH}/app.cpp + ${CERT_CHECKER_SERVICE_PATH}/logic.cpp + ${CERT_CHECKER_SERVICE_PATH}/queue.cpp + ${CERT_CHECKER_SERVICE_PATH}/certs.cpp + ${CERT_CHECKER_SERVICE_PATH}/ocsp-service.cpp + ${CERT_CHECKER_LOG_PATH}/log.cpp + ${CERT_CHECKER_DB_PATH}/sql_query.cpp + ${CERT_CHECKER_UI_PATH}/UIBackend.cpp + ${CERT_CHECKER_UI_PATH}/popup-runner.cpp + ${DPL_CORE_SRC_PATH}/assert.cpp + ${DPL_CORE_SRC_PATH}/char_traits.cpp + ${DPL_CORE_SRC_PATH}/errno_string.cpp + ${DPL_CORE_SRC_PATH}/exception.cpp + ${DPL_CORE_SRC_PATH}/noncopyable.cpp + ${DPL_CORE_SRC_PATH}/string.cpp + ${DPL_CORE_SRC_PATH}/serialization.cpp + ${DPL_DB_SRC_PATH}/sql_connection.cpp + ${DPL_DB_SRC_PATH}/naive_synchronization_object.cpp +) INCLUDE_DIRECTORIES(SYSTEM - ${CERT_CHECKER_DEP_INCLUDE_DIRS} + ./ + ${${TARGET_CERT_CHECKER}_DEP_INCLUDE_DIRS} ${CERT_CHECKER_SRC_PATH}/include/ - ${CERT_CHECKER_SRC_PATH}/dpl/core/include/ - ${CERT_CHECKER_SRC_PATH}/dpl/db/include/ - ) - -ADD_EXECUTABLE(${TARGET_CERT_CHECKER} ${CERT_CHECKER_SOURCES}) + ${DPL_CORE_PATH}/include/ + ${DPL_DB_PATH}/include/ +) -SET_TARGET_PROPERTIES(${TARGET_CERT_CHECKER} PROPERTIES - COMPILE_FLAGS - -fpie +SET_SOURCE_FILES_PROPERTIES(${${TARGET_CERT_CHECKER}_SRCS} + PROPERTIES + COMPILE_FLAGS "-D_GNU_SOURCE -fPIE -fvisibility=default" ) +ADD_EXECUTABLE(${TARGET_CERT_CHECKER} ${${TARGET_CERT_CHECKER}_SRCS}) + TARGET_LINK_LIBRARIES(${TARGET_CERT_CHECKER} - ${CERT_CHECKER_DEP_LIBRARIES} + ${${TARGET_CERT_CHECKER}_DEP_LIBRARIES} + ${TARGET_CERT_CHECKER_COMMON} -pie - ) +) -INSTALL(TARGETS ${TARGET_CERT_CHECKER} DESTINATION ${BINDIR}) +INSTALL(TARGETS ${TARGET_CERT_CHECKER} DESTINATION ${BIN_DIR}) +ADD_SUBDIRECTORY(main) +ADD_SUBDIRECTORY(service) +ADD_SUBDIRECTORY(common) ADD_SUBDIRECTORY(po) ADD_SUBDIRECTORY(ui) diff --git a/src/app.cpp b/src/app.cpp deleted file mode 100644 index 29a9b2d..0000000 --- a/src/app.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2015 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. - */ -/* - * @file app.cpp - * @author Janusz Kozerski (j.kozerski@samsung.com) - * @version 1.0 - * @brief This file is the implementation of app struct - */ - -#include -#include -#include - -#include -#include - -namespace CCHECKER { - -app_t::app_t(void): - uid((uid_t)-1), // (uid_t)-1 (0xFF) is defined to be invalid uid. According - // to chown manual page, you cannot change file group of owner - // to (uid_t)-1, so we'll use it as initial, invalid value. - verified(verified_t::UNKNOWN) -{} - -app_t::app_t(const std::string &app_id, - const std::string &pkg_id, - uid_t uid, - const signatures_t &signatures): - app_id(app_id), - pkg_id(pkg_id), - uid(uid), - signatures(signatures), - verified(verified_t::UNKNOWN) -{} - -std::ostream & operator<< (std::ostream &out, const app_t &app) -{ - out << "app: " << app.app_id << ", pkg: " << app.pkg_id << ", uid: " << app.uid; - return out; -} - -std::string app_t::str() const -{ - std::stringstream ss; - ss << *this; - return ss.str(); -} - -std::string app_t::str_certs(void) const -{ - std::stringstream ss; - - for (const auto &iter : signatures) { - ss << " { "; - for (const auto iter_cert : iter) { - ss << "\"" << iter_cert << "\", "; - } - ss << " } ,"; - } - return ss.str(); -} - -} //CCHECKER diff --git a/src/cert-checker.cpp b/src/cert-checker.cpp deleted file mode 100644 index c6e7537..0000000 --- a/src/cert-checker.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2015 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 - */ -/* - * @file cert-checker.cpp - * @author Janusz Kozerski (j.kozerski@samsung.com) - * @version 1.0 - * @brief Cert-checker daemon main loop. - */ - -#include - -#include -#include - -using namespace CCHECKER; - -int main(void) -{ - LogDebug("Cert-checker start!"); - - setlocale(LC_ALL, ""); - GMainLoop *main_loop = g_main_loop_new(NULL, FALSE); - - Logic logic; - if (logic.setup() != NO_ERROR) { - LogError("Cannot setup logic. Exit cert-checker!"); - return -1; - } - - LogDebug("Running the main loop"); - g_main_loop_run(main_loop); - - LogDebug("Cert-checker exit!"); - return 0; -} diff --git a/src/certs.cpp b/src/certs.cpp deleted file mode 100644 index 8f45a7f..0000000 --- a/src/certs.cpp +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright (c) 2015 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. - */ -/* - * @file certs.cpp - * @author Janusz Kozerski (j.kozerski@samsung.com) - * @version 1.0 - * @brief This file is the implementation of certificates logic - * Getting out app signature, getting certificates out of - * signature. Checking OCSP - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -namespace CCHECKER { - -namespace { -struct PkgmgrinfoCertInfo { - PkgmgrinfoCertInfo() - { - ret = pkgmgrinfo_pkginfo_create_certinfo(&handle); - } - ~PkgmgrinfoCertInfo() - { - pkgmgrinfo_pkginfo_destroy_certinfo(handle); - } - - pkgmgrinfo_certinfo_h handle; - int ret; -}; - -static void get_cert_chain(const char *pkgid, uid_t uid, int sig_type, chain_t &chain) -{ - LogDebug("Get cert chain start. pkgid : " << pkgid << ", uid : " << uid); - int ret; - int cert_type; - const char *cert_value; - - auto pm_certinfo = std::make_shared(); - - if (pm_certinfo->ret != PMINFO_R_OK) { - LogError("Get pkgmgrinfo certinfo failed. ret : " << ret); - return; - } - - ret = pkgmgrinfo_pkginfo_load_certinfo(pkgid, pm_certinfo->handle, uid); - if (ret != PMINFO_R_OK) { - LogError("Load pkgmgrinfo certinfo failed. ret : " << ret); - return; - } - - // add signer, intermediate, root certificates. - for (int cert_cnt = 0; cert_cnt < 3; cert_cnt++) { - cert_type = sig_type - cert_cnt; - ret = pkgmgrinfo_pkginfo_get_cert_value(pm_certinfo->handle, - static_cast(cert_type), &cert_value); - - if (ret != PMINFO_R_OK) { - LogError("Get cert value from certinfo failed. ret : " << ret); - return; - } - - if (cert_value == NULL) { - LogDebug("cert_type[" << cert_type << "] is null"); - } else { - LogDebug("Add cert_type[" << cert_type << "] data : " << cert_value); - chain.push_back(cert_value); - } - } - - return; -} -} - -Certs::Certs() -{ - m_ckm = CKM::Manager::create(); -} - -Certs::~Certs() -{} - -void Certs::get_certificates(app_t &app) -{ - // build chain using pkgmgr-info - std::map sig_type; - sig_type[AUTHOR_SIG] = PMINFO_AUTHOR_SIGNER_CERT; - sig_type[DISTRIBUTOR_SIG] = PMINFO_DISTRIBUTOR_SIGNER_CERT; - sig_type[DISTRIBUTOR2_SIG] = PMINFO_DISTRIBUTOR2_SIGNER_CERT; - - for (auto s : sig_type) { - chain_t chain; - get_cert_chain(app.pkg_id.c_str(), app.uid, s.second, chain); - - if(!chain.empty()) { - LogDebug("Add certificates chain to app. Size of chain : " << chain.size()); - app.signatures.emplace_back(std::move(chain)); - } - } -} - -Certs::ocsp_response_t Certs::check_ocsp_chain(const chain_t &chain) -{ - CKM::CertificateShPtrVector vect_ckm_chain; - - LogDebug("Size of chain: " << chain.size()); - for (auto &iter : chain) { - CKM::RawBuffer buff(iter.begin(), iter.end()); - auto cert = CKM::Certificate::create(buff, CKM::DataFormat::FORM_DER_BASE64); - vect_ckm_chain.emplace_back(std::move(cert)); - } - - int status = CKM_API_OCSP_STATUS_UNKNOWN; - int ret = m_ckm->ocspCheck(vect_ckm_chain, status); - if (ret != CKM_API_SUCCESS) { - LogError("CKM ckeck OCSP returned " << ret); - // Add handling for different errors codes - // For these we can try to check ocsp again later: - switch (ret) { - case CKM_API_ERROR_NOT_SUPPORTED: - LogDebug("Key-manager OCSP API temporary diabled."); - case CKM_API_ERROR_SOCKET: - case CKM_API_ERROR_BAD_REQUEST: - case CKM_API_ERROR_BAD_RESPONSE: - case CKM_API_ERROR_SEND_FAILED: - case CKM_API_ERROR_RECV_FAILED: - case CKM_API_ERROR_SERVER_ERROR: - case CKM_API_ERROR_OUT_OF_MEMORY: - return Certs::ocsp_response_t::OCSP_CHECK_AGAIN; - // Any other error should be recurrent - checking the same app again - // should give the same result. - default: - return Certs::ocsp_response_t::OCSP_CERT_ERROR; - } - } - - LogDebug("OCSP status: " << status); - switch (status) { - // Remove app from "to-check" list: - case CKM_API_OCSP_STATUS_GOOD: - return Certs::ocsp_response_t::OCSP_APP_OK; - case CKM_API_OCSP_STATUS_UNSUPPORTED: - case CKM_API_OCSP_STATUS_UNKNOWN: - case CKM_API_OCSP_STATUS_INVALID_URL: - return Certs::ocsp_response_t::OCSP_CERT_ERROR; - - //Show popup to user and remove app from "to-check" list - case CKM_API_OCSP_STATUS_REVOKED: - return Certs::ocsp_response_t::OCSP_APP_REVOKED; - - //Keep app for checking it again later: - case CKM_API_OCSP_STATUS_NET_ERROR: - case CKM_API_OCSP_STATUS_INVALID_RESPONSE: - case CKM_API_OCSP_STATUS_REMOTE_ERROR: - case CKM_API_OCSP_STATUS_INTERNAL_ERROR: - return Certs::ocsp_response_t::OCSP_CHECK_AGAIN; - - default: - // This should never happen - return Certs::ocsp_response_t::OCSP_CERT_ERROR; - } -} - -Certs::ocsp_response_t Certs::check_ocsp (const app_t &app) -{ - bool check_again = false; - - for (auto &iter : app.signatures) { - Certs::ocsp_response_t resp = check_ocsp_chain(iter); - if (resp == Certs::ocsp_response_t::OCSP_APP_REVOKED) - return Certs::ocsp_response_t::OCSP_APP_REVOKED; - if (resp == Certs::ocsp_response_t::OCSP_CHECK_AGAIN) - check_again = true; - } - - if (check_again) - return Certs::ocsp_response_t::OCSP_CHECK_AGAIN; - return Certs::ocsp_response_t::OCSP_APP_OK; -} - -} // CCHECKER diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt new file mode 100644 index 0000000..fbfd9ff --- /dev/null +++ b/src/common/CMakeLists.txt @@ -0,0 +1,58 @@ +# Copyright (c) 2016 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. +# +# @file CMakeLists.txt +# @author Sangwan Kwon (sangwan.kwon@samsung.com) +# @brief Make common library for both of server and client. +# +PKG_CHECK_MODULES(${TARGET_CERT_CHECKER_COMMON}_DEP + REQUIRED + libsystemd-journal + libsystemd-daemon +) + +SET(COMMON_PATH ${CERT_CHECKER_SRC_PATH}/common) + +SET(${TARGET_CERT_CHECKER_COMMON}_SRCS + ${COMMON_PATH}/binary-queue.cpp + ${COMMON_PATH}/connection.cpp + ${COMMON_PATH}/mainloop.cpp + ${COMMON_PATH}/service.cpp + ${COMMON_PATH}/socket.cpp +) + +INCLUDE_DIRECTORIES(SYSTEM + ${${TARGET_CERT_CHECKER_COMMON}_DEP_INCLUDE_DIRS} + ${CERT_CHECKER_SRC_PATH}/include/ + ${DPL_CORE_PATH}/include/ + ${DPL_DB_PATH}/include/ +) + +ADD_LIBRARY(${TARGET_CERT_CHECKER_COMMON} + SHARED ${${TARGET_CERT_CHECKER_COMMON}_SRCS} +) + +SET_TARGET_PROPERTIES(${TARGET_CERT_CHECKER_COMMON} + PROPERTIES + COMPILE_FLAGS "-D_GNU_SOURCE -fvisibility=default" # TODO: visibility hidden + LINKER_LANGUAGE CXX + SOVERSION ${API_VERSION} + VERSION ${VERSION} +) + +TARGET_LINK_LIBRARIES(${TARGET_CERT_CHECKER_COMMON} + ${${TARGET_CERT_CHECKER_COMMON}_DEP_LIBRARIES} +) + +INSTALL(TARGETS ${TARGET_CERT_CHECKER_COMMON} DESTINATION ${LIB_INSTALL_DIR}) diff --git a/src/common/binary-queue.cpp b/src/common/binary-queue.cpp new file mode 100644 index 0000000..776f65e --- /dev/null +++ b/src/common/binary-queue.cpp @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2016 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. + */ +/* + * @file binary-queue.cpp + * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com) + * Kyungwook Tak (k.tak@samsung.com) + * @version 1.0 + * @brief + */ +#include "common/binary-queue.h" + +#include +#include +#include + +namespace CCHECKER { + +BinaryQueue::BinaryQueue() : m_size(0) +{ +} + +BinaryQueue::~BinaryQueue() +{ +} + +RawBuffer BinaryQueue::pop() +{ + RawBuffer buf(m_size); + + read(m_size, buf.data()); + + return buf; +} + +void BinaryQueue::push(const RawBuffer &data) +{ + write(data.size(), data.data()); +} + +void BinaryQueue::write(size_t size, const void *bytes) +{ + while (size > 0) { + auto s = (size > MaxBucketSize) ? MaxBucketSize : size; + auto b = new unsigned char[s]; + memcpy(b, bytes, s); + m_buckets.emplace(new Bucket(b, s)); + m_size += s; + size -= s; + } +} + +void BinaryQueue::read(size_t size, void *bytes) +{ + if (size == 0) + return; + + if (size > m_size) + throw std::logic_error("protocol broken. no more binary to flatten in queue"); + + void *cur = bytes; + + while (size > 0) { + if (m_buckets.empty()) + throw std::logic_error("protocol broken. no more buckets to extract"); + + size_t count = std::min(size, m_buckets.front()->left); + cur = m_buckets.front()->extractTo(cur, count); + + size -= count; + m_size -= count; + + if (m_buckets.front()->left == 0) + m_buckets.pop(); + } +} + +BinaryQueue::Bucket::Bucket(unsigned char *_data, size_t _size) : + data(_data), + cur(_data), + left(_size) +{ + if (_data == nullptr || _size == 0) + throw std::invalid_argument("Bucket construct failed."); +} + +BinaryQueue::Bucket::~Bucket() +{ + delete []data; +} + +void *BinaryQueue::Bucket::extractTo(void *dest, size_t size) +{ + if (dest == nullptr || size == 0) + throw std::logic_error("logic error. invalid input to Bucket::extractTo."); + + memcpy(dest, cur, size); + + cur += size; + left -= size; + + return static_cast(dest) + size; +} + +} // namespace CCHECKER diff --git a/src/common/binary-queue.h b/src/common/binary-queue.h new file mode 100644 index 0000000..a70c9ec --- /dev/null +++ b/src/common/binary-queue.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2016 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. + */ +/* + * @file binary-queue.h + * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com) + * Kyungwook Tak (k.tak@samsung.com) + * @version 1.0 + * @brief This file is the header file of binary queue + */ +#pragma once + +#include +#include +#include + +#include "common/serialization.h" +#include "common/types.h" + +using namespace CCHECKER::Common; + +namespace CCHECKER { + +class BinaryQueue : public IStream { +public: + BinaryQueue(); + virtual ~BinaryQueue(); + + BinaryQueue(BinaryQueue &&) = default; + BinaryQueue &operator=(BinaryQueue &&) = default; + BinaryQueue(const BinaryQueue &) = delete; + BinaryQueue &operator=(const BinaryQueue &) = delete; + + RawBuffer pop(void); + void push(const RawBuffer &); + + template + static BinaryQueue Serialize(const Args &...args); + + template + void Deserialize(Args &...args); + + virtual void read(size_t num, void *bytes) override; + virtual void write(size_t num, const void *bytes) override; + +private: + const static size_t MaxBucketSize = 1024; /* Bytes */ + + struct Bucket { + explicit Bucket(unsigned char *_data, size_t _size); + virtual ~Bucket(); + + /* extract ''size'' of bytes from bucket to dest and return updated dest */ + void *extractTo(void *dest, size_t size); + + Bucket(Bucket &&) = default; + Bucket &operator=(Bucket &&) = default; + Bucket(const Bucket &) = delete; + Bucket &operator=(const Bucket &) = delete; + + unsigned char *data; + const unsigned char *cur; // current valid position of data + size_t left; + }; + + std::queue> m_buckets; + size_t m_size; +}; + +template +BinaryQueue BinaryQueue::Serialize(const Args &...args) +{ + BinaryQueue q; + Serializer::Serialize(q, args...); + return q; +} + +template +void BinaryQueue::Deserialize(Args &...args) +{ + Deserializer::Deserialize(*this, args...); +} + +} // namespace CCHECKER diff --git a/src/common/connection.cpp b/src/common/connection.cpp new file mode 100644 index 0000000..54abe7c --- /dev/null +++ b/src/common/connection.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2016 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 + */ +/* + * @file connection.cpp + * @author Kyungwook Tak (k.tak@samsung.com) + * @version 1.0 + * @brief + */ +#include "common/connection.h" + +#include + +namespace CCHECKER { + +Connection::Connection(Socket &&socket) : m_socket(std::move(socket)) +{ +} + +Connection::~Connection() +{ +} + +Connection::Connection(Connection &&other) : m_socket(std::move(other.m_socket)) +{ +} + +Connection &Connection::operator=(Connection &&other) +{ + if (this == &other) + return *this; + + m_socket = std::move(other.m_socket); + return *this; +} + +void Connection::send(const RawBuffer &buf) const +{ + std::lock_guard lock(m_mSend); + m_socket.write(buf); +} + +RawBuffer Connection::receive() const +{ + std::lock_guard lock(m_mRecv); + return m_socket.read(); +} + +int Connection::getFd() const +{ + return m_socket.getFd(); +} + +} diff --git a/src/common/connection.h b/src/common/connection.h new file mode 100644 index 0000000..3172772 --- /dev/null +++ b/src/common/connection.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2016 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 + */ +/* + * @file connection.h + * @author Kyungwook Tak (k.tak@samsung.com) + * @version 1.0 + * @brief + */ +#pragma once + +#include +#include + +#include "common/socket.h" +#include "common/types.h" + +namespace CCHECKER { + +class Connection { +public: + explicit Connection(Socket &&socket); + virtual ~Connection(); + + Connection(const Connection &) = delete; + Connection &operator=(const Connection &) = delete; + + Connection(Connection &&); + Connection &operator=(Connection &&); + + void send(const RawBuffer &) const; + RawBuffer receive(void) const; + int getFd(void) const; + +private: + Socket m_socket; + mutable std::mutex m_mSend; + mutable std::mutex m_mRecv; +}; + +using ConnShPtr = std::shared_ptr; + +} // namespace CCHECKER diff --git a/src/common/mainloop.cpp b/src/common/mainloop.cpp new file mode 100644 index 0000000..19ff477 --- /dev/null +++ b/src/common/mainloop.cpp @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2016 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 + */ +/* + * @file mainloop.cpp + * @author Kyungwook Tak (k.tak@samsung.com) + * @version 1.0 + * @brief Mainloop with epoll + */ +#include "common/mainloop.h" + +#include +#include +#include +#include +#include + +#include + +namespace CCHECKER { + +Mainloop::Mainloop() : + m_isTimedOut(false), + m_pollfd(::epoll_create1(EPOLL_CLOEXEC)) +{ + if (m_pollfd == -1) + throw std::system_error( + std::error_code(errno, std::generic_category()), + "Failed to epoll_create1"); +} + +Mainloop::~Mainloop() +{ + if (!m_isTimedOut && !m_callbacks.empty()) + throw std::logic_error("mainloop registered callbacks should be empty " + "except timed out case"); + + ::close(m_pollfd); +} + +void Mainloop::run(int timeout) +{ + m_isTimedOut = false; + + while (!m_isTimedOut) { + dispatch(timeout); + } + + LogDebug("Mainloop run stopped"); +} + +void Mainloop::addEventSource(int fd, uint32_t event, Callback &&callback) +{ + /* TODO: use scoped-lock to thread safe on member variables */ + if (m_callbacks.count(fd) != 0) + throw std::logic_error("event source already added!"); + + LogDebug("Add event[" << event << "] source on fd[" << fd << "]"); + + epoll_event e; + + e.events = event; + e.data.fd = fd; + + if (::epoll_ctl(m_pollfd, EPOLL_CTL_ADD, fd, &e) == -1) + throw std::system_error( + std::error_code(errno, std::generic_category()), + "epoll_ctl failed to EPOLL_CTL_ADD."); + + m_callbacks[fd] = std::move(callback); +} + +void Mainloop::removeEventSource(int fd) +{ + /* TODO: use scoped-lock to thread safe on member variables */ + if (m_callbacks.count(fd) == 0) + throw std::logic_error("event source isn't added at all"); + + LogDebug("Remove event source on fd[" << fd << "]"); + + do { + m_callbacks.erase(fd); + + if (::epoll_ctl(m_pollfd, EPOLL_CTL_DEL, fd, nullptr) == -1) { + if (errno == ENOENT) + throw std::logic_error("Tried to delete epoll item which wasn't added"); + else + throw std::system_error( + std::error_code(errno, std::generic_category()), + "epoll_ctl failed to EPOLL_CTL_DEL."); + } + } while (false); +} + +void Mainloop::dispatch(int timeout) +{ + int nfds = -1; + epoll_event event[MAX_EPOLL_EVENTS]; + + LogDebug("Mainloop dispatched with timeout: " << timeout); + + do { + nfds = ::epoll_wait(m_pollfd, event, MAX_EPOLL_EVENTS, timeout); + } while ((nfds == -1) && (errno == EINTR)); + + if (nfds < 0) + throw std::system_error( + std::error_code(errno, std::generic_category()), + "epoll_wait failed!"); + + if (nfds == 0) { + LogDebug("Mainloop timed out!"); + m_isTimedOut = true; + return; + } + + for (int i = 0; i < nfds; i++) { + /* TODO: use scoped-lock to thread safe on member variables */ + int fd = event[i].data.fd; + + if (m_callbacks.count(fd) == 0) + throw std::logic_error("event in, but associated callback isn't exist!"); + + if (event[i].events & (EPOLLHUP | EPOLLRDHUP)) { + LogInfo("peer connection closed on fd[" << fd << "]"); + event[i].events &= ~EPOLLIN; + } + + LogDebug("event[" << event[i].events << "] polled on fd[" << fd << "]"); + + m_callbacks[fd](event[i].events); + } +} + +} // namespace CCHECKER diff --git a/src/common/mainloop.h b/src/common/mainloop.h new file mode 100644 index 0000000..c52a115 --- /dev/null +++ b/src/common/mainloop.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2016 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 + */ +/* + * @file mainloop.h + * @author Kyungwook Tak (k.tak@samsung.com) + * @version 1.0 + * @brief Manageloop with epoll + */ +#pragma once + +#include +#include +#include + +namespace CCHECKER { + +class Mainloop { +public: + typedef std::function Callback; + + Mainloop(); + virtual ~Mainloop(); + + Mainloop(const Mainloop &) = delete; + Mainloop &operator=(const Mainloop &) = delete; + Mainloop(Mainloop &&) = delete; + Mainloop &operator=(Mainloop &&) = delete; + + void run(int timeout); + + void addEventSource(int fd, uint32_t event, Callback &&callback); + void removeEventSource(int fd); + +private: + void dispatch(int timeout); + + bool m_isTimedOut; + int m_pollfd; + std::mutex m_mutex; + std::unordered_map m_callbacks; + + constexpr static size_t MAX_EPOLL_EVENTS = 32; +}; + +} // namespace CCHECKER diff --git a/src/common/serialization.h b/src/common/serialization.h new file mode 100644 index 0000000..7f0ee84 --- /dev/null +++ b/src/common/serialization.h @@ -0,0 +1,610 @@ +/* + * Copyright (c) 2016 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. + */ +/** + * @file serialization.h + * @author Tomasz Swierczek (t.swierczek@samsung.com) + * @version 1.0 + * @brief Interfaces and templates used for data serialization. + */ +#pragma once + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace CCHECKER { + +namespace Common { + +// Abstract data stream buffer +class IStream { +public: + virtual void read(size_t num, void *bytes) = 0; + virtual void write(size_t num, const void *bytes) = 0; + virtual ~IStream() {} +}; + +// Serializable interface +class ISerializable { +public: + ISerializable() {} + ISerializable(IStream &) {} + virtual void Serialize(IStream &) const = 0; + virtual ~ISerializable() {} +}; + +struct Serialization { + // serialization + // normal functions + + // ISerializable objects + static void Serialize(IStream &stream, const ISerializable &object) + { + object.Serialize(stream); + } + + static void Serialize(IStream &stream, const ISerializable *const object) + { + object->Serialize(stream); + } + + // char + static void Serialize(IStream &stream, const char value) + { + stream.write(sizeof(value), &value); + } + static void Serialize(IStream &stream, const char *const value) + { + stream.write(sizeof(*value), value); + } + + // unsigned char + static void Serialize(IStream &stream, const unsigned char value) + { + stream.write(sizeof(value), &value); + } + static void Serialize(IStream &stream, const unsigned char *const value) + { + stream.write(sizeof(*value), value); + } + + // unsigned int32 + static void Serialize(IStream &stream, const uint32_t value) + { + stream.write(sizeof(value), &value); + } + static void Serialize(IStream &stream, const uint32_t *const value) + { + stream.write(sizeof(*value), value); + } + + // int32 + static void Serialize(IStream &stream, const int32_t value) + { + stream.write(sizeof(value), &value); + } + static void Serialize(IStream &stream, const int32_t *const value) + { + stream.write(sizeof(*value), value); + } + + // unsigned int64 + static void Serialize(IStream &stream, const uint64_t value) + { + stream.write(sizeof(value), &value); + } + static void Serialize(IStream &stream, const uint64_t *const value) + { + stream.write(sizeof(*value), value); + } + + // int64 + static void Serialize(IStream &stream, const int64_t value) + { + stream.write(sizeof(value), &value); + } + static void Serialize(IStream &stream, const int64_t *const value) + { + stream.write(sizeof(*value), value); + } + + static void Serialize(IStream &stream, const time_t value) + { + stream.write(sizeof(value), &value); + } + static void Serialize(IStream &stream, const time_t *const value) + { + stream.write(sizeof(*value), value); + } + + // bool + static void Serialize(IStream &stream, const bool value) + { + stream.write(sizeof(value), &value); + } + static void Serialize(IStream &stream, const bool *const value) + { + stream.write(sizeof(*value), value); + } + + // std::string + template + static void Serialize(IStream &stream, const std::basic_string &str) + { + int length = str.size(); + stream.write(sizeof(length), &length); + stream.write(length * sizeof(T), str.data()); + } + + template + static void Serialize(IStream &stream, + const std::basic_string *const str) + { + int length = str->size(); + stream.write(sizeof(length), &length); + stream.write(length * sizeof(T), str->data()); + } + + // STL templates + + // std::list + template + static void Serialize(IStream &stream, const std::list &list) + { + size_t length = list.size(); + stream.write(sizeof(length), &length); + + for (const auto &item : list) + Serialize(stream, item); + } + template + static void Serialize(IStream &stream, const std::list *const list) + { + Serialize(stream, *list); + } + + template + static void Serialize(IStream &stream, const std::set &set) + { + auto len = set.size(); + stream.write(sizeof(len), &len); + + for (const auto &item : set) + Serialize(stream, item); + } + template + static void Serialize(IStream &stream, const std::set *const set) + { + Serialize(stream, *set); + } + + // RawBuffer + template + static void Serialize(IStream &stream, const std::vector &vec) + { + int length = vec.size(); + stream.write(sizeof(length), &length); + stream.write(length, vec.data()); + } + + template + static void Serialize(IStream &stream, + const std::vector *const vec) + { + Serialize(stream, *vec); + } + + // std::vector + template + static void Serialize(IStream &stream, const std::vector &vec) + { + int length = vec.size(); + stream.write(sizeof(length), &length); + + for (const auto &i : vec) + Serialize(stream, i); + } + template + static void Serialize(IStream &stream, const std::vector *const vec) + { + Serialize(stream, *vec); + } + + // std::pair + template + static void Serialize(IStream &stream, const std::pair &p) + { + Serialize(stream, p.first); + Serialize(stream, p.second); + } + template + static void Serialize(IStream &stream, const std::pair *const p) + { + Serialize(stream, *p); + } + + // std::map + template + static void Serialize(IStream &stream, const std::map &map) + { + size_t length = map.size(); + stream.write(sizeof(length), &length); + + for (const auto &item : map) { + Serialize(stream, item.first); + Serialize(stream, item.second); + } + } + template + static void Serialize(IStream &stream, const std::map *const map) + { + Serialize(stream, *map); + } + + // std::unordered_map + template + static void Serialize(IStream &stream, const std::unordered_map &map) + { + size_t length = map.size(); + stream.write(sizeof(length), &length); + + for (const auto &item : map) { + Serialize(stream, item.first); + Serialize(stream, item.second); + } + } + template + static void Serialize(IStream &stream, + const std::unordered_map *const map) + { + Serialize(stream, *map); + } + + // std::unique_ptr + template + static void Serialize(IStream &stream, const std::unique_ptr &p) + { + Serialize(stream, *p); + } + + // std::shared_ptr + template + static void Serialize(IStream &stream, const std::shared_ptr &p) + { + Serialize(stream, *p); + } +}; // struct Serialization + +struct Deserialization { + // deserialization + // normal functions + + // ISerializable objects + // T instead of ISerializable is needed to call proper constructor + template + static void Deserialize(IStream &stream, T &object) + { + object = T(stream); + } + template + static void Deserialize(IStream &stream, T *&object) + { + object = new T(stream); + } + + template + static void Deserialize(IStream &stream, std::shared_ptr &object) + { + object.reset(new T(stream)); + } + + // char + static void Deserialize(IStream &stream, char &value) + { + stream.read(sizeof(value), &value); + } + static void Deserialize(IStream &stream, char *&value) + { + value = new char; + stream.read(sizeof(*value), value); + } + + // unsigned char + static void Deserialize(IStream &stream, unsigned char &value) + { + stream.read(sizeof(value), &value); + } + static void Deserialize(IStream &stream, unsigned char *&value) + { + value = new unsigned char; + stream.read(sizeof(*value), value); + } + + // unsigned int32 + static void Deserialize(IStream &stream, uint32_t &value) + { + stream.read(sizeof(value), &value); + } + static void Deserialize(IStream &stream, uint32_t *&value) + { + value = new uint32_t; + stream.read(sizeof(*value), value); + } + + // int32 + static void Deserialize(IStream &stream, int32_t &value) + { + stream.read(sizeof(value), &value); + } + static void Deserialize(IStream &stream, int32_t *&value) + { + value = new int32_t; + stream.read(sizeof(*value), value); + } + + // unsigned int64 + static void Deserialize(IStream &stream, uint64_t &value) + { + stream.read(sizeof(value), &value); + } + static void Deserialize(IStream &stream, uint64_t *&value) + { + value = new uint64_t; + stream.read(sizeof(*value), value); + } + + // int64 + static void Deserialize(IStream &stream, int64_t &value) + { + stream.read(sizeof(value), &value); + } + static void Deserialize(IStream &stream, int64_t *&value) + { + value = new int64_t; + stream.read(sizeof(*value), value); + } + + static void Deserialize(IStream &stream, time_t &value) + { + stream.read(sizeof(value), &value); + } + static void Deserialize(IStream &stream, time_t *&value) + { + value = new time_t; + stream.read(sizeof(*value), value); + } + + // bool + static void Deserialize(IStream &stream, bool &value) + { + stream.read(sizeof(value), &value); + } + static void Deserialize(IStream &stream, bool *&value) + { + value = new bool; + stream.read(sizeof(*value), value); + } + + template + static void Deserialize(IStream &stream, std::basic_string &str) + { + int length; + stream.read(sizeof(length), &length); + std::vector buf(length); + stream.read(length * sizeof(T), buf.data()); + str = std::basic_string(buf.data(), buf.data() + length); + } + + template + static void Deserialize(IStream &stream, std::basic_string *&str) + { + int length; + stream.read(sizeof(length), &length); + std::vector buf(length); + stream.read(length * sizeof(T), buf.data()); + str = new std::basic_string(buf.data(), buf.data() + length); + } + + // STL templates + + // std::list + template + static void Deserialize(IStream &stream, std::list &list) + { + int length; + stream.read(sizeof(length), &length); + + for (int i = 0; i < length; ++i) { + T obj; + Deserialize(stream, obj); + list.push_back(std::move(obj)); + } + } + template + static void Deserialize(IStream &stream, std::list *&list) + { + list = new std::list; + Deserialize(stream, *list); + } + + template + static void Deserialize(IStream &stream, std::set &set) + { + size_t len; + stream.read(sizeof(len), &len); + + for (size_t i = 0; i < len; ++i) { + T obj; + Deserialize(stream, obj); + set.insert(std::move(obj)); + } + } + template + static void Deserialize(IStream &stream, std::set *&set) + { + set = new std::set; + Deserialize(stream, *set); + } + + // RawBuffer + template + static void Deserialize(IStream &stream, std::vector &vec) + { + int length; + stream.read(sizeof(length), &length); + vec.resize(length); + stream.read(length, vec.data()); + } + + template + static void Deserialize(IStream &stream, std::vector *&vec) + { + vec = new std::vector; + Deserialize(stream, *vec); + } + + // std::vector + template + static void Deserialize(IStream &stream, std::vector &vec) + { + int length; + stream.read(sizeof(length), &length); + + for (int i = 0; i < length; ++i) { + T obj; + Deserialize(stream, obj); + vec.push_back(std::move(obj)); + } + } + template + static void Deserialize(IStream &stream, std::vector *&vec) + { + vec = new std::vector; + Deserialize(stream, *vec); + } + + // std::pair + template + static void Deserialize(IStream &stream, std::pair &p) + { + Deserialize(stream, p.first); + Deserialize(stream, p.second); + } + template + static void Deserialize(IStream &stream, std::pair *&p) + { + p = new std::pair; + Deserialize(stream, *p); + } + + // std::map + template + static void Deserialize(IStream &stream, std::map &map) + { + int length; + stream.read(sizeof(length), &length); + + for (int i = 0; i < length; ++i) { + K key; + T obj; + Deserialize(stream, key); + Deserialize(stream, obj); + map[key] = std::move(obj); + } + } + template + static void Deserialize(IStream &stream, std::map *&map) + { + map = new std::map; + Deserialize(stream, *map); + } + + // std::unordered_map + template + static void Deserialize(IStream &stream, std::unordered_map &map) + { + size_t length; + stream.read(sizeof(length), &length); + + for (size_t i = 0; i < length; ++i) { + K key; + T obj; + Deserialize(stream, key); + Deserialize(stream, obj); + map[key] = std::move(obj); + } + } + template + static void Deserialize(IStream &stream, std::unordered_map *&map) + { + map = new std::map; + Deserialize(stream, *map); + } +}; // struct Deserialization + +// generic serialization +template +struct Serializer; + +template +struct Serializer : public Serializer { + static void Serialize(IStream &stream, const First &f, const Args &... args) + { + Serialization::Serialize(stream, f); + Serializer::Serialize(stream, args...); + } +}; + +// end of recursion +template <> +struct Serializer<> { + static void Serialize(IStream &) + { + return; + } +}; + +// generic deserialization +template +struct Deserializer; + +template +struct Deserializer : public Deserializer { + static void Deserialize(IStream &stream, First &f, Args &... args) + { + Deserialization::Deserialize(stream, f); + Deserializer::Deserialize(stream, args...); + } +}; + +// end of recursion +template <> +struct Deserializer<> { + static void Deserialize(IStream &) + { + return; + } +}; + +} // namespace Common +} // namespace CCHECKER diff --git a/src/common/service.cpp b/src/common/service.cpp new file mode 100644 index 0000000..49f2408 --- /dev/null +++ b/src/common/service.cpp @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2016 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 + */ +/* + * @file service.cpp + * @author Kyungwook Tak (k.tak@samsung.com) + * @author Sangwan Kwon (sangwan.kwon@samsung.com) + * @version 1.0 + * @brief + */ +#include "common/service.h" + +#include +#include + +#include + +namespace CCHECKER { + +Service::Service(const std::string &address) : m_address(address) +{ + LogDebug("Service constructed with address[" << address << "]"); + + m_timeout = -1; + setNewConnectionCallback(nullptr); + setCloseConnectionCallback(nullptr); +} + +Service::~Service() +{ +} + +void Service::start() +{ + LogInfo("Service start!"); + + Socket socket(m_address); + + LogDebug("Get systemd socket[" << socket.getFd() + << "] with address[" << m_address << "]"); + + m_loop.addEventSource(socket.getFd(), EPOLLIN | EPOLLHUP | EPOLLRDHUP, + [&](uint32_t event) { + if (event != EPOLLIN) + return; + + m_onNewConnection(std::make_shared(socket.accept())); + }); + + m_loop.run(m_timeout); +} + +void Service::stop() +{ + LogInfo("Service stop!"); +} + +void Service::setNewConnectionCallback(const ConnCallback &/*callback*/) +{ + /* TODO: scoped-lock */ + m_onNewConnection = [&](const ConnShPtr & connection) { + if (!connection) + throw std::logic_error("onNewConnection called but ConnShPtr is nullptr."); + + int fd = connection->getFd(); + + LogInfo("welcome! accepted client socket fd[" << fd << "]"); + + /* + // TODO: disable temporarily + if (callback) + callback(connection); + */ + + m_loop.addEventSource(fd, EPOLLIN | EPOLLHUP | EPOLLRDHUP, + [ &, fd](uint32_t event) { + LogDebug("read event comes in to fd[" << fd << "]"); + + if (m_connectionRegistry.count(fd) == 0) + throw std::logic_error("get event on fd, but no associated connection exist"); + + auto &conn = m_connectionRegistry[fd]; + + if (event & (EPOLLHUP | EPOLLRDHUP)) { + LogDebug("event of epoll hup. close connection on fd[" << fd << "]"); + m_onCloseConnection(conn); + return; + } + + LogDebug("Start message process on fd[" << fd << "]"); + + onMessageProcess(conn); + }); + + m_connectionRegistry[fd] = connection; + }; +} + +void Service::setCloseConnectionCallback(const ConnCallback &/*callback*/) +{ + /* TODO: scoped-lock */ + m_onCloseConnection = [&](const ConnShPtr & connection) { + if (!connection) + throw std::logic_error("no connection to close"); + + int fd = connection->getFd(); + + if (m_connectionRegistry.count(fd) == 0) + throw std::logic_error("no connection in registry to remove."); + + LogInfo("good-bye! close socket fd[" << fd << "]"); + + m_loop.removeEventSource(fd); + m_connectionRegistry.erase(fd); /* scoped-lock needed? */ + + /* + // TODO: disable temporarily + if (callback) + callback(connection); + */ + }; +} + +void Service::setTimeout(int timeout) +{ + m_timeout = timeout; +} + +} // namespace CCHECKER diff --git a/src/common/service.h b/src/common/service.h new file mode 100644 index 0000000..3297b78 --- /dev/null +++ b/src/common/service.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2016 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 + */ +/* + * @file service.h + * @author Kyungwook Tak (k.tak@samsung.com) + * @author Sangwan Kwon (sangwan.kwon@samsung.com) + * @version 1.0 + * @brief + */ +#pragma once + +#include +#include + +#include "common/connection.h" +#include "common/mainloop.h" + +namespace CCHECKER { + +using ConnCallback = std::function; + +class Service { +public: + Service(const std::string &address); + virtual ~Service(); + + Service(const Service &) = delete; + Service &operator=(const Service &) = delete; + Service(Service &&) = delete; + Service &operator=(Service &&) = delete; + + virtual void start(void) final; + virtual void stop(void) final; + + /* ConnCallback param should throw exception to handle error */ + virtual void setNewConnectionCallback(const ConnCallback &) final; + virtual void setCloseConnectionCallback(const ConnCallback &) final; + + virtual void setTimeout(int timeout) final; + +private: + virtual void onMessageProcess(const ConnShPtr &) = 0; + + ConnCallback m_onNewConnection; + ConnCallback m_onCloseConnection; + + int m_timeout; + std::unordered_map m_connectionRegistry; + Mainloop m_loop; + std::string m_address; +}; + +} // namespace CCHECKER diff --git a/src/common/socket.cpp b/src/common/socket.cpp new file mode 100644 index 0000000..a829484 --- /dev/null +++ b/src/common/socket.cpp @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2016 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 + */ +/* + * @file socket.cpp + * @author Kyungwook Tak (k.tak@samsung.com) + * @version 1.0 + * @brief + */ +#include "common/socket.h" + +#include +#include + +#include +#include +#include +#include + +#include + +#include + +namespace { + +int createSystemdSocket(const std::string &path) +{ + int n = ::sd_listen_fds(-1); + + if (n < 0) + throw std::system_error(std::error_code(), "failed to sd_listen_fds"); + + for (int fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; ++fd) { + if (::sd_is_socket_unix(fd, SOCK_STREAM, 1, path.c_str(), 0) > 0) { + LogInfo("service's systemd socket found with fd: " << fd); + return fd; + } + } + + throw std::system_error(std::error_code(), "get systemd socket failed!"); +} + +} // namespace anonymous + +namespace CCHECKER { + +Socket::Socket(int fd) : m_fd(fd) +{ + if (m_fd < 0) + throw std::logic_error("Socket fd from constructor is invalid!!"); +} + +Socket::Socket(const std::string &path) : m_fd(createSystemdSocket(path)) +{ +} + +Socket::Socket(Socket &&other) +{ + if (other.m_fd < 0) + throw std::logic_error("Socket fd from move constructor is invalid!!"); + + m_fd = other.m_fd; + other.m_fd = 0; +} + +Socket &Socket::operator=(Socket &&other) +{ + if (this == &other) + return *this; + + if (other.m_fd < 0) + throw std::logic_error("Socket fd from move assignment is invalid!!"); + + m_fd = other.m_fd; + other.m_fd = 0; + + return *this; +} + +Socket::~Socket() +{ + if (m_fd == 0) + return; + + LogInfo("Close socket of fd: " << m_fd); + ::close(m_fd); +} + +Socket Socket::accept() const +{ + int fd = ::accept(m_fd, nullptr, nullptr); + + if (fd < 0) + throw std::system_error( + std::error_code(errno, std::generic_category()), + "socket accept failed!"); + + LogInfo("Accept client success with fd: " << fd); + + return Socket(fd); +} + +Socket Socket::connect(const std::string &path) +{ + if (path.size() >= sizeof(sockaddr_un::sun_path)) + throw std::invalid_argument("socket path size too long!"); + + int fd = ::socket(AF_UNIX, SOCK_STREAM, 0); + + if (fd < 0) + throw std::system_error( + std::error_code(errno, std::generic_category()), + "socket create failed!"); + + sockaddr_un addr; + addr.sun_family = AF_UNIX; + + strncpy(addr.sun_path, path.c_str(), sizeof(addr.sun_path)); + + if (::connect(fd, reinterpret_cast(&addr), + sizeof(sockaddr_un)) == -1) + throw std::system_error( + std::error_code(errno, std::generic_category()), + "socket connect failed!"); + + LogInfo("Connect to CSR server success with fd:" << fd); + + return Socket(fd); +} + +int Socket::getFd() const +{ + return m_fd; +} + +RawBuffer Socket::read(void) const +{ + size_t total = 0; + + RawBuffer data(1024, 0); + auto buf = reinterpret_cast(data.data()); + auto size = data.size(); + + LogDebug("Read data from stream on socket fd[" << m_fd << "]"); + + while (total < size) { + int bytes = ::read(m_fd, buf + total, size - total); + + if (bytes < 0) { + if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) + continue; + else + throw std::system_error( + std::error_code(errno, std::generic_category()), + "socket read failed!"); + } + + /* TODO: handle the case of more bytes in stream to read than buffer size */ + total += bytes; + break; + } + + data.resize(total); + + LogDebug("Read data of size[" << total + << "] from stream on socket fd[" << m_fd << "] done."); + + return data; +} + +void Socket::write(const RawBuffer &data) const +{ + size_t total = 0; + + auto buf = reinterpret_cast(data.data()); + auto size = data.size(); + + LogDebug("Write data to stream on socket fd[" << m_fd << "]"); + + while (total < size) { + int bytes = ::write(m_fd, buf + total, size - total); + + if (bytes < 0) { + if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) + continue; + else + throw std::system_error( + std::error_code(errno, std::generic_category()), + "socket write failed!"); + } + + total += bytes; + } + + LogDebug("Write data of size[" << total << + "] to stream on socket fd[" << m_fd << "] done."); +} + +} // namespace CCHECKER diff --git a/src/common/socket.h b/src/common/socket.h new file mode 100644 index 0000000..6283cba --- /dev/null +++ b/src/common/socket.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2016 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 + */ +/* + * @file socket.h + * @author Kyungwook Tak (k.tak@samsung.com) + * @version 1.0 + * @brief + */ +#pragma once + +#include + +#include "common/types.h" + +namespace CCHECKER { + +class Socket { +public: + Socket(int fd = 0); + Socket(const std::string &path); /* Construct with systemd socket from path */ + + Socket(const Socket &) = delete; + Socket &operator=(const Socket &) = delete; + + Socket(Socket &&); + Socket &operator=(Socket &&); + + virtual ~Socket(); + + Socket accept(void) const; + int getFd(void) const; + + RawBuffer read(void) const; + void write(const RawBuffer &data) const; + + /* TODO: can it be constructor? */ + static Socket connect(const std::string &path); + +private: + int m_fd; +}; + +} diff --git a/src/common/types.h b/src/common/types.h new file mode 100644 index 0000000..b00419b --- /dev/null +++ b/src/common/types.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2016 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 + */ +/* + * @file types.h + * @author Kyungwook Tak (k.tak@samsung.com) + * @version 1.0 + * @brief Typedefs of primitives + */ +#pragma once + +#include + +namespace CCHECKER { + +using RawBuffer = std::vector; + +} // namespace CCHECKER diff --git a/src/include/cchecker/UIBackend.h b/src/include/cchecker/UIBackend.h index 6133078..659adb8 100644 --- a/src/include/cchecker/UIBackend.h +++ b/src/include/cchecker/UIBackend.h @@ -21,7 +21,7 @@ #pragma once -#include +#include "service/app.h" namespace CCHECKER { namespace UI { diff --git a/src/include/cchecker/app.h b/src/include/cchecker/app.h deleted file mode 100644 index df4a860..0000000 --- a/src/include/cchecker/app.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2015 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. - */ -/* - * @file app.h - * @author Janusz Kozerski (j.kozerski@samsung.com) - * @version 1.0 - * @brief This file is the implementation of app struct - */ -#ifndef CCHECKER_APP_H -#define CCHECKER_APP_H - -#include -#include -#include - -namespace CCHECKER { - -// Used as app_id when no information about app id in signal -// Currently in signals from pkgmgr only information about pkg_id is included -const char *const TEMP_APP_ID = "temp#app_id"; - -typedef std::list chain_t; -typedef std::list signatures_t; - -struct app_t { - enum class verified_t : int32_t { - NO = 0, - YES = 1, - UNKNOWN = 2 - }; - - std::string app_id; - std::string pkg_id; - uid_t uid; - signatures_t signatures; - verified_t verified; - - app_t(void); - app_t(const std::string &app_id, - const std::string &pkg_id, - uid_t uid, - const signatures_t &signatures); - std::string str(void) const; - std::string str_certs(void) const; -}; - -} //CCHECKER - -#endif //CCHECKER_APP_H diff --git a/src/include/cchecker/certs.h b/src/include/cchecker/certs.h deleted file mode 100644 index 0cb9135..0000000 --- a/src/include/cchecker/certs.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2015 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. - */ -/* - * @file certs.h - * @author Janusz Kozerski (j.kozerski@samsung.com) - * @version 1.0 - * @brief This file is the implementation of certificates logic - * Getting out findinf app signature, getting certificates out of - * signature. Checking OCSP - */ - -#ifndef CCHECKER_CERTS_H -#define CCHECKER_CERTS_H - -#include -#include - -#include -#include - -namespace CCHECKER { - -enum sig_t { - AUTHOR_SIG, - DISTRIBUTOR_SIG, - DISTRIBUTOR2_SIG -}; - -class Certs { - public: - enum class ocsp_response_t { - OCSP_APP_OK, - OCSP_APP_REVOKED, - OCSP_CHECK_AGAIN, - OCSP_CERT_ERROR - }; - Certs(); - virtual ~Certs(); - void get_certificates (app_t &app); - ocsp_response_t check_ocsp (const app_t &app); - - protected: // Needed for tests - ocsp_response_t check_ocsp_chain (const chain_t &chain); - - //private: - CKM::ManagerShPtr m_ckm; -}; - -} // CCHECKER - - -#endif // CCHECKER_CERTS_H diff --git a/src/include/cchecker/logic.h b/src/include/cchecker/logic.h deleted file mode 100644 index 888fe07..0000000 --- a/src/include/cchecker/logic.h +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (c) 2015 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. - */ -/* - * @file logic.h - * @author Janusz Kozerski (j.kozerski@samsung.com) - * @version 1.0 - * @brief This file is the implementation of SQL queries - */ - -#ifndef CCHECKER_LOGIC_H -#define CCHECKER_LOGIC_H - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -namespace CCHECKER { - -namespace DB { -class SqlQuery; -} - -enum error_t { - NO_ERROR, - REGISTER_CALLBACK_ERROR, - DBUS_ERROR, - PACKAGE_MANAGER_ERROR, - DATABASE_ERROR, - INTERNAL_ERROR -}; - -enum pkgmgr_event_t { - EVENT_INSTALL, - EVENT_UNINSTALL -}; - -class Logic { - public: - Logic(void); - virtual ~Logic(void); - error_t setup(void); - virtual void clean(void); - - static void connman_callback(GDBusProxy *proxy, - gchar *sender_name, - gchar *signal_name, - GVariant *parameters, - void *logic_ptr); - - protected: - error_t setup_db(); - void load_database_to_buffer(); - - void add_app_to_buffer_and_database(const app_t &app); - void remove_app_from_buffer_and_database(const app_t &app); - - void set_connman_online_state(); - error_t register_dbus_signal_handler(GDBusProxy **proxy, - const char *name, - const char *object_path, - const char *interface_name, - void (*callback) (GDBusProxy *proxy, - gchar *sender_name, - gchar *signal_name, - GVariant *parameters, - void *logic_ptr) - ); - - static int pkgmgrinfo_event_handler_static( - uid_t uid, - int reqid, - const char *pkgtype, - const char *pkgid, - const char *key, - const char *val, - const void *pmsg, - void *data); - - int pkgmgrinfo_event_handler( - uid_t uid, - int reqid, - const char *pkgtype, - const char *pkgid, - const char *key, - const char *val, - const void *pmsg, - void *data); - - int push_pkgmgrinfo_event(uid_t uid, const char *pkgid); - - void push_event(event_t event); - - void process_all(void); - void process_queue(void); - virtual void process_event(const event_t &event); - - bool process_app(app_t& app); - void process_buffer(void); - virtual void app_processed() {}; // for tests - - bool get_online(void) const; - void set_online(bool online); - - bool get_should_exit(void) const; - void set_should_exit(void); - - bool call_ui(const app_t &app); - - Queue m_queue; - Certs m_certs; - std::list m_buffer; - DB::SqlQuery *m_sqlquery; - bool m_was_setup_called; - - bool m_is_online; - // TODO: use m_queue for online events - bool m_is_online_enabled; - std::condition_variable m_to_process; - std::mutex m_mutex_cv; - std::thread m_thread; - bool m_should_exit; - - GDBusProxy *m_proxy_connman; - - int m_reqid_install; - int m_reqid_uninstall; - std::unique_ptr m_pc_install; - std::unique_ptr m_pc_uninstall; -}; - -} // CCHECKER - -#endif //CCHECKER_LOGIC_H diff --git a/src/include/cchecker/queue.h b/src/include/cchecker/queue.h deleted file mode 100644 index 7100265..0000000 --- a/src/include/cchecker/queue.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2015 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. - */ -/* - * @file queue.h - * @author Janusz Kozerski (j.kozerski@samsung.com) - * @version 1.0 - * @brief This file is the implementation of thread-safe queue - */ - -#ifndef CCHECKER_QUEUE_H -#define CCHECKER_QUEUE_H - -#include -#include - -#include - -namespace CCHECKER { - -struct event_t { - enum class event_type_t { - APP_INSTALL, - APP_UNINSTALL, - EVENT_TYPE_UNKNOWN - }; - - event_type_t event_type; - app_t app; - - event_t(); - event_t(const app_t &app, event_type_t type); -}; - -class Queue { - public: - void push_event(const event_t &event); - bool pop_event(event_t &event); - bool empty(); - - private: - std::mutex m_mutex; - std::queue m_event_list; -}; - -} // CCHECKER - -#endif // CCHECKER_QUEUE_H diff --git a/src/include/cchecker/sql_query.h b/src/include/cchecker/sql_query.h index fd28fd5..6338561 100644 --- a/src/include/cchecker/sql_query.h +++ b/src/include/cchecker/sql_query.h @@ -24,7 +24,7 @@ #include #include -#include +#include "service/app.h" namespace CCHECKER { namespace DB { diff --git a/src/logic.cpp b/src/logic.cpp deleted file mode 100644 index 181ebea..0000000 --- a/src/logic.cpp +++ /dev/null @@ -1,624 +0,0 @@ -/* - * Copyright (c) 2015 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. - */ -/* - * @file logic.cpp - * @author Janusz Kozerski (j.kozerski@samsung.com) - * @version 1.0 - * @brief This file is the implementation of SQL queries - */ -#include - -#include -#include -#include -#include - -#include - -using namespace std; - -namespace CCHECKER { - -namespace { -struct PkgmgrinfoEvent { - PkgmgrinfoEvent(uid_t _uid, const char *_pkgid) - : uid(_uid) - , pkgid(_pkgid) {} - - inline bool operator==(const PkgmgrinfoEvent &rhs) const - { - return uid == rhs.uid && pkgid.compare(rhs.pkgid) == 0; - } - - inline bool operator<(const PkgmgrinfoEvent &rhs) const - { - if (uid < rhs.uid) - return true; - else if (uid < rhs.uid) - return false; - else - return pkgid.compare(rhs.pkgid) < 0; - } - - inline bool operator>(const PkgmgrinfoEvent &rhs) const - { - if (uid > rhs.uid) - return true; - else if (uid < rhs.uid) - return false; - else - return pkgid.compare(rhs.pkgid) > 0; - } - - uid_t uid; - std::string pkgid; - pkgmgr_event_t type; -}; - -std::set pkgmgrinfo_event_set; -const char *const DB_PATH = DB_INSTALL_DIR"/.cert-checker.db"; -} - -Logic::~Logic(void) -{ - clean(); -} - -void Logic::clean(void) -{ - LogDebug("Cert-checker cleaning."); - - // wait and join processing thread - if (m_thread.joinable()) { - LogDebug("Waiting for join processing thread"); - { - std::lock_guard lock(m_mutex_cv); - set_should_exit(); - m_to_process.notify_one(); - } - m_thread.join(); - LogDebug("Processing thread joined"); - } - else - LogDebug("No thread to join"); - - if (m_proxy_connman) - g_object_unref(m_proxy_connman); - - delete m_sqlquery; -} - -Logic::Logic(void) : - m_sqlquery(NULL), - m_was_setup_called(false), - m_is_online(false), - m_is_online_enabled(false), - m_should_exit(false), - m_proxy_connman(NULL), - m_pc_install(nullptr, nullptr), - m_pc_uninstall(nullptr, nullptr) -{} - -bool Logic::get_online() const -{ - return m_is_online; -} - -void Logic::set_online(bool online) -{ - std::lock_guard lock(m_mutex_cv); - if (m_is_online == online) - return; - m_is_online = online; - if (m_is_online) { - m_is_online_enabled = true; - m_to_process.notify_one(); - } -} - -error_t Logic::setup_db() -{ - // TODO: If database doesn't exist -should we create a new one? - Try { - m_sqlquery = new DB::SqlQuery(DB_PATH); - } Catch (runtime_error) { - LogError("Error while creating SqlQuery object"); - return DATABASE_ERROR; - } - - if(!m_sqlquery) { - LogError("Cannot open database"); - return DATABASE_ERROR; - } - - return NO_ERROR; -} - -error_t Logic::setup() -{ - // Check if setup was called - if (m_was_setup_called) { - LogError("You can call setup only once"); - return INTERNAL_ERROR; - } - m_was_setup_called = true; - - // Check if DB exists and create a new one if it doesn't - error_t err = setup_db(); - if (err != NO_ERROR) { - LogError("Database error"); - return err; - } - - load_database_to_buffer(); - - // run process thread - thread will be waiting on condition variable - m_thread = std::thread(&Logic::process_all, this); - - // Add connman callback - LogDebug("register connman event callback start"); - if (register_dbus_signal_handler(&m_proxy_connman, - "net.connman", - "/", - "net.connman.Manager", - connman_callback) != NO_ERROR) { - LogError("Error in register_connman_signal_handler"); - return REGISTER_CALLBACK_ERROR; - } - LogDebug("register connman event callback success"); - - set_connman_online_state(); - - // Add pkgmgrinfo callback - LogDebug("Register package event handler start"); - - std::unique_ptr - _pcInstall(pkgmgrinfo_client_new(PMINFO_LISTENING), pkgmgrinfo_client_free); - std::unique_ptr - _pcUninstall(pkgmgrinfo_client_new(PMINFO_LISTENING), pkgmgrinfo_client_free); - m_pc_install = std::move(_pcInstall); - m_pc_uninstall = std::move(_pcUninstall); - - if (!m_pc_install || !m_pc_uninstall) { - LogError("Get pkgmgrinfo client failed"); - return REGISTER_CALLBACK_ERROR; - } - - int ret_status_install; - int ret_status_uninstall; - ret_status_install = pkgmgrinfo_client_set_status_type( - m_pc_install.get(), PKGMGR_CLIENT_STATUS_INSTALL); - ret_status_uninstall = pkgmgrinfo_client_set_status_type( - m_pc_uninstall.get(), PKGMGR_CLIENT_STATUS_UNINSTALL); - - if (ret_status_install == PMINFO_R_ERROR || ret_status_uninstall == PMINFO_R_ERROR) { - LogError("Set pkgmgrinfo status fail"); - return REGISTER_CALLBACK_ERROR; - } - m_reqid_install = pkgmgrinfo_client_listen_status( - m_pc_install.get(), pkgmgrinfo_event_handler_static, this); - m_reqid_uninstall = pkgmgrinfo_client_listen_status( - m_pc_uninstall.get(), pkgmgrinfo_event_handler_static, this); - - if (m_reqid_install < 0 || m_reqid_uninstall < 0) { - LogError("Register pacakge install event handler fail"); - return REGISTER_CALLBACK_ERROR; - } - - LogDebug("Register package event handler success"); - - return NO_ERROR; -} - -int Logic::pkgmgrinfo_event_handler_static( - uid_t uid, - int reqid, - const char *pkgtype, - const char *pkgid, - const char *key, - const char *val, - const void *pmsg, - void *data) -{ - LogDebug("pkgmgrinfo event handler start!!"); - if (data == nullptr) - return -1; - - std::string keyStr(key); - std::string valStr(val); - LogDebug("pkgmgrinfo event was caught. type : " << valStr << ", status : " << keyStr); - - if ((valStr.compare("install") == 0 || valStr.compare("uninstall") == 0) - && keyStr.compare("start") == 0) { - return static_cast(data)->pkgmgrinfo_event_handler( - uid, reqid, pkgtype, pkgid, key, val, pmsg, data); - } else if (keyStr.compare("end") == 0 && valStr.compare("ok") == 0) { - return static_cast(data)->push_pkgmgrinfo_event(uid, pkgid); - } else { - LogDebug("Untreated event was caught : " << val); - return -1; - } -} - -int Logic::pkgmgrinfo_event_handler( - uid_t uid, - int reqid, - const char */*pkgtype*/, - const char *pkgid, - const char *key, - const char *val, - const void */*pmsg*/, - void */*data*/) -{ - if (pkgid == nullptr || key == nullptr || val == nullptr) { - LogError("Invalid parameter."); - return -1; - } - - std::string keyStr(key); - std::string valStr(val); - - LogDebug("uid: " << uid << " pkgid: " << pkgid << " key: " << keyStr << " val: " << valStr); - - PkgmgrinfoEvent event(uid, pkgid); - - if(valStr.compare("install") == 0) { - if (reqid != m_reqid_install) { - LogError("pkgmgrinfo event reqid unmatched"); - return -1; - } - event.type = EVENT_INSTALL; - } else if(valStr.compare("uninstall") == 0) { - if (reqid != m_reqid_uninstall) { - LogError("pkgmgrinfo event reqid unmatched"); - return -1; - } - event.type = EVENT_UNINSTALL; - } - - pkgmgrinfo_event_set.insert(event); - - return 0; -} - -int Logic::push_pkgmgrinfo_event(uid_t uid, const char *pkgid) -{ - PkgmgrinfoEvent event(uid, pkgid); - std::set::iterator pkgmgrinfo_event_iter = pkgmgrinfo_event_set.find(event); - - if (pkgmgrinfo_event_iter != pkgmgrinfo_event_set.end()) { - // FIXME: No information about app_id in the signal. Use stub. - app_t app(TEMP_APP_ID, pkgid, uid, {}); - - if (pkgmgrinfo_event_iter->type == EVENT_INSTALL) { - LogDebug("Successfully Installed. uid: " << uid << ", pkgid: " << pkgid); - push_event(event_t(app, event_t::event_type_t::APP_INSTALL)); - } else if (pkgmgrinfo_event_iter->type == EVENT_UNINSTALL) { - LogDebug("Successfully Uninstalled. uid: " << uid << ", pkgid: " << pkgid); - push_event(event_t(app, event_t::event_type_t::APP_UNINSTALL)); - } - - LogDebug("push pkgmgrifo success. pkgid: " << pkgid << ", uid: " << uid); - pkgmgrinfo_event_set.erase(event); - return 0; - } else { - // if update status, return fail - LogDebug("push pkgmgrifo fail. pkgid: " << pkgid << ", uid: " << uid); - return -1; - } -} - -error_t Logic::register_dbus_signal_handler(GDBusProxy **proxy, - const char *name, - const char *object_path, - const char *interface_name, - void (*callback) (GDBusProxy *proxy, - gchar *sender_name, - gchar *signal_name, - GVariant *parameters, - void *logic_ptr) - ) -{ - GError *error = NULL; - GDBusProxyFlags flags = G_DBUS_PROXY_FLAGS_NONE; - - // Obtain a connection to the System Bus - *proxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM, - flags, - NULL, /* GDBusInterfaceInfo */ - name, - object_path, - interface_name, - NULL, /* GCancellable */ - &error); - - if (*proxy == NULL) { - if (error) { - LogError("Error creating D-Bus proxy for /'" << interface_name <<"/': " << error->message); - g_error_free(error); - } else { - LogError("Error creating D-Bus proxy for /'" << interface_name <<"/'. Unknown error"); - } - return DBUS_ERROR; - } - - // Connect to g-signal to receive signals from proxy - if (g_signal_connect(*proxy, "g-signal", G_CALLBACK(callback), this) < 1) { - LogError("g_signal_connect error while connecting " << interface_name); - return REGISTER_CALLBACK_ERROR; - } - - return NO_ERROR; -} - -void Logic::set_connman_online_state() -{ - GError *error = NULL; - GVariant *response; - - if (m_proxy_connman == NULL) { - LogError("connman proxy is NULL"); - return; - } - - response = g_dbus_proxy_call_sync (m_proxy_connman, - "GetProperties", - NULL, // GetProperties gets no parameters - G_DBUS_CALL_FLAGS_NONE, - -1, // Default timeout - NULL, - &error); - - if (error) { - LogError("Error while calling connman GetProperties() Dbus API: " << error->message); - g_error_free(error); - return; - } - - if (response == NULL) { - // This should never happen - return; - } - - gchar *resp_g = g_variant_print(response, TRUE); - std::string resp_s(resp_g); - LogDebug("response: " << resp_s); - g_free(resp_g); - - // Response should look like this: - // ({'State': <'online'>, 'OfflineMode': , 'SessionMode': },) - if (resp_s.find("'State': <'online'>", 0) != std::string::npos) { - LogDebug("Connman has returned: online"); - set_online(true); - } - - // free memory - g_variant_unref(response); -} - -void Logic::connman_callback(GDBusProxy */*proxy*/, - gchar */*sender_name*/, - gchar *signal_name, - GVariant *parameters, - void *logic_ptr) -{ - string signal_name_str = string(signal_name); - if (signal_name_str != "PropertyChanged") { - // Invalid param. Nothing to do here. - return; - } - - gchar *parameters_g = g_variant_print(parameters, TRUE); - string params_str = string(parameters_g); - g_free (parameters_g); - - Logic *logic = static_cast (logic_ptr); - - if (params_str == "('State', <'online'>)") { - LogDebug("Device online"); - logic->set_online(true); - logic->m_to_process.notify_one(); - } - else if (params_str == "('State', <'offline'>)") { - LogDebug("Device offline"); - logic->set_online(false); - } -} - -void Logic::load_database_to_buffer() -{ - LogDebug("Loading database to the buffer"); - m_sqlquery->get_app_list(m_buffer); -} - -/** - * This function should move all event from queue to the buffer - **/ -void Logic::process_queue(void) -{ - event_t event; - while(m_queue.pop_event(event)) { - process_event(event); - } -} - -bool Logic::call_ui(const app_t &app) -{ - UI::UIBackend ui; - - if (ui.call_popup(app)) { // If calling popup or app_controll service will fail, - // do not remove application, and ask about it once again later - LogDebug("Popup shown correctly. Application will be removed from DB and buffer"); - return true; - } - LogDebug("Popup error. Application will be marked to show popup later."); - return false; -} - -bool Logic::process_app(app_t& app) { - // Check if app hasn't already been verified. - // If yes then just try to display popup once again, and go the next app. -#if POPUP - if (app.verified == app_t::verified_t::NO) { - LogDebug(app.str() << " has been verified before. Popup should be shown."); - return call_ui(app); - } -#endif - - Certs::ocsp_response_t ret; - ret = m_certs.check_ocsp(app); - - // If OCSP returns success or OCSP checking fails we should remove application from buffer and database - if (ret == Certs::ocsp_response_t::OCSP_APP_OK || - ret == Certs::ocsp_response_t::OCSP_CERT_ERROR) { - LogDebug(app.str() << " OCSP verified (or not available for app's chains)"); - return true; - } - else if (ret == Certs::ocsp_response_t::OCSP_APP_REVOKED) { - LogDebug(app.str() << " certificate has been revoked. Popup should be shown"); - app.verified = app_t::verified_t::NO; -#if POPUP -// Do not remove app here - just waits for user answer from popup - return call_ui(app); -#else - return true; -#endif - } - else { - LogDebug(app.str() << " should be checked again later"); - // If check_ocsp returns Certs::ocsp_response_t::OCSP_CHECK_AGAIN - // app should be checked again later - } - return false; -} - -void Logic::process_buffer(void) -{ - for (auto iter = m_buffer.begin(); iter != m_buffer.end();) { - bool remove = process_app(*iter); - auto prev = *iter; - iter++; - if (remove) - remove_app_from_buffer_and_database(prev); - app_processed(); - } -} - -void Logic::push_event(event_t event) -{ - std::lock_guard lock(m_mutex_cv); - m_queue.push_event(std::move(event)); - m_to_process.notify_one(); -} - -void Logic::process_all() -{ - for(;;) { - std::unique_lock lock(m_mutex_cv); - if (m_should_exit) - break; //lock will be unlocked upon destruction - - // don't sleep if there are online/installation/deinstallation events to process - if(m_queue.empty() && !m_is_online_enabled) { - LogDebug("Processing thread: waiting on condition"); - m_to_process.wait(lock); // spurious wakeups do not concern us - LogDebug("Processing thread: running"); - } - - m_is_online_enabled = false; - lock.unlock(); - - process_queue(); - if (get_online()) - process_buffer(); - else - LogDebug("No network. Buffer won't be processed"); - - LogDebug("Processing done"); - } -} - -void Logic::process_event(const event_t &event) -{ - if (event.event_type == event_t::event_type_t::APP_INSTALL) { - // pulling out certificates from signatures - app_t app = event.app; - m_certs.get_certificates(app); - add_app_to_buffer_and_database(app); - } - else if (event.event_type == event_t::event_type_t::APP_UNINSTALL) { - remove_app_from_buffer_and_database(event.app); - } - else - LogError("Unknown event type"); -} - -void Logic::add_app_to_buffer_and_database(const app_t &app) -{ - // First add app to DB - if(!m_sqlquery->add_app_to_check_list(app)) { - LogError("Failed to add " << app.str() << "to database"); - // We can do nothing about it. We can only log the error. - } - - // Then add app to buffer - skip if already added. - // FIXME: What to do if the same app will be installed twice? - // Add it twice to the buffer, or check if apps in buffer are unique? - // At the moment doubled apps are skipped. - for (auto &iter : m_buffer) { - if (iter.app_id == app.app_id && - iter.pkg_id == app.pkg_id && - iter.uid == app.uid) { - LogDebug(app.str() << " already in buffer. Skip."); - return; - } - } - - // Then add app to buffer - m_buffer.push_back(app); -} - -// Notice that this operator doesn't compare list of certificate, because it isn't needed here. -// This operator is implemented only for using in m_buffer.remove() method; -// Operator which compares certificates is implemented in tests. -bool operator ==(const app_t &app1, const app_t &app2) -{ - return app1.app_id == app2.app_id && - app1.pkg_id == app2.pkg_id && - app1.uid == app2.uid; -} - -void Logic::remove_app_from_buffer_and_database(const app_t &app) -{ - // First remove app from DB - m_sqlquery->remove_app_from_check_list(app); - - // Then remove app from buffer - m_buffer.remove(app); -} - -bool Logic::get_should_exit(void) const -{ - return m_should_exit; -} - -void Logic::set_should_exit(void) -{ - m_should_exit = true; - -} - -} //CCHECKER diff --git a/src/main/cert-checker.cpp b/src/main/cert-checker.cpp new file mode 100644 index 0000000..e4cdb44 --- /dev/null +++ b/src/main/cert-checker.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2015 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 + */ +/* + * @file cert-checker.cpp + * @author Janusz Kozerski (j.kozerski@samsung.com) + * @version 1.0 + * @brief Cert-checker daemon main loop. + */ + +#include + +#include + +#include "service/logic.h" +#include "service/ocsp-service.h" + +using namespace CCHECKER; + +int main(void) +{ + try { + LogInfo("Cert-checker start!"); + + CCHECKER::OcspService service(SERVICE_STREAM); + + setlocale(LC_ALL, ""); + + // Set timeout about socket read event. + service.setTimeout(50); + service.start(); + + LogInfo("Cert-checker exit!"); + return 0; + + } catch (const std::exception &e) { + LogError("Exception occured in cert-checker main : " << e.what()); + return -1; + } catch (...) { + LogError("Unhandled exception occured in cert-checker main."); + return -1; + } +} diff --git a/src/po/CMakeLists.txt b/src/po/CMakeLists.txt index b89f4cb..27eae39 100644 --- a/src/po/CMakeLists.txt +++ b/src/po/CMakeLists.txt @@ -37,7 +37,7 @@ FOREACH(pofile ${POFILES}) DEPENDS ${absPofile} ) INSTALL(FILES ${moFile} - DESTINATION ${LOCALEDIR}/${lang}/LC_MESSAGES RENAME ${PROJECT_NAME}.mo) + DESTINATION ${LOCALEDIR}/${lang}/LC_MESSAGES RENAME ${SERVICE_NAME}.mo) SET(moFiles ${moFiles} ${moFile}) ENDFOREACH(pofile) diff --git a/src/queue.cpp b/src/queue.cpp deleted file mode 100644 index d0ecb41..0000000 --- a/src/queue.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2015 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. - */ -/* - * @file queue.cpp - * @author Janusz Kozerski (j.kozerski@samsung.com) - * @version 1.0 - * @brief This file is the implementation of thread-safe queue - */ - -#include -#include - -#include - -namespace CCHECKER { - -event_t::event_t(): - event_type(event_type_t::EVENT_TYPE_UNKNOWN), - app() -{} - -event_t::event_t(const app_t &app, event_type_t type): - event_type(type), - app(app) -{} - -void Queue::push_event(const event_t &event) -{ - std::lock_guard lock(m_mutex); - m_event_list.push(event); -} - -bool Queue::pop_event(event_t &event) -{ - std::lock_guard lock(m_mutex); - if (m_event_list.empty()) - return false; - - event = std::move(m_event_list.front()); - m_event_list.pop(); - return true; -} - -bool Queue::empty() -{ - return m_event_list.empty(); -} - -} //CCHECKER diff --git a/src/service/app.cpp b/src/service/app.cpp new file mode 100644 index 0000000..a61f4a3 --- /dev/null +++ b/src/service/app.cpp @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2015 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. + */ +/* + * @file app.cpp + * @author Janusz Kozerski (j.kozerski@samsung.com) + * @version 1.0 + * @brief This file is the implementation of app struct + */ +#include "service/app.h" + +#include +#include +#include + +#include + +namespace CCHECKER { + +app_t::app_t(void): + uid((uid_t)-1), // (uid_t)-1 (0xFF) is defined to be invalid uid. According + // to chown manual page, you cannot change file group of owner + // to (uid_t)-1, so we'll use it as initial, invalid value. + verified(verified_t::UNKNOWN) +{} + +app_t::app_t(const std::string &app_id, + const std::string &pkg_id, + uid_t uid, + const signatures_t &signatures): + app_id(app_id), + pkg_id(pkg_id), + uid(uid), + signatures(signatures), + verified(verified_t::UNKNOWN) +{} + +std::ostream & operator<< (std::ostream &out, const app_t &app) +{ + out << "app: " << app.app_id << ", pkg: " << app.pkg_id << ", uid: " << app.uid; + return out; +} + +std::string app_t::str() const +{ + std::stringstream ss; + ss << *this; + return ss.str(); +} + +std::string app_t::str_certs(void) const +{ + std::stringstream ss; + + for (const auto &iter : signatures) { + ss << " { "; + for (const auto iter_cert : iter) { + ss << "\"" << iter_cert << "\", "; + } + ss << " } ,"; + } + return ss.str(); +} + +} //CCHECKER diff --git a/src/service/app.h b/src/service/app.h new file mode 100644 index 0000000..df4a860 --- /dev/null +++ b/src/service/app.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2015 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. + */ +/* + * @file app.h + * @author Janusz Kozerski (j.kozerski@samsung.com) + * @version 1.0 + * @brief This file is the implementation of app struct + */ +#ifndef CCHECKER_APP_H +#define CCHECKER_APP_H + +#include +#include +#include + +namespace CCHECKER { + +// Used as app_id when no information about app id in signal +// Currently in signals from pkgmgr only information about pkg_id is included +const char *const TEMP_APP_ID = "temp#app_id"; + +typedef std::list chain_t; +typedef std::list signatures_t; + +struct app_t { + enum class verified_t : int32_t { + NO = 0, + YES = 1, + UNKNOWN = 2 + }; + + std::string app_id; + std::string pkg_id; + uid_t uid; + signatures_t signatures; + verified_t verified; + + app_t(void); + app_t(const std::string &app_id, + const std::string &pkg_id, + uid_t uid, + const signatures_t &signatures); + std::string str(void) const; + std::string str_certs(void) const; +}; + +} //CCHECKER + +#endif //CCHECKER_APP_H diff --git a/src/service/certs.cpp b/src/service/certs.cpp new file mode 100644 index 0000000..248b867 --- /dev/null +++ b/src/service/certs.cpp @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2015 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. + */ +/* + * @file certs.cpp + * @author Janusz Kozerski (j.kozerski@samsung.com) + * @version 1.0 + * @brief This file is the implementation of certificates logic + * Getting out app signature, getting certificates out of + * signature. Checking OCSP + */ +#include "service/certs.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace CCHECKER { + +namespace { +struct PkgmgrinfoCertInfo { + PkgmgrinfoCertInfo() + { + ret = pkgmgrinfo_pkginfo_create_certinfo(&handle); + } + ~PkgmgrinfoCertInfo() + { + pkgmgrinfo_pkginfo_destroy_certinfo(handle); + } + + pkgmgrinfo_certinfo_h handle; + int ret; +}; + +static void get_cert_chain(const char *pkgid, uid_t uid, int sig_type, chain_t &chain) +{ + LogDebug("Get cert chain start. pkgid : " << pkgid << ", uid : " << uid); + int ret; + int cert_type; + const char *cert_value; + + auto pm_certinfo = std::make_shared(); + + if (pm_certinfo->ret != PMINFO_R_OK) { + LogError("Get pkgmgrinfo certinfo failed. ret : " << ret); + return; + } + + ret = pkgmgrinfo_pkginfo_load_certinfo(pkgid, pm_certinfo->handle, uid); + if (ret != PMINFO_R_OK) { + LogError("Load pkgmgrinfo certinfo failed. ret : " << ret); + return; + } + + // add signer, intermediate, root certificates. + for (int cert_cnt = 0; cert_cnt < 3; cert_cnt++) { + cert_type = sig_type - cert_cnt; + ret = pkgmgrinfo_pkginfo_get_cert_value(pm_certinfo->handle, + static_cast(cert_type), &cert_value); + + if (ret != PMINFO_R_OK) { + LogError("Get cert value from certinfo failed. ret : " << ret); + return; + } + + if (cert_value == NULL) { + LogDebug("cert_type[" << cert_type << "] is null"); + } else { + LogDebug("Add cert_type[" << cert_type << "] data : " << cert_value); + chain.push_back(cert_value); + } + } + + return; +} +} + +Certs::Certs() +{ + m_ckm = CKM::Manager::create(); +} + +Certs::~Certs() +{} + +void Certs::get_certificates(app_t &app) +{ + // build chain using pkgmgr-info + std::map sig_type; + sig_type[AUTHOR_SIG] = PMINFO_AUTHOR_SIGNER_CERT; + sig_type[DISTRIBUTOR_SIG] = PMINFO_DISTRIBUTOR_SIGNER_CERT; + sig_type[DISTRIBUTOR2_SIG] = PMINFO_DISTRIBUTOR2_SIGNER_CERT; + + for (auto s : sig_type) { + chain_t chain; + get_cert_chain(app.pkg_id.c_str(), app.uid, s.second, chain); + + if(!chain.empty()) { + LogDebug("Add certificates chain to app. Size of chain : " << chain.size()); + app.signatures.emplace_back(std::move(chain)); + } + } +} + +Certs::ocsp_response_t Certs::check_ocsp_chain(const chain_t &chain) +{ + CKM::CertificateShPtrVector vect_ckm_chain; + + LogDebug("Size of chain: " << chain.size()); + for (auto &iter : chain) { + CKM::RawBuffer buff(iter.begin(), iter.end()); + auto cert = CKM::Certificate::create(buff, CKM::DataFormat::FORM_DER_BASE64); + vect_ckm_chain.emplace_back(std::move(cert)); + } + + int status = CKM_API_OCSP_STATUS_UNKNOWN; + int ret = m_ckm->ocspCheck(vect_ckm_chain, status); + if (ret != CKM_API_SUCCESS) { + LogError("CKM ckeck OCSP returned " << ret); + // Add handling for different errors codes + // For these we can try to check ocsp again later: + switch (ret) { + case CKM_API_ERROR_NOT_SUPPORTED: + LogDebug("Key-manager OCSP API temporary diabled."); + case CKM_API_ERROR_SOCKET: + case CKM_API_ERROR_BAD_REQUEST: + case CKM_API_ERROR_BAD_RESPONSE: + case CKM_API_ERROR_SEND_FAILED: + case CKM_API_ERROR_RECV_FAILED: + case CKM_API_ERROR_SERVER_ERROR: + case CKM_API_ERROR_OUT_OF_MEMORY: + return Certs::ocsp_response_t::OCSP_CHECK_AGAIN; + // Any other error should be recurrent - checking the same app again + // should give the same result. + default: + return Certs::ocsp_response_t::OCSP_CERT_ERROR; + } + } + + LogDebug("OCSP status: " << status); + switch (status) { + // Remove app from "to-check" list: + case CKM_API_OCSP_STATUS_GOOD: + return Certs::ocsp_response_t::OCSP_APP_OK; + case CKM_API_OCSP_STATUS_UNSUPPORTED: + case CKM_API_OCSP_STATUS_UNKNOWN: + case CKM_API_OCSP_STATUS_INVALID_URL: + return Certs::ocsp_response_t::OCSP_CERT_ERROR; + + //Show popup to user and remove app from "to-check" list + case CKM_API_OCSP_STATUS_REVOKED: + return Certs::ocsp_response_t::OCSP_APP_REVOKED; + + //Keep app for checking it again later: + case CKM_API_OCSP_STATUS_NET_ERROR: + case CKM_API_OCSP_STATUS_INVALID_RESPONSE: + case CKM_API_OCSP_STATUS_REMOTE_ERROR: + case CKM_API_OCSP_STATUS_INTERNAL_ERROR: + return Certs::ocsp_response_t::OCSP_CHECK_AGAIN; + + default: + // This should never happen + return Certs::ocsp_response_t::OCSP_CERT_ERROR; + } +} + +Certs::ocsp_response_t Certs::check_ocsp (const app_t &app) +{ + bool check_again = false; + + for (auto &iter : app.signatures) { + Certs::ocsp_response_t resp = check_ocsp_chain(iter); + if (resp == Certs::ocsp_response_t::OCSP_APP_REVOKED) + return Certs::ocsp_response_t::OCSP_APP_REVOKED; + if (resp == Certs::ocsp_response_t::OCSP_CHECK_AGAIN) + check_again = true; + } + + if (check_again) + return Certs::ocsp_response_t::OCSP_CHECK_AGAIN; + return Certs::ocsp_response_t::OCSP_APP_OK; +} + +} // CCHECKER diff --git a/src/service/certs.h b/src/service/certs.h new file mode 100644 index 0000000..4871c39 --- /dev/null +++ b/src/service/certs.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2015 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. + */ +/* + * @file certs.h + * @author Janusz Kozerski (j.kozerski@samsung.com) + * @version 1.0 + * @brief This file is the implementation of certificates logic + * Getting out findinf app signature, getting certificates out of + * signature. Checking OCSP + */ + +#ifndef CCHECKER_CERTS_H +#define CCHECKER_CERTS_H + +#include +#include + +#include "service/app.h" +#include + +namespace CCHECKER { + +enum sig_t { + AUTHOR_SIG, + DISTRIBUTOR_SIG, + DISTRIBUTOR2_SIG +}; + +class Certs { + public: + enum class ocsp_response_t { + OCSP_APP_OK, + OCSP_APP_REVOKED, + OCSP_CHECK_AGAIN, + OCSP_CERT_ERROR + }; + Certs(); + virtual ~Certs(); + void get_certificates (app_t &app); + ocsp_response_t check_ocsp (const app_t &app); + + protected: // Needed for tests + ocsp_response_t check_ocsp_chain (const chain_t &chain); + + //private: + CKM::ManagerShPtr m_ckm; +}; + +} // CCHECKER + + +#endif // CCHECKER_CERTS_H diff --git a/src/service/logic.cpp b/src/service/logic.cpp new file mode 100644 index 0000000..f0ebaee --- /dev/null +++ b/src/service/logic.cpp @@ -0,0 +1,647 @@ +/* + * Copyright (c) 2015 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. + */ +/* + * @file logic.cpp + * @author Janusz Kozerski (j.kozerski@samsung.com) + * @author Sangwan Kwon (sangwan.kwon@samsung.com) + * @version 1.0 + * @brief This file is the implementation of SQL queries + */ +#include "logic.h" + +#include +#include + +#include +#include +#include + +#include "common/binary-queue.h" + +using namespace std; + +namespace CCHECKER { + +namespace { +struct PkgmgrinfoEvent { + PkgmgrinfoEvent(uid_t _uid, const char *_pkgid) + : uid(_uid) + , pkgid(_pkgid) {} + + inline bool operator==(const PkgmgrinfoEvent &rhs) const + { + return uid == rhs.uid && pkgid.compare(rhs.pkgid) == 0; + } + + inline bool operator<(const PkgmgrinfoEvent &rhs) const + { + if (uid < rhs.uid) + return true; + else if (uid < rhs.uid) + return false; + else + return pkgid.compare(rhs.pkgid) < 0; + } + + inline bool operator>(const PkgmgrinfoEvent &rhs) const + { + if (uid > rhs.uid) + return true; + else if (uid < rhs.uid) + return false; + else + return pkgid.compare(rhs.pkgid) > 0; + } + + uid_t uid; + std::string pkgid; + pkgmgr_event_t type; +}; + +std::set pkgmgrinfo_event_set; +const char *const DB_PATH = DB_INSTALL_DIR"/.cert-checker.db"; + +} // namespace Anonymous + +Logic::~Logic(void) +{ + clean(); +} + +void Logic::clean(void) +{ + LogDebug("Cert-checker cleaning start."); + + // wait and join processing thread + if (m_thread.joinable()) { + LogDebug("Waiting for join processing thread"); + { + std::lock_guard lock(m_mutex_cv); + set_should_exit(); + LogDebug("Notify thread : enforced by cleaning"); + m_to_process.notify_one(); + } + m_thread.join(); + LogDebug("Processing thread joined"); + } + else + LogDebug("No thread to join"); + + if (m_proxy_connman) + g_object_unref(m_proxy_connman); + + if (m_loop) + g_main_loop_unref(m_loop); + + delete m_sqlquery; + + LogDebug("Cert-checker cleaning finish."); +} + +Logic::Logic(void) : + m_loop(g_main_loop_new(NULL, FALSE)), + m_sqlquery(NULL), + m_was_setup_called(false), + m_is_online(false), + m_is_online_enabled(false), + m_should_exit(false), + m_proxy_connman(NULL), + m_pc_install(nullptr, nullptr), + m_pc_uninstall(nullptr, nullptr) +{ +} + +bool Logic::get_online() const +{ + return m_is_online; +} + +void Logic::set_online(bool online) +{ + std::lock_guard lock(m_mutex_cv); + if (m_is_online == online) + return; + m_is_online = online; + if (m_is_online) { + m_is_online_enabled = true; + LogDebug("Notify thread : Network connected"); + m_to_process.notify_one(); + } +} + +error_t Logic::setup_db() +{ + // TODO: If database doesn't exist -should we create a new one? + Try { + m_sqlquery = new DB::SqlQuery(DB_PATH); + } Catch (runtime_error) { + LogError("Error while creating SqlQuery object"); + return DATABASE_ERROR; + } + + if(!m_sqlquery) { + LogError("Cannot open database"); + return DATABASE_ERROR; + } + + return NO_ERROR; +} + +error_t Logic::setup() +{ + // Check if setup was called + if (m_was_setup_called) { + LogError("You can call setup only once"); + return INTERNAL_ERROR; + } + m_was_setup_called = true; + + // Check if DB exists and create a new one if it doesn't + error_t err = setup_db(); + if (err != NO_ERROR) { + LogError("Database error"); + return err; + } + + load_database_to_buffer(); + + // run process thread - thread will be waiting on condition variable + m_thread = std::thread(&Logic::process_all, this); + + // Add connman callback + LogDebug("register connman event callback start"); + if (register_dbus_signal_handler(&m_proxy_connman, + "net.connman", + "/", + "net.connman.Manager", + connman_callback) != NO_ERROR) { + LogError("Error in register_connman_signal_handler"); + return REGISTER_CALLBACK_ERROR; + } + LogDebug("register connman event callback success"); + + set_connman_online_state(); + + // Add pkgmgrinfo callback + LogDebug("Register package event handler start"); + + std::unique_ptr + _pcInstall(pkgmgrinfo_client_new(PMINFO_LISTENING), pkgmgrinfo_client_free); + std::unique_ptr + _pcUninstall(pkgmgrinfo_client_new(PMINFO_LISTENING), pkgmgrinfo_client_free); + m_pc_install = std::move(_pcInstall); + m_pc_uninstall = std::move(_pcUninstall); + + if (!m_pc_install || !m_pc_uninstall) { + LogError("Get pkgmgrinfo client failed"); + return REGISTER_CALLBACK_ERROR; + } + + int ret_status_install; + int ret_status_uninstall; + ret_status_install = pkgmgrinfo_client_set_status_type( + m_pc_install.get(), PKGMGR_CLIENT_STATUS_INSTALL); + ret_status_uninstall = pkgmgrinfo_client_set_status_type( + m_pc_uninstall.get(), PKGMGR_CLIENT_STATUS_UNINSTALL); + + if (ret_status_install == PMINFO_R_ERROR || ret_status_uninstall == PMINFO_R_ERROR) { + LogError("Set pkgmgrinfo status fail"); + return REGISTER_CALLBACK_ERROR; + } + m_reqid_install = pkgmgrinfo_client_listen_status( + m_pc_install.get(), pkgmgrinfo_event_handler_static, this); + m_reqid_uninstall = pkgmgrinfo_client_listen_status( + m_pc_uninstall.get(), pkgmgrinfo_event_handler_static, this); + + if (m_reqid_install < 0 || m_reqid_uninstall < 0) { + LogError("Register pacakge install event handler fail"); + return REGISTER_CALLBACK_ERROR; + } + + LogDebug("Register package event handler success"); + + LogDebug("Running the main loop"); + g_main_loop_run(m_loop); + + return NO_ERROR; +} + +int Logic::pkgmgrinfo_event_handler_static( + uid_t uid, + int reqid, + const char *pkgtype, + const char *pkgid, + const char *key, + const char *val, + const void *pmsg, + void *data) +{ + LogDebug("pkgmgrinfo event handler start!!"); + if (data == nullptr) + return -1; + + std::string keyStr(key); + std::string valStr(val); + LogDebug("pkgmgrinfo event was caught. type : " << valStr << ", status : " << keyStr); + + if ((valStr.compare("install") == 0 || valStr.compare("uninstall") == 0) + && keyStr.compare("start") == 0) { + return static_cast(data)->pkgmgrinfo_event_handler( + uid, reqid, pkgtype, pkgid, key, val, pmsg, data); + } else if (keyStr.compare("end") == 0 && valStr.compare("ok") == 0) { + return static_cast(data)->push_pkgmgrinfo_event(uid, pkgid); + } else { + // TODO(sangwan.kwon) if get untreat event like fail, must quit loop + LogDebug("Untreated event was caught : " << val); + return -1; + } +} + +int Logic::pkgmgrinfo_event_handler( + uid_t uid, + int reqid, + const char */*pkgtype*/, + const char *pkgid, + const char *key, + const char *val, + const void */*pmsg*/, + void */*data*/) +{ + if (pkgid == nullptr || key == nullptr || val == nullptr) { + LogError("Invalid parameter."); + return -1; + } + + std::string keyStr(key); + std::string valStr(val); + + LogDebug("uid: " << uid << " pkgid: " << pkgid << " key: " << keyStr << " val: " << valStr); + + PkgmgrinfoEvent event(uid, pkgid); + + if(valStr.compare("install") == 0) { + if (reqid != m_reqid_install) { + LogError("pkgmgrinfo event reqid unmatched"); + return -1; + } + event.type = EVENT_INSTALL; + } else if(valStr.compare("uninstall") == 0) { + if (reqid != m_reqid_uninstall) { + LogError("pkgmgrinfo event reqid unmatched"); + return -1; + } + event.type = EVENT_UNINSTALL; + } + + pkgmgrinfo_event_set.insert(event); + + return 0; +} + +int Logic::push_pkgmgrinfo_event(uid_t uid, const char *pkgid) +{ + PkgmgrinfoEvent event(uid, pkgid); + std::set::iterator pkgmgrinfo_event_iter = pkgmgrinfo_event_set.find(event); + + if (pkgmgrinfo_event_iter != pkgmgrinfo_event_set.end()) { + // FIXME: No information about app_id in the signal. Use stub. + app_t app(TEMP_APP_ID, pkgid, uid, {}); + + if (pkgmgrinfo_event_iter->type == EVENT_INSTALL) { + LogDebug("Successfully Installed. uid: " << uid << ", pkgid: " << pkgid); + push_event(event_t(app, event_t::event_type_t::APP_INSTALL)); + } else if (pkgmgrinfo_event_iter->type == EVENT_UNINSTALL) { + LogDebug("Successfully Uninstalled. uid: " << uid << ", pkgid: " << pkgid); + push_event(event_t(app, event_t::event_type_t::APP_UNINSTALL)); + } + + LogDebug("push pkgmgrifo success. pkgid: " << pkgid << ", uid: " << uid); + pkgmgrinfo_event_set.erase(event); + return 0; + } else { + // if update status, return fail + LogDebug("push pkgmgrifo fail. pkgid: " << pkgid << ", uid: " << uid); + return -1; + } +} + +error_t Logic::register_dbus_signal_handler(GDBusProxy **proxy, + const char *name, + const char *object_path, + const char *interface_name, + void (*callback) (GDBusProxy *proxy, + gchar *sender_name, + gchar *signal_name, + GVariant *parameters, + void *logic_ptr) + ) +{ + GError *error = NULL; + GDBusProxyFlags flags = G_DBUS_PROXY_FLAGS_NONE; + + // Obtain a connection to the System Bus + *proxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM, + flags, + NULL, /* GDBusInterfaceInfo */ + name, + object_path, + interface_name, + NULL, /* GCancellable */ + &error); + + if (*proxy == NULL) { + if (error) { + LogError("Error creating D-Bus proxy for /'" << interface_name <<"/': " << error->message); + g_error_free(error); + } else { + LogError("Error creating D-Bus proxy for /'" << interface_name <<"/'. Unknown error"); + } + return DBUS_ERROR; + } + + // Connect to g-signal to receive signals from proxy + if (g_signal_connect(*proxy, "g-signal", G_CALLBACK(callback), this) < 1) { + LogError("g_signal_connect error while connecting " << interface_name); + return REGISTER_CALLBACK_ERROR; + } + + return NO_ERROR; +} + +void Logic::set_connman_online_state() +{ + GError *error = NULL; + GVariant *response; + + if (m_proxy_connman == NULL) { + LogError("connman proxy is NULL"); + return; + } + + response = g_dbus_proxy_call_sync (m_proxy_connman, + "GetProperties", + NULL, // GetProperties gets no parameters + G_DBUS_CALL_FLAGS_NONE, + -1, // Default timeout + NULL, + &error); + + if (error) { + LogError("Error while calling connman GetProperties() Dbus API: " << error->message); + g_error_free(error); + return; + } + + if (response == NULL) { + // This should never happen + return; + } + + gchar *resp_g = g_variant_print(response, TRUE); + std::string resp_s(resp_g); + LogDebug("response: " << resp_s); + g_free(resp_g); + + // Response should look like this: + // ({'State': <'online'>, 'OfflineMode': , 'SessionMode': },) + if (resp_s.find("'State': <'online'>", 0) != std::string::npos) { + LogDebug("Connman has returned: online"); + set_online(true); + } + + // free memory + g_variant_unref(response); +} + +void Logic::connman_callback(GDBusProxy */*proxy*/, + gchar */*sender_name*/, + gchar *signal_name, + GVariant *parameters, + void *logic_ptr) +{ + string signal_name_str = string(signal_name); + if (signal_name_str != "PropertyChanged") { + // Invalid param. Nothing to do here. + return; + } + + gchar *parameters_g = g_variant_print(parameters, TRUE); + string params_str = string(parameters_g); + g_free (parameters_g); + + Logic *logic = static_cast (logic_ptr); + + if (params_str == "('State', <'online'>)") { + LogDebug("Device online"); + logic->set_online(true); + } + else if (params_str == "('State', <'offline'>)") { + LogDebug("Device offline"); + logic->set_online(false); + } +} + +void Logic::load_database_to_buffer() +{ + LogDebug("Loading database to the buffer"); + m_sqlquery->get_app_list(m_buffer); +} + +/** + * This function should move all event from queue to the buffer + **/ +void Logic::process_queue(void) +{ + event_t event; + while(m_queue.pop_event(event)) { + process_event(event); + } +} + +bool Logic::call_ui(const app_t &app) +{ + UI::UIBackend ui; + + if (ui.call_popup(app)) { // If calling popup or app_controll service will fail, + // do not remove application, and ask about it once again later + LogDebug("Popup shown correctly. Application will be removed from DB and buffer"); + return true; + } + LogDebug("Popup error. Application will be marked to show popup later."); + return false; +} + +bool Logic::process_app(app_t& app) { + // Check if app hasn't already been verified. + // If yes then just try to display popup once again, and go the next app. +#if POPUP + if (app.verified == app_t::verified_t::NO) { + LogDebug(app.str() << " has been verified before. Popup should be shown."); + return call_ui(app); + } +#endif + + Certs::ocsp_response_t ret; + ret = m_certs.check_ocsp(app); + + // If OCSP returns success or OCSP checking fails we should remove application from buffer and database + if (ret == Certs::ocsp_response_t::OCSP_APP_OK || + ret == Certs::ocsp_response_t::OCSP_CERT_ERROR) { + LogDebug(app.str() << " OCSP verified (or not available for app's chains)"); + return true; + } + else if (ret == Certs::ocsp_response_t::OCSP_APP_REVOKED) { + LogDebug(app.str() << " certificate has been revoked. Popup should be shown"); + app.verified = app_t::verified_t::NO; +#if POPUP +// Do not remove app here - just waits for user answer from popup + return call_ui(app); +#else + return true; +#endif + } + else { + LogDebug(app.str() << " should be checked again later"); + // If check_ocsp returns Certs::ocsp_response_t::OCSP_CHECK_AGAIN + // app should be checked again later + } + return false; +} + +void Logic::process_buffer(void) +{ + for (auto iter = m_buffer.begin(); iter != m_buffer.end();) { + bool remove = process_app(*iter); + auto prev = *iter; + iter++; + if (remove) + remove_app_from_buffer_and_database(prev); + app_processed(); + } +} + +void Logic::push_event(event_t event) +{ + std::lock_guard lock(m_mutex_cv); + m_queue.push_event(std::move(event)); + LogDebug("Notify thread : pkgmgr event added"); + m_to_process.notify_one(); +} + +void Logic::process_all() +{ + for(;;) { + std::unique_lock lock(m_mutex_cv); + + // don't sleep if there are online/installation/deinstallation events to process + if(m_queue.empty() || !get_online()) { + LogDebug("Processing thread : wait condition : " + << !m_queue.empty() << ", " << get_online()); + m_to_process.wait(lock); // spurious wakeups do not concern us + LogDebug("Processing thread : running"); + } + + lock.unlock(); + + if (m_should_exit) + break; + + if (get_online() && !m_queue.empty()) { + process_queue(); // move event data from queue to buffer & database + process_buffer(); + + LogDebug("Processing thread : done. g_main_loop quit"); + g_main_loop_quit(m_loop); + break; + } else if (!get_online()) { + LogDebug("Processing thread : no network. Buffer won't be processed"); + } else { + LogDebug("Processing thread : no event since cert-checker started"); + } + } +} + +void Logic::process_event(const event_t &event) +{ + if (event.event_type == event_t::event_type_t::APP_INSTALL) { + // pulling out certificates from signatures + app_t app = event.app; + m_certs.get_certificates(app); + add_app_to_buffer_and_database(app); + } + else if (event.event_type == event_t::event_type_t::APP_UNINSTALL) { + remove_app_from_buffer_and_database(event.app); + } + else + LogError("Unknown event type"); +} + +void Logic::add_app_to_buffer_and_database(const app_t &app) +{ + // First add app to DB + if(!m_sqlquery->add_app_to_check_list(app)) { + LogError("Failed to add " << app.str() << "to database"); + // We can do nothing about it. We can only log the error. + } + + // Then add app to buffer - skip if already added. + // FIXME: What to do if the same app will be installed twice? + // Add it twice to the buffer, or check if apps in buffer are unique? + // At the moment doubled apps are skipped. + for (auto &iter : m_buffer) { + if (iter.app_id == app.app_id && + iter.pkg_id == app.pkg_id && + iter.uid == app.uid) { + LogDebug(app.str() << " already in buffer. Skip."); + return; + } + } + + // Then add app to buffer + m_buffer.push_back(app); +} + +// Notice that this operator doesn't compare list of certificate, because it isn't needed here. +// This operator is implemented only for using in m_buffer.remove() method; +// Operator which compares certificates is implemented in tests. +bool operator ==(const app_t &app1, const app_t &app2) +{ + return app1.app_id == app2.app_id && + app1.pkg_id == app2.pkg_id && + app1.uid == app2.uid; +} + +void Logic::remove_app_from_buffer_and_database(const app_t &app) +{ + // First remove app from DB + m_sqlquery->remove_app_from_check_list(app); + + // Then remove app from buffer + m_buffer.remove(app); +} + +bool Logic::get_should_exit(void) const +{ + return m_should_exit; +} + +void Logic::set_should_exit(void) +{ + m_should_exit = true; + +} + +} // namespace CCHECKER diff --git a/src/service/logic.h b/src/service/logic.h new file mode 100644 index 0000000..dca58b7 --- /dev/null +++ b/src/service/logic.h @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2015 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. + */ +/* + * @file logic.h + * @author Janusz Kozerski (j.kozerski@samsung.com) + * @author Sangwan Kwon (sangwan.kwon@samsung.com) + * @version 1.0 + * @brief This file is the implementation of SQL queries + */ + +#ifndef CCHECKER_LOGIC_H +#define CCHECKER_LOGIC_H + +#include +#include +#include +#include +#include +#include +#include + +#include "common/types.h" +#include "common/binary-queue.h" +#include "service/app.h" +#include "service/certs.h" +#include "service/queue.h" + +#include +#include + +namespace CCHECKER { + +namespace DB { +class SqlQuery; +} // namespace DB + +enum error_t { + NO_ERROR, + REGISTER_CALLBACK_ERROR, + DBUS_ERROR, + PACKAGE_MANAGER_ERROR, + DATABASE_ERROR, + INTERNAL_ERROR +}; + +enum pkgmgr_event_t { + EVENT_INSTALL, + EVENT_UNINSTALL +}; + +enum class CommandId : int { + CC_OCSP_SYN = 0x01, + CC_OCSP_ACK = 0x02 +}; + +class Logic { + public: + Logic(void); + virtual ~Logic(void); + error_t setup(void); + virtual void clean(void); + + static void connman_callback(GDBusProxy *proxy, + gchar *sender_name, + gchar *signal_name, + GVariant *parameters, + void *logic_ptr); + + protected: + error_t setup_db(); + void load_database_to_buffer(); + + void add_app_to_buffer_and_database(const app_t &app); + void remove_app_from_buffer_and_database(const app_t &app); + + void set_connman_online_state(); + error_t register_dbus_signal_handler(GDBusProxy **proxy, + const char *name, + const char *object_path, + const char *interface_name, + void (*callback) (GDBusProxy *proxy, + gchar *sender_name, + gchar *signal_name, + GVariant *parameters, + void *logic_ptr) + ); + + static int pkgmgrinfo_event_handler_static( + uid_t uid, + int reqid, + const char *pkgtype, + const char *pkgid, + const char *key, + const char *val, + const void *pmsg, + void *data); + + int pkgmgrinfo_event_handler( + uid_t uid, + int reqid, + const char *pkgtype, + const char *pkgid, + const char *key, + const char *val, + const void *pmsg, + void *data); + + int push_pkgmgrinfo_event(uid_t uid, const char *pkgid); + + void push_event(event_t event); + + void process_all(void); + void process_queue(void); + virtual void process_event(const event_t &event); + + bool process_app(app_t& app); + void process_buffer(void); + virtual void app_processed() {}; // for tests + + bool get_online(void) const; + void set_online(bool online); + + bool get_should_exit(void) const; + void set_should_exit(void); + + bool call_ui(const app_t &app); + + + // main event loop data type + GMainLoop *m_loop; + + Queue m_queue; + Certs m_certs; + std::list m_buffer; + DB::SqlQuery *m_sqlquery; + bool m_was_setup_called; + + bool m_is_online; + // TODO: use m_queue for online events + bool m_is_online_enabled; + std::condition_variable m_to_process; + std::mutex m_mutex_cv; + std::thread m_thread; + bool m_should_exit; + + GDBusProxy *m_proxy_connman; + + // about pkgmgr event + int m_reqid_install; + int m_reqid_uninstall; + std::unique_ptr m_pc_install; + std::unique_ptr m_pc_uninstall; +}; + +} // namespace CCHECKER + +#endif //CCHECKER_LOGIC_H diff --git a/src/service/ocsp-service.cpp b/src/service/ocsp-service.cpp new file mode 100644 index 0000000..f41d7b6 --- /dev/null +++ b/src/service/ocsp-service.cpp @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2016 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 + */ +/* + * @file ocsp-service.cpp + * @author Sangwan Kwon (sangwan.kwon@samsung.com) + * @version 1.0 + * @brief + */ +#include "service/ocsp-service.h" + +#include + +namespace CCHECKER { + +OcspService::OcspService(const std::string &address) : + Service(address) +{ +} + +OcspService::~OcspService() +{ +} + +void OcspService::onMessageProcess(const ConnShPtr &connection) +{ + LogDebug("Start to process message on ocsp service."); + + auto in = connection->receive(); + connection->send(this->process(connection, in)); + + if (m_logic.setup() != NO_ERROR) + throw std::logic_error("Cannot setup logic."); + + LogDebug("Start to process message on ocsp service."); +} + +RawBuffer OcspService::process(const ConnShPtr &, RawBuffer &data) +{ + BinaryQueue q; + q.push(data); + + int cmd; + q.Deserialize(cmd); + + LogInfo("Request dispatch on ocsp-service."); + switch (static_cast(cmd)) { + case CommandId::CC_OCSP_SYN: { + // TODO(sangwan.kwon) : set protocol with client + return BinaryQueue::Serialize(1).pop(); + } + case CommandId::CC_OCSP_ACK: + default: + throw std::logic_error("Protocol error. unknown command id."); + } +} + +} // namespace CCHECKER diff --git a/src/service/ocsp-service.h b/src/service/ocsp-service.h new file mode 100644 index 0000000..1f497cc --- /dev/null +++ b/src/service/ocsp-service.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2016 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 + */ +/* + * @file ocsp-service.h + * @author Sangwan Kwon (sagnwan.kwon@samsung.com) + * @version 1.0 + * @brief + */ +#pragma once + +#include + +#include "common/service.h" +#include "service/logic.h" + +namespace CCHECKER { + +class OcspService : public Service { +public: + OcspService(const std::string &address); + virtual ~OcspService(); + +private: + virtual void onMessageProcess(const ConnShPtr &) override; + + RawBuffer process(const ConnShPtr &, RawBuffer &); + + Logic m_logic; +}; + +} // namespace CCHECKER diff --git a/src/service/queue.cpp b/src/service/queue.cpp new file mode 100644 index 0000000..1ae4f1b --- /dev/null +++ b/src/service/queue.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2015 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. + */ +/* + * @file queue.cpp + * @author Janusz Kozerski (j.kozerski@samsung.com) + * @version 1.0 + * @brief This file is the implementation of thread-safe queue + */ +#include "service/queue.h" + +#include +#include + +namespace CCHECKER { + +event_t::event_t(): + event_type(event_type_t::EVENT_TYPE_UNKNOWN), + app() +{} + +event_t::event_t(const app_t &app, event_type_t type): + event_type(type), + app(app) +{} + +void Queue::push_event(const event_t &event) +{ + std::lock_guard lock(m_mutex); + m_event_list.push(event); +} + +bool Queue::pop_event(event_t &event) +{ + std::lock_guard lock(m_mutex); + if (m_event_list.empty()) + return false; + + event = std::move(m_event_list.front()); + m_event_list.pop(); + return true; +} + +bool Queue::empty() +{ + return m_event_list.empty(); +} + +} //CCHECKER diff --git a/src/service/queue.h b/src/service/queue.h new file mode 100644 index 0000000..9c3eaae --- /dev/null +++ b/src/service/queue.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2015 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. + */ +/* + * @file queue.h + * @author Janusz Kozerski (j.kozerski@samsung.com) + * @version 1.0 + * @brief This file is the implementation of thread-safe queue + */ + +#ifndef CCHECKER_QUEUE_H +#define CCHECKER_QUEUE_H + +#include +#include + +#include "service/app.h" + +namespace CCHECKER { + +struct event_t { + enum class event_type_t { + APP_INSTALL, + APP_UNINSTALL, + EVENT_TYPE_UNKNOWN + }; + + event_type_t event_type; + app_t app; + + event_t(); + event_t(const app_t &app, event_type_t type); +}; + +class Queue { + public: + void push_event(const event_t &event); + bool pop_event(event_t &event); + bool empty(); + + private: + std::mutex m_mutex; + std::queue m_event_list; +}; + +} // CCHECKER + +#endif // CCHECKER_QUEUE_H diff --git a/src/ui/popup-bin/CMakeLists.txt b/src/ui/popup-bin/CMakeLists.txt index 8c2ac68..285653a 100644 --- a/src/ui/popup-bin/CMakeLists.txt +++ b/src/ui/popup-bin/CMakeLists.txt @@ -29,16 +29,16 @@ set(CERT_CHECKER_POPUP_SRC_DIR ${PROJECT_SOURCE_DIR}/src/ui/popup-bin) set(CERT_CHECKER_POPUP_SOURCES ${CERT_CHECKER_POPUP_SRC_DIR}/popup.cpp - ${CERT_CHECKER_SRC_PATH}/ui/popup-runner.cpp - ${CERT_CHECKER_SRC_PATH}/app.cpp + ${CERT_CHECKER_UI_PATH}/popup-runner.cpp + ${CERT_CHECKER_SERVICE_PATH}/app.cpp # logs - ${CERT_CHECKER_SRC_PATH}/log/log.cpp + ${CERT_CHECKER_LOG_PATH}/log.cpp # dpl - ${CERT_CHECKER_SRC_PATH}/dpl/core/src/assert.cpp - ${CERT_CHECKER_SRC_PATH}/dpl/core/src/exception.cpp - ${CERT_CHECKER_SRC_PATH}/dpl/core/src/serialization.cpp - ${CERT_CHECKER_SRC_PATH}/dpl/core/src/errno_string.cpp - ${CERT_CHECKER_SRC_PATH}/dpl/core/src/noncopyable.cpp + ${DPL_CORE_SRC_PATH}/assert.cpp + ${DPL_CORE_SRC_PATH}/exception.cpp + ${DPL_CORE_SRC_PATH}/serialization.cpp + ${DPL_CORE_SRC_PATH}/errno_string.cpp + ${DPL_CORE_SRC_PATH}/noncopyable.cpp ) ADD_DEFINITIONS(${CERT_CHECKER_POPUP_DEP_CFLAGS}) @@ -47,7 +47,7 @@ INCLUDE_DIRECTORIES( ${CERT_CHECKER_POPUP_SRC_DIR} ${CERT_CHECKER_POPUP_DEP_INCLUDE_DIRS} ${CERT_CHECKER_SRC_PATH}/include/ - ${CERT_CHECKER_SRC_PATH}/dpl/core/include/ + ${DPL_CORE_SRC_PATH}/include/ ) ADD_EXECUTABLE(${TARGET_CERT_CHECKER_POPUP} @@ -64,4 +64,4 @@ TARGET_LINK_LIBRARIES(${TARGET_CERT_CHECKER_POPUP} -pie ) -INSTALL(TARGETS ${TARGET_CERT_CHECKER_POPUP} DESTINATION ${BINDIR}) +INSTALL(TARGETS ${TARGET_CERT_CHECKER_POPUP} DESTINATION ${BIN_DIR}) diff --git a/src/ui/popup-bin/popup.cpp b/src/ui/popup-bin/popup.cpp index 019ef04..f616907 100644 --- a/src/ui/popup-bin/popup.cpp +++ b/src/ui/popup-bin/popup.cpp @@ -82,7 +82,7 @@ void show_popup(struct cert_checker_popup_data *pdp) { } pdp->win = elm_win_add(NULL, - dgettext(PROJECT_NAME, "SID_TITLE_OCSP_VERIFICATION_FAILED"), + dgettext(SERVICE_NAME, "SID_TITLE_OCSP_VERIFICATION_FAILED"), ELM_WIN_NOTIFICATION); elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED); @@ -98,7 +98,7 @@ void show_popup(struct cert_checker_popup_data *pdp) { pdp->title = elm_label_add(pdp->popup); elm_object_style_set(pdp->title, "elm.text.title"); - elm_object_text_set(pdp->title, dgettext(PROJECT_NAME, "SID_TITLE_OCSP_VERIFICATION_FAILED")); + elm_object_text_set(pdp->title, dgettext(SERVICE_NAME, "SID_TITLE_OCSP_VERIFICATION_FAILED")); evas_object_show(pdp->title); elm_box_pack_end(pdp->box, pdp->title); @@ -112,11 +112,11 @@ void show_popup(struct cert_checker_popup_data *pdp) { // Set message // App ID may be absent, so in that case we need to use only package ID if (pdp->app_id == std::string(CCHECKER::TEMP_APP_ID)) { - char *content = dgettext(PROJECT_NAME, "SID_CONTENT_OCSP_PACKAGE VERIFICATION_FAILED"); + char *content = dgettext(SERVICE_NAME, "SID_CONTENT_OCSP_PACKAGE VERIFICATION_FAILED"); ret = asprintf(&buff, content, pdp->pkg_id.c_str()); } else { - char *content = dgettext(PROJECT_NAME, "SID_CONTENT_OCSP_VERIFICATION_FAILED"); + char *content = dgettext(SERVICE_NAME, "SID_CONTENT_OCSP_VERIFICATION_FAILED"); ret = asprintf(&buff, content, pdp->app_id.c_str(), pdp->pkg_id.c_str()); } @@ -139,13 +139,13 @@ void show_popup(struct cert_checker_popup_data *pdp) { pdp->keep_button = elm_button_add(pdp->popup); elm_object_style_set(pdp->keep_button, "elm.swallow.content.button1"); - elm_object_text_set(pdp->keep_button, dgettext(PROJECT_NAME, "SID_BTN_OCSP_KEEP_APP")); + elm_object_text_set(pdp->keep_button, dgettext(SERVICE_NAME, "SID_BTN_OCSP_KEEP_APP")); elm_object_part_content_set(pdp->popup, "button1", pdp->keep_button); evas_object_smart_callback_add(pdp->keep_button, "clicked", keep_answer, pdp); pdp->uninstall_button = elm_button_add(pdp->popup); elm_object_style_set(pdp->uninstall_button, "elm.swallow.content.button2"); - elm_object_text_set(pdp->uninstall_button, dgettext(PROJECT_NAME, "SID_BTN_OCSP_UNINSTALL_APP")); + elm_object_text_set(pdp->uninstall_button, dgettext(SERVICE_NAME, "SID_BTN_OCSP_UNINSTALL_APP")); elm_object_part_content_set(pdp->popup, "button2 ", pdp->uninstall_button); evas_object_smart_callback_add(pdp->uninstall_button, "clicked", uninstall_answer, pdp); diff --git a/src/ui/popup-runner.cpp b/src/ui/popup-runner.cpp index 2004e05..bae75e8 100644 --- a/src/ui/popup-runner.cpp +++ b/src/ui/popup-runner.cpp @@ -29,8 +29,8 @@ #include -#include -#include +#include "service/app.h" +#include "service/logic.h" #include #include #include diff --git a/systemd/CMakeLists.txt b/systemd/CMakeLists.txt index 982fe1d..0b25467 100644 --- a/systemd/CMakeLists.txt +++ b/systemd/CMakeLists.txt @@ -1,4 +1,13 @@ -INSTALL(FILES - ${PROJECT_SOURCE_DIR}/systemd/cert-checker.service - DESTINATION - ${SYSTEMD_UNIT_DIR}) +CONFIGURE_FILE( + ${SERVICE_NAME}.socket.in + ${SERVICE_NAME}.socket @ONLY) +CONFIGURE_FILE( + ${SERVICE_NAME}.service.in + ${SERVICE_NAME}.service @ONLY) + +INSTALL( + FILES + ${SERVICE_NAME}.socket + ${SERVICE_NAME}.service + DESTINATION + ${SYSTEMD_UNIT_DIR}) diff --git a/systemd/cert-checker.service b/systemd/cert-checker.service deleted file mode 100644 index ab744c9..0000000 --- a/systemd/cert-checker.service +++ /dev/null @@ -1,15 +0,0 @@ -[Unit] -Description=Start the Cert-Checker -Requires=dbus.service - -[Service] -User=security_fw -Group=security_fw -EnvironmentFile=-/etc/sysconfig/enlightenment -# Makes popup bigger -Environment="ELM_SCALE=4.0" -Type=simple -ExecStart=/usr/bin/cert-checker - -[Install] -WantedBy=multi-user.target diff --git a/systemd/cert-checker.service.in b/systemd/cert-checker.service.in new file mode 100644 index 0000000..8819f29 --- /dev/null +++ b/systemd/cert-checker.service.in @@ -0,0 +1,13 @@ +[Unit] +Description=Start the Cert-Checker +Requires=dbus.service + +[Service] +User=@SERVICE_USER@ +Group=@SERVICE_GROUP@ +EnvironmentFile=-/etc/sysconfig/enlightenment +# Makes popup bigger +Environment="ELM_SCALE=4.0" +Type=simple +ExecStart=@BIN_DIR@/cert-checker +Sockets=@SERVICE_NAME@.socket diff --git a/systemd/cert-checker.socket.in b/systemd/cert-checker.socket.in new file mode 100644 index 0000000..26d6ace --- /dev/null +++ b/systemd/cert-checker.socket.in @@ -0,0 +1,7 @@ +[Socket] +ListenStream=@SERVICE_STREAM@ +SocketUser=@SERVICE_USER@ +SocketGroup=@SERVICE_GROUP@ +SocketMode=0777 + +Service=@SERVICE_NAME@.service diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index fa2817a..cf924e1 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -19,7 +19,6 @@ FIND_PACKAGE(Threads REQUIRED) ADD_DEFINITIONS( "-DBOOST_TEST_DYN_LINK" ) ADD_DEFINITIONS("-DTEST_APP_SIGNATURES_DIR=\"${TEST_APP_SIGNATURES_DIR}\"") -SET(CERT_CHECKER_SRC_PATH ${PROJECT_SOURCE_DIR}/src) SET(CERT_CHECKER_TESTS_SRC_PATH ${PROJECT_SOURCE_DIR}/tests) SET(CERT_CHECKER_TESTS_SOURCES @@ -35,24 +34,24 @@ SET(CERT_CHECKER_TESTS_SOURCES ${CERT_CHECKER_TESTS_SRC_PATH}/test_certs.cpp ${CERT_CHECKER_TESTS_SRC_PATH}/certs_.cpp # cert-checker - ${CERT_CHECKER_SRC_PATH}/app.cpp - ${CERT_CHECKER_SRC_PATH}/queue.cpp - ${CERT_CHECKER_SRC_PATH}/certs.cpp + ${CERT_CHECKER_SERVICE_PATH}/app.cpp + ${CERT_CHECKER_SERVICE_PATH}/queue.cpp + ${CERT_CHECKER_SERVICE_PATH}/certs.cpp # logs - ${CERT_CHECKER_SRC_PATH}/log/log.cpp + ${CERT_CHECKER_LOG_PATH}/log.cpp # dpl - ${CERT_CHECKER_SRC_PATH}/dpl/core/src/assert.cpp - ${CERT_CHECKER_SRC_PATH}/dpl/core/src/char_traits.cpp - ${CERT_CHECKER_SRC_PATH}/dpl/core/src/colors.cpp - ${CERT_CHECKER_SRC_PATH}/dpl/core/src/errno_string.cpp - ${CERT_CHECKER_SRC_PATH}/dpl/core/src/exception.cpp - ${CERT_CHECKER_SRC_PATH}/dpl/core/src/noncopyable.cpp - ${CERT_CHECKER_SRC_PATH}/dpl/core/src/string.cpp + ${DPL_CORE_SRC_PATH}/assert.cpp + ${DPL_CORE_SRC_PATH}/char_traits.cpp + ${DPL_CORE_SRC_PATH}/colors.cpp + ${DPL_CORE_SRC_PATH}/errno_string.cpp + ${DPL_CORE_SRC_PATH}/exception.cpp + ${DPL_CORE_SRC_PATH}/noncopyable.cpp + ${DPL_CORE_SRC_PATH}/string.cpp # dpl DB - ${CERT_CHECKER_SRC_PATH}/dpl/db/src/sql_connection.cpp - ${CERT_CHECKER_SRC_PATH}/dpl/db/src/naive_synchronization_object.cpp + ${DPL_DB_SRC_PATH}/sql_connection.cpp + ${DPL_DB_SRC_PATH}/naive_synchronization_object.cpp # DB - ${CERT_CHECKER_SRC_PATH}/db/sql_query.cpp + ${CERT_CHECKER_DB_PATH}/sql_query.cpp ) SET(CERT_CHECKER_TESTS_LOGIC_SOURCES @@ -63,31 +62,32 @@ SET(CERT_CHECKER_TESTS_LOGIC_SOURCES ${CERT_CHECKER_TESTS_SRC_PATH}/logic_.cpp ${CERT_CHECKER_TESTS_SRC_PATH}/stubs_.cpp # cert-checker - ${CERT_CHECKER_SRC_PATH}/logic.cpp - ${CERT_CHECKER_SRC_PATH}/app.cpp - ${CERT_CHECKER_SRC_PATH}/queue.cpp + ${CERT_CHECKER_SERVICE_PATH}/logic.cpp + ${CERT_CHECKER_SERVICE_PATH}/app.cpp + ${CERT_CHECKER_SERVICE_PATH}/queue.cpp # logs - ${CERT_CHECKER_SRC_PATH}/log/log.cpp + ${CERT_CHECKER_LOG_PATH}/log.cpp # dpl - ${CERT_CHECKER_SRC_PATH}/dpl/core/src/colors.cpp + ${DPL_CORE_SRC_PATH}/colors.cpp ) SET(CERT_CHECKER_POPUP_TEST_SOURCES # tests ${CERT_CHECKER_TESTS_SRC_PATH}/popup_test.cpp # cert-checker - ${CERT_CHECKER_SRC_PATH}/app.cpp - ${CERT_CHECKER_SRC_PATH}/ui/popup-runner.cpp - ${CERT_CHECKER_SRC_PATH}/ui/UIBackend.cpp + ${CERT_CHECKER_SERVICE_PATH}/app.cpp + ${CERT_CHECKER_UI_PATH}/popup-runner.cpp + ${CERT_CHECKER_UI_PATH}/UIBackend.cpp # logs - ${CERT_CHECKER_SRC_PATH}/log/log.cpp + ${CERT_CHECKER_LOG_PATH}/log.cpp ) INCLUDE_DIRECTORIES(SYSTEM - ${CERT_CHECKER_DEP_INCLUDE_DIRS} + ${CERT_CHECKER_TESTS_DEP_INCLUDE_DIRS} + ${CERT_CHECKER_SRC_PATH}/ ${CERT_CHECKER_SRC_PATH}/include/ - ${CERT_CHECKER_SRC_PATH}/dpl/core/include/ - ${CERT_CHECKER_SRC_PATH}/dpl/db/include/ + ${DPL_CORE_PATH}/include/ + ${DPL_DB_PATH}/include/ ${CERT_CHECKER_TESTS_SRC_PATH}/ ) @@ -96,6 +96,7 @@ ADD_EXECUTABLE(${TARGET_CERT_CHECKER_TESTS_LOGIC} ${CERT_CHECKER_TESTS_LOGIC_SOU ADD_EXECUTABLE(${TARGET_CERT_CHECKER_POPUP_TEST} ${CERT_CHECKER_POPUP_TEST_SOURCES}) TARGET_LINK_LIBRARIES(${TARGET_CERT_CHECKER_TESTS} + ${TARGET_CERT_CHECKER_COMMON} ${CERT_CHECKER_TESTS_DEP_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} boost_unit_test_framework @@ -103,6 +104,7 @@ TARGET_LINK_LIBRARIES(${TARGET_CERT_CHECKER_TESTS} ) TARGET_LINK_LIBRARIES(${TARGET_CERT_CHECKER_TESTS_LOGIC} + ${TARGET_CERT_CHECKER_COMMON} ${CERT_CHECKER_TESTS_DEP_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} boost_unit_test_framework @@ -110,6 +112,7 @@ TARGET_LINK_LIBRARIES(${TARGET_CERT_CHECKER_TESTS_LOGIC} ) TARGET_LINK_LIBRARIES(${TARGET_CERT_CHECKER_POPUP_TEST} + ${TARGET_CERT_CHECKER_COMMON} ${CERT_CHECKER_TESTS_DEP_LIBRARIES} -ldl ) @@ -130,6 +133,6 @@ INSTALL(FILES files/app4/signature1.xml DESTINATION ${TEST_APP_SIGNATURES_DIR}/app4/) -INSTALL(TARGETS ${TARGET_CERT_CHECKER_TESTS} DESTINATION ${BINDIR}) -INSTALL(TARGETS ${TARGET_CERT_CHECKER_TESTS_LOGIC} DESTINATION ${BINDIR}) -INSTALL(TARGETS ${TARGET_CERT_CHECKER_POPUP_TEST} DESTINATION ${BINDIR}) +INSTALL(TARGETS ${TARGET_CERT_CHECKER_TESTS} DESTINATION ${BIN_DIR}) +INSTALL(TARGETS ${TARGET_CERT_CHECKER_TESTS_LOGIC} DESTINATION ${BIN_DIR}) +INSTALL(TARGETS ${TARGET_CERT_CHECKER_POPUP_TEST} DESTINATION ${BIN_DIR}) diff --git a/tests/app_event_operators.h b/tests/app_event_operators.h index 2638c19..a047e56 100644 --- a/tests/app_event_operators.h +++ b/tests/app_event_operators.h @@ -20,8 +20,8 @@ * @brief Implementation of app_test class (from app_t) */ -#include -#include +#include "service/app.h" +#include "service/queue.h" #ifndef CCHECKER_APP_TEST_CLASS_H #define CCHECKER_APP_TEST_CLASS_H diff --git a/tests/certs_.h b/tests/certs_.h index ba1daab..163d299 100644 --- a/tests/certs_.h +++ b/tests/certs_.h @@ -20,7 +20,7 @@ * @brief Implementation of Certs for testing */ -#include +#include "service/certs.h" #ifndef CCHECKER_DBFIXTURE_H #define CCHECKER_DBFIXTURE_H diff --git a/tests/logic_.h b/tests/logic_.h index 45ed559..a9317aa 100644 --- a/tests/logic_.h +++ b/tests/logic_.h @@ -28,7 +28,7 @@ * Some of methods are stubbed, and some of them just calls corresponding methods from Logic Class. */ -#include +#include "service/logic.h" namespace CCHECKER { diff --git a/tests/queue_test_thread.cpp b/tests/queue_test_thread.cpp index aefc11b..b553dde 100644 --- a/tests/queue_test_thread.cpp +++ b/tests/queue_test_thread.cpp @@ -23,8 +23,8 @@ #include #include -#include -#include +#include "service/app.h" +#include "service/queue.h" #include #include diff --git a/tests/queue_test_thread.h b/tests/queue_test_thread.h index c2489d5..2c2989e 100644 --- a/tests/queue_test_thread.h +++ b/tests/queue_test_thread.h @@ -20,7 +20,7 @@ * @brief Implementation of class for multi-thread testing Queue */ -#include +#include "service/queue.h" namespace CCHECKER { diff --git a/tests/stubs_.cpp b/tests/stubs_.cpp index c63c668..1360986 100644 --- a/tests/stubs_.cpp +++ b/tests/stubs_.cpp @@ -20,8 +20,9 @@ * @brief Implementation of stubbed functions for testing */ -#include -#include +#include "service/certs.h" +#include "service/queue.h" + #include #include diff --git a/tests/test_logic.cpp b/tests/test_logic.cpp index 99871fe..e471e99 100644 --- a/tests/test_logic.cpp +++ b/tests/test_logic.cpp @@ -49,12 +49,10 @@ std::string log_apps(std::list &apps, std::list buff) return ret; } - -} //anonymus +} // anonymous namespace BOOST_FIXTURE_TEST_SUITE(LOGIC_TEST, LogicWrapper) - BOOST_AUTO_TEST_CASE(logic_setup) { BOOST_REQUIRE(setup() == NO_ERROR); @@ -448,5 +446,4 @@ BOOST_AUTO_TEST_CASE(logic_workflow_OCSP_APP_REVOKED_2) { buff = get_buffer_(); BOOST_CHECK_MESSAGE(buff == apps, log_apps(apps, buff)); } - BOOST_AUTO_TEST_SUITE_END() -- cgit v1.2.3