Update to upstream 1.0.1
[profile/ivi/gsignond.git] / src / extensions / tizen / tizen-access-control-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  * This file is part of gsignond
5  *
6  * Copyright (C) 2013 Intel Corporation.
7  *
8  * Contact: Jussi Laako <jussi.laako@linux.intel.com>
9  * Contact: Elena Reshetova <elena.reshetova@linux.intel.com>
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public
13  * License as published by the Free Software Foundation; either
14  * version 2.1 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  * Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with this library; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
24  * 02110-1301 USA
25  */
26
27 #include <stdlib.h>
28 #include <sys/smack.h>
29 #include <glib.h>
30 #include <gio/gio.h>
31
32 #include "gsignond/gsignond-log.h"
33 #include "tizen-access-control-manager.h"
34
35 #define EXTENSION_TIZEN_ACCESS_CONTROL_MANAGER_GET_PRIVATE(obj) \
36     (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
37                                   EXTENSION_TYPE_TIZEN_ACCESS_CONTROL_MANAGER, \
38                                   ExtensionTizenAccessControlManagerPrivate))
39
40 #define DBUS_SERVICE_DBUS "org.freedesktop.DBus"
41 #define DBUS_PATH_DBUS "/org/freedesktop/DBus"
42 #define DBUS_INTERFACE_DBUS "org.freedesktop.DBus"
43
44 static const gchar keychainAppId[] = "gSignond::keychain";
45
46 struct _ExtensionTizenAccessControlManagerPrivate
47 {
48 };
49
50 G_DEFINE_TYPE (ExtensionTizenAccessControlManager,
51                extension_tizen_access_control_manager,
52                GSIGNOND_TYPE_ACCESS_CONTROL_MANAGER);
53
54 static void
55 extension_tizen_access_control_manager_class_init (
56                               ExtensionTizenAccessControlManagerClass *klass)
57 {
58    
59     /*GObjectClass *base = G_OBJECT_CLASS (klass);
60
61     g_type_class_add_private (klass,
62                               sizeof(ExtensionTestAccessControlManagerPrivate));*/
63
64     GSignondAccessControlManagerClass *parent =
65         GSIGNOND_ACCESS_CONTROL_MANAGER_CLASS (klass);
66                               
67     parent->security_context_of_peer = extension_tizen_access_control_manager_security_context_of_peer;
68     parent->peer_is_allowed_to_use_identity = extension_tizen_access_control_manager_peer_is_allowed_to_use_identity;
69     parent->peer_is_owner_of_identity = extension_tizen_access_control_manager_peer_is_owner_of_identity;
70     parent->security_context_of_keychain = extension_tizen_access_control_manager_security_context_of_keychain;
71 }
72
73 static void
74 extension_tizen_access_control_manager_init (
75                                        ExtensionTizenAccessControlManager *self)
76 {
77     /*self->priv = EXTENSION_TEST_ACCESS_CONTROL_MANAGER_GET_PRIVATE (self);*/
78 }
79
80 void
81 extension_tizen_access_control_manager_security_context_of_peer (
82                             GSignondAccessControlManager *self,
83                             GSignondSecurityContext *peer_ctx,
84                             int peer_fd, const gchar *peer_service,
85                             const gchar *peer_app_ctx)
86 {
87     (void) self;
88
89     gsignond_security_context_set_system_context (peer_ctx, "");
90     gsignond_security_context_set_application_context (peer_ctx,
91                                                        peer_app_ctx);
92     if (peer_fd != -1) {
93         char *label = NULL;
94
95         smack_new_label_from_socket(peer_fd, &label);
96         if (label) {
97             gsignond_security_context_set_system_context (peer_ctx,
98                                                           label);
99             free (label);
100         }
101     } else if (peer_service != NULL) {
102         GError *error = NULL;
103         GDBusConnection *connection;
104         GDBusProxy *proxy;
105         GVariant *response = NULL;
106         const gchar *label;
107
108         connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
109         if (connection == NULL) {
110             WARN ("Failed to open connection to bus: %s", error->message);
111             g_error_free (error);
112             return;
113         }
114         
115         error = NULL;
116         proxy = g_dbus_proxy_new_sync (connection,
117                                        G_DBUS_PROXY_FLAGS_NONE, 
118                                        NULL,
119                                        DBUS_SERVICE_DBUS,
120                                        DBUS_PATH_DBUS,
121                                        DBUS_INTERFACE_DBUS,
122                                        NULL,
123                                        &error);
124         if (proxy == NULL) {
125             WARN ("Error creating proxy: %s", error->message);
126             g_error_free (error);
127             goto _dbus_connection_exit;
128         }
129
130         /* Call getConnectionSmackContext method, wait for reply */
131
132         error = NULL;
133         response = g_dbus_proxy_call_sync (proxy,
134                                            "GetConnectionSmackContext",  
135                                            g_variant_new ("(s)", peer_service),
136                                            G_DBUS_CALL_FLAGS_NONE,
137                                            -1,
138                                            NULL,
139                                            &error);
140         if (response == NULL) {
141             WARN ("Error: %s", error->message);
142             g_error_free (error);
143             goto _dbus_proxy_exit;
144         }
145         
146         label = g_variant_get_string (response, NULL);
147         DBG ("Obtained label from dbus: %s", label);
148         if (label)
149             gsignond_security_context_set_system_context (peer_ctx,
150                                                           label);
151
152         g_variant_unref (response);
153
154 _dbus_proxy_exit:
155         g_object_unref (proxy);
156 _dbus_connection_exit:
157         g_object_unref (connection);
158     } 
159 }
160
161 gboolean
162 extension_tizen_access_control_manager_peer_is_allowed_to_use_identity (
163                             GSignondAccessControlManager *self,
164                             const GSignondSecurityContext *peer_ctx,
165                             const GSignondSecurityContext *identity_owner,
166                             const GSignondSecurityContextList *identity_acl)
167 {
168     GSignondSecurityContext* acl_ctx = NULL;
169     const gchar *peer_system_ctx = gsignond_security_context_get_system_context(peer_ctx);
170     const gchar *owner_system_ctx = gsignond_security_context_get_system_context(identity_owner);
171     
172     (void) self;
173     
174     for ( ; identity_acl != NULL; identity_acl = g_list_next (identity_acl)) {
175         acl_ctx = (GSignondSecurityContext *) identity_acl->data;
176         if (gsignond_security_context_check (acl_ctx, peer_ctx)) {
177             // we have a match in acl, now we need to check is smack allows such access
178             /* smack_have_access() returns
179              * 1 = have access,
180              * 0 = no access,
181              * -1 = error
182              */
183             return (smack_have_access (peer_system_ctx, owner_system_ctx, "x") == 1) ? TRUE : FALSE;
184         }
185     }
186     
187     return FALSE;
188 }
189
190 gboolean
191 extension_tizen_access_control_manager_peer_is_owner_of_identity (
192                             GSignondAccessControlManager *self,
193                             const GSignondSecurityContext *peer_ctx,
194                             const GSignondSecurityContext *identity_owner)
195 {
196     (void) self;
197
198     return (gsignond_security_context_compare (peer_ctx, identity_owner) == 0);
199 }
200
201 GSignondSecurityContext *
202 extension_tizen_access_control_manager_security_context_of_keychain (
203                                              GSignondAccessControlManager *self)
204 {
205     g_return_val_if_fail (self != NULL, NULL);
206
207     const gchar *keychain_sysctx;
208
209     keychain_sysctx = gsignond_config_get_string (
210                                       self->config,
211                                       GSIGNOND_CONFIG_GENERAL_KEYCHAIN_SYSCTX);
212     if (!keychain_sysctx)
213 #       ifdef KEYCHAIN_SYSCTX
214         keychain_sysctx = KEYCHAIN_SYSCTX;
215 #       else
216         keychain_sysctx = keychainAppId;
217 #       endif
218
219     return gsignond_security_context_new_from_values (keychain_sysctx, NULL);
220 }