~singpolyma/biboumi

189015afb4632bd1dc78c1bd87bed1ca4cc48b19 — louiz’ 2 years ago e4550d3
Conditionally compile the SASL code only with botan and database
M src/biboumi.h.cmake => src/biboumi.h.cmake +3 -0
@@ 14,3 14,6 @@
#cmakedefine HAS_PUT_TIME
#cmakedefine DEBUG_SQL_QUERIES

#if defined(USE_DATABASE) && defined(BOTAN_FOUND)
# define WITH_SASL
#endif

M src/irc/irc_client.cpp => src/irc/irc_client.cpp +13 -12
@@ 83,11 83,11 @@ static const std::unordered_map<std::string,
  {"KICK", {&IrcClient::on_kick, {3, 0}}},
  {"INVITE", {&IrcClient::on_invite, {2, 0}}},
  {"CAP", {&IrcClient::on_cap, {3, 0}}},
#ifdef WITH_SASL
  {"AUTHENTICATE", {&IrcClient::on_authenticate, {1, 0}}},
  {"903", {&IrcClient::on_sasl_success, {0, 0}}},
  {"900", {&IrcClient::on_sasl_login, {3, 0}}},


#endif
  {"401", {&IrcClient::on_generic_error, {2, 0}}},
  {"402", {&IrcClient::on_generic_error, {2, 0}}},
  {"403", {&IrcClient::on_generic_error, {2, 0}}},


@@ 286,12 286,14 @@ void IrcClient::on_connected()
  auto options = Database::get_irc_server_options(this->bridge.get_bare_jid(),
                                                  this->get_hostname());

  const auto& sasl_password = options.col<Database::SaslPassword>();
  const auto& server_password = options.col<Database::Pass>();

  if (!server_password.empty())
    this->send_pass_command(options.col<Database::Pass>());
#endif

#ifdef WITH_SASL
  const auto& sasl_password = options.col<Database::SaslPassword>();
  if (!sasl_password.empty())
    {
      this->capabilities["sasl"] = {


@@ 325,10 327,8 @@ void IrcClient::on_connected()
      this->send_user_command(username, realname);
    }
  else
    this->send_user_command(this->username, this->realname);
#else
  this->send_user_command(this->username, this->realname);
#endif
  this->send_user_command(this->username, this->realname);
}

void IrcClient::on_connection_close(const std::string& error_msg)


@@ 1346,9 1346,11 @@ void IrcClient::on_cap(const IrcMessage &message)
  else if (sub_command == "NACK")
    capability.on_nack();
  this->capabilities.erase(it);
  this->cap_end();
  if (this->capabilities.empty())
    this->cap_end();
}

#ifdef WITH_SASL
void IrcClient::on_authenticate(const IrcMessage &)
{
  if (this->sasl_state == SaslState::unneeded)


@@ 1356,13 1358,12 @@ void IrcClient::on_authenticate(const IrcMessage &)
      log_warning("Received an AUTHENTICATE command but we don’t intend to authenticate…");
      return;
    }
#ifdef USE_DATABASE

  auto options = Database::get_irc_server_options(this->bridge.get_bare_jid(),
                                                  this->get_hostname());
  const auto auth_string = '\0' + options.col<Database::Nick>() + '\0' + options.col<Database::SaslPassword>();
  const auto base64_auth_string = base64::encode(auth_string);
  this->send_message({"AUTHENTICATE", {base64_auth_string}});
#endif
}

void IrcClient::on_sasl_success(const IrcMessage &)


@@ 1379,15 1380,15 @@ void IrcClient::on_sasl_login(const IrcMessage &message)
    text = message.arguments[3];
  this->bridge.send_xmpp_message(this->hostname, message.prefix, text);
}
#endif

void IrcClient::cap_end()
{
  if (!this->capabilities.empty())
    return;
#ifdef WITH_SASL
  // If we are currently authenticating through sasl, finish that before sending CAP END
  if (this->sasl_state == SaslState::needed)
    return;

#endif
  this->send_message({"CAP", {"END"}});
  this->bridge.on_irc_client_connected(this->get_hostname());
}

M src/irc/irc_client.hpp => src/irc/irc_client.hpp +10 -1
@@ 3,7 3,12 @@
#include <irc/irc_message.hpp>
#include <irc/irc_channel.hpp>
#include <irc/capability.hpp>
#include <irc/sasl.hpp>

#include "biboumi.h"

