1 /* vi: set et sw=4 ts=4 cino=t0,(0: */
2 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
4 * This file is part of message-port.
6 * Copyright (C) 2013 Intel Corporation.
8 * Contact: Amarnath Valluri <amarnath.valluri@linux.intel.com>
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
26 #include "dbus-manager.h"
27 #include "common/dbus-manager-glue.h"
28 #include "common/dbus-service-glue.h"
29 #include "common/dbus-error.h"
30 #include "common/log.h"
31 #include "dbus-service.h"
32 #include "dbus-server.h"
37 #include <pkgmgr-info.h>
39 G_DEFINE_TYPE (MsgPortDbusManager, msgport_dbus_manager, G_TYPE_OBJECT)
41 #define MSGPORT_DBUS_MANAGER_GET_PRIV(obj) \
42 G_TYPE_INSTANCE_GET_PRIVATE ((obj), MSGPORT_TYPE_DBUS_MANAGER, MsgPortDbusManagerPrivate)
44 struct _MsgPortDbusManagerPrivate {
45 MsgPortDbusGlueManager *dbus_skeleton;
46 GDBusConnection *connection;
47 MsgPortManager *manager;
48 MsgPortDbusServer *server;
50 gboolean is_null_cert;
51 GHashTable *peer_certs;
56 _dbus_manager_finalize (GObject *self)
58 //MsgPortDbusManager *manager = MSGPORT_DBUS_MANAGER (self);
60 G_OBJECT_CLASS (msgport_dbus_manager_parent_class)->finalize (self);
64 _dbus_manager_dispose (GObject *self)
66 MsgPortDbusManager *dbus_mgr = MSGPORT_DBUS_MANAGER (self);
68 DBG ("Unexporting dbus manager %p on connection %p", dbus_mgr, dbus_mgr->priv->connection);
69 if (dbus_mgr->priv->dbus_skeleton) {
70 g_dbus_interface_skeleton_unexport (
71 G_DBUS_INTERFACE_SKELETON (dbus_mgr->priv->dbus_skeleton));
72 g_clear_object (&dbus_mgr->priv->dbus_skeleton);
75 g_clear_object (&dbus_mgr->priv->connection);
77 /* unregister all services owned by this connection */
78 msgport_manager_unregister_services (dbus_mgr->priv->manager, dbus_mgr, NULL);
80 g_clear_object (&dbus_mgr->priv->manager);
82 if (dbus_mgr->priv->peer_certs) {
83 g_hash_table_unref (dbus_mgr->priv->peer_certs);
84 dbus_mgr->priv->peer_certs = NULL;
87 G_OBJECT_CLASS (msgport_dbus_manager_parent_class)->dispose (self);
92 _dbus_manager_handle_register_service (
93 MsgPortDbusManager *dbus_mgr,
94 GDBusMethodInvocation *invocation,
95 const gchar *port_name,
100 MsgPortDbusService *dbus_service = NULL;
101 msgport_return_val_if_fail (dbus_mgr && MSGPORT_IS_DBUS_MANAGER (dbus_mgr), FALSE);
103 DBG ("register service request from %p('%s') for port '%s', is_trusted: %d",
104 dbus_mgr, dbus_mgr->priv->app_id, port_name, is_trusted);
106 dbus_service = msgport_manager_register_service (
107 dbus_mgr->priv->manager, dbus_mgr,
108 port_name, is_trusted, &error);
111 msgport_dbus_glue_manager_complete_register_service (
112 dbus_mgr->priv->dbus_skeleton, invocation,
113 msgport_dbus_service_get_object_path(dbus_service));
117 if (!error) error = msgport_error_unknown_new ();
118 g_dbus_method_invocation_take_error (invocation, error);
124 _dbus_manager_handle_check_for_remote_service (
125 MsgPortDbusManager *dbus_mgr,
126 GDBusMethodInvocation *invocation,
127 const gchar *remote_app_id,
128 const gchar *remote_port_name,
132 GError *error = NULL;
133 MsgPortDbusService *dbus_service = NULL;
134 MsgPortDbusManager *remote_dbus_manager = NULL;
136 msgport_return_val_if_fail (dbus_mgr && MSGPORT_IS_DBUS_MANAGER (dbus_mgr), FALSE);
138 DBG ("check remote service request from %p for '%s' '%s', is_trusted: %d",
139 dbus_mgr, remote_app_id, remote_port_name, is_trusted);
141 remote_dbus_manager = msgport_dbus_server_get_dbus_manager_by_app_id (
142 dbus_mgr->priv->server, remote_app_id);
144 if (remote_dbus_manager) {
145 dbus_service = msgport_manager_get_service (dbus_mgr->priv->manager,
146 remote_dbus_manager, remote_port_name, is_trusted, &error);
148 DBG ("Found service id : %d", msgport_dbus_service_get_id (dbus_service));
149 msgport_dbus_glue_manager_complete_check_for_remote_service (
150 dbus_mgr->priv->dbus_skeleton, invocation,
151 msgport_dbus_service_get_id (dbus_service));
156 if (!error) error = msgport_error_port_not_found (remote_app_id, remote_port_name);
157 g_dbus_method_invocation_take_error (invocation, error);
163 _dbus_manager_handle_send_message (
164 MsgPortDbusManager *dbus_mgr,
165 GDBusMethodInvocation *invocation,
170 GError *error = NULL;
171 MsgPortDbusService *peer_dbus_service = 0;
173 msgport_return_val_if_fail (dbus_mgr && MSGPORT_IS_DBUS_MANAGER (dbus_mgr), FALSE);
175 DBG ("send_message from %p('%s') to service_id %d",
176 dbus_mgr, dbus_mgr->priv->app_id, service_id);
178 peer_dbus_service = msgport_manager_get_service_by_id (
179 dbus_mgr->priv->manager, service_id, &error);
181 if (peer_dbus_service) {
182 if (msgport_dbus_service_send_message (peer_dbus_service, data, dbus_mgr->priv->app_id, "", FALSE, &error)) {
183 msgport_dbus_glue_manager_complete_send_message (
184 dbus_mgr->priv->dbus_skeleton, invocation);
189 if (!error) error = msgport_error_unknown_new ();
190 g_dbus_method_invocation_take_error (invocation, error);
196 msgport_dbus_manager_class_init (MsgPortDbusManagerClass *klass)
198 GObjectClass *gklass = G_OBJECT_CLASS(klass);
200 g_type_class_add_private (klass, sizeof(MsgPortDbusManagerPrivate));
202 gklass->finalize = _dbus_manager_finalize;
203 gklass->dispose = _dbus_manager_dispose;
207 msgport_dbus_manager_init (MsgPortDbusManager *self)
209 MsgPortDbusManagerPrivate *priv = MSGPORT_DBUS_MANAGER_GET_PRIV (self);
211 priv->dbus_skeleton = msgport_dbus_glue_manager_skeleton_new ();
212 priv->manager = msgport_manager_new ();
213 priv->is_null_cert = FALSE;
214 priv->peer_certs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
216 g_signal_connect_swapped (priv->dbus_skeleton, "handle-register-service",
217 G_CALLBACK (_dbus_manager_handle_register_service), (gpointer)self);
218 g_signal_connect_swapped (priv->dbus_skeleton, "handle-check-for-remote-service",
219 G_CALLBACK (_dbus_manager_handle_check_for_remote_service), (gpointer)self);
220 g_signal_connect_swapped (priv->dbus_skeleton, "handle-send-message",
221 G_CALLBACK (_dbus_manager_handle_send_message), (gpointer)self);
226 _get_app_id_from_connection (GDBusConnection *connection)
229 GError *error = NULL;
230 GCredentials *cred = g_dbus_connection_get_peer_credentials (connection);
232 msgport_return_val_if_fail (cred != NULL, NULL);
234 gchar *str_cred = g_credentials_to_string (cred);
235 DBG ("Client Credentials : %s", str_cred);
239 peer_pid = g_credentials_get_unix_pid (cred, &error);
241 WARN ("Faild to get peer pid on conneciton %p : %s", connection, error->message);
242 g_error_free (error);
248 if ((res = aul_app_get_appid_bypid (peer_pid, app_id, sizeof(app_id))) == AUL_R_OK) {
249 return g_strdup (app_id);
251 WARN ("Fail to get appid of peer pid '%d', error : %d, considering pid as app_id", peer_pid, res);
253 return g_strdup_printf ("%d", peer_pid);
259 msgport_dbus_manager_new (
260 GDBusConnection *connection,
261 MsgPortDbusServer *server,
264 MsgPortDbusManager *dbus_mgr = NULL;
266 dbus_mgr = MSGPORT_DBUS_MANAGER (g_object_new (MSGPORT_TYPE_DBUS_MANAGER, NULL));
268 if (error) *error = msgport_error_new (MSGPORT_ERROR_OUT_OF_MEMORY, "Out of memory");
272 if (!g_dbus_interface_skeleton_export (
273 G_DBUS_INTERFACE_SKELETON (dbus_mgr->priv->dbus_skeleton),
277 WARN ("Failed to export dbus object on connection %p : %s",
278 connection, error ? (*error)->message : "");
279 g_object_unref (dbus_mgr);
282 dbus_mgr->priv->connection = g_object_ref (connection);
283 dbus_mgr->priv->server = server;
284 dbus_mgr->priv->app_id = _get_app_id_from_connection (connection);
290 msgport_dbus_manager_get_manager (MsgPortDbusManager *dbus_manager)
292 msgport_return_val_if_fail (dbus_manager && MSGPORT_IS_DBUS_MANAGER (dbus_manager), NULL);
294 return dbus_manager->priv->manager;
298 msgport_dbus_manager_get_connection (MsgPortDbusManager *dbus_manager)
300 msgport_return_val_if_fail (dbus_manager && MSGPORT_IS_DBUS_MANAGER (dbus_manager), NULL);
302 return dbus_manager->priv->connection;
306 msgport_dbus_manager_get_app_id (MsgPortDbusManager *dbus_manager)
308 msgport_return_val_if_fail (dbus_manager && MSGPORT_IS_DBUS_MANAGER (dbus_manager), NULL);
310 return (const gchar *)dbus_manager->priv->app_id;
314 msgport_dbus_manager_validate_peer_certificate (MsgPortDbusManager *dbus_manager, const gchar *peer_app_id)
317 pkgmgrinfo_cert_compare_result_type_e compare_result;
318 gboolean is_valid_cert = FALSE;
320 /* check if the source application has no certificate info */
321 if (dbus_manager->priv->is_null_cert)
322 return TRUE; /* allow all peers to connect */
324 /* check if we have cached status */
325 if (g_hash_table_contains (dbus_manager->priv->peer_certs, peer_app_id))
326 return ((gboolean)(glong)g_hash_table_lookup (dbus_manager->priv->peer_certs, peer_app_id));
328 if ((res = pkgmgrinfo_pkginfo_compare_app_cert_info (dbus_manager->priv->app_id,
329 peer_app_id, &compare_result)) != PMINFO_R_OK) {
330 WARN ("Fail to compare certificates of applications('%s', '%s') : error %d",
331 dbus_manager->priv->app_id, peer_app_id, res);
335 if (compare_result == PMINFO_CERT_COMPARE_LHS_NO_CERT) {
336 dbus_manager->priv->is_null_cert = TRUE;
340 is_valid_cert = (compare_result == PMINFO_CERT_COMPARE_MATCH) ;
341 g_hash_table_insert (dbus_manager->priv->peer_certs, g_strdup (peer_app_id), (gpointer)is_valid_cert);
343 return is_valid_cert;