Add support for sending flight mode indication
[connman] / plugins / polkit.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2009  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <errno.h>
27
28 #include <glib.h>
29 #include <polkit-dbus/polkit-dbus.h>
30
31 #define CONNMAN_API_SUBJECT_TO_CHANGE
32 #include <connman/plugin.h>
33 #include <connman/security.h>
34 #include <connman/dbus.h>
35 #include <connman/log.h>
36
37 #define ACTION_MODIFY "org.moblin.connman.modify"
38 #define ACTION_SECRET "org.moblin.connman.secret"
39
40 static DBusConnection *connection;
41 static PolKitContext *polkit_context;
42
43 static int polkit_authorize(const char *sender,
44                                 enum connman_security_privilege privilege)
45 {
46         DBusError error;
47         PolKitCaller *caller;
48         PolKitAction *action;
49         PolKitResult result;
50         const char *id = NULL;
51
52         DBG("sender %s", sender);
53
54         switch (privilege) {
55         case CONNMAN_SECURITY_PRIVILEGE_PUBLIC:
56                 return 0;
57         case CONNMAN_SECURITY_PRIVILEGE_MODIFY:
58                 id = ACTION_MODIFY;
59                 break;
60         case CONNMAN_SECURITY_PRIVILEGE_SECRET:
61                 id = ACTION_SECRET;
62                 break;
63         }
64
65         dbus_error_init(&error);
66
67         caller = polkit_caller_new_from_dbus_name(connection, sender, &error);
68         if (caller == NULL) {
69                 if (dbus_error_is_set(&error) == TRUE) {
70                         connman_error("%s", error.message);
71                         dbus_error_free(&error);
72                 } else
73                         connman_error("Failed to get caller information");
74                 return -EIO;
75         }
76
77         action = polkit_action_new();
78         polkit_action_set_action_id(action, id);
79
80         result = polkit_context_is_caller_authorized(polkit_context,
81                                                 action, caller, TRUE, NULL);
82
83         polkit_action_unref(action);
84         polkit_caller_unref(caller);
85
86         DBG("result %s", polkit_result_to_string_representation(result));
87
88         if (result == POLKIT_RESULT_NO)
89                 return -EPERM;
90
91         return 0;
92 }
93
94 static struct connman_security polkit_security = {
95         .name                   = "polkit",
96         .authorize_sender       = polkit_authorize,
97 };
98
99 static gboolean watch_event(GIOChannel *channel, GIOCondition condition,
100                                                         gpointer user_data)
101 {
102         PolKitContext *context = user_data;
103         int fd;
104
105         DBG("context %p", context);
106
107         fd = g_io_channel_unix_get_fd(channel);
108
109         polkit_context_io_func(context, fd);
110
111         return TRUE;
112 }
113
114 static int add_watch(PolKitContext *context, int fd)
115 {
116         GIOChannel *channel;
117         guint id = 0;
118
119         DBG("context %p", context);
120
121         channel = g_io_channel_unix_new(fd);
122         if (channel == NULL)
123                 return 0;
124
125         id = g_io_add_watch(channel, G_IO_IN, watch_event, context);
126
127         g_io_channel_unref(channel);
128
129         return id;
130 }
131
132 static void remove_watch(PolKitContext *context, int id)
133 {
134         DBG("context %p", context);
135
136         g_source_remove(id);
137 }
138
139 static int polkit_init(void)
140 {
141         int err;
142
143         connection = connman_dbus_get_connection();
144         if (connection == NULL)
145                 return -EIO;
146
147         polkit_context = polkit_context_new();
148
149         polkit_context_set_io_watch_functions(polkit_context,
150                                                 add_watch, remove_watch);
151
152         if (polkit_context_init(polkit_context, NULL) == FALSE) {
153                 connman_error("Can't initialize PolicyKit");
154                 polkit_context_unref(polkit_context);
155                 dbus_connection_unref(connection);
156                 return -EIO;
157         }
158
159         err = connman_security_register(&polkit_security);
160         if (err < 0) {
161                 polkit_context_unref(polkit_context);
162                 dbus_connection_unref(connection);
163                 return err;
164         }
165
166         return 0;
167 }
168
169 static void polkit_exit(void)
170 {
171         connman_security_unregister(&polkit_security);
172
173         polkit_context_unref(polkit_context);
174
175         dbus_connection_unref(connection);
176 }
177
178 CONNMAN_PLUGIN_DEFINE(polkit, "PolicyKit authorization plugin", VERSION,
179                 CONNMAN_PLUGIN_PRIORITY_DEFAULT, polkit_init, polkit_exit)