00001 #include <string>
00002 #include <iostream>
00003 #include "md5.hpp"
00004 #include <string.h>
00005 #include <mysql++.h>
00006
00007 namespace forum_auth {
00008
00009
00010
00011
00012
00013
00014
00015
00016 class forum_auth
00017 {
00018 private :
00019
00020
00021 std::string user_name;
00022 std::string user_password;
00023 bool authorised;
00024 bool validate(void);
00025 public :
00026
00027 forum_auth(std::string name, std::string password);
00028
00029 ~forum_auth(void);
00030
00031 bool is_authorised(void);
00032 };
00033
00034 forum_auth::~forum_auth(void)
00035 {
00036 }
00037
00038 forum_auth::forum_auth(std::string name, std::string password)
00039 {
00040 user_name = name;
00041 user_password = password;
00042 authorised = validate();
00043 }
00044
00045 bool forum_auth::validate(void)
00046 {
00047
00048 std::string itoa64("./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
00049 std::string hash, db_name, db_host, db_user, db_password;
00050
00051 std::fstream db_access_file("db_auth_data.cfg", std::fstream::out);
00052 if(!db_access_file.is_open())
00053 {
00054 std::string error("Forum auth : No file with access data\n");
00055 throw error;
00056 }
00057 db_access_file >> db_name;
00058 db_access_file >> db_host;
00059 db_access_file >> db_user;
00060 db_access_file >> db_password;
00061
00062 mysqlpp::Connection db_interface(false);
00063 if (!db_interface.connect(db_name, db_host, db_user, db_password))
00064 {
00065 std::string error("Forum auth : Connection to the databese failed\n");
00066 throw error;
00067 }
00068
00069 std::string sql("SELECT hash FROM phpbb3_wesnothd WHERE username='");
00070 sql.append(user_name);
00071 sql.append("'");
00072 mysqlpp::Query query = db_interface.query(sql);
00073 if(!(mysqlpp::StoreQueryReult sql_res = query.store()))
00074 {
00075 std::string error("Forum auth : User not found");
00076 throw error;
00077 }
00078 hash = std::string(sql_res[0][0]);
00079
00080 if(hash.substr(0,3) != "$H$")
00081 return false;
00082
00083 int hash_seed = itoa64.find_first_of(hash[3]);
00084
00085 if(hash_seed < 7 || hash_seed > 30)
00086 return false;
00087
00088 hash_seed = 1 << hash_seed;
00089
00090 std::string salt=hash.substr(4,8);
00091
00092 salt.append(user_password);
00093 MD5 md5_worker;
00094 md5_worker.update((unsigned char *)salt.c_str(),salt.length());
00095 md5_worker.finalize();
00096 unsigned char * output = (unsigned char *) malloc (sizeof(unsigned char) * 16);
00097 output = md5_worker.raw_digest();
00098 std::string temp_hash;
00099 do
00100 {
00101 temp_hash = std::string((char *) output, (char *) output + 16);
00102 temp_hash.append(user_password);
00103 md5_worker.~MD5();
00104 MD5 md5_worker;
00105 md5_worker.update((unsigned char *)temp_hash.c_str(),temp_hash.length());
00106 md5_worker.finalize();
00107 output = md5_worker.raw_digest();
00108 } while (--hash_seed);
00109 temp_hash = std::string((char *) output, (char *) output + 16);
00110
00111 std::string encoded_hash;
00112 unsigned int i = 0, value;
00113 do
00114 {
00115 value = output[i++];
00116 encoded_hash.append(itoa64.substr(value & 0x3f,1));
00117 if(i < 16)
00118 value |= (int)output[i] << 8;
00119 encoded_hash.append(itoa64.substr((value >> 6) & 0x3f,1));
00120 if(i++ >= 16)
00121 break;
00122 if(i < 16)
00123 value |= (int)output[i] << 16;
00124 encoded_hash.append(itoa64.substr((value >> 12) & 0x3f,1));
00125 if(i++ >= 16)
00126 break;
00127 encoded_hash.append(itoa64.substr((value >> 18) & 0x3f,1));
00128 } while (i < 16);
00129 free (output);
00130
00131 std::string result = hash.substr(0,12);
00132
00133 result.append(encoded_hash);
00134
00135 if( result != hash)
00136 return false;
00137 return true;
00138 }
00139
00140 bool forum_auth::is_authorised(void)
00141 {
00142 return authorised;
00143 }
00144
00145 }
00146