config: harden admin page secrets
This commit is contained in:
@@ -1,4 +1,8 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
|
#include <array>
|
||||||
|
#include <cerrno>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <limits>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#ifndef OS_WINDOWS
|
#ifndef OS_WINDOWS
|
||||||
#include <ifaddrs.h>
|
#include <ifaddrs.h>
|
||||||
@@ -20,6 +24,161 @@
|
|||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
enum class ESqlConfigIndex : size_t
|
||||||
|
{
|
||||||
|
Account = 0,
|
||||||
|
Player = 1,
|
||||||
|
Common = 2,
|
||||||
|
Count = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SqlConnectionConfig
|
||||||
|
{
|
||||||
|
std::string host;
|
||||||
|
std::string user;
|
||||||
|
std::string password;
|
||||||
|
std::string database;
|
||||||
|
int port = 0;
|
||||||
|
|
||||||
|
bool IsConfigured() const
|
||||||
|
{
|
||||||
|
return !host.empty() && !user.empty() && !password.empty() && !database.empty();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
bool ReadEnvString(const char* envName, std::string& output)
|
||||||
|
{
|
||||||
|
const char* envValue = std::getenv(envName);
|
||||||
|
if (!envValue || !*envValue)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
output = envValue;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ReadEnvPort(const char* envName, int& output)
|
||||||
|
{
|
||||||
|
const char* envValue = std::getenv(envName);
|
||||||
|
if (!envValue || !*envValue)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
char* end = nullptr;
|
||||||
|
unsigned long parsed = std::strtoul(envValue, &end, 10);
|
||||||
|
if (errno != 0 || end == envValue || *end != '\0' || parsed > std::numeric_limits<uint16_t>::max())
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Invalid %s value: %s\n", envName, envValue);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
output = static_cast<int>(parsed);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LogEnvOverride(const char* envName)
|
||||||
|
{
|
||||||
|
fprintf(stdout, "CONFIG: using %s override\n", envName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ApplySqlEnvOverrides(const char* prefix, SqlConnectionConfig& config)
|
||||||
|
{
|
||||||
|
char envName[64];
|
||||||
|
|
||||||
|
snprintf(envName, sizeof(envName), "METIN2_%s_HOST", prefix);
|
||||||
|
if (ReadEnvString(envName, config.host))
|
||||||
|
LogEnvOverride(envName);
|
||||||
|
|
||||||
|
snprintf(envName, sizeof(envName), "METIN2_%s_USER", prefix);
|
||||||
|
if (ReadEnvString(envName, config.user))
|
||||||
|
LogEnvOverride(envName);
|
||||||
|
|
||||||
|
snprintf(envName, sizeof(envName), "METIN2_%s_PASSWORD", prefix);
|
||||||
|
if (ReadEnvString(envName, config.password))
|
||||||
|
LogEnvOverride(envName);
|
||||||
|
|
||||||
|
snprintf(envName, sizeof(envName), "METIN2_%s_DATABASE", prefix);
|
||||||
|
if (ReadEnvString(envName, config.database))
|
||||||
|
LogEnvOverride(envName);
|
||||||
|
|
||||||
|
snprintf(envName, sizeof(envName), "METIN2_%s_PORT", prefix);
|
||||||
|
if (ReadEnvPort(envName, config.port))
|
||||||
|
LogEnvOverride(envName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParseSqlConfigOrExit(const char* tokenName, const char* value, SqlConnectionConfig& config)
|
||||||
|
{
|
||||||
|
char host[64];
|
||||||
|
char user[64];
|
||||||
|
char password[64];
|
||||||
|
char database[64];
|
||||||
|
int port = 0;
|
||||||
|
|
||||||
|
*host = '\0';
|
||||||
|
*user = '\0';
|
||||||
|
*password = '\0';
|
||||||
|
*database = '\0';
|
||||||
|
|
||||||
|
const char* line = two_arguments(value, host, sizeof(host), user, sizeof(user));
|
||||||
|
line = two_arguments(line, password, sizeof(password), database, sizeof(database));
|
||||||
|
|
||||||
|
if (line[0])
|
||||||
|
{
|
||||||
|
char portBuffer[32];
|
||||||
|
one_argument(line, portBuffer, sizeof(portBuffer));
|
||||||
|
str_to_number(port, portBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!*host || !*user || !*password || !*database)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s syntax: %s <host user password db [port]>\n", tokenName, tokenName);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
config.host = host;
|
||||||
|
config.user = user;
|
||||||
|
config.password = password;
|
||||||
|
config.database = database;
|
||||||
|
config.port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ValidateSqlConfigOrExit(const char* label, const SqlConnectionConfig& config)
|
||||||
|
{
|
||||||
|
if (config.IsConfigured())
|
||||||
|
return;
|
||||||
|
|
||||||
|
fprintf(stderr, "%s must be configured as <host user password db [port]>\n", label);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ApplyAdminPagePasswordEnvOverride()
|
||||||
|
{
|
||||||
|
if (ReadEnvString("METIN2_ADMINPAGE_PASSWORD", g_stAdminPagePassword))
|
||||||
|
LogEnvOverride("METIN2_ADMINPAGE_PASSWORD");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ValidateAdminPageConfigOrExit()
|
||||||
|
{
|
||||||
|
if (!IsAdminPageEnabled())
|
||||||
|
{
|
||||||
|
if (!g_stAdminPageIP.empty())
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ADMIN_PAGE_PASSWORD must be configured when adminpage_ip is set\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stdout, "ADMIN_PAGE: disabled\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_stAdminPageIP.empty())
|
||||||
|
fprintf(stdout, "ADMIN_PAGE: enabled without IP restriction\n");
|
||||||
|
else
|
||||||
|
fprintf(stdout, "ADMIN_PAGE: enabled for %zu IP entries\n", g_stAdminPageIP.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BYTE g_bChannel = 0;
|
BYTE g_bChannel = 0;
|
||||||
WORD mother_port = 50080;
|
WORD mother_port = 50080;
|
||||||
int passes_per_sec = 25;
|
int passes_per_sec = 25;
|
||||||
@@ -75,7 +234,7 @@ string g_stDefaultQuestObjectDir = "./quest/object";
|
|||||||
std::set<string> g_setQuestObjectDir;
|
std::set<string> g_setQuestObjectDir;
|
||||||
|
|
||||||
std::vector<std::string> g_stAdminPageIP;
|
std::vector<std::string> g_stAdminPageIP;
|
||||||
std::string g_stAdminPagePassword = "SHOWMETHEMONEY";
|
std::string g_stAdminPagePassword;
|
||||||
|
|
||||||
string g_stBlockDate = "30000705";
|
string g_stBlockDate = "30000705";
|
||||||
|
|
||||||
@@ -195,7 +354,12 @@ static void FN_log_adminpage()
|
|||||||
++iter;
|
++iter;
|
||||||
}
|
}
|
||||||
|
|
||||||
sys_log(1, "ADMIN_PAGE_PASSWORD = %s", g_stAdminPagePassword.c_str());
|
sys_log(1, "ADMIN_PAGE_PASSWORD = %s", IsAdminPageEnabled() ? "[configured]" : "[disabled]");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsAdminPageEnabled()
|
||||||
|
{
|
||||||
|
return !g_stAdminPagePassword.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -340,35 +504,14 @@ void config_init(const string& st_localeServiceName)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
char db_host[3][64], db_user[3][64], db_pwd[3][64], db_db[3][64];
|
std::array<SqlConnectionConfig, static_cast<size_t>(ESqlConfigIndex::Count)> dbConfig;
|
||||||
// ... 아... db_port는 이미 있는데... 네이밍 어찌해야함...
|
SqlConnectionConfig logConfig;
|
||||||
int mysql_db_port[3];
|
|
||||||
|
|
||||||
for (int n = 0; n < 3; ++n)
|
|
||||||
{
|
|
||||||
*db_host[n] = '\0';
|
|
||||||
*db_user[n] = '\0';
|
|
||||||
*db_pwd[n]= '\0';
|
|
||||||
*db_db[n]= '\0';
|
|
||||||
mysql_db_port[n] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
char log_host[64], log_user[64], log_pwd[64], log_db[64];
|
|
||||||
int log_port = 0;
|
|
||||||
|
|
||||||
*log_host = '\0';
|
|
||||||
*log_user = '\0';
|
|
||||||
*log_pwd = '\0';
|
|
||||||
*log_db = '\0';
|
|
||||||
|
|
||||||
|
|
||||||
// DB에서 로케일정보를 세팅하기위해서는 다른 세팅값보다 선행되어서
|
// DB에서 로케일정보를 세팅하기위해서는 다른 세팅값보다 선행되어서
|
||||||
// DB정보만 읽어와 로케일 세팅을 한후 다른 세팅을 적용시켜야한다.
|
// DB정보만 읽어와 로케일 세팅을 한후 다른 세팅을 적용시켜야한다.
|
||||||
// 이유는 로케일관련된 초기화 루틴이 곳곳에 존재하기 때문.
|
// 이유는 로케일관련된 초기화 루틴이 곳곳에 존재하기 때문.
|
||||||
|
|
||||||
bool isCommonSQL = false;
|
|
||||||
bool isPlayerSQL = false;
|
|
||||||
|
|
||||||
FILE* fp_common;
|
FILE* fp_common;
|
||||||
if (!(fp_common = fopen("conf/game.txt", "r")))
|
if (!(fp_common = fopen("conf/game.txt", "r")))
|
||||||
{
|
{
|
||||||
@@ -381,96 +524,25 @@ void config_init(const string& st_localeServiceName)
|
|||||||
|
|
||||||
TOKEN("account_sql")
|
TOKEN("account_sql")
|
||||||
{
|
{
|
||||||
const char* line = two_arguments(value_string, db_host[0], sizeof(db_host[0]), db_user[0], sizeof(db_user[0]));
|
ParseSqlConfigOrExit("account_sql", value_string, dbConfig[static_cast<size_t>(ESqlConfigIndex::Account)]);
|
||||||
line = two_arguments(line, db_pwd[0], sizeof(db_pwd[0]), db_db[0], sizeof(db_db[0]));
|
|
||||||
|
|
||||||
if (line[0])
|
|
||||||
{
|
|
||||||
char buf[256];
|
|
||||||
one_argument(line, buf, sizeof(buf));
|
|
||||||
str_to_number(mysql_db_port[0], buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!*db_host[0] || !*db_user[0] || !*db_pwd[0] || !*db_db[0])
|
|
||||||
{
|
|
||||||
fprintf(stderr, "PLAYER_SQL syntax: logsql <host user password db>\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
char buf[1024];
|
|
||||||
snprintf(buf, sizeof(buf), "PLAYER_SQL: %s %s %s %s %d", db_host[0], db_user[0], db_pwd[0], db_db[0], mysql_db_port[0]);
|
|
||||||
isPlayerSQL = true;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
TOKEN("player_sql")
|
TOKEN("player_sql")
|
||||||
{
|
{
|
||||||
const char* line = two_arguments(value_string, db_host[1], sizeof(db_host[1]), db_user[1], sizeof(db_user[1]));
|
ParseSqlConfigOrExit("player_sql", value_string, dbConfig[static_cast<size_t>(ESqlConfigIndex::Player)]);
|
||||||
line = two_arguments(line, db_pwd[1], sizeof(db_pwd[1]), db_db[1], sizeof(db_db[1]));
|
|
||||||
|
|
||||||
if (line[0])
|
|
||||||
{
|
|
||||||
char buf[256];
|
|
||||||
one_argument(line, buf, sizeof(buf));
|
|
||||||
str_to_number(mysql_db_port[1], buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!*db_host[1] || !*db_user[1] || !*db_pwd[1] || !*db_db[1])
|
|
||||||
{
|
|
||||||
fprintf(stderr, "PLAYER_SQL syntax: logsql <host user password db>\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
char buf[1024];
|
|
||||||
snprintf(buf, sizeof(buf), "PLAYER_SQL: %s %s %s %s %d", db_host[1], db_user[1], db_pwd[1], db_db[1], mysql_db_port[1]);
|
|
||||||
isPlayerSQL = true;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
TOKEN("common_sql")
|
TOKEN("common_sql")
|
||||||
{
|
{
|
||||||
const char* line = two_arguments(value_string, db_host[2], sizeof(db_host[2]), db_user[2], sizeof(db_user[2]));
|
ParseSqlConfigOrExit("common_sql", value_string, dbConfig[static_cast<size_t>(ESqlConfigIndex::Common)]);
|
||||||
line = two_arguments(line, db_pwd[2], sizeof(db_pwd[2]), db_db[2], sizeof(db_db[2]));
|
|
||||||
|
|
||||||
if (line[0])
|
|
||||||
{
|
|
||||||
char buf[256];
|
|
||||||
one_argument(line, buf, sizeof(buf));
|
|
||||||
str_to_number(mysql_db_port[2], buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!*db_host[2] || !*db_user[2] || !*db_pwd[2] || !*db_db[2])
|
|
||||||
{
|
|
||||||
fprintf(stderr, "COMMON_SQL syntax: logsql <host user password db>\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
char buf[1024];
|
|
||||||
snprintf(buf, sizeof(buf), "COMMON_SQL: %s %s %s %s %d", db_host[2], db_user[2], db_pwd[2], db_db[2], mysql_db_port[2]);
|
|
||||||
isCommonSQL = true;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
TOKEN("log_sql")
|
TOKEN("log_sql")
|
||||||
{
|
{
|
||||||
const char* line = two_arguments(value_string, log_host, sizeof(log_host), log_user, sizeof(log_user));
|
ParseSqlConfigOrExit("log_sql", value_string, logConfig);
|
||||||
line = two_arguments(line, log_pwd, sizeof(log_pwd), log_db, sizeof(log_db));
|
|
||||||
|
|
||||||
if (line[0])
|
|
||||||
{
|
|
||||||
char buf[256];
|
|
||||||
one_argument(line, buf, sizeof(buf));
|
|
||||||
str_to_number(log_port, buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!*log_host || !*log_user || !*log_pwd || !*log_db)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "LOG_SQL syntax: logsql <host user password db>\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
char buf[1024];
|
|
||||||
snprintf(buf, sizeof(buf), "LOG_SQL: %s %s %s %s %d", log_host, log_user, log_pwd, log_db, log_port);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -753,6 +825,12 @@ void config_init(const string& st_localeServiceName)
|
|||||||
}
|
}
|
||||||
fclose(fp_common);
|
fclose(fp_common);
|
||||||
|
|
||||||
|
ApplySqlEnvOverrides("ACCOUNT_SQL", dbConfig[static_cast<size_t>(ESqlConfigIndex::Account)]);
|
||||||
|
ApplySqlEnvOverrides("PLAYER_SQL", dbConfig[static_cast<size_t>(ESqlConfigIndex::Player)]);
|
||||||
|
ApplySqlEnvOverrides("COMMON_SQL", dbConfig[static_cast<size_t>(ESqlConfigIndex::Common)]);
|
||||||
|
ApplySqlEnvOverrides("LOG_SQL", logConfig);
|
||||||
|
ApplyAdminPagePasswordEnvOverride();
|
||||||
|
|
||||||
FILE* fpOnlyForDB;
|
FILE* fpOnlyForDB;
|
||||||
|
|
||||||
if (!(fpOnlyForDB = fopen(st_configFileName.c_str(), "r")))
|
if (!(fpOnlyForDB = fopen(st_configFileName.c_str(), "r")))
|
||||||
@@ -814,31 +892,15 @@ void config_init(const string& st_localeServiceName)
|
|||||||
//처리가 끝났으니 파일을 닫자.
|
//처리가 끝났으니 파일을 닫자.
|
||||||
fclose(fpOnlyForDB);
|
fclose(fpOnlyForDB);
|
||||||
|
|
||||||
// CONFIG_SQL_INFO_ERROR
|
ValidateSqlConfigOrExit("COMMON_SQL", dbConfig[static_cast<size_t>(ESqlConfigIndex::Common)]);
|
||||||
if (!isCommonSQL)
|
ValidateSqlConfigOrExit(g_bAuthServer ? "ACCOUNT_SQL" : "PLAYER_SQL", dbConfig[static_cast<size_t>(g_bAuthServer ? ESqlConfigIndex::Account : ESqlConfigIndex::Player)]);
|
||||||
{
|
if (!g_bAuthServer)
|
||||||
puts("LOAD_COMMON_SQL_INFO_FAILURE:");
|
ValidateSqlConfigOrExit("LOG_SQL", logConfig);
|
||||||
puts("");
|
ValidateAdminPageConfigOrExit();
|
||||||
puts("CONFIG:");
|
|
||||||
puts("------------------------------------------------");
|
|
||||||
puts("COMMON_SQL: HOST USER PASSWORD DATABASE");
|
|
||||||
puts("");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isPlayerSQL)
|
|
||||||
{
|
|
||||||
puts("LOAD_PLAYER_SQL_INFO_FAILURE:");
|
|
||||||
puts("");
|
|
||||||
puts("CONFIG:");
|
|
||||||
puts("------------------------------------------------");
|
|
||||||
puts("PLAYER_SQL: HOST USER PASSWORD DATABASE");
|
|
||||||
puts("");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Common DB 가 Locale 정보를 가지고 있기 때문에 가장 먼저 접속해야 한다.
|
// Common DB 가 Locale 정보를 가지고 있기 때문에 가장 먼저 접속해야 한다.
|
||||||
AccountDB::instance().Connect(db_host[2], mysql_db_port[2], db_user[2], db_pwd[2], db_db[2]);
|
const SqlConnectionConfig& commonDb = dbConfig[static_cast<size_t>(ESqlConfigIndex::Common)];
|
||||||
|
AccountDB::instance().Connect(commonDb.host.c_str(), commonDb.port, commonDb.user.c_str(), commonDb.password.c_str(), commonDb.database.c_str());
|
||||||
|
|
||||||
if (false == AccountDB::instance().IsConnected())
|
if (false == AccountDB::instance().IsConnected())
|
||||||
{
|
{
|
||||||
@@ -884,13 +946,14 @@ void config_init(const string& st_localeServiceName)
|
|||||||
|
|
||||||
AccountDB::instance().SetLocale(g_stLocale);
|
AccountDB::instance().SetLocale(g_stLocale);
|
||||||
|
|
||||||
AccountDB::instance().ConnectAsync(db_host[2], mysql_db_port[2], db_user[2], db_pwd[2], db_db[2], g_stLocale.c_str());
|
AccountDB::instance().ConnectAsync(commonDb.host.c_str(), commonDb.port, commonDb.user.c_str(), commonDb.password.c_str(), commonDb.database.c_str(), g_stLocale.c_str());
|
||||||
|
|
||||||
// Player DB 접속
|
// Player DB 접속
|
||||||
|
const SqlConnectionConfig& playerDb = dbConfig[static_cast<size_t>(g_bAuthServer ? ESqlConfigIndex::Account : ESqlConfigIndex::Player)];
|
||||||
if (g_bAuthServer)
|
if (g_bAuthServer)
|
||||||
DBManager::instance().Connect(db_host[0], mysql_db_port[0], db_user[0], db_pwd[0], db_db[0]);
|
DBManager::instance().Connect(playerDb.host.c_str(), playerDb.port, playerDb.user.c_str(), playerDb.password.c_str(), playerDb.database.c_str());
|
||||||
else
|
else
|
||||||
DBManager::instance().Connect(db_host[1], mysql_db_port[1], db_user[1], db_pwd[1], db_db[1]);
|
DBManager::instance().Connect(playerDb.host.c_str(), playerDb.port, playerDb.user.c_str(), playerDb.password.c_str(), playerDb.database.c_str());
|
||||||
|
|
||||||
if (!DBManager::instance().IsConnected())
|
if (!DBManager::instance().IsConnected())
|
||||||
{
|
{
|
||||||
@@ -903,7 +966,7 @@ void config_init(const string& st_localeServiceName)
|
|||||||
if (false == g_bAuthServer) // 인증 서버가 아닐 경우
|
if (false == g_bAuthServer) // 인증 서버가 아닐 경우
|
||||||
{
|
{
|
||||||
// Log DB 접속
|
// Log DB 접속
|
||||||
LogManager::instance().Connect(log_host, log_port, log_user, log_pwd, log_db);
|
LogManager::instance().Connect(logConfig.host.c_str(), logConfig.port, logConfig.user.c_str(), logConfig.password.c_str(), logConfig.database.c_str());
|
||||||
|
|
||||||
if (!LogManager::instance().IsConnected())
|
if (!LogManager::instance().IsConnected())
|
||||||
{
|
{
|
||||||
@@ -1238,4 +1301,3 @@ bool IsValidFileCRC(DWORD dwCRC)
|
|||||||
return s_set_dwFileCRC.find(dwCRC) != s_set_dwFileCRC.end();
|
return s_set_dwFileCRC.find(dwCRC) != s_set_dwFileCRC.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ enum
|
|||||||
void config_init(const std::string& st_localeServiceName); // default "" is CONFIG
|
void config_init(const std::string& st_localeServiceName); // default "" is CONFIG
|
||||||
|
|
||||||
extern char sql_addr[256];
|
extern char sql_addr[256];
|
||||||
|
bool IsAdminPageEnabled();
|
||||||
|
|
||||||
extern WORD mother_port;
|
extern WORD mother_port;
|
||||||
extern WORD p2p_port;
|
extern WORD p2p_port;
|
||||||
@@ -106,4 +107,3 @@ extern int gPlayerMaxLevel;
|
|||||||
extern bool g_BlockCharCreation;
|
extern bool g_BlockCharCreation;
|
||||||
|
|
||||||
#endif /* __INC_METIN_II_GAME_CONFIG_H__ */
|
#endif /* __INC_METIN_II_GAME_CONFIG_H__ */
|
||||||
|
|
||||||
|
|||||||
@@ -18,19 +18,35 @@
|
|||||||
|
|
||||||
extern time_t get_global_time();
|
extern time_t get_global_time();
|
||||||
|
|
||||||
bool IsEmptyAdminPage()
|
namespace
|
||||||
{
|
{
|
||||||
return g_stAdminPageIP.empty();
|
bool IsEmptyAdminPage()
|
||||||
}
|
|
||||||
|
|
||||||
bool IsAdminPage(const char * ip)
|
|
||||||
{
|
|
||||||
for (size_t n = 0; n < g_stAdminPageIP.size(); ++n)
|
|
||||||
{
|
{
|
||||||
if (g_stAdminPageIP[n] == ip)
|
return g_stAdminPageIP.empty();
|
||||||
return 1;
|
}
|
||||||
}
|
|
||||||
return 0;
|
bool IsAdminPage(const char * ip)
|
||||||
|
{
|
||||||
|
for (size_t n = 0; n < g_stAdminPageIP.size(); ++n)
|
||||||
|
{
|
||||||
|
if (g_stAdminPageIP[n] == ip)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HasAdminPageIpAccess(const char* ip)
|
||||||
|
{
|
||||||
|
if (!IsAdminPageEnabled())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return IsEmptyAdminPage() || IsAdminPage(ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsAdminCommandAuthorized(LPDESC d)
|
||||||
|
{
|
||||||
|
return d->IsAdminMode();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CInputProcessor::CInputProcessor() : m_pPacketInfo(NULL), m_iBufferLeft(0)
|
CInputProcessor::CInputProcessor() : m_pPacketInfo(NULL), m_iBufferLeft(0)
|
||||||
@@ -245,14 +261,15 @@ int CInputHandshake::HandleText(LPDESC d, const char * c_pData)
|
|||||||
stResult = "YES";
|
stResult = "YES";
|
||||||
}
|
}
|
||||||
//else if (!stBuf.compare("SHOWMETHEMONEY"))
|
//else if (!stBuf.compare("SHOWMETHEMONEY"))
|
||||||
else if (stBuf == g_stAdminPagePassword)
|
else if (IsAdminPageEnabled() && stBuf == g_stAdminPagePassword)
|
||||||
{
|
{
|
||||||
|
const char* hostIp = inet_ntoa(d->GetAddr().sin_addr);
|
||||||
if (!IsEmptyAdminPage())
|
if (!IsEmptyAdminPage())
|
||||||
{
|
{
|
||||||
if (!IsAdminPage(inet_ntoa(d->GetAddr().sin_addr)))
|
if (!IsAdminPage(hostIp))
|
||||||
{
|
{
|
||||||
char szTmp[64];
|
char szTmp[64];
|
||||||
snprintf(szTmp, sizeof(szTmp), "WEBADMIN : Wrong Connector : %s", inet_ntoa(d->GetAddr().sin_addr));
|
snprintf(szTmp, sizeof(szTmp), "WEBADMIN : Wrong Connector : %s", hostIp);
|
||||||
stResult += szTmp;
|
stResult += szTmp;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -270,21 +287,14 @@ int CInputHandshake::HandleText(LPDESC d, const char * c_pData)
|
|||||||
else if (!stBuf.compare("USER_COUNT"))
|
else if (!stBuf.compare("USER_COUNT"))
|
||||||
{
|
{
|
||||||
char szTmp[64];
|
char szTmp[64];
|
||||||
|
const char* hostIp = inet_ntoa(d->GetAddr().sin_addr);
|
||||||
|
|
||||||
if (!IsEmptyAdminPage())
|
if (!HasAdminPageIpAccess(hostIp))
|
||||||
{
|
{
|
||||||
if (!IsAdminPage(inet_ntoa(d->GetAddr().sin_addr)))
|
if (IsAdminPageEnabled())
|
||||||
{
|
snprintf(szTmp, sizeof(szTmp), "WEBADMIN : Wrong Connector : %s", hostIp);
|
||||||
snprintf(szTmp, sizeof(szTmp), "WEBADMIN : Wrong Connector : %s", inet_ntoa(d->GetAddr().sin_addr));
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
strlcpy(szTmp, "WEBADMIN : Disabled", sizeof(szTmp));
|
||||||
int iTotal;
|
|
||||||
int * paiEmpireUserCount;
|
|
||||||
int iLocal;
|
|
||||||
DESC_MANAGER::instance().GetUserCount(iTotal, &paiEmpireUserCount, iLocal);
|
|
||||||
snprintf(szTmp, sizeof(szTmp), "%d %d %d %d %d", iTotal, paiEmpireUserCount[1], paiEmpireUserCount[2], paiEmpireUserCount[3], iLocal);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -298,48 +308,68 @@ int CInputHandshake::HandleText(LPDESC d, const char * c_pData)
|
|||||||
}
|
}
|
||||||
else if (!stBuf.compare("CHECK_P2P_CONNECTIONS"))
|
else if (!stBuf.compare("CHECK_P2P_CONNECTIONS"))
|
||||||
{
|
{
|
||||||
std::ostringstream oss(std::ostringstream::out);
|
if (!IsAdminCommandAuthorized(d))
|
||||||
|
stResult = "UNKNOWN";
|
||||||
oss << "P2P CONNECTION NUMBER : " << P2P_MANAGER::instance().GetDescCount() << "\n";
|
else
|
||||||
std::string hostNames;
|
{
|
||||||
P2P_MANAGER::Instance().GetP2PHostNames(hostNames);
|
std::ostringstream oss(std::ostringstream::out);
|
||||||
oss << hostNames;
|
|
||||||
stResult = oss.str();
|
|
||||||
TPacketGGCheckAwakeness packet;
|
|
||||||
packet.header = GG::CHECK_AWAKENESS;
|
|
||||||
packet.length = sizeof(packet);
|
|
||||||
|
|
||||||
P2P_MANAGER::instance().Send(&packet, sizeof(packet));
|
oss << "P2P CONNECTION NUMBER : " << P2P_MANAGER::instance().GetDescCount() << "\n";
|
||||||
|
std::string hostNames;
|
||||||
|
P2P_MANAGER::Instance().GetP2PHostNames(hostNames);
|
||||||
|
oss << hostNames;
|
||||||
|
stResult = oss.str();
|
||||||
|
TPacketGGCheckAwakeness packet;
|
||||||
|
packet.header = GG::CHECK_AWAKENESS;
|
||||||
|
packet.length = sizeof(packet);
|
||||||
|
|
||||||
|
P2P_MANAGER::instance().Send(&packet, sizeof(packet));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (!stBuf.compare("PACKET_INFO"))
|
else if (!stBuf.compare("PACKET_INFO"))
|
||||||
{
|
{
|
||||||
m_pMainPacketInfo->Log("packet_info.txt");
|
if (!IsAdminCommandAuthorized(d))
|
||||||
stResult = "OK";
|
stResult = "UNKNOWN";
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_pMainPacketInfo->Log("packet_info.txt");
|
||||||
|
stResult = "OK";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (!stBuf.compare("PROFILE"))
|
else if (!stBuf.compare("PROFILE"))
|
||||||
{
|
{
|
||||||
CProfiler::instance().Log("profile.txt");
|
if (!IsAdminCommandAuthorized(d))
|
||||||
stResult = "OK";
|
stResult = "UNKNOWN";
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CProfiler::instance().Log("profile.txt");
|
||||||
|
stResult = "OK";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//gift notify delete command
|
//gift notify delete command
|
||||||
else if (!stBuf.compare(0,15,"DELETE_AWARDID "))
|
else if (!stBuf.compare(0,15,"DELETE_AWARDID "))
|
||||||
{
|
{
|
||||||
char szTmp[64];
|
if (!IsAdminCommandAuthorized(d))
|
||||||
std::string msg = stBuf.substr(15,26); // item_award의 id범위?
|
stResult = "UNKNOWN";
|
||||||
|
else
|
||||||
TPacketDeleteAwardID p;
|
{
|
||||||
p.dwID = (DWORD)(atoi(msg.c_str()));
|
char szTmp[64];
|
||||||
snprintf(szTmp,sizeof(szTmp),"Sent to DB cache to delete ItemAward, id: %d",p.dwID);
|
std::string msg = stBuf.substr(15,26); // item_award의 id범위?
|
||||||
//sys_log(0,"%d",p.dwID);
|
|
||||||
// strlcpy(p.login, msg.c_str(), sizeof(p.login));
|
TPacketDeleteAwardID p;
|
||||||
db_clientdesc->DBPacket(GD::DELETE_AWARDID, 0, &p, sizeof(p));
|
p.dwID = (DWORD)(atoi(msg.c_str()));
|
||||||
stResult += szTmp;
|
snprintf(szTmp,sizeof(szTmp),"Sent to DB cache to delete ItemAward, id: %d",p.dwID);
|
||||||
|
//sys_log(0,"%d",p.dwID);
|
||||||
|
// strlcpy(p.login, msg.c_str(), sizeof(p.login));
|
||||||
|
db_clientdesc->DBPacket(GD::DELETE_AWARDID, 0, &p, sizeof(p));
|
||||||
|
stResult += szTmp;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
stResult = "UNKNOWN";
|
stResult = "UNKNOWN";
|
||||||
|
|
||||||
if (d->IsAdminMode())
|
if (d->IsAdminMode())
|
||||||
{
|
{
|
||||||
// 어드민 명령들
|
// 어드민 명령들
|
||||||
if (!stBuf.compare(0, 7, "NOTICE "))
|
if (!stBuf.compare(0, 7, "NOTICE "))
|
||||||
|
|||||||
Reference in New Issue
Block a user