From 237ee464644b5c8d9485c1e4943019a24ade76e1 Mon Sep 17 00:00:00 2001 From: s1lent Date: Mon, 3 Sep 2018 17:34:08 +0700 Subject: [PATCH] SV_WriteId_f, DemoFile::StartRecording: Enforce certain extensions be used for files (*.dem, *.cfg) and prevent certain path characters from being used in commands SV_CheckForDuplicateNames: revert checks (default behavior hlds) --- rehlds/HLTV/common/DemoFile.cpp | 18 ++++++++++ rehlds/HLTV/common/common.cpp | 56 ++++++++++++++++++++++++++++++++ rehlds/HLTV/common/common_hltv.h | 2 ++ rehlds/engine/server.h | 2 +- rehlds/engine/sv_main.cpp | 34 +++++++++++++++++-- 5 files changed, 108 insertions(+), 4 deletions(-) diff --git a/rehlds/HLTV/common/DemoFile.cpp b/rehlds/HLTV/common/DemoFile.cpp index 611c7e2..f3ddbee 100644 --- a/rehlds/HLTV/common/DemoFile.cpp +++ b/rehlds/HLTV/common/DemoFile.cpp @@ -253,6 +253,24 @@ bool DemoFile::StartRecording(char *newName) Q_strlcpy(m_FileName, newName); + COM_DefaultExtension(m_FileName, ".dem"); + + if (m_FileName[0] == '/' + || Q_strstr(m_FileName, ":") + || Q_strstr(m_FileName, "..") + || Q_strstr(m_FileName, "\\")) + { + m_System->Printf("WARNING! DemoFile::StartRecording: unable to open %s (contains illegal characters).\n", m_FileName); + return false; + } + + const char *pszFileExt = COM_FileExtension(m_FileName); + if (Q_stricmp(pszFileExt, "dem") != 0) + { + m_System->Printf("WARNING! DemoFile::StartRecording: unable to open %s (wrong file extension, must be .dem).\n", m_FileName); + return false; + } + m_FileHandle = m_FileSystem->Open(m_FileName, "wb"); if (!m_FileHandle) { m_System->Printf("WARNING! DemoFile::StartRecording: coudn't open demo file %s.\n", m_FileName); diff --git a/rehlds/HLTV/common/common.cpp b/rehlds/HLTV/common/common.cpp index 76d0ecd..8b4b3d8 100644 --- a/rehlds/HLTV/common/common.cpp +++ b/rehlds/HLTV/common/common.cpp @@ -181,6 +181,62 @@ void COM_FileBase(char *in, char *out) out[len] = '\0'; } +void COM_DefaultExtension(char *path, char *extension) +{ + char *src; + src = path + Q_strlen(path) - 1; + + while (*src != '/' && *src != '\\' && src != path) + { + if (*src == '.') + { + return; + } + + src--; + } + + Q_strcat(path, extension); +} + +char *COM_FileExtension(char *in) +{ + static char exten[MAX_PATH]; + char *c, *d = nullptr; + int i; + + // Search for the first dot after the last path separator + c = in; + while (*c) + { + if (*c == '/' || *c == '\\') + { + d = nullptr; // reset dot location on path separator + } + else if (d == nullptr && *c == '.') + { + d = c; // store first dot location in the file name + } + c++; + } + + if (d == nullptr) + { + return ""; + } + + d++; // skip dot + + // Copy extension + for (i = 0; i < (ARRAYSIZE(exten) - 1) && *d; i++, d++) + { + exten[i] = *d; + } + + exten[i] = '\0'; + return exten; +} + char com_token[COM_TOKEN_LEN]; qboolean s_com_token_unget = FALSE; diff --git a/rehlds/HLTV/common/common_hltv.h b/rehlds/HLTV/common/common_hltv.h index 8af86ed..ecd8ebf 100644 --- a/rehlds/HLTV/common/common_hltv.h +++ b/rehlds/HLTV/common/common_hltv.h @@ -34,6 +34,8 @@ char *COM_SkipPath(char *pathname); char *COM_GetBaseDir(); void COM_FixSlashes(char *pname); void COM_FileBase(char *in, char *out); +void COM_DefaultExtension(char *path, char *extension); +char *COM_FileExtension(char *in); void COM_UngetToken(); char *COM_Parse(char *data); char *COM_VarArgs(char *format, ...); diff --git a/rehlds/engine/server.h b/rehlds/engine/server.h index 7adca46..9110369 100644 --- a/rehlds/engine/server.h +++ b/rehlds/engine/server.h @@ -494,7 +494,7 @@ int SV_FinishCertificateCheck_internal(netadr_t *adr, int nAuthProtocol, char *s int SV_CheckKeyInfo(netadr_t *adr, char *protinfo, unsigned short *port, int *pAuthProtocol, char *pszRaw, char *cdkey); int SV_CheckKeyInfo_internal(netadr_t *adr, char *protinfo, unsigned short *port, int *pAuthProtocol, char *pszRaw, char *cdkey); int SV_CheckForDuplicateSteamID(client_t *client); -int SV_CheckForDuplicateNames(char *userinfo, qboolean bIsReconnecting, int nExcludeSlot); +qboolean SV_CheckForDuplicateNames(char *userinfo, qboolean bIsReconnecting, int nExcludeSlot); int SV_CheckUserInfo(netadr_t *adr, char *userinfo, qboolean bIsReconnecting, int nReconnectSlot, char *name); int SV_FindEmptySlot(netadr_t *adr, int *pslot, client_t ** ppClient); void SV_ConnectClient(void); diff --git a/rehlds/engine/sv_main.cpp b/rehlds/engine/sv_main.cpp index 663a330..45b70e7 100644 --- a/rehlds/engine/sv_main.cpp +++ b/rehlds/engine/sv_main.cpp @@ -1985,13 +1985,21 @@ int SV_CheckForDuplicateSteamID(client_t *client) return -1; } -int SV_CheckForDuplicateNames(char *userinfo, qboolean bIsReconnecting, int nExcludeSlot) +qboolean SV_CheckForDuplicateNames(char *userinfo, qboolean bIsReconnecting, int nExcludeSlot) { int dupc = 0; - int changed = FALSE; + qboolean changed = FALSE; const char *val = Info_ValueForKey(userinfo, "name"); +#ifndef REHLDS_FIXES + if (!val || val[0] == '\0' || Q_strstr(val, "..") != NULL || Q_strstr(val, "\"") != NULL || Q_strstr(val, "\\") != NULL) + { + Info_SetValueForKey(userinfo, "name", "unnamed", MAX_INFO_STRING); + return TRUE; + } +#endif // REHLDS_FIXES + char rawname[MAX_NAME]; Q_strncpy(rawname, val, MAX_NAME - 1); @@ -2011,6 +2019,7 @@ int SV_CheckForDuplicateNames(char *userinfo, qboolean bIsReconnecting, int nExc char newname[MAX_NAME]; Q_snprintf(newname, sizeof(newname), "(%d)%-0.*s", ++dupc, 28, rawname); + #ifdef REHLDS_FIXES // Fix possibly incorrectly cut UTF8 chars if (!Q_UnicodeValidate(newname)) @@ -2018,6 +2027,7 @@ int SV_CheckForDuplicateNames(char *userinfo, qboolean bIsReconnecting, int nExc Q_UnicodeRepair(newname); } #endif // REHLDS_FIXES + Info_SetValueForKey(userinfo, "name", newname, MAX_INFO_STRING); val = Info_ValueForKey(userinfo, "name"); changed = TRUE; @@ -6816,8 +6826,26 @@ void SV_RemoveId_f(void) void SV_WriteId_f(void) { + if (bannedcfgfile.string[0] == '/' || + Q_strstr(bannedcfgfile.string, ":") || + Q_strstr(bannedcfgfile.string, "..") || + Q_strstr(bannedcfgfile.string, "\\")) + { + Con_Printf("Couldn't open %s (contains illegal characters).\n", bannedcfgfile.string); + return; + } + char name[MAX_PATH]; - Q_snprintf(name, MAX_PATH, "%s", bannedcfgfile.string); + Q_strlcpy(name, bannedcfgfile.string); + COM_DefaultExtension(name, ".cfg"); + + const char *pszFileExt = COM_FileExtension(name); + if (Q_stricmp(pszFileExt, "cfg") != 0) + { + Con_Printf("Couldn't open %s (wrong file extension, must be .cfg).\n", name); + return; + } + Con_Printf("Writing %s.\n", name); FILE *f = FS_Open(name, "wt");