neard: move recipe and patches to the proper dir
[scm/bb/meta-tizen.git] / meta-tizen-adaptation / meta / recipes-connectivity / connman / connman / 0027-multi-user-Add-multi-user-support-in-service.patch
1 From 44a0a44c579df0192ec33c291b2efdfabfe5c7eb Mon Sep 17 00:00:00 2001
2 From: Zhang zhengguang <zhengguang.zhang@intel.com>
3 Date: Sat, 11 Oct 2014 15:08:18 +0800
4 Subject: [PATCH 27/32] multi-user: Add multi-user support in service
5
6 Use cases:
7
8 Given 2 users: UserA and UserB
9
10 1. If UserA is connected to a wifi service, then UserB is not allowed
11 to connect wifi service, and not allowed to disconnect the service
12 UserA connected.
13
14 2. If UserA is connected to a wifi service, then UserB is allowed to
15 use the same connection, but he is not allowed to modify the connection.
16
17 3. If UserA is connected to a wifi service with security wep/wpa/psk,
18 then UserA disconnects it, when UserB tries to connect the same wifi
19 service, it must input passphrase to connect it.
20
21 Change-Id: Id686ebd7d1f3490875a9d8f877219bd004907227
22 ---
23  src/connman.h |   3 ++
24  src/service.c | 157 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
25  2 files changed, 159 insertions(+), 1 deletion(-)
26
27 diff --git a/src/connman.h b/src/connman.h
28 index 4d78eab..386e8c8 100644
29 --- a/src/connman.h
30 +++ b/src/connman.h
31 @@ -791,6 +791,9 @@ void __connman_service_notify(struct connman_service *service,
32                         unsigned int rx_error, unsigned int tx_error,
33                         unsigned int rx_dropped, unsigned int tx_dropped);
34  
35 +bool __connman_service_is_user_allowed(enum connman_service_type type,
36 +                                       uid_t uid);
37 +
38  int __connman_service_counter_register(const char *counter);
39  void __connman_service_counter_unregister(const char *counter);
40  
41 diff --git a/src/service.c b/src/service.c
42 index 99bb35d..a1124ae 100644
43 --- a/src/service.c
44 +++ b/src/service.c
45 @@ -39,6 +39,9 @@
46  
47  #define CONNECT_TIMEOUT                120
48  
49 +#define USER_ROOT              0
50 +#define USER_NONE              (uid_t)-1
51 +
52  #if defined TIZEN_EXT
53  #define WIFI_BSSID_STR_LEN     18
54  #endif
55 @@ -67,6 +70,11 @@ struct connman_stats_counter {
56         struct connman_stats stats_roaming;
57  };
58  
59 +struct connman_service_user {
60 +       uid_t favorite_user;
61 +       uid_t current_user;
62 +};
63 +
64  struct connman_service {
65         int refcount;
66         char *identifier;
67 @@ -89,6 +97,8 @@ struct connman_service {
68         char *name;
69         char *passphrase;
70         bool roaming;
71 +       bool request_passphrase_input;
72 +       struct connman_service_user user;
73         struct connman_ipconfig *ipconfig_ipv4;
74         struct connman_ipconfig *ipconfig_ipv6;
75         struct connman_network *network;
76 @@ -351,6 +361,24 @@ static enum connman_service_proxy_method string2proxymethod(const char *method)
77                 return CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN;
78  }
79  
80 +static bool
81 +connman_service_is_user_allowed(struct connman_service *service, uid_t uid)
82 +{
83 +       uid_t favorite_user = service->user.favorite_user;
84 +       uid_t current_user = uid;
85 +
86 +       DBG("Service favorite UID: %d, current UID: %d", favorite_user, current_user);
87 +       if (favorite_user == USER_NONE || current_user == USER_ROOT)
88 +               return true;
89 +
90 +       if (favorite_user != current_user || current_user == USER_NONE) {
91 +               DBG("Current user is not a favorite user to this service!");
92 +               return false;
93 +       }
94 +
95 +       return true;
96 +}
97 +
98  int __connman_service_load_modifiable(struct connman_service *service)
99  {
100         GKeyFile *keyfile;
101 @@ -574,6 +602,8 @@ static int service_load(struct connman_service *service)
102         service->hidden_service = g_key_file_get_boolean(keyfile,
103                                         service->identifier, "Hidden", NULL);
104  
105 +       service->user.favorite_user = g_key_file_get_integer(keyfile,
106 +                                       service->identifier, "UID", NULL);
107  done:
108         g_key_file_free(keyfile);
109  
110 @@ -619,6 +649,9 @@ static int service_save(struct connman_service *service)
111                         const unsigned char *ssid;
112                         unsigned int ssid_len = 0;
113  
114 +                       g_key_file_set_integer(keyfile, service->identifier,
115 +                               "UID", service->user.favorite_user);
116 +
117                         ssid = connman_network_get_blob(service->network,
118                                                         "WiFi.SSID", &ssid_len);
119  
120 @@ -3236,6 +3269,21 @@ static DBusMessage *set_property(DBusConnection *conn,
121         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
122                 return __connman_error_invalid_arguments(msg);
123  
124 +       if (service->type == CONNMAN_SERVICE_TYPE_WIFI && is_connected(service)) {
125 +               uid_t uid;
126 +               if (connman_dbus_get_connection_unix_user_sync(conn,
127 +                                               dbus_message_get_sender(msg),
128 +                                               &uid) < 0) {
129 +                       DBG("Can not get unix user id!");
130 +                       return __connman_error_permission_denied(msg);
131 +               }
132 +
133 +               if (!connman_service_is_user_allowed(service, uid)) {
134 +                       DBG("Not allow this user to operate this wifi service now!");
135 +                       return __connman_error_permission_denied(msg);
136 +               }
137 +       }
138 +
139         dbus_message_iter_get_basic(&iter, &name);
140         dbus_message_iter_next(&iter);
141  
142 @@ -3997,6 +4045,26 @@ static DBusMessage *connect_service(DBusConnection *conn,
143         if (service->pending)
144                 return __connman_error_in_progress(msg);
145  
146 +       if (service->type == CONNMAN_SERVICE_TYPE_WIFI) {
147 +               uid_t uid;
148 +               if (connman_dbus_get_connection_unix_user_sync(conn,
149 +                                               dbus_message_get_sender(msg),
150 +                                               &uid) < 0) {
151 +                       DBG("Can not get unix user id!");
152 +                       return __connman_error_permission_denied(msg);
153 +               }
154 +
155 +               if (!__connman_service_is_user_allowed(CONNMAN_SERVICE_TYPE_WIFI, uid)) {
156 +                       DBG("Not allow this user to connect this wifi service now!");
157 +                       return __connman_error_permission_denied(msg);
158 +               }
159 +
160 +               if (uid != USER_ROOT && uid != service->user.favorite_user)
161 +                       service->request_passphrase_input = true;
162 +
163 +               service->user.current_user = uid;
164 +       }
165 +
166         index = __connman_service_get_index(service);
167  
168         for (list = service_list; list; list = list->next) {
169 @@ -4048,6 +4116,21 @@ static DBusMessage *disconnect_service(DBusConnection *conn,
170  
171         DBG("service %p", service);
172  
173 +       if (service->type == CONNMAN_SERVICE_TYPE_WIFI) {
174 +               uid_t uid;
175 +               if (connman_dbus_get_connection_unix_user_sync(conn,
176 +                                               dbus_message_get_sender(msg),
177 +                                               &uid) < 0) {
178 +                       DBG("Can not get unix user id!");
179 +                       return __connman_error_permission_denied(msg);
180 +               }
181 +
182 +               if (!connman_service_is_user_allowed(service, uid)) {
183 +                       DBG("Not allow this user to disconnect this wifi service now!");
184 +                       return __connman_error_permission_denied(msg);
185 +               }
186 +       }
187 +
188         service->ignore = true;
189  
190         err = __connman_service_disconnect(service);
191 @@ -4103,6 +4186,21 @@ static DBusMessage *remove_service(DBusConnection *conn,
192  
193         DBG("service %p", service);
194  
195 +       if (service->type == CONNMAN_SERVICE_TYPE_WIFI) {
196 +               uid_t uid;
197 +               if (connman_dbus_get_connection_unix_user_sync(conn,
198 +                                               dbus_message_get_sender(msg),
199 +                                               &uid) < 0) {
200 +                       DBG("Can not get unix user id!");
201 +                       return __connman_error_permission_denied(msg);
202 +               }
203 +
204 +               if (!connman_service_is_user_allowed(service, uid)) {
205 +                       DBG("Not allow this user to remove this wifi service now!");
206 +                       return __connman_error_permission_denied(msg);
207 +               }
208 +       }
209 +
210         if (!__connman_service_remove(service))
211                 return __connman_error_not_supported(msg);
212  
213 @@ -4583,6 +4681,11 @@ static void service_initialize(struct connman_service *service)
214  
215         service->ignore = false;
216  
217 +       service->user.favorite_user = USER_NONE;
218 +       service->user.current_user = USER_NONE;
219 +
220 +       service->request_passphrase_input = false;
221 +
222         service->connect_reason = CONNMAN_SERVICE_CONNECT_REASON_NONE;
223  
224         service->order = 0;
225 @@ -4809,6 +4912,40 @@ char *connman_service_get_interface(struct connman_service *service)
226  }
227  
228  /**
229 + * __connman_service_is_user_allowed:
230 + * @type: service type
231 + * @uid: user id
232 + *
233 + * Check a user is allowed to operate a type of service
234 + */
235 +bool __connman_service_is_user_allowed(enum connman_service_type type,
236 +                                       uid_t uid)
237 +{
238 +       GList *list;
239 +       uid_t owner_user = USER_NONE;
240 +
241 +       for (list = service_list; list; list = list->next) {
242 +               struct connman_service *service = list->data;
243 +
244 +               if (service->type != type)
245 +                       continue;
246 +
247 +               if (is_connected(service)) {
248 +                       owner_user = service->user.favorite_user;
249 +                       break;
250 +               }
251 +       }
252 +
253 +       if (uid == USER_NONE ||
254 +                       (uid != USER_ROOT &&
255 +                       owner_user != USER_NONE &&
256 +                       owner_user != uid))
257 +               return false;
258 +
259 +       return true;
260 +}
261 +
262 +/**
263   * connman_service_get_network:
264   * @service: service structure
265   *
266 @@ -5487,6 +5624,20 @@ static int service_indicate_state(struct connman_service *service)
267                 default_changed();
268         }
269  
270 +       if (service->type == CONNMAN_SERVICE_TYPE_WIFI &&
271 +               service->connect_reason == CONNMAN_SERVICE_CONNECT_REASON_USER &&
272 +               (new_state == CONNMAN_SERVICE_STATE_READY ||
273 +               new_state == CONNMAN_SERVICE_STATE_ONLINE)) {
274 +               if (service->user.favorite_user != service->user.current_user) {
275 +                       DBG("Now set service favorite user id from %d to %d",
276 +                       service->user.favorite_user, service->user.current_user);
277 +
278 +                       service->user.favorite_user = service->user.current_user;
279 +
280 +                       service_save(service);
281 +               }
282 +       }
283 +
284         return 0;
285  }
286  
287 @@ -5898,7 +6049,11 @@ static int service_connect(struct connman_service *service)
288                 case CONNMAN_SERVICE_SECURITY_PSK:
289                 case CONNMAN_SERVICE_SECURITY_WPA:
290                 case CONNMAN_SERVICE_SECURITY_RSN:
291 -                       if (!service->passphrase) {
292 +                       if (service->request_passphrase_input) {
293 +                               DBG("Now try to connect other user's favorite service");
294 +                               service->request_passphrase_input = false;
295 +                               return -ENOKEY;
296 +                       } else if (!service->passphrase) {
297                                 if (!service->network)
298                                         return -EOPNOTSUPP;
299  
300 -- 
301 1.8.1.4
302