Adjust AccessProvider api to current security-server.
[platform/core/test/security-tests.git] / tests / common / dbus_access.cpp
1 /*
2  * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Contact: Bumjin Im <bj.im@samsung.com>
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *   http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License
17  */
18 /*
19  * @file        dbus_access.cpp
20  * @author      Zbigniew Jasinski (z.jasinski@samsung.com)
21  * @version     1.0
22  * @brief       Functios used in security-tests package for restarting Security Server through
23  *              SystemD DBuS interface.
24  */
25
26 #include <dpl/log/log.h>
27 #include <tests_common.h>
28
29 #include <cstring>
30
31 #include "dbus_access.h"
32
33 DBusAccess::DBusAccess()
34   : m_conn(NULL)
35   , m_msg(NULL)
36   , m_pending(NULL)
37   , m_handled(FALSE)
38 {
39     dbus_error_init(&m_err);
40
41     m_signal_type         = "signal";
42     m_signal_interface    = "org.freedesktop.systemd1.Manager";
43     m_signal_member       = "JobRemoved";
44     m_signal_path         = "/org/freedesktop/systemd1";
45
46     m_signal_match        = "type='" + m_signal_type + "',interface='" + m_signal_interface +
47                             "',member='" + m_signal_member + "',path='" + m_signal_path + "'";
48
49     m_dbus_client_name    = "tests.dbus.client";
50 }
51
52 void DBusAccess::connect() {
53     m_conn = dbus_bus_get_private(DBUS_BUS_SYSTEM, &m_err);
54     RUNNER_ASSERT_MSG_BT(dbus_error_is_set(&m_err) != 1,
55         "Error in dbus_bus_get: " << m_err.message);
56     dbus_connection_set_exit_on_disconnect(m_conn, FALSE);
57 }
58
59 void DBusAccess::requestName() {
60     dbus_bus_request_name(m_conn, m_dbus_client_name.c_str(),
61         DBUS_NAME_FLAG_REPLACE_EXISTING , &m_err);
62     RUNNER_ASSERT_MSG_BT(dbus_error_is_set(&m_err) != 1,
63         "Error in dbus_bus_request_name: " << m_err.message);
64 }
65
66 void DBusAccess::newMethodCall(const std::string& method) {
67     const std::string dbus_systemd_name = "org.freedesktop.systemd1";
68     const std::string dbus_systemd_object =
69         "/org/freedesktop/systemd1/unit/security_2dserver_2eservice";
70     const std::string dbus_systemd_interface = "org.freedesktop.systemd1.Unit";
71
72     m_msg = dbus_message_new_method_call(dbus_systemd_name.c_str(),
73                                          dbus_systemd_object.c_str(),
74                                          dbus_systemd_interface.c_str(),
75                                          method.c_str());
76     RUNNER_ASSERT_MSG_BT(NULL != m_msg,
77         "Error in dbus_message_new_method_call");
78 }
79
80 void DBusAccess::appendToMsg() {
81     DBusMessageIter iter;
82     const char *dbus_systemd_srv_unit_mode = "fail";
83
84     dbus_message_iter_init_append(m_msg, &iter);
85     int ret = dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING,
86         &dbus_systemd_srv_unit_mode);
87     RUNNER_ASSERT_MSG_BT(ret != 0,
88         "Error in dbus_message_iter_append_basic");
89 }
90
91 void DBusAccess::sendMsgWithReply() {
92     int ret = dbus_connection_send_with_reply(m_conn, m_msg, &m_pending, -1);
93     RUNNER_ASSERT_MSG_BT(ret == 1,
94         "Error in dbus_connection_send_with_reply");
95
96     RUNNER_ASSERT_MSG_BT(NULL != m_pending, "Pending call null");
97
98     dbus_connection_flush(m_conn);
99     dbus_pending_call_block(m_pending);
100     dbus_message_unref(m_msg);
101     m_msg = NULL;
102 }
103
104 void DBusAccess::getMsgReply() {
105     m_msg = dbus_pending_call_steal_reply(m_pending);
106     RUNNER_ASSERT_MSG_BT(NULL != m_msg,
107         "Error in dbus_pending_call_steal_reply");
108 }
109
110 void DBusAccess::handleMsgRestartReply() {
111     char *object_path = NULL;
112     DBusMessageIter iter;
113
114     RUNNER_ASSERT_MSG_BT(dbus_message_iter_init(m_msg, &iter) != 0,
115         "Message has no arguments");
116     if (DBUS_TYPE_OBJECT_PATH == dbus_message_iter_get_arg_type(&iter)) {
117         dbus_message_iter_get_basic(&iter, &object_path);
118         m_jobID = std::strrchr(object_path, '/') + 1;
119     } else {
120         RUNNER_ASSERT_MSG_BT(false, "No job path in msg");
121     }
122     dbus_message_unref(m_msg);
123     dbus_pending_call_unref(m_pending);
124     m_msg = NULL;
125     m_pending = NULL;
126 }
127
128 DBusHandlerResult DBusAccess::signalFilter(DBusConnection *, DBusMessage *message, void *This) {
129     DBusMessageIter iter;
130     dbus_uint32_t id;
131     DBusAccess *a = reinterpret_cast<DBusAccess *>(This);
132
133     if (dbus_message_is_signal(message, a->m_signal_interface.c_str(), a->m_signal_member.c_str()))
134     {
135         RUNNER_ASSERT_MSG_BT(dbus_message_iter_init(message, &iter) != 0,
136             "No messages in reply");
137
138         RUNNER_ASSERT_MSG_BT(dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_UINT32,
139             "Argument is not integer");
140
141         dbus_message_iter_get_basic(&iter, &id);
142
143         if (id == (unsigned int)std::stoi(a->m_jobID)) {
144             while (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INVALID) {
145                 if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING) {
146                     char *str = NULL;
147                     dbus_message_iter_get_basic(&iter, &str);
148                     if (!strncmp(str, "done", strlen("done")))
149                         a->m_handled = TRUE;
150                 }
151                 dbus_message_iter_next(&iter);
152             }
153         }
154     }
155     return (a->m_handled ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
156 }
157
158 void DBusAccess::handleMsgRestartSignal() {
159     dbus_bus_add_match(m_conn, m_signal_match.c_str(), &m_err);
160     RUNNER_ASSERT_MSG_BT(dbus_error_is_set(&m_err) != 1,
161         "Error in dbus_bus_add_match: " << m_err.message);
162
163     dbus_connection_add_filter(m_conn, signalFilter, reinterpret_cast<void *>(this), NULL);
164
165     while(dbus_connection_read_write_dispatch(m_conn, 1000)) {
166         if(m_handled)
167             break;
168     }
169 }
170
171 void DBusAccess::connectToDBus() {
172     connect();
173     requestName();
174 }
175
176 void DBusAccess::sendRestartToSS() {
177     const std::string method = "Restart";
178
179     newMethodCall(method);
180     appendToMsg();
181     sendMsgWithReply();
182     getMsgReply();
183     handleMsgRestartReply();
184     handleMsgRestartSignal();
185 }
186
187 void DBusAccess::sendResetFailedToSS() {
188     const std::string method = "ResetFailed";
189
190     newMethodCall(method);
191     sendMsgWithReply();
192     getMsgReply();
193 }
194
195 void DBusAccess::restartSS() {
196     connectToDBus();
197     sendRestartToSS();
198     sendResetFailedToSS();
199 }
200
201 DBusAccess::~DBusAccess() {
202     dbus_connection_close(m_conn);
203     if (m_conn)
204         dbus_connection_unref(m_conn);
205     dbus_error_free(&m_err);
206     if (m_msg)
207         dbus_message_unref(m_msg);
208     if (m_pending)
209         dbus_pending_call_unref(m_pending);
210 }