diff options
Diffstat (limited to 'dom/media/gmp/rlz')
-rw-r--r-- | dom/media/gmp/rlz/OWNERS | 4 | ||||
-rw-r--r-- | dom/media/gmp/rlz/README.mozilla | 4 | ||||
-rw-r--r-- | dom/media/gmp/rlz/lib/assert.h | 14 | ||||
-rw-r--r-- | dom/media/gmp/rlz/lib/crc8.cc | 90 | ||||
-rw-r--r-- | dom/media/gmp/rlz/lib/crc8.h | 24 | ||||
-rw-r--r-- | dom/media/gmp/rlz/lib/machine_id.cc | 93 | ||||
-rw-r--r-- | dom/media/gmp/rlz/lib/machine_id.h | 33 | ||||
-rw-r--r-- | dom/media/gmp/rlz/lib/string_utils.cc | 34 | ||||
-rw-r--r-- | dom/media/gmp/rlz/lib/string_utils.h | 20 | ||||
-rw-r--r-- | dom/media/gmp/rlz/mac/lib/machine_id_mac.cc | 322 | ||||
-rw-r--r-- | dom/media/gmp/rlz/moz.build | 34 | ||||
-rw-r--r-- | dom/media/gmp/rlz/win/lib/machine_id_win.cc | 136 |
12 files changed, 808 insertions, 0 deletions
diff --git a/dom/media/gmp/rlz/OWNERS b/dom/media/gmp/rlz/OWNERS new file mode 100644 index 0000000000..66f24ebb37 --- /dev/null +++ b/dom/media/gmp/rlz/OWNERS @@ -0,0 +1,4 @@ +rogerta@chromium.org +thakis@chromium.org + +# COMPONENT: Internals>Core diff --git a/dom/media/gmp/rlz/README.mozilla b/dom/media/gmp/rlz/README.mozilla new file mode 100644 index 0000000000..4408737a5e --- /dev/null +++ b/dom/media/gmp/rlz/README.mozilla @@ -0,0 +1,4 @@ +Code taken from rlz project in Chromium repository: https://chromium.googlesource.com/chromium/src.git/+/6f3478dfd7d29b9872871718bd08493ed0c8bc8e + +Note: base/ contains wrappers/dummies to provide implementations of the +Chromium APIs that this code relies upon. diff --git a/dom/media/gmp/rlz/lib/assert.h b/dom/media/gmp/rlz/lib/assert.h new file mode 100644 index 0000000000..c64dd7ff82 --- /dev/null +++ b/dom/media/gmp/rlz/lib/assert.h @@ -0,0 +1,14 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef FAKE_ASSERT_H_ +#define FAKE_ASSERT_H_ + +#include <assert.h> + +#define ASSERT_STRING(x) { assert(false); } +#define VERIFY(x) { assert(x); }; + +#endif diff --git a/dom/media/gmp/rlz/lib/crc8.cc b/dom/media/gmp/rlz/lib/crc8.cc new file mode 100644 index 0000000000..fe02eabf1b --- /dev/null +++ b/dom/media/gmp/rlz/lib/crc8.cc @@ -0,0 +1,90 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "rlz/lib/crc8.h" + +namespace { + +// The CRC lookup table used for ATM HES (Polynomial = 0x07). +// These are 256 unique 8-bit values. +const unsigned char kCrcTable[256] = { + 0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15, + 0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D, + 0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65, + 0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D, + 0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5, + 0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD, + 0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85, + 0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD, + 0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2, + 0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA, + 0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2, + 0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A, + 0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32, + 0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A, + 0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42, + 0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A, + 0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C, + 0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4, + 0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC, + 0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4, + 0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C, + 0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44, + 0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C, + 0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34, + 0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B, + 0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63, + 0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B, + 0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13, + 0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB, + 0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83, + 0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB, + 0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3 +}; + +} // namespace anonymous + + +namespace rlz_lib { + +bool Crc8::Generate(const unsigned char *data, int length, + unsigned char* check_sum) { + if (!check_sum) + return false; + + *check_sum = 0; + if (!data) + return false; + + // The inital and final constants are as used in the ATM HEC. + static const unsigned char kInitial = 0x00; + static const unsigned char kFinal = 0x55; + unsigned char crc = kInitial; + for (int i = 0; i < length; ++i) { + crc = kCrcTable[(data[i] ^ crc) & 0xFFU]; + } + + *check_sum = crc ^ kFinal; + return true; +} + +bool Crc8::Verify(const unsigned char* data, int length, + unsigned char check_sum, bool* matches) { + if (!matches) + return false; + + *matches = false; + if (!data) + return false; + + unsigned char calculated_crc; + if (!Generate(data, length, &calculated_crc)) + return false; + + *matches = check_sum == calculated_crc; + + return true; +} + +} // namespace rlz_lib diff --git a/dom/media/gmp/rlz/lib/crc8.h b/dom/media/gmp/rlz/lib/crc8.h new file mode 100644 index 0000000000..6c3c84859b --- /dev/null +++ b/dom/media/gmp/rlz/lib/crc8.h @@ -0,0 +1,24 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Crc8 utility functions. + +#ifndef RLZ_LIB_CRC8_H_ +#define RLZ_LIB_CRC8_H_ + +namespace rlz_lib { +// CRC-8 methods: +class Crc8 { + public: + static bool Generate(const unsigned char* data, + int length, + unsigned char* check_sum); + static bool Verify(const unsigned char* data, + int length, + unsigned char checksum, + bool * matches); +}; +}; // namespace rlz_lib + +#endif // RLZ_LIB_CRC8_H_ diff --git a/dom/media/gmp/rlz/lib/machine_id.cc b/dom/media/gmp/rlz/lib/machine_id.cc new file mode 100644 index 0000000000..b2943f90ff --- /dev/null +++ b/dom/media/gmp/rlz/lib/machine_id.cc @@ -0,0 +1,93 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "rlz/lib/machine_id.h" + +#include <stddef.h> + +#include "rlz/lib/assert.h" +#include "rlz/lib/crc8.h" +#include "rlz/lib/string_utils.h" + +// Note: The original machine_id.cc code depends on Chromium's sha1 implementation. +// Using Mozilla's implmentation as replacement to reduce the dependency of +// some external files. +#include "mozilla/SHA1.h" + +namespace rlz_lib { + +bool GetMachineId(std::string* machine_id) { + if (!machine_id) + return false; + + static std::string calculated_id; + static bool calculated = false; + if (calculated) { + *machine_id = calculated_id; + return true; + } + + std::vector<uint8_t> sid_bytes; + int volume_id; + if (!GetRawMachineId(&sid_bytes, &volume_id)) + return false; + + if (!testing::GetMachineIdImpl(sid_bytes, volume_id, machine_id)) + return false; + + calculated = true; + calculated_id = *machine_id; + return true; +} + +namespace testing { + +bool GetMachineIdImpl(const std::vector<uint8_t>& sid_bytes, + int volume_id, + std::string* machine_id) { + machine_id->clear(); + + // The ID should be the SID hash + the Hard Drive SNo. + checksum byte. + static const int kSizeWithoutChecksum = mozilla::SHA1Sum::kHashSize + sizeof(int); + std::basic_string<unsigned char> id_binary(kSizeWithoutChecksum + 1, 0); + + if (!sid_bytes.empty()) { + // In order to be compatible with the old version of RLZ, the hash of the + // SID must be done with all the original bytes from the unicode string. + // However, the chromebase SHA1 hash function takes only an std::string as + // input, so the unicode string needs to be converted to std::string + // "as is". + size_t byte_count = sid_bytes.size() * sizeof(std::vector<uint8_t>::value_type); + const char* buffer = reinterpret_cast<const char*>(sid_bytes.data()); + + // Note that digest can have embedded nulls. + mozilla::SHA1Sum SHA1; + mozilla::SHA1Sum::Hash hash; + SHA1.update(buffer, byte_count); + SHA1.finish(hash); + std::string digest(reinterpret_cast<char*>(hash), mozilla::SHA1Sum::kHashSize); + VERIFY(digest.size() == mozilla::SHA1Sum::kHashSize); + std::copy(digest.begin(), digest.end(), id_binary.begin()); + } + + // Convert from int to binary (makes big-endian). + for (size_t i = 0; i < sizeof(int); i++) { + int shift_bits = 8 * (sizeof(int) - i - 1); + id_binary[mozilla::SHA1Sum::kHashSize + i] = static_cast<unsigned char>( + (volume_id >> shift_bits) & 0xFF); + } + + // Append the checksum byte. + if (!sid_bytes.empty() || (0 != volume_id)) + rlz_lib::Crc8::Generate(id_binary.c_str(), + kSizeWithoutChecksum, + &id_binary[kSizeWithoutChecksum]); + + return rlz_lib::BytesToString( + id_binary.c_str(), kSizeWithoutChecksum + 1, machine_id); +} + +} // namespace testing + +} // namespace rlz_lib diff --git a/dom/media/gmp/rlz/lib/machine_id.h b/dom/media/gmp/rlz/lib/machine_id.h new file mode 100644 index 0000000000..5fa343efa3 --- /dev/null +++ b/dom/media/gmp/rlz/lib/machine_id.h @@ -0,0 +1,33 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef RLZ_LIB_MACHINE_ID_H_ +#define RLZ_LIB_MACHINE_ID_H_ + +#include <string> +#include <vector> + +namespace rlz_lib { + +// Gets the unique ID for the machine used for RLZ tracking purposes. On +// Windows, this ID is derived from the Windows machine SID, and is the string +// representation of a 20 byte hash + 4 bytes volum id + a 1 byte checksum. +// Included in financial pings with events, unless explicitly forbidden by the +// calling application. +bool GetMachineId(std::string* machine_id); + +// Retrieves a raw machine identifier string and a machine-specific +// 4 byte value. GetMachineId() will SHA1 |data|, append |more_data|, compute +// the Crc8 of that, and return a hex-encoded string of that data. +bool GetRawMachineId(std::vector<uint8_t>* data, int* more_data); + +namespace testing { +bool GetMachineIdImpl(const std::vector<uint8_t>& sid_bytes, + int volume_id, + std::string* machine_id); +} // namespace testing + +} // namespace rlz_lib + +#endif // RLZ_LIB_MACHINE_ID_H_ diff --git a/dom/media/gmp/rlz/lib/string_utils.cc b/dom/media/gmp/rlz/lib/string_utils.cc new file mode 100644 index 0000000000..6da7323823 --- /dev/null +++ b/dom/media/gmp/rlz/lib/string_utils.cc @@ -0,0 +1,34 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// String manipulation functions used in the RLZ library. + +#include "rlz/lib/string_utils.h" + +namespace rlz_lib { + +bool BytesToString(const unsigned char* data, + int data_len, + std::string* string) { + if (!string) + return false; + + string->clear(); + if (data_len < 1 || !data) + return false; + + static const char kHex[] = "0123456789ABCDEF"; + + // Fix the buffer size to begin with to avoid repeated re-allocation. + string->resize(data_len * 2); + int index = data_len; + while (index--) { + string->at(2 * index) = kHex[data[index] >> 4]; // high digit + string->at(2 * index + 1) = kHex[data[index] & 0x0F]; // low digit + } + + return true; +} + +} // namespace rlz_lib diff --git a/dom/media/gmp/rlz/lib/string_utils.h b/dom/media/gmp/rlz/lib/string_utils.h new file mode 100644 index 0000000000..500133ade1 --- /dev/null +++ b/dom/media/gmp/rlz/lib/string_utils.h @@ -0,0 +1,20 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// String manipulation functions used in the RLZ library. + +#ifndef RLZ_LIB_STRING_UTILS_H_ +#define RLZ_LIB_STRING_UTILS_H_ + +#include <string> + +namespace rlz_lib { + +bool BytesToString(const unsigned char* data, + int data_len, + std::string* string); + +}; // namespace + +#endif // RLZ_LIB_STRING_UTILS_H_ diff --git a/dom/media/gmp/rlz/mac/lib/machine_id_mac.cc b/dom/media/gmp/rlz/mac/lib/machine_id_mac.cc new file mode 100644 index 0000000000..8c0bae22e8 --- /dev/null +++ b/dom/media/gmp/rlz/mac/lib/machine_id_mac.cc @@ -0,0 +1,322 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <CoreFoundation/CoreFoundation.h> +#include <IOKit/IOKitLib.h> +#include <IOKit/network/IOEthernetController.h> +#include <IOKit/network/IOEthernetInterface.h> +#include <IOKit/network/IONetworkInterface.h> +#include <stddef.h> +#include <stdint.h> + +#include <vector> +#include <string> +// Note: The original machine_id_mac.cc code is in namespace rlz_lib below. +// It depends on some external files, which would bring in a log of Chromium +// code if imported as well. +// Instead only the necessary code has been extracted from the relevant files, +// and further combined and reduced to limit the maintenance burden. + +// [Extracted from base/logging.h] +#define DCHECK assert + +namespace base { + +// [Extracted from base/mac/scoped_typeref.h and base/mac/scoped_cftyperef.h] +template<typename T> +class ScopedCFTypeRef { + public: + typedef T element_type; + + explicit ScopedCFTypeRef(T object) + : object_(object) { + } + + ScopedCFTypeRef(const ScopedCFTypeRef<T>& that) = delete; + ScopedCFTypeRef(ScopedCFTypeRef<T>&& that) = delete; + + ~ScopedCFTypeRef() { + if (object_) + CFRelease(object_); + } + + ScopedCFTypeRef& operator=(const ScopedCFTypeRef<T>& that) = delete; + ScopedCFTypeRef& operator=(ScopedCFTypeRef<T>&& that) = delete; + + operator T() const { + return object_; + } + + // ScopedCFTypeRef<>::release() is like scoped_ptr<>::release. It is NOT + // a wrapper for CFRelease(). + T release() { + T temp = object_; + object_ = NULL; + return temp; + } + + private: + T object_; +}; + +namespace mac { + +// [Extracted from base/mac/scoped_ioobject.h] +// Just like ScopedCFTypeRef but for io_object_t and subclasses. +template<typename IOT> +class ScopedIOObject { + public: + typedef IOT element_type; + + explicit ScopedIOObject(IOT object = IO_OBJECT_NULL) + : object_(object) { + } + + ~ScopedIOObject() { + if (object_) + IOObjectRelease(object_); + } + + ScopedIOObject(const ScopedIOObject&) = delete; + void operator=(const ScopedIOObject&) = delete; + + void reset(IOT object = IO_OBJECT_NULL) { + if (object_) + IOObjectRelease(object_); + object_ = object; + } + + operator IOT() const { + return object_; + } + + private: + IOT object_; +}; + +// [Extracted from base/mac/foundation_util.h] +template<typename T> +T CFCast(const CFTypeRef& cf_val); + +template<> +CFDataRef +CFCast<CFDataRef>(const CFTypeRef& cf_val) { + if (cf_val == NULL) { + return NULL; + } + if (CFGetTypeID(cf_val) == CFDataGetTypeID()) { + return (CFDataRef)(cf_val); + } + return NULL; +} + +template<> +CFStringRef +CFCast<CFStringRef>(const CFTypeRef& cf_val) { + if (cf_val == NULL) { + return NULL; + } + if (CFGetTypeID(cf_val) == CFStringGetTypeID()) { + return (CFStringRef)(cf_val); + } + return NULL; +} + +} // namespace mac + +// [Extracted from base/strings/sys_string_conversions_mac.mm] +static const CFStringEncoding kNarrowStringEncoding = kCFStringEncodingUTF8; + +template<typename StringType> +static StringType CFStringToSTLStringWithEncodingT(CFStringRef cfstring, + CFStringEncoding encoding) { + CFIndex length = CFStringGetLength(cfstring); + if (length == 0) + return StringType(); + + CFRange whole_string = CFRangeMake(0, length); + CFIndex out_size; + CFIndex converted = CFStringGetBytes(cfstring, + whole_string, + encoding, + 0, // lossByte + false, // isExternalRepresentation + NULL, // buffer + 0, // maxBufLen + &out_size); + if (converted == 0 || out_size == 0) + return StringType(); + + // out_size is the number of UInt8-sized units needed in the destination. + // A buffer allocated as UInt8 units might not be properly aligned to + // contain elements of StringType::value_type. Use a container for the + // proper value_type, and convert out_size by figuring the number of + // value_type elements per UInt8. Leave room for a NUL terminator. + typename StringType::size_type elements = + out_size * sizeof(UInt8) / sizeof(typename StringType::value_type) + 1; + + std::vector<typename StringType::value_type> out_buffer(elements); + converted = CFStringGetBytes(cfstring, + whole_string, + encoding, + 0, // lossByte + false, // isExternalRepresentation + reinterpret_cast<UInt8*>(&out_buffer[0]), + out_size, + NULL); // usedBufLen + if (converted == 0) + return StringType(); + + out_buffer[elements - 1] = '\0'; + return StringType(&out_buffer[0], elements - 1); +} + +std::string SysCFStringRefToUTF8(CFStringRef ref) +{ + return CFStringToSTLStringWithEncodingT<std::string>(ref, + kNarrowStringEncoding); +} + +} // namespace base + +namespace rlz_lib { + +namespace { + +// See http://developer.apple.com/library/mac/#technotes/tn1103/_index.html + +// The caller is responsible for freeing |matching_services|. +bool FindEthernetInterfaces(io_iterator_t* matching_services) { + base::ScopedCFTypeRef<CFMutableDictionaryRef> matching_dict( + IOServiceMatching(kIOEthernetInterfaceClass)); + if (!matching_dict) + return false; + + base::ScopedCFTypeRef<CFMutableDictionaryRef> primary_interface( + CFDictionaryCreateMutable(kCFAllocatorDefault, + 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks)); + if (!primary_interface) + return false; + + CFDictionarySetValue( + primary_interface, CFSTR(kIOPrimaryInterface), kCFBooleanTrue); + CFDictionarySetValue( + matching_dict, CFSTR(kIOPropertyMatchKey), primary_interface); + + kern_return_t kern_result = IOServiceGetMatchingServices( + kIOMasterPortDefault, matching_dict.release(), matching_services); + + return kern_result == KERN_SUCCESS; +} + +bool GetMACAddressFromIterator(io_iterator_t primary_interface_iterator, + uint8_t* buffer, size_t buffer_size) { + if (buffer_size < kIOEthernetAddressSize) + return false; + + bool success = false; + + bzero(buffer, buffer_size); + base::mac::ScopedIOObject<io_object_t> primary_interface; + for (primary_interface.reset(IOIteratorNext(primary_interface_iterator)); + primary_interface; + primary_interface.reset(IOIteratorNext(primary_interface_iterator))) { + io_object_t primary_interface_parent; + kern_return_t kern_result = IORegistryEntryGetParentEntry( + primary_interface, kIOServicePlane, &primary_interface_parent); + base::mac::ScopedIOObject<io_object_t> primary_interface_parent_deleter( + primary_interface_parent); + success = kern_result == KERN_SUCCESS; + + if (!success) + continue; + + base::ScopedCFTypeRef<CFTypeRef> mac_data( + IORegistryEntryCreateCFProperty(primary_interface_parent, + CFSTR(kIOMACAddress), + kCFAllocatorDefault, + 0)); + CFDataRef mac_data_data = base::mac::CFCast<CFDataRef>(mac_data); + if (mac_data_data) { + CFDataGetBytes( + mac_data_data, CFRangeMake(0, kIOEthernetAddressSize), buffer); + } + } + + return success; +} + +bool GetMacAddress(unsigned char* buffer, size_t size) { + io_iterator_t primary_interface_iterator; + if (!FindEthernetInterfaces(&primary_interface_iterator)) + return false; + bool result = GetMACAddressFromIterator( + primary_interface_iterator, buffer, size); + IOObjectRelease(primary_interface_iterator); + return result; +} + +CFStringRef CopySerialNumber() { + base::mac::ScopedIOObject<io_service_t> expert_device( + IOServiceGetMatchingService(kIOMasterPortDefault, + IOServiceMatching("IOPlatformExpertDevice"))); + if (!expert_device) + return NULL; + + base::ScopedCFTypeRef<CFTypeRef> serial_number( + IORegistryEntryCreateCFProperty(expert_device, + CFSTR(kIOPlatformSerialNumberKey), + kCFAllocatorDefault, + 0)); + CFStringRef serial_number_cfstring = + base::mac::CFCast<CFStringRef>(serial_number.release()); + if (!serial_number_cfstring) + return NULL; + + return serial_number_cfstring; +} + +} // namespace + +bool GetRawMachineId(std::vector<uint8_t>* data, int* more_data) { + uint8_t mac_address[kIOEthernetAddressSize]; + + std::string id; + if (GetMacAddress(mac_address, sizeof(mac_address))) { + id += "mac:"; + static const char hex[] = + { '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + for (int i = 0; i < kIOEthernetAddressSize; ++i) { + uint8_t byte = mac_address[i]; + id += hex[byte >> 4]; + id += hex[byte & 0xF]; + } + } + + // A MAC address is enough to uniquely identify a machine, but it's only 6 + // bytes, 3 of which are manufacturer-determined. To make brute-forcing the + // SHA1 of this harder, also append the system's serial number. + CFStringRef serial = CopySerialNumber(); + if (serial) { + if (!id.empty()) { + id += ' '; + } + id += "serial:"; + id += base::SysCFStringRefToUTF8(serial); + CFRelease(serial); + } + + // Get the contents of the string 'id' as a bunch of bytes. + data->assign(&id[0], &id[id.size()]); + + // On windows, this is set to the volume id. Since it's not scrambled before + // being sent, just set it to 1. + *more_data = 1; + return true; +} + +} // namespace rlz_lib diff --git a/dom/media/gmp/rlz/moz.build b/dom/media/gmp/rlz/moz.build new file mode 100644 index 0000000000..8e2d9ea5d1 --- /dev/null +++ b/dom/media/gmp/rlz/moz.build @@ -0,0 +1,34 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# Note: build rlz in its own moz.build, so it doesn't pickup any of +# Chromium IPC's headers used in the moz.build of the parent file. + +FINAL_LIBRARY = 'xul' + +if CONFIG['OS_TARGET'] in ['WINNT', 'Darwin']: + UNIFIED_SOURCES += [ + 'lib/crc8.cc', + 'lib/machine_id.cc', + 'lib/string_utils.cc', + ] + +if CONFIG['OS_TARGET'] == 'WINNT': + UNIFIED_SOURCES += [ + 'win/lib/machine_id_win.cc', + ] + +if CONFIG['OS_TARGET'] == 'Darwin': + UNIFIED_SOURCES += [ + 'mac/lib/machine_id_mac.cc', + ] + OS_LIBS += [ + '-framework IOKit', + ] + +LOCAL_INCLUDES += [ + '..', +] diff --git a/dom/media/gmp/rlz/win/lib/machine_id_win.cc b/dom/media/gmp/rlz/win/lib/machine_id_win.cc new file mode 100644 index 0000000000..85f1d6cf54 --- /dev/null +++ b/dom/media/gmp/rlz/win/lib/machine_id_win.cc @@ -0,0 +1,136 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <windows.h> +#include <sddl.h> // For ConvertSidToStringSidW. + +#include <memory> +#include <string> +#include <vector> + +#include "mozilla/ArrayUtils.h" + +#include "rlz/lib/assert.h" + +namespace rlz_lib { + +namespace { + +bool GetSystemVolumeSerialNumber(int* number) { + if (!number) + return false; + + *number = 0; + + // Find the system root path (e.g: C:\). + wchar_t system_path[MAX_PATH + 1]; + if (!GetSystemDirectoryW(system_path, MAX_PATH)) + return false; + + wchar_t* first_slash = wcspbrk(system_path, L"\\/"); + if (first_slash != NULL) + *(first_slash + 1) = 0; + + DWORD number_local = 0; + if (!GetVolumeInformationW(system_path, NULL, 0, &number_local, NULL, NULL, + NULL, 0)) + return false; + + *number = (int)number_local; + return true; +} + +bool GetComputerSid(const wchar_t* account_name, SID* sid, DWORD sid_size) { + static const DWORD kStartDomainLength = 128; // reasonable to start with + + std::unique_ptr<wchar_t[]> domain_buffer(new wchar_t[kStartDomainLength]); + DWORD domain_size = kStartDomainLength; + DWORD sid_dword_size = sid_size; + SID_NAME_USE sid_name_use; + + BOOL success = ::LookupAccountNameW(NULL, account_name, sid, + &sid_dword_size, domain_buffer.get(), + &domain_size, &sid_name_use); + if (!success && ::GetLastError() == ERROR_INSUFFICIENT_BUFFER) { + // We could have gotten the insufficient buffer error because + // one or both of sid and szDomain was too small. Check for that + // here. + if (sid_dword_size > sid_size) + return false; + + if (domain_size > kStartDomainLength) + domain_buffer.reset(new wchar_t[domain_size]); + + success = ::LookupAccountNameW(NULL, account_name, sid, &sid_dword_size, + domain_buffer.get(), &domain_size, + &sid_name_use); + } + + return success != FALSE; +} + +std::vector<uint8_t> ConvertSidToBytes(SID* sid) { + std::wstring sid_string; +#if _WIN32_WINNT >= 0x500 + wchar_t* sid_buffer = NULL; + if (ConvertSidToStringSidW(sid, &sid_buffer)) { + sid_string = sid_buffer; + LocalFree(sid_buffer); + } +#else + SID_IDENTIFIER_AUTHORITY* sia = ::GetSidIdentifierAuthority(sid); + + if(sia->Value[0] || sia->Value[1]) { + base::SStringPrintf( + &sid_string, L"S-%d-0x%02hx%02hx%02hx%02hx%02hx%02hx", + SID_REVISION, (USHORT)sia->Value[0], (USHORT)sia->Value[1], + (USHORT)sia->Value[2], (USHORT)sia->Value[3], (USHORT)sia->Value[4], + (USHORT)sia->Value[5]); + } else { + ULONG authority = 0; + for (int i = 2; i < 6; ++i) { + authority <<= 8; + authority |= sia->Value[i]; + } + base::SStringPrintf(&sid_string, L"S-%d-%lu", SID_REVISION, authority); + } + + int sub_auth_count = *::GetSidSubAuthorityCount(sid); + for(int i = 0; i < sub_auth_count; ++i) + base::StringAppendF(&sid_string, L"-%lu", *::GetSidSubAuthority(sid, i)); +#endif + + // Get the contents of the string as a bunch of bytes. + return std::vector<uint8_t>( + reinterpret_cast<uint8_t*>(&sid_string[0]), + reinterpret_cast<uint8_t*>(&sid_string[sid_string.size()])); +} + +} // namespace + +bool GetRawMachineId(std::vector<uint8_t>* sid_bytes, int* volume_id) { + // Calculate the Windows SID. + + wchar_t computer_name[MAX_COMPUTERNAME_LENGTH + 1] = {0}; + DWORD size = mozilla::ArrayLength(computer_name); + + if (GetComputerNameW(computer_name, &size)) { + char sid_buffer[SECURITY_MAX_SID_SIZE]; + SID* sid = reinterpret_cast<SID*>(sid_buffer); + if (GetComputerSid(computer_name, sid, SECURITY_MAX_SID_SIZE)) { + *sid_bytes = ConvertSidToBytes(sid); + } + } + + // Get the system drive volume serial number. + *volume_id = 0; + if (!GetSystemVolumeSerialNumber(volume_id)) { + ASSERT_STRING("GetMachineId: Failed to retrieve volume serial number"); + *volume_id = 0; + } + + return true; +} + +} // namespace rlz_lib |