summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--database/database.xml1
-rw-r--r--louloulibs/network/credentials_manager.cpp15
-rw-r--r--louloulibs/network/credentials_manager.hpp2
-rw-r--r--louloulibs/network/tcp_socket_handler.hpp2
-rw-r--r--src/irc/irc_client.cpp7
-rw-r--r--src/xmpp/biboumi_adhoc_commands.cpp22
6 files changed, 47 insertions, 2 deletions
diff --git a/database/database.xml b/database/database.xml
index a22b49d..f102db0 100644
--- a/database/database.xml
+++ b/database/database.xml
@@ -13,6 +13,7 @@
<field name="username" type="string" length="1024" default=""/>
<field name="realname" type="string" length="1024" default=""/>
<field name="verifyCert" type="boolean" default="true"/>
+ <field name="trustedFingerprint" type="string"/>
<field name="encodingOut" type="string" default="ISO-8859-1"/>
<field name="encodingIn" type="string" default="ISO-8859-1"/>
diff --git a/louloulibs/network/credentials_manager.cpp b/louloulibs/network/credentials_manager.cpp
index 57100ee..f92aef8 100644
--- a/louloulibs/network/credentials_manager.cpp
+++ b/louloulibs/network/credentials_manager.cpp
@@ -26,11 +26,17 @@ bool Basic_Credentials_Manager::certs_loaded = false;
Basic_Credentials_Manager::Basic_Credentials_Manager(const TCPSocketHandler* const socket_handler):
Botan::Credentials_Manager(),
- socket_handler(socket_handler)
+ socket_handler(socket_handler),
+ trusted_fingerprint{}
{
this->load_certs();
}
+void Basic_Credentials_Manager::set_trusted_fingerprint(const std::string& fingerprint)
+{
+ this->trusted_fingerprint = fingerprint;
+}
+
void Basic_Credentials_Manager::verify_certificate_chain(const std::string& type,
const std::string& purported_hostname,
const std::vector<Botan::X509_Certificate>& certs)
@@ -44,6 +50,13 @@ void Basic_Credentials_Manager::verify_certificate_chain(const std::string& type
catch (const std::exception& tls_exception)
{
log_warning("TLS certificate check failed: " << tls_exception.what());
+ if (!this->trusted_fingerprint.empty() && !certs.empty() &&
+ this->trusted_fingerprint == certs[0].fingerprint() &&
+ certs[0].matches_dns_name(purported_hostname))
+ // We trust the certificate, based on the trusted fingerprint and
+ // the fact that the hostname matches
+ return;
+
if (this->socket_handler->abort_on_invalid_cert())
throw;
}
diff --git a/louloulibs/network/credentials_manager.hpp b/louloulibs/network/credentials_manager.hpp
index e292321..dbd1d95 100644
--- a/louloulibs/network/credentials_manager.hpp
+++ b/louloulibs/network/credentials_manager.hpp
@@ -19,6 +19,7 @@ public:
const std::vector<Botan::X509_Certificate>&) override final;
std::vector<Botan::Certificate_Store*> trusted_certificate_authorities(const std::string& type,
const std::string& context) override final;
+ void set_trusted_fingerprint(const std::string& fingerprint);
private:
const TCPSocketHandler* const socket_handler;
@@ -26,6 +27,7 @@ private:
static void load_certs();
static Botan::Certificate_Store_In_Memory certificate_store;
static bool certs_loaded;
+ std::string trusted_fingerprint;
};
#endif //BOTAN_FOUND
diff --git a/louloulibs/network/tcp_socket_handler.hpp b/louloulibs/network/tcp_socket_handler.hpp
index 9f5caa3..fb4195d 100644
--- a/louloulibs/network/tcp_socket_handler.hpp
+++ b/louloulibs/network/tcp_socket_handler.hpp
@@ -248,7 +248,9 @@ private:
static Botan::AutoSeeded_RNG rng;
static Botan::TLS::Policy policy;
static Botan::TLS::Session_Manager_In_Memory session_manager;
+protected:
Basic_Credentials_Manager credential_manager;
+private:
/**
* We use a unique_ptr because we may not want to create the object at
* all. The Botan::TLS::Client object generates a handshake message and
diff --git a/src/irc/irc_client.cpp b/src/irc/irc_client.cpp
index e71d38c..1a83446 100644
--- a/src/irc/irc_client.cpp
+++ b/src/irc/irc_client.cpp
@@ -89,6 +89,13 @@ void IrcClient::start()
this->bind_addr = Config::get("outgoing_bind", "");
+#ifdef BOTAN_FOUND
+# ifdef USE_DATABASE
+ auto options = Database::get_irc_server_options(this->bridge.get_bare_jid(),
+ this->get_hostname());
+ this->credential_manager.set_trusted_fingerprint(options.trustedFingerprint);
+# endif
+#endif
this->connect(this->hostname, port, tls);
}
diff --git a/src/xmpp/biboumi_adhoc_commands.cpp b/src/xmpp/biboumi_adhoc_commands.cpp
index be755e9..7c157cb 100644
--- a/src/xmpp/biboumi_adhoc_commands.cpp
+++ b/src/xmpp/biboumi_adhoc_commands.cpp
@@ -175,6 +175,19 @@ void ConfigureIrcServerStep1(XmppComponent&, AdhocSession& session, XmlNode& com
verify_cert_value.set_inner("false");
verify_cert.add_child(std::move(verify_cert_value));
x.add_child(std::move(verify_cert));
+
+ XmlNode fingerprint("field");
+ fingerprint["var"] = "fingerprint";
+ fingerprint["type"] = "text-single";
+ fingerprint["label"] = "SHA-1 fingerprint of the TLS certificate to trust.";
+ if (!options.trustedFingerprint.value().empty())
+ {
+ XmlNode fingerprint_value("value");
+ fingerprint_value.set_inner(options.trustedFingerprint.value());
+ fingerprint.add_child(std::move(fingerprint_value));
+ }
+ fingerprint.add_child(required);
+ x.add_child(std::move(fingerprint));
#endif
XmlNode pass("field");
@@ -295,12 +308,19 @@ void ConfigureIrcServerStep2(XmppComponent&, AdhocSession& session, XmlNode& com
options.tlsPorts = ports;
}
- else if (field->get_tag("var") == "verify_cert" && value
+ else if (field->get_tag("var") == "verify_cert" && value
&& !value->get_inner().empty())
{
auto val = to_bool(value->get_inner());
options.verifyCert = val;
}
+
+ else if (field->get_tag("var") == "fingerprint" && value &&
+ !value->get_inner().empty())
+ {
+ options.trustedFingerprint = value->get_inner();
+ }
+
#endif // BOTAN_FOUND
else if (field->get_tag("var") == "pass" &&