bolt-device.c 29.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/*
 * Copyright © 2017 Red Hat, Inc
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
 *
 * Authors:
 *       Christian J. Kellner <christian@kellner.me>
 */

#include "config.h"

#include "bolt-device.h"
24

25
#include "bolt-enums.h"
26
#include "bolt-error.h"
27
#include "bolt-io.h"
28
#include "bolt-log.h"
29
#include "bolt-manager.h"
30
#include "bolt-names.h"
31
#include "bolt-store.h"
32
#include "bolt-str.h"
33

34
#include <dirent.h>
35 36
#include <libudev.h>

37 38 39 40 41 42
/* dbus property setter */
static gboolean handle_set_label (BoltExported *obj,
                                  const char   *name,
                                  const GValue *value,
                                  GError      **error);

43
/* dbus method calls */
44 45 46
static gboolean    handle_authorize (BoltExported          *object,
                                     GVariant              *params,
                                     GDBusMethodInvocation *invocation);
47

48

49 50
struct _BoltDevice
{
51
  BoltExported object;
52

53
  /* device props */
54
  char          *dbus_path;
55

56 57 58
  char          *uid;
  char          *name;
  char          *vendor;
59

60 61
  BoltDeviceType type;
  BoltStatus     status;
62

63
  /* when device is attached */
64 65
  char        *syspath;
  BoltSecurity security;
66
  char        *parent;
67

68
  guint64      conntime;
69
  guint64      authtime;
70

71
  /* when device is stored */
72
  BoltStore   *store;
73 74
  BoltPolicy   policy;
  BoltKeyState key;
75
  guint64      storetime;
76 77

  char        *label;
78 79 80 81 82 83
};


enum {
  PROP_0,

84 85
  PROP_STORE,

86
  /* exported properties start here, */
87
  PROP_UID,
88 89
  PROP_NAME,
  PROP_VENDOR,
90
  PROP_TYPE,
91
  PROP_STATUS,
92

93
  PROP_PARENT,
94
  PROP_SYSFS,
95
  PROP_SECURITY,
96
  PROP_CONNTIME,
97
  PROP_AUTHTIME,
98

99 100 101
  PROP_STORED,
  PROP_POLICY,
  PROP_HAVE_KEY,
102
  PROP_STORETIME,
103
  PROP_LABEL,
104 105 106

  PROP_LAST,
  PROP_EXPORTED = PROP_UID
107 108
};

109
static GParamSpec *props[PROP_LAST] = {NULL, };
110

111 112 113 114 115 116 117
enum {
  SIGNAL_STATUS_CHANGED,
  SIGNAL_LAST
};

static guint signals[SIGNAL_LAST] = {0};

118 119
G_DEFINE_TYPE (BoltDevice,
               bolt_device,
120
               BOLT_TYPE_EXPORTED)
121 122 123 124 125 126

static void
bolt_device_finalize (GObject *object)
{
  BoltDevice *dev = BOLT_DEVICE (object);

127 128
  g_clear_object (&dev->store);

129 130
  g_free (dev->dbus_path);

131
  g_free (dev->uid);
132 133
  g_free (dev->name);
  g_free (dev->vendor);
134 135

  g_free (dev->parent);
136
  g_free (dev->syspath);
137
  g_free (dev->label);
138 139 140 141 142

  G_OBJECT_CLASS (bolt_device_parent_class)->finalize (object);
}

static void
143
bolt_device_init (BoltDevice *dev)
144 145 146 147 148 149 150 151 152 153 154 155 156
{
}

