1
0
mirror of https://github.com/anope/anope.git synced 2026-07-04 05:33:12 +02:00

Add a db-upgrade to convert base64-encoded encrypted passwords to hexadecimal strings of the raw data, add in Anope::Hex for C-style strings and added Anope::Unhex, modified the encryption modules to use Hex and Unhex.

This commit is contained in:
Naram Qashat
2010-08-08 21:53:32 -04:00
parent de7643a14f
commit bbff5ae4d3
7 changed files with 304 additions and 20 deletions
+8
View File
@@ -322,6 +322,14 @@ namespace Anope
* @return a anope::string containing the hex value
*/
extern CoreExport string Hex(const string &data);
extern CoreExport string Hex(const char *data, unsigned len);
/** Converts a string from hex
* @param src The data to be converted
* @param dest The destination string
*/
extern CoreExport void Unhex(const Anope::string &src, Anope::string &dest);
extern CoreExport void Unhex(const Anope::string &src, char *dest);
}
/** sepstream allows for splitting token seperated lists.
+2 -4
View File
@@ -330,14 +330,12 @@ class EMD5 : public Module
MD5_CTX context;
char digest[17] = "";
Anope::string buf = "md5:";
Anope::string cpass;
MD5Init(&context);
MD5Update(&context, reinterpret_cast<const unsigned char *>(src.c_str()), src.length());
MD5Final(reinterpret_cast<char *>(digest), &context);
MD5Final(reinterpret_cast<unsigned char *>(digest), &context);
b64_encode(digest, cpass);
buf += cpass;
buf += Anope::Hex(digest, 16);
Alog(LOG_DEBUG_2) << "(enc_md5) hashed password from [" << src << "] to [" << buf << "]";
dest = buf;
return EVENT_ALLOW;
+1 -3
View File
@@ -334,7 +334,6 @@ class EOld : public Module
{
MD5_CTX context;
char digest[33] = "", digest2[17] = "";
Anope::string cpass;
int i;
Anope::string buf = "oldmd5:";
@@ -346,8 +345,7 @@ class EOld : public Module
for (i = 0; i < 32; i += 2)
digest2[i / 2] = XTOI(digest[i]) << 4 | XTOI(digest[i + 1]);
b64_encode(digest2, cpass);
buf += cpass;
buf += Anope::Hex(digest2, 16);
Alog(LOG_DEBUG_2) << "(enc_old) hashed password from [" << src << "] to [" << buf << "]";
dest = buf;
return EVENT_ALLOW;
+1 -3
View File
@@ -184,14 +184,12 @@ class ESHA1 : public Module
SHA1_CTX context;
char digest[21] = "";
Anope::string buf = "sha1:";
Anope::string cpass;
SHA1Init(&context);
SHA1Update(&context, reinterpret_cast<const unsigned char *>(src.c_str()), src.length());
SHA1Final(reinterpret_cast<unsigned char *>(digest), &context);
b64_encode(digest, cpass);
buf += cpass;
buf += Anope::Hex(digest, 20);
Alog(LOG_DEBUG_2) << "(enc_sha1) hashed password from [" << src << "] to [" << buf << "]";
dest = buf;
return EVENT_ALLOW;
+5 -9
View File
@@ -135,12 +135,10 @@ class ESHA256 : public Module
Anope::string GetIVString()
{
char buf[33];
Anope::string buf2;
for (int i = 0; i < 8; ++i)
UNPACK32(iv[i], reinterpret_cast<unsigned char *>(&buf[i << 2]));
buf[32] = '\0';
b64_encode(buf, buf2);
return buf2;
return Anope::Hex(buf, 32);
}
/* splits the appended IV from the password string so it can be used for the next encryption */
@@ -149,8 +147,8 @@ class ESHA256 : public Module
{
size_t pos = password.find(':');
Anope::string buf = password.substr(password.find(':', pos + 1) + 1, password.length());
Anope::string buf2;
b64_decode(buf, buf2);
char buf2[33];
Anope::Unhex(buf, buf2);
for (int i = 0 ; i < 8; ++i)
PACK32(reinterpret_cast<unsigned char *>(&buf2[i << 2]), iv[i]);
}
@@ -263,8 +261,7 @@ class ESHA256 : public Module
EventReturn OnEncrypt(const Anope::string &src, Anope::string &dest)
{
char digest[SHA256_DIGEST_SIZE+1];
Anope::string cpass;
char digest[SHA256_DIGEST_SIZE + 1];
SHA256Context ctx;
std::stringstream buf;
@@ -277,8 +274,7 @@ class ESHA256 : public Module
SHA256Update(&ctx, reinterpret_cast<const unsigned char *>(src.c_str()), src.length());
SHA256Final(&ctx, reinterpret_cast<unsigned char *>(digest));
digest[SHA256_DIGEST_SIZE] = '\0';
b64_encode(digest, cpass);
buf << "sha256:" << cpass << ":" << GetIVString();
buf << "sha256:" << Anope::Hex(digest, SHA256_DIGEST_SIZE) << ":" << GetIVString();
Alog(LOG_DEBUG_2) << "(enc_sha256) hashed password from [" << src << "] to [" << buf.str() << " ]";
dest = buf.str();
return EVENT_ALLOW;
+44 -1
View File
@@ -1319,7 +1319,6 @@ bool str_is_cidr(const Anope::string &str, uint32 &ip, uint32 &mask, Anope::stri
* @param the data to be converted
* @return a anope::string containing the hex value
*/
Anope::string Anope::Hex(const Anope::string &data)
{
const char hextable[] = "0123456789abcdef";
@@ -1335,3 +1334,47 @@ Anope::string Anope::Hex(const Anope::string &data)
return rv;
}
Anope::string Anope::Hex(const char *data, unsigned len)
{
const char hextable[] = "0123456789abcdef";
Anope::string rv;
for (size_t i = 0; i < len; ++i)
{
unsigned char c = data[i];
rv += hextable[c >> 4];
rv += hextable[c & 0xF];
}
return rv;
}
/** Converts a string from hex
* @param src The data to be converted
* @param dest The destination string
*/
void Anope::Unhex(const Anope::string &src, Anope::string &dest)
{
size_t len = src.length();
Anope::string rv;
for (size_t i = 0; i < len; i += 2)
{
char h = src[i], l = src[i + 1];
unsigned char byte = (h >= 'a' ? h - 'a' + 10 : h - '0') << 4;
byte += (l >= 'a' ? l - 'a' + 10 : l - '0');
rv += byte;
}
dest = rv;
}
void Anope::Unhex(const Anope::string &src, char *dest)
{
size_t len = src.length(), destpos = 0;
for (size_t i = 0; i < len; i += 2)
{
char h = src[i], l = src[i + 1];
unsigned char byte = (h >= 'a' ? h - 'a' + 10 : h - '0') << 4;
byte += (l >= 'a' ? l - 'a' + 10 : l - '0');
dest[destpos++] = byte;
}
dest[destpos] = 0;
}
+243
View File
@@ -0,0 +1,243 @@
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
#ifndef _WIN32
static const std::string C_LBLUE = "\033[1;34m";
static const std::string C_NONE = "\033[m";
#else
static const std::string C_LBLUE = "";
static const std::string C_NONE = "";
#endif
/** sepstream allows for splitting token seperated lists.
* Each successive call to sepstream::GetToken() returns
* the next token, until none remain, at which point the method returns
* an empty string.
*/
class sepstream
{
private:
/** Original string.
*/
std::string tokens;
/** Last position of a seperator token
*/
std::string::iterator last_starting_position;
/** Current string position
*/
std::string::iterator n;
/** Seperator value
*/
char sep;
public:
/** Create a sepstream and fill it with the provided data
*/
sepstream(const std::string &source, char seperator);
virtual ~sepstream() { }
/** Fetch the next token from the stream
* @param token The next token from the stream is placed here
* @return True if tokens still remain, false if there are none left
*/
virtual bool GetToken(std::string &token);
/** Fetch the entire remaining stream, without tokenizing
* @return The remaining part of the stream
*/
virtual const std::string GetRemaining();
/** Returns true if the end of the stream has been reached
* @return True if the end of the stream has been reached, otherwise false
*/
virtual bool StreamEnd();
};
sepstream::sepstream(const std::string &source, char seperator) : tokens(source), sep(seperator)
{
last_starting_position = n = tokens.begin();
}
bool sepstream::GetToken(std::string &token)
{
std::string::iterator lsp = last_starting_position;
while (n != tokens.end())
{
if (*n == sep || n + 1 == tokens.end())
{
last_starting_position = n + 1;
token = std::string(lsp, n + 1 == tokens.end() ? n + 1 : n);
while (token.length() && token.rfind(sep) == token.length() - 1)
token.erase(token.end() - 1);
++n;
return true;
}
++n;
}
token.clear();
return false;
}
const std::string sepstream::GetRemaining()
{
return std::string(n, tokens.end());
}
bool sepstream::StreamEnd()
{
return n == tokens.end();
}
std::vector<std::string> BuildStringVector(const std::string &src, char delim = ' ')
{
sepstream tokens(src, delim);
std::string token;
std::vector<std::string> Ret;
while (tokens.GetToken(token))
Ret.push_back(token);
return Ret;
}
std::string Hex(const char *data, size_t len)
{
const char hextable[] = "0123456789abcdef";
std::string rv;
for (size_t i = 0; i < len; ++i)
{
unsigned char c = data[i];
rv += hextable[c >> 4];
rv += hextable[c & 0xF];
}
return rv;
}
static const std::string Base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static const char Pad64 = '=';
unsigned b64_decode(const std::string &src, char *target)
{
unsigned state = 0, tarindex = 0;
std::string::const_iterator ch = src.begin(), end = src.end();
for (; ch != end; ++ch)
{
if (isspace(*ch)) /* Skip whitespace anywhere */
continue;
if (*ch == Pad64)
break;
size_t pos = Base64.find(*ch);
if (pos == std::string::npos) /* A non-base64 character */
return 0;
switch (state)
{
case 0:
target[tarindex] = pos << 2;
state = 1;
break;
case 1:
target[tarindex++] |= pos >> 4;
target[tarindex] = (pos & 0x0f) << 4;
state = 2;
break;
case 2:
target[tarindex++] |= pos >> 2;
target[tarindex] = (pos & 0x03) << 6;
state = 3;
break;
case 3:
target[tarindex++] |= pos;
state = 0;
}
}
return tarindex;
}
int main(int argc, char *argv[])
{
std::cout << C_LBLUE << "Anope 1.9.2 -> 1.9.3 database upgrader" << C_NONE << std::endl << std::endl;
std::ifstream in("anope.db.old");
if (!in.is_open())
{
std::cout << C_LBLUE << "Could not open anope.db.old for reading" << C_NONE << std::endl << std::endl;
return 1;
}
std::ofstream out("anope.db");
if (!out.is_open())
{
std::cout << C_LBLUE << "Could not open anope.db for writing" << C_NONE << std::endl << std::endl;
in.close();
return 1;
}
std::string line;
while (getline(in, line))
{
if (line.substr(0, 2) == "NC")
{
std::vector<std::string> parts = BuildStringVector(line);
std::string password = parts[2];
size_t colon = password.find(':');
if (colon != std::string::npos && password.substr(0, colon) != "plain")
{
std::string hash = password.substr(colon + 1), iv;
unsigned len;
if (password.substr(0, colon) == "sha256")
{
colon = hash.find(':');
iv = hash.substr(colon + 1);
hash = hash.substr(0, colon);
char *iv_decoded = new char[iv.length() * 3 / 4 + 1];
memset(iv_decoded, 0, iv.length() * 3 / 4 + 1);
len = b64_decode(iv, iv_decoded);
if (len)
iv = Hex(iv_decoded, len);
else
iv.clear();
delete [] iv_decoded;
}
char *hash_decoded = new char[hash.length() * 3 / 4 + 1];
memset(hash_decoded, 0, hash.length() * 3 / 4 + 1);
len = b64_decode(hash, hash_decoded);
if (len)
hash = Hex(hash_decoded, len);
else
hash.clear();
delete [] hash_decoded;
password = password.substr(0, colon + 1);
if (!hash.empty())
password += hash;
if (!iv.empty())
password += ":" + iv;
parts[2] = password;
}
line.clear();
for (unsigned part = 0, end = parts.size(); part < end; ++part)
{
if (part)
line += ' ';
line += parts[part];
}
}
out << line << std::endl;
}
in.close();
out.close();
return 0;
}