#ifdef WITH_SASL
# include <irc/sasl.hpp>
#endif
#include <irc/iid.hpp>

#include <bridge/history_limit.hpp>


@@ 240,9 245,11 @@ public:
private:
  void cap_end();
public:
#ifdef WITH_SASL
  void on_authenticate(const IrcMessage& message);
  void on_sasl_success(const IrcMessage& message);
  void on_sasl_login(const IrcMessage& message);
#endif
  /**
   * The channel has been completely joined (self presence, topic, all names
   * received etc), send the self presence and topic to the XMPP user.


@@ 371,11 378,13 @@ private:
   * has been established, we are authentified and we have a nick)
   */
  bool welcomed;
#ifdef WITH_SASL
  /**
   * Whether or not we are trying to authenticate using sasl. If this is true we need to wait for a
   * successful auth
   */
  SaslState sasl_state{SaslState::unneeded};
#endif
  std::map<std::string, Capability> capabilities;
  /**
   * See http://www.irc.org/tech_docs/draft-brocklesby-irc-isupport-03.txt section 3.3

M src/utils/base64.cpp => src/utils/base64.cpp +2 -5
@@ 2,18 2,15 @@

#ifdef BOTAN_FOUND
#include <botan/base64.h>
#endif

namespace base64
{

std::string encode(const std::string &input)
{
#ifdef BOTAN_FOUND
  return Botan::base64_encode(reinterpret_cast<const uint8_t*>(input.data()), input.size());
#else
#error "base64::encode() not yet implemented without Botan."
#endif
}

}

#endif

M src/utils/base64.hpp => src/utils/base64.hpp +4 -0
@@ 2,9 2,13 @@

#include "biboumi.h"

#ifdef BOTAN_FOUND

#include <string>

namespace base64
{
std::string encode(const std::string& input);
}

#endif

M src/xmpp/biboumi_adhoc_commands.cpp => src/xmpp/biboumi_adhoc_commands.cpp +19 -19
@@ 310,31 310,32 @@ void ConfigureIrcServerStep1(XmppComponent&, AdhocSession& session, XmlNode& com
        fingerprint_value.set_inner(options.col<Database::TrustedFingerprint>());
      }
  }
#endif

  {
    XmlSubNode field(x, "field");
    field["var"] = "nick";
    field["type"] = "text-single";
    field["label"] = "Nickname";
    set_desc(field, "If set, will override the nickname provided in the initial presence sent to join the first server channel");
    if (!options.col<Database::Nick>().empty())
    field["var"] = "sasl_password";
    field["type"] = "text-private";
    field["label"] = "SASL Password";
    set_desc(field, "Use it to authenticate with your nick.");
    if (!options.col<Database::SaslPassword>().empty())
      {
        XmlSubNode value(field, "value");
        value.set_inner(options.col<Database::Nick>());
        value.set_inner(options.col<Database::SaslPassword>());
      }
  }

#endif

  {
    XmlSubNode field(x, "field");
    field["var"] = "sasl_password";
    field["type"] = "text-private";
    field["label"] = "SASL Password";
    set_desc(field, "Use it to authenticate with your nick.");
    if (!options.col<Database::SaslPassword>().empty())
    field["var"] = "nick";
    field["type"] = "text-single";
    field["label"] = "Nickname";
    set_desc(field, "If set, will override the nickname provided in the initial presence sent to join the first server channel");
    if (!options.col<Database::Nick>().empty())
      {
        XmlSubNode value(field, "value");
        value.set_inner(options.col<Database::SaslPassword>());
        value.set_inner(options.col<Database::Nick>());
      }
  }



@@ 486,18 487,17 @@ void ConfigureIrcServerStep2(XmppComponent& xmpp_component, AdhocSession& sessio
            }

          else if (field->get_tag("var") == "fingerprint" && value)
            {
              options.col<Database::TrustedFingerprint>() = value->get_inner();
            }
            options.col<Database::TrustedFingerprint>() = value->get_inner();

          else if (field->get_tag("var") == "sasl_password" && value)
            options.col<Database::SaslPassword>() = value->get_inner();


#endif // BOTAN_FOUND

          else if (field->get_tag("var") == "nick" && value)
            options.col<Database::Nick>() = value->get_inner();

          else if (field->get_tag("var") == "sasl_password" && value)
            options.col<Database::SaslPassword>() = value->get_inner();

          else if (field->get_tag("var") == "pass" && value)
            options.col<Database::Pass>() = value->get_inner();