diff options
| author | 2024-07-17 00:06:50 +0100 | |
|---|---|---|
| committer | 2024-07-17 00:06:50 +0100 | |
| commit | 889d521e05f2e922683d48c74eb00290e7a2f548 (patch) | |
| tree | b4c56bd4cdf0881601c7e4d6ff571e491af10bf4 /modules/spanningtree/hmac.cpp | |
| parent | Use 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.cpp | 113 |
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; +} |
