From: Zbigniew Jasinski Date: Thu, 23 Apr 2015 09:38:56 +0000 (+0200) Subject: Merge branch 'tizen' into dbus X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fheads%2Fdbus;p=platform%2Fcore%2Ftest%2Fsecurity-tests.git Merge branch 'tizen' into dbus Conflicts: src/security-tests-all.sh src/smack-dbus-tests/CMakeLists.txt tests/CMakeLists.txt Change-Id: I6a190cf7b1b955aa608aa45b2b20f37575bb5165 --- c9e15572e2291f7c5b8bc1e69a7e6884b6b5d5a6 diff --cc src/common/dbus_connection.cpp index 00000000,424bd0eb..9ddceea5 mode 000000,100644..100644 --- a/src/common/dbus_connection.cpp +++ b/src/common/dbus_connection.cpp @@@ -1,0 -1,135 +1,196 @@@ + /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved ++ * 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 + + #include + + 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"); + } + -void Connection::readWriteDispatch() ++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) + { - dbus_bool_t ret = dbus_connection_read_write_dispatch(m_connection, -1); ++ 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); + } + -void Connection::requestName(const std::string &name) ++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); - 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"); - } ++ 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( ++ 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 diff --cc src/common/dbus_connection.h index 00000000,f2db5ace..b338fc2c mode 000000,100644..100644 --- a/src/common/dbus_connection.h +++ b/src/common/dbus_connection.h @@@ -1,0 -1,64 +1,78 @@@ + /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved ++ * 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 + + #include + #include + #include + ++#include + #include + + 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 readWriteDispatch(); ++ void readWrite(int timeoutMilliseconds = -1); ++ void dispatch(); ++ void readWriteDispatch(int timeoutMilliseconds = -1); + void flush(); - void requestName(const std::string &name); ++ 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 m_pathVTables; + bool m_busPrivate; ++ bool m_unref; + }; + + } // namespace DBus + + #endif // COMMON_DBUS_CONNECTION_H diff --cc src/common/dbus_message_in.cpp index 00000000,c04533bb..41478b40 mode 000000,100644..100644 --- a/src/common/dbus_message_in.cpp +++ b/src/common/dbus_message_in.cpp @@@ -1,0 -1,180 +1,185 @@@ + /* + * 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 + + #include + + 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(); + } + + 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(); + } + + uint16_t MessageIn::Iterator::getArgUint16() + { + return getArg(); + } + + int32_t MessageIn::Iterator::getArgInt32() + { + return getArg(); + } + + uint32_t MessageIn::Iterator::getArgUint32() + { + return getArg(); + } + + int64_t MessageIn::Iterator::getArgInt64() + { + return getArg(); + } + + uint64_t MessageIn::Iterator::getArgUint64() + { + return getArg(); + } + + double MessageIn::Iterator::getArgDouble() + { + return getArg(); + } + + 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 diff --cc src/common/dbus_message_in.h index 00000000,e0a0dc78..1c26e219 mode 000000,100644..100644 --- a/src/common/dbus_message_in.h +++ b/src/common/dbus_message_in.h @@@ -1,0 -1,94 +1,96 @@@ + /* + * 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 + + #include + #include + + 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 + 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 diff --cc src/common/dbus_message_out.cpp index 00000000,2de0659b..c055cd79 mode 000000,100644..100644 --- a/src/common/dbus_message_out.cpp +++ b/src/common/dbus_message_out.cpp @@@ -1,0 -1,111 +1,120 @@@ + /* + * 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 + + #include + + 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 &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 diff --cc src/common/dbus_message_out.h index 00000000,8b34d06e..6ceb6f7b mode 000000,100644..100644 --- a/src/common/dbus_message_out.h +++ b/src/common/dbus_message_out.h @@@ -1,0 -1,60 +1,63 @@@ + /* + * 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 + + #include + #include + + 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 &strs); + + private: + DBusMessage *m_message; + }; + + } // namespace DBus + + #endif // COMMON_DBUS_MESSAGE_OUT_H diff --cc src/common/smack_access.cpp index 00000000,354b9971..b917027f mode 000000,100644..100644 --- a/src/common/smack_access.cpp +++ b/src/common/smack_access.cpp @@@ -1,0 -1,57 +1,62 @@@ + /* + * 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 + + #include + + #include + + 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); + } + diff --cc src/common/smack_access.h index 00000000,f20842be..f7e69b90 mode 000000,100644..100644 --- a/src/common/smack_access.h +++ b/src/common/smack_access.h @@@ -1,0 -1,45 +1,46 @@@ + /* + * 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 + + 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_ + diff --cc src/security-tests.sh index 00000000,f99127bc..772021b3 mode 000000,100644..100644 --- a/src/security-tests.sh +++ b/src/security-tests.sh @@@ -1,0 -1,108 +1,108 @@@ + #!/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) + ;; -"smack-dbus") ++"dbus") + echo "=========================================================================" - echo "SMACK DBUS TEST" ++ echo "DBUS TEST" + echo - smack-dbus-tests "${@:2}" ++ 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 " + echo - echo "modules: smack, smack-dbus, libprivilege-control, ss-clientsmack" ++ 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 ##########################################################" diff --cc src/smack-dbus-tests/CMakeLists.txt index 00000000,865b714b..39793a1c mode 000000,100644..100644 --- a/src/smack-dbus-tests/CMakeLists.txt +++ b/src/smack-dbus-tests/CMakeLists.txt @@@ -1,0 -1,56 +1,68 @@@ ++# + # 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(SMACK_DBUS_TESTS_DEP ++PKG_CHECK_MODULES(DBUS_TESTS_DEP + libsmack ++ cynara-admin + dbus-1 + REQUIRED) + + # Targets definition + + INCLUDE_DIRECTORIES(SYSTEM - ${SMACK_DBUS_TESTS_DEP_INCLUDE_DIRS} ++ ${DBUS_TESTS_DEP_INCLUDE_DIRS} + ) + -SET(TARGET_SMACK_DBUS_TESTS "smack-dbus-tests") ++SET(TARGET_DBUS_TESTS "dbus-tests") + + # Sources definition + -SET(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/ + ) + -ADD_EXECUTABLE(${TARGET_SMACK_DBUS_TESTS} ${SMACK_DBUS_SOURCES}) ++ADD_EXECUTABLE(${TARGET_DBUS_TESTS} ${DBUS_TESTS_SOURCES}) + -TARGET_LINK_LIBRARIES(${TARGET_SMACK_DBUS_TESTS} - ${SMACK_DBUS_TESTS_DEP_LIBRARIES} ++TARGET_LINK_LIBRARIES(${TARGET_DBUS_TESTS} ++ ${DBUS_TESTS_DEP_LIBRARIES} + dpl-test-framework + tests-common + ) + + # Installation + -INSTALL(TARGETS ${TARGET_SMACK_DBUS_TESTS} DESTINATION /usr/bin) ++INSTALL(TARGETS ${TARGET_DBUS_TESTS} DESTINATION /usr/bin) diff --cc src/smack-dbus-tests/common/dbus_test_busconfig_writer.cpp index 00000000,00000000..1f5cc198 new file mode 100644 --- /dev/null +++ b/src/smack-dbus-tests/common/dbus_test_busconfig_writer.cpp @@@ -1,0 -1,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 --cc src/smack-dbus-tests/common/dbus_test_busconfig_writer.h index 00000000,00000000..7b41bbf5 new file mode 100644 --- /dev/null +++ b/src/smack-dbus-tests/common/dbus_test_busconfig_writer.h @@@ -1,0 -1,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 --cc src/smack-dbus-tests/common/dbus_test_commons.cpp index 00000000,00000000..548d015a new file mode 100644 --- /dev/null +++ b/src/smack-dbus-tests/common/dbus_test_commons.cpp @@@ -1,0 -1,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 --cc src/smack-dbus-tests/common/dbus_test_commons.h index 00000000,00000000..24090635 new file mode 100644 --- /dev/null +++ b/src/smack-dbus-tests/common/dbus_test_commons.h @@@ -1,0 -1,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 --cc src/smack-dbus-tests/common/dbus_test_service.cpp index 00000000,00000000..81da52b7 new file mode 100644 --- /dev/null +++ b/src/smack-dbus-tests/common/dbus_test_service.cpp @@@ -1,0 -1,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 --cc src/smack-dbus-tests/common/dbus_test_service.h index 00000000,00000000..bf986df5 new file mode 100644 --- /dev/null +++ b/src/smack-dbus-tests/common/dbus_test_service.h @@@ -1,0 -1,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 --cc src/smack-dbus-tests/common/dbus_test_service_object.cpp index 00000000,00000000..8cc1ca6c new file mode 100644 --- /dev/null +++ b/src/smack-dbus-tests/common/dbus_test_service_object.cpp @@@ -1,0 -1,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 --cc src/smack-dbus-tests/common/dbus_test_service_object.h index 00000000,00000000..d2692c25 new file mode 100644 --- /dev/null +++ b/src/smack-dbus-tests/common/dbus_test_service_object.h @@@ -1,0 -1,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 --cc src/smack-dbus-tests/cynara_dbus_tests.cpp index 00000000,00000000..0cbd8fc7 new file mode 100644 --- /dev/null +++ b/src/smack-dbus-tests/cynara_dbus_tests.cpp @@@ -1,0 -1,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 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 &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 --cc src/smack-dbus-tests/main.cpp index 00000000,00000000..8d2261b7 new file mode 100644 --- /dev/null +++ b/src/smack-dbus-tests/main.cpp @@@ -1,0 -1,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 --cc src/smack-dbus-tests/smack_dbus_tests.cpp index 00000000,233994e8..a17b5431 mode 000000,100644..100644 --- a/src/smack-dbus-tests/smack_dbus_tests.cpp +++ b/src/smack-dbus-tests/smack_dbus_tests.cpp @@@ -1,0 -1,305 +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(tc01_smack_context_from_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(tc01_smack_context_from_DBus_nosmack) ++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); + } + } - -int main(int argc, char *argv[]) -{ - return DPL::Test::TestRunnerSingleton::Instance().ExecTestRunner(argc, argv); -}