static void
bolt_device_get_property (GObject    *object,
                          guint       prop_id,
                          GValue     *value,
                          GParamSpec *pspec)
{
  BoltDevice *dev = BOLT_DEVICE (object);

  switch (prop_id)
    {
157 158 159 160
    case PROP_STORE:
      g_value_set_object (value, dev->store);
      break;

161 162 163 164
    case PROP_UID:
      g_value_set_string (value, dev->uid);
      break;

165 166 167 168
    case PROP_NAME:
      g_value_set_string (value, dev->name);
      break;

169 170 171 172
    case PROP_TYPE:
      g_value_set_uint (value, dev->type);
      break;

173 174 175 176
    case PROP_VENDOR:
      g_value_set_string (value, dev->vendor);
      break;

177 178 179 180
    case PROP_STATUS:
      g_value_set_uint (value, dev->status);
      break;

181 182 183 184
    case PROP_PARENT:
      g_value_set_string (value, dev->parent);
      break;

185 186 187 188
    case PROP_SYSFS:
      g_value_set_string (value, dev->syspath);
      break;

189 190 191 192
    case PROP_SECURITY:
      g_value_set_uint (value, dev->security);
      break;

193 194 195 196
    case PROP_CONNTIME:
      g_value_set_uint64 (value, dev->conntime);
      break;

197 198 199 200
    case PROP_AUTHTIME:
      g_value_set_uint64 (value, dev->authtime);
      break;

201
    case PROP_STORED:
202
      g_value_set_boolean (value, dev->store != NULL);
203 204 205 206 207 208 209 210 211 212
      break;

    case PROP_POLICY:
      g_value_set_uint (value, dev->policy);
      break;

    case PROP_HAVE_KEY:
      g_value_set_uint (value, dev->key);
      break;

213 214 215 216
    case PROP_STORETIME:
      g_value_set_uint64 (value, dev->storetime);
      break;

217 218 219 220
    case PROP_LABEL:
      g_value_set_string (value, dev->label);
      break;

221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
    }
}

static void
bolt_device_set_property (GObject      *object,
                          guint         prop_id,
                          const GValue *value,
                          GParamSpec   *pspec)
{
  BoltDevice *dev = BOLT_DEVICE (object);

  switch (prop_id)
    {
236 237
    case PROP_STORE:
      dev->store = g_value_dup_object (value);
238
      g_object_notify_by_pspec (object, props[PROP_STORED]);
239 240
      break;

241
    case PROP_UID:
242
      g_return_if_fail (dev->uid == NULL);
243 244 245
      dev->uid = g_value_dup_string (value);
      break;

246
    case PROP_NAME:
247
      g_clear_pointer (&dev->name, g_free);
248
      dev->name = g_value_dup_string (value);
249 250 251
      break;

    case PROP_VENDOR:
252
      g_clear_pointer (&dev->vendor, g_free);
253
      dev->vendor = g_value_dup_string (value);
254 255
      break;

256 257 258 259
    case PROP_TYPE:
      dev->type = g_value_get_uint (value);
      break;

260
    case PROP_STATUS:
261 262 263 264 265 266 267 268 269 270 271 272 273
      {
        BoltStatus old = dev->status;
        BoltStatus now = g_value_get_uint (value);
        if (old == now)
          break;

        dev->status = now;
        g_signal_emit (dev,
                       signals[SIGNAL_STATUS_CHANGED],
                       0,
                       old);
        break;
      }
274

275 276 277 278 279
    case PROP_PARENT:
      g_clear_pointer (&dev->parent, g_free);
      dev->parent = g_value_dup_string (value);
      break;

280
    case PROP_SYSFS:
281
      g_clear_pointer (&dev->syspath, g_free);
282 283
      dev->syspath = g_value_dup_string (value);
      break;
284 285 286 287

    case PROP_SECURITY:
      dev->security = g_value_get_uint (value);
      break;
288

289 290 291 292
    case PROP_CONNTIME:
      dev->conntime = g_value_get_uint64 (value);
      break;

293 294 295 296
    case PROP_AUTHTIME:
      dev->authtime = g_value_get_uint64 (value);
      break;

297 298 299 300 301 302 303 304
    case PROP_POLICY:
      dev->policy = g_value_get_uint (value);
      break;

    case PROP_HAVE_KEY:
      dev->key = g_value_get_uint (value);
      break;

305 306 307 308
    case PROP_STORETIME:
      dev->storetime = g_value_get_uint64 (value);
      break;

309 310 311 312 313
    case PROP_LABEL:
      g_clear_pointer (&dev->label, g_free);
      dev->label = g_value_dup_string (value);
      break;

314 315 316 317 318 319 320 321 322 323
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
    }
}


