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
8 Given 2 users: UserA and UserB
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
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.
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.
21 Change-Id: Id686ebd7d1f3490875a9d8f877219bd004907227
24 src/service.c | 157 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
25 2 files changed, 159 insertions(+), 1 deletion(-)
27 diff --git a/src/connman.h b/src/connman.h
28 index 4d78eab..386e8c8 100644
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);
35 +bool __connman_service_is_user_allowed(enum connman_service_type type,
38 int __connman_service_counter_register(const char *counter);
39 void __connman_service_counter_unregister(const char *counter);
41 diff --git a/src/service.c b/src/service.c
42 index 99bb35d..a1124ae 100644
47 #define CONNECT_TIMEOUT 120
50 +#define USER_NONE (uid_t)-1
53 #define WIFI_BSSID_STR_LEN 18
55 @@ -67,6 +70,11 @@ struct connman_stats_counter {
56 struct connman_stats stats_roaming;
59 +struct connman_service_user {
60 + uid_t favorite_user;
64 struct connman_service {
67 @@ -89,6 +97,8 @@ struct connman_service {
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;
81 +connman_service_is_user_allowed(struct connman_service *service, uid_t uid)
83 + uid_t favorite_user = service->user.favorite_user;
84 + uid_t current_user = uid;
86 + DBG("Service favorite UID: %d, current UID: %d", favorite_user, current_user);
87 + if (favorite_user == USER_NONE || current_user == USER_ROOT)
90 + if (favorite_user != current_user || current_user == USER_NONE) {
91 + DBG("Current user is not a favorite user to this service!");
98 int __connman_service_load_modifiable(struct connman_service *service)
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);
105 + service->user.favorite_user = g_key_file_get_integer(keyfile,
106 + service->identifier, "UID", NULL);
108 g_key_file_free(keyfile);
110 @@ -619,6 +649,9 @@ static int service_save(struct connman_service *service)
111 const unsigned char *ssid;
112 unsigned int ssid_len = 0;
114 + g_key_file_set_integer(keyfile, service->identifier,
115 + "UID", service->user.favorite_user);
117 ssid = connman_network_get_blob(service->network,
118 "WiFi.SSID", &ssid_len);
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);
124 + if (service->type == CONNMAN_SERVICE_TYPE_WIFI && is_connected(service)) {
126 + if (connman_dbus_get_connection_unix_user_sync(conn,
127 + dbus_message_get_sender(msg),
129 + DBG("Can not get unix user id!");
130 + return __connman_error_permission_denied(msg);
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);
139 dbus_message_iter_get_basic(&iter, &name);
140 dbus_message_iter_next(&iter);
142 @@ -3997,6 +4045,26 @@ static DBusMessage *connect_service(DBusConnection *conn,
143 if (service->pending)
144 return __connman_error_in_progress(msg);
146 + if (service->type == CONNMAN_SERVICE_TYPE_WIFI) {
148 + if (connman_dbus_get_connection_unix_user_sync(conn,
149 + dbus_message_get_sender(msg),
151 + DBG("Can not get unix user id!");
152 + return __connman_error_permission_denied(msg);
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);
160 + if (uid != USER_ROOT && uid != service->user.favorite_user)
161 + service->request_passphrase_input = true;
163 + service->user.current_user = uid;
166 index = __connman_service_get_index(service);
168 for (list = service_list; list; list = list->next) {
169 @@ -4048,6 +4116,21 @@ static DBusMessage *disconnect_service(DBusConnection *conn,
171 DBG("service %p", service);
173 + if (service->type == CONNMAN_SERVICE_TYPE_WIFI) {
175 + if (connman_dbus_get_connection_unix_user_sync(conn,
176 + dbus_message_get_sender(msg),
178 + DBG("Can not get unix user id!");
179 + return __connman_error_permission_denied(msg);
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);
188 service->ignore = true;
190 err = __connman_service_disconnect(service);
191 @@ -4103,6 +4186,21 @@ static DBusMessage *remove_service(DBusConnection *conn,
193 DBG("service %p", service);
195 + if (service->type == CONNMAN_SERVICE_TYPE_WIFI) {
197 + if (connman_dbus_get_connection_unix_user_sync(conn,
198 + dbus_message_get_sender(msg),
200 + DBG("Can not get unix user id!");
201 + return __connman_error_permission_denied(msg);
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);
210 if (!__connman_service_remove(service))
211 return __connman_error_not_supported(msg);
213 @@ -4583,6 +4681,11 @@ static void service_initialize(struct connman_service *service)
215 service->ignore = false;
217 + service->user.favorite_user = USER_NONE;
218 + service->user.current_user = USER_NONE;
220 + service->request_passphrase_input = false;
222 service->connect_reason = CONNMAN_SERVICE_CONNECT_REASON_NONE;
225 @@ -4809,6 +4912,40 @@ char *connman_service_get_interface(struct connman_service *service)
229 + * __connman_service_is_user_allowed:
230 + * @type: service type
233 + * Check a user is allowed to operate a type of service
235 +bool __connman_service_is_user_allowed(enum connman_service_type type,
239 + uid_t owner_user = USER_NONE;
241 + for (list = service_list; list; list = list->next) {
242 + struct connman_service *service = list->data;
244 + if (service->type != type)
247 + if (is_connected(service)) {
248 + owner_user = service->user.favorite_user;
253 + if (uid == USER_NONE ||
254 + (uid != USER_ROOT &&
255 + owner_user != USER_NONE &&
256 + owner_user != uid))
263 * connman_service_get_network:
264 * @service: service structure
266 @@ -5487,6 +5624,20 @@ static int service_indicate_state(struct connman_service *service)
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);
278 + service->user.favorite_user = service->user.current_user;
280 + service_save(service);
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;
296 + } else if (!service->passphrase) {
297 if (!service->network)