Remove WPA2 and WPA3 service together
[platform/upstream/connman.git] / src / dbus.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2012  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 <string.h>
27 #include <errno.h>
28 #include <gdbus.h>
29
30 #include "connman.h"
31
32 dbus_bool_t connman_dbus_validate_ident(const char *ident)
33 {
34         unsigned int i;
35
36         if (!ident)
37                 return FALSE;
38
39         for (i = 0; i < strlen(ident); i++) {
40                 if (ident[i] >= '0' && ident[i] <= '9')
41                         continue;
42                 if (ident[i] >= 'a' && ident[i] <= 'z')
43                         continue;
44                 if (ident[i] >= 'A' && ident[i] <= 'Z')
45                         continue;
46                 return FALSE;
47         }
48
49         return TRUE;
50 }
51
52 char *connman_dbus_encode_string(const char *value)
53 {
54         GString *str;
55         unsigned int i, size;
56
57         if (!value)
58                 return NULL;
59
60         size = strlen(value);
61
62         str = g_string_new(NULL);
63         if (!str)
64                 return NULL;
65
66         for (i = 0; i < size; i++) {
67                 const char tmp = value[i];
68                 if ((tmp < '0' || tmp > '9') && (tmp < 'A' || tmp > 'Z') &&
69                                                 (tmp < 'a' || tmp > 'z'))
70                         g_string_append_printf(str, "_%02x", tmp);
71                 else
72                         str = g_string_append_c(str, tmp);
73         }
74
75         return g_string_free(str, FALSE);
76 }
77
78 void connman_dbus_property_append_basic(DBusMessageIter *iter,
79                                         const char *key, int type, void *val)
80 {
81         DBusMessageIter value;
82         const char *signature;
83
84         dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &key);
85
86         switch (type) {
87         case DBUS_TYPE_BOOLEAN:
88                 signature = DBUS_TYPE_BOOLEAN_AS_STRING;
89                 break;
90         case DBUS_TYPE_STRING:
91                 signature = DBUS_TYPE_STRING_AS_STRING;
92                 break;
93         case DBUS_TYPE_BYTE:
94                 signature = DBUS_TYPE_BYTE_AS_STRING;
95                 break;
96         case DBUS_TYPE_UINT16:
97                 signature = DBUS_TYPE_UINT16_AS_STRING;
98                 break;
99         case DBUS_TYPE_INT16:
100                 signature = DBUS_TYPE_INT16_AS_STRING;
101                 break;
102         case DBUS_TYPE_UINT32:
103                 signature = DBUS_TYPE_UINT32_AS_STRING;
104                 break;
105         case DBUS_TYPE_INT32:
106                 signature = DBUS_TYPE_INT32_AS_STRING;
107                 break;
108         case DBUS_TYPE_UINT64:
109                 signature = DBUS_TYPE_UINT64_AS_STRING;
110                 break;
111         case DBUS_TYPE_INT64:
112                 signature = DBUS_TYPE_INT64_AS_STRING;
113                 break;
114         case DBUS_TYPE_OBJECT_PATH:
115                 signature = DBUS_TYPE_OBJECT_PATH_AS_STRING;
116                 break;
117         default:
118                 signature = DBUS_TYPE_VARIANT_AS_STRING;
119                 break;
120         }
121
122         dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
123                                                         signature, &value);
124         dbus_message_iter_append_basic(&value, type, val);
125         dbus_message_iter_close_container(iter, &value);
126 }
127
128 void connman_dbus_property_append_dict(DBusMessageIter *iter, const char *key,
129                         connman_dbus_append_cb_t function, void *user_data)
130 {
131         DBusMessageIter value, dict;
132
133         dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &key);
134
135         dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
136                         DBUS_TYPE_ARRAY_AS_STRING
137                         DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
138                         DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
139                         DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &value);
140
141         connman_dbus_dict_open(&value, &dict);
142         if (function)
143                 function(&dict, user_data);
144         connman_dbus_dict_close(&value, &dict);
145
146         dbus_message_iter_close_container(iter, &value);
147 }
148
149 void connman_dbus_property_append_fixed_array(DBusMessageIter *iter,
150                                 const char *key, int type, void *val, int len)
151 {
152         DBusMessageIter value, array;
153         const char *variant_sig, *array_sig;
154
155         switch (type) {
156         case DBUS_TYPE_BYTE:
157                 variant_sig = DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING;
158                 array_sig = DBUS_TYPE_BYTE_AS_STRING;
159                 break;
160         default:
161                 return;
162         }
163
164         dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &key);
165
166         dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
167                                                         variant_sig, &value);
168
169         dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
170                                                         array_sig, &array);
171         dbus_message_iter_append_fixed_array(&array, type, val, len);
172         dbus_message_iter_close_container(&value, &array);
173
174         dbus_message_iter_close_container(iter, &value);
175 }
176
177 void connman_dbus_property_append_array(DBusMessageIter *iter,
178                                                 const char *key, int type,
179                         connman_dbus_append_cb_t function, void *user_data)
180 {
181         DBusMessageIter value, array;
182         const char *variant_sig, *array_sig;
183
184         switch (type) {
185         case DBUS_TYPE_STRING:
186                 variant_sig = DBUS_TYPE_ARRAY_AS_STRING
187                                 DBUS_TYPE_STRING_AS_STRING;
188                 array_sig = DBUS_TYPE_STRING_AS_STRING;
189                 break;
190         case DBUS_TYPE_OBJECT_PATH:
191                 variant_sig = DBUS_TYPE_ARRAY_AS_STRING
192                                 DBUS_TYPE_OBJECT_PATH_AS_STRING;
193                 array_sig = DBUS_TYPE_OBJECT_PATH_AS_STRING;
194                 break;
195         case DBUS_TYPE_DICT_ENTRY:
196                 variant_sig = DBUS_TYPE_ARRAY_AS_STRING
197                                 DBUS_STRUCT_BEGIN_CHAR_AS_STRING
198                                 DBUS_TYPE_ARRAY_AS_STRING
199                                         DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
200                                                 DBUS_TYPE_STRING_AS_STRING
201                                                 DBUS_TYPE_VARIANT_AS_STRING
202                                         DBUS_DICT_ENTRY_END_CHAR_AS_STRING
203                                 DBUS_STRUCT_END_CHAR_AS_STRING;
204                 array_sig = DBUS_STRUCT_BEGIN_CHAR_AS_STRING
205                                 DBUS_TYPE_ARRAY_AS_STRING
206                                         DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
207                                                 DBUS_TYPE_STRING_AS_STRING
208                                                 DBUS_TYPE_VARIANT_AS_STRING
209                                         DBUS_DICT_ENTRY_END_CHAR_AS_STRING
210                                 DBUS_STRUCT_END_CHAR_AS_STRING;
211                 break;
212         default:
213                 return;
214         }
215
216         dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &key);
217
218         dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
219                                                         variant_sig, &value);
220
221         dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
222                                                         array_sig, &array);
223         if (function)
224                 function(&array, user_data);
225         dbus_message_iter_close_container(&value, &array);
226
227         dbus_message_iter_close_container(iter, &value);
228 }
229
230 static DBusConnection *connection = NULL;
231
232 dbus_bool_t connman_dbus_property_changed_basic(const char *path,
233                                 const char *interface, const char *key,
234                                                         int type, void *val)
235 {
236         DBusMessage *signal;
237         DBusMessageIter iter;
238
239         if (!path)
240                 return FALSE;
241
242         signal = dbus_message_new_signal(path, interface, "PropertyChanged");
243         if (!signal)
244                 return FALSE;
245
246         dbus_message_iter_init_append(signal, &iter);
247         connman_dbus_property_append_basic(&iter, key, type, val);
248
249         return g_dbus_send_message(connection, signal);
250 }
251
252 dbus_bool_t connman_dbus_property_changed_dict(const char *path,
253                                 const char *interface, const char *key,
254                         connman_dbus_append_cb_t function, void *user_data)
255 {
256         DBusMessage *signal;
257         DBusMessageIter iter;
258
259         if (!path)
260                 return FALSE;
261
262         signal = dbus_message_new_signal(path, interface, "PropertyChanged");
263         if (!signal)
264                 return FALSE;
265
266         dbus_message_iter_init_append(signal, &iter);
267         connman_dbus_property_append_dict(&iter, key, function, user_data);
268
269         return g_dbus_send_message(connection, signal);
270 }
271
272 dbus_bool_t connman_dbus_property_changed_array(const char *path,
273                         const char *interface, const char *key, int type,
274                         connman_dbus_append_cb_t function, void *user_data)
275 {
276         DBusMessage *signal;
277         DBusMessageIter iter;
278
279         if (!path)
280                 return FALSE;
281
282         signal = dbus_message_new_signal(path, interface, "PropertyChanged");
283         if (!signal)
284                 return FALSE;
285
286         dbus_message_iter_init_append(signal, &iter);
287         connman_dbus_property_append_array(&iter, key, type,
288                                                 function, user_data);
289
290         return g_dbus_send_message(connection, signal);
291 }
292
293 dbus_bool_t connman_dbus_setting_changed_basic(const char *owner,
294                                 const char *path, const char *key,
295                                 int type, void *val)
296 {
297         DBusMessage *msg;
298         DBusMessageIter array, dict;
299
300         if (!owner || !path)
301                 return FALSE;
302
303         msg = dbus_message_new_method_call(owner, path,
304                                                 CONNMAN_NOTIFICATION_INTERFACE,
305                                                 "Update");
306         if (!msg)
307                 return FALSE;
308
309         dbus_message_iter_init_append(msg, &array);
310         connman_dbus_dict_open(&array, &dict);
311
312         connman_dbus_dict_append_basic(&dict, key, type, val);
313
314         connman_dbus_dict_close(&array, &dict);
315
316         return g_dbus_send_message(connection, msg);
317 }
318
319 dbus_bool_t connman_dbus_setting_changed_dict(const char *owner,
320                                 const char *path, const char *key,
321                                 connman_dbus_append_cb_t function,
322                                 void *user_data)
323 {
324         DBusMessage *msg;
325         DBusMessageIter array, dict;
326
327         if (!owner || !path)
328                 return FALSE;
329
330         msg = dbus_message_new_method_call(owner, path,
331                                                 CONNMAN_NOTIFICATION_INTERFACE,
332                                                 "Update");
333         if (!msg)
334                 return FALSE;
335
336         dbus_message_iter_init_append(msg, &array);
337         connman_dbus_dict_open(&array, &dict);
338
339         connman_dbus_dict_append_dict(&dict, key, function, user_data);
340
341         connman_dbus_dict_close(&array, &dict);
342
343         return g_dbus_send_message(connection, msg);
344 }
345
346 dbus_bool_t connman_dbus_setting_changed_array(const char *owner,
347                                 const char *path, const char *key, int type,
348                                 connman_dbus_append_cb_t function,
349                                 void *user_data)
350 {
351         DBusMessage *msg;
352         DBusMessageIter array, dict;
353
354         if (!owner || !path)
355                 return FALSE;
356
357         msg = dbus_message_new_method_call(owner, path,
358                                                 CONNMAN_NOTIFICATION_INTERFACE,
359                                                 "Update");
360         if (!msg)
361                 return FALSE;
362
363         dbus_message_iter_init_append(msg, &array);
364         connman_dbus_dict_open(&array, &dict);
365
366         connman_dbus_dict_append_array(&dict, key, type, function, user_data);
367
368         connman_dbus_dict_close(&array, &dict);
369
370         return g_dbus_send_message(connection, msg);
371 }
372
373 dbus_bool_t __connman_dbus_append_objpath_dict_array(DBusMessage *msg,
374                 connman_dbus_append_cb_t function, void *user_data)
375 {
376         DBusMessageIter iter, array;
377
378         if (!msg || !function)
379                 return FALSE;
380
381         dbus_message_iter_init_append(msg, &iter);
382         dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
383                         DBUS_STRUCT_BEGIN_CHAR_AS_STRING
384                         DBUS_TYPE_OBJECT_PATH_AS_STRING
385                         DBUS_TYPE_ARRAY_AS_STRING
386                                 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
387                                         DBUS_TYPE_STRING_AS_STRING
388                                         DBUS_TYPE_VARIANT_AS_STRING
389                                 DBUS_DICT_ENTRY_END_CHAR_AS_STRING
390                         DBUS_STRUCT_END_CHAR_AS_STRING, &array);
391
392         function(&array, user_data);
393
394         dbus_message_iter_close_container(&iter, &array);
395
396         return TRUE;
397 }
398
399 dbus_bool_t __connman_dbus_append_objpath_array(DBusMessage *msg,
400                         connman_dbus_append_cb_t function, void *user_data)
401 {
402         DBusMessageIter iter, array;
403
404         if (!msg || !function)
405                 return FALSE;
406
407         dbus_message_iter_init_append(msg, &iter);
408         dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
409                                 DBUS_TYPE_OBJECT_PATH_AS_STRING, &array);
410
411         function(&array, user_data);
412
413         dbus_message_iter_close_container(&iter, &array);
414
415         return TRUE;
416 }
417
418 struct callback_data {
419         void *cb;
420         void *user_data;
421 };
422
423 static void get_connection_unix_user_reply(DBusPendingCall *call,
424                                                 void *user_data)
425 {
426         struct callback_data *data = user_data;
427         connman_dbus_get_connection_unix_user_cb_t cb = data->cb;
428         DBusMessageIter iter;
429         DBusMessage *reply;
430         int err = 0;
431         unsigned int uid = 0;
432
433         reply = dbus_pending_call_steal_reply(call);
434
435         if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
436                 DBG("Failed to retrieve UID");
437                 err = -EIO;
438                 goto done;
439         }
440
441         if (!dbus_message_has_signature(reply, "u")) {
442                 DBG("Message signature is wrong");
443                 err = -EINVAL;
444                 goto done;
445         }
446
447         dbus_message_iter_init(reply, &iter);
448         dbus_message_iter_get_basic(&iter, &uid);
449
450 done:
451         (*cb)(uid, data->user_data, err);
452
453         dbus_message_unref(reply);
454
455         dbus_pending_call_unref(call);
456 }
457
458 int connman_dbus_get_connection_unix_user(DBusConnection *connection,
459                                 const char *bus_name,
460                                 connman_dbus_get_connection_unix_user_cb_t func,
461                                 void *user_data)
462 {
463         struct callback_data *data;
464         DBusPendingCall *call;
465         DBusMessage *msg = NULL;
466         int err;
467
468         data = g_try_new0(struct callback_data, 1);
469         if (!data) {
470                 DBG("Can't allocate data structure");
471                 return -ENOMEM;
472         }
473
474         msg = dbus_message_new_method_call(DBUS_SERVICE_DBUS, DBUS_PATH_DBUS,
475                                         DBUS_INTERFACE_DBUS,
476                                         "GetConnectionUnixUser");
477         if (!msg) {
478                 DBG("Can't allocate new message");
479                 err = -ENOMEM;
480                 goto err;
481         }
482
483         dbus_message_append_args(msg, DBUS_TYPE_STRING, &bus_name,
484                                         DBUS_TYPE_INVALID);
485
486         if (!dbus_connection_send_with_reply(connection, msg, &call, -1)) {
487                 DBG("Failed to execute method call");
488                 err = -EINVAL;
489                 goto err;
490         }
491
492         if (!call) {
493                 DBG("D-Bus connection not available");
494                 err = -EINVAL;
495                 goto err;
496         }
497
498         data->cb = func;
499         data->user_data = user_data;
500
501         dbus_pending_call_set_notify(call, get_connection_unix_user_reply,
502                                                         data, g_free);
503
504         dbus_message_unref(msg);
505
506         return 0;
507
508 err:
509         dbus_message_unref(msg);
510         g_free(data);
511
512         return err;
513 }
514
515 static unsigned char *parse_context(DBusMessage *msg)
516 {
517         DBusMessageIter iter, array;
518         unsigned char *ctx, *p;
519         int size = 0;
520
521         dbus_message_iter_init(msg, &iter);
522         dbus_message_iter_recurse(&iter, &array);
523         while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_BYTE) {
524                 size++;
525
526                 dbus_message_iter_next(&array);
527         }
528
529         if (size == 0)
530                 return NULL;
531
532         ctx = g_try_malloc0(size + 1);
533         if (!ctx)
534                 return NULL;
535
536         p = ctx;
537
538         dbus_message_iter_init(msg, &iter);
539         dbus_message_iter_recurse(&iter, &array);
540         while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_BYTE) {
541                 dbus_message_iter_get_basic(&array, p);
542
543                 p++;
544                 dbus_message_iter_next(&array);
545         }
546
547         return ctx;
548 }
549
550 static void selinux_get_context_reply(DBusPendingCall *call, void *user_data)
551 {
552         struct callback_data *data = user_data;
553         connman_dbus_get_context_cb_t cb = data->cb;
554         DBusMessage *reply;
555         unsigned char *context = NULL;
556         int err = 0;
557
558         reply = dbus_pending_call_steal_reply(call);
559
560         if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
561                 DBG("Failed to retrieve SELinux context");
562                 err = -EIO;
563                 goto done;
564         }
565
566         if (!dbus_message_has_signature(reply, "ay")) {
567                 DBG("Message signature is wrong");
568                 err = -EINVAL;
569                 goto done;
570         }
571
572         context = parse_context(reply);
573
574 done:
575         (*cb)(context, data->user_data, err);
576
577         g_free(context);
578
579         dbus_message_unref(reply);
580
581         dbus_pending_call_unref(call);
582 }
583
584 int connman_dbus_get_selinux_context(DBusConnection *connection,
585                                 const char *service,
586                                 connman_dbus_get_context_cb_t func,
587                                 void *user_data)
588 {
589         struct callback_data *data;
590         DBusPendingCall *call;
591         DBusMessage *msg = NULL;
592         int err;
593
594         if (!func)
595                 return -EINVAL;
596
597         data = g_try_new0(struct callback_data, 1);
598         if (!data) {
599                 DBG("Can't allocate data structure");
600                 return -ENOMEM;
601         }
602
603         msg = dbus_message_new_method_call(DBUS_SERVICE_DBUS, DBUS_PATH_DBUS,
604                                         DBUS_INTERFACE_DBUS,
605                                         "GetConnectionSELinuxSecurityContext");
606         if (!msg) {
607                 DBG("Can't allocate new message");
608                 err = -ENOMEM;
609                 goto err;
610         }
611
612         dbus_message_append_args(msg, DBUS_TYPE_STRING, &service,
613                                         DBUS_TYPE_INVALID);
614
615         if (!dbus_connection_send_with_reply(connection, msg, &call, -1)) {
616                 DBG("Failed to execute method call");
617                 err = -EINVAL;
618                 goto err;
619         }
620
621         if (!call) {
622                 DBG("D-Bus connection not available");
623                 err = -EINVAL;
624                 goto err;
625         }
626
627         data->cb = func;
628         data->user_data = user_data;
629
630         dbus_pending_call_set_notify(call, selinux_get_context_reply,
631                                                         data, g_free);
632
633         dbus_message_unref(msg);
634
635         return 0;
636
637 err:
638         dbus_message_unref(msg);
639         g_free(data);
640
641         return err;
642 }
643
644 void connman_dbus_reply_pending(DBusMessage *pending,
645                                         int error, const char *path)
646 {
647         if (pending) {
648                 if (error > 0) {
649                         DBusMessage *reply;
650
651                         reply = __connman_error_failed(pending, error);
652                         if (reply)
653                                 g_dbus_send_message(connection, reply);
654                 } else {
655                         const char *sender;
656
657                         sender = dbus_message_get_interface(pending);
658                         if (!path)
659                                 path = dbus_message_get_path(pending);
660
661                         DBG("sender %s path %s", sender, path);
662
663                         if (g_strcmp0(sender, CONNMAN_MANAGER_INTERFACE) == 0)
664                                 g_dbus_send_reply(connection, pending,
665                                         DBUS_TYPE_OBJECT_PATH, &path,
666                                                         DBUS_TYPE_INVALID);
667                         else
668                                 g_dbus_send_reply(connection, pending,
669                                                         DBUS_TYPE_INVALID);
670                 }
671
672                 dbus_message_unref(pending);
673         }
674 }
675
676 DBusConnection *connman_dbus_get_connection(void)
677 {
678         if (!connection)
679                 return NULL;
680
681         return dbus_connection_ref(connection);
682 }
683
684 int __connman_dbus_init(DBusConnection *conn)
685 {
686         DBG("");
687
688         connection = conn;
689
690         return g_dbus_attach_object_manager(conn);
691 }
692
693 void __connman_dbus_cleanup(void)
694 {
695         DBG("");
696
697         connection = NULL;
698 }