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

#include "dse_auth_gssapi.hpp"
#include "logger.hpp"
#include "scoped_ptr.hpp"
#include "string_ref.hpp"

#include <string.h>

#include <gssapi/gssapi.h>
#include <gssapi/gssapi_generic.h>
#include <gssapi/gssapi_krb5.h>

#define DSE_AUTHENTICATOR "com.datastax.bdp.cassandra.auth.DseAuthenticator"

#define GSSAPI_AUTH_MECHANISM "GSSAPI"
#define GSSAPI_AUTH_SERVER_INITIAL_CHALLENGE "GSSAPI-START"

#define PLAINTEXT_AUTH_MECHANISM "PLAIN"
#define PLAINTEXT_AUTH_SERVER_INITIAL_CHALLENGE "PLAIN-START"

using namespace datastax;
using namespace datastax::internal::core;
using namespace datastax::internal::enterprise;

static void dse_gssapi_authenticator_nop_lock(void* data) {}
static void dse_gssapi_authenticator_nop_unlock(void* data) {}

struct GssapiBuffer {
public:
  gss_buffer_desc buffer;

public:
  GssapiBuffer() {
    buffer.value = NULL;
    buffer.length = 0;
  }

  ~GssapiBuffer() { release(); }

  const unsigned char* value() const { return static_cast<const unsigned char*>(buffer.value); }

  const char* data() const { return static_cast<const char*>(buffer.value); }

  size_t length() const { return buffer.length; }

  bool is_empty() const { return buffer.length == 0; }

  void release() {
    if (buffer.value) {
      OM_uint32 min_stat;

      DseGssapiAuthenticator::lock();
      gss_release_buffer(&min_stat, &buffer);
      DseGssapiAuthenticator::unlock();
    }
  }
};

class GssapiName {
public:
  gss_name_t name;

public:
  GssapiName()
      : name(GSS_C_NO_NAME) {}

  ~GssapiName() { release(); }

  void release() {
    if (name != GSS_C_NO_NAME) {
      OM_uint32 min_stat;

      DseGssapiAuthenticator::lock();
      gss_release_name(&min_stat, &name);
      DseGssapiAuthenticator::unlock();
    }
  }
};

namespace datastax { namespace internal { namespace enterprise {

class GssapiAuthenticatorImpl : public Allocated {
public:
  enum State { NEGOTIATION, AUTHENTICATION, AUTHENTICATED };

  enum Result { RESULT_ERROR, RESULT_CONTINUE, RESULT_COMPLETE };

  enum Type { AUTH_NONE = 1, AUTH_INTEGRITY = 2, AUTH_CONFIDENTIALITY = 3 };

  GssapiAuthenticatorImpl(const String& authorization_id);
  ~GssapiAuthenticatorImpl();

  const String& response() const { return response_; }
  const String& error() const { return error_; }

  Result init(const String& service, const String& principal);
  Result process(const String& token);

private:
  Result negotiate(gss_buffer_t challenge_token);
  Result authenticate(gss_buffer_t challenge_token);

  static String display_status(OM_uint32 maj, OM_uint32 min);

private:
  gss_ctx_id_t context_;
  gss_name_t server_name_;
  OM_uint32 gss_flags_;
  gss_cred_id_t client_creds_;
  String username_;
  String response_;
  String error_;
  State state_;
  String authorization_id_;
};

}}} // namespace datastax::internal::enterprise

GssapiAuthenticatorImpl::GssapiAuthenticatorImpl(const String& authorization_id)
    : context_(GSS_C_NO_CONTEXT)
    , server_name_(GSS_C_NO_NAME)
    , gss_flags_(GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG)
    , client_creds_(GSS_C_NO_CREDENTIAL)
    , state_(NEGOTIATION)
    , authorization_id_(authorization_id) {}

GssapiAuthenticatorImpl::~GssapiAuthenticatorImpl() {
  OM_uint32 min_stat;

  if (context_ != GSS_C_NO_CONTEXT) {
    DseGssapiAuthenticator::lock();
    gss_delete_sec_context(&min_stat, &context_, GSS_C_NO_BUFFER);
    DseGssapiAuthenticator::unlock();
  }

  if (server_name_ != GSS_C_NO_NAME) {
    DseGssapiAuthenticator::lock();
    gss_release_name(&min_stat, &server_name_);
    DseGssapiAuthenticator::unlock();
  }

  if (client_creds_ != GSS_C_NO_CREDENTIAL) {
    DseGssapiAuthenticator::lock();
    gss_release_cred(&min_stat, &client_creds_);
    DseGssapiAuthenticator::unlock();
  }
}

