// 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 "kudu/rpc/sasl_helper.h"

#include <cstring>
#include <ostream>
#include <set>
#include <string>

#include <glog/logging.h>
#include <sasl/sasl.h>

#include "kudu/gutil/map-util.h"
#include "kudu/gutil/port.h"
#include "kudu/gutil/strings/join.h"
#include "kudu/gutil/strings/substitute.h"
#include "kudu/rpc/constants.h"
#include "kudu/rpc/rpc_header.pb.h"
#include "kudu/rpc/sasl_common.h"
#include "kudu/util/slice.h"
#include "kudu/util/status.h"

using std::string;

namespace kudu {
namespace rpc {

SaslHelper::SaslHelper(PeerType peer_type)
  : peer_type_(peer_type),
    global_mechs_(SaslListAvailableMechs()),
    plain_enabled_(false),
    gssapi_enabled_(false) {
  tag_ = (peer_type_ == SERVER) ? "Server" : "Client";
}

void SaslHelper::set_server_fqdn(const string& domain_name) {
  server_fqdn_ = domain_name;
}
const char* SaslHelper::server_fqdn() const {
  return server_fqdn_.empty() ? nullptr : server_fqdn_.c_str();
}

const char* SaslHelper::EnabledMechsString() const {
  enabled_mechs_string_ = JoinMapped(enabled_mechs_, SaslMechanism::name_of, " ");
  return enabled_mechs_string_.c_str();
}

int SaslHelper::GetOptionCb(const char* plugin_name, const char* option,
                            const char** result, unsigned* len) {
  DVLOG(4) << tag_ << ": GetOption Callback called. ";
  DVLOG(4) << tag_ << ": GetOption Plugin name: "
                   << (plugin_name == nullptr ? "NULL" : plugin_name);
  DVLOG(4) << tag_ << ": GetOption Option name: " << option;

  if (PREDICT_FALSE(result == nullptr)) {
    LOG(DFATAL) << tag_ << ": SASL Library passed NULL result out-param to GetOption callback!";
    return SASL_BADPARAM;
  }

  if (plugin_name == nullptr) {
    // SASL library option, not a plugin option
    if (strcmp(option, "mech_list") == 0) {
      *result = EnabledMechsString();
      if (len != nullptr) *len = strlen(*result);
      VLOG(4) << tag_ << ": Enabled mech list: " << *result;
      return SASL_OK;
    }
    VLOG(4) << tag_ << ": GetOptionCb: Unknown library option: " << option;
  } else {
    VLOG(4) << tag_ << ": GetOptionCb: Unknown plugin: " << plugin_name;
  }
  return SASL_FAIL;
}

Status SaslHelper::EnablePlain() {
  RETURN_NOT_OK(EnableMechanism(SaslMechanism::PLAIN));
  plain_enabled_ = true;
  return Status::OK();
}

Status SaslHelper::EnableGSSAPI() {
  RETURN_NOT_OK(EnableMechanism(SaslMechanism::GSSAPI));
  gssapi_enabled_ = true;
  return Status::OK();
}

Status SaslHelper::EnableMechanism(SaslMechanism::Type mech) {
  if (PREDICT_FALSE(!ContainsKey(global_mechs_, mech))) {
    return Status::InvalidArgument("unable to find SASL plugin", SaslMechanism::name_of(mech));
  }
  enabled_mechs_.insert(mech);
  return Status::OK();
}

bool SaslHelper::IsPlainEnabled() const {
  return plain_enabled_;
}

Status SaslHelper::CheckNegotiateCallId(int32_t call_id) const {
  if (call_id != kNegotiateCallId) {
    Status s = Status::IllegalState(strings::Substitute(
        "Received illegal call-id during negotiation; expected: $0, received: $1",
        kNegotiateCallId, call_id));
    LOG(DFATAL) << tag_ << ": " << s.ToString();
    return s;
  }
  return Status::OK();
}

Status SaslHelper::ParseNegotiatePB(const Slice& param_buf, NegotiatePB* msg) {
  if (!msg->ParseFromArray(param_buf.data(), param_buf.size())) {
    return Status::IOError(tag_ + ": Invalid SASL message, missing fields",
        msg->InitializationErrorString());
  }
  return Status::OK();
}

} // namespace rpc
} // namespace kudu
