// 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 "base/logging.h"
#include "base/mac/foundation_util.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/mac/scoped_ioobject.h"
#include "base/strings/string16.h"
#include "base/strings/stringprintf.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"

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;
  while (primary_interface.reset(IOIteratorNext(primary_interface_iterator)),
         primary_interface) {
    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);
  if (!serial_number_cfstring)
    return NULL;

  ignore_result(serial_number.release());
  return serial_number_cfstring;
}

}  // namespace

bool GetRawMachineId(base::string16* data, int* more_data) {
  uint8_t mac_address[kIOEthernetAddressSize];

  data->clear();
  if (GetMacAddress(mac_address, sizeof(mac_address))) {
    *data += base::ASCIIToUTF16(
        base::StringPrintf("mac:%02x%02x%02x%02x%02x%02x",
                           mac_address[0], mac_address[1], mac_address[2],
                           mac_address[3], mac_address[4], mac_address[5]));
  }

  // 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 (!data->empty())
      *data += base::UTF8ToUTF16(" ");
    *data += base::UTF8ToUTF16("serial:") + base::SysCFStringRefToUTF16(serial);
    CFRelease(serial);
  }

  // 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