GssapiAuthenticatorImpl::Result GssapiAuthenticatorImpl::init(const String& service,
                                                              const String& principal) {
  OM_uint32 maj_stat;
  OM_uint32 min_stat;
  gss_buffer_desc name_token = GSS_C_EMPTY_BUFFER;

  name_token.value = const_cast<void*>(static_cast<const void*>(service.c_str()));
  name_token.length = service.size();

  DseGssapiAuthenticator::lock();
  maj_stat = gss_import_name(&min_stat, &name_token, GSS_C_NT_HOSTBASED_SERVICE, &server_name_);
  DseGssapiAuthenticator::unlock();

  if (GSS_ERROR(maj_stat)) {
    error_.assign("Failed to import server name (gss_import_name()): " +
                  display_status(maj_stat, min_stat));
    return RESULT_ERROR;
  }

  GssapiName principal_name; // Initialized to GSS_C_NO_NAME

  if (!principal.empty()) {
    gss_buffer_desc principal_token = GSS_C_EMPTY_BUFFER;

    principal_token.value = const_cast<void*>(static_cast<const void*>(principal.c_str()));
    principal_token.length = principal.size();

    DseGssapiAuthenticator::lock();
    maj_stat =
        gss_import_name(&min_stat, &principal_token, GSS_C_NT_USER_NAME, &principal_name.name);
    DseGssapiAuthenticator::unlock();

    if (GSS_ERROR(maj_stat)) {
      error_.assign("Failed to import principal name (gss_import_name()): " +
                    display_status(maj_stat, min_stat));
      return RESULT_ERROR;
    }
  }

  DseGssapiAuthenticator::lock();
  maj_stat = gss_acquire_cred(&min_stat, principal_name.name, GSS_C_INDEFINITE, GSS_C_NO_OID_SET,
                              GSS_C_INITIATE, &client_creds_, NULL, NULL);
  DseGssapiAuthenticator::unlock();

  if (GSS_ERROR(maj_stat)) {
    error_.assign("Failed to acquire principal credentials (gss_acquire_cred()): " +
                  display_status(maj_stat, min_stat));
    return RESULT_ERROR;
  }

  return RESULT_COMPLETE;
}

GssapiAuthenticatorImpl::Result GssapiAuthenticatorImpl::negotiate(gss_buffer_t challenge_token) {
  OM_uint32 maj_stat;
  OM_uint32 min_stat;
  GssapiBuffer output_token;
  Result result = RESULT_ERROR;

  DseGssapiAuthenticator::lock();
  maj_stat = gss_init_sec_context(&min_stat, client_creds_, &context_, server_name_, GSS_C_NO_OID,
                                  gss_flags_, 0, GSS_C_NO_CHANNEL_BINDINGS, challenge_token, NULL,
                                  &output_token.buffer, NULL, NULL);
  DseGssapiAuthenticator::unlock();

  if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED) {
    error_.assign("Failed to initalize security context (gss_init_sec_context()): " +
                  display_status(maj_stat, min_stat));
    return RESULT_ERROR;
  }

  result = (maj_stat == GSS_S_COMPLETE) ? RESULT_COMPLETE : RESULT_CONTINUE;

  if (!output_token.is_empty()) {
    response_.assign(output_token.data(), output_token.length());
  }

  if (result == RESULT_COMPLETE) {
    GssapiName user;

    DseGssapiAuthenticator::lock();
    maj_stat =
        gss_inquire_context(&min_stat, context_, &user.name, NULL, NULL, NULL, NULL, NULL, NULL);
    DseGssapiAuthenticator::unlock();

    if (GSS_ERROR(maj_stat)) {
      error_.assign(
          "Failed to inquire security context for user principal (gss_inquire_context()): " +
          display_status(maj_stat, min_stat));
      return RESULT_ERROR;
    }

    GssapiBuffer user_token;

    DseGssapiAuthenticator::lock();
    maj_stat = gss_display_name(&min_stat, user.name, &user_token.buffer, NULL);
    DseGssapiAuthenticator::unlock();

    if (GSS_ERROR(maj_stat)) {
      error_.assign("Failed to get display name for user principal (gss_inquire_context()): " +
                    display_status(maj_stat, min_stat));
      return RESULT_ERROR;
    } else {
      username_.assign(user_token.data(), user_token.length());
      state_ = AUTHENTICATION;
    }
  }

  return result;
}

