1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
2 *
3 * Copyright (C) 2018 Ludovico de Nittis <denittis@gnome.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20 #include "config.h"
21
22 #include <gio/gio.h>
23 #include <glib-object.h>
24 #include <glib/gi18n.h>
25 #include <libnotify/notify.h>
26 #include <locale.h>
27 #include <string.h>
28
29 #include <gdesktop-enums.h>
30
31 #include "gnome-settings-bus.h"
32 #include "gnome-settings-profile.h"
33 #include "gsd-enums.h"
34 #include "gsd-usb-protection-manager.h"
35
36 #define PRIVACY_SETTINGS "org.gnome.desktop.privacy"
37 #define USB_PROTECTION "usb-protection"
38 #define USB_PROTECTION_LEVEL "usb-protection-level"
39
40 #define DBUS_VERSION "1"
41
42 #define USBGUARD_DBUS_NAME "org.usbguard" DBUS_VERSION
43 #define USBGUARD_DBUS_PATH "/org/usbguard" DBUS_VERSION
44 #define USBGUARD_DBUS_INTERFACE "org.usbguard"
45 #define USBGUARD_DBUS_INTERFACE_VERSIONED USBGUARD_DBUS_INTERFACE DBUS_VERSION
46
47 #define USBGUARD_DBUS_PATH_POLICY USBGUARD_DBUS_PATH "/Policy"
48 #define USBGUARD_DBUS_INTERFACE_POLICY USBGUARD_DBUS_INTERFACE ".Policy" DBUS_VERSION
49
50 #define USBGUARD_DBUS_PATH_DEVICES USBGUARD_DBUS_PATH "/Devices"
51 #define USBGUARD_DBUS_INTERFACE_DEVICES USBGUARD_DBUS_INTERFACE ".Devices" DBUS_VERSION
52
53 #define APPLY_POLICY "apply-policy"
54 #define BLOCK "block"
55 #define REJECT "reject"
56
57 #define APPLY_DEVICE_POLICY "applyDevicePolicy"
58 #define LIST_DEVICES "listDevices"
59 #define LIST_RULES "listRules"
60 #define ALLOW "allow"
61 #define DEVICE_POLICY_CHANGED "DevicePolicyChanged"
62 #define DEVICE_PRESENCE_CHANGED "DevicePresenceChanged"
63 #define INSERTED_DEVICE_POLICY "InsertedDevicePolicy"
64 #define APPEND_RULE "appendRule"
65 #define ALLOW_ALL "allow id *:* label \"GNOME_SETTINGS_DAEMON_RULE\""
66 #define WITH_CONNECT_TYPE "with-connect-type"
67 #define WITH_INTERFACE "with-interface"
68 #define NAME "name"
69
70 struct _GsdUsbProtectionManager
71 {
72 GObject parent;
73 guint start_idle_id;
74 GDBusNodeInfo *introspection_data;
75 GSettings *settings;
76 guint name_id;
77 GDBusConnection *connection;
78 gboolean available;
79 GDBusProxy *usb_protection;
80 GDBusProxy *usb_protection_devices;
81 GDBusProxy *usb_protection_policy;
82 GCancellable *cancellable;
83 GsdScreenSaver *screensaver_proxy;
84 gboolean screensaver_active;
85 NotifyNotification *notification;
86 };
87
88 typedef enum {
89 EVENT_PRESENT,
90 EVENT_INSERT,
91 EVENT_UPDATE,
92 EVENT_REMOVE
93 } UsbGuardEvent;
94
95
96 typedef enum {
97 TARGET_ALLOW,
98 TARGET_BLOCK,
99 TARGET_REJECT
100 } UsbGuardTarget;
101
102 typedef enum {
103 POLICY_DEVICE_ID,
104 POLICY_TARGET_OLD,
105 /* This is the rule that has been applied */
106 POLICY_TARGET_NEW,
107 POLICY_DEV_RULE,
108 /* The ID of the rule that has been applied.
109 * uint32 - 1 is one of the implicit rules,
110 * e.g. ImplicitPolicyTarget or InsertedDevicePolicy.
111 */
112 POLICY_RULE_ID,
113 POLICY_ATTRIBUTES
114 } UsbGuardPolicyChanged;
115
116 typedef enum {
117 PRESENCE_DEVICE_ID,
118 PRESENCE_EVENT,
119 /* That does not reflect what USBGuard intends to do with the device :( */
120 PRESENCE_TARGET,
121 PRESENCE_DEV_RULE,
122 PRESENCE_ATTRIBUTES
123 } UsbGuardPresenceChanged;
124
125 static void gsd_usb_protection_manager_finalize (GObject *object);
126
127 G_DEFINE_TYPE (GsdUsbProtectionManager, gsd_usb_protection_manager, G_TYPE_OBJECT)
128
129 static gpointer manager_object = NULL;
130
131 #define GSD_DBUS_NAME "org.gnome.SettingsDaemon"
132 #define GSD_DBUS_PATH "/org/gnome/SettingsDaemon"
133 #define GSD_DBUS_BASE_INTERFACE "org.gnome.SettingsDaemon"
134
135 #define GSD_USB_PROTECTION_DBUS_NAME GSD_DBUS_NAME ".UsbProtection"
136 #define GSD_USB_PROTECTION_DBUS_PATH GSD_DBUS_PATH "/UsbProtection"
137
138 static const gchar introspection_xml[] =
139 "<node>"
140 " <interface name='org.gnome.SettingsDaemon.UsbProtection'>"
141 " <property name='Available' type='b' access='read'/>"
142 " </interface>"
143 "</node>";
144
145 static void
dbus_call_log_error(GObject * source_object,GAsyncResult * res,gpointer user_data)146 dbus_call_log_error (GObject *source_object,
147 GAsyncResult *res,
148 gpointer user_data)
149 {
150 g_autoptr(GVariant) result = NULL;
151 g_autoptr(GError) error = NULL;
152 const gchar *msg = user_data;
153
154 result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
155 res,
156 &error);
157 if (result == NULL &&
158 !g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN))
159 g_warning ("%s: %s", msg, error->message);
160 }
161
162 static void
add_usbguard_allow_rule(GsdUsbProtectionManager * manager)163 add_usbguard_allow_rule (GsdUsbProtectionManager *manager)
164 {
165 /* This appends a "allow all" rule.
166 * It has the purpose of ensuring the authorization of new devices when
167 * the lockscreen is off while respecting existing rules.
168 * We make it temporary, so that we are stateless and don't alter the
169 * existing (persistent) configuration.
170 */
171
172 GVariant *params;
173 GDBusProxy *policy_proxy = manager->usb_protection_policy;
174
175 if (policy_proxy == NULL) {
176 g_warning ("Cannot add allow rule, because dbus proxy is missing");
177 } else {
178 gboolean temporary = TRUE;
179 /* This is USBGuard's Rule::LastID */
180 /* const guint32 last_rule_id = G_MAXUINT32 - 2; */
181 /* We can't use Rule::LastID, due to a bug in USBGuard.
182 * We cannot pick an arbitrary number, so we pick
183 * "0" which means we prepend our rule.
184 * https://github.com/USBGuard/usbguard/pull/355
185 */
186 const guint32 last_rule_id = 0;
187 g_debug ("Adding rule %u", last_rule_id);
188 params = g_variant_new ("(sub)", ALLOW_ALL, last_rule_id, temporary);
189 g_dbus_proxy_call (policy_proxy,
190 APPEND_RULE,
191 params,
192 G_DBUS_CALL_FLAGS_NONE,
193 -1,
194 manager->cancellable,
195 dbus_call_log_error,
196 "Error appending USBGuard rule");
197 }
198 }
199
200 static gboolean
is_usbguard_allow_rule_present(GVariant * rules)201 is_usbguard_allow_rule_present (GVariant *rules)
202 {
203 g_autoptr(GVariantIter) iter = NULL;
204 g_autofree gchar *value = NULL;
205 guint number = 0;
206
207 g_debug ("Detecting rule...");
208
209 g_variant_get (rules, "a(us)", &iter);
210 while (g_variant_iter_loop (iter, "(us)", &number, &value)) {
211 if (g_strcmp0 (value, ALLOW_ALL) == 0) {
212 g_debug ("Detected rule!");
213 return TRUE;
214 }
215 }
216 return FALSE;
217 }
218
219 static void
usbguard_listrules_cb(GObject * source_object,GAsyncResult * res,gpointer user_data)220 usbguard_listrules_cb (GObject *source_object,
221 GAsyncResult *res,
222 gpointer user_data)
223 {
224 GVariant *result, *rules;
225 g_autoptr(GError) error = NULL;
226
227 result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
228 res,
229 &error);
230
231 if (!result) {
232 if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
233 g_warning ("Failed to fetch USBGuard rules list: %s", error->message);
234 }
235 return;
236 }
237
238 rules = g_variant_get_child_value (result, 0);
239 g_variant_unref (result);
240 if (!is_usbguard_allow_rule_present (rules))
241 add_usbguard_allow_rule (user_data);
242
243 }
244
245 static void
usbguard_ensure_allow_rule(GsdUsbProtectionManager * manager)246 usbguard_ensure_allow_rule (GsdUsbProtectionManager *manager)
247 {
248 GVariant *params;
249 GDBusProxy *policy_proxy = manager->usb_protection_policy;
250
251 if (policy_proxy == NULL) {
252 g_warning ("Cannot list rules, because dbus proxy is missing");
253 } else {
254 /* listRules parameter is a label for matching rules.
255 * Currently we are using an empty label to get all the
256 * rules instead of just using "GNOME_SETTINGS_DAEMON_RULE"
257 * until this bug gets solved:
258 * https://github.com/USBGuard/usbguard/issues/328 */
259 params = g_variant_new ("(s)", "");
260 g_dbus_proxy_call (policy_proxy,
261 LIST_RULES,
262 params,
263 G_DBUS_CALL_FLAGS_NONE,
264 -1,
265 manager->cancellable,
266 usbguard_listrules_cb,
267 manager);
268 }
269 }
270
271 static void
settings_changed_callback(GSettings * settings,const char * key,GsdUsbProtectionManager * manager)272 settings_changed_callback (GSettings *settings,
273 const char *key,
274 GsdUsbProtectionManager *manager)
275 {
276 gchar *value_usbguard;
277 gboolean usbguard_controlled;
278 GVariant *params;
279 GDesktopUsbProtection protection_level;
280
281 /* We react only if one of the two USB related properties has been changed */
282 if (g_strcmp0 (key, USB_PROTECTION) != 0 && g_strcmp0 (key, USB_PROTECTION_LEVEL) != 0)
283 return;
284
285 usbguard_controlled = g_settings_get_boolean (settings, USB_PROTECTION);
286 protection_level = g_settings_get_enum (settings, USB_PROTECTION_LEVEL);
287 g_debug ("USBGuard control is currently %i with a protection level of %i",
288 usbguard_controlled, protection_level);
289
290 /* If previously we were controlling USBGuard and now we are not,
291 * we leave the USBGuard configuration in a clean state. I.e. we set
292 * "InsertedDevicePolicy" to "apply-policy" and we ensure that
293 * there is an always allow rule. In this way even if USBGuard daemon
294 * is running every USB devices will be automatically authorized. */
295 if (g_strcmp0 (key, USB_PROTECTION) == 0 && !usbguard_controlled) {
296 g_debug ("let's clean usbguard config state");
297 params = g_variant_new ("(ss)",
298 INSERTED_DEVICE_POLICY,
299 APPLY_POLICY);
300
301 if (manager->usb_protection != NULL) {
302 g_dbus_proxy_call (manager->usb_protection,
303 "setParameter",
304 params,
305 G_DBUS_CALL_FLAGS_NONE,
306 -1,
307 manager->cancellable,
308 dbus_call_log_error,
309 "Error calling USBGuard DBus to set a clean configuration state");
310 }
311
312 usbguard_ensure_allow_rule (manager);
313 }
314
315 /* Only if we are entitled to handle USBGuard */
316 if (usbguard_controlled && manager->usb_protection != NULL) {
317 value_usbguard = (protection_level == G_DESKTOP_USB_PROTECTION_ALWAYS) ? BLOCK : APPLY_POLICY;
318 params = g_variant_new ("(ss)",
319 INSERTED_DEVICE_POLICY,
320 value_usbguard);
321
322 g_dbus_proxy_call (manager->usb_protection,
323 "setParameter",
324 params,
325 G_DBUS_CALL_FLAGS_NONE,
326 -1,
327 manager->cancellable,
328 dbus_call_log_error,
329 "Error calling USBGuard DBus to set the desidered protection level");
330
331 /* If we are in "When lockscreen is active" we also check if the
332 * always allow rule is present. */
333 if (protection_level == G_DESKTOP_USB_PROTECTION_LOCKSCREEN)
334 usbguard_ensure_allow_rule (manager);
335 }
336 }
337
update_usb_protection_store(GsdUsbProtectionManager * manager,GVariant * parameter)338 static void update_usb_protection_store (GsdUsbProtectionManager *manager,
339 GVariant *parameter)
340 {
341 const gchar *key;
342 gboolean usbguard_controlled;
343 GDesktopUsbProtection protection_level;
344 GSettings *settings = manager->settings;
345
346 usbguard_controlled = g_settings_get_boolean (settings, USB_PROTECTION);
347 /* If we are not handling USBGuard configuration (e.g. the user is using
348 * a third party program) we do nothing when the config changes. */
349 if (usbguard_controlled) {
350 key = g_variant_get_string (parameter, NULL);
351 protection_level = g_settings_get_enum (settings, USB_PROTECTION_LEVEL);
352 /* If the USBGuard configuration has been changed and doesn't match
353 * our internal state, most likely means that the user externally
354 * changed it. When this happens we set to false the control value. */
355 if ((g_strcmp0 (key, APPLY_POLICY) == 0 && protection_level == G_DESKTOP_USB_PROTECTION_ALWAYS)) {
356 g_settings_set (settings, USB_PROTECTION, "b", FALSE);
357 g_warning ("We don't control anymore USBGuard because the configuration changed externally.");
358 }
359 }
360 }
361
362 static gboolean
is_protection_active(GsdUsbProtectionManager * manager)363 is_protection_active (GsdUsbProtectionManager *manager)
364 {
365 GSettings *settings = manager->settings;
366
367 return g_settings_get_boolean (settings, USB_PROTECTION);
368 }
369
370 static void
on_notification_closed(NotifyNotification * n,GsdUsbProtectionManager * manager)371 on_notification_closed (NotifyNotification *n,
372 GsdUsbProtectionManager *manager)
373 {
374 g_clear_object (&manager->notification);
375 }
376
377 static void
show_notification(GsdUsbProtectionManager * manager,const char * summary,const char * body)378 show_notification (GsdUsbProtectionManager *manager,
379 const char *summary,
380 const char *body)
381 {
382 /* Don't show a notice if one is already displayed */
383 if (manager->notification != NULL)
384 return;
385
386 manager->notification = notify_notification_new (summary, body, "drive-removable-media-symbolic");
387 notify_notification_set_app_name (manager->notification, _("USB Protection"));
388 notify_notification_set_hint (manager->notification, "transient", g_variant_new_boolean (TRUE));
389 notify_notification_set_hint_string (manager->notification, "x-gnome-privacy-scope", "system");
390 notify_notification_set_timeout (manager->notification, NOTIFY_EXPIRES_DEFAULT);
391 notify_notification_set_urgency (manager->notification, NOTIFY_URGENCY_CRITICAL);
392 g_signal_connect_object (manager->notification,
393 "closed",
394 G_CALLBACK (on_notification_closed),
395 manager,
396 0);
397 if (!notify_notification_show (manager->notification, NULL)) {
398 g_warning ("Failed to send USB protection notification");
399 g_clear_object (&manager->notification);
400 }
401 }
402
authorize_device(GDBusProxy * proxy,GsdUsbProtectionManager * manager,guint device_id,guint target,gboolean permanent)403 static void authorize_device (GDBusProxy *proxy,
404 GsdUsbProtectionManager *manager,
405 guint device_id,
406 guint target,
407 gboolean permanent)
408 {
409 if (manager->usb_protection_devices == NULL) {
410 g_warning("Could not authorize device, because DBus is missing");
411 } else {
412 GVariant *params = g_variant_new ("(uub)", device_id, target, permanent);
413 g_dbus_proxy_call (manager->usb_protection_devices,
414 APPLY_DEVICE_POLICY,
415 params,
416 G_DBUS_CALL_FLAGS_NONE,
417 -1,
418 manager->cancellable,
419 dbus_call_log_error,
420 "Error calling USBGuard DBus to authorize a device");
421 }
422 }
423
424 static gboolean
is_hid_or_hub(GVariant * device,gboolean * has_other_classes)425 is_hid_or_hub (GVariant *device,
426 gboolean *has_other_classes)
427 {
428 g_autoptr(GVariantIter) iter = NULL;
429 g_autofree gchar *name = NULL;
430 g_autofree gchar *value = NULL;
431 guint i;
432 gboolean is_hid_or_hub = FALSE;
433
434 if (has_other_classes != NULL) {
435 *has_other_classes = FALSE;
436 }
437
438 g_variant_get_child (device, PRESENCE_ATTRIBUTES, "a{ss}", &iter);
439 while (g_variant_iter_loop (iter, "{ss}", &name, &value)) {
440 if (g_strcmp0 (name, WITH_INTERFACE) == 0) {
441 g_auto(GStrv) interfaces_splitted = NULL;
442 interfaces_splitted = g_strsplit (value, " ", -1);
443 for (i = 0; i < g_strv_length (interfaces_splitted); i++) {
444 if (g_str_has_prefix (interfaces_splitted[i], "03:")
445 || g_str_has_prefix (interfaces_splitted[i], "09:")) {
446 is_hid_or_hub = TRUE;
447 }
448 else if (has_other_classes != NULL) {
449 *has_other_classes = TRUE;
450 }
451 }
452 }
453 }
454 return is_hid_or_hub;
455 }
456
457 static gboolean
is_hardwired(GVariant * device)458 is_hardwired (GVariant *device)
459 {
460 g_autoptr(GVariantIter) iter = NULL;
461 g_autofree gchar *name = NULL;
462 g_autofree gchar *value = NULL;
463
464 g_variant_get_child (device, PRESENCE_ATTRIBUTES, "a{ss}", &iter);
465 while (g_variant_iter_loop (iter, "{ss}", &name, &value)) {
466 if (g_strcmp0 (name, WITH_CONNECT_TYPE) == 0) {
467 return g_strcmp0 (value, "hardwired") == 0;
468 }
469 }
470 return FALSE;
471 }
472
473 static void
auth_device(GsdUsbProtectionManager * manager,GVariant * device)474 auth_device (GsdUsbProtectionManager *manager,
475 GVariant *device)
476 {
477 guint device_id;
478
479 if (manager->usb_protection_devices == NULL)
480 return;
481
482 g_variant_get_child (device, POLICY_DEVICE_ID, "u", &device_id);
483 authorize_device(manager->usb_protection_devices,
484 manager,
485 device_id,
486 TARGET_ALLOW,
487 FALSE);
488 }
489
490 static void
on_screen_locked(GsdScreenSaver * screen_saver,GAsyncResult * result,GsdUsbProtectionManager * manager)491 on_screen_locked (GsdScreenSaver *screen_saver,
492 GAsyncResult *result,
493 GsdUsbProtectionManager *manager)
494 {
495 g_autoptr(GError) error = NULL;
496
497 gsd_screen_saver_call_lock_finish (screen_saver, result, &error);
498
499 if (error) {
500 if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
501 return;
502 g_warning ("Couldn't lock screen: %s", error->message);
503 }
504
505 show_notification (manager,
506 _("New USB device"),
507 _("New device has been detected while the session was not locked. "
508 "If you did not plug anything, check your system for any suspicious device."));
509
510 }
511
512 static void
on_usbguard_signal(GDBusProxy * proxy,gchar * sender_name,gchar * signal_name,GVariant * parameters,gpointer user_data)513 on_usbguard_signal (GDBusProxy *proxy,
514 gchar *sender_name,
515 gchar *signal_name,
516 GVariant *parameters,
517 gpointer user_data)
518 {
519 UsbGuardTarget target = TARGET_BLOCK;
520 UsbGuardEvent device_event;
521 GDesktopUsbProtection protection_level;
522 GsdUsbProtectionManager *manager = user_data;
523 g_autoptr(GVariantIter) iter = NULL;
524 g_autofree gchar *name = NULL;
525 g_autofree gchar *device_name = NULL;
526 gboolean hid_or_hub = FALSE;
527 gboolean has_other_classes = FALSE;
528
529 g_debug ("USBGuard signal: %s", signal_name);
530
531 /* We act only if we receive a signal indicating that a device has been inserted */
532 if (g_strcmp0 (signal_name, DEVICE_PRESENCE_CHANGED) != 0) {
533 return;
534 }
535
536 g_variant_get_child (parameters, PRESENCE_EVENT, "u", &device_event);
537 if (device_event != EVENT_INSERT) {
538 g_debug ("Device hat not been inserted (%d); ignoring", device_event);
539 return;
540 }
541
542 /* We would like to show a notification for an inserted device that
543 * *has not been blocked*. But USBGuard is not providing that information.
544 * So we have to work around that limitation and assume that any device plugged in
545 * during screensaver shall be blocked.
546 * https://github.com/USBGuard/usbguard/issues/353
547
548 g_variant_get_child (parameters, POLICY_TARGET_NEW, "u", &target);
549 */
550
551 /* If the device is already authorized we do nothing */
552 if (target == TARGET_ALLOW) {
553 g_debug ("Device will be allowed, we return");
554 return;
555 }
556
557 /* If the USB protection is disabled we do nothing */
558 if (!is_protection_active (manager)) {
559 g_debug ("Protection is not active. Not acting on the device");
560 return;
561 }
562
563 g_variant_get_child (parameters, PRESENCE_ATTRIBUTES, "a{ss}", &iter);
564 while (g_variant_iter_loop (iter, "{ss}", &name, &device_name)) {
565 if (g_strcmp0 (name, NAME) == 0)
566 g_debug ("A new USB device has been connected: %s", device_name);
567 }
568
569 if (is_hardwired (parameters)) {
570 g_debug ("Device is hardwired, allowing it to be connected");
571 auth_device (manager, parameters);
572 return;
573 }
574
575 protection_level = g_settings_get_enum (manager->settings, USB_PROTECTION_LEVEL);
576
577 g_debug ("Screensaver active: %d", manager->screensaver_active);
578 hid_or_hub = is_hid_or_hub (parameters, &has_other_classes);
579 if (manager->screensaver_active) {
580 /* If the session is locked we check if the inserted device is a HID,
581 * e.g. a keyboard or a mouse, or an HUB.
582 * If that is the case we authorize the newly inserted device as an
583 * antilockout policy.
584 *
585 * If this device advertises also interfaces outside the HID class, or the
586 * HUB class, it is suspect. It could be a false positive because this could
587 * be a "smart" keyboard for example, but at this stage is better be safe. */
588 if (hid_or_hub && !has_other_classes) {
589 show_notification (manager,
590 _("New device detected"),
591 _("Either one of your existing devices has been reconnected or a new one has been plugged in. "
592 "If you did not do it, check your system for any suspicious device."));
593 auth_device (manager, parameters);
594 } else {
595 if (protection_level == G_DESKTOP_USB_PROTECTION_LOCKSCREEN) {
596 show_notification (manager,
597 _("Reconnect USB device"),
598 _("New device has been detected while you were away. "
599 "Please disconnect and reconnect the device to start using it."));
600 } else {
601 const char* name_for_notification = device_name ? device_name : "unknown name";
602 g_debug ("Showing notification for %s", name_for_notification);
603 show_notification (manager,
604 _("USB device blocked"),
605 _("New device has been detected while you were away. "
606 "It has been blocked because the USB protection is active."));
607 }
608 }
609 } else {
610 /* If the protection level is "lockscreen" the device will be automatically
611 * authorized by usbguard. */
612 if (protection_level == G_DESKTOP_USB_PROTECTION_ALWAYS) {
613 /* We authorize the device if this is a HID,
614 * e.g. a keyboard or a mouse, or an HUB.
615 * We also lock the screen to prevent an attacker to plug malicious
616 * devices if the legitimate user forgot to lock his session.
617 *
618 * If this device advertises also interfaces outside the HID class, or the
619 * HUB class, it is suspect. It could be a false positive because this could
620 * be a "smart" keyboard for example, but at this stage is better be safe. */
621 if (hid_or_hub && !has_other_classes) {
622 gsd_screen_saver_call_lock (manager->screensaver_proxy,
623 manager->cancellable,
624 (GAsyncReadyCallback) on_screen_locked,
625 manager);
626 auth_device (manager, parameters);
627 } else {
628 show_notification (manager,
629 _("USB device blocked"),
630 _("The new inserted device has been blocked because the USB protection is active."));
631 }
632 }
633 }
634 }
635
636 static void
on_usb_protection_signal(GDBusProxy * proxy,gchar * sender_name,gchar * signal_name,GVariant * parameters,gpointer user_data)637 on_usb_protection_signal (GDBusProxy *proxy,
638 gchar *sender_name,
639 gchar *signal_name,
640 GVariant *parameters,
641 gpointer user_data)
642 {
643 g_autoptr(GVariant) parameter = NULL;
644 g_autofree gchar *policy_name = NULL;
645
646 if (g_strcmp0 (signal_name, "PropertyParameterChanged") != 0)
647 return;
648
649 g_variant_get_child (parameters, 0, "s", &policy_name);
650
651 /* Right now we just care about the InsertedDevicePolicy value */
652 if (g_strcmp0 (policy_name, INSERTED_DEVICE_POLICY) != 0)
653 return;
654
655 parameter = g_variant_get_child_value (parameters, 2);
656 update_usb_protection_store (user_data, parameter);
657
658 }
659
660 static void
get_parameter_cb(GObject * source_object,GAsyncResult * res,gpointer user_data)661 get_parameter_cb (GObject *source_object,
662 GAsyncResult *res,
663 gpointer user_data)
664 {
665 GVariant *result;
666 GVariant *params = NULL;
667 g_autofree gchar *key = NULL;
668 GDesktopUsbProtection protection_level;
669 GsdUsbProtectionManager *manager;
670 GSettings *settings;
671 g_autoptr(GError) error = NULL;
672
673 result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
674 res,
675 &error);
676 if (result == NULL) {
677 if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
678 g_warning ("Failed to fetch USBGuard parameters: %s", error->message);
679 }
680 return;
681 }
682
683 manager = GSD_USB_PROTECTION_MANAGER (user_data);
684 settings = manager->settings;
685
686 g_variant_get_child (result, 0, "s", &key);
687 g_variant_unref (result);
688 protection_level = g_settings_get_enum (settings, USB_PROTECTION_LEVEL);
689
690 g_debug ("InsertedDevicePolicy is: %s", key);
691
692 if (protection_level == G_DESKTOP_USB_PROTECTION_LOCKSCREEN) {
693 if (g_strcmp0 (key, APPLY_POLICY) != 0) {
694 /* We are out of sync. */
695 params = g_variant_new ("(ss)",
696 INSERTED_DEVICE_POLICY,
697 APPLY_POLICY);
698 }
699 } else if (protection_level == G_DESKTOP_USB_PROTECTION_ALWAYS) {
700 if (g_strcmp0 (key, BLOCK) != 0) {
701 /* We are out of sync. */
702 params = g_variant_new ("(ss)",
703 INSERTED_DEVICE_POLICY,
704 BLOCK);
705 }
706 }
707
708 if (params != NULL) {
709 /* We are out of sync. We need to call setParameter to update USBGuard state */
710 if (manager->usb_protection != NULL) {
711 g_debug ("Setting InsertedDevicePolicy");
712 g_dbus_proxy_call (manager->usb_protection,
713 "setParameter",
714 params,
715 G_DBUS_CALL_FLAGS_NONE,
716 -1,
717 manager->cancellable,
718 dbus_call_log_error,
719 "Error calling USBGuard DBus while we were out of sync");
720 }
721
722 }
723
724 /* If we are in "When lockscreen is active" we also check
725 * if the "always allow" rule is present. */
726 if (protection_level == G_DESKTOP_USB_PROTECTION_LOCKSCREEN) {
727 g_debug ("Ensuring allow all");
728 usbguard_ensure_allow_rule (manager);
729 }
730 }
731
732 static void
sync_usb_protection(GDBusProxy * proxy,GsdUsbProtectionManager * manager)733 sync_usb_protection (GDBusProxy *proxy,
734 GsdUsbProtectionManager *manager)
735 {
736 GVariant *params;
737 gboolean usbguard_controlled;
738 GSettings *settings = manager->settings;
739
740 usbguard_controlled = g_settings_get_boolean (settings, USB_PROTECTION);
741
742 g_debug ("Attempting to sync USB parameters: %d %p %p",
743 usbguard_controlled, proxy, manager->usb_protection);
744
745 if (!usbguard_controlled || manager->usb_protection == NULL)
746 return;
747
748 params = g_variant_new ("(s)", INSERTED_DEVICE_POLICY);
749 g_dbus_proxy_call (manager->usb_protection,
750 "getParameter",
751 params,
752 G_DBUS_CALL_FLAGS_NONE,
753 -1,
754 manager->cancellable,
755 get_parameter_cb,
756 manager);
757 }
758
759 static void
usb_protection_properties_changed(GsdUsbProtectionManager * manager)760 usb_protection_properties_changed (GsdUsbProtectionManager *manager)
761 {
762 GVariantBuilder props_builder;
763 GVariant *props_changed = NULL;
764
765 /* not yet connected to the session bus */
766 if (manager->connection == NULL)
767 return;
768
769 g_variant_builder_init (&props_builder, G_VARIANT_TYPE ("a{sv}"));
770
771 g_variant_builder_add (&props_builder, "{sv}", "Available",
772 g_variant_new_boolean (manager->available));
773
774 props_changed = g_variant_new ("(s@a{sv}@as)", GSD_USB_PROTECTION_DBUS_NAME,
775 g_variant_builder_end (&props_builder),
776 g_variant_new_strv (NULL, 0));
777
778 g_dbus_connection_emit_signal (manager->connection,
779 NULL,
780 GSD_USB_PROTECTION_DBUS_PATH,
781 "org.freedesktop.DBus.Properties",
782 "PropertiesChanged",
783 props_changed, NULL);
784 }
785
786 static void
on_usb_protection_owner_changed_cb(GObject * object,GParamSpec * pspec,gpointer user_data)787 on_usb_protection_owner_changed_cb (GObject *object,
788 GParamSpec *pspec,
789 gpointer user_data)
790 {
791 GsdUsbProtectionManager *manager = user_data;
792 GDBusProxy *proxy = G_DBUS_PROXY(object);
793 g_autofree gchar *name_owner = NULL;
794
795 name_owner = g_dbus_proxy_get_name_owner (proxy);
796 g_debug ("Got owner change: %s", name_owner);
797
798 if (name_owner) {
799 manager->available = TRUE;
800 } else {
801 manager->available = FALSE;
802 }
803
804 usb_protection_properties_changed (manager);
805 }
806
807 static void
handle_screensaver_active(GsdUsbProtectionManager * manager,GVariant * parameters)808 handle_screensaver_active (GsdUsbProtectionManager *manager,
809 GVariant *parameters)
810 {
811 gboolean active;
812 gchar *value_usbguard;
813 gboolean usbguard_controlled;
814 GVariant *params;
815 GDesktopUsbProtection protection_level;
816 GSettings *settings = manager->settings;
817
818 usbguard_controlled = g_settings_get_boolean (settings, USB_PROTECTION);
819 protection_level = g_settings_get_enum (settings, USB_PROTECTION_LEVEL);
820
821 g_variant_get (parameters, "(b)", &active);
822 g_debug ("Received screensaver ActiveChanged signal: %d (old: %d)", active, manager->screensaver_active);
823 if (manager->screensaver_active != active) {
824 manager->screensaver_active = active;
825 if (usbguard_controlled && protection_level == G_DESKTOP_USB_PROTECTION_LOCKSCREEN) {
826 /* If we are in the "lockscreen protection" level we change
827 * the usbguard config with apply-policy or block if the session
828 * is unlocked or locked, respectively. */
829 value_usbguard = active ? BLOCK : APPLY_POLICY;
830 params = g_variant_new ("(ss)",
831 INSERTED_DEVICE_POLICY,
832 value_usbguard);
833 if (manager->usb_protection != NULL) {
834 g_dbus_proxy_call (manager->usb_protection,
835 "setParameter",
836 params,
837 G_DBUS_CALL_FLAGS_NONE,
838 -1,
839 manager->cancellable,
840 dbus_call_log_error,
841 "Error calling USBGuard DBus to change the protection after a screensaver event");
842 }
843 }
844 }
845 }
846
847 static void
screensaver_signal_cb(GDBusProxy * proxy,const gchar * sender_name,const gchar * signal_name,GVariant * parameters,gpointer user_data)848 screensaver_signal_cb (GDBusProxy *proxy,
849 const gchar *sender_name,
850 const gchar *signal_name,
851 GVariant *parameters,
852 gpointer user_data)
853 {
854 g_debug ("ScreenSaver Signal: %s", signal_name);
855 if (g_strcmp0 (signal_name, "ActiveChanged") == 0)
856 handle_screensaver_active (GSD_USB_PROTECTION_MANAGER (user_data), parameters);
857 }
858
859 static void
usb_protection_policy_proxy_ready(GObject * source_object,GAsyncResult * res,gpointer user_data)860 usb_protection_policy_proxy_ready (GObject *source_object,
861 GAsyncResult *res,
862 gpointer user_data)
863 {
864 GsdUsbProtectionManager *manager;
865 GDBusProxy *proxy;
866 g_autoptr(GError) error = NULL;
867 g_debug ("usb_protection_policy_proxy_ready");
868
869 proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
870 if (!proxy) {
871 if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
872 g_warning ("Failed to contact USBGuard: %s", error->message);
873 return;
874 } else {
875 manager = GSD_USB_PROTECTION_MANAGER (user_data);
876 manager->usb_protection_policy = proxy;
877 g_debug ("Set protection policy proxy to %p", proxy);
878 sync_usb_protection (proxy, manager);
879 }
880 }
881
882 static void
usb_protection_devices_proxy_ready(GObject * source_object,GAsyncResult * res,gpointer user_data)883 usb_protection_devices_proxy_ready (GObject *source_object,
884 GAsyncResult *res,
885 gpointer user_data)
886 {
887 GsdUsbProtectionManager *manager;
888 GDBusProxy *proxy;
889 g_autoptr(GError) error = NULL;
890
891 proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
892 if (!proxy) {
893 if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
894 g_warning ("Failed to contact USBGuard: %s", error->message);
895 return;
896 }
897 manager = GSD_USB_PROTECTION_MANAGER (user_data);
898 manager->usb_protection_devices = proxy;
899
900 /* We don't care about already plugged in devices because they'll be
901 * already autorized by the "allow all" rule in USBGuard. */
902 g_debug ("Listening to signals");
903 g_signal_connect_object (source_object,
904 "g-signal",
905 G_CALLBACK (on_usbguard_signal),
906 user_data,
907 0);
908 }
909
910 static void
get_current_screen_saver_status(GsdUsbProtectionManager * manager)911 get_current_screen_saver_status (GsdUsbProtectionManager *manager)
912 {
913 g_autoptr(GVariant) ret = NULL;
914 g_autoptr(GError) error = NULL;
915
916 ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (manager->screensaver_proxy),
917 "GetActive",
918 NULL,
919 G_DBUS_CALL_FLAGS_NONE,
920 -1,
921 manager->cancellable,
922 &error);
923 if (ret == NULL) {
924 if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
925 g_warning ("Failed to get screen saver status: %s", error->message);
926 return;
927 }
928 handle_screensaver_active (manager, ret);
929 }
930
931 static void
usb_protection_proxy_ready(GObject * source_object,GAsyncResult * res,gpointer user_data)932 usb_protection_proxy_ready (GObject *source_object,
933 GAsyncResult *res,
934 gpointer user_data)
935 {
936 GsdUsbProtectionManager *manager;
937 GDBusProxy *proxy;
938 g_autofree gchar *name_owner = NULL;
939 g_autoptr(GError) error = NULL;
940
941 proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
942 if (!proxy) {
943 if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
944 g_warning ("Failed to contact USBGuard: %s", error->message);
945 return;
946 }
947 manager = GSD_USB_PROTECTION_MANAGER (user_data);
948 manager->usb_protection = proxy;
949
950 g_signal_connect (G_OBJECT (manager->settings), "changed",
951 G_CALLBACK (settings_changed_callback), manager);
952
953 manager->screensaver_proxy = gnome_settings_bus_get_screen_saver_proxy ();
954
955 get_current_screen_saver_status (manager);
956
957 g_signal_connect (manager->screensaver_proxy, "g-signal",
958 G_CALLBACK (screensaver_signal_cb), manager);
959
960 name_owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (proxy));
961
962 if (name_owner == NULL) {
963 g_debug("Probably USBGuard >= 0.7.5 is not currently installed.");
964 manager->available = FALSE;
965 } else {
966 manager->available = TRUE;
967 }
968
969 g_signal_connect_object (source_object,
970 "notify::g-name-owner",
971 G_CALLBACK (on_usb_protection_owner_changed_cb),
972 user_data,
973 0);
974
975 g_signal_connect_object (source_object,
976 "g-signal",
977 G_CALLBACK (on_usb_protection_signal),
978 user_data,
979 0);
980
981 g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
982 G_DBUS_PROXY_FLAGS_NONE,
983 NULL,
984 USBGUARD_DBUS_NAME,
985 USBGUARD_DBUS_PATH_DEVICES,
986 USBGUARD_DBUS_INTERFACE_DEVICES,
987 manager->cancellable,
988 usb_protection_devices_proxy_ready,
989 manager);
990
991 g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
992 G_DBUS_PROXY_FLAGS_NONE,
993 NULL,
994 USBGUARD_DBUS_NAME,
995 USBGUARD_DBUS_PATH_POLICY,
996 USBGUARD_DBUS_INTERFACE_POLICY,
997 manager->cancellable,
998 usb_protection_policy_proxy_ready,
999 manager);
1000 }
1001
1002 static GVariant *
handle_get_property(GDBusConnection * connection,const gchar * sender,const gchar * object_path,const gchar * interface_name,const gchar * property_name,GError ** error,gpointer user_data)1003 handle_get_property (GDBusConnection *connection,
1004 const gchar *sender,
1005 const gchar *object_path,
1006 const gchar *interface_name,
1007 const gchar *property_name,
1008 GError **error,
1009 gpointer user_data)
1010 {
1011 GsdUsbProtectionManager *manager = GSD_USB_PROTECTION_MANAGER (user_data);
1012
1013 /* Check session pointer as a proxy for whether the manager is in the
1014 start or stop state */
1015 if (manager->connection == NULL)
1016 return NULL;
1017
1018 if (g_strcmp0 (property_name, "Available") == 0)
1019 return g_variant_new_boolean (manager->available);
1020
1021 return NULL;
1022 }
1023
1024 static const GDBusInterfaceVTable interface_vtable =
1025 {
1026 NULL,
1027 handle_get_property,
1028 NULL
1029 };
1030
1031 static void
on_bus_gotten(GObject * source_object,GAsyncResult * res,GsdUsbProtectionManager * manager)1032 on_bus_gotten (GObject *source_object,
1033 GAsyncResult *res,
1034 GsdUsbProtectionManager *manager)
1035 {
1036 GDBusConnection *connection;
1037 GError *error = NULL;
1038
1039 connection = g_bus_get_finish (res, &error);
1040 if (connection == NULL) {
1041 if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
1042 g_warning ("Could not get session bus: %s", error->message);
1043 g_error_free (error);
1044 return;
1045 }
1046 manager->connection = connection;
1047
1048 g_dbus_connection_register_object (connection,
1049 GSD_USB_PROTECTION_DBUS_PATH,
1050 manager->introspection_data->interfaces[0],
1051 &interface_vtable,
1052 manager,
1053 NULL,
1054 NULL);
1055
1056 manager->name_id = g_bus_own_name_on_connection (connection,
1057 GSD_USB_PROTECTION_DBUS_NAME,
1058 G_BUS_NAME_OWNER_FLAGS_NONE,
1059 NULL,
1060 NULL,
1061 NULL,
1062 NULL);
1063 }
1064
1065 static gboolean
start_usb_protection_idle_cb(GsdUsbProtectionManager * manager)1066 start_usb_protection_idle_cb (GsdUsbProtectionManager *manager)
1067 {
1068 g_debug ("Starting USB protection manager");
1069
1070 manager->settings = g_settings_new (PRIVACY_SETTINGS);
1071 manager->cancellable = g_cancellable_new ();
1072
1073 g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
1074 G_DBUS_PROXY_FLAGS_NONE,
1075 NULL,
1076 USBGUARD_DBUS_NAME,
1077 USBGUARD_DBUS_PATH,
1078 USBGUARD_DBUS_INTERFACE_VERSIONED,
1079 manager->cancellable,
1080 usb_protection_proxy_ready,
1081 manager);
1082
1083 notify_init ("gnome-settings-daemon");
1084
1085 manager->start_idle_id = 0;
1086
1087 return FALSE;
1088 }
1089
1090 gboolean
gsd_usb_protection_manager_start(GsdUsbProtectionManager * manager,GError ** error)1091 gsd_usb_protection_manager_start (GsdUsbProtectionManager *manager,
1092 GError **error)
1093 {
1094 gnome_settings_profile_start (NULL);
1095
1096 manager->start_idle_id = g_idle_add ((GSourceFunc) start_usb_protection_idle_cb, manager);
1097 g_source_set_name_by_id (manager->start_idle_id, "[gnome-settings-daemon] start_usbguard_idle_cb");
1098
1099 manager->introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
1100 g_assert (manager->introspection_data != NULL);
1101
1102 /* Start process of owning a D-Bus name */
1103 g_bus_get (G_BUS_TYPE_SESSION,
1104 manager->cancellable,
1105 (GAsyncReadyCallback) on_bus_gotten,
1106 manager);
1107
1108 gnome_settings_profile_end (NULL);
1109 return TRUE;
1110 }
1111
1112 void
gsd_usb_protection_manager_stop(GsdUsbProtectionManager * manager)1113 gsd_usb_protection_manager_stop (GsdUsbProtectionManager *manager)
1114 {
1115 g_debug ("Stopping USB protection manager");
1116
1117 if (manager->cancellable != NULL) {
1118 g_cancellable_cancel (manager->cancellable);
1119 g_clear_object (&manager->cancellable);
1120 }
1121
1122 g_clear_object (&manager->notification);
1123
1124 if (manager->start_idle_id != 0) {
1125 g_source_remove (manager->start_idle_id);
1126 manager->start_idle_id = 0;
1127 }
1128
1129 if (manager->name_id != 0) {
1130 g_bus_unown_name (manager->name_id);
1131 manager->name_id = 0;
1132 }
1133
1134 g_clear_pointer (&manager->introspection_data, g_dbus_node_info_unref);
1135 g_clear_object (&manager->connection);
1136 g_clear_object (&manager->settings);
1137 g_clear_object (&manager->usb_protection);
1138 g_clear_object (&manager->usb_protection_devices);
1139 g_clear_object (&manager->usb_protection_policy);
1140 g_clear_object (&manager->screensaver_proxy);
1141 }
1142
1143 static void
gsd_usb_protection_manager_class_init(GsdUsbProtectionManagerClass * klass)1144 gsd_usb_protection_manager_class_init (GsdUsbProtectionManagerClass *klass)
1145 {
1146 GObjectClass *object_class = G_OBJECT_CLASS (klass);
1147
1148 object_class->finalize = gsd_usb_protection_manager_finalize;
1149 }
1150
1151 static void
gsd_usb_protection_manager_init(GsdUsbProtectionManager * manager)1152 gsd_usb_protection_manager_init (GsdUsbProtectionManager *manager)
1153 {
1154 }
1155
1156 static void
gsd_usb_protection_manager_finalize(GObject * object)1157 gsd_usb_protection_manager_finalize (GObject *object)
1158 {
1159 GsdUsbProtectionManager *usb_protection_manager;
1160
1161 usb_protection_manager = GSD_USB_PROTECTION_MANAGER (object);
1162 gsd_usb_protection_manager_stop (usb_protection_manager);
1163
1164 G_OBJECT_CLASS (gsd_usb_protection_manager_parent_class)->finalize (object);
1165 }
1166
1167 GsdUsbProtectionManager *
gsd_usb_protection_manager_new(void)1168 gsd_usb_protection_manager_new (void)
1169 {
1170 if (manager_object != NULL) {
1171 g_object_ref (manager_object);
1172 } else {
1173 manager_object = g_object_new (GSD_TYPE_USB_PROTECTION_MANAGER, NULL);
1174 g_object_add_weak_pointer (manager_object,
1175 (gpointer *) &manager_object);
1176 }
1177
1178 return GSD_USB_PROTECTION_MANAGER (manager_object);
1179 }
1180