--- /dev/null
- * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ /*
-void Connection::readWriteDispatch()
++ * 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 dbus_connection.cpp
+ * @author Marcin Niesluchowski (m.niesluchow@samsung.com)
+ * @version 1.0
+ * @brief DBus connection wrapper class source file
+ */
+
+ #include <dbus_connection.h>
+
+ #include <dpl/test/test_runner.h>
+
+ namespace DBus
+ {
+
+ Connection::Connection(DBusBusType busType, bool busPrivate)
+ : m_busPrivate(busPrivate)
++ , m_unref(true)
+ {
+ DBusError error;
+ dbus_error_init(&error);
+ ErrorPtr errorPtr(&error);
+
+ if (busPrivate)
+ m_connection = dbus_bus_get_private(busType, &error);
+ else
+ m_connection = dbus_bus_get(busType, &error);
+ RUNNER_ASSERT_MSG(m_connection != nullptr,
+ "Failed to open connection on "
+ << (busPrivate ? "private" : "public") << " bus."
+ << " Error: " << error.message);
+ dbus_connection_set_exit_on_disconnect(m_connection, FALSE);
+ }
+
++Connection::Connection(DBusConnection *connection)
++ : m_connection(connection)
++ , m_unref(false)
++{
++}
++
+ Connection::~Connection()
+ {
++ if (!m_unref)
++ return;
+ if (m_busPrivate)
+ dbus_connection_close(m_connection);
+ dbus_connection_unref(m_connection);
+ }
+
+ void Connection::addMatch(const std::string &rule)
+ {
+ DBusError error;
+ dbus_error_init(&error);
+ ErrorPtr errorPtr(&error);
+
+ dbus_bus_add_match(m_connection, rule.c_str(), &error);
+ RUNNER_ASSERT_MSG(dbus_error_is_set(&error) != TRUE, "Failed to add match."
+ << " Rule: " << rule << ";"
+ << " Error: " << error.message);
+ }
+
+ void Connection::addFilter(DBusHandleMessageFunction handleMessageFunction,
+ void *userData,
+ DBusFreeFunction freeDataFunction)
+ {
+ if (freeDataFunction == nullptr)
+ freeDataFunction = [](void*)->void {};
+
+ dbus_bool_t ret = dbus_connection_add_filter(m_connection,
+ handleMessageFunction,
+ userData,
+ freeDataFunction);
+ RUNNER_ASSERT_MSG(ret == TRUE, "Failed to add filter. Not enough memory");
+ }
+
- dbus_bool_t ret = dbus_connection_read_write_dispatch(m_connection, -1);
++void Connection::readWrite(int timeoutMilliseconds)
++{
++ dbus_bool_t ret = dbus_connection_read_write(m_connection, timeoutMilliseconds);
++ RUNNER_ASSERT_MSG(ret == TRUE, "Failed to read write. Disconnect message has been processed");
++}
++
++void Connection::dispatch()
++{
++ DBusDispatchStatus ret = dbus_connection_dispatch(m_connection);
++ RUNNER_ASSERT_MSG(ret != DBUS_DISPATCH_NEED_MEMORY,
++ "Failed to dispatch. Not enough memory");
++}
++
++void Connection::readWriteDispatch(int timeoutMilliseconds)
+ {
-void Connection::requestName(const std::string &name)
++ dbus_bool_t ret = dbus_connection_read_write_dispatch(m_connection, timeoutMilliseconds);
+ RUNNER_ASSERT_MSG(ret == TRUE, "Failed to read write dispatch. Disconnect message has been processed");
+ }
+
+ void Connection::flush()
+ {
+ dbus_connection_flush(m_connection);
+ }
+
- switch (ret)
- {
- case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER:
- case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER:
- return;
- case DBUS_REQUEST_NAME_REPLY_EXISTS:
- RUNNER_FAIL_MSG("Failed to request name."
- << " Name: " << name << ";"
- << " Owner did not specified DBUS_NAME_FLAG_ALLOW_REPLACEMENT flag");
- case -1:
- RUNNER_FAIL_MSG("Failed to request name."
- << " Name: " << name << ";"
- << " Error: " << error.message);
- default: // DBUS_REQUEST_NAME_REPLY_IN_QUEUE
- RUNNER_FAIL_MSG("Should not happen");
- }
++void Connection::requestName(const std::string &name, int expectedResult)
+ {
+ DBusError error;
+ dbus_error_init(&error);
+ ErrorPtr errorPtr(&error);
+
+ int ret = dbus_bus_request_name(m_connection,
+ name.c_str(),
+ DBUS_NAME_FLAG_REPLACE_EXISTING | DBUS_NAME_FLAG_DO_NOT_QUEUE,
+ &error);
++ RUNNER_ASSERT_MSG(ret == expectedResult, "dbus_bus_request_name returned wrong value."
++ << " Result: " << ret << ","
++ << " Expected result: " << expectedResult << ","
++ << " Name: " << name << ","
++ << " Error: " << error.message);
++}
++
++void Connection::registerObjectPath(const std::string &path,
++ DBusObjectPathMessageFunction messageFunction,
++ void *userData)
++{
++ auto p = m_pathVTables.insert(
++ std::pair<std::string, DBusObjectPathVTable>(
++ path, { [] (DBusConnection *connection, void *userData)->void { (void) connection;
++ (void) userData; },
++ messageFunction,
++ nullptr, nullptr, nullptr, nullptr
++ }
++ )
++ );
++ RUNNER_ASSERT_MSG(p.second, "Path <" << path << "> already exists");
++
++ DBusError error;
++ dbus_error_init(&error);
++ ErrorPtr errorPtr(&error);
++ dbus_bool_t ret = dbus_connection_try_register_object_path(m_connection,
++ path.c_str(),
++ &(p.first->second),
++ userData,
++ &error);
++ RUNNER_ASSERT_MSG(ret != FALSE, "Failed to register object path. "
++ << "Error: " << error.message);
+ }
+
+ MessageIn Connection::sendWithReplyAndBlock(const MessageOut &messageOut)
+ {
+ DBusError error;
+ dbus_error_init(&error);
+ ErrorPtr errorPtr(&error);
+
+ DBusMessage *messageRecv = dbus_connection_send_with_reply_and_block(m_connection,
+ messageOut.getMessage(),
+ -1,
+ &error);
+ RUNNER_ASSERT_MSG(messageRecv != nullptr, "Failed to send with reply and block. "
+ << "Error: " << error.message);
+ return MessageIn(messageRecv);
+ }
+
++DBusMessage* Connection::sendWithReplyAndBlock(const MessageOut &messageOut,
++ int timeoutMilliseconds,
++ DBusError *error)
++{
++ return dbus_connection_send_with_reply_and_block(m_connection,
++ messageOut.getMessage(),
++ timeoutMilliseconds,
++ error);
++}
++
++
++void Connection::send(const MessageOut &messageOut)
++{
++ DBusError error;
++ dbus_error_init(&error);
++ ErrorPtr errorPtr(&error);
++
++ dbus_bool_t ret = dbus_connection_send(m_connection,
++ messageOut.getMessage(),
++ nullptr);
++ RUNNER_ASSERT_MSG(ret == TRUE, "Failed to send. Not enough memory");
++}
++
+ } // namespace DBus
--- /dev/null
- * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ /*
- void readWriteDispatch();
++ * 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 dbus_connection.h
+ * @author Marcin Niesluchowski (m.niesluchow@samsung.com)
+ * @version 1.0
+ * @brief DBus connection wrapper class header
+ */
+
+ #ifndef COMMON_DBUS_CONNECTION_H
+ #define COMMON_DBUS_CONNECTION_H
+
+ #include <dbus/dbus.h>
+
+ #include <dbus_message_in.h>
+ #include <dbus_message_out.h>
+ #include <memory.h>
+
++#include <map>
+ #include <string>
+
+ namespace DBus
+ {
+
+ DEFINE_SMARTPTR(dbus_error_free, DBusError, ErrorPtr);
+
+ class Connection
+ {
+ public:
+ Connection(DBusBusType busType, bool privateGet);
++ Connection(DBusConnection *connection);
+ Connection(const Connection &other) = delete;
+ ~Connection();
+
+ Connection& operator=(const Connection &other) = delete;
+
+ void addMatch(const std::string &rule);
+ void addFilter(DBusHandleMessageFunction handleMessageFunction,
+ void *userData,
+ DBusFreeFunction freeDataFunction = nullptr);
- void requestName(const std::string &name);
++ void readWrite(int timeoutMilliseconds = -1);
++ void dispatch();
++ void readWriteDispatch(int timeoutMilliseconds = -1);
+ void flush();
++ void requestName(const std::string &name,
++ int expectedResult = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER);
++ void registerObjectPath(const std::string &path,
++ DBusObjectPathMessageFunction messageFunction,
++ void *userData);
+ MessageIn sendWithReplyAndBlock(const MessageOut &messageOut);
++ DBusMessage* sendWithReplyAndBlock(const MessageOut &messageOut,
++ int timeoutMilliseconds,
++ DBusError *error);
++ void send(const MessageOut &messageOut);
+
+ private:
+ DBusConnection *m_connection;
++ std::map<std::string, DBusObjectPathVTable> m_pathVTables;
+ bool m_busPrivate;
++ bool m_unref;
+ };
+
+ } // namespace DBus
+
+ #endif // COMMON_DBUS_CONNECTION_H
--- /dev/null
+ /*
+ * 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 dbus_message_in.cpp
+ * @author Marcin Niesluchowski (m.niesluchow@samsung.com)
+ * @version 1.0
+ * @brief DBus incoming message wrapper class source file
+ */
+
+ #include <dbus_message_in.h>
+
+ #include <dpl/test/test_runner.h>
+
+ namespace DBus
+ {
+
+ MessageIn::MessageIn(DBusMessage *message, bool ref)
+ : m_message(message)
+ {
+ RUNNER_ASSERT(m_message != nullptr);
+ if (ref)
+ dbus_message_ref(m_message);
+ }
+
+ MessageIn::MessageIn(MessageIn &&other)
+ : m_message(other.m_message)
+ {
+ other.m_message = nullptr;
+ }
+
+ MessageIn::~MessageIn()
+ {
+ if (m_message != nullptr)
+ dbus_message_unref(m_message);
+ }
+
++DBusMessage* MessageIn::getMessage() const
++{
++ return m_message;
++}
++
+ int MessageIn::getType()
+ {
+ return dbus_message_get_type(m_message);
+ }
+
+ bool MessageIn::isMethodCall(const std::string &interface, const std::string &method)
+ {
+ dbus_bool_t ret = dbus_message_is_method_call(m_message,
+ interface.c_str(),
+ method.c_str());
+ return ret == TRUE;
+ }
+
+ bool MessageIn::isSignal(const std::string &interface, const std::string &signalName)
+ {
+ dbus_bool_t ret = dbus_message_is_signal(m_message,
+ interface.c_str(),
+ signalName.c_str());
+ return ret == TRUE;
+ }
+
+ bool MessageIn::isError(const std::string &errorName)
+ {
+ dbus_bool_t ret = dbus_message_is_error(m_message,
+ errorName.c_str());
+ return ret == TRUE;
+ }
+
+ MessageIn::Iterator MessageIn::iterInit()
+ {
+ return Iterator(this->m_message);
+ }
+
+ MessageIn::Iterator::Iterator(DBusMessage* message)
+ {
+ dbus_message_iter_init(message, &m_iterator);
+ }
+
+ MessageIn::Iterator::Iterator(DBusMessageIter *iteratorOver)
+ {
+ dbus_message_iter_recurse(iteratorOver, &m_iterator);
+ }
+
+ bool MessageIn::Iterator::next()
+ {
+ return dbus_message_iter_next(&m_iterator) != FALSE;
+ }
+
+ void MessageIn::Iterator::expectNext()
+ {
+ RUNNER_ASSERT_MSG(next(), "No next argument in message");
+ }
+
+ int MessageIn::Iterator::getArgType()
+ {
+ return dbus_message_iter_get_arg_type(&m_iterator);
+ }
+
+ void MessageIn::Iterator::expectArgType(int argType)
+ {
+ int argTypeActual = getArgType();
+ RUNNER_ASSERT_MSG(argTypeActual == argType, "Wrong argument type in message"
+ << " Actual: " << argTypeActual
+ << " Expected: " << argType);
+ }
+
+ void MessageIn::Iterator::expectArgTypeValid()
+ {
+ RUNNER_ASSERT_MSG(getArgType() != DBUS_TYPE_INVALID, "Invalid argument type in message");
+ }
+
+ char MessageIn::Iterator::getArgChar()
+ {
+ return getArg<char>();
+ }
+
+ bool MessageIn::Iterator::getArgBool()
+ {
+ dbus_bool_t value;
+ dbus_message_iter_get_basic(&m_iterator, &value);
+ return value != FALSE;
+ }
+
+ int16_t MessageIn::Iterator::getArgInt16()
+ {
+ return getArg<int16_t>();
+ }
+
+ uint16_t MessageIn::Iterator::getArgUint16()
+ {
+ return getArg<uint16_t>();
+ }
+
+ int32_t MessageIn::Iterator::getArgInt32()
+ {
+ return getArg<int32_t>();
+ }
+
+ uint32_t MessageIn::Iterator::getArgUint32()
+ {
+ return getArg<uint32_t>();
+ }
+
+ int64_t MessageIn::Iterator::getArgInt64()
+ {
+ return getArg<int64_t>();
+ }
+
+ uint64_t MessageIn::Iterator::getArgUint64()
+ {
+ return getArg<uint64_t>();
+ }
+
+ double MessageIn::Iterator::getArgDouble()
+ {
+ return getArg<double>();
+ }
+
+ std::string MessageIn::Iterator::getArgString()
+ {
+ char *value;
+ dbus_message_iter_get_basic(&m_iterator, &value);
+ return std::string(value);
+ }
+
+ MessageIn::Iterator MessageIn::Iterator::recurse()
+ {
+ return Iterator(&(this->m_iterator));
+ }
+
+ } // namespace DBus
--- /dev/null
+ /*
+ * 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 dbus_message_in.h
+ * @author Marcin Niesluchowski (m.niesluchow@samsung.com)
+ * @version 1.0
+ * @brief DBus incoming message wrapper class header
+ */
+
+ #ifndef COMMON_DBUS_MESSAGE_IN_H
+ #define COMMON_DBUS_MESSAGE_IN_H
+
+ #include <dbus/dbus.h>
+
+ #include <cstdint>
+ #include <string>
+
+ namespace DBus
+ {
+
+ class MessageIn
+ {
+ public:
+ MessageIn(DBusMessage *message, bool ref = false);
+ MessageIn(const MessageIn &other) = delete;
+ MessageIn(MessageIn &&other);
+ ~MessageIn();
+
+ MessageIn& operator=(const MessageIn &other) = delete;
+
++ DBusMessage* getMessage() const;
++
+ int getType();
+ bool isMethodCall(const std::string &interface, const std::string &method);
+ bool isSignal(const std::string &interface, const std::string &signalName);
+ bool isError(const std::string &errorName);
+
+ class Iterator
+ {
+ public:
+ friend class MessageIn;
+
+ bool next();
+ void expectNext();
+ int getArgType();
+ void expectArgType(int argType);
+ void expectArgTypeValid();
+ char getArgChar();
+ bool getArgBool();
+ int16_t getArgInt16();
+ uint16_t getArgUint16();
+ int32_t getArgInt32();
+ uint32_t getArgUint32();
+ int64_t getArgInt64();
+ uint64_t getArgUint64();
+ double getArgDouble();
+ std::string getArgString();
+ Iterator recurse();
+
+ private:
+ template<class T>
+ T getArg() {
+ T value;
+ dbus_message_iter_get_basic(&m_iterator, &value);
+ return value;
+ }
+
+ // sub constructor
+ Iterator(DBusMessageIter *iteratorOver);
+ // message constructor
+ Iterator(DBusMessage *message);
+ DBusMessageIter m_iterator;
+ };
+
+ Iterator iterInit();
+
+ private:
+ DBusMessage *m_message;
+ };
+
+ } // namespace DBus
+
+ #endif // COMMON_DBUS_MESSAGE_IN_H
--- /dev/null
+ /*
+ * 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 dbus_message_out.cpp
+ * @author Marcin Niesluchowski (m.niesluchow@samsung.com)
+ * @version 1.0
+ * @brief DBus outgoing message wrapper class source file
+ */
+
+ #include <dbus_message_out.h>
+
+ #include <dpl/test/test_runner.h>
+
+ namespace DBus
+ {
+
+ MessageOut::MessageOut(const std::string &destination,
+ const std::string &path,
+ const std::string &interface,
+ const std::string &method)
+ {
+ m_message = dbus_message_new_method_call(destination.c_str(),
+ path.c_str(),
+ interface.c_str(),
+ method.c_str());
+ RUNNER_ASSERT_MSG(nullptr != m_message,
+ "Failed to create new method call. Not enough memory");
+ }
+
++MessageOut::MessageOut(DBusMessage *replyTo,
++ const std::string &errorName,
++ const std::string &errorMessage)
++{
++ m_message = dbus_message_new_error(replyTo, errorName.c_str(), errorMessage.c_str());
++ RUNNER_ASSERT_MSG(nullptr != m_message,
++ "Failed to create new error");
++}
++
+ MessageOut::MessageOut(MessageOut &&other)
+ : m_message(other.m_message)
+ {
+ other.m_message = nullptr;
+ }
+
+ MessageOut::~MessageOut()
+ {
+ if (m_message != nullptr)
+ dbus_message_unref(m_message);
+ }
+
+ DBusMessage* MessageOut::getMessage() const
+ {
+ return m_message;
+ }
+
+ void MessageOut::append(bool b)
+ {
+ DBusMessageIter iter;
+ dbus_message_iter_init_append(m_message, &iter);
+
+ dbus_bool_t bArg = b ? TRUE : FALSE;
+ dbus_bool_t ret = dbus_message_iter_append_basic(&iter,
+ DBUS_TYPE_BOOLEAN,
+ &bArg);
+ RUNNER_ASSERT_MSG(ret != FALSE, "Failed to append basic boolean. Not enough memory");
+ }
+
+ void MessageOut::append(const char *cstr)
+ {
+ DBusMessageIter iter;
+ dbus_message_iter_init_append(m_message, &iter);
+
+ dbus_bool_t ret = dbus_message_iter_append_basic(&iter,
+ DBUS_TYPE_STRING,
+ &cstr);
+ RUNNER_ASSERT_MSG(ret != FALSE, "Failed to append basic string. Not enough memory");
+ }
+
+ void MessageOut::append(const std::string &str)
+ {
+ append(str.c_str());
+ }
+
+ void MessageOut::append(const std::vector<std::string> &strs)
+ {
+ DBusMessageIter iter;
+ dbus_message_iter_init_append(m_message, &iter);
+
+ DBusMessageIter subIter;
+ dbus_bool_t ret = dbus_message_iter_open_container(&iter,
+ DBUS_TYPE_ARRAY,
+ DBUS_TYPE_STRING_AS_STRING,
+ &subIter);
+ RUNNER_ASSERT_MSG(ret != FALSE, "Failed to open container. Not enough memory");
+ for (const auto &str : strs) {
+ const char *cstr = str.c_str();
+ ret = dbus_message_iter_append_basic(&subIter, DBUS_TYPE_STRING, &cstr);
+ if (ret == FALSE) {
+ dbus_message_iter_abandon_container(&iter, &subIter);
+ RUNNER_FAIL_MSG("Failed to append basic string. Not enough memory");
+ }
+ }
+ ret = dbus_message_iter_close_container(&iter, &subIter);
+ RUNNER_ASSERT_MSG(ret != FALSE, "Failed to close container. Not enough memory");
+ }
+
+ } // namespace DBus
--- /dev/null
+ /*
+ * 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 dbus_message_out.h
+ * @author Marcin Niesluchowski (m.niesluchow@samsung.com)
+ * @version 1.0
+ * @brief DBus outgoing message wrapper class header
+ */
+
+ #ifndef COMMON_DBUS_MESSAGE_OUT_H
+ #define COMMON_DBUS_MESSAGE_OUT_H
+
+ #include <dbus/dbus.h>
+
+ #include <string>
+ #include <vector>
+
+ namespace DBus
+ {
+
+ class MessageOut
+ {
+ public:
+ MessageOut(const std::string &destination,
+ const std::string &path,
+ const std::string &interface,
+ const std::string &method);
++ MessageOut(DBusMessage *replyTo,
++ const std::string &errorName,
++ const std::string &errorMessage);
+ MessageOut(const MessageOut &other) = delete;
+ MessageOut(MessageOut &&other);
+ ~MessageOut();
+
+ MessageOut& operator=(const MessageOut &other) = delete;
+
+ DBusMessage* getMessage() const;
+
+ void append(bool b);
+ void append(const char *cstr);
+ void append(const std::string &str);
+ void append(const std::vector<std::string> &strs);
+
+ private:
+ DBusMessage *m_message;
+ };
+
+ } // namespace DBus
+
+ #endif // COMMON_DBUS_MESSAGE_OUT_H
--- /dev/null
+ /*
+ * Copyright (c) 2013 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 smack_access.cpp
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 1.0
+ * @brief Common functions and macros used in security-tests package.
+ */
+
+ #include <sys/smack.h>
+
+ #include <tests_common.h>
+
+ #include <smack_access.h>
+
+ SmackAccess::SmackAccess()
+ : m_handle(nullptr)
+ {
+ RUNNER_ASSERT_MSG(0 == smack_accesses_new(&m_handle),
+ "Error in smack_accesses_new");
+ }
+
+ void SmackAccess::add(
+ const std::string &subject,
+ const std::string &object,
+ const std::string &rights)
+ {
+ RUNNER_ASSERT_MSG(0 == smack_accesses_add(m_handle,
+ subject.c_str(),
+ object.c_str(),
+ rights.c_str()),
+ "Error in smack_accesses_add.");
+ }
+
+ void SmackAccess::apply() {
+ RUNNER_ASSERT_MSG(0 == smack_accesses_apply(m_handle),
+ "Error in smack_accessses_apply.");
+ }
+
++void SmackAccess::clear() {
++ RUNNER_ASSERT_MSG(0 == smack_accesses_clear(m_handle),
++ "Error in smack_accessses_clear.");
++}
++
+ SmackAccess::~SmackAccess() {
+ if (m_handle)
+ smack_accesses_free(m_handle);
+ }
+
--- /dev/null
+ /*
+ * Copyright (c) 2013 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 smack_access.h
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 1.0
+ * @brief Common functions and macros used in security-tests package.
+ */
+ #ifndef _SMACK_ACCESS_H_
+ #define _SMACK_ACCESS_H_
+
+ #include <string>
+
+ struct smack_accesses;
+
+ class SmackAccess {
+ public:
+ SmackAccess();
+ SmackAccess(const SmackAccess &second) = delete;
+ SmackAccess& operator=(SmackAccess &second) = delete;
+
+ void add(const std::string &subject,
+ const std::string &object,
+ const std::string &rights);
+ void apply();
++ void clear();
+ virtual ~SmackAccess();
+ private:
+ struct smack_accesses *m_handle;
+ };
+
+ #endif // _SMACK_ACCESS_H_
+
--- /dev/null
-"smack-dbus")
+ #!/bin/sh
+
+ #####################################################################
+ # Copyright (c) 2012-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.
+ #####################################################################
+
+ #testing internet access and date on the target
+
+ echo "### Starting tests ######################################################"
+
+ case $1 in
+
+ "smack")
+ echo "========================================================================="
+ echo $1
+ echo
+ libsmack-test "${@:2}" # propagate all remaining arguments (except first)
+ ;;
- echo "SMACK DBUS TEST"
++"dbus")
+ echo "========================================================================="
- smack-dbus-tests "${@:2}"
++ echo "DBUS TEST"
+ echo
- echo "modules: smack, smack-dbus, libprivilege-control, ss-clientsmack"
++ dbus-tests "${@:2}"
+ ;;
+ "libprivilege-control")
+ echo "========================================================================="
+ echo $1
+ echo
+ libprivilege-control-test "${@:2}"
+ ;;
+ "ss-clientsmack")
+ echo "========================================================================="
+ echo "SECURITY SERVER TEST CLIENT SMACK"
+ echo
+ security-server-tests-client-smack "${@:2}"
+ ;;
+ "ss-stress")
+ echo "========================================================================="
+ echo "SECURITY SERVER TEST STRESS"
+ echo
+ security-server-tests-stress "${@:2}"
+ ;;
+ "ss-server")
+ echo "========================================================================="
+ echo "SECURITY SERVER TEST SERVER"
+ echo
+ security-server-tests-server "${@:2}"
+ ;;
+ "ss-api-speed")
+ echo "========================================================================="
+ echo "SECURITY SERVER MEASURER SERVER"
+ echo
+ security-server-tests-api-speed "${@:2}"
+ ;;
+ "ss-password")
+ echo "========================================================================="
+ echo "SECURITY SERVER TEST PASSWORD"
+ echo
+ security-server-tests-password "${@:2}"
+ ;;
+ "ss-privilege")
+ echo "========================================================================="
+ echo "SECURITY SERVER TEST PRIVILEGE"
+ echo
+ security-server-tests-privilege "${@:2}"
+ ;;
+ "security-manager")
+ echo "========================================================================="
+ echo "SECURITY MANAGER TESTS"
+ echo
+ security-manager-tests "${@:2}"
+ ;;
+ "cynara")
+ echo "========================================================================="
+ echo "CYNARA TEST"
+ echo
+ cynara-test "${@:2}"
+ ;;
+ "ckm")
+ echo "========================================================================="
+ echo "KEY MANAGER TESTS"
+ echo
+ ckm-tests "${@:2}"
+ ;;
+ *)
+ echo "Correct using:"
+ echo " security_test.sh <module> <args_for_module>"
+ echo
++ echo "modules: smack, dbus, libprivilege-control, ss-clientsmack"
+ echo " ss-server, ss-api-speed, ss-password, ss-stress"
+ echo " ss-privilege, security-manager, cynara, ckm"
+ ;;
+
+ esac
+
+ echo "### Tests done ##########################################################"
--- /dev/null
-PKG_CHECK_MODULES(SMACK_DBUS_TESTS_DEP
++#
+ # 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
- ${SMACK_DBUS_TESTS_DEP_INCLUDE_DIRS}
++PKG_CHECK_MODULES(DBUS_TESTS_DEP
+ libsmack
++ cynara-admin
+ dbus-1
+ REQUIRED)
+
+ # Targets definition
+
+ INCLUDE_DIRECTORIES(SYSTEM
-SET(TARGET_SMACK_DBUS_TESTS "smack-dbus-tests")
++ ${DBUS_TESTS_DEP_INCLUDE_DIRS}
+ )
+
-SET(SMACK_DBUS_SOURCES
++SET(TARGET_DBUS_TESTS "dbus-tests")
+
+ # Sources definition
+
-ADD_EXECUTABLE(${TARGET_SMACK_DBUS_TESTS} ${SMACK_DBUS_SOURCES})
++SET(DBUS_TESTS_SOURCES
++ ${PROJECT_SOURCE_DIR}/src/cynara-tests/common/cynara_test_admin.cpp
++ ${PROJECT_SOURCE_DIR}/src/smack-dbus-tests/common/dbus_test_commons.cpp
++ ${PROJECT_SOURCE_DIR}/src/smack-dbus-tests/common/dbus_test_service.cpp
++ ${PROJECT_SOURCE_DIR}/src/smack-dbus-tests/common/dbus_test_service_object.cpp
++ ${PROJECT_SOURCE_DIR}/src/smack-dbus-tests/main.cpp
++ ${PROJECT_SOURCE_DIR}/src/smack-dbus-tests/common/dbus_test_busconfig_writer.cpp
++ ${PROJECT_SOURCE_DIR}/src/smack-dbus-tests/cynara_dbus_tests.cpp
+ ${PROJECT_SOURCE_DIR}/src/smack-dbus-tests/smack_dbus_tests.cpp
+ )
+
+ INCLUDE_DIRECTORIES(
+ ${PROJECT_SOURCE_DIR}/src/common/
++ ${PROJECT_SOURCE_DIR}/src/cynara-tests/common/
++ ${PROJECT_SOURCE_DIR}/src/cynara-tests/plugins/
++ ${PROJECT_SOURCE_DIR}/src/smack-dbus-tests/common/
+ )
+
-TARGET_LINK_LIBRARIES(${TARGET_SMACK_DBUS_TESTS}
- ${SMACK_DBUS_TESTS_DEP_LIBRARIES}
++ADD_EXECUTABLE(${TARGET_DBUS_TESTS} ${DBUS_TESTS_SOURCES})
+
-INSTALL(TARGETS ${TARGET_SMACK_DBUS_TESTS} DESTINATION /usr/bin)
++TARGET_LINK_LIBRARIES(${TARGET_DBUS_TESTS}
++ ${DBUS_TESTS_DEP_LIBRARIES}
+ dpl-test-framework
+ tests-common
+ )
+
+ # Installation
+
++INSTALL(TARGETS ${TARGET_DBUS_TESTS} DESTINATION /usr/bin)
--- /dev/null
--- /dev/null
++/*
++ * 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 <m.niesluchow@samsung.com>
++ * @version 1.0
++ * @brief dbus test busconfig writer definition
++ */
++
++#include <dbus_test_busconfig_writer.h>
++
++#include <dpl/test/test_runner.h>
++
++#include <map>
++#include <unistd.h>
++
++namespace DBusTest {
++
++namespace {
++
++const char* const BUSCONFIG_ENCODING = "ISO-8859-1";
++
++const std::map<Attr, std::string> 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);
++}
++
++}
--- /dev/null
--- /dev/null
++/*
++ * 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 <m.niesluchow@samsung.com>
++ * @version 1.0
++ * @brief dbus test busconfig writer declaration
++ */
++
++#ifndef DBUS_TEST_BUSCONFIG_WRITER
++#define DBUS_TEST_BUSCONFIG_WRITER
++
++#include <libxml/xmlwriter.h>
++
++#include <string>
++#include <vector>
++
++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<AttrVal> 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
--- /dev/null
--- /dev/null
++/*
++ * 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 <m.niesluchow@samsung.com>
++ * @version 1.0
++ * @brief commons for dbus test files
++ */
++
++#include <dbus_test_commons.h>
++
++namespace DBusTest
++{
++
++const std::string CONNECTION_NAME_PREFIX("com.security_tests");
++
++const std::string connectionNameFromStr(const std::string &str)
++{
++ return CONNECTION_NAME_PREFIX + "." + str;
++}
++
++}
--- /dev/null
--- /dev/null
++/*
++ * 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 <m.niesluchow@samsung.com>
++ * @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 <string>
++
++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
--- /dev/null
--- /dev/null
++/*
++ * 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 <m.niesluchow@samsung.com>
++ * @version 1.0
++ * @brief dbus test service definition
++ */
++
++#include <dbus_test_service.h>
++#include <dbus_test_commons.h>
++
++#include <chrono>
++
++#include <dpl/test/test_runner.h>
++
++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<Service*>(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
--- /dev/null
--- /dev/null
++/*
++ * 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 <m.niesluchow@samsung.com>
++ * @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 <dbus_test_service_object.h>
++
++#include <dbus_connection.h>
++
++#include <string>
++
++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
--- /dev/null
--- /dev/null
++/*
++ * 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 <m.niesluchow@samsungcom>
++ * @version 1.0
++ * @brief Definition of dbus test service object class for handling
++ * incoming messages
++ */
++
++#include <dbus_test_service_object.h>
++
++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
--- /dev/null
--- /dev/null
++/*
++ * 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 <m.niesluchow@samsungcom>
++ * @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 <dbus_connection.h>
++#include <dbus_message_in.h>
++
++#include <functional>
++#include <map>
++#include <string>
++
++namespace DBusTest
++{
++
++using MessageHandler = std::function<void(DBus::Connection &connection,
++ DBus::MessageIn &messageIn,
++ std::string &errorStr)>;
++
++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<std::string, MessageHandler> m_methodHandlers;
++ std::string m_interface;
++};
++
++} // namespace DBusTest
++
++#endif // DBUS_TESTS_COMMON_DBUS_TEST_SERVICE_OBJECT_H
--- /dev/null
--- /dev/null
++/*
++ * 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 <dpl/test/test_runner.h>
++#include <dpl/test/test_runner_child.h>
++
++#include <cynara_test_admin.h>
++#include <dbus_connection.h>
++#include <dbus_message_out.h>
++#include <dbus_test_busconfig_writer.h>
++#include <dbus_test_commons.h>
++#include <dbus_test_service.h>
++#include <smack_access.h>
++#include <tests_common.h>
++
++#include <dbus/dbus.h>
++#include <sys/smack.h>
++
++#include <string>
++#include <unistd.h>
++#include <iostream>
++
++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 admin;
++ CynaraTestAdmin::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<void(const std::string &)> &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<void(const std::string &)> 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<void(const std::string &)> 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);
++}
--- /dev/null
--- /dev/null
++/*
++ * 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 <dpl/test/test_runner.h>
++
++int main(int argc, char *argv[])
++{
++ return DPL::Test::TestRunnerSingleton::Instance().ExecTestRunner(argc, argv);
++}
--- /dev/null
-RUNNER_MULTIPROCESS_TEST_SMACK(tc01_smack_context_from_DBus)
+ #include <cstring>
+ #include <unistd.h>
+ #include <sys/smack.h>
+ #include <dpl/test/test_runner.h>
+ #include <dpl/test/test_runner_multiprocess.h>
+ #include <dbus/dbus.h>
+ #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_NOSMACK(tc01_smack_context_from_DBus_nosmack)
++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////////////////
+ ///////////////////////////////////////
+
-
-int main(int argc, char *argv[])
-{
- return DPL::Test::TestRunnerSingleton::Instance().ExecTestRunner(argc, argv);
-}
++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);
+ }
+ }