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