I want to preface that I have not tested this code. I do believe that it will accomplish its goal (and I know that it compiles), but I don't have a dev server up to test it at the moment.
Give it a shot and let me know what you think.
.\common\database.h
Change:
Code:
bool CheckNameFilter(const char* name);
bool CheckUsedName(const char* name);
int32 GetAccountIDByChar(const char* charname, int32* oCharID = 0);
uint32 GetAccountIDByChar(uint32 char_id);
int32 GetAccountIDByName(const char* accname, sint16* status = 0, int32* lsid = 0);
void GetAccountName(int32 accountid, char* name, int32* oLSAccountID = 0);
void GetCharName(int32 char_id, char* name);
int32 GetCharacterInfo(const char* iName, int32* oAccID = 0, int32* oZoneID = 0, float* oX = 0, float* oY = 0, float* oZ = 0);
int32 GetCharacterID(const char *name);
To:
Code:
bool CheckNameFilter(const char* name);
bool CheckUsedName(const char* name);
int32 GetAccountIDByChar(const char* charname, int32* oCharID = 0);
uint32 GetAccountIDByChar(uint32 char_id);
int32 GetAccountIDByName(const char* accname, sint16* status = 0, int32* lsid = 0);
void GetAccountName(int32 accountid, char* name, int32* oLSAccountID = 0);
void GetCharName(int32 char_id, char* name);
int32 GetCharacterInfo(const char* iName, int32* oAccID = 0, int32* oZoneID = 0, float* oX = 0, float* oY = 0, float* oZ = 0);
int32 GetCharacterID(const char *name);
bool CheckBannedIPs(int32 loginIP); //Lieka Edit: Check incomming connection against banned IP table.
.\common\database.cpp
After:
Code:
int32 Database::CheckLogin(const char* name, const char* password, sint16* oStatus) {
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
if(strlen(name) >= 50 || strlen(password) >= 50)
return(0);
char tmpUN[100];
char tmpPW[100];
DoEscapeString(tmpUN, name, strlen(name));
DoEscapeString(tmpPW, password, strlen(password));
if (RunQuery(query, MakeAnyLenString(&query,
"SELECT id, status FROM account WHERE name='%s' AND password is not null "
"and length(password) > 0 and (password='%s' or password=MD5('%s'))",
tmpUN, tmpPW, tmpPW), errbuf, &result)) {
safe_delete_array(query);
if (mysql_num_rows(result) == 1)
{
row = mysql_fetch_row(result);
int32 id = atoi(row[0]);
if (oStatus)
*oStatus = atoi(row[1]);
mysql_free_result(result);
return id;
}
else
{
mysql_free_result(result);
return 0;
}
mysql_free_result(result);
}
else
{
cerr << "Error in CheckLogin query '" << query << "' " << errbuf << endl;
safe_delete_array(query);
return false;
}
return 0;
}
Add:
Code:
//Lieka Edit: Get Banned IP Address List - Only return false if the incoming connection's IP address is not present in the banned_ips table.
bool Database::CheckBannedIPs(int32 loginIP)
{
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
if (RunQuery(query, MakeAnyLenString(&query, "SELECT ip_address FROM Banned_IPs WHERE ip_address='%i'", loginIP), errbuf, &result)) {
safe_delete_array(query);
if (mysql_num_rows(result) == 1)
{
mysql_free_result(result);
return true;
}
else
{
mysql_free_result(result);
return false;
}
mysql_free_result(result);
}
else
{
cerr << "Error in CheckBannedIPs query '" << query << "' " << errbuf << endl;
safe_delete_array(query);
return true;
}
return true;
}
//End Lieka Edit
.\world\client.cpp
After:
Code:
case OP_EnterWorld: // Enter world
{
if (GetAccountID() == 0) {
clog(WORLD__CLIENT_ERR,"Enter world with no logged in account");
eqs->Close();
break;
}
if(GetAdmin() < 0)
{
clog(WORLD__CLIENT,"Account banned or suspended.");
eqs->Close();
break;
}
Add:
Code:
//Lieka Edit Begin
if (RuleI(World, UseBannedIPsTable) == 1) {
if (database.CheckBannedIPs(this->GetIP())) {//Lieka Edit: Check banned_ips table against incoming connection
client_list.RemoveBannedIPs(this->GetIP()); //Lieka Edit: Terminate all sessions with this IP address.
clog(WORLD__CLIENT,"IP Address banned.");
}
}//Lieka Edit End
.\world\clientlist.h
After:
Code:
ClientListEntry* GetCLE(int32 iID);
Add:
Code:
void RemoveBannedIPs(int32 bIP); //Lieka Edit
.\world\clientlist.cpp
After:
Code:
ClientListEntry* ClientList::GetCLE(int32 iID) {
LinkedListIterator<ClientListEntry*> iterator(clientlist);
iterator.Reset();
while(iterator.MoreElements()) {
if (iterator.GetData()->GetID() == iID) {
return iterator.GetData();
}
iterator.Advance();
}
return 0;
}
Add:
Code:
//Lieka Edit Begin: Terminate all active sessions that exist with a banned IP.
void ClientList::RemoveBannedIPs(int32 bIP) {
ClientListEntry* countCLEIPs = 0;
LinkedListIterator<ClientListEntry*> iterator(clientlist);
iterator.Reset();
while (iterator.MoreElements()) {
countCLEIPs = iterator.GetData();
if (countCLEIPs->GetIP() == bIP) {
countCLEIPs->SetOnline(CLE_Status_Offline);
iterator.RemoveCurrent();
}
iterator.Advance();
}
}
//Lieka Edit End
Required SQL:
Code:
CREATE TABLE `Banned_IPs` (
`ip_address` VARCHAR(32) NOT NULL,
PRIMARY KEY (`ip_address`)
)
ENGINE = InnoDB;
Code:
Insert into rule_values values (0, 'World:UseBannedIPsTable', 0);
There is 1 new rule created from this:
World:UseBannedIPsTable = Toggle whether or not to check incoming client connections against the Banned_IPs table. Set this value to 0 to disable this feature.
There is 1 table created from this:
Banned_IPs = this table has 1 column "ip_address". Place IP addresses into this field that should be denied access to your server.
If this code works well, I will create an in-game "#ipban <charname>" command to accompany it.
Thanks,
Dax