// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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.

#pragma once

#include "kudu/util/openssl_util.h"

#include <string>

#include <glog/logging.h>
#include <openssl/bio.h>
#include <openssl/buffer.h>

#include "kudu/gutil/strings/substitute.h"
#include "kudu/util/status.h"

namespace kudu {
namespace security {


template<typename TYPE, typename Traits = SslTypeTraits<TYPE>>
Status ToBIO(BIO* bio, DataFormat format, TYPE* obj) {
  CHECK(bio);
  CHECK(obj);
  switch (format) {
    case DataFormat::DER:
      OPENSSL_RET_NOT_OK(Traits::kWriteDerFunc(bio, obj),
          "error exporting data in DER format");
      break;
    case DataFormat::PEM:
      OPENSSL_RET_NOT_OK(Traits::kWritePemFunc(bio, obj),
          "error exporting data in PEM format");
      break;
  }
  OPENSSL_RET_NOT_OK(BIO_flush(bio), "error flushing BIO");
  return Status::OK();
}

// The callback which is called by the OpenSSL library when trying to decrypt
// a password protected private key.
inline int TLSPasswordCB(char* buf, int size, int /* rwflag */, void* userdata) {
  const auto* cb = reinterpret_cast<const PasswordCallback*>(userdata);
  std::string pw = (*cb)();
  if (pw.size() >= size) {
    LOG(ERROR) << "Provided key password is longer than maximum length "
               << size;
    return -1;
  }
  strncpy(buf, pw.c_str(), size);
  return pw.size();
}

template<typename TYPE, typename Traits = SslTypeTraits<TYPE>>
Status FromBIO(BIO* bio, DataFormat format, c_unique_ptr<TYPE>* ret,
    const PasswordCallback& cb = PasswordCallback()) {
  CHECK(bio);
  switch (format) {
    case DataFormat::DER:
      *ret = ssl_make_unique(Traits::kReadDerFunc(bio, nullptr));
      break;
    case DataFormat::PEM:
      *ret = ssl_make_unique(Traits::kReadPemFunc(bio, nullptr, &TLSPasswordCB,
          const_cast<PasswordCallback*>(&cb)));
      break;
  }
  if (PREDICT_FALSE(!*ret)) {
    return Status::RuntimeError(GetOpenSSLErrors());
  }
  return Status::OK();
}

template<typename Type, typename Traits = SslTypeTraits<Type>>
Status FromString(const std::string& data, DataFormat format,
                  c_unique_ptr<Type>* ret) {
  const void* mdata = reinterpret_cast<const void*>(data.data());
  auto bio = ssl_make_unique(BIO_new_mem_buf(
#if OPENSSL_VERSION_NUMBER < 0x10002000L
      const_cast<void*>(mdata),
#else
      mdata,
#endif
      data.size()));
  RETURN_NOT_OK_PREPEND((FromBIO<Type, Traits>(bio.get(), format, ret)),
                        "unable to load data from memory");
  return Status::OK();
}

template<typename Type, typename Traits = SslTypeTraits<Type>>
Status ToString(std::string* data, DataFormat format, Type* obj) {
  CHECK(data);
  auto bio = ssl_make_unique(BIO_new(BIO_s_mem()));
  RETURN_NOT_OK_PREPEND((ToBIO<Type, Traits>(bio.get(), format, obj)),
                        "error serializing data");
  BUF_MEM* membuf;
  OPENSSL_CHECK_OK(BIO_get_mem_ptr(bio.get(), &membuf));
  data->assign(membuf->data, membuf->length);
  return Status::OK();
}

template<typename Type, typename Traits = SslTypeTraits<Type>>
Status FromFile(const std::string& fpath, DataFormat format,
                c_unique_ptr<Type>* ret, const PasswordCallback& cb = PasswordCallback()) {
  auto bio = ssl_make_unique(BIO_new(BIO_s_file()));
  OPENSSL_RET_NOT_OK(BIO_read_filename(bio.get(), fpath.c_str()),
      strings::Substitute("could not read data from file '$0'", fpath));
  RETURN_NOT_OK_PREPEND((FromBIO<Type, Traits>(bio.get(), format, ret, cb)),
      strings::Substitute("unable to load data from file '$0'", fpath));
  return Status::OK();
}

} // namespace security
} // namespace kudu