static void
bolt_device_class_init (BoltDeviceClass *klass)
{
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
324
  BoltExportedClass *exported_class = BOLT_EXPORTED_CLASS (klass);
325 326 327 328 329 330

  gobject_class->finalize = bolt_device_finalize;

  gobject_class->get_property = bolt_device_get_property;
  gobject_class->set_property = bolt_device_set_property;

331 332 333 334 335
  props[PROP_STORE] =
    g_param_spec_object ("store",
                         NULL, NULL,
                         BOLT_TYPE_STORE,
                         G_PARAM_READWRITE |
336
                         G_PARAM_STATIC_STRINGS);
337

338 339 340 341 342 343 344
  props[PROP_UID] =
    g_param_spec_string ("uid",
                         "Uid", NULL,
                         NULL,
                         G_PARAM_READWRITE |
                         G_PARAM_CONSTRUCT_ONLY |
                         G_PARAM_STATIC_STRINGS);
345

346 347 348 349 350 351 352
  props[PROP_NAME] =
    g_param_spec_string ("name",
                         "Name", NULL,
                         NULL,
                         G_PARAM_READWRITE |
                         G_PARAM_CONSTRUCT_ONLY |
                         G_PARAM_STATIC_STRINGS);
353

354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386
  props[PROP_VENDOR] =
    g_param_spec_string ("vendor",
                         "Vendor", NULL,
                         NULL,
                         G_PARAM_READWRITE |
                         G_PARAM_CONSTRUCT_ONLY |
                         G_PARAM_STATIC_STRINGS);

  props[PROP_TYPE] =
    g_param_spec_uint ("type",
                       "Type", NULL,
                       BOLT_DEVICE_HOST,
                       BOLT_DEVICE_PERIPHERAL,
                       BOLT_DEVICE_PERIPHERAL,
                       G_PARAM_READWRITE |
                       G_PARAM_CONSTRUCT_ONLY |
                       G_PARAM_STATIC_STRINGS);

  props[PROP_STATUS] =
    g_param_spec_uint ("status",
                       "Status", NULL,
                       0,
                       BOLT_STATUS_LAST,
                       BOLT_STATUS_DISCONNECTED,
                       G_PARAM_READWRITE |
                       G_PARAM_STATIC_STRINGS);

  props[PROP_PARENT] =
    g_param_spec_string ("parent",
                         "Parent", NULL,
                         NULL,
                         G_PARAM_READWRITE |
                         G_PARAM_STATIC_STRINGS);
387

388 389 390 391 392 393
  props[PROP_SYSFS] =
    g_param_spec_string ("sysfs-path",
                         "SysfsPath", NULL,
                         NULL,
                         G_PARAM_READWRITE |
                         G_PARAM_STATIC_STRINGS);
394

395 396 397 398 399 400 401 402 403
  props[PROP_SECURITY] =
    g_param_spec_uint ("security",
                       "Security", NULL,
                       0,
                       BOLT_SECURITY_LAST,
                       BOLT_SECURITY_NONE,
                       G_PARAM_READWRITE |
                       G_PARAM_STATIC_STRINGS);

404 405 406 407 408 409 410
  props[PROP_CONNTIME] =
    g_param_spec_uint64 ("conntime",
                         "ConnectTime", NULL,
                         0, G_MAXUINT64, 0,
                         G_PARAM_READWRITE |
                         G_PARAM_STATIC_STRINGS);

411 412 413 414 415 416 417
  props[PROP_AUTHTIME] =
    g_param_spec_uint64 ("authtime",
                         "AuthorizeTime", NULL,
                         0, G_MAXUINT64, 0,
                         G_PARAM_READWRITE |
                         G_PARAM_STATIC_STRINGS);

418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441
  props[PROP_STORED] =
    g_param_spec_boolean ("stored",
                          "Stored", NULL,
                          FALSE,
                          G_PARAM_READWRITE |
                          G_PARAM_STATIC_STRINGS);

  props[PROP_POLICY] =
    g_param_spec_uint ("policy",
                       "Policy", NULL,
                       0,
                       BOLT_POLICY_LAST,
                       BOLT_POLICY_DEFAULT,
                       G_PARAM_READWRITE |
                       G_PARAM_STATIC_STRINGS);

  props[PROP_HAVE_KEY] =
    g_param_spec_uint ("key",
                       "Key", NULL,
                       0,
                       BOLT_KEY_NEW,
                       BOLT_KEY_MISSING,
                       G_PARAM_READWRITE |
                       G_PARAM_STATIC_STRINGS);
442

443 444 445 446 447 448 449
  props[PROP_STORETIME] =
    g_param_spec_uint64 ("storetime",
                         "StoreTime", NULL,
                         0, G_MAXUINT64, 0,
                         G_PARAM_READWRITE |
                         G_PARAM_STATIC_STRINGS);

450 451 452 453 454 455 456
  props[PROP_LABEL] =
    g_param_spec_string ("label",
                         "Label", NULL,
                         NULL,
                         G_PARAM_READWRITE |
                         G_PARAM_STATIC_STRINGS);

457 458 459
  g_object_class_install_properties (gobject_class,
                                     PROP_LAST,
                                     props);
460 461 462 463 464 465 466 467 468 469 470

  signals[SIGNAL_STATUS_CHANGED] =
    g_signal_new ("status-changed",
                  G_TYPE_FROM_CLASS (gobject_class),
                  G_SIGNAL_RUN_LAST,
                  0,
                  NULL, NULL,
                  NULL,
                  G_TYPE_NONE,
                  1, BOLT_TYPE_STATUS);

471 472 473 474 475 476 477 478 479
  bolt_exported_class_set_interface_info (exported_class,
                                          BOLT_DBUS_DEVICE_INTERFACE,
                                          "/boltd/org.freedesktop.bolt.xml");

  bolt_exported_class_export_properties (exported_class,
                                         PROP_EXPORTED,
                                         PROP_LAST,
                                         props);

480 481 482 483
  bolt_exported_class_property_setter (exported_class,
                                       props[PROP_LABEL],
                                       handle_set_label);

484 485 486 487
  bolt_exported_class_export_method (exported_class,
                                     "Authorize",
                                     handle_authorize);

488
}
489 490 491

