+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 m_sha256.so is not loaded, we MUST fall back to plaintext with no
+ * HMAC challenge/response.
+ */
+ Module* sha256 = Instance->FindModule("m_sha256.so");
+ if (Utils->ChallengeResponse && sha256 && !challenge.empty())
+ {
+ /* XXX: This is how HMAC is supposed to be done:
+ *
+ * sha256( (pass xor 0x5c) + sha256((pass xor 0x36) + m) )
+ *
+ * Note that we are encoding the hex hash, not the binary
+ * output of the hash which is slightly different to standard.
+ *
+ * Don't ask me why its always 0x5c and 0x36... it just is.
+ */
+ std::string hmac1, hmac2;
+
+ for (size_t n = 0; n < password.length(); n++)
+ {
+ hmac1 += static_cast<char>(password[n] ^ 0x5C);
+ hmac2 += static_cast<char>(password[n] ^ 0x36);
+ }
+
+ HashResetRequest(Utils->Creator, sha256).Send();
+ hmac2 = HashSumRequest(Utils->Creator, sha256, hmac2).Send();
+
+ HashResetRequest(Utils->Creator, sha256).Send();
+ std::string hmac = hmac1 + hmac2 + challenge;
+ hmac = HashSumRequest(Utils->Creator, sha256, hmac).Send();
+
+ return "HMAC-SHA256:"+ hmac;
+ }
+ else if (!challenge.empty() && !sha256)
+ Instance->Log(DEFAULT,"Not authenticating to server using SHA256/HMAC because we don't have m_sha256 loaded!");
+
+ return password;
+}
+