GssapiAuthenticatorImpl::Result
GssapiAuthenticatorImpl::authenticate(gss_buffer_t challenge_token) {
  OM_uint32 maj_stat;
  OM_uint32 min_stat;
  OM_uint32 req_output_size;
  OM_uint32 max_input_size;
  unsigned char qop;
  String input;
  gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
  GssapiBuffer output_token;

  DseGssapiAuthenticator::lock();
  maj_stat = gss_unwrap(&min_stat, context_, challenge_token, &output_token.buffer, NULL, NULL);
  DseGssapiAuthenticator::unlock();

  if (GSS_ERROR(maj_stat)) {
    error_.assign("Failed to get unwrap challenge token (gss_unwrap()): " +
                  display_status(maj_stat, min_stat));
    return RESULT_ERROR;
  }

  if (output_token.length() != 4) {
    return RESULT_ERROR;
  }

  qop = output_token.value()[0];
  if (qop & AUTH_CONFIDENTIALITY) {
    qop = AUTH_CONFIDENTIALITY;
  } else if (qop & AUTH_INTEGRITY) {
    qop = AUTH_INTEGRITY;
  } else {
    qop = AUTH_NONE;
  }

  req_output_size = ((output_token.value())[1] << 16) | ((output_token.value())[2] << 8) |
                    ((output_token.value())[3] << 0);

  req_output_size = req_output_size & 0xFFFFFF;

  DseGssapiAuthenticator::lock();
  maj_stat = gss_wrap_size_limit(&min_stat, context_, 1, GSS_C_QOP_DEFAULT, req_output_size,
                                 &max_input_size);
  DseGssapiAuthenticator::unlock();

  if (max_input_size < req_output_size) {
    req_output_size = max_input_size;
  }

  input.push_back(qop);
  input.push_back((req_output_size >> 16) & 0xFF);
  input.push_back((req_output_size >> 8) & 0xFF);
  input.push_back((req_output_size >> 0) & 0xFF);

  // Send the authorization_id if present (proxy login), otherwise the username.
  const String& authorization_id = authorization_id_.empty() ? username_ : authorization_id_;
  input.append(authorization_id);

  input_token.length = 4 + authorization_id.size();
  input_token.value = const_cast<void*>(static_cast<const void*>(input.c_str()));

  output_token.release();

  DseGssapiAuthenticator::lock();
  maj_stat =
      gss_wrap(&min_stat, context_, 0, GSS_C_QOP_DEFAULT, &input_token, NULL, &output_token.buffer);
  DseGssapiAuthenticator::unlock();

  if (GSS_ERROR(maj_stat)) {
    error_.assign("Failed to get wrape response token (gss_wrap()): " +
                  display_status(maj_stat, min_stat));
    return RESULT_ERROR;
  }

  if (!output_token.is_empty()) {
    response_.assign(output_token.data(), output_token.length());
  }

  state_ = AUTHENTICATED;

  return RESULT_COMPLETE;
}

String GssapiAuthenticatorImpl::display_status(OM_uint32 maj, OM_uint32 min) {
  String error;
  OM_uint32 message_context;

  message_context = 0;

  do {
    GssapiBuffer message;
    OM_uint32 maj_stat, min_stat;

    DseGssapiAuthenticator::lock();
    maj_stat = gss_display_status(&min_stat, maj, GSS_C_GSS_CODE, GSS_C_NO_OID, &message_context,
                                  &message.buffer);
    DseGssapiAuthenticator::unlock();

    if (GSS_ERROR(maj_stat)) {
      error.append("GSSAPI error: (unable to get major error)");
      break;
    }

    error.append(message.data(), message.length());
  } while (message_context != 0);

  message_context = 0;

  error.append(" (");
  do {
    GssapiBuffer message;
    OM_uint32 maj_stat, min_stat;

    DseGssapiAuthenticator::lock();
    maj_stat = gss_display_status(&min_stat, min, GSS_C_MECH_CODE, GSS_C_NO_OID, &message_context,
                                  &message.buffer);
    DseGssapiAuthenticator::unlock();

    if (GSS_ERROR(maj_stat)) {
      error.append("GSSAPI error: (unable to get minor error)");
      break;
    }

    error.append(message.data(), message.length());
  } while (message_context != 0);
  error.append(" )");

  return error;
}

