From: Zbigniew Jasinski Date: Thu, 23 Apr 2015 09:27:15 +0000 (+0200) Subject: Change directory name to smack-dbus-tests before merge X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f73ad0dfc48caf87e505da20d548812fc74ada18;p=platform%2Fcore%2Ftest%2Fsecurity-tests.git Change directory name to smack-dbus-tests before merge Change-Id: I950a86c8e918d3268c7e280bc8fc91b4e2d39cad --- diff --git a/tests/dbus-tests/CMakeLists.txt b/tests/dbus-tests/CMakeLists.txt deleted file mode 100644 index a263055e..00000000 --- a/tests/dbus-tests/CMakeLists.txt +++ /dev/null @@ -1,67 +0,0 @@ -# -#Copyright (c) 2014-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 Michal Eljasiewicz (m.eljasiewic@samsung.com) -# @brief -# - -INCLUDE(FindPkgConfig) - -# Dependencies -PKG_CHECK_MODULES(DBUS_TESTS_DEP - libsmack - cynara-admin - dbus-1 - REQUIRED) - -# Targets definition - -INCLUDE_DIRECTORIES(SYSTEM - ${DBUS_TESTS_DEP_INCLUDE_DIRS} - ) - -SET(TARGET_DBUS_TESTS "dbus-tests") - -# Sources definition - -SET(DBUS_TESTS_SOURCES - ${PROJECT_SOURCE_DIR}/tests/cynara-tests/common/cynara_test_admin.cpp - ${PROJECT_SOURCE_DIR}/tests/dbus-tests/common/dbus_test_commons.cpp - ${PROJECT_SOURCE_DIR}/tests/dbus-tests/common/dbus_test_service.cpp - ${PROJECT_SOURCE_DIR}/tests/dbus-tests/common/dbus_test_service_object.cpp - ${PROJECT_SOURCE_DIR}/tests/dbus-tests/main.cpp - ${PROJECT_SOURCE_DIR}/tests/dbus-tests/common/dbus_test_busconfig_writer.cpp - ${PROJECT_SOURCE_DIR}/tests/dbus-tests/cynara_dbus_tests.cpp - ${PROJECT_SOURCE_DIR}/tests/dbus-tests/smack_dbus_tests.cpp - ) - -INCLUDE_DIRECTORIES( - ${PROJECT_SOURCE_DIR}/tests/common/ - ${PROJECT_SOURCE_DIR}/tests/cynara-tests/common/ - ${PROJECT_SOURCE_DIR}/tests/dbus-tests/common/ - ) - -ADD_EXECUTABLE(${TARGET_DBUS_TESTS} ${DBUS_TESTS_SOURCES}) - -TARGET_LINK_LIBRARIES(${TARGET_DBUS_TESTS} - ${DBUS_TESTS_DEP_LIBRARIES} - dpl-test-framework - tests-common - ) - -# Installation - -INSTALL(TARGETS ${TARGET_DBUS_TESTS} DESTINATION /usr/bin) diff --git a/tests/dbus-tests/common/dbus_test_busconfig_writer.cpp b/tests/dbus-tests/common/dbus_test_busconfig_writer.cpp deleted file mode 100644 index 1f5cc198..00000000 --- a/tests/dbus-tests/common/dbus_test_busconfig_writer.cpp +++ /dev/null @@ -1,163 +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 dbus_test_busconfig_writer.cpp - * @author Marcin Niesluchowski - * @version 1.0 - * @brief dbus test busconfig writer definition - */ - -#include - -#include - -#include -#include - -namespace DBusTest { - -namespace { - -const char* const BUSCONFIG_ENCODING = "ISO-8859-1"; - -const std::map ATTR_MAP = { - { Attr::OWN, "own" }, - { Attr::OWN_PREFIX, "own_prefix" }, - - { Attr::SEND_DESTINATION, "send_destination" }, - { Attr::SEND_PATH, "send_path" }, - { Attr::SEND_INTERFACE, "send_interface" }, - { Attr::SEND_TYPE, "send_type" }, - { Attr::SEND_MEMBER, "send_member" }, - { Attr::SEND_ERROR, "send_error" }, - - { Attr::RECEIVE_SENDER, "receive_sender" }, - { Attr::RECEIVE_PATH, "receive_path" }, - { Attr::RECEIVE_INTERFACE, "receive_interface" }, - { Attr::RECEIVE_TYPE, "receive_type" }, - { Attr::RECEIVE_MEMBER, "receive_member" }, - { Attr::RECEIVE_ERROR, "receive_error" } -}; - -} - -const std::string VAL_ALL = "*"; -const std::string CONF_FILE_PATH("/etc/dbus-1/system.d/security_tests_dbus_tests.conf"); - -BusConfigWriter::BusConfigWriter() - : m_writer(nullptr) - , m_doc(nullptr) -{ - RUNNER_ASSERT_MSG(0 == unlink(CONF_FILE_PATH.c_str()) || errno == ENOENT, - "Unable to unlink existing file " << CONF_FILE_PATH << " file"); - - m_writer = xmlNewTextWriterDoc(&m_doc, 0); - RUNNER_ASSERT_MSG(m_writer, "xmlNewTextWriterDoc failed"); - - RUNNER_ASSERT(0 <= xmlTextWriterStartDocument(m_writer, NULL, BUSCONFIG_ENCODING, NULL)); - - RUNNER_ASSERT(0 <= xmlTextWriterWriteDTD( - m_writer, - BAD_CAST "busconfig", - BAD_CAST "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN", - BAD_CAST "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd", - NULL)); - - startElement("busconfig"); - - writeElement("type", "system"); - - startElement("policy"); - writeAttribute("context", "default"); -} - -BusConfigWriter::~BusConfigWriter() -{ - if (m_doc) - xmlFreeDoc(m_doc); - if (m_writer) - xmlFreeTextWriter(m_writer); -} - -void BusConfigWriter::addPolicyAllow(const AttrValVec &attrValVec) -{ - startElement("allow"); - for (const auto &attrVal : attrValVec) - writeAttribute(attrVal); - endElement(); -} - -void BusConfigWriter::addPolicyDeny(const AttrValVec &attrValVec) -{ - startElement("deny"); - for (const auto &attrVal : attrValVec) - writeAttribute(attrVal); - endElement(); -} - -void BusConfigWriter::addPolicyCheck(const std::string &privilege, const AttrValVec &attrValVec) -{ - startElement("check"); - for (const auto &attrVal : attrValVec) - writeAttribute(attrVal); - writeAttribute("privilege", privilege); - endElement(); -} - -void BusConfigWriter::save() -{ - endElement(); - endElement(); - - RUNNER_ASSERT(0 <= xmlTextWriterEndDocument(m_writer)); - - RUNNER_ASSERT_MSG(0 <= xmlSaveFileEnc(CONF_FILE_PATH.c_str(), m_doc, BUSCONFIG_ENCODING), - "Unable to save doc file: " << CONF_FILE_PATH); -} - -void BusConfigWriter::startElement(const std::string &element) -{ - RUNNER_ASSERT_MSG(0 <= xmlTextWriterStartElement(m_writer, BAD_CAST element.c_str()), - "Unable to start element: " << element); -} - -void BusConfigWriter::writeAttribute(const std::string &attr, const std::string &val) -{ - RUNNER_ASSERT_MSG(0 <= xmlTextWriterWriteAttribute(m_writer, - BAD_CAST attr.c_str(), - BAD_CAST val.c_str()), - "Unable to write attribute: " << attr << "=\"" << val << "\""); -} - -void BusConfigWriter::writeAttribute(const AttrVal &attrVal) -{ - writeAttribute(ATTR_MAP.at(attrVal.attr), attrVal.val); -} - -void BusConfigWriter::endElement() -{ - RUNNER_ASSERT(0 <= xmlTextWriterEndElement(m_writer)); -} - -void BusConfigWriter::writeElement(const std::string &element, const std::string &content) -{ - RUNNER_ASSERT_MSG(0 <= xmlTextWriterWriteElement(m_writer, - BAD_CAST element.c_str(), - BAD_CAST content.c_str()), - "Unable to write element: " << element << "; content: " << content); -} - -} diff --git a/tests/dbus-tests/common/dbus_test_busconfig_writer.h b/tests/dbus-tests/common/dbus_test_busconfig_writer.h deleted file mode 100644 index 7b41bbf5..00000000 --- a/tests/dbus-tests/common/dbus_test_busconfig_writer.h +++ /dev/null @@ -1,90 +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 dbus_test_busconfig_writer.h - * @author Marcin Niesluchowski - * @version 1.0 - * @brief dbus test busconfig writer declaration - */ - -#ifndef DBUS_TEST_BUSCONFIG_WRITER -#define DBUS_TEST_BUSCONFIG_WRITER - -#include - -#include -#include - -namespace DBusTest { - -enum class Attr -{ - OWN, - OWN_PREFIX, - - SEND_DESTINATION, - SEND_PATH, - SEND_INTERFACE, - SEND_TYPE, - SEND_MEMBER, - SEND_ERROR, - - RECEIVE_SENDER, - RECEIVE_PATH, - RECEIVE_INTERFACE, - RECEIVE_TYPE, - RECEIVE_MEMBER, - RECEIVE_ERROR -}; - -struct AttrVal -{ - Attr attr; - std::string val; -}; - -extern const std::string VAL_ALL; -extern const std::string CONF_FILE_PATH; - -typedef std::vector AttrValVec; - -class BusConfigWriter -{ -public: - BusConfigWriter(); - ~BusConfigWriter(); - - void addPolicyAllow(const AttrValVec &attrValVec); - void addPolicyDeny(const AttrValVec &attrValVec); - void addPolicyCheck(const std::string &privilege, const AttrValVec &attrValVec); - - void save(); - -private: - void startElement(const std::string &element); - void writeAttribute(const std::string &attr, const std::string &val); - void writeAttribute(const AttrVal &attrVal); - void endElement(); - void writeElement(const std::string &element, const std::string &content); - - xmlTextWriterPtr m_writer; - xmlDocPtr m_doc; - std::string m_filePath; -}; - -} - -#endif // DBUS_TEST_BUSCONFIG_WRITER diff --git a/tests/dbus-tests/common/dbus_test_commons.cpp b/tests/dbus-tests/common/dbus_test_commons.cpp deleted file mode 100644 index 548d015a..00000000 --- a/tests/dbus-tests/common/dbus_test_commons.cpp +++ /dev/null @@ -1,35 +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 dbus_test_commons.cpp - * @author Marcin Niesluchowski - * @version 1.0 - * @brief commons for dbus test files - */ - -#include - -namespace DBusTest -{ - -const std::string CONNECTION_NAME_PREFIX("com.security_tests"); - -const std::string connectionNameFromStr(const std::string &str) -{ - return CONNECTION_NAME_PREFIX + "." + str; -} - -} diff --git a/tests/dbus-tests/common/dbus_test_commons.h b/tests/dbus-tests/common/dbus_test_commons.h deleted file mode 100644 index 24090635..00000000 --- a/tests/dbus-tests/common/dbus_test_commons.h +++ /dev/null @@ -1,37 +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 dbus_test_commons.h - * @author Marcin Niesluchowski - * @version 1.0 - * @brief commons for dbus test files - */ - -#ifndef DBUS_TESTS_COMMON_DBUS_TEST_COMMONS_H -#define DBUS_TESTS_COMMON_DBUS_TEST_COMMONS_H - -#include - -namespace DBusTest -{ - -extern const std::string CONNECTION_NAME_PREFIX; - -const std::string connectionNameFromStr(const std::string &str); - -} - -#endif // DBUS_TESTS_COMMON_DBUS_TEST_COMMONS_H diff --git a/tests/dbus-tests/common/dbus_test_service.cpp b/tests/dbus-tests/common/dbus_test_service.cpp deleted file mode 100644 index 81da52b7..00000000 --- a/tests/dbus-tests/common/dbus_test_service.cpp +++ /dev/null @@ -1,127 +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 dbus_test_service.cpp - * @author Marcin Niesluchowski - * @version 1.0 - * @brief dbus test service definition - */ - -#include -#include - -#include - -#include - -namespace { - -const std::string OBJECT_PATH_DIR("/com/security_tests/"); -const std::string INTERFACE_SUFFIX("TestInterface"); - -} - -namespace DBusTest -{ - -ServiceCreds::ServiceCreds(const std::string &name) - : m_connectionName(connectionNameFromStr(name)) - , m_objectPath(OBJECT_PATH_DIR + name) - , m_interface(m_connectionName + "." + INTERFACE_SUFFIX) -{ -} - -const std::string& ServiceCreds::connectionName() const -{ - return m_connectionName; -} - -const std::string& ServiceCreds::objectPath() const -{ - return m_objectPath; -} - -const std::string& ServiceCreds::interface() const -{ - return m_interface; -} - -Service::Service(const ServiceCreds &serviceCreds) - : m_connection(DBUS_BUS_SYSTEM, true) - , m_object(serviceCreds.interface()) - , m_messageReceived(false) - , m_exceptionThrown(false) -{ - m_connection.requestName(serviceCreds.connectionName()); - m_connection.registerObjectPath(serviceCreds.objectPath(), - handleMessage, - (void*)this); -} - -void Service::insertMethodHandler(const std::string &method, - const MessageHandler &messageHandler) -{ - m_object.insertMethodHandler(method, messageHandler); -} - -DBusHandlerResult Service::handleMessage(DBusConnection *connection, - DBusMessage *message, - void *userData) -{ - Service* service = reinterpret_cast(userData); - (void)userData; - try { - service->m_messageReceived = true; - DBus::MessageIn messageIn(message, true); - DBus::Connection conn(connection); - service->m_object.handleMessage(conn, messageIn, service->m_errorString); - } catch(...) { - service->m_exceptionThrown = true; - } - return DBUS_HANDLER_RESULT_HANDLED; -} - -void Service::run(bool &finish, bool timeout) -{ - using namespace std::chrono; - high_resolution_clock::time_point tpEnd = high_resolution_clock::now() + seconds(5); - while (!finish) { - m_connection.readWrite(1000); - - high_resolution_clock::time_point tp = high_resolution_clock::now(); - if (tp > tpEnd) { - if (timeout) - return; - RUNNER_FAIL_MSG("Timeout not expected"); - } - - while(true) { - m_errorString.clear(); - m_exceptionThrown = false; - - m_connection.dispatch(); - if (!m_messageReceived) - break; - m_messageReceived = false; - - RUNNER_ASSERT_MSG(!m_exceptionThrown, "Exception thrown while handling message"); - RUNNER_ASSERT_MSG(m_errorString.empty(), "Error while handling dispatched message. " - << m_errorString); - } - } -} - -} // namespace DBusTest diff --git a/tests/dbus-tests/common/dbus_test_service.h b/tests/dbus-tests/common/dbus_test_service.h deleted file mode 100644 index bf986df5..00000000 --- a/tests/dbus-tests/common/dbus_test_service.h +++ /dev/null @@ -1,78 +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 dbus_test_service.h - * @author Marcin Niesluchowski - * @version 1.0 - * @brief dbus test service declaration - */ - -#ifndef DBUS_TESTS_COMMON_DBUS_TEST_SERVICE_H -#define DBUS_TESTS_COMMON_DBUS_TEST_SERVICE_H - -#include - -#include - -#include - -namespace DBusTest -{ - -class ServiceCreds -{ -public: - ServiceCreds(const std::string &name); - ~ServiceCreds() = default; - - const std::string& connectionName() const; - const std::string& objectPath() const; - const std::string& interface() const; - -private: - std::string m_connectionName; - std::string m_objectPath; - std::string m_interface; -}; - -class Service -{ -public: - Service(const ServiceCreds &serviceCreds); - Service(const Service &other) = delete; - ~Service() = default; - - Service& operator=(const Service &other) = delete; - - void insertMethodHandler(const std::string &method, - const MessageHandler &messageHandler); - void run(bool &finish, bool timeout); - -private: - static DBusHandlerResult handleMessage(DBusConnection *connection, - DBusMessage *message, - void *userData); - - DBus::Connection m_connection; - ServiceObject m_object; - bool m_messageReceived; - bool m_exceptionThrown; - std::string m_errorString; -}; - -} // namespace DBusTest - -#endif // DBUS_TESTS_COMMON_DBUS_TEST_SERVICE_H diff --git a/tests/dbus-tests/common/dbus_test_service_object.cpp b/tests/dbus-tests/common/dbus_test_service_object.cpp deleted file mode 100644 index 8cc1ca6c..00000000 --- a/tests/dbus-tests/common/dbus_test_service_object.cpp +++ /dev/null @@ -1,58 +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 dbus_test_service_object.cpp - * @author Marcin Niesluchowski - * @version 1.0 - * @brief Definition of dbus test service object class for handling - * incoming messages - */ - -#include - -namespace DBusTest -{ - -ServiceObject::ServiceObject(const std::string &interface) - : m_interface(interface) -{ -} - -const std::string& ServiceObject::interface() const -{ - return m_interface; -} - -void ServiceObject::insertMethodHandler(const std::string &method, - const MessageHandler &messageHandler) -{ - m_methodHandlers[method] = messageHandler; -} - -void ServiceObject::handleMessage(DBus::Connection &connection, - DBus::MessageIn &messageIn, - std::string &errorStr) -{ - for (auto &methodHandler : m_methodHandlers) { - if (messageIn.isMethodCall(m_interface, methodHandler.first)) { - methodHandler.second(connection, messageIn, errorStr); - return; - } - } - errorStr = "Received unregistered message"; -} - -} // namespace DBusTest diff --git a/tests/dbus-tests/common/dbus_test_service_object.h b/tests/dbus-tests/common/dbus_test_service_object.h deleted file mode 100644 index d2692c25..00000000 --- a/tests/dbus-tests/common/dbus_test_service_object.h +++ /dev/null @@ -1,64 +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 dbus_test_service_object.h - * @author Marcin Niesluchowski - * @version 1.0 - * @brief Declaration of dbus test service object class for handling - * incoming messages - */ - -#ifndef DBUS_TESTS_COMMON_DBUS_TEST_SERVICE_OBJECT_H -#define DBUS_TESTS_COMMON_DBUS_TEST_SERVICE_OBJECT_H - -#include -#include - -#include -#include -#include - -namespace DBusTest -{ - -using MessageHandler = std::function; - -class ServiceObject -{ -public: - ServiceObject(const std::string &interface); - ServiceObject(const ServiceObject &other) = delete; - ~ServiceObject() = default; - - ServiceObject& operator=(const ServiceObject &other) = delete; - - const std::string& interface() const; - void insertMethodHandler(const std::string &method, - const MessageHandler &messageHandler); - void handleMessage(DBus::Connection &connection, - DBus::MessageIn &messageIn, - std::string &errorStr); - -private: - std::map m_methodHandlers; - std::string m_interface; -}; - -} // namespace DBusTest - -#endif // DBUS_TESTS_COMMON_DBUS_TEST_SERVICE_OBJECT_H diff --git a/tests/dbus-tests/cynara_dbus_tests.cpp b/tests/dbus-tests/cynara_dbus_tests.cpp deleted file mode 100644 index 1ac4d091..00000000 --- a/tests/dbus-tests/cynara_dbus_tests.cpp +++ /dev/null @@ -1,671 +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 cynara_dbus_tests.cpp - * @author Marcin Niesluchowski (m.niesluchow@samsung.com) - * @version 1.0 - * @brief Tests for cynara checks implemented in dbus - */ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -using namespace DBusTest; - -static const std::string ROOT_UID_STR("0"); -static const std::string MESSSAGE_TYPE_METHOD_CALL = "method_call"; -static const std::string MESSSAGE_TYPE_ERROR = "error"; - -static const std::string clientIdFromStr(const std::string &str) -{ - return str + "Client"; -} - -static const std::string serviceIdFromStr(const std::string &str) -{ - return str + "Service"; -} - -static const std::string memberFromStr(const std::string &str) -{ - return str + "Member"; -} - -static const std::string privilegeFromStr(const std::string &str) -{ - return str + "Privilege"; -} - -static const std::string smackLabelFromStr(const std::string &str) -{ - return str + "SmackLabel"; -} - -static const std::string errorFromStr(const std::string &interface, const std::string &str) -{ - return interface + ".Error.Err" + str; -} - -static void addBusconfigPolicyOwn(const std::string &id) -{ - BusConfigWriter writer; - writer.addPolicyCheck(privilegeFromStr(id), {{Attr::OWN, connectionNameFromStr(id)}}); - writer.save(); -} - -static void assertUnlink(const std::string &filePath) -{ - RUNNER_ASSERT_MSG(0 == unlink(filePath.c_str()), "Unable to unlink " << filePath << " file"); -} - -static void addCynaraPolicy(const std::string &id) -{ - CynaraTestAdmin admin; - CynaraPoliciesContainer cp; - cp.add(CYNARA_ADMIN_DEFAULT_BUCKET, - smackLabelFromStr(id).c_str(), ROOT_UID_STR.c_str(), privilegeFromStr(id).c_str(), - CYNARA_ADMIN_ALLOW, nullptr); - admin.setPolicies(cp); -} - -static void addSmackAccessForDbus(SmackAccess &access, const std::string &label) -{ - access.add("System", label, "rx"); - access.apply(); -} - -static void removeSmackAccessForDbus(SmackAccess &access) -{ - access.clear(); -} - -static pid_t assertFork() -{ - pid_t pid = fork(); - RUNNER_ASSERT_ERRNO_MSG(pid != -1, "fork() failed"); - return pid; -} - -RUNNER_TEST_GROUP_INIT(CYNARA_DBUS); - -static void testOwn(const std::string &testId, - const std::function &addBusconfigPolicyFunc, - bool allow) -{ - SmackAccess access; - const std::string label(smackLabelFromStr(testId)); - - addBusconfigPolicyFunc(testId); - addSmackAccessForDbus(access, label); - if (allow) - addCynaraPolicy(testId); - - sleep(1); - - pid_t pid = assertFork(); - - if (pid == 0) { - RUNNER_ASSERT(0 == smack_set_label_for_self(label.c_str())); - DBus::Connection client(DBUS_BUS_SYSTEM, true); - client.requestName(connectionNameFromStr(testId), - allow ? DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER : -1); - } else { - sleep(3); - removeSmackAccessForDbus(access); - assertUnlink(CONF_FILE_PATH); - } -} - -RUNNER_MULTIPROCESS_TEST_SMACK(tcc_1130_own_deny) -{ - testOwn("tcc1130", addBusconfigPolicyOwn, false); -} - -RUNNER_MULTIPROCESS_TEST_SMACK(tcc_1170_own_allow) -{ - testOwn("tcc1170", addBusconfigPolicyOwn, true); -} - -static void addBusconfigPolicyOwnPrefix(const std::string &id) -{ - BusConfigWriter writer; - writer.addPolicyCheck(privilegeFromStr(id), {{Attr::OWN_PREFIX, CONNECTION_NAME_PREFIX}}); - writer.save(); -} - -RUNNER_CHILD_TEST_SMACK(tcc_1230_own_prefix_deny) -{ - testOwn("tcc1230", addBusconfigPolicyOwnPrefix, false); -} - -RUNNER_CHILD_TEST_SMACK(tcc_1270_own_prefix_allow) -{ - testOwn("tcc1270", addBusconfigPolicyOwnPrefix, true); -} - -static void addBusconfigPolicySendAllows(BusConfigWriter &writer) -{ - writer.addPolicyAllow({{Attr::OWN_PREFIX, CONNECTION_NAME_PREFIX}}); - writer.addPolicyAllow({{Attr::RECEIVE_TYPE, MESSSAGE_TYPE_METHOD_CALL}}); -} - -static void addBusconfigPolicySendDestination(const std::string &testId) -{ - BusConfigWriter writer; - addBusconfigPolicySendAllows(writer); - writer.addPolicyCheck(privilegeFromStr(clientIdFromStr(testId)), - {{Attr::SEND_DESTINATION, connectionNameFromStr(serviceIdFromStr(testId))}}); - writer.save(); -} - -static void runMessageClient(const std::string &testId, bool changeLabel) -{ - const std::string clientId(clientIdFromStr(testId)); - const std::string serviceId(serviceIdFromStr(testId)); - const ServiceCreds serviceCreds(serviceId); - - sleep(1); - - if (changeLabel) - RUNNER_ASSERT(0 == smack_set_label_for_self(smackLabelFromStr(clientId).c_str())); - DBus::Connection client(DBUS_BUS_SYSTEM, true); - client.requestName(connectionNameFromStr(clientId)); - - DBus::MessageOut messageOut(serviceCreds.connectionName(), - serviceCreds.objectPath(), - serviceCreds.interface(), - memberFromStr(serviceId)); - client.send(messageOut); - client.flush(); - - sleep(1); -} - -static void runMessageService(const std::string &testId, bool changeLabel, - const std::string &errorStr, bool allow) -{ - const std::string clientId(clientIdFromStr(testId)); - const std::string serviceId(serviceIdFromStr(testId)); - const std::string member(memberFromStr(serviceId)); - const ServiceCreds serviceCreds(serviceId); - - if (changeLabel) - RUNNER_ASSERT(0 == smack_set_label_for_self(smackLabelFromStr(serviceId).c_str())); - - Service service(serviceCreds); - bool finish = false; - if (allow) { - service.insertMethodHandler( - member, - [&] (DBus::Connection &connection, - DBus::MessageIn &messageIn, - std::string &errorMessage)->void { - (void) connection; - (void) messageIn; - (void) errorMessage; - finish = true; - }); - } else { - service.insertMethodHandler( - member, - [&] (DBus::Connection &connection, - DBus::MessageIn &messageIn, - std::string &errorMessage)->void { - (void) connection; - (void) messageIn; - errorMessage = errorStr; - }); - } - service.run(finish, !allow); - - assertUnlink(CONF_FILE_PATH); -} - -static void testSend(const std::string &testId, - const std::function addBusconfigPolicyFunc, - bool allow) -{ - SmackAccess access; - const std::string clientId(clientIdFromStr(testId)); - const std::string serviceId(serviceIdFromStr(testId)); - - addBusconfigPolicyFunc(testId); - addSmackAccessForDbus(access, smackLabelFromStr(clientId)); - if (allow) - addCynaraPolicy(clientId); - - sleep(1); - - pid_t pid = assertFork(); - if (pid == 0) - runMessageClient(testId, true); - else - runMessageService(testId, false, - "Should not be able to send to " + connectionNameFromStr(serviceId), - allow); -} - -RUNNER_MULTIPROCESS_TEST_SMACK(tcc_2130_send_destination_deny) -{ - testSend("tcc2130", addBusconfigPolicySendDestination, false); -} - -RUNNER_MULTIPROCESS_TEST_SMACK(tcc_2170_send_destination_allow) -{ - testSend("tcc2170", addBusconfigPolicySendDestination, true); -} - -static void addBusconfigPolicySendPath(const std::string &testId) -{ - const ServiceCreds serviceCreds(serviceIdFromStr(testId)); - BusConfigWriter writer; - addBusconfigPolicySendAllows(writer); - writer.addPolicyCheck(privilegeFromStr(clientIdFromStr(testId)), - {{Attr::SEND_DESTINATION, serviceCreds.connectionName()}, - {Attr::SEND_PATH, serviceCreds.objectPath()}}); - writer.save(); -} - -RUNNER_MULTIPROCESS_TEST_SMACK(tcc_2230_send_path_deny) -{ - testSend("tcc2230", addBusconfigPolicySendPath, false); -} - -RUNNER_MULTIPROCESS_TEST_SMACK(tcc_2270_send_path_allow) -{ - testSend("tcc2270", addBusconfigPolicySendPath, true); -} - -static void addBusconfigPolicySendInterface(const std::string &testId) -{ - const ServiceCreds serviceCreds(serviceIdFromStr(testId)); - BusConfigWriter writer; - addBusconfigPolicySendAllows(writer); - writer.addPolicyCheck(privilegeFromStr(clientIdFromStr(testId)), - {{Attr::SEND_DESTINATION, serviceCreds.connectionName()}, - {Attr::SEND_INTERFACE, serviceCreds.interface()}}); - writer.save(); -} - -RUNNER_MULTIPROCESS_TEST_SMACK(tcc_2330_send_interface_deny) -{ - testSend("tcc2330", addBusconfigPolicySendInterface, false); -} - -RUNNER_MULTIPROCESS_TEST_SMACK(tcc_2370_send_interface_allow) -{ - testSend("tcc2370", addBusconfigPolicySendInterface, true); -} - -static void addBusconfigPolicySendType(const std::string &testId) -{ - const ServiceCreds serviceCreds(serviceIdFromStr(testId)); - BusConfigWriter writer; - addBusconfigPolicySendAllows(writer); - writer.addPolicyCheck(privilegeFromStr(clientIdFromStr(testId)), - {{Attr::SEND_DESTINATION, serviceCreds.connectionName()}, - {Attr::SEND_TYPE, MESSSAGE_TYPE_METHOD_CALL}}); - writer.save(); -} - -RUNNER_MULTIPROCESS_TEST_SMACK(tcc_2430_send_type_deny) -{ - testSend("tcc2430", addBusconfigPolicySendType, false); -} - -RUNNER_MULTIPROCESS_TEST_SMACK(tcc_2470_send_type_allow) -{ - testSend("tcc2470", addBusconfigPolicySendType, true); -} - -static void addBusconfigPolicySendMember(const std::string &testId) -{ - const std::string serviceId = serviceIdFromStr(testId); - const ServiceCreds serviceCreds(serviceId); - BusConfigWriter writer; - addBusconfigPolicySendAllows(writer); - writer.addPolicyCheck(privilegeFromStr(clientIdFromStr(testId)), - {{Attr::SEND_DESTINATION, serviceCreds.connectionName()}, - {Attr::SEND_INTERFACE, serviceCreds.interface()}, - {Attr::SEND_MEMBER, memberFromStr(serviceId)}}); - writer.save(); -} - -RUNNER_MULTIPROCESS_TEST_SMACK(tcc_2530_send_member_deny) -{ - testSend("tcc2530", addBusconfigPolicySendMember, false); -} - -RUNNER_MULTIPROCESS_TEST_SMACK(tcc_2570_send_member_allow) -{ - testSend("tcc2570", addBusconfigPolicySendMember, true); -} - -static void addBusconfigPolicySendError(const std::string &testId) -{ - const std::string serviceId(serviceIdFromStr(testId)); - const ServiceCreds serviceCreds(serviceId); - BusConfigWriter writer; - addBusconfigPolicySendAllows(writer); - writer.addPolicyAllow({{Attr::RECEIVE_TYPE, MESSSAGE_TYPE_ERROR}}); - writer.addPolicyAllow({{Attr::SEND_TYPE, MESSSAGE_TYPE_ERROR}}); - writer.addPolicyAllow({{Attr::SEND_TYPE, MESSSAGE_TYPE_METHOD_CALL}}); - writer.addPolicyAllow({{Attr::SEND_DESTINATION, serviceCreds.connectionName()}}); - writer.addPolicyCheck(privilegeFromStr(serviceId), - {{Attr::SEND_DESTINATION, connectionNameFromStr(clientIdFromStr(testId))}, - {Attr::SEND_ERROR, errorFromStr(serviceCreds.interface(), serviceId)}}); - writer.save(); -} - -static void runClientError(const std::string &testId, bool changeLabel, bool allow) -{ - const std::string clientId(clientIdFromStr(testId)); - const std::string serviceId(serviceIdFromStr(testId)); - const ServiceCreds serviceCreds(serviceId); - - sleep(1); - - if (changeLabel) - RUNNER_ASSERT(0 == smack_set_label_for_self(smackLabelFromStr(clientId).c_str())); - DBus::Connection client(DBUS_BUS_SYSTEM, true); - client.requestName(connectionNameFromStr(clientId)); - - DBus::MessageOut messageOut(serviceCreds.connectionName(), - serviceCreds.objectPath(), - serviceCreds.interface(), - memberFromStr(serviceId)); - - DBusError error; - dbus_error_init(&error); - DBus::ErrorPtr errorPtr(&error); - - DBusMessage* message = client.sendWithReplyAndBlock(messageOut, - 4000, - &error); - if (message != nullptr) { - DBus::MessageIn messageIn(message); - RUNNER_FAIL_MSG("message received is null"); - } - - std::string expectedErrorName; - if (allow) - expectedErrorName = errorFromStr(serviceCreds.interface(), serviceId); - else - expectedErrorName = "org.freedesktop.DBus.Error.NoReply"; - - RUNNER_ASSERT_MSG(expectedErrorName == error.name, - "Wrong error received." - << "\n Expected error name: " << expectedErrorName - << "\n Received error name: " << error.name - << "\n Received error message: " << error.message); - - assertUnlink(CONF_FILE_PATH); -} - -static void runServiceError(const std::string &testId, bool changeLabel) -{ - const std::string clientId(clientIdFromStr(testId)); - const std::string serviceId(serviceIdFromStr(testId)); - const ServiceCreds serviceCreds(serviceId); - - if (changeLabel) - RUNNER_ASSERT(0 == smack_set_label_for_self(smackLabelFromStr(serviceId).c_str())); - - Service service(serviceCreds); - bool finish = false; - service.insertMethodHandler( - memberFromStr(serviceId), - [&] (DBus::Connection &connection, - DBus::MessageIn &messageIn, - std::string &errorMessage)->void { - DBus::MessageOut messageOut(messageIn.getMessage(), - errorFromStr(serviceCreds.interface(), serviceId), - "Security-tests error message"); - connection.send(messageOut); - connection.flush(); - (void) errorMessage; - finish = true; - }); - service.run(finish, false); - - sleep(2); -} - -static void testSendError(const std::string &testId, bool allow) -{ - const std::string serviceId(serviceIdFromStr(testId)); - SmackAccess access; - addBusconfigPolicySendError(testId); - addSmackAccessForDbus(access, smackLabelFromStr(serviceId)); - if (allow) - addCynaraPolicy(serviceId); - - sleep(1); - - pid_t pid = assertFork(); - if (pid == 0) { - runServiceError(testId, true); - } else { - runClientError(testId, false, allow); - } -} - -RUNNER_MULTIPROCESS_TEST_SMACK(tcc_2630_send_error_deny) -{ - testSendError("tcc2630", false); -} - -RUNNER_MULTIPROCESS_TEST_SMACK(tcc_2670_send_error_allow) -{ - testSendError("tcc2670", true); -} - -static void addBusconfigPolicyReceiveAllows(BusConfigWriter &writer) -{ - writer.addPolicyAllow({{Attr::OWN_PREFIX, CONNECTION_NAME_PREFIX}}); - writer.addPolicyAllow({{Attr::SEND_TYPE, MESSSAGE_TYPE_METHOD_CALL}}); -} - -static void addBusconfigPolicyReceiveSender(const std::string &testId) -{ - BusConfigWriter writer; - addBusconfigPolicyReceiveAllows(writer); - writer.addPolicyCheck(privilegeFromStr(serviceIdFromStr(testId)), - {{Attr::RECEIVE_SENDER, connectionNameFromStr(clientIdFromStr(testId))}}); - writer.save(); -} - -static void testReceive(const std::string &testId, - const std::function addBusconfigPolicyFunc, - bool allow) -{ - const std::string clientId(clientIdFromStr(testId)); - const std::string serviceId(serviceIdFromStr(testId)); - addBusconfigPolicyFunc(testId); - SmackAccess access; - addSmackAccessForDbus(access, smackLabelFromStr(serviceId)); - if (allow) - addCynaraPolicy(serviceId); - - sleep(1); - - pid_t pid = assertFork(); - if (pid == 0) - runMessageService(testId, true, - "Should not be able to receive from " + connectionNameFromStr(clientId), - allow); - else - runMessageClient(testId, false); -} - -RUNNER_MULTIPROCESS_TEST_SMACK(tcc_3130_receive_sender_deny) -{ - testReceive("tcc3130", addBusconfigPolicyReceiveSender, false); -} - -RUNNER_MULTIPROCESS_TEST_SMACK(tcc_3170_receive_sender_allow) -{ - testReceive("tcc3170", addBusconfigPolicyReceiveSender, true); -} - -static void addBusconfigPolicyReceivePath(const std::string &testId) -{ - const ServiceCreds serviceCreds(serviceIdFromStr(testId)); - BusConfigWriter writer; - addBusconfigPolicyReceiveAllows(writer); - writer.addPolicyCheck(privilegeFromStr(serviceIdFromStr(testId)), - {{Attr::RECEIVE_SENDER, connectionNameFromStr(clientIdFromStr(testId))}, - {Attr::RECEIVE_PATH, serviceCreds.objectPath()}}); - writer.save(); -} - -RUNNER_MULTIPROCESS_TEST_SMACK(tcc_3230_receive_path_deny) -{ - testReceive("tcc3230", addBusconfigPolicyReceivePath, false); -} - -RUNNER_MULTIPROCESS_TEST_SMACK(tcc_3270_receive_path_allow) -{ - testReceive("tcc3270", addBusconfigPolicyReceivePath, true); -} - -static void addBusconfigPolicyReceiveInterface(const std::string &testId) -{ - const ServiceCreds serviceCreds(serviceIdFromStr(testId)); - BusConfigWriter writer; - addBusconfigPolicyReceiveAllows(writer); - writer.addPolicyCheck(privilegeFromStr(serviceIdFromStr(testId)), - {{Attr::RECEIVE_SENDER, connectionNameFromStr(clientIdFromStr(testId))}, - {Attr::RECEIVE_INTERFACE, serviceCreds.interface()}}); - writer.save(); -} - -RUNNER_MULTIPROCESS_TEST_SMACK(tcc_3330_receive_interface_deny) -{ - testReceive("tcc3330", addBusconfigPolicyReceiveInterface, false); -} - -RUNNER_MULTIPROCESS_TEST_SMACK(tcc_3370_receive_interface_allow) -{ - testReceive("tcc3370", addBusconfigPolicyReceiveInterface, true); -} - -static void addBusconfigPolicyReceiveType(const std::string &testId) -{ - BusConfigWriter writer; - addBusconfigPolicyReceiveAllows(writer); - writer.addPolicyCheck(privilegeFromStr(serviceIdFromStr(testId)), - {{Attr::RECEIVE_SENDER, connectionNameFromStr(clientIdFromStr(testId))}, - {Attr::RECEIVE_TYPE, MESSSAGE_TYPE_METHOD_CALL}}); - writer.save(); -} - -RUNNER_MULTIPROCESS_TEST_SMACK(tcc_3430_receive_type_deny) -{ - testReceive("tcc3430", addBusconfigPolicyReceiveType, false); -} - -RUNNER_MULTIPROCESS_TEST_SMACK(tcc_3470_receive_interface_allow) -{ - testReceive("tcc3470", addBusconfigPolicyReceiveType, true); -} - -static void addBusconfigPolicyReceiveMember(const std::string &testId) -{ - const std::string serviceId(serviceIdFromStr(testId)); - const ServiceCreds serviceCreds(serviceId); - BusConfigWriter writer; - addBusconfigPolicyReceiveAllows(writer); - writer.addPolicyCheck(privilegeFromStr(serviceId), - {{Attr::RECEIVE_SENDER, connectionNameFromStr(clientIdFromStr(testId))}, - {Attr::RECEIVE_INTERFACE, serviceCreds.interface()}, - {Attr::RECEIVE_MEMBER, memberFromStr(serviceId)}}); - writer.save(); -} - -RUNNER_MULTIPROCESS_TEST_SMACK(tcc_3530_receive_member_deny) -{ - testReceive("tcc3530", addBusconfigPolicyReceiveMember, false); -} - -RUNNER_MULTIPROCESS_TEST_SMACK(tcc_3570_receive_member_allow) -{ - testReceive("tcc3570", addBusconfigPolicyReceiveMember, true); -} - -static void addBusconfigPolicyReceiveError(const std::string &testId) -{ - const std::string clientId(clientIdFromStr(testId)); - const std::string serviceId(serviceIdFromStr(testId)); - const ServiceCreds serviceCreds(serviceId); - BusConfigWriter writer; - addBusconfigPolicyReceiveAllows(writer); - writer.addPolicyAllow({{Attr::SEND_TYPE, MESSSAGE_TYPE_ERROR}}); - writer.addPolicyAllow({{Attr::RECEIVE_TYPE, MESSSAGE_TYPE_ERROR}}); - writer.addPolicyAllow({{Attr::RECEIVE_TYPE, MESSSAGE_TYPE_METHOD_CALL}}); - writer.addPolicyAllow({{Attr::SEND_DESTINATION, serviceCreds.connectionName()}}); - writer.addPolicyAllow({{Attr::SEND_DESTINATION, connectionNameFromStr(clientId)}}); - writer.addPolicyCheck(privilegeFromStr(clientId), - {{Attr::RECEIVE_SENDER, serviceCreds.connectionName()}, - {Attr::RECEIVE_ERROR, errorFromStr(serviceCreds.interface(), serviceId)}}); - writer.save(); -} - -static void testReceiveError(const std::string &testId, bool allow) -{ - const std::string clientId(clientIdFromStr(testId)); - addBusconfigPolicyReceiveError(testId); - SmackAccess access; - addSmackAccessForDbus(access, smackLabelFromStr(clientId)); - if (allow) - addCynaraPolicy(clientId); - - sleep(1); - - pid_t pid = assertFork(); - if (pid == 0) { - runClientError(testId, true, allow); - } else { - runServiceError(testId, false); - } -} - -RUNNER_MULTIPROCESS_TEST_SMACK(tcc_3630_receive_error_deny) -{ - testReceiveError("tcc3630", false); -} - -RUNNER_MULTIPROCESS_TEST_SMACK(tcc_3670_receive_error_allow) -{ - testReceiveError("tcc3670", true); -} diff --git a/tests/dbus-tests/main.cpp b/tests/dbus-tests/main.cpp deleted file mode 100644 index 8d2261b7..00000000 --- a/tests/dbus-tests/main.cpp +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2014 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 main.cpp - * @author Marcin Niesluchowski (m.niesluchow@samsung.com) - * @version 1.0 - * @brief main for dbus tests - */ - -#include - -int main(int argc, char *argv[]) -{ - return DPL::Test::TestRunnerSingleton::Instance().ExecTestRunner(argc, argv); -} diff --git a/tests/dbus-tests/smack_dbus_tests.cpp b/tests/dbus-tests/smack_dbus_tests.cpp deleted file mode 100644 index a17b5431..00000000 --- a/tests/dbus-tests/smack_dbus_tests.cpp +++ /dev/null @@ -1,300 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include "tests_common.h" - -#define DBUS_SERVER_NAME "test.method.server" -#define DBUS_CALLER_NAME "test.method.caller" - -#define DBUS_SMACK_NAME "org.freedesktop.DBus" -#define DBUS_SMACK_OBJECT "/org/freedesktop/DBus" -#define DBUS_SMACK_INTERFACE "org.freedesktop.DBus" -#define DBUS_SMACK_METHOD "GetConnectionCredentials" - -RUNNER_TEST_GROUP_INIT(SMACK_DBUS); - -RUNNER_MULTIPROCESS_TEST_SMACK(tcs_01_smack_context_from_DBus) -{ - RUNNER_IGNORED_MSG("dbus does not support smack context in GetConnectionCredentials method" - " yet."); - - int ret = -1; - const char *subject_parent = "subject_parent"; - const char *subject_child = "subject_child"; - - DBusMessage* msg = nullptr; - DBusMessageIter args, iter, var, var_iter, var_value; - DBusConnection* conn = nullptr; - DBusError err; - DBusPendingCall *pending = nullptr; - const char *dbus_server_name = DBUS_SERVER_NAME; - char *smack_context = nullptr; - - pid_t pid = fork(); - RUNNER_ASSERT_ERRNO_MSG(-1 != pid, "fork() failed"); - - if (pid == 0) { - // child - ret = smack_set_label_for_self(subject_child); - RUNNER_ASSERT_MSG(ret == PC_OPERATION_SUCCESS, - "smack_set__label_for_self() failed, ret: " << ret); - - // initialize the errors - dbus_error_init(&err); - - // connect to the system bus and check for errors - conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err); - ret = dbus_error_is_set(&err); - if (1 == ret) { - dbus_error_free(&err); - RUNNER_ASSERT_MSG(0 == ret, "dbus_bus_get() failed, ret: " << ret); - } - - // request our name on the bus - ret = dbus_bus_request_name(conn, DBUS_CALLER_NAME, DBUS_NAME_FLAG_REPLACE_EXISTING , &err); - if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) { - dbus_error_free(&err); - RUNNER_ASSERT_MSG(DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret, - "dbus_bus_request_name() failed, ret: " << ret); - } - - // crate a new method call for checking SMACK context from DBus interface - msg = dbus_message_new_method_call(DBUS_SMACK_NAME, - DBUS_SMACK_OBJECT, - DBUS_SMACK_INTERFACE, - DBUS_SMACK_METHOD); - - RUNNER_ASSERT_MSG(nullptr != msg, - "dbus_message_new_method_call() failed, ret: " << ret); - - // append arguments, we need SMACK context for our parent process "test.method.server" - dbus_message_iter_init_append(msg, &args); - ret = dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &dbus_server_name); - RUNNER_ASSERT_MSG(1 == ret, "Out of memory"); - - // wait for parent to connect to DBus - sleep(3); - - // send message and get a handle for a reply - // -1 is default timeout - ret = dbus_connection_send_with_reply (conn, msg, &pending, -1); - RUNNER_ASSERT_MSG(1 == ret, "Out of memory"); - RUNNER_ASSERT_MSG(nullptr != pending, "Pending call null"); - - dbus_connection_flush(conn); - - // free message - dbus_message_unref(msg); - - // block until reply - dbus_pending_call_block(pending); - - // get the reply - msg = dbus_pending_call_steal_reply(pending); - RUNNER_ASSERT_MSG(nullptr != msg, "Reply null"); - - // free message handle - dbus_pending_call_unref(pending); - - ret = dbus_message_iter_init(msg, &iter); - RUNNER_ASSERT_MSG(0 != ret, "Message has no arguments"); - - dbus_message_iter_recurse(&iter, &var); - - while (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_INVALID) { - dbus_message_iter_recurse(&var, &var_iter); - while(dbus_message_iter_get_arg_type(&var_iter) != DBUS_TYPE_INVALID) { - dbus_message_iter_recurse(&var_iter, &var_value); - switch(dbus_message_iter_get_arg_type(&var_value)) { - case DBUS_TYPE_STRING: - dbus_message_iter_get_basic(&var_value, &smack_context); - break; - default: - ; - } - dbus_message_iter_next(&var_iter); - } - dbus_message_iter_next(&var); - } - - // free reply and close connection - dbus_message_unref(msg); - dbus_connection_unref(conn); - - RUNNER_ASSERT(smack_context != nullptr); - ret = strcmp(smack_context, subject_parent); - RUNNER_ASSERT_MSG(0 == ret, - "Context mismatch! context from dbus: " << smack_context); - - exit(0); - - } else { - // parent - ret = smack_set_label_for_self(subject_parent); - RUNNER_ASSERT_MSG(ret == PC_OPERATION_SUCCESS, - "smack_set_label_for_self() failed, ret: " << ret); - - // initialise the error - dbus_error_init(&err); - - // connect to the bus and check for errors - conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err); - ret = dbus_error_is_set(&err); - if (1 == ret) { - dbus_error_free(&err); - RUNNER_ASSERT_MSG(0 == ret, "dbus_bus_get() failed, ret: " << ret); - } - - // request our name on the bus and check for errors - ret = dbus_bus_request_name(conn, DBUS_SERVER_NAME, DBUS_NAME_FLAG_REPLACE_EXISTING , &err); - if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) { - dbus_error_free(&err); - RUNNER_ASSERT_MSG(DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret, - "dbus_bus_request_name() failed, ret: " << ret); - } - - // close the connection - dbus_connection_unref(conn); - } -} - -/////////////////////////////////////// -//////NOSMACK ENV TESTS//////////////// -/////////////////////////////////////// - -RUNNER_MULTIPROCESS_TEST_NOSMACK(tcs_01_smack_context_from_DBus_nosmack) -{ - RUNNER_IGNORED_MSG("dbus does not support smack context in GetConnectionCredentials method" - " yet."); - - int ret = -1; - const char* subject_parent = "subject_parent"; - - DBusMessage* msg = nullptr; - DBusMessageIter args, iter, var, var_iter, var_value; - DBusConnection* conn = nullptr; - DBusError err; - DBusPendingCall *pending = nullptr; - const char *dbus_server_name = DBUS_SERVER_NAME; - char *smack_context = nullptr; - - pid_t pid = fork(); - RUNNER_ASSERT_ERRNO_MSG(-1 != pid, "fork() failed"); - - if (pid == 0) { - // child - - // initialize the errors - dbus_error_init(&err); - - // connect to the system bus and check for errors; failure = exit with result 1 - conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err); - ret = dbus_error_is_set(&err); - if (1 == ret) { - dbus_error_free(&err); - RUNNER_FAIL_MSG("Failed to connect to system bus. Ret " << ret); - } - - // request our name on the bus; failure = exit with result 2 - ret = dbus_bus_request_name(conn, DBUS_CALLER_NAME, DBUS_NAME_FLAG_REPLACE_EXISTING , &err); - if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) { - dbus_error_free(&err); - RUNNER_FAIL_MSG("Failed to request name on the bus. Ret " << ret); - } - - // crate a new method call for checking SMACK context from DBus interface - msg = dbus_message_new_method_call(DBUS_SMACK_NAME, - DBUS_SMACK_OBJECT, - DBUS_SMACK_INTERFACE, - DBUS_SMACK_METHOD); - - RUNNER_ASSERT_MSG(msg != nullptr, "dbus_message_new_method_call() failed."); - - // append arguments, we need SMACK context for our parent process "test.method.server" - dbus_message_iter_init_append(msg, &args); - ret = dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &dbus_server_name); - RUNNER_ASSERT_MSG(ret == 1, "Out of memory. Ret " << ret); - - // wait for parent to connect to DBus - sleep(3); - - // send message and get a handle for a reply - // -1 is default timeout - ret = dbus_connection_send_with_reply (conn, msg, &pending, -1); - RUNNER_ASSERT_MSG(ret == 1, "Out of memory. Ret " << ret); - RUNNER_ASSERT_MSG(pending != nullptr, "Pending call is nullptr."); - - dbus_connection_flush(conn); - - // free message - dbus_message_unref(msg); - - // block until reply - dbus_pending_call_block(pending); - - // get the reply - msg = dbus_pending_call_steal_reply(pending); - RUNNER_ASSERT_MSG(msg != nullptr, "Failed to get the reply from bus."); - - // free message handle - dbus_pending_call_unref(pending); - - ret = dbus_message_iter_init(msg, &iter); - RUNNER_ASSERT_MSG(ret != 0, "DBus message has no arguments. Ret " << ret); - - dbus_message_iter_recurse(&iter, &var); - while (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_INVALID) { - dbus_message_iter_recurse(&var, &var_iter); - while(dbus_message_iter_get_arg_type(&var_iter) != DBUS_TYPE_INVALID) { - dbus_message_iter_recurse(&var_iter, &var_value); - switch(dbus_message_iter_get_arg_type(&var_value)) { - case DBUS_TYPE_STRING: - dbus_message_iter_get_basic(&var_value, &smack_context); - break; - default: - ; - } - dbus_message_iter_next(&var_iter); - } - dbus_message_iter_next(&var); - } - - // free reply and close connection - dbus_message_unref(msg); - dbus_connection_unref(conn); - - RUNNER_ASSERT(smack_context != nullptr); - ret = strcmp(smack_context, subject_parent); - RUNNER_ASSERT_MSG(ret == 0, "Context mismatch. Context " << smack_context); - - exit(0); - - } else { - // parent - - // initialise the error - dbus_error_init(&err); - - // connect to the bus and check for errors - conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err); - ret = dbus_error_is_set(&err); - if (1 == ret) { - dbus_error_free(&err); - RUNNER_ASSERT_MSG(0 == ret, "dbus_bus_get() failed, ret: " << ret); - } - - // request our name on the bus and check for errors - ret = dbus_bus_request_name(conn, DBUS_SERVER_NAME, DBUS_NAME_FLAG_REPLACE_EXISTING , &err); - if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) { - dbus_error_free(&err); - RUNNER_ASSERT_MSG(DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret, - "dbus_bus_request_name() failed, ret: " << ret); - } - - // close the connection - dbus_connection_unref(conn); - } -} diff --git a/tests/smack-dbus-tests/CMakeLists.txt b/tests/smack-dbus-tests/CMakeLists.txt new file mode 100644 index 00000000..a263055e --- /dev/null +++ b/tests/smack-dbus-tests/CMakeLists.txt @@ -0,0 +1,67 @@ +# +#Copyright (c) 2014-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 Michal Eljasiewicz (m.eljasiewic@samsung.com) +# @brief +# + +INCLUDE(FindPkgConfig) + +# Dependencies +PKG_CHECK_MODULES(DBUS_TESTS_DEP + libsmack + cynara-admin + dbus-1 + REQUIRED) + +# Targets definition + +INCLUDE_DIRECTORIES(SYSTEM + ${DBUS_TESTS_DEP_INCLUDE_DIRS} + ) + +SET(TARGET_DBUS_TESTS "dbus-tests") + +# Sources definition + +SET(DBUS_TESTS_SOURCES + ${PROJECT_SOURCE_DIR}/tests/cynara-tests/common/cynara_test_admin.cpp + ${PROJECT_SOURCE_DIR}/tests/dbus-tests/common/dbus_test_commons.cpp + ${PROJECT_SOURCE_DIR}/tests/dbus-tests/common/dbus_test_service.cpp + ${PROJECT_SOURCE_DIR}/tests/dbus-tests/common/dbus_test_service_object.cpp + ${PROJECT_SOURCE_DIR}/tests/dbus-tests/main.cpp + ${PROJECT_SOURCE_DIR}/tests/dbus-tests/common/dbus_test_busconfig_writer.cpp + ${PROJECT_SOURCE_DIR}/tests/dbus-tests/cynara_dbus_tests.cpp + ${PROJECT_SOURCE_DIR}/tests/dbus-tests/smack_dbus_tests.cpp + ) + +INCLUDE_DIRECTORIES( + ${PROJECT_SOURCE_DIR}/tests/common/ + ${PROJECT_SOURCE_DIR}/tests/cynara-tests/common/ + ${PROJECT_SOURCE_DIR}/tests/dbus-tests/common/ + ) + +ADD_EXECUTABLE(${TARGET_DBUS_TESTS} ${DBUS_TESTS_SOURCES}) + +TARGET_LINK_LIBRARIES(${TARGET_DBUS_TESTS} + ${DBUS_TESTS_DEP_LIBRARIES} + dpl-test-framework + tests-common + ) + +# Installation + +INSTALL(TARGETS ${TARGET_DBUS_TESTS} DESTINATION /usr/bin) diff --git a/tests/smack-dbus-tests/common/dbus_test_busconfig_writer.cpp b/tests/smack-dbus-tests/common/dbus_test_busconfig_writer.cpp new file mode 100644 index 00000000..1f5cc198 --- /dev/null +++ b/tests/smack-dbus-tests/common/dbus_test_busconfig_writer.cpp @@ -0,0 +1,163 @@ +/* + * 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 dbus_test_busconfig_writer.cpp + * @author Marcin Niesluchowski + * @version 1.0 + * @brief dbus test busconfig writer definition + */ + +#include + +#include + +#include +#include + +namespace DBusTest { + +namespace { + +const char* const BUSCONFIG_ENCODING = "ISO-8859-1"; + +const std::map ATTR_MAP = { + { Attr::OWN, "own" }, + { Attr::OWN_PREFIX, "own_prefix" }, + + { Attr::SEND_DESTINATION, "send_destination" }, + { Attr::SEND_PATH, "send_path" }, + { Attr::SEND_INTERFACE, "send_interface" }, + { Attr::SEND_TYPE, "send_type" }, + { Attr::SEND_MEMBER, "send_member" }, + { Attr::SEND_ERROR, "send_error" }, + + { Attr::RECEIVE_SENDER, "receive_sender" }, + { Attr::RECEIVE_PATH, "receive_path" }, + { Attr::RECEIVE_INTERFACE, "receive_interface" }, + { Attr::RECEIVE_TYPE, "receive_type" }, + { Attr::RECEIVE_MEMBER, "receive_member" }, + { Attr::RECEIVE_ERROR, "receive_error" } +}; + +} + +const std::string VAL_ALL = "*"; +const std::string CONF_FILE_PATH("/etc/dbus-1/system.d/security_tests_dbus_tests.conf"); + +BusConfigWriter::BusConfigWriter() + : m_writer(nullptr) + , m_doc(nullptr) +{ + RUNNER_ASSERT_MSG(0 == unlink(CONF_FILE_PATH.c_str()) || errno == ENOENT, + "Unable to unlink existing file " << CONF_FILE_PATH << " file"); + + m_writer = xmlNewTextWriterDoc(&m_doc, 0); + RUNNER_ASSERT_MSG(m_writer, "xmlNewTextWriterDoc failed"); + + RUNNER_ASSERT(0 <= xmlTextWriterStartDocument(m_writer, NULL, BUSCONFIG_ENCODING, NULL)); + + RUNNER_ASSERT(0 <= xmlTextWriterWriteDTD( + m_writer, + BAD_CAST "busconfig", + BAD_CAST "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN", + BAD_CAST "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd", + NULL)); + + startElement("busconfig"); + + writeElement("type", "system"); + + startElement("policy"); + writeAttribute("context", "default"); +} + +BusConfigWriter::~BusConfigWriter() +{ + if (m_doc) + xmlFreeDoc(m_doc); + if (m_writer) + xmlFreeTextWriter(m_writer); +} + +void BusConfigWriter::addPolicyAllow(const AttrValVec &attrValVec) +{ + startElement("allow"); + for (const auto &attrVal : attrValVec) + writeAttribute(attrVal); + endElement(); +} + +void BusConfigWriter::addPolicyDeny(const AttrValVec &attrValVec) +{ + startElement("deny"); + for (const auto &attrVal : attrValVec) + writeAttribute(attrVal); + endElement(); +} + +void BusConfigWriter::addPolicyCheck(const std::string &privilege, const AttrValVec &attrValVec) +{ + startElement("check"); + for (const auto &attrVal : attrValVec) + writeAttribute(attrVal); + writeAttribute("privilege", privilege); + endElement(); +} + +void BusConfigWriter::save() +{ + endElement(); + endElement(); + + RUNNER_ASSERT(0 <= xmlTextWriterEndDocument(m_writer)); + + RUNNER_ASSERT_MSG(0 <= xmlSaveFileEnc(CONF_FILE_PATH.c_str(), m_doc, BUSCONFIG_ENCODING), + "Unable to save doc file: " << CONF_FILE_PATH); +} + +void BusConfigWriter::startElement(const std::string &element) +{ + RUNNER_ASSERT_MSG(0 <= xmlTextWriterStartElement(m_writer, BAD_CAST element.c_str()), + "Unable to start element: " << element); +} + +void BusConfigWriter::writeAttribute(const std::string &attr, const std::string &val) +{ + RUNNER_ASSERT_MSG(0 <= xmlTextWriterWriteAttribute(m_writer, + BAD_CAST attr.c_str(), + BAD_CAST val.c_str()), + "Unable to write attribute: " << attr << "=\"" << val << "\""); +} + +void BusConfigWriter::writeAttribute(const AttrVal &attrVal) +{ + writeAttribute(ATTR_MAP.at(attrVal.attr), attrVal.val); +} + +void BusConfigWriter::endElement() +{ + RUNNER_ASSERT(0 <= xmlTextWriterEndElement(m_writer)); +} + +void BusConfigWriter::writeElement(const std::string &element, const std::string &content) +{ + RUNNER_ASSERT_MSG(0 <= xmlTextWriterWriteElement(m_writer, + BAD_CAST element.c_str(), + BAD_CAST content.c_str()), + "Unable to write element: " << element << "; content: " << content); +} + +} diff --git a/tests/smack-dbus-tests/common/dbus_test_busconfig_writer.h b/tests/smack-dbus-tests/common/dbus_test_busconfig_writer.h new file mode 100644 index 00000000..7b41bbf5 --- /dev/null +++ b/tests/smack-dbus-tests/common/dbus_test_busconfig_writer.h @@ -0,0 +1,90 @@ +/* + * 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 dbus_test_busconfig_writer.h + * @author Marcin Niesluchowski + * @version 1.0 + * @brief dbus test busconfig writer declaration + */ + +#ifndef DBUS_TEST_BUSCONFIG_WRITER +#define DBUS_TEST_BUSCONFIG_WRITER + +#include + +#include +#include + +namespace DBusTest { + +enum class Attr +{ + OWN, + OWN_PREFIX, + + SEND_DESTINATION, + SEND_PATH, + SEND_INTERFACE, + SEND_TYPE, + SEND_MEMBER, + SEND_ERROR, + + RECEIVE_SENDER, + RECEIVE_PATH, + RECEIVE_INTERFACE, + RECEIVE_TYPE, + RECEIVE_MEMBER, + RECEIVE_ERROR +}; + +struct AttrVal +{ + Attr attr; + std::string val; +}; + +extern const std::string VAL_ALL; +extern const std::string CONF_FILE_PATH; + +typedef std::vector AttrValVec; + +class BusConfigWriter +{ +public: + BusConfigWriter(); + ~BusConfigWriter(); + + void addPolicyAllow(const AttrValVec &attrValVec); + void addPolicyDeny(const AttrValVec &attrValVec); + void addPolicyCheck(const std::string &privilege, const AttrValVec &attrValVec); + + void save(); + +private: + void startElement(const std::string &element); + void writeAttribute(const std::string &attr, const std::string &val); + void writeAttribute(const AttrVal &attrVal); + void endElement(); + void writeElement(const std::string &element, const std::string &content); + + xmlTextWriterPtr m_writer; + xmlDocPtr m_doc; + std::string m_filePath; +}; + +} + +#endif // DBUS_TEST_BUSCONFIG_WRITER diff --git a/tests/smack-dbus-tests/common/dbus_test_commons.cpp b/tests/smack-dbus-tests/common/dbus_test_commons.cpp new file mode 100644 index 00000000..548d015a --- /dev/null +++ b/tests/smack-dbus-tests/common/dbus_test_commons.cpp @@ -0,0 +1,35 @@ +/* + * 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 dbus_test_commons.cpp + * @author Marcin Niesluchowski + * @version 1.0 + * @brief commons for dbus test files + */ + +#include + +namespace DBusTest +{ + +const std::string CONNECTION_NAME_PREFIX("com.security_tests"); + +const std::string connectionNameFromStr(const std::string &str) +{ + return CONNECTION_NAME_PREFIX + "." + str; +} + +} diff --git a/tests/smack-dbus-tests/common/dbus_test_commons.h b/tests/smack-dbus-tests/common/dbus_test_commons.h new file mode 100644 index 00000000..24090635 --- /dev/null +++ b/tests/smack-dbus-tests/common/dbus_test_commons.h @@ -0,0 +1,37 @@ +/* + * 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 dbus_test_commons.h + * @author Marcin Niesluchowski + * @version 1.0 + * @brief commons for dbus test files + */ + +#ifndef DBUS_TESTS_COMMON_DBUS_TEST_COMMONS_H +#define DBUS_TESTS_COMMON_DBUS_TEST_COMMONS_H + +#include + +namespace DBusTest +{ + +extern const std::string CONNECTION_NAME_PREFIX; + +const std::string connectionNameFromStr(const std::string &str); + +} + +#endif // DBUS_TESTS_COMMON_DBUS_TEST_COMMONS_H diff --git a/tests/smack-dbus-tests/common/dbus_test_service.cpp b/tests/smack-dbus-tests/common/dbus_test_service.cpp new file mode 100644 index 00000000..81da52b7 --- /dev/null +++ b/tests/smack-dbus-tests/common/dbus_test_service.cpp @@ -0,0 +1,127 @@ +/* + * 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 dbus_test_service.cpp + * @author Marcin Niesluchowski + * @version 1.0 + * @brief dbus test service definition + */ + +#include +#include + +#include + +#include + +namespace { + +const std::string OBJECT_PATH_DIR("/com/security_tests/"); +const std::string INTERFACE_SUFFIX("TestInterface"); + +} + +namespace DBusTest +{ + +ServiceCreds::ServiceCreds(const std::string &name) + : m_connectionName(connectionNameFromStr(name)) + , m_objectPath(OBJECT_PATH_DIR + name) + , m_interface(m_connectionName + "." + INTERFACE_SUFFIX) +{ +} + +const std::string& ServiceCreds::connectionName() const +{ + return m_connectionName; +} + +const std::string& ServiceCreds::objectPath() const +{ + return m_objectPath; +} + +const std::string& ServiceCreds::interface() const +{ + return m_interface; +} + +Service::Service(const ServiceCreds &serviceCreds) + : m_connection(DBUS_BUS_SYSTEM, true) + , m_object(serviceCreds.interface()) + , m_messageReceived(false) + , m_exceptionThrown(false) +{ + m_connection.requestName(serviceCreds.connectionName()); + m_connection.registerObjectPath(serviceCreds.objectPath(), + handleMessage, + (void*)this); +} + +void Service::insertMethodHandler(const std::string &method, + const MessageHandler &messageHandler) +{ + m_object.insertMethodHandler(method, messageHandler); +} + +DBusHandlerResult Service::handleMessage(DBusConnection *connection, + DBusMessage *message, + void *userData) +{ + Service* service = reinterpret_cast(userData); + (void)userData; + try { + service->m_messageReceived = true; + DBus::MessageIn messageIn(message, true); + DBus::Connection conn(connection); + service->m_object.handleMessage(conn, messageIn, service->m_errorString); + } catch(...) { + service->m_exceptionThrown = true; + } + return DBUS_HANDLER_RESULT_HANDLED; +} + +void Service::run(bool &finish, bool timeout) +{ + using namespace std::chrono; + high_resolution_clock::time_point tpEnd = high_resolution_clock::now() + seconds(5); + while (!finish) { + m_connection.readWrite(1000); + + high_resolution_clock::time_point tp = high_resolution_clock::now(); + if (tp > tpEnd) { + if (timeout) + return; + RUNNER_FAIL_MSG("Timeout not expected"); + } + + while(true) { + m_errorString.clear(); + m_exceptionThrown = false; + + m_connection.dispatch(); + if (!m_messageReceived) + break; + m_messageReceived = false; + + RUNNER_ASSERT_MSG(!m_exceptionThrown, "Exception thrown while handling message"); + RUNNER_ASSERT_MSG(m_errorString.empty(), "Error while handling dispatched message. " + << m_errorString); + } + } +} + +} // namespace DBusTest diff --git a/tests/smack-dbus-tests/common/dbus_test_service.h b/tests/smack-dbus-tests/common/dbus_test_service.h new file mode 100644 index 00000000..bf986df5 --- /dev/null +++ b/tests/smack-dbus-tests/common/dbus_test_service.h @@ -0,0 +1,78 @@ +/* + * 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 dbus_test_service.h + * @author Marcin Niesluchowski + * @version 1.0 + * @brief dbus test service declaration + */ + +#ifndef DBUS_TESTS_COMMON_DBUS_TEST_SERVICE_H +#define DBUS_TESTS_COMMON_DBUS_TEST_SERVICE_H + +#include + +#include + +#include + +namespace DBusTest +{ + +class ServiceCreds +{ +public: + ServiceCreds(const std::string &name); + ~ServiceCreds() = default; + + const std::string& connectionName() const; + const std::string& objectPath() const; + const std::string& interface() const; + +private: + std::string m_connectionName; + std::string m_objectPath; + std::string m_interface; +}; + +class Service +{ +public: + Service(const ServiceCreds &serviceCreds); + Service(const Service &other) = delete; + ~Service() = default; + + Service& operator=(const Service &other) = delete; + + void insertMethodHandler(const std::string &method, + const MessageHandler &messageHandler); + void run(bool &finish, bool timeout); + +private: + static DBusHandlerResult handleMessage(DBusConnection *connection, + DBusMessage *message, + void *userData); + + DBus::Connection m_connection; + ServiceObject m_object; + bool m_messageReceived; + bool m_exceptionThrown; + std::string m_errorString; +}; + +} // namespace DBusTest + +#endif // DBUS_TESTS_COMMON_DBUS_TEST_SERVICE_H diff --git a/tests/smack-dbus-tests/common/dbus_test_service_object.cpp b/tests/smack-dbus-tests/common/dbus_test_service_object.cpp new file mode 100644 index 00000000..8cc1ca6c --- /dev/null +++ b/tests/smack-dbus-tests/common/dbus_test_service_object.cpp @@ -0,0 +1,58 @@ +/* + * 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 dbus_test_service_object.cpp + * @author Marcin Niesluchowski + * @version 1.0 + * @brief Definition of dbus test service object class for handling + * incoming messages + */ + +#include + +namespace DBusTest +{ + +ServiceObject::ServiceObject(const std::string &interface) + : m_interface(interface) +{ +} + +const std::string& ServiceObject::interface() const +{ + return m_interface; +} + +void ServiceObject::insertMethodHandler(const std::string &method, + const MessageHandler &messageHandler) +{ + m_methodHandlers[method] = messageHandler; +} + +void ServiceObject::handleMessage(DBus::Connection &connection, + DBus::MessageIn &messageIn, + std::string &errorStr) +{ + for (auto &methodHandler : m_methodHandlers) { + if (messageIn.isMethodCall(m_interface, methodHandler.first)) { + methodHandler.second(connection, messageIn, errorStr); + return; + } + } + errorStr = "Received unregistered message"; +} + +} // namespace DBusTest diff --git a/tests/smack-dbus-tests/common/dbus_test_service_object.h b/tests/smack-dbus-tests/common/dbus_test_service_object.h new file mode 100644 index 00000000..d2692c25 --- /dev/null +++ b/tests/smack-dbus-tests/common/dbus_test_service_object.h @@ -0,0 +1,64 @@ +/* + * 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 dbus_test_service_object.h + * @author Marcin Niesluchowski + * @version 1.0 + * @brief Declaration of dbus test service object class for handling + * incoming messages + */ + +#ifndef DBUS_TESTS_COMMON_DBUS_TEST_SERVICE_OBJECT_H +#define DBUS_TESTS_COMMON_DBUS_TEST_SERVICE_OBJECT_H + +#include +#include + +#include +#include +#include + +namespace DBusTest +{ + +using MessageHandler = std::function; + +class ServiceObject +{ +public: + ServiceObject(const std::string &interface); + ServiceObject(const ServiceObject &other) = delete; + ~ServiceObject() = default; + + ServiceObject& operator=(const ServiceObject &other) = delete; + + const std::string& interface() const; + void insertMethodHandler(const std::string &method, + const MessageHandler &messageHandler); + void handleMessage(DBus::Connection &connection, + DBus::MessageIn &messageIn, + std::string &errorStr); + +private: + std::map m_methodHandlers; + std::string m_interface; +}; + +} // namespace DBusTest + +#endif // DBUS_TESTS_COMMON_DBUS_TEST_SERVICE_OBJECT_H diff --git a/tests/smack-dbus-tests/cynara_dbus_tests.cpp b/tests/smack-dbus-tests/cynara_dbus_tests.cpp new file mode 100644 index 00000000..1ac4d091 --- /dev/null +++ b/tests/smack-dbus-tests/cynara_dbus_tests.cpp @@ -0,0 +1,671 @@ +/* + * 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 cynara_dbus_tests.cpp + * @author Marcin Niesluchowski (m.niesluchow@samsung.com) + * @version 1.0 + * @brief Tests for cynara checks implemented in dbus + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +using namespace DBusTest; + +static const std::string ROOT_UID_STR("0"); +static const std::string MESSSAGE_TYPE_METHOD_CALL = "method_call"; +static const std::string MESSSAGE_TYPE_ERROR = "error"; + +static const std::string clientIdFromStr(const std::string &str) +{ + return str + "Client"; +} + +static const std::string serviceIdFromStr(const std::string &str) +{ + return str + "Service"; +} + +static const std::string memberFromStr(const std::string &str) +{ + return str + "Member"; +} + +static const std::string privilegeFromStr(const std::string &str) +{ + return str + "Privilege"; +} + +static const std::string smackLabelFromStr(const std::string &str) +{ + return str + "SmackLabel"; +} + +static const std::string errorFromStr(const std::string &interface, const std::string &str) +{ + return interface + ".Error.Err" + str; +} + +static void addBusconfigPolicyOwn(const std::string &id) +{ + BusConfigWriter writer; + writer.addPolicyCheck(privilegeFromStr(id), {{Attr::OWN, connectionNameFromStr(id)}}); + writer.save(); +} + +static void assertUnlink(const std::string &filePath) +{ + RUNNER_ASSERT_MSG(0 == unlink(filePath.c_str()), "Unable to unlink " << filePath << " file"); +} + +static void addCynaraPolicy(const std::string &id) +{ + CynaraTestAdmin admin; + CynaraPoliciesContainer cp; + cp.add(CYNARA_ADMIN_DEFAULT_BUCKET, + smackLabelFromStr(id).c_str(), ROOT_UID_STR.c_str(), privilegeFromStr(id).c_str(), + CYNARA_ADMIN_ALLOW, nullptr); + admin.setPolicies(cp); +} + +static void addSmackAccessForDbus(SmackAccess &access, const std::string &label) +{ + access.add("System", label, "rx"); + access.apply(); +} + +static void removeSmackAccessForDbus(SmackAccess &access) +{ + access.clear(); +} + +static pid_t assertFork() +{ + pid_t pid = fork(); + RUNNER_ASSERT_ERRNO_MSG(pid != -1, "fork() failed"); + return pid; +} + +RUNNER_TEST_GROUP_INIT(CYNARA_DBUS); + +static void testOwn(const std::string &testId, + const std::function &addBusconfigPolicyFunc, + bool allow) +{ + SmackAccess access; + const std::string label(smackLabelFromStr(testId)); + + addBusconfigPolicyFunc(testId); + addSmackAccessForDbus(access, label); + if (allow) + addCynaraPolicy(testId); + + sleep(1); + + pid_t pid = assertFork(); + + if (pid == 0) { + RUNNER_ASSERT(0 == smack_set_label_for_self(label.c_str())); + DBus::Connection client(DBUS_BUS_SYSTEM, true); + client.requestName(connectionNameFromStr(testId), + allow ? DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER : -1); + } else { + sleep(3); + removeSmackAccessForDbus(access); + assertUnlink(CONF_FILE_PATH); + } +} + +RUNNER_MULTIPROCESS_TEST_SMACK(tcc_1130_own_deny) +{ + testOwn("tcc1130", addBusconfigPolicyOwn, false); +} + +RUNNER_MULTIPROCESS_TEST_SMACK(tcc_1170_own_allow) +{ + testOwn("tcc1170", addBusconfigPolicyOwn, true); +} + +static void addBusconfigPolicyOwnPrefix(const std::string &id) +{ + BusConfigWriter writer; + writer.addPolicyCheck(privilegeFromStr(id), {{Attr::OWN_PREFIX, CONNECTION_NAME_PREFIX}}); + writer.save(); +} + +RUNNER_CHILD_TEST_SMACK(tcc_1230_own_prefix_deny) +{ + testOwn("tcc1230", addBusconfigPolicyOwnPrefix, false); +} + +RUNNER_CHILD_TEST_SMACK(tcc_1270_own_prefix_allow) +{ + testOwn("tcc1270", addBusconfigPolicyOwnPrefix, true); +} + +static void addBusconfigPolicySendAllows(BusConfigWriter &writer) +{ + writer.addPolicyAllow({{Attr::OWN_PREFIX, CONNECTION_NAME_PREFIX}}); + writer.addPolicyAllow({{Attr::RECEIVE_TYPE, MESSSAGE_TYPE_METHOD_CALL}}); +} + +static void addBusconfigPolicySendDestination(const std::string &testId) +{ + BusConfigWriter writer; + addBusconfigPolicySendAllows(writer); + writer.addPolicyCheck(privilegeFromStr(clientIdFromStr(testId)), + {{Attr::SEND_DESTINATION, connectionNameFromStr(serviceIdFromStr(testId))}}); + writer.save(); +} + +static void runMessageClient(const std::string &testId, bool changeLabel) +{ + const std::string clientId(clientIdFromStr(testId)); + const std::string serviceId(serviceIdFromStr(testId)); + const ServiceCreds serviceCreds(serviceId); + + sleep(1); + + if (changeLabel) + RUNNER_ASSERT(0 == smack_set_label_for_self(smackLabelFromStr(clientId).c_str())); + DBus::Connection client(DBUS_BUS_SYSTEM, true); + client.requestName(connectionNameFromStr(clientId)); + + DBus::MessageOut messageOut(serviceCreds.connectionName(), + serviceCreds.objectPath(), + serviceCreds.interface(), + memberFromStr(serviceId)); + client.send(messageOut); + client.flush(); + + sleep(1); +} + +static void runMessageService(const std::string &testId, bool changeLabel, + const std::string &errorStr, bool allow) +{ + const std::string clientId(clientIdFromStr(testId)); + const std::string serviceId(serviceIdFromStr(testId)); + const std::string member(memberFromStr(serviceId)); + const ServiceCreds serviceCreds(serviceId); + + if (changeLabel) + RUNNER_ASSERT(0 == smack_set_label_for_self(smackLabelFromStr(serviceId).c_str())); + + Service service(serviceCreds); + bool finish = false; + if (allow) { + service.insertMethodHandler( + member, + [&] (DBus::Connection &connection, + DBus::MessageIn &messageIn, + std::string &errorMessage)->void { + (void) connection; + (void) messageIn; + (void) errorMessage; + finish = true; + }); + } else { + service.insertMethodHandler( + member, + [&] (DBus::Connection &connection, + DBus::MessageIn &messageIn, + std::string &errorMessage)->void { + (void) connection; + (void) messageIn; + errorMessage = errorStr; + }); + } + service.run(finish, !allow); + + assertUnlink(CONF_FILE_PATH); +} + +static void testSend(const std::string &testId, + const std::function addBusconfigPolicyFunc, + bool allow) +{ + SmackAccess access; + const std::string clientId(clientIdFromStr(testId)); + const std::string serviceId(serviceIdFromStr(testId)); + + addBusconfigPolicyFunc(testId); + addSmackAccessForDbus(access, smackLabelFromStr(clientId)); + if (allow) + addCynaraPolicy(clientId); + + sleep(1); + + pid_t pid = assertFork(); + if (pid == 0) + runMessageClient(testId, true); + else + runMessageService(testId, false, + "Should not be able to send to " + connectionNameFromStr(serviceId), + allow); +} + +RUNNER_MULTIPROCESS_TEST_SMACK(tcc_2130_send_destination_deny) +{ + testSend("tcc2130", addBusconfigPolicySendDestination, false); +} + +RUNNER_MULTIPROCESS_TEST_SMACK(tcc_2170_send_destination_allow) +{ + testSend("tcc2170", addBusconfigPolicySendDestination, true); +} + +static void addBusconfigPolicySendPath(const std::string &testId) +{ + const ServiceCreds serviceCreds(serviceIdFromStr(testId)); + BusConfigWriter writer; + addBusconfigPolicySendAllows(writer); + writer.addPolicyCheck(privilegeFromStr(clientIdFromStr(testId)), + {{Attr::SEND_DESTINATION, serviceCreds.connectionName()}, + {Attr::SEND_PATH, serviceCreds.objectPath()}}); + writer.save(); +} + +RUNNER_MULTIPROCESS_TEST_SMACK(tcc_2230_send_path_deny) +{ + testSend("tcc2230", addBusconfigPolicySendPath, false); +} + +RUNNER_MULTIPROCESS_TEST_SMACK(tcc_2270_send_path_allow) +{ + testSend("tcc2270", addBusconfigPolicySendPath, true); +} + +static void addBusconfigPolicySendInterface(const std::string &testId) +{ + const ServiceCreds serviceCreds(serviceIdFromStr(testId)); + BusConfigWriter writer; + addBusconfigPolicySendAllows(writer); + writer.addPolicyCheck(privilegeFromStr(clientIdFromStr(testId)), + {{Attr::SEND_DESTINATION, serviceCreds.connectionName()}, + {Attr::SEND_INTERFACE, serviceCreds.interface()}}); + writer.save(); +} + +RUNNER_MULTIPROCESS_TEST_SMACK(tcc_2330_send_interface_deny) +{ + testSend("tcc2330", addBusconfigPolicySendInterface, false); +} + +RUNNER_MULTIPROCESS_TEST_SMACK(tcc_2370_send_interface_allow) +{ + testSend("tcc2370", addBusconfigPolicySendInterface, true); +} + +static void addBusconfigPolicySendType(const std::string &testId) +{ + const ServiceCreds serviceCreds(serviceIdFromStr(testId)); + BusConfigWriter writer; + addBusconfigPolicySendAllows(writer); + writer.addPolicyCheck(privilegeFromStr(clientIdFromStr(testId)), + {{Attr::SEND_DESTINATION, serviceCreds.connectionName()}, + {Attr::SEND_TYPE, MESSSAGE_TYPE_METHOD_CALL}}); + writer.save(); +} + +RUNNER_MULTIPROCESS_TEST_SMACK(tcc_2430_send_type_deny) +{ + testSend("tcc2430", addBusconfigPolicySendType, false); +} + +RUNNER_MULTIPROCESS_TEST_SMACK(tcc_2470_send_type_allow) +{ + testSend("tcc2470", addBusconfigPolicySendType, true); +} + +static void addBusconfigPolicySendMember(const std::string &testId) +{ + const std::string serviceId = serviceIdFromStr(testId); + const ServiceCreds serviceCreds(serviceId); + BusConfigWriter writer; + addBusconfigPolicySendAllows(writer); + writer.addPolicyCheck(privilegeFromStr(clientIdFromStr(testId)), + {{Attr::SEND_DESTINATION, serviceCreds.connectionName()}, + {Attr::SEND_INTERFACE, serviceCreds.interface()}, + {Attr::SEND_MEMBER, memberFromStr(serviceId)}}); + writer.save(); +} + +RUNNER_MULTIPROCESS_TEST_SMACK(tcc_2530_send_member_deny) +{ + testSend("tcc2530", addBusconfigPolicySendMember, false); +} + +RUNNER_MULTIPROCESS_TEST_SMACK(tcc_2570_send_member_allow) +{ + testSend("tcc2570", addBusconfigPolicySendMember, true); +} + +static void addBusconfigPolicySendError(const std::string &testId) +{ + const std::string serviceId(serviceIdFromStr(testId)); + const ServiceCreds serviceCreds(serviceId); + BusConfigWriter writer; + addBusconfigPolicySendAllows(writer); + writer.addPolicyAllow({{Attr::RECEIVE_TYPE, MESSSAGE_TYPE_ERROR}}); + writer.addPolicyAllow({{Attr::SEND_TYPE, MESSSAGE_TYPE_ERROR}}); + writer.addPolicyAllow({{Attr::SEND_TYPE, MESSSAGE_TYPE_METHOD_CALL}}); + writer.addPolicyAllow({{Attr::SEND_DESTINATION, serviceCreds.connectionName()}}); + writer.addPolicyCheck(privilegeFromStr(serviceId), + {{Attr::SEND_DESTINATION, connectionNameFromStr(clientIdFromStr(testId))}, + {Attr::SEND_ERROR, errorFromStr(serviceCreds.interface(), serviceId)}}); + writer.save(); +} + +static void runClientError(const std::string &testId, bool changeLabel, bool allow) +{ + const std::string clientId(clientIdFromStr(testId)); + const std::string serviceId(serviceIdFromStr(testId)); + const ServiceCreds serviceCreds(serviceId); + + sleep(1); + + if (changeLabel) + RUNNER_ASSERT(0 == smack_set_label_for_self(smackLabelFromStr(clientId).c_str())); + DBus::Connection client(DBUS_BUS_SYSTEM, true); + client.requestName(connectionNameFromStr(clientId)); + + DBus::MessageOut messageOut(serviceCreds.connectionName(), + serviceCreds.objectPath(), + serviceCreds.interface(), + memberFromStr(serviceId)); + + DBusError error; + dbus_error_init(&error); + DBus::ErrorPtr errorPtr(&error); + + DBusMessage* message = client.sendWithReplyAndBlock(messageOut, + 4000, + &error); + if (message != nullptr) { + DBus::MessageIn messageIn(message); + RUNNER_FAIL_MSG("message received is null"); + } + + std::string expectedErrorName; + if (allow) + expectedErrorName = errorFromStr(serviceCreds.interface(), serviceId); + else + expectedErrorName = "org.freedesktop.DBus.Error.NoReply"; + + RUNNER_ASSERT_MSG(expectedErrorName == error.name, + "Wrong error received." + << "\n Expected error name: " << expectedErrorName + << "\n Received error name: " << error.name + << "\n Received error message: " << error.message); + + assertUnlink(CONF_FILE_PATH); +} + +static void runServiceError(const std::string &testId, bool changeLabel) +{ + const std::string clientId(clientIdFromStr(testId)); + const std::string serviceId(serviceIdFromStr(testId)); + const ServiceCreds serviceCreds(serviceId); + + if (changeLabel) + RUNNER_ASSERT(0 == smack_set_label_for_self(smackLabelFromStr(serviceId).c_str())); + + Service service(serviceCreds); + bool finish = false; + service.insertMethodHandler( + memberFromStr(serviceId), + [&] (DBus::Connection &connection, + DBus::MessageIn &messageIn, + std::string &errorMessage)->void { + DBus::MessageOut messageOut(messageIn.getMessage(), + errorFromStr(serviceCreds.interface(), serviceId), + "Security-tests error message"); + connection.send(messageOut); + connection.flush(); + (void) errorMessage; + finish = true; + }); + service.run(finish, false); + + sleep(2); +} + +static void testSendError(const std::string &testId, bool allow) +{ + const std::string serviceId(serviceIdFromStr(testId)); + SmackAccess access; + addBusconfigPolicySendError(testId); + addSmackAccessForDbus(access, smackLabelFromStr(serviceId)); + if (allow) + addCynaraPolicy(serviceId); + + sleep(1); + + pid_t pid = assertFork(); + if (pid == 0) { + runServiceError(testId, true); + } else { + runClientError(testId, false, allow); + } +} + +RUNNER_MULTIPROCESS_TEST_SMACK(tcc_2630_send_error_deny) +{ + testSendError("tcc2630", false); +} + +RUNNER_MULTIPROCESS_TEST_SMACK(tcc_2670_send_error_allow) +{ + testSendError("tcc2670", true); +} + +static void addBusconfigPolicyReceiveAllows(BusConfigWriter &writer) +{ + writer.addPolicyAllow({{Attr::OWN_PREFIX, CONNECTION_NAME_PREFIX}}); + writer.addPolicyAllow({{Attr::SEND_TYPE, MESSSAGE_TYPE_METHOD_CALL}}); +} + +static void addBusconfigPolicyReceiveSender(const std::string &testId) +{ + BusConfigWriter writer; + addBusconfigPolicyReceiveAllows(writer); + writer.addPolicyCheck(privilegeFromStr(serviceIdFromStr(testId)), + {{Attr::RECEIVE_SENDER, connectionNameFromStr(clientIdFromStr(testId))}}); + writer.save(); +} + +static void testReceive(const std::string &testId, + const std::function addBusconfigPolicyFunc, + bool allow) +{ + const std::string clientId(clientIdFromStr(testId)); + const std::string serviceId(serviceIdFromStr(testId)); + addBusconfigPolicyFunc(testId); + SmackAccess access; + addSmackAccessForDbus(access, smackLabelFromStr(serviceId)); + if (allow) + addCynaraPolicy(serviceId); + + sleep(1); + + pid_t pid = assertFork(); + if (pid == 0) + runMessageService(testId, true, + "Should not be able to receive from " + connectionNameFromStr(clientId), + allow); + else + runMessageClient(testId, false); +} + +RUNNER_MULTIPROCESS_TEST_SMACK(tcc_3130_receive_sender_deny) +{ + testReceive("tcc3130", addBusconfigPolicyReceiveSender, false); +} + +RUNNER_MULTIPROCESS_TEST_SMACK(tcc_3170_receive_sender_allow) +{ + testReceive("tcc3170", addBusconfigPolicyReceiveSender, true); +} + +static void addBusconfigPolicyReceivePath(const std::string &testId) +{ + const ServiceCreds serviceCreds(serviceIdFromStr(testId)); + BusConfigWriter writer; + addBusconfigPolicyReceiveAllows(writer); + writer.addPolicyCheck(privilegeFromStr(serviceIdFromStr(testId)), + {{Attr::RECEIVE_SENDER, connectionNameFromStr(clientIdFromStr(testId))}, + {Attr::RECEIVE_PATH, serviceCreds.objectPath()}}); + writer.save(); +} + +RUNNER_MULTIPROCESS_TEST_SMACK(tcc_3230_receive_path_deny) +{ + testReceive("tcc3230", addBusconfigPolicyReceivePath, false); +} + +RUNNER_MULTIPROCESS_TEST_SMACK(tcc_3270_receive_path_allow) +{ + testReceive("tcc3270", addBusconfigPolicyReceivePath, true); +} + +static void addBusconfigPolicyReceiveInterface(const std::string &testId) +{ + const ServiceCreds serviceCreds(serviceIdFromStr(testId)); + BusConfigWriter writer; + addBusconfigPolicyReceiveAllows(writer); + writer.addPolicyCheck(privilegeFromStr(serviceIdFromStr(testId)), + {{Attr::RECEIVE_SENDER, connectionNameFromStr(clientIdFromStr(testId))}, + {Attr::RECEIVE_INTERFACE, serviceCreds.interface()}}); + writer.save(); +} + +RUNNER_MULTIPROCESS_TEST_SMACK(tcc_3330_receive_interface_deny) +{ + testReceive("tcc3330", addBusconfigPolicyReceiveInterface, false); +} + +RUNNER_MULTIPROCESS_TEST_SMACK(tcc_3370_receive_interface_allow) +{ + testReceive("tcc3370", addBusconfigPolicyReceiveInterface, true); +} + +static void addBusconfigPolicyReceiveType(const std::string &testId) +{ + BusConfigWriter writer; + addBusconfigPolicyReceiveAllows(writer); + writer.addPolicyCheck(privilegeFromStr(serviceIdFromStr(testId)), + {{Attr::RECEIVE_SENDER, connectionNameFromStr(clientIdFromStr(testId))}, + {Attr::RECEIVE_TYPE, MESSSAGE_TYPE_METHOD_CALL}}); + writer.save(); +} + +RUNNER_MULTIPROCESS_TEST_SMACK(tcc_3430_receive_type_deny) +{ + testReceive("tcc3430", addBusconfigPolicyReceiveType, false); +} + +RUNNER_MULTIPROCESS_TEST_SMACK(tcc_3470_receive_interface_allow) +{ + testReceive("tcc3470", addBusconfigPolicyReceiveType, true); +} + +static void addBusconfigPolicyReceiveMember(const std::string &testId) +{ + const std::string serviceId(serviceIdFromStr(testId)); + const ServiceCreds serviceCreds(serviceId); + BusConfigWriter writer; + addBusconfigPolicyReceiveAllows(writer); + writer.addPolicyCheck(privilegeFromStr(serviceId), + {{Attr::RECEIVE_SENDER, connectionNameFromStr(clientIdFromStr(testId))}, + {Attr::RECEIVE_INTERFACE, serviceCreds.interface()}, + {Attr::RECEIVE_MEMBER, memberFromStr(serviceId)}}); + writer.save(); +} + +RUNNER_MULTIPROCESS_TEST_SMACK(tcc_3530_receive_member_deny) +{ + testReceive("tcc3530", addBusconfigPolicyReceiveMember, false); +} + +RUNNER_MULTIPROCESS_TEST_SMACK(tcc_3570_receive_member_allow) +{ + testReceive("tcc3570", addBusconfigPolicyReceiveMember, true); +} + +static void addBusconfigPolicyReceiveError(const std::string &testId) +{ + const std::string clientId(clientIdFromStr(testId)); + const std::string serviceId(serviceIdFromStr(testId)); + const ServiceCreds serviceCreds(serviceId); + BusConfigWriter writer; + addBusconfigPolicyReceiveAllows(writer); + writer.addPolicyAllow({{Attr::SEND_TYPE, MESSSAGE_TYPE_ERROR}}); + writer.addPolicyAllow({{Attr::RECEIVE_TYPE, MESSSAGE_TYPE_ERROR}}); + writer.addPolicyAllow({{Attr::RECEIVE_TYPE, MESSSAGE_TYPE_METHOD_CALL}}); + writer.addPolicyAllow({{Attr::SEND_DESTINATION, serviceCreds.connectionName()}}); + writer.addPolicyAllow({{Attr::SEND_DESTINATION, connectionNameFromStr(clientId)}}); + writer.addPolicyCheck(privilegeFromStr(clientId), + {{Attr::RECEIVE_SENDER, serviceCreds.connectionName()}, + {Attr::RECEIVE_ERROR, errorFromStr(serviceCreds.interface(), serviceId)}}); + writer.save(); +} + +static void testReceiveError(const std::string &testId, bool allow) +{ + const std::string clientId(clientIdFromStr(testId)); + addBusconfigPolicyReceiveError(testId); + SmackAccess access; + addSmackAccessForDbus(access, smackLabelFromStr(clientId)); + if (allow) + addCynaraPolicy(clientId); + + sleep(1); + + pid_t pid = assertFork(); + if (pid == 0) { + runClientError(testId, true, allow); + } else { + runServiceError(testId, false); + } +} + +RUNNER_MULTIPROCESS_TEST_SMACK(tcc_3630_receive_error_deny) +{ + testReceiveError("tcc3630", false); +} + +RUNNER_MULTIPROCESS_TEST_SMACK(tcc_3670_receive_error_allow) +{ + testReceiveError("tcc3670", true); +} diff --git a/tests/smack-dbus-tests/main.cpp b/tests/smack-dbus-tests/main.cpp new file mode 100644 index 00000000..8d2261b7 --- /dev/null +++ b/tests/smack-dbus-tests/main.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2014 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 main.cpp + * @author Marcin Niesluchowski (m.niesluchow@samsung.com) + * @version 1.0 + * @brief main for dbus tests + */ + +#include + +int main(int argc, char *argv[]) +{ + return DPL::Test::TestRunnerSingleton::Instance().ExecTestRunner(argc, argv); +} diff --git a/tests/smack-dbus-tests/smack_dbus_tests.cpp b/tests/smack-dbus-tests/smack_dbus_tests.cpp new file mode 100644 index 00000000..a17b5431 --- /dev/null +++ b/tests/smack-dbus-tests/smack_dbus_tests.cpp @@ -0,0 +1,300 @@ +#include +#include +#include +#include +#include +#include +#include "tests_common.h" + +#define DBUS_SERVER_NAME "test.method.server" +#define DBUS_CALLER_NAME "test.method.caller" + +#define DBUS_SMACK_NAME "org.freedesktop.DBus" +#define DBUS_SMACK_OBJECT "/org/freedesktop/DBus" +#define DBUS_SMACK_INTERFACE "org.freedesktop.DBus" +#define DBUS_SMACK_METHOD "GetConnectionCredentials" + +RUNNER_TEST_GROUP_INIT(SMACK_DBUS); + +RUNNER_MULTIPROCESS_TEST_SMACK(tcs_01_smack_context_from_DBus) +{ + RUNNER_IGNORED_MSG("dbus does not support smack context in GetConnectionCredentials method" + " yet."); + + int ret = -1; + const char *subject_parent = "subject_parent"; + const char *subject_child = "subject_child"; + + DBusMessage* msg = nullptr; + DBusMessageIter args, iter, var, var_iter, var_value; + DBusConnection* conn = nullptr; + DBusError err; + DBusPendingCall *pending = nullptr; + const char *dbus_server_name = DBUS_SERVER_NAME; + char *smack_context = nullptr; + + pid_t pid = fork(); + RUNNER_ASSERT_ERRNO_MSG(-1 != pid, "fork() failed"); + + if (pid == 0) { + // child + ret = smack_set_label_for_self(subject_child); + RUNNER_ASSERT_MSG(ret == PC_OPERATION_SUCCESS, + "smack_set__label_for_self() failed, ret: " << ret); + + // initialize the errors + dbus_error_init(&err); + + // connect to the system bus and check for errors + conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err); + ret = dbus_error_is_set(&err); + if (1 == ret) { + dbus_error_free(&err); + RUNNER_ASSERT_MSG(0 == ret, "dbus_bus_get() failed, ret: " << ret); + } + + // request our name on the bus + ret = dbus_bus_request_name(conn, DBUS_CALLER_NAME, DBUS_NAME_FLAG_REPLACE_EXISTING , &err); + if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) { + dbus_error_free(&err); + RUNNER_ASSERT_MSG(DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret, + "dbus_bus_request_name() failed, ret: " << ret); + } + + // crate a new method call for checking SMACK context from DBus interface + msg = dbus_message_new_method_call(DBUS_SMACK_NAME, + DBUS_SMACK_OBJECT, + DBUS_SMACK_INTERFACE, + DBUS_SMACK_METHOD); + + RUNNER_ASSERT_MSG(nullptr != msg, + "dbus_message_new_method_call() failed, ret: " << ret); + + // append arguments, we need SMACK context for our parent process "test.method.server" + dbus_message_iter_init_append(msg, &args); + ret = dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &dbus_server_name); + RUNNER_ASSERT_MSG(1 == ret, "Out of memory"); + + // wait for parent to connect to DBus + sleep(3); + + // send message and get a handle for a reply + // -1 is default timeout + ret = dbus_connection_send_with_reply (conn, msg, &pending, -1); + RUNNER_ASSERT_MSG(1 == ret, "Out of memory"); + RUNNER_ASSERT_MSG(nullptr != pending, "Pending call null"); + + dbus_connection_flush(conn); + + // free message + dbus_message_unref(msg); + + // block until reply + dbus_pending_call_block(pending); + + // get the reply + msg = dbus_pending_call_steal_reply(pending); + RUNNER_ASSERT_MSG(nullptr != msg, "Reply null"); + + // free message handle + dbus_pending_call_unref(pending); + + ret = dbus_message_iter_init(msg, &iter); + RUNNER_ASSERT_MSG(0 != ret, "Message has no arguments"); + + dbus_message_iter_recurse(&iter, &var); + + while (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_INVALID) { + dbus_message_iter_recurse(&var, &var_iter); + while(dbus_message_iter_get_arg_type(&var_iter) != DBUS_TYPE_INVALID) { + dbus_message_iter_recurse(&var_iter, &var_value); + switch(dbus_message_iter_get_arg_type(&var_value)) { + case DBUS_TYPE_STRING: + dbus_message_iter_get_basic(&var_value, &smack_context); + break; + default: + ; + } + dbus_message_iter_next(&var_iter); + } + dbus_message_iter_next(&var); + } + + // free reply and close connection + dbus_message_unref(msg); + dbus_connection_unref(conn); + + RUNNER_ASSERT(smack_context != nullptr); + ret = strcmp(smack_context, subject_parent); + RUNNER_ASSERT_MSG(0 == ret, + "Context mismatch! context from dbus: " << smack_context); + + exit(0); + + } else { + // parent + ret = smack_set_label_for_self(subject_parent); + RUNNER_ASSERT_MSG(ret == PC_OPERATION_SUCCESS, + "smack_set_label_for_self() failed, ret: " << ret); + + // initialise the error + dbus_error_init(&err); + + // connect to the bus and check for errors + conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err); + ret = dbus_error_is_set(&err); + if (1 == ret) { + dbus_error_free(&err); + RUNNER_ASSERT_MSG(0 == ret, "dbus_bus_get() failed, ret: " << ret); + } + + // request our name on the bus and check for errors + ret = dbus_bus_request_name(conn, DBUS_SERVER_NAME, DBUS_NAME_FLAG_REPLACE_EXISTING , &err); + if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) { + dbus_error_free(&err); + RUNNER_ASSERT_MSG(DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret, + "dbus_bus_request_name() failed, ret: " << ret); + } + + // close the connection + dbus_connection_unref(conn); + } +} + +/////////////////////////////////////// +//////NOSMACK ENV TESTS//////////////// +/////////////////////////////////////// + +RUNNER_MULTIPROCESS_TEST_NOSMACK(tcs_01_smack_context_from_DBus_nosmack) +{ + RUNNER_IGNORED_MSG("dbus does not support smack context in GetConnectionCredentials method" + " yet."); + + int ret = -1; + const char* subject_parent = "subject_parent"; + + DBusMessage* msg = nullptr; + DBusMessageIter args, iter, var, var_iter, var_value; + DBusConnection* conn = nullptr; + DBusError err; + DBusPendingCall *pending = nullptr; + const char *dbus_server_name = DBUS_SERVER_NAME; + char *smack_context = nullptr; + + pid_t pid = fork(); + RUNNER_ASSERT_ERRNO_MSG(-1 != pid, "fork() failed"); + + if (pid == 0) { + // child + + // initialize the errors + dbus_error_init(&err); + + // connect to the system bus and check for errors; failure = exit with result 1 + conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err); + ret = dbus_error_is_set(&err); + if (1 == ret) { + dbus_error_free(&err); + RUNNER_FAIL_MSG("Failed to connect to system bus. Ret " << ret); + } + + // request our name on the bus; failure = exit with result 2 + ret = dbus_bus_request_name(conn, DBUS_CALLER_NAME, DBUS_NAME_FLAG_REPLACE_EXISTING , &err); + if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) { + dbus_error_free(&err); + RUNNER_FAIL_MSG("Failed to request name on the bus. Ret " << ret); + } + + // crate a new method call for checking SMACK context from DBus interface + msg = dbus_message_new_method_call(DBUS_SMACK_NAME, + DBUS_SMACK_OBJECT, + DBUS_SMACK_INTERFACE, + DBUS_SMACK_METHOD); + + RUNNER_ASSERT_MSG(msg != nullptr, "dbus_message_new_method_call() failed."); + + // append arguments, we need SMACK context for our parent process "test.method.server" + dbus_message_iter_init_append(msg, &args); + ret = dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &dbus_server_name); + RUNNER_ASSERT_MSG(ret == 1, "Out of memory. Ret " << ret); + + // wait for parent to connect to DBus + sleep(3); + + // send message and get a handle for a reply + // -1 is default timeout + ret = dbus_connection_send_with_reply (conn, msg, &pending, -1); + RUNNER_ASSERT_MSG(ret == 1, "Out of memory. Ret " << ret); + RUNNER_ASSERT_MSG(pending != nullptr, "Pending call is nullptr."); + + dbus_connection_flush(conn); + + // free message + dbus_message_unref(msg); + + // block until reply + dbus_pending_call_block(pending); + + // get the reply + msg = dbus_pending_call_steal_reply(pending); + RUNNER_ASSERT_MSG(msg != nullptr, "Failed to get the reply from bus."); + + // free message handle + dbus_pending_call_unref(pending); + + ret = dbus_message_iter_init(msg, &iter); + RUNNER_ASSERT_MSG(ret != 0, "DBus message has no arguments. Ret " << ret); + + dbus_message_iter_recurse(&iter, &var); + while (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_INVALID) { + dbus_message_iter_recurse(&var, &var_iter); + while(dbus_message_iter_get_arg_type(&var_iter) != DBUS_TYPE_INVALID) { + dbus_message_iter_recurse(&var_iter, &var_value); + switch(dbus_message_iter_get_arg_type(&var_value)) { + case DBUS_TYPE_STRING: + dbus_message_iter_get_basic(&var_value, &smack_context); + break; + default: + ; + } + dbus_message_iter_next(&var_iter); + } + dbus_message_iter_next(&var); + } + + // free reply and close connection + dbus_message_unref(msg); + dbus_connection_unref(conn); + + RUNNER_ASSERT(smack_context != nullptr); + ret = strcmp(smack_context, subject_parent); + RUNNER_ASSERT_MSG(ret == 0, "Context mismatch. Context " << smack_context); + + exit(0); + + } else { + // parent + + // initialise the error + dbus_error_init(&err); + + // connect to the bus and check for errors + conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err); + ret = dbus_error_is_set(&err); + if (1 == ret) { + dbus_error_free(&err); + RUNNER_ASSERT_MSG(0 == ret, "dbus_bus_get() failed, ret: " << ret); + } + + // request our name on the bus and check for errors + ret = dbus_bus_request_name(conn, DBUS_SERVER_NAME, DBUS_NAME_FLAG_REPLACE_EXISTING , &err); + if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) { + dbus_error_free(&err); + RUNNER_ASSERT_MSG(DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret, + "dbus_bus_request_name() failed, ret: " << ret); + } + + // close the connection + dbus_connection_unref(conn); + } +}