Skip to content

Commit

Permalink
Split the lines
Browse files Browse the repository at this point in the history
Allow more whitespace
Change whitelist format to domain:port
Tighten the space/tab regex a bit
Clear the whitelist when module closes
Use map and set instead of vector
Don't need to pass in lua interface
Use errcodes instead
Fixed lua error usage
Move comment
Got it compiling
Update premake5.lua
These aren't external
Progress
Started whitelist code
  • Loading branch information
thegrb93 committed Jan 16, 2020
1 parent 963d53a commit cdc65b1
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 4 deletions.
21 changes: 17 additions & 4 deletions projects/premake5.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,14 @@ newoption({
value = "path to garrysmod_common directory"
})

newoption({
trigger = "whitelist",
description = "Enables wrapping of getaddrinfo and a whitelist file to filter valid addresses and ports",
value = "0 or 1"
})

local gmcommon = _OPTIONS.gmcommon or os.getenv("GARRYSMOD_COMMON")
local whitelist = _OPTIONS.whitelist == "1"
if gmcommon == nil then
error("you didn't provide a path to your garrysmod_common (https://github.com/danielga/garrysmod_common) directory")
end
Expand All @@ -16,6 +23,7 @@ local LUASOCKET_FOLDER = "../luasocket/src"
CreateWorkspace({name = "socket.core"})
CreateProject({serverside = true, manual_files = true})
files("../source/socket.cpp")
if whitelist then files("../source/whitelist.cpp") defines({"USE_WHITELIST"}) includedirs(LUASOCKET_FOLDER) end
IncludeLuaShared()
links("socket")

Expand All @@ -24,6 +32,7 @@ CreateWorkspace({name = "socket.core"})

CreateProject({serverside = false, manual_files = true})
files("../source/socket.cpp")
if whitelist then files("../source/whitelist.cpp") defines({"USE_WHITELIST"}) includedirs(LUASOCKET_FOLDER) end
IncludeLuaShared()
links("socket")

Expand Down Expand Up @@ -52,19 +61,23 @@ CreateWorkspace({name = "socket.core"})
IncludeLuaShared()

filter("system:windows")
defines({
local windowsdefines = {
"LUASOCKET_API=__declspec(dllexport)",
"MIME_API=__declspec(dllexport)"
})
}
if whitelist then windowsdefines[#windowsdefines+1] = "getaddrinfo=__wrap_getaddrinfo" end
defines(windowsdefines)
files(LUASOCKET_FOLDER .. "/wsocket.c")
links("ws2_32")

filter("system:not windows")
defines({
local unixdefines = {
"LUASOCKET_API=''",
"UNIX_API=''",
"MIME_API=''"
})
}
if whitelist then unixdefines[#unixdefines+1] = "getaddrinfo=__wrap_getaddrinfo" end
defines(unixdefines)
files(LUASOCKET_FOLDER .. "/usocket.c")

CreateWorkspace({name = "mime.core"})
Expand Down
29 changes: 29 additions & 0 deletions source/socket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,33 @@

extern "C" int luaopen_socket_core( lua_State *state );

int parseWhitelist();
void clearWhitelist();
enum : int
{
PARSE_SUCCESS = 0,
PARSE_CANT_READ = 1,
PARSE_NO_ENTRIES = 2
};

GMOD_MODULE_OPEN( )
{
#ifdef USE_WHITELIST
switch (parseWhitelist())
{
case PARSE_SUCCESS:
break;
case PARSE_CANT_READ:
LUA->ThrowError("Failed to read whitelist file!");
break;
case PARSE_NO_ENTRIES:
LUA->ThrowError("Didn't find any valid entries in whitelist file!");
break;
default:
break;
}
#endif

if( luaopen_socket_core( LUA->GetState( ) ) == 1 )
{
LUA->Push( -1 );
Expand All @@ -15,6 +40,10 @@ GMOD_MODULE_OPEN( )

GMOD_MODULE_CLOSE( )
{
#ifdef USE_WHITELIST
clearWhitelist();
#endif

LUA->PushNil( );
LUA->SetField( GarrysMod::Lua::INDEX_GLOBAL, "socket" );
return 0;
Expand Down
90 changes: 90 additions & 0 deletions source/whitelist.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#undef getaddrinfo

#include "socket.h"
#include <map>
#include <set>
#include <fstream>
#include <sstream>
#include <regex>

//Somewhere glua can't read?
const char* whitelistDir = "../gm_socket_whitelist.txt";
std::map<std::string, std::set<std::string> > whitelist;

enum : int
{
PARSE_SUCCESS = 0,
PARSE_CANT_READ = 1,
PARSE_NO_ENTRIES = 2
};

int parseWhitelist()
{
std::ifstream input(whitelistDir);
if (input)
{
std::stringstream filereader;
filereader << input.rdbuf();
std::string filedata = filereader.str();
std::regex line_parser("(?:(?!\r?\n).)+");
std::regex entry_parser("^[ \\t]*([\\w\\.-]+)\\:(\\d+)[ \\t]*$");
for (std::sregex_iterator line = std::sregex_iterator(filedata.begin(), filedata.end(), line_parser), end = std::sregex_iterator(); line != end; ++line)
{
const std::string& linestr = line->operator[](0);
std::smatch match;
if(std::regex_match(linestr, match, entry_parser))
{
whitelist[match[1].str()].insert(match[2].str());
}
}
if (whitelist.empty())
{
return PARSE_NO_ENTRIES;
}
}
else
{
return PARSE_CANT_READ;
}
return PARSE_SUCCESS;
}

void clearWhitelist()
{
whitelist.clear();
}

bool isSafe(const char* pNodeName, const char* pServiceName)
{
std::map<std::string, std::set<std::string> >::iterator domain = whitelist.find(pNodeName);
return domain != whitelist.end() && domain->second.count(pServiceName)==1;
}

extern "C" {

#ifdef _WIN32
INT WSAAPI __wrap_getaddrinfo(
_In_opt_ PCSTR pNodeName,
_In_opt_ PCSTR pServiceName,
_In_opt_ const ADDRINFOA * pHints,
_Outptr_result_maybenull_ PADDRINFOA * ppResult
)
#else
int __wrap_getaddrinfo (__const char *__restrict pNodeName,
__const char *__restrict pServiceName,
__const struct addrinfo *__restrict pHints,
struct addrinfo **__restrict ppResult)
#endif
{
if(isSafe(pNodeName, pServiceName))
{
return getaddrinfo(pNodeName, pServiceName, pHints, ppResult);
}
else
{
*ppResult = nullptr;
return EAI_FAIL;
}
}

}

0 comments on commit cdc65b1

Please sign in to comment.