/* internal methods */

492 493 494 495 496 497 498 499
static guint64
bolt_now_in_seconds (void)
{
  gint64 now = g_get_real_time ();

  return (guint64) now / G_USEC_PER_SEC;
}

500 501
static const char *
read_sysattr_name (struct udev_device *udev, const char *attr, GError **error)
502 503
{
  g_autofree char *s = NULL;
504
  const char *v;
505 506

  s = g_strdup_printf ("%s_name", attr);
507 508 509 510 511 512
  v = udev_device_get_sysattr_value (udev, s);

  if (v != NULL)
    return v;

  v = udev_device_get_sysattr_value (udev, attr);
513

514
  if (v == NULL)
515 516 517
    g_set_error (error,
                 BOLT_ERROR, BOLT_ERROR_UDEV,
                 "failed to get sysfs attr: %s", attr);
518 519

  return v;
520 521
}

522 523 524 525 526 527 528 529 530 531 532 533
static gint
read_sysfs_attr_int (struct udev_device *device, const char *attr)
{
  const char *str;
  char *end;
  gint64 val;

  str = udev_device_get_sysattr_value (device, attr);

  if (str == NULL)
    return 0;

534
  val = g_ascii_strtoll (str, &end, 0);
535 536 537 538 539 540

  if (str == end)
    return 0;

  if (val > G_MAXINT || val < G_MININT)
    {
541
      bolt_warn ("value read from sysfs outside of gint's range.");
542 543 544 545 546 547 548 549 550 551 552 553
      val = 0;
    }

  return (gint) val;
}

static gboolean
string_nonzero (const char *str)
{
  return str != NULL && str[0] != '\0';
}

554 555 556 557 558 559 560 561 562 563 564 565 566
static struct udev_device *
bolt_sysfs_get_parent (struct udev_device *udev,
                       GError            **error)
{
  struct udev_device * parent = udev_device_get_parent (udev);

  if (parent == NULL)
    g_set_error (error, BOLT_ERROR, BOLT_ERROR_UDEV,
                 "could not get parent udev device");

  return parent;
}

