1
0
mirror of https://github.com/anope/anope.git synced 2026-07-04 19: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
+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;
}