GssapiAuthenticatorImpl::Result GssapiAuthenticatorImpl::process(const String& token) {
  Result result = RESULT_ERROR;
  gss_buffer_desc challenge_token = GSS_C_EMPTY_BUFFER;

  response_.clear();

  if (!token.empty()) {
    challenge_token.value = const_cast<char*>(token.c_str());
    challenge_token.length = token.length();
  }

  switch (state_) {
    case NEGOTIATION:
      result = negotiate(&challenge_token);
      break;

    case AUTHENTICATION:
      result = authenticate(&challenge_token);
      break;

    default:
      break;
  }

  return result;
}

DseGssapiAuthenticatorLockCallback DseGssapiAuthenticator::lock_callback_ =
    dse_gssapi_authenticator_nop_lock;
DseGssapiAuthenticatorUnlockCallback DseGssapiAuthenticator::unlock_callback_ =
    dse_gssapi_authenticator_nop_unlock;
void* DseGssapiAuthenticator::data_ = NULL;

CassError
DseGssapiAuthenticator::set_lock_callbacks(DseGssapiAuthenticatorLockCallback lock_callback,
                                           DseGssapiAuthenticatorUnlockCallback unlock_callback,
                                           void* data) {
  if (lock_callback == NULL || unlock_callback == NULL || data_ == NULL) {
    lock_callback_ = dse_gssapi_authenticator_nop_lock;
    unlock_callback_ = dse_gssapi_authenticator_nop_unlock;
    data_ = NULL;
    return CASS_ERROR_LIB_BAD_PARAMS;
  } else {
    lock_callback_ = lock_callback;
    unlock_callback_ = unlock_callback;
    data_ = data;
    return CASS_OK;
  }
}

DseGssapiAuthenticator::DseGssapiAuthenticator(const Address& address, const String& hostname,
                                               const String& class_name, const String& service,
                                               const String& principal,
                                               const String& authorization_id)
    : address_(address)
    , hostname_(hostname)
    , class_name_(class_name)
    , service_(service)
    , principal_(principal)
    , authorization_id_(authorization_id)
    , impl_(new GssapiAuthenticatorImpl(authorization_id)) {}

bool DseGssapiAuthenticator::initial_response(String* response) {

  String service;

  if (hostname_.empty()) {
    service.append(service_);
    service.append("@");
    service.append(address_.to_string());
  } else {
    service.append(service_);
    service.append("@");
    service.append(hostname_);
  }

  if (impl_->init(service, principal_) == GssapiAuthenticatorImpl::RESULT_ERROR) {
    set_error("Unable to initialize GSSAPI: " + impl_->error());
    return false;
  }

  if (class_name_ == DSE_AUTHENTICATOR) {
    response->assign(GSSAPI_AUTH_MECHANISM);
    return true;
  } else {
    return evaluate_challenge(GSSAPI_AUTH_SERVER_INITIAL_CHALLENGE, response);
  }
}

bool DseGssapiAuthenticator::evaluate_challenge(const String& token, String* response) {
  if (token == GSSAPI_AUTH_SERVER_INITIAL_CHALLENGE) {
    if (impl_->process(String()) == GssapiAuthenticatorImpl::RESULT_ERROR) {
      set_error("GSSAPI initial handshake failed: " + impl_->error());
      return false;
    }
  } else {
    if (impl_->process(token) == GssapiAuthenticatorImpl::RESULT_ERROR) {
      set_error("GSSAPI challenge handshake failed: " + impl_->error());
      return false;
    }
  }
  *response = impl_->response();
  return true;
}

bool DseGssapiAuthenticator::success(const String& token) {
  // no-op
  return true;
}
