// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// Mobius Forensic Toolkit
// Copyright (C) 2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022 Eduardo Aguiar
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
// Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
#include "init.h"
#include <mobius/exception.inc>
#include <mobius/exception_posix.inc>
#include <cstdint>
#include <mutex>
#include <stdexcept>
#include <libsmbclient.h>

namespace mobius
{
namespace io
{
namespace smb
{
namespace
{
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// Local variables
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
static constexpr int DEBUG_LEVEL = 0;         //< Libsmbclient debug level

static std::mutex mutex_;
static bool is_initialized_ = false;
static std::string smb_user_;
static std::string smb_passwd_;
static std::string smb_workgroup_;

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief Authentication function passed to smbc_init
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
static void
_get_auth_data_fn (
  const char *,         // server
  const char *,         // share
  char * workgroup,
  int workgroup_size,
  char * username,
  int username_size,
  char * password,
  int password_size
)
{
  if (smb_user_.size () >= static_cast <std::uint64_t> (username_size))
    throw std::invalid_argument (MOBIUS_EXCEPTION_MSG ("SMB user name too large"));

  if (smb_passwd_.size () >= static_cast <std::uint64_t> (password_size))
    throw std::invalid_argument (MOBIUS_EXCEPTION_MSG ("SMB password too large"));

  if (smb_workgroup_.size () >= static_cast <std::uint64_t> (workgroup_size))
    throw std::invalid_argument (MOBIUS_EXCEPTION_MSG ("SMB workgroup name too large"));

  strcpy (username, smb_user_.c_str ());
  strcpy (password, smb_passwd_.c_str ());
  strcpy (workgroup, smb_workgroup_.c_str ());
}

} // namespace

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief Initialize SMB library
//! \param user User name
//! \param passwd User password
//! \param workgroup Workgroup name
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void
init (
  const std::string& user,
  const std::string& passwd,
  const std::string& workgroup
)
{
  const std::lock_guard <std::mutex> lock (mutex_);

  if (!is_initialized_ || !user.empty () || !passwd.empty () || !workgroup.empty ())
    {
      smb_user_ = user;
      smb_passwd_ = passwd;
      smb_workgroup_ = workgroup;

      if (smbc_init (_get_auth_data_fn, DEBUG_LEVEL) < 0)
        throw std::runtime_error (MOBIUS_EXCEPTION_POSIX);
      
      is_initialized_ = true;
    }
}

} // namespace smb
} // namespace io
} // namespace mobius
