Provide Ports and TLS Ports IRC-server ad-hoc options

This let any user choose which ports to use when connecting to the IRC
server. This also lets the user choose whether or not to force TLS usage (by
setting no non-TLS port).

fix #2731
This commit is contained in:
Florent Le Coz
2015-09-21 04:27:23 +02:00
parent 532228a3ce
commit 890cfe9099
4 changed files with 75 additions and 29 deletions
+3 -2
View File
@@ -6,8 +6,9 @@
<field name="owner" type="string" length="3071"/> <field name="owner" type="string" length="3071"/>
<field name="server" type="string" length="3071"/> <field name="server" type="string" length="3071"/>
<field name="requireTls" type="boolean" default="true"/> <field name="pass" type="string" length="1024" default=""/>
<field name="pass" type="string" length="1024"/> <field name="tlsPorts" type="string" length="4096" default="6697;6670" />
<field name="ports" type="string" length="4096" default="6667" />
<index unique="true"> <index unique="true">
<indexfield name="owner"/> <indexfield name="owner"/>
+18 -4
View File
@@ -16,11 +16,13 @@
#include <chrono> #include <chrono>
#include <string> #include <string>
#include "biboumi.h"
#include "louloulibs.h" #include "louloulibs.h"
using namespace std::string_literals; using namespace std::string_literals;
using namespace std::chrono_literals; using namespace std::chrono_literals;
IrcClient::IrcClient(std::shared_ptr<Poller> poller, const std::string& hostname, const std::string& username, Bridge* bridge): IrcClient::IrcClient(std::shared_ptr<Poller> poller, const std::string& hostname, const std::string& username, Bridge* bridge):
TCPSocketHandler(poller), TCPSocketHandler(poller),
hostname(hostname), hostname(hostname),
@@ -39,13 +41,25 @@ IrcClient::IrcClient(std::shared_ptr<Poller> poller, const std::string& hostname
"alive without having to join a real channel of that server. " "alive without having to join a real channel of that server. "
"To disconnect from the IRC server, leave this room and all " "To disconnect from the IRC server, leave this room and all "
"other IRC channels of that server."; "other IRC channels of that server.";
// TODO: get the values from the preferences of the user, and only use the #ifdef USE_DATABASE
// list of default ports if the user didn't specify anything auto options = Database::get_irc_server_options(this->bridge->get_bare_jid(),
this->get_hostname());
std::vector<std::string> ports = utils::split(options.ports, ';', false);
for (auto it = ports.rbegin(); it != ports.rend(); ++it)
this->ports_to_try.emplace(*it, false);
# ifdef BOTAN_FOUND
ports = utils::split(options.tlsPorts, ';', false);
for (auto it = ports.rbegin(); it != ports.rend(); ++it)
this->ports_to_try.emplace(*it, true);
# endif // BOTAN_FOUND
#else // not USE_DATABASE
this->ports_to_try.emplace("6667", false); // standard non-encrypted port this->ports_to_try.emplace("6667", false); // standard non-encrypted port
#ifdef BOTAN_FOUND # ifdef BOTAN_FOUND
this->ports_to_try.emplace("6670", true); // non-standard but I want it for some servers this->ports_to_try.emplace("6670", true); // non-standard but I want it for some servers
this->ports_to_try.emplace("6697", true); // standard encrypted port this->ports_to_try.emplace("6697", true); // standard encrypted port
#endif // BOTAN_FOUND # endif // BOTAN_FOUND
#endif // USE_DATABASE
} }
IrcClient::~IrcClient() IrcClient::~IrcClient()
-10
View File
@@ -423,12 +423,9 @@ int main()
Config::set("db_name", "test.db"); Config::set("db_name", "test.db");
Database::set_verbose(true); Database::set_verbose(true);
auto o = Database::get_irc_server_options("zouzou@example.com", "irc.example.com"); auto o = Database::get_irc_server_options("zouzou@example.com", "irc.example.com");
o.requireTls = false;
o.update(); o.update();
auto a = Database::get_irc_server_options("zouzou@example.com", "irc.example.com"); auto a = Database::get_irc_server_options("zouzou@example.com", "irc.example.com");
assert(a.requireTls == false);
auto b = Database::get_irc_server_options("moumou@example.com", "irc.example.com"); auto b = Database::get_irc_server_options("moumou@example.com", "irc.example.com");
assert(b.requireTls == true);
// b does not yet exist in the db, the object is created but not yet // b does not yet exist in the db, the object is created but not yet
// inserted // inserted
@@ -439,13 +436,6 @@ int main()
assert(b.pass == ""); assert(b.pass == "");
assert(b.pass.value() == ""); assert(b.pass.value() == "");
std::vector<litesql::FieldType> ftypes;
db::IrcServerOptions::getFieldTypes(ftypes);
for (const auto& type: ftypes)
{
std::cout << type.type() << std::endl;
}
} }
#endif #endif
{ {
+54 -13
View File
@@ -2,6 +2,7 @@
#include <xmpp/biboumi_component.hpp> #include <xmpp/biboumi_component.hpp>
#include <bridge/bridge.hpp> #include <bridge/bridge.hpp>
#include <utils/string.hpp> #include <utils/string.hpp>
#include <utils/split.hpp>
#include <xmpp/jid.hpp> #include <xmpp/jid.hpp>
#include <biboumi.h> #include <biboumi.h>
@@ -10,6 +11,8 @@
#include <database/database.hpp> #include <database/database.hpp>
#endif #endif
#include <louloulibs.h>
using namespace std::string_literals; using namespace std::string_literals;
void DisconnectUserStep1(XmppComponent* xmpp_component, AdhocSession&, XmlNode& command_node) void DisconnectUserStep1(XmppComponent* xmpp_component, AdhocSession&, XmlNode& command_node)
@@ -127,16 +130,39 @@ void ConfigureIrcServerStep1(XmppComponent* xmpp_component, AdhocSession& sessio
instructions.set_inner("Edit the form, to configure the settings of the IRC server "s + target.local); instructions.set_inner("Edit the form, to configure the settings of the IRC server "s + target.local);
x.add_child(std::move(instructions)); x.add_child(std::move(instructions));
XmlNode require_tls("field");
require_tls["var"] = "require_tls";
require_tls["type"] = "boolean";
require_tls["label"] = "Require TLS (refuse to connect insecurely)";
XmlNode require_tls_value("value");
require_tls_value.set_inner(options.requireTls ? "true": "false");
require_tls.add_child(std::move(require_tls_value));
XmlNode required("required"); XmlNode required("required");
require_tls.add_child(required);
x.add_child(std::move(require_tls)); XmlNode ports("field");
ports["var"] = "ports";
ports["type"] = "text-multi";
ports["label"] = "Ports";
ports["desc"] = "List of ports to try, without TLS. Defaults: 6667.";
auto vals = utils::split(options.ports.value(), ';', false);
for (const auto& val: vals)
{
XmlNode ports_value("value");
ports_value.set_inner(val);
ports.add_child(std::move(ports_value));
}
ports.add_child(required);
x.add_child(std::move(ports));
#ifdef BOTAN_FOUND
XmlNode tls_ports("field");
tls_ports["var"] = "tls_ports";
tls_ports["type"] = "text-multi";
tls_ports["label"] = "TLS ports";
tls_ports["desc"] = "List of ports to try, with TLS. Defaults: 6697, 6670.";
vals = utils::split(options.tlsPorts.value(), ';', false);
for (const auto& val: vals)
{
XmlNode tls_ports_value("value");
tls_ports_value.set_inner(val);
tls_ports.add_child(std::move(tls_ports_value));
}
tls_ports.add_child(required);
x.add_child(std::move(tls_ports));
#endif
XmlNode pass("field"); XmlNode pass("field");
pass["var"] = "pass"; pass["var"] = "pass";
@@ -168,12 +194,27 @@ void ConfigureIrcServerStep2(XmppComponent* xmpp_component, AdhocSession& sessio
for (const XmlNode* field: x->get_children("field", "jabber:x:data")) for (const XmlNode* field: x->get_children("field", "jabber:x:data"))
{ {
const XmlNode* value = field->get_child("value", "jabber:x:data"); const XmlNode* value = field->get_child("value", "jabber:x:data");
if (field->get_tag("var") == "require_tls" && const std::vector<const XmlNode*> values = field->get_children("value", "jabber:x:data");
value && !value->get_inner().empty()) if (field->get_tag("var") == "ports")
options.requireTls = to_bool(value->get_inner()); {
std::string ports;
for (const auto& val: values)
ports += val->get_inner() + ";";
options.ports = ports;
}
#ifdef BOTAN_FOUND
else if (field->get_tag("var") == "tls_ports")
{
std::string ports;
for (const auto& val: values)
ports += val->get_inner() + ";";
options.tlsPorts = ports;
}
#endif // BOTAN_FOUND
else if (field->get_tag("var") == "pass" && else if (field->get_tag("var") == "pass" &&
value && !value->get_inner().empty()) value && !value->get_inner().empty())
options.pass = value->get_inner(); options.pass = value->get_inner();
} }