certifiacte validation code added
[profile/ivi/message-port.git] / daemon / dbus-manager.c
1 /* vi: set et sw=4 ts=4 cino=t0,(0: */
2 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 /*
4  * Copyright (C) 2013 Intel Corporation.
5  *
6  * Contact: Amarnath Valluri <amarnath.valluri@linux.intel.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21  * 02110-1301 USA
22  */
23
24 #include "dbus-manager.h"
25 #include "common/dbus-manager-glue.h"
26 #include "common/dbus-service-glue.h"
27 #include "common/dbus-error.h"
28 #include "common/log.h"
29 #include "dbus-service.h"
30 #include "dbus-server.h"
31 #include "manager.h"
32 #include "utils.h"
33
34 G_DEFINE_TYPE (MsgPortDbusManager, msgport_dbus_manager, G_TYPE_OBJECT)
35
36 #define MSGPORT_DBUS_MANAGER_GET_PRIV(obj) \
37     G_TYPE_INSTANCE_GET_PRIVATE ((obj), MSGPORT_TYPE_DBUS_MANAGER, MsgPortDbusManagerPrivate)
38
39 struct _MsgPortDbusManagerPrivate {
40     MsgPortDbusGlueManager *dbus_skeleton;
41     GDBusConnection        *connection;
42     MsgPortManager         *manager;
43     MsgPortDbusServer      *server;
44     gchar                  *app_id;
45     gboolean                is_null_cert;
46     GHashTable             *peer_certs;
47 };
48
49
50 static void
51 _dbus_manager_finalize (GObject *self)
52 {
53     //MsgPortDbusManager *manager = MSGPORT_DBUS_MANAGER (self);
54
55     G_OBJECT_CLASS (msgport_dbus_manager_parent_class)->finalize (self);
56 }
57
58 static void
59 _dbus_manager_dispose (GObject *self)
60 {
61     MsgPortDbusManager *dbus_mgr = MSGPORT_DBUS_MANAGER (self);
62
63     DBG ("Unexporting dbus manager %p on connection %p", dbus_mgr, dbus_mgr->priv->connection);
64     if (dbus_mgr->priv->dbus_skeleton) {
65         g_dbus_interface_skeleton_unexport (
66                 G_DBUS_INTERFACE_SKELETON (dbus_mgr->priv->dbus_skeleton));
67         g_clear_object (&dbus_mgr->priv->dbus_skeleton);
68     }
69
70     g_clear_object (&dbus_mgr->priv->connection);
71
72     /* unregister all services owned by this connection */
73     msgport_manager_unregister_services (dbus_mgr->priv->manager, dbus_mgr, NULL);
74
75     g_clear_object (&dbus_mgr->priv->manager);
76
77     if (dbus_mgr->priv->peer_certs) {
78         g_hash_table_unref (dbus_mgr->priv->peer_certs);
79         dbus_mgr->priv->peer_certs = NULL;
80     }
81
82     G_OBJECT_CLASS (msgport_dbus_manager_parent_class)->dispose (self);
83 }
84
85
86 static gboolean
87 _dbus_manager_handle_register_service (
88     MsgPortDbusManager    *dbus_mgr,
89     GDBusMethodInvocation *invocation,
90     const gchar           *port_name,
91     gboolean               is_trusted,
92     gpointer               userdata)
93 {
94     GError *error = NULL;
95     MsgPortDbusService *dbus_service = NULL;
96     msgport_return_val_if_fail (dbus_mgr &&  MSGPORT_IS_DBUS_MANAGER (dbus_mgr), FALSE);
97
98     DBG ("register service request from %p for port %s", dbus_mgr, port_name);
99
100     dbus_service = msgport_manager_register_service (
101             dbus_mgr->priv->manager, dbus_mgr, 
102             port_name, is_trusted, &error);
103
104     if (dbus_service) {
105         msgport_dbus_glue_manager_complete_register_service (
106                 dbus_mgr->priv->dbus_skeleton, invocation, 
107                 msgport_dbus_service_get_object_path(dbus_service));
108         return TRUE;
109     }
110
111     if (!error) error = msgport_error_unknown_new ();
112     g_dbus_method_invocation_take_error (invocation, error);
113
114     return TRUE;
115 }
116
117 static gboolean
118 _dbus_manager_handle_check_for_remote_service (
119     MsgPortDbusManager    *dbus_mgr,
120     GDBusMethodInvocation *invocation,
121     const gchar    *remote_app_id,
122     const gchar    *remote_port_name,
123     gboolean        is_trusted,
124     gpointer        userdata)
125 {
126     GError *error = NULL;
127     MsgPortDbusService *dbus_service = NULL;
128     MsgPortDbusManager *remote_dbus_manager = NULL;
129
130     msgport_return_val_if_fail (dbus_mgr && MSGPORT_IS_DBUS_MANAGER (dbus_mgr), FALSE);
131
132     DBG ("check remote service request from %p for %s %s %d", 
133             dbus_mgr, remote_app_id, remote_port_name, is_trusted);
134
135     remote_dbus_manager = msgport_dbus_server_get_dbus_manager_by_app_id (
136                 dbus_mgr->priv->server, remote_app_id);
137
138     if (remote_dbus_manager) {
139         dbus_service = msgport_manager_get_service (dbus_mgr->priv->manager, 
140                             remote_dbus_manager, remote_port_name, is_trusted, &error);
141         if (dbus_service) {
142             DBG ("Found service id : %d", msgport_dbus_service_get_id (dbus_service));
143             msgport_dbus_glue_manager_complete_check_for_remote_service (
144                 dbus_mgr->priv->dbus_skeleton, invocation, 
145                 msgport_dbus_service_get_id (dbus_service));
146             return TRUE;
147         }
148     }
149
150     if (!error) error = msgport_error_port_not_found (remote_app_id, remote_port_name);
151     g_dbus_method_invocation_take_error (invocation, error);
152
153     return TRUE;
154 }
155
156 static gboolean
157 _dbus_manager_handle_send_message (
158     MsgPortDbusManager    *dbus_mgr,
159     GDBusMethodInvocation *invocation,
160     guint                  service_id,
161     GVariant              *data,
162     gpointer               userdata)
163 {
164     GError *error = NULL;
165     MsgPortDbusService *peer_dbus_service = 0;
166
167     msgport_return_val_if_fail (dbus_mgr && MSGPORT_IS_DBUS_MANAGER (dbus_mgr), FALSE);
168
169     DBG ("send_message from %p : %d ", dbus_mgr, service_id);
170
171     peer_dbus_service = msgport_manager_get_service_by_id (
172             dbus_mgr->priv->manager, service_id, &error);
173
174     if (peer_dbus_service) {
175         if (msgport_dbus_service_send_message (peer_dbus_service, data, dbus_mgr->priv->app_id, "", FALSE, &error)) {
176             msgport_dbus_glue_manager_complete_send_message (
177                 dbus_mgr->priv->dbus_skeleton, invocation);
178             return TRUE;
179         }
180     }
181
182     if (!error) error = msgport_error_unknown_new ();
183     g_dbus_method_invocation_take_error (invocation, error);
184
185     return TRUE;
186 }
187
188 static void
189 msgport_dbus_manager_class_init (MsgPortDbusManagerClass *klass)
190 {
191     GObjectClass *gklass = G_OBJECT_CLASS(klass);
192
193     g_type_class_add_private (klass, sizeof(MsgPortDbusManagerPrivate));
194
195     gklass->finalize = _dbus_manager_finalize;
196     gklass->dispose = _dbus_manager_dispose;
197 }
198
199 static void
200 msgport_dbus_manager_init (MsgPortDbusManager *self)
201 {
202     MsgPortDbusManagerPrivate *priv = MSGPORT_DBUS_MANAGER_GET_PRIV (self);
203
204     priv->dbus_skeleton = msgport_dbus_glue_manager_skeleton_new ();
205     priv->manager = msgport_manager_new ();
206     priv->is_null_cert = FALSE;
207     priv->peer_certs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
208
209     g_signal_connect_swapped (priv->dbus_skeleton, "handle-register-service",
210                 G_CALLBACK (_dbus_manager_handle_register_service), (gpointer)self);
211     g_signal_connect_swapped (priv->dbus_skeleton, "handle-check-for-remote-service",
212                 G_CALLBACK (_dbus_manager_handle_check_for_remote_service), (gpointer)self);
213     g_signal_connect_swapped (priv->dbus_skeleton, "handle-send-message",
214                 G_CALLBACK (_dbus_manager_handle_send_message), (gpointer)self);
215
216     self->priv = priv;
217 }
218 static gchar *
219 _get_app_id_from_connection (GDBusConnection *connection)
220 {
221     pid_t peer_pid;
222     GError *error = NULL;
223     GCredentials *cred = g_dbus_connection_get_peer_credentials (connection);
224
225     msgport_return_val_if_fail (cred != NULL, NULL);
226
227 #ifdef ENABLE_DEBUG
228     gchar *str_cred = g_credentials_to_string (cred);
229     DBG ("Client Credentials : %s", str_cred);
230     g_free (str_cred);
231 #endif
232
233     peer_pid = g_credentials_get_unix_pid (cred, &error);
234     if (error) {
235         WARN ("Faild to get peer pid on conneciton %p : %s", connection, error->message);
236         g_error_free (error);
237         return NULL;
238     }
239
240 #if 0
241     char buffer[255];
242     if ((res = aul_app_get_appid_bypid (peer_pid, &buffer, sizeof(buffer))) != AUL_R_OK) {
243         WARN ("Fail to get appid of peer pid '%d', error : %d", peer_pid, res);
244         return NULL;
245     }
246     else g_strdup (buffer);
247 #else
248     return g_strdup_printf ("%d", peer_pid);
249 #endif
250 }
251
252 MsgPortDbusManager *
253 msgport_dbus_manager_new (
254     GDBusConnection *connection,
255     MsgPortDbusServer *server,
256     GError **error)
257 {
258     MsgPortDbusManager *dbus_mgr = NULL;
259
260     dbus_mgr = MSGPORT_DBUS_MANAGER (g_object_new (MSGPORT_TYPE_DBUS_MANAGER, NULL));
261     if (!dbus_mgr) {
262         if (error) *error = msgport_error_new (MSGPORT_ERROR_OUT_OF_MEMORY, "Out of memory");
263         return NULL;
264     }
265
266     if (!g_dbus_interface_skeleton_export (
267             G_DBUS_INTERFACE_SKELETON (dbus_mgr->priv->dbus_skeleton),
268             connection,
269             "/",
270             error)) {
271         WARN ("Failed to export dbus object on connection %p : %s",
272                     connection, error ? (*error)->message : "");
273         g_object_unref (dbus_mgr);
274         return NULL;
275     }
276     dbus_mgr->priv->connection = g_object_ref (connection);
277     dbus_mgr->priv->server = server;
278     dbus_mgr->priv->app_id =  _get_app_id_from_connection (connection);
279
280     return dbus_mgr;
281 }
282
283 MsgPortManager *
284 msgport_dbus_manager_get_manager (MsgPortDbusManager *dbus_manager)
285 {
286     msgport_return_val_if_fail (dbus_manager && MSGPORT_IS_DBUS_MANAGER (dbus_manager), NULL);
287
288     return dbus_manager->priv->manager;
289 }
290
291 GDBusConnection *
292 msgport_dbus_manager_get_connection (MsgPortDbusManager *dbus_manager)
293 {
294     msgport_return_val_if_fail (dbus_manager && MSGPORT_IS_DBUS_MANAGER (dbus_manager), NULL);
295
296     return dbus_manager->priv->connection;
297 }
298
299 const gchar *
300 msgport_dbus_manager_get_app_id (MsgPortDbusManager *dbus_manager)
301 {
302     msgport_return_val_if_fail (dbus_manager && MSGPORT_IS_DBUS_MANAGER (dbus_manager), NULL);
303
304     return (const gchar *)dbus_manager->priv->app_id;
305 }
306
307 gboolean
308 msgport_dbus_manager_validate_peer_certificate (MsgPortDbusManager *dbus_manager, const gchar *peer_app_id)
309 {
310     //int res ;
311     //pkgmgrinfo_cert_compare_result_type_e compare_result;
312     gboolean is_valid_cert = FALSE;
313
314     /* check if the source application has no certificate info */
315     if (dbus_manager->priv->is_null_cert)
316         return TRUE; /* allow all peers to connect */
317
318     /* check if we have cached status */
319     if (g_hash_table_contains (dbus_manager->priv->peer_certs, peer_app_id))
320         return (gboolean) g_hash_table_lookup (dbus_manager->priv->peer_certs, peer_app_id);
321 #if 0
322     if ((res = pkgmgrinfo_pkginfo_compare_app_cert_info (dbus_manager->priv->app_id,
323                     peer_app_id, &compare_result)) != PACKAGE_MANAGER_ERROR_NONE) {
324         WARN ("Fail to compare certificates of applications('%s', '%s') : error %d", 
325                 dbus_manager->priv->app_id, peer_app_id, res);
326         return FALSE;
327     }
328     if (compare_result == PMINFO_CERT_COMPARE_LHS_NO_CERT) {
329         dbus_manager->priv->is_null_cert = TRUE;
330         return TRUE;
331     }
332
333     is_valid_cert = (compare_result == PMINFO_CERT_COMPARE_MATCH) ;
334     g_hash_table_insert (dbus_manager->priv->peer_certs, g_strdup (peer_app_id), (gpointer)is_valid_cert);
335 #endif
336
337     return is_valid_cert;
338 }
339