/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "wifi_system/hostapd_manager.h"

#include <iomanip>
#include <sstream>
#include <string>
#include <vector>

#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/parseint.h>
#include <android-base/stringprintf.h>
#include <cutils/properties.h>
#include <openssl/evp.h>
#include <openssl/sha.h>
#include <private/android_filesystem_config.h>

#include "wifi_system/supplicant_manager.h"

using android::base::ParseInt;
using android::base::ReadFileToString;
using android::base::RemoveFileIfExists;
using android::base::StringPrintf;
using android::base::WriteStringToFile;
using std::string;
using std::vector;
using std::stringstream;

namespace android {
namespace wifi_system {
namespace {

const int kDefaultApChannel = 6;
const char kHostapdServiceName[] = "hostapd";
const char kHostapdConfigFilePath[] = "/data/misc/wifi/hostapd.conf";


string GeneratePsk(const vector<uint8_t>& ssid,
                   const vector<uint8_t>& passphrase) {
  string result;
  unsigned char psk[SHA256_DIGEST_LENGTH];

  // Use the PKCS#5 PBKDF2 with 4096 iterations
  if (PKCS5_PBKDF2_HMAC_SHA1(reinterpret_cast<const char*>(passphrase.data()),
                             passphrase.size(),
                             ssid.data(), ssid.size(),
                             4096, sizeof(psk), psk) != 1) {
    LOG(ERROR) << "Cannot generate PSK using PKCS#5 PBKDF2";
    return result;
  }

  stringstream ss;
  ss << std::hex;
  ss << std::setfill('0');
  for (int j = 0; j < SHA256_DIGEST_LENGTH; j++) {
    ss << std::setw(2) << static_cast<unsigned int>(psk[j]);
  }
  result = ss.str();

  return result;
}

}  // namespace

bool HostapdManager::StartHostapd() {
  if (property_set("ctl.start", kHostapdServiceName) != 0) {
    LOG(ERROR) << "Failed to start SoftAP";
    return false;
  }

  LOG(DEBUG) << "SoftAP started successfully";
  return true;
}

bool HostapdManager::StopHostapd() {
  LOG(DEBUG) << "Stopping the SoftAP service...";

  if (property_set("ctl.stop", kHostapdServiceName) < 0) {
    LOG(ERROR) << "Failed to stop hostapd service!";
    return false;
  }

  LOG(DEBUG) << "SoftAP stopped successfully";
  return true;
}

bool HostapdManager::WriteHostapdConfig(const string& config) {
  // Remove hostapd.conf because its file owner might be system
  // in previous OS and chmod fails in that case.
  RemoveFileIfExists(kHostapdConfigFilePath);
  if (!WriteStringToFile(config, kHostapdConfigFilePath,
                         S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
                         AID_WIFI, AID_WIFI)) {
    int error = errno;
    LOG(ERROR) << "Cannot write hostapd config to \""
               << kHostapdConfigFilePath << "\": " << strerror(error);
    struct stat st;
    int result = stat(kHostapdConfigFilePath, &st);
    if (result == 0) {
      LOG(ERROR) << "hostapd config file uid: "<< st.st_uid << ", gid: " << st.st_gid
                 << ", mode: " << st.st_mode;
    } else {
      LOG(ERROR) << "Error calling stat() on hostapd config file: " << strerror(errno);
    }
    return false;
  }
  return true;
}

string HostapdManager::CreateHostapdConfig(
    const string& interface_name,
    const vector<uint8_t> ssid,
    bool is_hidden,
    int channel,
    EncryptionType encryption_type,
    const vector<uint8_t> passphrase) {
  string result;

  if (channel < 0) {
    channel = kDefaultApChannel;
  }

  if (ssid.size() > 32) {
    LOG(ERROR) << "SSIDs must be <= 32 bytes long";
    return result;
  }

  stringstream ss;
  ss << std::hex;
  ss << std::setfill('0');
  for (uint8_t b : ssid) {
    ss << std::setw(2) << static_cast<unsigned int>(b);
  }
  const string ssid_as_string  = ss.str();

  string encryption_config;
  if (encryption_type != EncryptionType::kOpen) {
    string psk = GeneratePsk(ssid, passphrase);
    if (psk.empty()) {
      return result;
    }
    if (encryption_type == EncryptionType::kWpa) {
      encryption_config = StringPrintf("wpa=3\n"
                                       "wpa_pairwise=TKIP CCMP\n"
                                       "wpa_psk=%s\n", psk.c_str());
    } else if (encryption_type == EncryptionType::kWpa2) {
      encryption_config = StringPrintf("wpa=2\n"
                                       "rsn_pairwise=CCMP\n"
                                       "wpa_psk=%s\n", psk.c_str());
    } else {
      using encryption_t = std::underlying_type<EncryptionType>::type;
      LOG(ERROR) << "Unknown encryption type ("
                 << static_cast<encryption_t>(encryption_type)
                 << ")";
      return result;
    }
  }

  result = StringPrintf(
      "interface=%s\n"
      "driver=nl80211\n"
      "ctrl_interface=/data/misc/wifi/hostapd/ctrl\n"
      // ssid2 signals to hostapd that the value is not a literal value
      // for use as a SSID.  In this case, we're giving it a hex string
      // and hostapd needs to expect that.
      "ssid2=%s\n"
      "channel=%d\n"
      "ieee80211n=1\n"
      "hw_mode=%c\n"
      "ignore_broadcast_ssid=%d\n"
      "wowlan_triggers=any\n"
      "%s",
      interface_name.c_str(),
      ssid_as_string.c_str(),
      channel,
      (channel <= 14) ? 'g' : 'a',
      (is_hidden) ? 1 : 0,
      encryption_config.c_str());
  return result;
}

}  // namespace wifi_system
}  // namespace android
