aboutsummaryrefslogtreecommitdiffstats
path: root/modules/spanningtree/hmac.cpp
diff options
context:
space:
mode:
authorGravatar Sadie Powell2024-07-17 00:06:50 +0100
committerGravatar Sadie Powell2024-07-17 00:06:50 +0100
commit889d521e05f2e922683d48c74eb00290e7a2f548 (patch)
treeb4c56bd4cdf0881601c7e4d6ff571e491af10bf4 /modules/spanningtree/hmac.cpp
parentUse std::endian from C++20 in the sha1 module. (diff)
Shuffle the modules about a bit.
Diffstat (limited to 'modules/spanningtree/hmac.cpp')
-rw-r--r--modules/spanningtree/hmac.cpp113
1 files changed, 113 insertions, 0 deletions
diff --git a/modules/spanningtree/hmac.cpp b/modules/spanningtree/hmac.cpp
new file mode 100644
index 000000000..996d69e96
--- /dev/null
+++ b/modules/spanningtree/hmac.cpp
@@ -0,0 +1,113 @@
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ * Copyright (C) 2014 Matthew Martin <phy1729@gmail.com>
+ * Copyright (C) 2013-2014 Attila Molnar <attilamolnar@hush.com>
+ * Copyright (C) 2013, 2019, 2021-2024 Sadie Powell <sadie@witchery.services>
+ * Copyright (C) 2012 Robby <robby@chatbelgie.be>
+ * Copyright (C) 2009-2010 Daniel De Graaf <danieldg@inspircd.org>
+ * Copyright (C) 2008 Robin Burchell <robin+git@viroteck.net>
+ *
+ * This file is part of InspIRCd. InspIRCd 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, version 2.
+ *
+ * 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 "inspircd.h"
+#include "modules/hash.h"
+#include "modules/ssl.h"
+
+#include "main.h"
+#include "link.h"
+#include "treesocket.h"
+
+const std::string& TreeSocket::GetOurChallenge()
+{
+ return capab->ourchallenge;
+}
+
+void TreeSocket::SetOurChallenge(const std::string& c)
+{
+ capab->ourchallenge = c;
+}
+
+const std::string& TreeSocket::GetTheirChallenge()
+{
+ return capab->theirchallenge;
+}
+
+void TreeSocket::SetTheirChallenge(const std::string& c)
+{
+ capab->theirchallenge = c;
+}
+
+std::string TreeSocket::MakePass(const std::string& password, const std::string& challenge)
+{
+ /* This is a simple (maybe a bit hacky?) HMAC algorithm, thanks to jilles for
+ * suggesting the use of HMAC to secure the password against various attacks.
+ *
+ * Note: If an sha256 provider is not available, we MUST fall back to plaintext with no
+ * HMAC challenge/response.
+ */
+ HashProvider* sha256 = ServerInstance->Modules.FindDataService<HashProvider>("hash/sha256");
+ if (sha256 && !challenge.empty())
+ return "AUTH:" + Base64::Encode(sha256->hmac(password, challenge));
+
+ if (!challenge.empty() && !sha256)
+ ServerInstance->Logs.Warning(MODNAME, "Not authenticating to server using HMAC-SHA256 because we don't have an SHA256 provider (e.g. the sha2 module) loaded!");
+
+ return password;
+}
+
+bool TreeSocket::ComparePass(const Link& link, const std::string& theirs)
+{
+ capab->auth_fingerprint = !link.Fingerprint.empty();
+ capab->auth_challenge = !capab->ourchallenge.empty() && !capab->theirchallenge.empty();
+
+ std::string fp = SSLClientCert::GetFingerprint(this);
+ if (capab->auth_fingerprint)
+ {
+ /* Require fingerprint to exist and match */
+ if (!InspIRCd::TimingSafeCompare(link.Fingerprint, fp))
+ {
+ ServerInstance->SNO.WriteToSnoMask('l', "Invalid TLS certificate fingerprint on link {}: need \"{}\" got \"{}\"",
+ link.Name, link.Fingerprint, fp);
+ SendError("Invalid TLS certificate fingerprint " + fp + " - expected " + link.Fingerprint);
+ return false;
+ }
+ }
+
+ if (capab->auth_challenge)
+ {
+ std::string our_hmac = MakePass(link.RecvPass, capab->ourchallenge);
+
+ // Use the timing-safe compare function to compare the hashes
+ if (!InspIRCd::TimingSafeCompare(our_hmac, theirs))
+ return false;
+ }
+ else
+ {
+ // Use the timing-safe compare function to compare the passwords
+ if (!InspIRCd::TimingSafeCompare(link.RecvPass, theirs))
+ return false;
+ }
+
+ // Tell opers to set up fingerprint verification if it's not already set up and the TLS mod gave us a fingerprint
+ // this time
+ if ((!capab->auth_fingerprint) && (!fp.empty()))
+ {
+ ServerInstance->SNO.WriteToSnoMask('l', "TLS certificate fingerprint for link {} is \"{}\". "
+ "You can improve security by specifying this in <link:fingerprint>.", link.Name, fp);
+ }
+
+ return true;
+}