567 568 569 570 571 572 573 574 575 576 577 578
static const char *
bolt_sysfs_get_parent_uid (struct udev_device *udev)
{
  struct udev_device *parent;
  const char *uid = NULL;

  parent = udev_device_get_parent (udev);
  if (parent)
    uid = udev_device_get_sysattr_value (parent, "unique_id");
  return uid;
}

579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628
typedef enum BoltStatTime {
  BOLT_ST_ATIME,
  BOLT_ST_CTIME,
  BOLT_ST_MTIME
} BoltStatTime;

static gint64
bolt_sysfs_device_get_time (struct udev_device *udev,
                            BoltStatTime        st)
{
  const char *path;
  struct stat sb;
  gint64 ms;
  int r;

  path = udev_device_get_syspath (udev);

  if (path == NULL)
    return 0;

  r = lstat (path, &sb);

  if (r == -1)
    return 0;

  switch (st)
    {
    case BOLT_ST_CTIME:
      ms = (gint64) sb.st_ctim.tv_sec;
      break;

    case BOLT_ST_ATIME:
      ms = (gint64) sb.st_atim.tv_sec;
      break;

    case BOLT_ST_MTIME:
      ms = (gint64) sb.st_mtim.tv_sec;
      break;

    default:
      bolt_warn_enum_unhandled (BoltStatTime, st);
      return 0;
    }

  if (ms < 0)
    ms = 0;

  return ms;
}

629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658
static BoltStatus
bolt_status_from_udev (struct udev_device *udev)
{
  gint authorized;
  const char *key;
  gboolean have_key;

  authorized = read_sysfs_attr_int (udev, "authorized");

  if (authorized == 2)
    return BOLT_STATUS_AUTHORIZED_SECURE;

  key = udev_device_get_sysattr_value (udev, "key");
  have_key = string_nonzero (key);

  if (authorized == 1)
    {
      if (have_key)
        return BOLT_STATUS_AUTHORIZED_NEWKEY;
      else
        return BOLT_STATUS_AUTHORIZED;
    }
  else if (authorized == 0 && have_key)
    {
      return BOLT_STATUS_AUTH_ERROR;
    }

  return BOLT_STATUS_CONNECTED;
}

659 660 661 662 663 664 665
static gboolean
bolt_sysfs_device_is_domain (struct udev_device *udev)
{
  const char *devtype = udev_device_get_devtype (udev);

  return bolt_streq (devtype, "thunderbolt_domain");
}
666 667

static struct udev_device *
668
bolt_sysfs_domain_for_device (struct udev_device *udev)
669 670 671 672 673 674 675 676 677 678 679 680
{
  struct udev_device *parent;
  gboolean found;

  found = FALSE;
  parent = udev;
  do
    {
      parent = udev_device_get_parent (parent);
      if (!parent)
        break;

681
      found = bolt_sysfs_device_is_domain (parent);
682 683 684 685 686 687 688
    }
  while (!found);

  return found ? parent : NULL;
}

static BoltSecurity
689
bolt_sysfs_security_for_device (struct udev_device *udev)
690 691 692 693 694
{
  struct udev_device *parent = NULL;
  const char *v;
  BoltSecurity s;

695
  parent = bolt_sysfs_domain_for_device (udev);
696 697
  if (parent == NULL)
    {
698
      bolt_warn ("failed to determine domain device");
699 700 701 702 703 704
      return BOLT_SECURITY_NONE;
    }

  v = udev_device_get_sysattr_value (parent, "security");
  s = bolt_security_from_string (v);

705 706
  if (!bolt_security_validate (s))
    {
707
      bolt_warn ("invalid security: %s", v);
708 709 710
      s = BOLT_SECURITY_NONE;
    }

711 712 713
  return s;
}

