summaryrefslogtreecommitdiff
path: root/src/tools/db-upgrade.cpp
diff options
context:
space:
mode:
authorNaram Qashat <cyberbotx@cyberbotx.com>2010-08-08 21:53:32 -0400
committerNaram Qashat <cyberbotx@cyberbotx.com>2010-08-08 21:53:32 -0400
commitbbff5ae4d3961d5c2bff61e7d989c4a69c17ffc7 (patch)
tree5c0eeb19ef090c61aac3e0dea98a71d8a78166c1 /src/tools/db-upgrade.cpp
parentde7643a14faf01d84aac8f078608dde13be831b6 (diff)
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.
Diffstat (limited to 'src/tools/db-upgrade.cpp')
-rw-r--r--src/tools/db-upgrade.cpp243
1 files changed, 243 insertions, 0 deletions
diff --git a/src/tools/db-upgrade.cpp b/src/tools/db-upgrade.cpp
new file mode 100644
index 000000000..fe9480803
--- /dev/null
+++ b/src/tools/db-upgrade.cpp
@@ -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;
+}