mirror of
https://git.do.srb2.org/KartKrew/Kart-Public.git
synced 2025-02-04 23:41:07 +00:00
Ban improvements
- Save a note of the username, not just the reason. - Allow setting a mask with the `banip` command. - Make ban.txt's formatting a lot more sane. Username and reason are stored in quotes. The mask uses the same formatting as actual CDIR. - Keep track of if we tried to load ban.txt. If it wasn't, then don't save over it with a blank file. - Disallow quotes in player names, as it makes player name detection in console more annoying, and saving username in files scary. # Conflicts: # src/d_clisrv.c # src/d_netcmd.c # src/i_tcp.c
This commit is contained in:
parent
8d05bf669b
commit
55be74396f
6 changed files with 172 additions and 28 deletions
122
src/d_clisrv.c
122
src/d_clisrv.c
|
@ -2673,15 +2673,25 @@ static void Command_ShowBan(void) //Print out ban list
|
||||||
CONS_Printf(M_GetText("(empty)\n"));
|
CONS_Printf(M_GetText("(empty)\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static boolean bansLoaded = false;
|
||||||
|
|
||||||
void D_SaveBan(void)
|
void D_SaveBan(void)
|
||||||
{
|
{
|
||||||
FILE *f;
|
FILE *f;
|
||||||
size_t i;
|
size_t i;
|
||||||
const char *address, *mask, *reason;
|
const char *address, *mask;
|
||||||
|
const char *username, *reason;
|
||||||
const time_t curTime = time(NULL);
|
const time_t curTime = time(NULL);
|
||||||
time_t unbanTime = NO_BAN_TIME;
|
time_t unbanTime = NO_BAN_TIME;
|
||||||
const char *path = va("%s"PATHSEP"%s", srb2home, "ban.txt");
|
const char *path = va("%s"PATHSEP"%s", srb2home, "ban.txt");
|
||||||
|
|
||||||
|
if (bansLoaded != true)
|
||||||
|
{
|
||||||
|
// You didn't even get to ATTEMPT to load bans.txt.
|
||||||
|
// Don't immediately save nothing over it.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
f = fopen(path, "w");
|
f = fopen(path, "w");
|
||||||
|
|
||||||
if (!f)
|
if (!f)
|
||||||
|
@ -2696,24 +2706,37 @@ void D_SaveBan(void)
|
||||||
{
|
{
|
||||||
unbanTime = I_GetUnbanTime(i);
|
unbanTime = I_GetUnbanTime(i);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unbanTime = NO_BAN_TIME;
|
||||||
|
}
|
||||||
|
|
||||||
if (unbanTime != NO_BAN_TIME && curTime >= unbanTime)
|
if (unbanTime != NO_BAN_TIME && curTime >= unbanTime)
|
||||||
{
|
{
|
||||||
// Don't need to save this one anymore.
|
// This one has served their sentence.
|
||||||
|
// We don't need to save them in the file anymore.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mask = NULL;
|
||||||
if (!I_GetBanMask || (mask = I_GetBanMask(i)) == NULL)
|
if (!I_GetBanMask || (mask = I_GetBanMask(i)) == NULL)
|
||||||
fprintf(f, "%s 0", address);
|
fprintf(f, "%s/0", address);
|
||||||
else
|
else
|
||||||
fprintf(f, "%s %s", address, mask);
|
fprintf(f, "%s/%s", address, mask);
|
||||||
|
|
||||||
fprintf(f, " %ld", (long)unbanTime);
|
fprintf(f, " %ld", (long)unbanTime);
|
||||||
|
|
||||||
if (I_GetBanReason && (reason = I_GetBanReason(i)) != NULL)
|
username = NULL;
|
||||||
fprintf(f, " %s\n", reason);
|
if (I_GetBanUsername && (username = I_GetBanUsername(i)) != NULL)
|
||||||
|
fprintf(f, " \"%s\"", username);
|
||||||
else
|
else
|
||||||
fprintf(f, " %s\n", "No reason given");
|
fprintf(f, " \"%s\"", "Direct IP ban");
|
||||||
|
|
||||||
|
reason = NULL;
|
||||||
|
if (I_GetBanReason && (reason = I_GetBanReason(i)) != NULL)
|
||||||
|
fprintf(f, " \"%s\"\n", reason);
|
||||||
|
else
|
||||||
|
fprintf(f, " \"%s\"\n", "No reason given");
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
@ -2728,14 +2751,21 @@ static void Command_ClearBans(void)
|
||||||
D_SaveBan();
|
D_SaveBan();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Ban_Load_File(boolean warning)
|
void D_LoadBan(boolean warning)
|
||||||
{
|
{
|
||||||
FILE *f;
|
FILE *f;
|
||||||
size_t i;
|
size_t i;
|
||||||
const char *address, *mask, *reason;
|
const char *address, *mask;
|
||||||
|
const char *username, *reason;
|
||||||
time_t unbanTime = NO_BAN_TIME;
|
time_t unbanTime = NO_BAN_TIME;
|
||||||
char buffer[MAX_WADPATH];
|
char buffer[MAX_WADPATH];
|
||||||
|
|
||||||
|
if (!I_ClearBans)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// We at least attempted loading bans.txt
|
||||||
|
bansLoaded = true;
|
||||||
|
|
||||||
f = fopen(va("%s"PATHSEP"%s", srb2home, "ban.txt"), "r");
|
f = fopen(va("%s"PATHSEP"%s", srb2home, "ban.txt"), "r");
|
||||||
|
|
||||||
if (!f)
|
if (!f)
|
||||||
|
@ -2747,16 +2777,26 @@ static void Ban_Load_File(boolean warning)
|
||||||
|
|
||||||
I_ClearBans();
|
I_ClearBans();
|
||||||
|
|
||||||
for (i=0; fgets(buffer, (int)sizeof(buffer), f); i++)
|
for (i = 0; fgets(buffer, (int)sizeof(buffer), f); i++)
|
||||||
{
|
{
|
||||||
address = strtok(buffer, " \t\r\n");
|
address = strtok(buffer, "/\t\r\n");
|
||||||
mask = strtok(NULL, " \t\r\n");
|
mask = strtok(NULL, " \t\r\n");
|
||||||
unbanTime = atoi(strtok(NULL, " \t\r\n"));
|
|
||||||
reason = strtok(NULL, "\r\n");
|
unbanTime = atoi(strtok(NULL, " \"\t\r\n"));
|
||||||
|
|
||||||
|
username = strtok(NULL, "\"\t\r\n"); // go until next "
|
||||||
|
|
||||||
|
strtok(NULL, "\"\t\r\n"); // remove first "
|
||||||
|
reason = strtok(NULL, "\"\r\n"); // go until next "
|
||||||
|
|
||||||
I_SetBanAddress(address, mask);
|
I_SetBanAddress(address, mask);
|
||||||
|
|
||||||
if (I_SetUnbanTime)
|
if (I_SetUnbanTime)
|
||||||
I_SetUnbanTime(unbanTime);
|
I_SetUnbanTime(unbanTime);
|
||||||
|
|
||||||
|
if (I_SetBanUsername)
|
||||||
|
I_SetBanUsername(username);
|
||||||
|
|
||||||
if (I_SetBanReason)
|
if (I_SetBanReason)
|
||||||
I_SetBanReason(reason);
|
I_SetBanReason(reason);
|
||||||
}
|
}
|
||||||
|
@ -2766,7 +2806,7 @@ static void Ban_Load_File(boolean warning)
|
||||||
|
|
||||||
static void Command_ReloadBan(void) //recheck ban.txt
|
static void Command_ReloadBan(void) //recheck ban.txt
|
||||||
{
|
{
|
||||||
Ban_Load_File(true);
|
D_LoadBan(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Command_connect(void)
|
static void Command_connect(void)
|
||||||
|
@ -3152,31 +3192,60 @@ static void Command_Ban(void)
|
||||||
|
|
||||||
static void Command_BanIP(void)
|
static void Command_BanIP(void)
|
||||||
{
|
{
|
||||||
if (COM_Argc() < 2)
|
size_t ac = COM_Argc();
|
||||||
|
|
||||||
|
if (ac < 2)
|
||||||
{
|
{
|
||||||
CONS_Printf(M_GetText("banip <ip> <reason>: ban an ip address\n"));
|
CONS_Printf(M_GetText("banip <ip> [<reason>]: ban an ip address\n"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (server) // Only the server can use this, otherwise does nothing.
|
if (server) // Only the server can use this, otherwise does nothing.
|
||||||
{
|
{
|
||||||
const char *address = (COM_Argv(1));
|
char *addressInput = Z_StrDup(COM_Argv(1));
|
||||||
const char *reason;
|
|
||||||
|
|
||||||
if (COM_Argc() == 2)
|
const char *address = NULL;
|
||||||
reason = NULL;
|
const char *mask = NULL;
|
||||||
else
|
|
||||||
|
const char *reason = NULL;
|
||||||
|
|
||||||
|
address = strtok(addressInput, "/");
|
||||||
|
mask = strtok(NULL, "");
|
||||||
|
|
||||||
|
if (ac > 2)
|
||||||
|
{
|
||||||
reason = COM_Argv(2);
|
reason = COM_Argv(2);
|
||||||
|
}
|
||||||
|
|
||||||
if (I_SetBanAddress && I_SetBanAddress(address, NULL))
|
if (I_SetBanAddress && I_SetBanAddress(address, mask))
|
||||||
{
|
{
|
||||||
if (reason)
|
if (reason)
|
||||||
CONS_Printf("Banned IP address %s for: %s\n", address, reason);
|
{
|
||||||
|
CONS_Printf(
|
||||||
|
"Banned IP address %s%s for: %s\n",
|
||||||
|
address,
|
||||||
|
(mask && (strlen(mask) > 0)) ? va("/%s", mask) : "",
|
||||||
|
reason
|
||||||
|
);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
CONS_Printf("Banned IP address %s\n", address);
|
{
|
||||||
|
CONS_Printf(
|
||||||
|
"Banned IP address %s%s\n",
|
||||||
|
address,
|
||||||
|
(mask && (strlen(mask) > 0)) ? va("/%s", mask) : ""
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (I_SetUnbanTime)
|
||||||
|
I_SetUnbanTime(NO_BAN_TIME);
|
||||||
|
|
||||||
|
if (I_SetBanUsername)
|
||||||
|
I_SetBanUsername(NULL);
|
||||||
|
|
||||||
if (I_SetBanReason)
|
if (I_SetBanReason)
|
||||||
I_SetBanReason(reason);
|
I_SetBanReason(reason);
|
||||||
|
|
||||||
D_SaveBan();
|
D_SaveBan();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -3337,6 +3406,9 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (I_SetBanUsername)
|
||||||
|
I_SetBanUsername(player_names[pnum]);
|
||||||
|
|
||||||
if (I_SetBanReason)
|
if (I_SetBanReason)
|
||||||
I_SetBanReason(reason);
|
I_SetBanReason(reason);
|
||||||
|
|
||||||
|
@ -3645,7 +3717,7 @@ void D_ClientServerInit(void)
|
||||||
#ifdef DUMPCONSISTENCY
|
#ifdef DUMPCONSISTENCY
|
||||||
CV_RegisterVar(&cv_dumpconsistency);
|
CV_RegisterVar(&cv_dumpconsistency);
|
||||||
#endif
|
#endif
|
||||||
Ban_Load_File(false);
|
D_LoadBan(false);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
gametic = 0;
|
gametic = 0;
|
||||||
|
|
|
@ -79,9 +79,11 @@ void (*I_ClearBans)(void) = NULL;
|
||||||
const char *(*I_GetNodeAddress) (INT32 node) = NULL;
|
const char *(*I_GetNodeAddress) (INT32 node) = NULL;
|
||||||
const char *(*I_GetBanAddress) (size_t ban) = NULL;
|
const char *(*I_GetBanAddress) (size_t ban) = NULL;
|
||||||
const char *(*I_GetBanMask) (size_t ban) = NULL;
|
const char *(*I_GetBanMask) (size_t ban) = NULL;
|
||||||
|
const char *(*I_GetBanUsername) (size_t ban) = NULL;
|
||||||
const char *(*I_GetBanReason) (size_t ban) = NULL;
|
const char *(*I_GetBanReason) (size_t ban) = NULL;
|
||||||
time_t (*I_GetUnbanTime) (size_t ban) = NULL;
|
time_t (*I_GetUnbanTime) (size_t ban) = NULL;
|
||||||
boolean (*I_SetBanAddress) (const char *address, const char *mask) = NULL;
|
boolean (*I_SetBanAddress) (const char *address, const char *mask) = NULL;
|
||||||
|
boolean (*I_SetBanUsername) (const char *username) = NULL;
|
||||||
boolean (*I_SetBanReason) (const char *reason) = NULL;
|
boolean (*I_SetBanReason) (const char *reason) = NULL;
|
||||||
boolean (*I_SetUnbanTime) (time_t timestamp) = NULL;
|
boolean (*I_SetUnbanTime) (time_t timestamp) = NULL;
|
||||||
boolean *bannednode = NULL;
|
boolean *bannednode = NULL;
|
||||||
|
|
|
@ -55,6 +55,7 @@ boolean HGetPacket(void);
|
||||||
void D_SetDoomcom(void);
|
void D_SetDoomcom(void);
|
||||||
#ifndef NONET
|
#ifndef NONET
|
||||||
void D_SaveBan(void);
|
void D_SaveBan(void);
|
||||||
|
void D_LoadBan(boolean warning);
|
||||||
#endif
|
#endif
|
||||||
boolean D_CheckNetGame(void);
|
boolean D_CheckNetGame(void);
|
||||||
void D_CloseConnection(void);
|
void D_CloseConnection(void);
|
||||||
|
|
|
@ -1035,7 +1035,16 @@ void D_RegisterClientCommands(void)
|
||||||
* \sa CleanupPlayerName, SetPlayerName, Got_NameAndColor
|
* \sa CleanupPlayerName, SetPlayerName, Got_NameAndColor
|
||||||
* \author Graue <graue@oceanbase.org>
|
* \author Graue <graue@oceanbase.org>
|
||||||
*/
|
*/
|
||||||
static boolean IsNameGood(char *name, INT32 playernum)
|
|
||||||
|
static boolean AllowedPlayerNameChar(char ch)
|
||||||
|
{
|
||||||
|
if (!isprint(ch) || ch == ';' || ch == '"' || (UINT8)(ch) >= 0x80)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean EnsurePlayerNameIsGood(char *name, INT32 playernum)
|
||||||
{
|
{
|
||||||
INT32 ix;
|
INT32 ix;
|
||||||
|
|
||||||
|
@ -1056,7 +1065,7 @@ static boolean IsNameGood(char *name, INT32 playernum)
|
||||||
// Also, anything over 0x80 is disallowed too, since compilers love to
|
// Also, anything over 0x80 is disallowed too, since compilers love to
|
||||||
// differ on whether they're printable characters or not.
|
// differ on whether they're printable characters or not.
|
||||||
for (ix = 0; name[ix] != '\0'; ix++)
|
for (ix = 0; name[ix] != '\0'; ix++)
|
||||||
if (!isprint(name[ix]) || name[ix] == ';' || (UINT8)(name[ix]) >= 0x80)
|
if (!AllowedPlayerNameChar(name[ix]))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Check if a player is currently using the name, case-insensitively.
|
// Check if a player is currently using the name, case-insensitively.
|
||||||
|
@ -1142,6 +1151,16 @@ static void CleanupPlayerName(INT32 playernum, const char *newname)
|
||||||
|
|
||||||
tmpname = p;
|
tmpname = p;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (!AllowedPlayerNameChar(*p))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
while (*++p) ;
|
||||||
|
|
||||||
|
if (*p)/* bad char found */
|
||||||
|
break;
|
||||||
|
|
||||||
// Remove trailing spaces.
|
// Remove trailing spaces.
|
||||||
p = &tmpname[strlen(tmpname)-1]; // last character
|
p = &tmpname[strlen(tmpname)-1]; // last character
|
||||||
while (*p == ' ' && p >= tmpname)
|
while (*p == ' ' && p >= tmpname)
|
||||||
|
|
|
@ -147,9 +147,11 @@ extern void (*I_ClearBans)(void);
|
||||||
extern const char *(*I_GetNodeAddress) (INT32 node);
|
extern const char *(*I_GetNodeAddress) (INT32 node);
|
||||||
extern const char *(*I_GetBanAddress) (size_t ban);
|
extern const char *(*I_GetBanAddress) (size_t ban);
|
||||||
extern const char *(*I_GetBanMask) (size_t ban);
|
extern const char *(*I_GetBanMask) (size_t ban);
|
||||||
|
extern const char *(*I_GetBanUsername) (size_t ban);
|
||||||
extern const char *(*I_GetBanReason) (size_t ban);
|
extern const char *(*I_GetBanReason) (size_t ban);
|
||||||
extern time_t (*I_GetUnbanTime) (size_t ban);
|
extern time_t (*I_GetUnbanTime) (size_t ban);
|
||||||
extern boolean (*I_SetBanAddress) (const char *address,const char *mask);
|
extern boolean (*I_SetBanAddress) (const char *address,const char *mask);
|
||||||
|
extern boolean (*I_SetBanUsername) (const char *username);
|
||||||
extern boolean (*I_SetBanReason) (const char *reason);
|
extern boolean (*I_SetBanReason) (const char *reason);
|
||||||
extern boolean (*I_SetUnbanTime) (time_t timestamp);
|
extern boolean (*I_SetUnbanTime) (time_t timestamp);
|
||||||
extern boolean *bannednode;
|
extern boolean *bannednode;
|
||||||
|
|
50
src/i_tcp.c
50
src/i_tcp.c
|
@ -235,6 +235,7 @@ typedef struct
|
||||||
{
|
{
|
||||||
mysockaddr_t address;
|
mysockaddr_t address;
|
||||||
UINT8 mask;
|
UINT8 mask;
|
||||||
|
char *username;
|
||||||
char *reason;
|
char *reason;
|
||||||
time_t timestamp;
|
time_t timestamp;
|
||||||
} banned_t;
|
} banned_t;
|
||||||
|
@ -500,6 +501,18 @@ static const char *SOCK_GetBanMask(size_t ban)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *SOCK_GetBanUsername(size_t ban)
|
||||||
|
{
|
||||||
|
#ifdef NONET
|
||||||
|
(void)ban;
|
||||||
|
return NULL;
|
||||||
|
#else
|
||||||
|
if (ban >= numbans)
|
||||||
|
return NULL;
|
||||||
|
return banned[ban].username;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static const char *SOCK_GetBanReason(size_t ban)
|
static const char *SOCK_GetBanReason(size_t ban)
|
||||||
{
|
{
|
||||||
#ifdef NONET
|
#ifdef NONET
|
||||||
|
@ -1564,6 +1577,11 @@ static boolean SOCK_SetBanAddress(const char *address, const char *mask)
|
||||||
banned[ban].mask = 128;
|
banned[ban].mask = 128;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Set defaults, in case anything funny happens.
|
||||||
|
SOCK_SetBanUsername(NULL);
|
||||||
|
SOCK_SetBanReason(NULL);
|
||||||
|
SOCK_SetUnbanTime(NO_BAN_TIME);
|
||||||
|
|
||||||
runp = runp->ai_next;
|
runp = runp->ai_next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1573,17 +1591,45 @@ static boolean SOCK_SetBanAddress(const char *address, const char *mask)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static boolean SOCK_SetBanUsername(const char *username)
|
||||||
|
{
|
||||||
|
#ifdef NONET
|
||||||
|
(void)username;
|
||||||
|
return false;
|
||||||
|
#else
|
||||||
|
if (username == NULL || strlen(username) == 0)
|
||||||
|
{
|
||||||
|
username = "Direct IP ban";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (banned[numbans - 1].username)
|
||||||
|
{
|
||||||
|
Z_Free(banned[numbans - 1].username);
|
||||||
|
banned[numbans - 1].username = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
banned[numbans - 1].username = Z_StrDup(username);
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static boolean SOCK_SetBanReason(const char *reason)
|
static boolean SOCK_SetBanReason(const char *reason)
|
||||||
{
|
{
|
||||||
#ifdef NONET
|
#ifdef NONET
|
||||||
(void)reason;
|
(void)reason;
|
||||||
return false;
|
return false;
|
||||||
#else
|
#else
|
||||||
if (!reason)
|
if (reason == NULL || strlen(reason) == 0)
|
||||||
{
|
{
|
||||||
reason = "No reason given";
|
reason = "No reason given";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (banned[numbans - 1].reason)
|
||||||
|
{
|
||||||
|
Z_Free(banned[numbans - 1].reason);
|
||||||
|
banned[numbans - 1].reason = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
banned[numbans - 1].reason = Z_StrDup(reason);
|
banned[numbans - 1].reason = Z_StrDup(reason);
|
||||||
return true;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
|
@ -1696,9 +1742,11 @@ boolean I_InitTcpNetwork(void)
|
||||||
I_GetNodeAddress = SOCK_GetNodeAddress;
|
I_GetNodeAddress = SOCK_GetNodeAddress;
|
||||||
I_GetBanAddress = SOCK_GetBanAddress;
|
I_GetBanAddress = SOCK_GetBanAddress;
|
||||||
I_GetBanMask = SOCK_GetBanMask;
|
I_GetBanMask = SOCK_GetBanMask;
|
||||||
|
I_GetBanUsername = SOCK_GetBanUsername;
|
||||||
I_GetBanReason = SOCK_GetBanReason;
|
I_GetBanReason = SOCK_GetBanReason;
|
||||||
I_GetUnbanTime = SOCK_GetUnbanTime;
|
I_GetUnbanTime = SOCK_GetUnbanTime;
|
||||||
I_SetBanAddress = SOCK_SetBanAddress;
|
I_SetBanAddress = SOCK_SetBanAddress;
|
||||||
|
I_SetBanUsername = SOCK_SetBanUsername;
|
||||||
I_SetBanReason = SOCK_SetBanReason;
|
I_SetBanReason = SOCK_SetBanReason;
|
||||||
I_SetUnbanTime = SOCK_SetUnbanTime;
|
I_SetUnbanTime = SOCK_SetUnbanTime;
|
||||||
bannednode = SOCK_bannednode;
|
bannednode = SOCK_bannednode;
|
||||||
|
|
Loading…
Reference in a new issue