714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741
static const char *
cleanup_name (const char *name,
              const char *vendor,
              GError    **error)
{
  g_return_val_if_fail (vendor != NULL, NULL);
  g_return_val_if_fail (name != NULL, NULL);

  /* some devices have the vendor name as a prefix */
  if (!g_str_has_prefix (name, vendor))
    return name;

  name += strlen (vendor);

  while (g_ascii_isspace (*name))
    name++;

  if (*name == '\0')
    {
      g_set_error_literal (error,
                           BOLT_ERROR, BOLT_ERROR_UDEV,
                           "device has empty name after cleanup");
      return NULL;
    }

  return name;
}

742 743 744 745
/*  device authorization */

typedef struct
{
746
  BoltAuth *auth;
747 748

  /* the outer callback  */
749 750
  GAsyncReadyCallback callback;
  gpointer            user_data;
751 752 753 754 755 756 757 758

} AuthData;

static void
auth_data_free (gpointer data)
{
  AuthData *auth = data;

759
  g_clear_object (&auth->auth);
760 761 762
  g_slice_free (AuthData, auth);
}

763 764
static gboolean
authorize_device_internal (BoltDevice *dev,
765
                           BoltAuth   *auth,
766
                           GError    **error)
767 768
{
  g_autoptr(DIR) devdir = NULL;
769 770
  BoltKey *key;
  BoltSecurity level;
771 772
  gboolean ok;

773 774 775
  key = bolt_auth_get_key (auth);
  level = bolt_auth_get_level (auth);

776
  devdir = bolt_opendir (dev->syspath, error);
777
  if (devdir == NULL)
778
    return FALSE;
779

780
  ok = bolt_verify_uid (dirfd (devdir), dev->uid, error);
781
  if (!ok)
782 783
    return FALSE;

784
  if (key)
785
    {
786 787
      int keyfd;

788
      bolt_debug (LOG_DEV (dev), "writing key");
789 790 791 792
      keyfd = bolt_openat (dirfd (devdir), "key", O_WRONLY | O_CLOEXEC, error);
      if (keyfd < 0)
        return FALSE;

793
      ok = bolt_key_write_to (key, keyfd, &level, error);
794 795 796
      close (keyfd);
      if (!ok)
        return FALSE;
797 798
    }

799
  bolt_debug (LOG_DEV (dev), "writing authorization");
800 801
  ok = bolt_write_char_at (dirfd (devdir),
                           "authorized",
802
                           level,
803 804 805 806 807 808 809 810 811 812 813 814
                           error);
  return ok;
}

static void
authorize_in_thread (GTask        *task,
                     gpointer      source,
                     gpointer      context,
                     GCancellable *cancellable)
{
  g_autoptr(GError) error = NULL;
  BoltDevice *dev = source;
815 816
  AuthData *auth_data = context;
  BoltAuth *auth = auth_data->auth;
817 818 819
  gboolean ok;

  ok = authorize_device_internal (dev, auth, &error);
820 821

  if (!ok)
822 823 824
    g_task_return_new_error (task, BOLT_ERROR, BOLT_ERROR_FAILED,
                             "failed to authorize device: %s",
                             error->message);
825
  else
826
    g_task_return_boolean (task, TRUE);
827 828 829 830 831 832 833
}

static void
authorize_thread_done (GObject      *object,
                       GAsyncResult *res,
                       gpointer      user_data)
{
834
  g_autoptr(GError) error = NULL;
835 836
  BoltDevice *dev = BOLT_DEVICE (object);
  GTask *task = G_TASK (res);
837
  BoltStatus status;
838 839
  AuthData *auth_data;
  BoltAuth *auth;
840
  gboolean ok;
841
  guint64 now;
842

843 844 845
  auth_data = g_task_get_task_data (task);
  auth = auth_data->auth;

846 847
  ok = g_task_propagate_boolean (task, &error);

848
  if (!ok)
849 850
    bolt_auth_return_error (auth, &error);

851
  now = bolt_now_in_seconds ();
852
  status = bolt_auth_to_status (auth);
853 854 855 856
  g_object_set (dev,
                "status", status,
                "authtime", now,
                NULL);
857

858 859 860 861
  if (auth_data->callback)
    auth_data->callback (G_OBJECT (dev),
                         G_ASYNC_RESULT (auth),
                         auth_data->user_data);
862 863
}

