Author: baufo
Date: Sun Mar 29 18:53:42 2009
New Revision: 34246
URL: http://svn.gna.org/viewcvs/wesnoth?rev=34246&view=rev
Log:
cleanup of the password hashing code and the login protocol (thus breaks
compatibility)
Added:
trunk/src/hash.cpp (with props)
trunk/src/hash.hpp (with props)
Modified:
trunk/src/SConscript
trunk/src/multiplayer.cpp
trunk/src/server/forum_user_handler.cpp
trunk/src/server/forum_user_handler.hpp
trunk/src/server/sample_user_handler.hpp
trunk/src/server/server.cpp
trunk/src/server/user_handler.hpp
Modified: trunk/src/SConscript
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/src/SConscript?rev=34246&r1=34245&r2=34246&view=diff
==============================================================================
--- trunk/src/SConscript (original)
+++ trunk/src/SConscript Sun Mar 29 18:53:42 2009
@@ -17,6 +17,7 @@
color_range.cpp
config.cpp
gettext.cpp
+ hash.cpp
log.cpp
map.cpp
map_location.cpp
Added: trunk/src/hash.cpp
URL: http://svn.gna.org/viewcvs/wesnoth/trunk/src/hash.cpp?rev=34246&view=auto
==============================================================================
--- trunk/src/hash.cpp (added)
+++ trunk/src/hash.cpp Sun Mar 29 18:53:42 2009
@@ -1,0 +1,90 @@
+/* $Id$ */
+/*
+ Copyright (C) 2008 - 2009 by Thomas Baumhauer
<[email protected]>
+ Part of the Battle for Wesnoth Project http://www.wesnoth.org/
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2
+ or at your option any later version.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY.
+
+ See the COPYING file for more details.
+*/
+
+#include <iostream>
+#include <string>
+
+#include "md5.hpp"
+#include "hash.hpp"
+
+namespace util {
+
+const std::string itoa64 =
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" ;
+const std::string hash_prefix = "$H$";
+
+unsigned char* md5(const std::string& input) {
+ MD5 md5_worker;
+ md5_worker.update((unsigned char*) input.c_str(), input.size());
+ md5_worker.finalize();
+ return md5_worker.raw_digest();
+}
+
+int get_iteration_count(const std::string& hash) {
+ return itoa64.find_first_of(hash[3]);
+}
+
+std::string get_salt(const std::string& hash) {
+ return hash.substr(4,8);
+}
+
+bool is_valid_hash(const std::string& hash) {
+ if(hash.size() != 34) return false;
+ if(hash.substr(0,3) != hash_prefix) return false;
+
+ const int iteration_count = get_iteration_count(hash);
+ if(iteration_count < 7 || iteration_count > 30) return false;
+
+ return true;
+}
+
+std::string encode_hash(unsigned char* input) {
+ std::string encoded_hash;
+
+ unsigned int i = 0, value;
+ do {
+ value = input[i++];
+ encoded_hash.append(itoa64.substr(value & 0x3f,1));
+ if(i < 16)
+ value |= (int)input[i] << 8;
+ encoded_hash.append(itoa64.substr((value >> 6) & 0x3f,1));
+ if(i++ >= 16)
+ break;
+ if(i < 16)
+ value |= (int)input[i] << 16;
+ encoded_hash.append(itoa64.substr((value >> 12) & 0x3f,1));
+ if(i++ >= 16)
+ break;
+ encoded_hash.append(itoa64.substr((value >> 18) & 0x3f,1));
+ } while (i < 16);
+
+ return encoded_hash;
+}
+
+std::string create_hash(const std::string& password, const std::string& salt,
int iteration_count) {
+ iteration_count = 1 << iteration_count;
+
+ unsigned char* output = md5(salt + password);
+ do {
+ output = md5(std::string((char *) output, (char *) output +
16).append(password));
+ } while(--iteration_count);
+
+ return encode_hash(output);
+}
+
+bool password_matches_hash(const std::string& password, const std::string&
hash) {
+ return hash.substr(12,34) == create_hash(password, get_salt(hash),
get_iteration_count(hash));
+}
+
+} // namespace util
+
Propchange: trunk/src/hash.cpp
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: trunk/src/hash.cpp
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Added: trunk/src/hash.hpp
URL: http://svn.gna.org/viewcvs/wesnoth/trunk/src/hash.hpp?rev=34246&view=auto
==============================================================================
--- trunk/src/hash.hpp (added)
+++ trunk/src/hash.hpp Sun Mar 29 18:53:42 2009
@@ -1,0 +1,32 @@
+/* $Id$ */
+/*
+ Copyright (C) 2008 - 2009 by Thomas Baumhauer
<[email protected]>
+ Part of the Battle for Wesnoth Project http://www.wesnoth.org/
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2
+ or at your option any later version.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY.
+
+ See the COPYING file for more details.
+*/
+
+#ifndef HASH_HPP_INCLUDED
+#define HASH_HPP_INCLUDED
+
+#include <string>
+
+namespace util {
+
+unsigned char* md5(const std::string& input);
+int get_iteration_count(const std::string& hash);
+std::string get_salt(const std::string& hash);
+bool is_valid_hash(const std::string& hash);
+std::string encode_hash(unsigned char* input);
+std::string create_hash(const std::string& password, const std::string& salt,
int iteration_count =10);
+bool password_matches_hash(const std::string& password, const std::string&
hash);
+
+} // namespace util
+
+#endif // HASH_HPP_INCLUDED
Propchange: trunk/src/hash.hpp
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: trunk/src/hash.hpp
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Modified: trunk/src/multiplayer.cpp
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/src/multiplayer.cpp?rev=34246&r1=34245&r2=34246&view=diff
==============================================================================
--- trunk/src/multiplayer.cpp (original)
+++ trunk/src/multiplayer.cpp Sun Mar 29 18:53:42 2009
@@ -19,7 +19,7 @@
#include "gui/dialogs/mp_connect.hpp"
#include "gui/dialogs/mp_create_game.hpp"
#include "gui/widgets/window.hpp"
-#include "md5.hpp"
+#include "hash.hpp"
#include "multiplayer.hpp"
#include "multiplayer_connect.hpp"
#include "multiplayer_error_codes.hpp"
@@ -242,72 +242,10 @@
for(std::string::size_type pos = 0; (pos = password.find('>', pos)) !=
std::string::npos; ++pos )
password.replace(pos, 1, ">");
- // start the
hashing
- std::string
result;
-
- // Check if we
have everything we need
-
if((*error)["salt"].empty() || (*error)["hash_seed"].empty()) {
- return
ABORT_SERVER;
- }
-
- std::string
itoa64("./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
-
- std::string
salt = (*error)["salt"];
- int hash_seed;
- try {
-
hash_seed = lexical_cast_default<int>((*error)["hash_seed"]);
- } catch
(bad_lexical_cast) {
-
std::cerr << "Bad lexical cast reading hash_seed\n";
- return
ABORT_SERVER;
- }
-
- // Start the
MD5 hashing
-
salt.append(password);
- MD5 md5_worker;
-
md5_worker.update((unsigned char *)salt.c_str(),salt.length());
-
md5_worker.finalize();
- unsigned char *
output = (unsigned char *) malloc (sizeof(unsigned char) * 16);
- output =
md5_worker.raw_digest();
- std::string
temp_hash;
- do {
-
temp_hash = std::string((char *) output, (char *) output + 16);
-
temp_hash.append(password);
- MD5
md5_worker;
-
md5_worker.update((unsigned char *)temp_hash.c_str(),temp_hash.length());
-
md5_worker.finalize();
- output
= md5_worker.raw_digest();
- } while
(--hash_seed);
-
- // Now encode
the resulting mix
- std::string
encoded_hash;
- unsigned int i
= 0, value;
- do {
- value =
output[i++];
-
encoded_hash.append(itoa64.substr(value & 0x3f,1));
- if(i <
16)
-
value |= (int)output[i] << 8;
-
encoded_hash.append(itoa64.substr((value >> 6) & 0x3f,1));
- if(i++
>= 16)
-
break;
- if(i <
16)
-
value |= (int)output[i] << 16;
-
encoded_hash.append(itoa64.substr((value >> 12) & 0x3f,1));
- if(i++
>= 16)
-
break;
-
encoded_hash.append(itoa64.substr((value >> 18) & 0x3f,1));
- } while (i <
16);
- free (output);
-
- // Now mix the
resulting hash with the random seed
- result =
encoded_hash + (*error)["random_salt"];
-
- MD5 md5_worker2;
-
md5_worker2.update((unsigned char *)result.c_str(), result.size());
-
md5_worker2.finalize();
-
- result =
std::string(md5_worker2.hex_digest());
-
- sp["password"]
= result;
+ const
std::string salt = (*error)["salt"];
+
+ sp["password"]
= util::create_hash(util::create_hash(password, util::get_salt(salt),
+
util::get_iteration_count(salt)), salt.substr(12, 8));
} else {
sp["password"]
= password;
Modified: trunk/src/server/forum_user_handler.cpp
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/src/server/forum_user_handler.cpp?rev=34246&r1=34245&r2=34246&view=diff
==============================================================================
--- trunk/src/server/forum_user_handler.cpp (original)
+++ trunk/src/server/forum_user_handler.cpp Sun Mar 29 18:53:42 2009
@@ -15,6 +15,7 @@
#ifdef HAVE_MYSQLPP
#include "forum_user_handler.hpp"
+#include "../hash.hpp"
#include <stdlib.h>
#include <sstream>
@@ -61,32 +62,25 @@
}
// Check hash prefix, if different than $H$ hash is invalid
- if(hash.substr(0,3) != "$H$") {
- ERR_UH << "Invalid hash prefix for user '" << name << "'" <<
std::endl;
- return false;
- }
-
- std::string valid_hash = hash.substr(12,34) + seed;
- MD5 md5_worker;
- md5_worker.update((unsigned char *)valid_hash.c_str(),
valid_hash.size());
- md5_worker.finalize();
- valid_hash = std::string(md5_worker.hex_digest());
+ if(!util::is_valid_hash(hash)) {
+ ERR_UH << "Invalid hash for user '" << name << "'" << std::endl;
+ return false;
+ }
+
+ std::string valid_hash = util::create_hash(hash.substr(12,34), seed);
if(password == valid_hash) return true;
return false;
}
-std::string fuh::create_pepper(const std::string& name, int index) {
+std::string fuh::create_pepper(const std::string& name) {
// Some doulbe security, this should never be neeeded
if(!(user_exists(name))) {
return "";
}
- // Set an alphabet-like string for use in encrytpion algorithm
- std::string
itoa64("./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
-
std::string hash;
try {
@@ -96,33 +90,9 @@
return "";
}
- // Check hash prefix, if different than $H$ hash is invalid
- if(hash.substr(0,3) != "$H$")
- return "";
-
- if(index == 0) {
- // Start of the encryption, get the position of first
nonidentifier character in extended alphabet
- int hash_seed = itoa64.find_first_of(hash[3]);
-
- // If position is lower than 8 or higher than 32 hash is also
invalid
- if(hash_seed < 7 || hash_seed > 30)
- return "";
-
- // Set the number of encryption passes as 2^position
- hash_seed = 1 << hash_seed;
-
- std::stringstream ss;
- ss << hash_seed;
- return ss.str();
-
- } else if (index == 1) {
- // Create salt for mixing with the hash
- return hash.substr(4,8);
-
- } else {
- return "";
- }
-
+ if(!util::is_valid_hash(hash)) return "";
+
+ return hash.substr(0,12);
}
void fuh::user_logged_in(const std::string& name) {
Modified: trunk/src/server/forum_user_handler.hpp
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/src/server/forum_user_handler.hpp?rev=34246&r1=34245&r2=34246&view=diff
==============================================================================
--- trunk/src/server/forum_user_handler.hpp (original)
+++ trunk/src/server/forum_user_handler.hpp Sun Mar 29 18:53:42 2009
@@ -20,7 +20,6 @@
#include <vector>
#include <mysql/mysql.h>
-#include "../md5.hpp"
/**
* @class A user_handler implementation to link the server
@@ -58,12 +57,10 @@
/**
* Needed because the hashing algorithm used by phpbb requires
some info
* from the original hash to recreate the same hash
- * index = 0 returns the hash seed
- * index = 1 return the salt
*
* Return an empty string if an error occurs
*/
- std::string create_pepper(const std::string& name, int index);
+ std::string create_pepper(const std::string& name);
void user_logged_in(const std::string& name);
Modified: trunk/src/server/sample_user_handler.hpp
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/src/server/sample_user_handler.hpp?rev=34246&r1=34245&r2=34246&view=diff
==============================================================================
--- trunk/src/server/sample_user_handler.hpp (original)
+++ trunk/src/server/sample_user_handler.hpp Sun Mar 29 18:53:42 2009
@@ -62,7 +62,7 @@
void set_user_detail(const std::string& user, const
std::string& detail, const std::string& value);
std::string get_valid_details();
- std::string create_pepper(const std::string&, int) { return "";
}
+ std::string create_pepper(const std::string&) { return ""; }
bool use_phpbb_encryption() const { return false; }
private:
Modified: trunk/src/server/server.cpp
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/src/server/server.cpp?rev=34246&r1=34245&r2=34246&view=diff
==============================================================================
--- trunk/src/server/server.cpp (original)
+++ trunk/src/server/server.cpp Sun Mar 29 18:53:42 2009
@@ -460,10 +460,9 @@
void server::send_password_request(network::connection sock, const char* msg,
const std::string& user, const char* error_code, bool
force_confirmation)
{
- std::string salt1 = user_handler_->create_salt();
- std::string salt2 = user_handler_->create_pepper(user, 0);
- std::string salt3 = user_handler_->create_pepper(user, 1);
- if(user_handler_->use_phpbb_encryption() && (salt2.empty() ||
salt3.empty())) {
+ std::string salt = user_handler_->create_salt();
+ std::string pepper = user_handler_->create_pepper(user);
+ if(user_handler_->use_phpbb_encryption() && pepper.empty()) {
send_error(sock, "Even though your nick is registered on this
server you "
"cannot log in due to an error in the
hashing algorithm. "
"Logging into your forum account on
http://forum.wesnoth.org "
@@ -471,16 +470,14 @@
return;
}
- seeds_.insert(std::pair<network::connection,std::string>(sock, salt1));
+ seeds_.insert(std::pair<network::connection,std::string>(sock, salt));
simple_wml::document doc;
doc.root().add_child("error").set_attr("message", msg);
(*(doc.root().child("error"))).set_attr("password_request", "yes");
(*(doc.root().child("error"))).set_attr("phpbb_encryption",
user_handler_->use_phpbb_encryption() ? "yes" : "no");
- (*(doc.root().child("error"))).set_attr("random_salt", salt1.c_str());
- (*(doc.root().child("error"))).set_attr("hash_seed", salt2.c_str());
- (*(doc.root().child("error"))).set_attr("salt", salt3.c_str());
+ (*(doc.root().child("error"))).set_attr("salt", (pepper +
salt).c_str());
(*(doc.root().child("error"))).set_attr("force_confirmation",
force_confirmation ? "yes" : "no");
if(strlen(error_code))
(*(doc.root().child("error"))).set_attr("error_code", error_code);
Modified: trunk/src/server/user_handler.hpp
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/src/server/user_handler.hpp?rev=34246&r1=34245&r2=34246&view=diff
==============================================================================
--- trunk/src/server/user_handler.hpp (original)
+++ trunk/src/server/user_handler.hpp Sun Mar 29 18:53:42 2009
@@ -145,7 +145,7 @@
*
* If not needed let it return and empty string or whatever you
feel like.
*/
- virtual std::string create_pepper(const std::string& name, int
index) =0;
+ virtual std::string create_pepper(const std::string& username)
=0;
/**
* Does this user_handler want passwords passed encrypted using
phpbb's algorithm?
_______________________________________________
Wesnoth-commits mailing list
[email protected]
https://mail.gna.org/listinfo/wesnoth-commits