summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Vassdal <shutter@canternet.org>2014-07-02 20:55:33 +0200
committerAttila Molnar <attilamolnar@hush.com>2014-08-04 12:38:12 +0200
commit5c7db14a557d7f980dfaa8c10d40c1ccc554b35d (patch)
treed9d0b3161928f1ba9cbf0ced5f894c2d1c6a1886
parent0c0a7b6404c5de51241cdaa3eb159d014ef51024 (diff)
Hashing: Redo API
* Don't assume the printable output of hashes is hex * Add virtual Compare() function, usable for KDFs like BCrypt Some changes and bugfixes are by @attilamolnar, original PR #767
-rw-r--r--include/modules/hash.h34
-rw-r--r--src/modules/m_cloaking.cpp2
-rw-r--r--src/modules/m_md5.cpp18
-rw-r--r--src/modules/m_password_hash.cpp19
-rw-r--r--src/modules/m_ripemd160.cpp4
-rw-r--r--src/modules/m_sha256.cpp4
-rw-r--r--src/modules/m_sqlauth.cpp4
-rw-r--r--src/modules/m_sqloper.cpp2
8 files changed, 50 insertions, 37 deletions
diff --git a/include/modules/hash.h b/include/modules/hash.h
index da04c45ba..7d46ee74a 100644
--- a/include/modules/hash.h
+++ b/include/modules/hash.h
@@ -26,24 +26,33 @@ class HashProvider : public DataProvider
public:
const unsigned int out_size;
const unsigned int block_size;
- HashProvider(Module* mod, const std::string& Name, int osiz, int bsiz)
- : DataProvider(mod, Name), out_size(osiz), block_size(bsiz) {}
- virtual std::string sum(const std::string& data) = 0;
- inline std::string hexsum(const std::string& data)
+ HashProvider(Module* mod, const std::string& Name, unsigned int osiz = 0, unsigned int bsiz = 0)
+ : DataProvider(mod, "hash/" + Name), out_size(osiz), block_size(bsiz)
{
- return BinToHex(sum(data));
}
- inline std::string b64sum(const std::string& data)
+ virtual std::string GenerateRaw(const std::string& data) = 0;
+
+ virtual std::string ToPrintable(const std::string& raw)
+ {
+ return BinToHex(raw);
+ }
+
+ virtual bool Compare(const std::string& input, const std::string& hash)
+ {
+ return InspIRCd::TimingSafeCompare(Generate(input), hash);
+ }
+
+ std::string Generate(const std::string& data)
{
- return BinToBase64(sum(data), NULL, 0);
+ return ToPrintable(GenerateRaw(data));
}
/** HMAC algorithm, RFC 2104 */
std::string hmac(const std::string& key, const std::string& msg)
{
std::string hmac1, hmac2;
- std::string kbuf = key.length() > block_size ? sum(key) : key;
+ std::string kbuf = key.length() > block_size ? GenerateRaw(key) : key;
kbuf.resize(block_size);
for (size_t n = 0; n < block_size; n++)
@@ -52,7 +61,12 @@ class HashProvider : public DataProvider
hmac2.push_back(static_cast<char>(kbuf[n] ^ 0x36));
}
hmac2.append(msg);
- hmac1.append(sum(hmac2));
- return sum(hmac1);
+ hmac1.append(GenerateRaw(hmac2));
+ return GenerateRaw(hmac1);
+ }
+
+ bool IsKDF() const
+ {
+ return (!block_size);
}
};
diff --git a/src/modules/m_cloaking.cpp b/src/modules/m_cloaking.cpp
index 5d62c9cf6..e0f3f01ef 100644
--- a/src/modules/m_cloaking.cpp
+++ b/src/modules/m_cloaking.cpp
@@ -192,7 +192,7 @@ class ModuleCloaking : public Module
input.append(1, '\0'); // null does not terminate a C++ string
input.append(item);
- std::string rv = Hash->sum(input).substr(0,len);
+ std::string rv = Hash->Generate(input).substr(0,len);
for(int i=0; i < len; i++)
{
// this discards 3 bits per byte. We have an
diff --git a/src/modules/m_md5.cpp b/src/modules/m_md5.cpp
index ecf76d07c..6e6f5006f 100644
--- a/src/modules/m_md5.cpp
+++ b/src/modules/m_md5.cpp
@@ -244,29 +244,15 @@ class MD5Provider : public HashProvider
MD5Final((unsigned char*)dest, &context);
}
-
- void GenHash(const char* src, char* dest, const char* xtab, unsigned int* ikey, size_t srclen)
- {
- unsigned char bytes[16];
-
- MyMD5((char*)bytes, (void*)src, srclen, ikey);
-
- for (int i = 0; i < 16; i++)
- {
- *dest++ = xtab[bytes[i] / 16];
- *dest++ = xtab[bytes[i] % 16];
- }
- *dest++ = 0;
- }
public:
- std::string sum(const std::string& data)
+ std::string GenerateRaw(const std::string& data)
{
char res[16];
MyMD5(res, (void*)data.data(), data.length(), NULL);
return std::string(res, 16);
}
- MD5Provider(Module* parent) : HashProvider(parent, "hash/md5", 16, 64) {}
+ MD5Provider(Module* parent) : HashProvider(parent, "md5", 16, 64) {}
};
class ModuleMD5 : public Module
diff --git a/src/modules/m_password_hash.cpp b/src/modules/m_password_hash.cpp
index 37effc79e..3cdd2b3ce 100644
--- a/src/modules/m_password_hash.cpp
+++ b/src/modules/m_password_hash.cpp
@@ -43,6 +43,13 @@ class CommandMkpasswd : public Command
user->WriteNotice("Unknown hash type");
return;
}
+
+ if (hp->IsKDF())
+ {
+ user->WriteNotice(type + " does not support HMAC");
+ return;
+ }
+
std::string salt = ServerInstance->GenRandomStr(hp->out_size, false);
std::string target = hp->hmac(salt, stuff);
std::string str = BinToBase64(salt) + "$" + BinToBase64(target, NULL, 0);
@@ -54,7 +61,7 @@ class CommandMkpasswd : public Command
if (hp)
{
/* Now attempt to generate a hash */
- std::string hexsum = hp->hexsum(stuff);
+ std::string hexsum = hp->Generate(stuff);
user->WriteNotice(algo + " hashed password for " + stuff + " is " + hexsum);
}
else
@@ -88,6 +95,13 @@ class ModuleOperHash : public Module
HashProvider* hp = ServerInstance->Modules->FindDataService<HashProvider>("hash/" + type);
if (!hp)
return MOD_RES_PASSTHRU;
+
+ if (hp->IsKDF())
+ {
+ ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "Tried to use HMAC with %s, which does not support HMAC", type.c_str());
+ return MOD_RES_DENY;
+ }
+
// this is a valid hash, from here on we either accept or deny
std::string::size_type sep = data.find('$');
if (sep == std::string::npos)
@@ -106,8 +120,7 @@ class ModuleOperHash : public Module
/* Is this a valid hash name? */
if (hp)
{
- // Use the timing-safe compare function to compare the hashes
- if (InspIRCd::TimingSafeCompare(data, hp->hexsum(input)))
+ if (hp->Compare(input, data))
return MOD_RES_ALLOW;
else
/* No match, and must be hashed, forbid */
diff --git a/src/modules/m_ripemd160.cpp b/src/modules/m_ripemd160.cpp
index 261cd1e27..8d3131bc0 100644
--- a/src/modules/m_ripemd160.cpp
+++ b/src/modules/m_ripemd160.cpp
@@ -434,13 +434,13 @@ class RIProv : public HashProvider
return (byte *)hashcode;
}
public:
- std::string sum(const std::string& data)
+ std::string GenerateRaw(const std::string& data)
{
char* rv = (char*)RMD((byte*)data.data(), data.length(), NULL);
return std::string(rv, RMDsize / 8);
}
- RIProv(Module* m) : HashProvider(m, "hash/ripemd160", 20, 64) {}
+ RIProv(Module* m) : HashProvider(m, "ripemd160", 20, 64) {}
};
class ModuleRIPEMD160 : public Module
diff --git a/src/modules/m_sha256.cpp b/src/modules/m_sha256.cpp
index d2755bacc..48bfc0041 100644
--- a/src/modules/m_sha256.cpp
+++ b/src/modules/m_sha256.cpp
@@ -247,14 +247,14 @@ class HashSHA256 : public HashProvider
}
public:
- std::string sum(const std::string& data)
+ std::string GenerateRaw(const std::string& data)
{
unsigned char bytes[SHA256_DIGEST_SIZE];
SHA256(data.data(), bytes, data.length());
return std::string((char*)bytes, SHA256_DIGEST_SIZE);
}
- HashSHA256(Module* parent) : HashProvider(parent, "hash/sha256", 32, 64) {}
+ HashSHA256(Module* parent) : HashProvider(parent, "sha256", 32, 64) {}
};
class ModuleSHA256 : public Module
diff --git a/src/modules/m_sqlauth.cpp b/src/modules/m_sqlauth.cpp
index 1ffb3305a..8a0b80ce1 100644
--- a/src/modules/m_sqlauth.cpp
+++ b/src/modules/m_sqlauth.cpp
@@ -124,11 +124,11 @@ class ModuleSQLAuth : public Module
HashProvider* md5 = ServerInstance->Modules->FindDataService<HashProvider>("hash/md5");
if (md5)
- userinfo["md5pass"] = md5->hexsum(user->password);
+ userinfo["md5pass"] = md5->Generate(user->password);
HashProvider* sha256 = ServerInstance->Modules->FindDataService<HashProvider>("hash/sha256");
if (sha256)
- userinfo["sha256pass"] = sha256->hexsum(user->password);
+ userinfo["sha256pass"] = sha256->Generate(user->password);
const std::string certfp = SSLClientCert::GetFingerprint(&user->eh);
userinfo["certfp"] = certfp;
diff --git a/src/modules/m_sqloper.cpp b/src/modules/m_sqloper.cpp
index d6581682c..bc46bd7e7 100644
--- a/src/modules/m_sqloper.cpp
+++ b/src/modules/m_sqloper.cpp
@@ -147,7 +147,7 @@ public:
ParamM userinfo;
SQL->PopulateUserInfo(user, userinfo);
userinfo["username"] = username;
- userinfo["password"] = hash ? hash->hexsum(password) : password;
+ userinfo["password"] = hash ? hash->Generate(password) : password;
SQL->submit(new OpMeQuery(this, user->uuid, username, password), query, userinfo);
}