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, "&gt;");
 
-                                                               // 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

Reply via email to