2
0
mirror of https://github.com/rehlds/rehlds.git synced 2025-01-14 15:48:04 +03:00

Fixes for new exploit involving " in info strings. (#596)

* Refactor SV_CheckForDuplicateNames

* Refactor and fix Info_IsValid
This commit is contained in:
Alik Aslanyan 2018-04-06 20:11:38 +04:00 committed by GitHub
parent 19e3a5df56
commit ce163a323b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 46 additions and 49 deletions

View File

@ -541,11 +541,6 @@ void Info_Print(const char *s)
qboolean Info_IsValid(const char *s)
{
char key[MAX_KV_LEN];
char value[MAX_KV_LEN];
char *c;
int nCount;
while (*s)
{
if (*s == '\\')
@ -553,46 +548,48 @@ qboolean Info_IsValid(const char *s)
s++; // skip the slash
}
// Copy a key
nCount = 0;
c = key;
while (*s != '\\')
// Returns character count
// -1 - error
// 0 - string size is zero
enum class AllowNull {
Yes,
No,
};
auto validate = [&s](AllowNull allowNull) -> int
{
if (!*s)
{
return FALSE; // key should end with a \, not a NULL
}
if (nCount >= MAX_KV_LEN)
{
return FALSE; // key length should be less then MAX_KV_LEN
}
*c++ = *s++;
nCount++;
}
*c = 0;
s++; // skip the slash
int nCount = 0;
// Copy a value
nCount = 0;
c = value;
while (*s != '\\')
{
if (!*s)
for(; *s != '\\'; nCount++, s++)
{
break; // allow value to be ended with NULL
}
if (nCount >= MAX_KV_LEN)
{
return FALSE; // value length should be less then MAX_KV_LEN
}
*c++ = *s++;
nCount++;
}
*c = 0;
if (!*s)
{
return (allowNull == AllowNull::Yes) ? nCount : -1;
}
if (value[0] == 0)
if (nCount >= MAX_KV_LEN)
{
return -1; // string length should be less then MAX_KV_LEN
}
#ifdef REHLDS_FIXES
if (*s == '\"')
{
return -1; // string should not contain "
}
#endif
}
return nCount;
};
if (validate(AllowNull::No) == -1)
{
return FALSE; // empty values are not valid
return FALSE;
}
s++; // Skip slash
if (validate(AllowNull::Yes) <= 0)
{
return FALSE;
}
if (!*s)

View File

@ -1977,29 +1977,29 @@ int SV_CheckForDuplicateSteamID(client_t *client)
int SV_CheckForDuplicateNames(char *userinfo, qboolean bIsReconnecting, int nExcludeSlot)
{
const char *val;
int i;
client_t *client;
int dupc = 0;
char rawname[MAX_NAME];
char newname[MAX_NAME];
int changed = FALSE;
val = Info_ValueForKey(userinfo, "name");
const char *val = Info_ValueForKey(userinfo, "name");
char rawname[MAX_NAME];
Q_strncpy(rawname, val, MAX_NAME - 1);
while (true)
{
for (i = 0, client = g_psvs.clients; i < g_psvs.maxclients; i++, client++)
int clientId = 0;
client_t *client = &g_psvs.clients[0];
for (; clientId < g_psvs.maxclients; clientId++, client++)
{
if (client->connected && !(i == nExcludeSlot && bIsReconnecting) && !Q_stricmp(client->name, val))
if (client->connected && !(clientId == nExcludeSlot && bIsReconnecting) && !Q_stricmp(client->name, val))
break;
}
// no duplicates for current name
if (i == g_psvs.maxclients)
if (clientId == g_psvs.maxclients)
return changed;
char newname[MAX_NAME];
Q_snprintf(newname, sizeof(newname), "(%d)%-0.*s", ++dupc, 28, rawname);
#ifdef REHLDS_FIXES
// Fix possibly incorrectly cut UTF8 chars