Update 11/13/11 - VoiDeD / Chrisaster took over development way more than a year ago and will be way more helpful than I can
GateKeeper allows Lua scripts to override the source server password check, allowing replacements of or additions to the normal sv_password check. This allows servers to have additional valid passwords or to use an authentication database that allows per-user or per-ip passwords. For private servers, this could help to eliminate password leaks, as the source of the leak would be immediately known. Furthermore, the function that it exposes completely invalidates the need for reserved slots in a server, as an unwanted player can be immediately dropped after a password has been verified, allowing a player to join an otherwise full server without receiving an error message.
Features:
Adds one new hook: "PlayerPasswordAuth"
Adds five new functions: "gatekeeper.Drop", "gatekeeper.DropAllClients", "gatekeeper.GetNumClients", "gatekeeper.GetUserByAddress", and "gatekeeper.ForceProtocol"
Usage:
Hook: PlayerPasswordAuth
Arguments: string username, string password, string steamid, string ipaddress
Returns: bool allowed OR string denyreason OR table { bool allowed [, string denyreason] }
Notes: Returning nil allows the default server password check to execute. Returning true forces the password to be accepted, while false forces it to be denied. If a string is returned, the client is denied access with the message contained in the string. If a table is used as the return value, the second member can be used as an error message to be displayed to the client in place of the typical "Bad password." message.
Example:
-- This function will print the username and provided password of all connection attempts. local function CheckPassword(user, pass, steam, ip) print(Format("User: '%s' Pass: '%s' SteamID: '%s'", name, pass, steam)) -- Force all password comparisons to fail and display a custom error. return {false, Format("'%s' is not the password I was looking for, %s", pass, name)} -- The above line is equivalent to: -- return Format("'%s' is not the password I was looking for, %s", pass, name) -- Or, if you do not want to specify an error message and simply want clients kicked: -- return false end hook.Add("PlayerPasswordAuth", "Example", CheckPassword)
Function: gatekeeper.Drop
Arguments: number userid (Not the entity index!), string reason
Returns: bool dropped (true if player found, false if userid was not connected)
Notes: This takes place instantly; when the function has returned the client has already been disconnected. This allows for the server to drop a player during password verification and have the slot be immediately filled by the client attempting to have their password verified. Reserved slots are a thing of the past! This can happen at any time, and is not limited to PlayerPasswordAuth. Be wary of this, however, as a call to this immediately removes the client from the server, so if done in a hook like PlayerSay, this can crash the server if you allow the message to go through. Only use this when you can ensure that nothing will be done with the player's object for the rest of the hook. This is safe to call in concommands. This is useful for kick messages in general.
Example:
-- Server sterilization for k,v in pairs(player.GetAll()) do if v:Name() == "SamuraiMushroom" then gatekeeper.Drop(v:UserID(), "Worthless") end end
Function: gatekeeper.GetNumClients
Arguments: none
Returns: table { active = ?, spawning = ?, total = ? }
Notes: Gets a table returning information about the clients connected to the server: How many there are, how many are ingame, and how many are currently connecting.
Example:
local clients = gatekeeper.GetNumClients() print(clients.active) -- prints the number of clients currently active (have spawned) in the server print(clients.spawning) -- prints the number of clients in the connection process print(clients.total) -- prints the total number of clients in the server (connecting AND in game)
Function: gatekeeper.DropAllClients
Arguments: string disconnectreason
Returns: nil
Notes: Self explanatory
Example:
hook.Add("Think", "Teh Kieranator", function() gatekeeper.DropAllClients("You have been Kieranated") end)
Function: gatekeeper.GetUserByAddress
Arguments: string ipaddress (in form ip:port)
Returns: int userid (if ip was valid and connected) or nil (no user connected from that ip)
Example: This will not work in PlayerPasswordAuth because the connecting player does not have a userid yet. At any other point except possibly PlayerConnect (untested), it should function as expected.
for k,v in pairs(player.GetAll()) do print(v:UserID(), gatekeeper.GetUserByAddress(v:IPAddress())) -- should be the same end
Long, drawn out example:
-- GateKeeper V4 Example File -- ComWalk -- -- This file demonstrates adding two additional passwords, one of which will -- force the server to make room for the client, invalidating the need for -- reserved slots to be used. require("gatekeeper") -- The cvar that will act as an additional password local pass_new = CreateConVar("sv_password_new", "", FCVAR_PROTECTED | FCVAR_NOTIFY) -- The cvar that will make room for a client if they attempt to join local pass_makeroom = CreateConVar("sv_password_makeroom", "", FCVAR_PROTECTED | FCVAR_NOTIFY) local function PasswordCheck(name, pass, steam, ip) print(Format("User: '%s' Pass: '%s' SteamID: '%s'", name, pass, steam)) -- To make use of the new error messages, you are forced to -- return a table. Garry's hook module does not support hooks -- that return multiple values, and this is the Next Best Thing. -- Valid return values are booleans and tables following the -- following format: { bool allow [, string reason] } -- The reason will only be used by the module if the client -- is not allowed in the server. if name == "SamuraiMushroom" then return {false, "Entry automatically denied: Worthless"} elseif steam == "STEAM_0:1:16258120" then return {false, "Changing your name won't help either."} elseif steam == "STEAM_0:0:9249431" then return {false, "Beat you to the punch on this one too."} end if pass_new:GetString() == pass and pass_new:GetString() != "" then -- Since the given password matches the 'new' password -- and the new password has been set, returning true -- will prevent the normal password check code -- from being executed. return true elseif pass_makeroom:GetString() == pass and pass_makeroom:GetString() != "" then local players = gatekeeper.GetNumClients().total -- There is no need to drop anybody if the server isn't full if players == MaxPlayers() then local dropme = players[math.random(1, #players)] -- Gatekeeper exposes a new function to Lua, gatekeeper.Drop, -- which allows for the server to drop a client with a custom reason. -- Unlike using RunConsoleCommand to kick the unwanted player, this -- takes place instantly, and because the maxplayers check takes place -- after the password check, any player that provides this password to -- the server will successfully join, without any error message. gatekeeper.Drop(dropme:UserID(), Format("Auto-kicking to make room for '%s'", name)) end -- Provided password was valid; force success and prevent -- the default password check from being executed. return true end -- Returning nil will allow the default password check to take place -- and, in the case of this example, check sv_password as well. -- In the event of a custom authentication system in which -- the default check doesn't need to be run at all, simply -- returning false here will suffice. return end hook.Add("PlayerPasswordAuth", "test", PasswordCheck)
Download:
Win32
Linux

Register
Events
Popular
More
Post #1


Lua King x 9
Useful x 9



Dumb x 1
Friendly x 1


Winner x 1