864 865 866 867 868
void
bolt_device_authorize (BoltDevice         *dev,
                       BoltAuth           *auth,
                       GAsyncReadyCallback callback,
                       gpointer            user_data)
869 870 871 872
{
  AuthData *auth_data;
  GTask *task;

873 874
  g_object_set (auth, "device", dev, NULL);

875 876 877
  if (dev->status != BOLT_STATUS_CONNECTED &&
      dev->status != BOLT_STATUS_AUTH_ERROR)
    {
878 879
      bolt_auth_return_new_error (auth, BOLT_ERROR, BOLT_ERROR_FAILED,
                                  "wrong device state: %u", dev->status);
880

881 882
      if (callback)
        callback (G_OBJECT (dev), G_ASYNC_RESULT (auth), user_data);
883

884
      return;
885 886 887
    }

  task = g_task_new (dev, NULL, authorize_thread_done, NULL);
888 889 890
  auth_data = g_slice_new (AuthData);
  auth_data->callback = callback;
  auth_data->user_data = user_data;
891
  auth_data->auth = g_object_ref (auth);
892 893
  g_task_set_task_data (task, auth_data, auth_data_free);

894
  g_object_set (dev, "status", BOLT_STATUS_AUTHORIZING, NULL);
895 896 897 898 899

  g_task_run_in_thread (task, authorize_in_thread);
  g_object_unref (task);
}

900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950
/* dbus property setter */

static gboolean
handle_set_label (BoltExported *obj,
                  const char   *name,
                  const GValue *value,
                  GError      **error)
{
  g_autofree char *nick = NULL;
  g_autofree char *old = NULL;
  BoltDevice *dev = BOLT_DEVICE (obj);
  const char *str = g_value_get_string (value);
  gboolean ok;

  nick = bolt_strdup_validate (str);

  if (nick == NULL)
    {
      g_set_error_literal (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
                           "string is invalid");
      return FALSE;
    }
  else if (strlen (nick) > 255)
    {
      g_set_error_literal (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
                           "string is too long");
      return FALSE;
    }

  if (dev->store == NULL)
    {
      g_set_error_literal (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
                           "device is not stored");
      return FALSE;
    }

  old = dev->label;
  dev->label = g_steal_pointer (&nick);

  ok = bolt_store_put_device (dev->store, dev, dev->policy, NULL, error);

  if (!ok)
    {
      bolt_warn_err (*error, LOG_DEV (dev), "failed to store device");

      nick = dev->label;
      dev->label = g_steal_pointer (&old);
    }

  return ok;
}
951 952 953 954

/* dbus methods */

static void
955 956 957
handle_authorize_done (GObject      *device,
                       GAsyncResult *res,
                       gpointer      user_data)
958
{
959 960 961 962 963 964 965
  GDBusMethodInvocation *inv;
  GError *error = NULL;
  BoltAuth *auth;
  gboolean ok;

  inv  = user_data;
  auth = BOLT_AUTH (res);
966

967
  ok = bolt_auth_check (auth, &error);
968
  if (ok)
969
    g_dbus_method_invocation_return_value (inv, g_variant_new ("()"));
970
  else
971
    g_dbus_method_invocation_take_error (inv, error);
972 973 974
}

static gboolean
975 976 977
handle_authorize (BoltExported          *object,
                  GVariant              *params,
                  GDBusMethodInvocation *inv)
978 979 980
{
  BoltDevice *dev = BOLT_DEVICE (object);
  GError *error = NULL;
981 982 983
  BoltAuth *auth;
  BoltSecurity level;
  BoltKey *key;
984

985 986
  level = dev->security;
  key = NULL;
987

988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003
  if (level == BOLT_SECURITY_SECURE)
    {
      if (dev->key)
        key = bolt_store_get_key (dev->store, dev->uid, &error);
      else
        level = BOLT_SECURITY_USER;
    }

  if (level == BOLT_SECURITY_SECURE && key == NULL)
    {
      g_dbus_method_invocation_take_error (inv, error);
      return TRUE;
    }

  auth = bolt_auth_new (dev, level, key);
  bolt_device_authorize (dev, auth, handle_authorize_done, inv);
1004 1005 1006 1007

  return TRUE;
}

