This source file includes following definitions.
- IsValidMacAddress
- ProcessAdapterAddress
- ProcessInterfaceRow
- mac_address
- ProcessPhysicalAddress
- GetMacAddressFromGetAdaptersAddresses
- GetMacAddressFromGetIfTable2
- GetLegacyDeviceId
#include "chrome/browser/prefs/tracked/pref_hash_calculator_helper.h"
#include <winsock2.h>
#include <ws2def.h>
#include <ws2ipdef.h>
#include <iphlpapi.h>
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/scoped_native_library.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/threading/thread_restrictions.h"
#include "net/base/net_util.h"
namespace {
bool IsValidMacAddress(const void* bytes, size_t size) {
const size_t MAC_LENGTH = 6;
const size_t OUI_LENGTH = 3;
struct InvalidMacEntry {
size_t size;
unsigned char address[MAC_LENGTH];
};
static const InvalidMacEntry kInvalidAddresses[] = {
{MAC_LENGTH, {0, 0, 0, 0, 0, 0}},
{OUI_LENGTH, {0x00, 0x50, 0x56}},
{OUI_LENGTH, {0x00, 0x05, 0x69}},
{OUI_LENGTH, {0x00, 0x0c, 0x29}},
{OUI_LENGTH, {0x00, 0x1c, 0x14}},
{OUI_LENGTH, {0x08, 0x00, 0x27}},
{MAC_LENGTH, {0x00, 0x26, 0x37, 0xbd, 0x39, 0x42}},
{MAC_LENGTH, {0x00, 0x05, 0x9a, 0x3c, 0x7a, 0x00}},
{MAC_LENGTH, {0x00, 0x11, 0x22, 0x33, 0x44, 0x55}},
{MAC_LENGTH-1, {0x65, 0x90, 0x07, 0x42, 0xf1}},
{2, {0x00, 0xff}},
{MAC_LENGTH, {0x00, 0xa0, 0xc6, 0x00, 0x00, 0x00}},
{MAC_LENGTH, {0x00, 0x15, 0x83, 0x3d, 0x0a, 0x57}},
{MAC_LENGTH, {0x20, 0x41, 0x53, 0x59, 0x4e, 0xff}},
{MAC_LENGTH, {0x00, 0xa0, 0xc6, 0x00, 0x00, 0x00}},
{MAC_LENGTH, {0x00, 0x53, 0x45, 0x00, 0x00, 0x00}},
{MAC_LENGTH, {0x00, 0x1f, 0x81, 0x00, 0x08, 0x30}},
{MAC_LENGTH, {0x00, 0x1b, 0x10, 0x00, 0x2a, 0xec}},
{MAC_LENGTH, {0x00, 0x15, 0x83, 0x15, 0xa3, 0x10}},
{MAC_LENGTH, {0x00, 0x15, 0x83, 0x07, 0xC6, 0x5A}},
{MAC_LENGTH, {0x00, 0x1f, 0x81, 0x00, 0x02, 0x00}},
{MAC_LENGTH, {0x00, 0x1f, 0x81, 0x00, 0x02, 0xdd}},
{MAC_LENGTH, {0x00, 0x22, 0x2c, 0xff, 0xff, 0xff}},
{MAC_LENGTH, {0x54, 0x55, 0x43, 0x44, 0x52, 0x09}},
{MAC_LENGTH, {0x54, 0xEF, 0x14, 0x71, 0xE4, 0x0E}},
{MAC_LENGTH, {0x54, 0xBA, 0xC6, 0xFF, 0x74, 0x10}},
{MAC_LENGTH, {0x00, 0x05, 0x9a, 0x3c, 0x7a, 0x00}},
{MAC_LENGTH, {0x00, 0x05, 0x9a, 0x3c, 0x78, 0x00}},
{MAC_LENGTH, {0x00, 0x1e, 0x10, 0x1f, 0x00, 0x01}},
{MAC_LENGTH, {0x80, 0x00, 0x60, 0x0f, 0xe8, 0x00}},
{MAC_LENGTH, {0x44, 0x45, 0x53, 0x54, 0x42, 0x00}},
{MAC_LENGTH, {0x00, 0x30, 0x70, 0x00, 0x00, 0x01}},
{MAC_LENGTH, {0x00, 0x02, 0x03, 0x04, 0x05, 0x06}},
{MAC_LENGTH, {0x00, 0x15, 0x83, 0x0B, 0x13, 0xC0}},
{MAC_LENGTH, {0x44, 0x45, 0x53, 0x54, 0x4f, 0x53}},
{OUI_LENGTH, {0x00, 0xA0, 0xD5}},
{MAC_LENGTH, {0x00, 0x04, 0x0E, 0xFF, 0xFF, 0xFF}},
{MAC_LENGTH, {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}},
{MAC_LENGTH, {0x00, 0x1F, 0x81, 0x00, 0x01, 0x00}},
{MAC_LENGTH, {0x00, 0x30, 0x91, 0x10, 0x00, 0x26}},
{MAC_LENGTH, {0x00, 0x25, 0x00, 0x5A, 0xC3, 0xD0}},
{MAC_LENGTH, {0x00, 0x15, 0x83, 0x0C, 0xBF, 0xEB}},
{MAC_LENGTH, {0x58, 0x2C, 0x80, 0x13, 0x92, 0x63}},
{OUI_LENGTH, {0x00, 0x09, 0x0F}},
{MAC_LENGTH, {0x00, 0x00, 0x00, 0x00, 0x00, 0x30}},
{MAC_LENGTH, {0x00, 0x11, 0xf5, 0x0d, 0x8a, 0xe8}},
{MAC_LENGTH, {0x00, 0x20, 0x07, 0x01, 0x16, 0x06}},
{MAC_LENGTH, {0x0d, 0x0b, 0x00, 0x00, 0xe0, 0x00}},
{MAC_LENGTH, {0x90, 0x4c, 0xe5, 0x0b, 0xc8, 0x8e}},
{MAC_LENGTH, {0x00, 0x1c, 0x23, 0x38, 0x49, 0xa4}},
{MAC_LENGTH, {0x00, 0x12, 0x3f, 0x82, 0x7c, 0x32}},
{MAC_LENGTH, {0x00, 0x11, 0x11, 0x32, 0xc3, 0x77}},
{MAC_LENGTH, {0x00, 0x24, 0xd6, 0xae, 0x3e, 0x39}},
{MAC_LENGTH, {0x00, 0x0f, 0xb0, 0x3a, 0xb4, 0x80}},
{MAC_LENGTH, {0x08, 0x10, 0x74, 0xa1, 0xda, 0x1b}},
{MAC_LENGTH, {0x00, 0x21, 0x9b, 0x2a, 0x0a, 0x9c}},
};
if (size != MAC_LENGTH) {
return false;
}
if (static_cast<const unsigned char *>(bytes)[0] & 0x02) {
return false;
}
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kInvalidAddresses); ++i) {
size_t count = kInvalidAddresses[i].size;
if (memcmp(kInvalidAddresses[i].address, bytes, count) == 0) {
return false;
}
}
return true;
}
class MacAddressProcessor {
public:
MacAddressProcessor() : found_index_(ULONG_MAX) {}
void ProcessAdapterAddress(PIP_ADAPTER_ADDRESSES address) {
if (address->IfType == IF_TYPE_TUNNEL)
return;
ProcessPhysicalAddress(address->IfIndex,
address->PhysicalAddress,
address->PhysicalAddressLength);
}
void ProcessInterfaceRow(const PMIB_IF_ROW2 row) {
if (row->Type == IF_TYPE_TUNNEL ||
!row->InterfaceAndOperStatusFlags.HardwareInterface) {
return;
}
ProcessPhysicalAddress(row->InterfaceIndex,
row->PhysicalAddress,
row->PhysicalAddressLength);
}
std::string mac_address() const { return found_mac_address_; }
private:
void ProcessPhysicalAddress(NET_IFINDEX index,
const void* bytes,
size_t size) {
if (index >= found_index_ || size == 0)
return;
if (!IsValidMacAddress(bytes, size))
return;
found_mac_address_ = StringToLowerASCII(base::HexEncode(bytes, size));
found_index_ = index;
}
std::string found_mac_address_;
NET_IFINDEX found_index_;
};
std::string GetMacAddressFromGetAdaptersAddresses() {
base::ThreadRestrictions::AssertIOAllowed();
ULONG bufferSize = 15 * 1024;
ULONG flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_DNS_SERVER |
GAA_FLAG_SKIP_FRIENDLY_NAME | GAA_FLAG_SKIP_MULTICAST |
GAA_FLAG_SKIP_UNICAST;
std::vector<unsigned char> buffer(bufferSize);
PIP_ADAPTER_ADDRESSES adapterAddresses =
reinterpret_cast<PIP_ADAPTER_ADDRESSES>(&buffer.front());
DWORD result = GetAdaptersAddresses(AF_UNSPEC, flags, 0,
adapterAddresses, &bufferSize);
if (result == ERROR_BUFFER_OVERFLOW) {
buffer.resize(bufferSize);
adapterAddresses =
reinterpret_cast<PIP_ADAPTER_ADDRESSES>(&buffer.front());
result = GetAdaptersAddresses(AF_UNSPEC, flags, 0,
adapterAddresses, &bufferSize);
}
if (result != NO_ERROR) {
VLOG(ERROR) << "GetAdapatersAddresses failed with error " << result;
return "";
}
MacAddressProcessor processor;
for (; adapterAddresses != NULL; adapterAddresses = adapterAddresses->Next) {
processor.ProcessAdapterAddress(adapterAddresses);
}
return processor.mac_address();
}
std::string GetMacAddressFromGetIfTable2() {
base::ThreadRestrictions::AssertIOAllowed();
base::ScopedNativeLibrary library(base::FilePath(L"Iphlpapi.dll"));
typedef DWORD (NETIOAPI_API_ *GetIfTablePtr)(PMIB_IF_TABLE2*);
typedef void (NETIOAPI_API_ *FreeMibTablePtr)(PMIB_IF_TABLE2);
GetIfTablePtr getIfTable = reinterpret_cast<GetIfTablePtr>(
library.GetFunctionPointer("GetIfTable2"));
FreeMibTablePtr freeMibTablePtr = reinterpret_cast<FreeMibTablePtr>(
library.GetFunctionPointer("FreeMibTable"));
if (getIfTable == NULL || freeMibTablePtr == NULL) {
VLOG(ERROR) << "Could not get proc addresses for machine identifier.";
return "";
}
PMIB_IF_TABLE2 ifTable = NULL;
DWORD result = getIfTable(&ifTable);
if (result != NO_ERROR || ifTable == NULL) {
VLOG(ERROR) << "GetIfTable failed with error " << result;
return "";
}
MacAddressProcessor processor;
for (size_t i = 0; i < ifTable->NumEntries; i++) {
processor.ProcessInterfaceRow(&(ifTable->Table[i]));
}
if (ifTable != NULL) {
freeMibTablePtr(ifTable);
ifTable = NULL;
}
return processor.mac_address();
}
}
std::string GetLegacyDeviceId(const std::string& modern_device_id) {
base::ThreadRestrictions::AssertIOAllowed();
if (modern_device_id.empty())
return std::string();
std::string mac_address = GetMacAddressFromGetAdaptersAddresses();
if (mac_address.empty()) {
mac_address = GetMacAddressFromGetIfTable2();
if (mac_address.empty())
return std::string();
}
return mac_address + modern_device_id;
}