forum_auth.cpp

Go to the documentation of this file.
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 // This class holds the result of authorisation against forum table for user_name
00010 // and password given. That result can be allways accesed by is_authorised() method.
00011 // Class throws an exception error (std::string) on :
00012 // * Failure to obtain database connection data
00013 // * Failure to connect to database
00014 // * Failure to find entry coresponding to username
00015 
00016 class forum_auth
00017 {
00018     private :
00019 // The class will only hold data provided by the user and the result of their validation
00020 // It's not required or desirable to remember data pulled out from the forum tables.            
00021         std::string user_name;
00022         std::string user_password;
00023         bool authorised;
00024         bool validate(void);
00025     public :
00026 // Constructor - sets the data and evaluates them          
00027         forum_auth(std::string name, std::string password);
00028 // Destructor is empty
00029         ~forum_auth(void);
00030 // Function to return authorisation status
00031         bool is_authorised(void);
00032 };
00033 // Destructor
00034 forum_auth::~forum_auth(void)
00035 {
00036 }
00037 // Constructor
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 // Validation function
00045 bool forum_auth::validate(void)
00046 {
00047 // Set an alphabet-like string for use in encrytpion algorithm   
00048     std::string itoa64("./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");                                    
00049     std::string hash, db_name, db_host, db_user, db_password;
00050 // Get the database acces details
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 // Connect to the database
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 // Retrive users' password as hash
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 // Check hash prefix, if different than $H$ hash is invalid
00080     if(hash.substr(0,3) != "$H$")
00081         return false;
00082 // Start of the encryption, get the position of first nonidentifier character in extended alphabet
00083     int hash_seed = itoa64.find_first_of(hash[3]);
00084 // If position is lower than 8 or higher than 32 hash is also invalid
00085     if(hash_seed < 7 || hash_seed > 30)
00086         return false;
00087 // Set the number of encryption passes as 2^position
00088     hash_seed = 1 << hash_seed;
00089 // Create salt for mixing with the hash
00090     std::string salt=hash.substr(4,8);
00091 // Start the MD5 hashing
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 // Now encode the resulting mix 
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 // Get the first 12 characters from correct hash
00131     std::string result = hash.substr(0,12);    
00132 // Append encoded results to the end of it
00133     result.append(encoded_hash);
00134 // Check if reult of above matches the original hash
00135     if( result != hash)
00136         return false;
00137     return true;
00138 }
00139 // Function returning status
00140 bool forum_auth::is_authorised(void)
00141 {
00142     return authorised;
00143 }
00144 
00145 } // End of forum_auth namespace
00146 

Generated by doxygen 1.5.5 on 23 May 2008 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs