1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
|
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "extensions/common/permissions/usb_device_permission_data.h"
#include <stdint.h>
#include <limits>
#include <memory>
#include <string>
#include <vector>
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/values.h"
#include "extensions/common/permissions/api_permission.h"
#include "extensions/common/permissions/usb_device_permission.h"
namespace extensions {
namespace {
const char kProductIdKey[] = "productId";
const char kVendorIdKey[] = "vendorId";
const char kInterfaceIdKey[] = "interfaceId";
const char kInterfaceClassKey[] = "interfaceClass";
bool ExtractFromDict(const std::string& key,
const base::Value::Dict* dict_value,
int max,
int* value) {
std::optional<int> temp = dict_value->FindInt(key);
if (!temp) {
*value = UsbDevicePermissionData::SPECIAL_VALUE_ANY;
return true;
}
if (*temp < UsbDevicePermissionData::SPECIAL_VALUE_ANY || *temp > max)
return false;
*value = *temp;
return true;
}
} // namespace
UsbDevicePermissionData::UsbDevicePermissionData() = default;
UsbDevicePermissionData::UsbDevicePermissionData(int vendor_id,
int product_id,
int interface_id,
int interface_class)
: vendor_id_(vendor_id),
product_id_(product_id),
interface_id_(interface_id),
interface_class_(interface_class) {}
bool UsbDevicePermissionData::Check(
const APIPermission::CheckParam* param) const {
if (!param)
return false;
const UsbDevicePermission::CheckParam& specific_param =
*static_cast<const UsbDevicePermission::CheckParam*>(param);
// The permission should be ignored if it filters by interface class when
// filtering by interface class is not allowed.
if (!specific_param.interface_class_allowed &&
interface_class_ != SPECIAL_VALUE_ANY) {
return false;
}
DCHECK(specific_param.interface_class_allowed ||
(vendor_id_ != SPECIAL_VALUE_ANY && product_id_ != SPECIAL_VALUE_ANY));
return (vendor_id_ == SPECIAL_VALUE_ANY ||
vendor_id_ == specific_param.vendor_id) &&
(product_id_ == SPECIAL_VALUE_ANY ||
product_id_ == specific_param.product_id) &&
(specific_param.interface_id == SPECIAL_VALUE_UNSPECIFIED ||
interface_id_ == specific_param.interface_id) &&
(!specific_param.interface_classes ||
interface_class_ == SPECIAL_VALUE_ANY ||
specific_param.interface_classes->count(interface_class_) > 0);
}
std::unique_ptr<base::Value> UsbDevicePermissionData::ToValue() const {
base::Value::Dict result;
result.Set(kVendorIdKey, vendor_id_);
result.Set(kProductIdKey, product_id_);
result.Set(kInterfaceIdKey, interface_id_);
result.Set(kInterfaceClassKey, interface_class_);
return std::make_unique<base::Value>(std::move(result));
}
bool UsbDevicePermissionData::FromValue(const base::Value* value) {
if (!value)
return false;
const base::Value::Dict* dict_value = value->GetIfDict();
if (!dict_value)
return false;
const int kMaxId = std::numeric_limits<uint16_t>::max();
if (!ExtractFromDict(kVendorIdKey, dict_value, kMaxId, &vendor_id_))
return false;
if (!ExtractFromDict(kProductIdKey, dict_value, kMaxId, &product_id_))
return false;
// If product ID is specified, so should be vendor ID.
if (product_id_ != SPECIAL_VALUE_ANY && vendor_id_ == SPECIAL_VALUE_ANY)
return false;
const int kMaxInterfaceData = std::numeric_limits<uint8_t>::max();
if (!ExtractFromDict(kInterfaceIdKey, dict_value, kMaxInterfaceData,
&interface_id_)) {
return false;
}
// If interface ID is specified, so should be vendor ID and product ID (note
// that product ID being set implies that vendor ID is set).
if (interface_id_ != SPECIAL_VALUE_ANY && product_id_ == SPECIAL_VALUE_ANY)
return false;
if (!ExtractFromDict(kInterfaceClassKey, dict_value, kMaxInterfaceData,
&interface_class_)) {
return false;
}
// Reject the permission if neither interface class nor vendor ID, product ID
// pair is specified in the permission.
// Note that set product ID implies that vendor ID is set as well, so only
// product ID has to be checked.
if (interface_class_ == SPECIAL_VALUE_ANY && product_id_ == SPECIAL_VALUE_ANY)
return false;
// Interface ID is ignored, but kept for backward compatibility - don't allow
// it's usage with interface class, as interface class property was introduced
// after interface ID support was dropped.
if (interface_class_ != SPECIAL_VALUE_ANY &&
interface_id_ != SPECIAL_VALUE_ANY) {
return false;
}
return true;
}
} // namespace extensions
|