2 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <security-server.h>
21 #include <types_internal.h>
22 #include <scope_mutex.h>
23 #include "response_handler.h"
24 #include "dbus_client.h"
26 static GDBusConnection *dbus_connection = NULL;
27 static GDBusNodeInfo *dbus_node_info = NULL;
29 static const gchar introspection_xml[] =
31 " <interface name='"DBUS_IFACE"'>"
32 " <method name='"METHOD_RESPOND"'>"
33 " <arg type='i' name='"ARG_REQID"' direction='in'/>"
34 " <arg type='s' name='"ARG_SUBJECT"' direction='in'/>"
35 " <arg type='i' name='"ARG_RESULT_ERR"' direction='in'/>"
36 " <arg type='s' name='"ARG_OUTPUT"' direction='in'/>"
41 static const char* get_security_cookie()
43 static char *cookie = NULL;
44 static GMutex cookie_mutex;
45 ctx::scope_mutex sm(&cookie_mutex);
48 int raw_size = security_server_get_cookie_size();
49 IF_FAIL_RETURN_TAG(raw_size > 0, NULL, _E, "Invalid cookie size");
52 char raw_cookie[raw_size];
54 ret = security_server_request_cookie(raw_cookie, raw_size);
55 IF_FAIL_RETURN_TAG(ret >= 0, NULL, _E, "Failed to get the security cookie");
57 cookie = g_base64_encode(reinterpret_cast<guchar*>(raw_cookie), raw_size);
58 IF_FAIL_RETURN_TAG(cookie, NULL, _E, "Failed to encode the cookie");
64 static void handle_response(const gchar *sender, GVariant *param, GDBusMethodInvocation *invocation)
67 const gchar *subject = NULL;
69 const gchar *data = NULL;
71 g_variant_get(param, "(i&si&s)", &req_id, &subject, &error, &data);
72 _D("[Response] ReqId: %d, Subject: %s, Error: %d", req_id, subject, error);
74 ctx::response_handler::deliver(subject, req_id, error, data);
75 g_dbus_method_invocation_return_value(invocation, NULL);
78 static void handle_method_call(GDBusConnection *conn, const gchar *sender,
79 const gchar *obj_path, const gchar *iface, const gchar *method_name,
80 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
82 IF_FAIL_VOID_TAG(STR_EQ(obj_path, DBUS_PATH), _W, "Invalid path: %s", obj_path);
83 IF_FAIL_VOID_TAG(STR_EQ(iface, DBUS_IFACE), _W, "Invalid interface: %s", obj_path);
85 if (STR_EQ(method_name, METHOD_RESPOND)) {
86 handle_response(sender, param, invocation);
88 _W("Invalid method: %s", method_name);
92 ctx::dbus_client::dbus_client()
96 ctx::dbus_client::~dbus_client()
101 bool ctx::dbus_client::init()
103 static GMutex connection_mutex;
104 ctx::scope_mutex sm(&connection_mutex);
106 if (dbus_connection) {
112 dbus_node_info = g_dbus_node_info_new_for_xml(introspection_xml, NULL);
113 IF_FAIL_RETURN_TAG(dbus_node_info != NULL, false, _E, "Initialization failed");
115 gchar *addr = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SYSTEM, NULL, &gerr);
117 IF_FAIL_RETURN_TAG(addr != NULL, false, _E, "Getting address failed");
118 _SD("Address: %s", addr);
120 dbus_connection = g_dbus_connection_new_for_address_sync(addr,
121 (GDBusConnectionFlags)(G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT | G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION),
125 IF_FAIL_RETURN_TAG(dbus_connection != NULL, false, _E, "Connection failed");
127 GDBusInterfaceVTable vtable;
128 vtable.method_call = handle_method_call;
129 vtable.get_property = NULL;
130 vtable.set_property = NULL;
132 guint reg_id = g_dbus_connection_register_object(dbus_connection, DBUS_PATH,
133 dbus_node_info->interfaces[0], &vtable, NULL, NULL, &gerr);
135 IF_FAIL_RETURN_TAG(reg_id>0, false, _E, "Object registration failed");
137 _I("Dbus connection established: %s", g_dbus_connection_get_unique_name(dbus_connection));
141 void ctx::dbus_client::release()
143 if (dbus_connection) {
144 g_dbus_connection_flush_sync(dbus_connection, NULL, NULL);
145 g_dbus_connection_close_sync(dbus_connection, NULL, NULL);
146 g_object_unref(dbus_connection);
147 dbus_connection = NULL;
150 if (dbus_node_info) {
151 g_dbus_node_info_unref(dbus_node_info);
152 dbus_node_info = NULL;
156 int ctx::dbus_client::request(
157 int type, int req_id, const char* subject, const char* input,
158 std::string* req_result, std::string* data_read)
160 _D("Requesting: %d, %d, %s", type, req_id, subject);
162 if (subject == NULL) {
163 subject = EMPTY_STRING;
167 input = EMPTY_JSON_OBJECT;
170 const char *cookie = get_security_cookie();
171 IF_FAIL_RETURN_TAG(cookie, ERR_OPERATION_FAILED, _E, "Cookie generation failed");
173 GVariant *param = g_variant_new("(isiss)", type, cookie, req_id, subject, input);
174 IF_FAIL_RETURN_TAG(param, ERR_OUT_OF_MEMORY, _E, "Memory allocation failed");
177 GVariant *response = g_dbus_connection_call_sync(dbus_connection, DBUS_DEST, DBUS_PATH, DBUS_IFACE,
178 METHOD_REQUEST, param, NULL, G_DBUS_CALL_FLAGS_NONE, DBUS_TIMEOUT, NULL, &err);
180 IF_FAIL_RETURN_TAG(response, ERR_OPERATION_FAILED, _E, "Method call failed");
182 gint _error = ERR_OPERATION_FAILED;
183 const gchar *_req_result = NULL;
184 const gchar *_data_read = NULL;
186 g_variant_get(response, "(i&s&s)", &_error, &_req_result, &_data_read);
188 *req_result = _req_result;
191 *data_read = _data_read;
194 g_variant_unref(response);
199 int ctx::dbus_client::request_with_no_reply(
200 int type, int req_id, const char* subject, const char* input)
202 _D("Requesting: %d, %d, %s", type, req_id, subject);
204 if (subject == NULL) {
205 subject = EMPTY_STRING;
209 input = EMPTY_JSON_OBJECT;
212 const char *cookie = get_security_cookie();
213 IF_FAIL_RETURN_TAG(cookie, ERR_OPERATION_FAILED, _E, "Cookie generation failed");
215 GVariant *param = g_variant_new("(isiss)", type, cookie, req_id, subject, input);
216 IF_FAIL_RETURN_TAG(param, ERR_OUT_OF_MEMORY, _E, "Memory allocation failed");
219 g_dbus_connection_call(dbus_connection, DBUS_DEST, DBUS_PATH, DBUS_IFACE,
220 METHOD_REQUEST, param, NULL, G_DBUS_CALL_FLAGS_NONE, DBUS_TIMEOUT, NULL, NULL, &err);
224 return ERR_OPERATION_FAILED;