1008 1009 1010
/* public methods */

BoltDevice *
1011
bolt_device_new_for_udev (struct udev_device *udev,
1012 1013
                          GError            **error)
{
1014
  struct udev_device *parent_dev;
1015 1016 1017 1018
  const char *uid;
  const char *name;
  const char *vendor;
  const char *syspath;
1019
  const char *parent;
1020 1021
  BoltSecurity security;
  BoltStatus status;
1022
  BoltDeviceType type;
1023
  BoltDevice *dev;
1024
  guint64 ct, at;
1025

1026 1027 1028 1029 1030 1031 1032
  uid = udev_device_get_sysattr_value (udev, "unique_id");
  if (udev == NULL)
    {
      g_set_error (error, BOLT_ERROR, BOLT_ERROR_UDEV,
                   "could not get unique_id for udev");
      return NULL;
    }
1033

1034 1035
  syspath = udev_device_get_syspath (udev);
  g_return_val_if_fail (syspath != NULL, NULL);
1036

1037
  name = read_sysattr_name (udev, "device", error);
1038 1039 1040
  if (name == NULL)
    return NULL;

1041
  vendor = read_sysattr_name (udev, "vendor", error);
1042 1043
  if (vendor == NULL)
    return NULL;
1044

1045 1046 1047 1048
  name = cleanup_name (name, vendor, error);
  if (name == NULL)
    return NULL;

1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063
  parent_dev = bolt_sysfs_get_parent (udev, error);
  if (parent_dev == NULL)
    return NULL;

  if (bolt_sysfs_device_is_domain (parent_dev))
    {
      parent = NULL;
      type = BOLT_DEVICE_HOST;
    }
  else
    {
      parent = udev_device_get_sysattr_value (parent_dev, "unique_id");
      type = BOLT_DEVICE_PERIPHERAL;
    }

1064 1065
  ct = (guint64) bolt_sysfs_device_get_time (udev, BOLT_ST_CTIME);

1066
  parent = bolt_sysfs_get_parent_uid (udev);
1067 1068 1069 1070
  security = bolt_sysfs_security_for_device (udev);
  status = bolt_status_from_udev (udev);
  at = bolt_status_is_authorized (status) ? ct : 0;

1071
  dev = g_object_new (BOLT_TYPE_DEVICE,
1072 1073 1074
                      "uid", uid,
                      "name", name,
                      "vendor", vendor,
1075
                      "type", type,
1076
                      "status", status,
1077
                      "sysfs-path", syspath,
1078
                      "parent", parent,
1079
                      "conntime", ct,
1080 1081
                      "authtime", at,
                      "security", security,
1082 1083
                      NULL);

1084

1085 1086 1087
  return dev;
}

1088
const char *
1089 1090 1091 1092
bolt_device_export (BoltDevice      *device,
                    GDBusConnection *connection,
                    GError         **error)
{
1093
  const char *path;
1094
  gboolean ok;
1095 1096

  g_return_val_if_fail (BOLT_IS_DEVICE (device), FALSE);
1097

1098
  path = bolt_device_get_object_path (device);
1099

1100 1101 1102 1103 1104
  ok = bolt_exported_export (BOLT_EXPORTED (device),
                             connection,
                             path,
                             error);

1105
  return ok ? path : NULL;
1106 1107 1108 1109 1110
}

void
bolt_device_unexport (BoltDevice *device)
{
1111
  bolt_exported_unexport (BOLT_EXPORTED (device));
1112
}
1113

1114 1115 1116 1117 1118 1119

BoltStatus
bolt_device_connected (BoltDevice         *dev,
                       struct udev_device *udev)
{
  const char *syspath;
1120
  const char *parent;
1121 1122
  BoltSecurity security;
  BoltStatus status;
1123
  guint64 ct, at;
1124 1125 1126

  syspath = udev_device_get_syspath (udev);
  status = bolt_status_from_udev (udev);
1127
  security = bolt_sysfs_security_for_device (udev);
1128
  parent = bolt_sysfs_get_parent_uid (udev);
1129