Skip to content

Commit 2ec9213

Browse files
authored
Freeroam security patch (#516)
1 parent 357fdf8 commit 2ec9213

File tree

4 files changed

+232
-65
lines changed

4 files changed

+232
-65
lines changed

[gameplay]/freeroam/fr_client.lua

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -198,9 +198,9 @@ function setSkinCommand(cmd, skin)
198198
return
199199
end
200200

201-
skin = skin and math.floor(tonumber(skin))
201+
skin = tonumber(skin)
202202

203-
if skin then
203+
if skin and skin == math.floor(skin) then
204204
server.setMySkin(skin)
205205
fadeCamera(true)
206206
closeWindow(wndSpawnMap)
@@ -234,7 +234,7 @@ function applyAnimation(leaf)
234234
return
235235
end
236236
end
237-
server.setPedAnimation(localPlayer, leaf.parent.name, leaf.name, true, true)
237+
server.setPedAnimation(localPlayer, leaf.parent.name, leaf.name, -1, true, true)
238238
end
239239

240240
function stopAnimation()
@@ -290,7 +290,7 @@ function animCmd(command, lib, name)
290290
errMsg('This animation may not be set by command')
291291
return
292292
end
293-
server.setPedAnimation(localPlayer, lib, name, true, true)
293+
server.setPedAnimation(localPlayer, lib, name, -1, true, true)
294294
end
295295
addCommandHandler('anim', animCmd)
296296

[gameplay]/freeroam/fr_server.lua

Lines changed: 80 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ g_RPCFunctions = {
3737
removeVehicleUpgrade = { option = 'upgrades', descr = 'Adding/removing upgrades' },
3838
setElementAlpha = { option = 'alpha', descr = 'Changing your alpha' },
3939
setElementInterior = true,
40+
setCameraInterior = true,
4041
setMySkin = { option = 'setskin', descr = 'Setting skin' },
4142
setPedAnimation = { option = 'anim', descr = 'Setting an animation' },
4243
setPedFightingStyle = { option = 'setstyle', descr = 'Setting fighting style' },
@@ -123,10 +124,6 @@ function onLocalSettingChange(setting,value)
123124
end
124125

125126
function joinHandler(player)
126-
if not player then
127-
player = source
128-
end
129-
130127
local r, g, b = math.random(50, 255), math.random(50, 255), math.random(50, 255)
131128
setPlayerNametagColor(player, r, g, b)
132129
g_PlayerData[player] = { vehicles = {}, settings={} }
@@ -137,7 +134,8 @@ function joinHandler(player)
137134
outputChatBox('Press F1 to show/hide controls', player, 0, 255, 0)
138135
end
139136
end
140-
addEventHandler('onPlayerJoin', root, joinHandler)
137+
138+
addEventHandler('onPlayerJoin', root, function() joinHandler(source) end)
141139

142140
local settingsToSend = {
143141
"command_spam_protection",
@@ -269,7 +267,7 @@ function handleClothesInit()
269267
end
270268
end
271269
addEvent('onClothesInit', true)
272-
addEventHandler('onClothesInit', resourceRoot, handleClothesInit)
270+
addEventHandler('onClothesInit', resourceRoot, handleClothesInit, false)
273271

274272
addEvent('onPlayerGravInit', true)
275273
addEventHandler('onPlayerGravInit', root,
@@ -281,122 +279,127 @@ addEventHandler('onPlayerGravInit', root,
281279
end
282280
)
283281

282+
------------------------------------------
283+
-- [START] Remote Player Call Functions --
284+
285+
284286
function setMySkin(skinid)
285-
if not isElement(source) then return end
286-
if getElementModel(source) == skinid then return end
287-
if isPedDead(source) then
288-
local x, y, z = getElementPosition(source)
287+
if not isElement(client) then return end
288+
if getElementModel(client) == skinid then return end
289+
if isPedDead(client) then
290+
local x, y, z = getElementPosition(client)
289291

290-
if isPedTerminated(source) then
292+
if isPedTerminated(client) then
291293
x = 0
292294
y = 0
293295
z = 3
294296
end
295297

296-
local r = getPedRotation(source)
297-
local interior = getElementInterior(source)
298-
spawnPlayer(source, x, y, z, r, skinid)
299-
setElementInterior(source, interior)
300-
setCameraInterior(source, interior)
298+
local r = getPedRotation(client)
299+
local interior = getElementInterior(client)
300+
spawnPlayer(client, x, y, z, r, skinid)
301+
setElementInterior(client, interior)
302+
setCameraInterior(client, interior)
301303
else
302-
setElementModel(source, skinid)
304+
setElementModel(client, skinid)
303305
end
304-
setCameraTarget(source, source)
305-
setCameraInterior(source, getElementInterior(source))
306+
setCameraTarget(client, client)
307+
setCameraInterior(client, getElementInterior(client))
306308
end
307309

308310
function spawnMe(x, y, z)
309311
if not x then
310-
x, y, z = getElementPosition(source)
312+
x, y, z = getElementPosition(client)
311313
end
312314

313-
if isPedTerminated(source) then
314-
repeat until spawnPlayer(source, x, y, z, 0, math.random(9, 288))
315+
if isPedTerminated(client) then
316+
repeat until spawnPlayer(client, x, y, z, 0, math.random(9, 288))
315317
else
316-
spawnPlayer(source, x, y, z, 0, getPedSkin(source))
318+
spawnPlayer(client, x, y, z, 0, getPedSkin(client))
317319
end
318320

319-
setCameraTarget(source, source)
320-
setCameraInterior(source, getElementInterior(source))
321+
setCameraTarget(client, client)
322+
setCameraInterior(client, getElementInterior(client))
321323
end
322324

323325
function warpMeIntoVehicle(vehicle)
324-
325326
if not isElement(vehicle) then return end
326327

327-
if isPedDead(source) then
328+
if isPedDead(client) then
328329
spawnMe()
329330
end
330331

331-
if getPedOccupiedVehicle(source) then
332-
outputChatBox('Get out of your vehicle first.', source, 255,0,0)
332+
if getPedOccupiedVehicle(client) then
333+
outputChatBox('Get out of your vehicle first.', client, 255, 0, 0)
333334
return
334335
end
335336
local interior = getElementInterior(vehicle)
336337
local numseats = getVehicleMaxPassengers(vehicle)
337338
local driver = getVehicleController(vehicle)
338339
for i=0,numseats do
339340
if not getVehicleOccupant(vehicle, i) then
340-
341-
if isPedDead(source) then
341+
if isPedDead(client) then
342342
local x, y, z = getElementPosition(vehicle)
343343
spawnMe(x + 4, y, z + 1)
344344
end
345345

346-
setElementInterior(source, interior)
347-
setCameraInterior(source, interior)
348-
warpPedIntoVehicle(source, vehicle, i)
346+
setElementInterior(client, interior)
347+
setCameraInterior(client, interior)
348+
warpPedIntoVehicle(client, vehicle, i)
349349
return
350350
end
351351
end
352352
if isElement(driver) then
353-
outputChatBox('No free seats left in ' .. getPlayerName(driver) .. '\'s vehicle.', source, 255, 0, 0)
353+
outputChatBox('No free seats left in ' .. getPlayerName(driver) .. '\'s vehicle.', client, 255, 0, 0)
354354
end
355-
356355
end
357356

358357
local sawnoffAntiAbuse = {}
358+
359359
function giveMeWeapon(weapon, amount)
360+
local player = client
360361
if table.find(getOption('weapons.disallowed'), weapon) then
361-
errMsg((getWeaponNameFromID(weapon) or tostring(weapon)) .. 's are not allowed', source)
362+
errMsg((getWeaponNameFromID(weapon) or tostring(weapon)) .. 's are not allowed', player)
362363
else
363-
giveWeapon(source, weapon, amount, true)
364+
giveWeapon(player, weapon, amount, true)
364365
if weapon == 26 then
365-
if not sawnoffAntiAbuse[source] then
366-
setControlState (source, "aim_weapon", false)
367-
setControlState (source, "fire", false)
368-
toggleControl (source, "fire", false)
369-
reloadPedWeapon (source)
370-
sawnoffAntiAbuse[source] = setTimer (function(source)
371-
if not source then return end
372-
toggleControl (source, "fire", true)
373-
sawnoffAntiAbuse[source] = nil
374-
end, 3000, 1, source)
366+
if not sawnoffAntiAbuse[player] then
367+
setControlState(player, "aim_weapon", false)
368+
setControlState(player, "fire", false)
369+
toggleControl(player, "fire", false)
370+
reloadPedWeapon(player)
371+
sawnoffAntiAbuse[player] = setTimer(function(thePlayer)
372+
if not isElement(thePlayer) then return end
373+
toggleControl(thePlayer, "fire", true)
374+
sawnoffAntiAbuse[thePlayer] = nil
375+
end, 3000, 1, player)
375376
end
376-
end
377+
end
377378
end
378379
end
379380

381+
380382
function giveMeVehicles(vehID)
381-
if not isElement(source) then return end
382-
local element = getPedOccupiedVehicle(source) or source
383+
local player = client
384+
if not isElement(player) then return end
385+
local element = getPedOccupiedVehicle(player) or player
383386
local px,py,pz = getElementPosition(element)
384387
local _,_,prot = getElementRotation(element)
385388
local posVector = Vector3(px,py,pz+2)
386389
local rotVector = Vector3(0,0,prot)
387390
local vehMatrix = Matrix(posVector,rotVector)
388-
local vehicleList = g_PlayerData[source].vehicles
391+
local vehicleList = g_PlayerData[player].vehicles
389392
if not vehID then return end
390393
if not table.find(getOption('vehicles.disallowed'), vehID) then
391394
if #vehicleList >= getOption('vehicles.maxperplayer') then unloadVehicle(vehicleList[1]) end
392395
local vehPos = posVector+vehMatrix.right*3
393396
local vehicle = Vehicle(vehID, vehPos, rotVector) or false
394397
if vehicle then
395-
vehicle.interior = source.interior
396-
vehicle.dimension = source.dimension
398+
vehicle.interior = player.interior
399+
vehicle.dimension = player.dimension
397400
if vehicle.vehicleType == "Bike" then vehicle.velocity = Vector3(0,0,-0.01) end
398401
table.insert(vehicleList, vehicle)
399-
g_VehicleData[vehicle] = { creator = source, timers = {} }
402+
g_VehicleData[vehicle] = { creator = player, timers = {} }
400403
if g_Trailers[vehID] then
401404
if getOption('vehicles.maxidletime') >= 0 then
402405
if getOption('vehicles.idleexplode') then
@@ -407,11 +410,14 @@ function giveMeVehicles(vehID)
407410
end
408411
end
409412
else
410-
errMsg(getVehicleNameFromModel(vehID):gsub('y$', 'ie') .. 's are not allowed', source)
413+
errMsg(getVehicleNameFromModel(vehID):gsub('y$', 'ie') .. 's are not allowed', player)
411414
end
412415
end
413416

414-
_setPlayerGravity = setPedGravity
417+
-- [END] Remote Player Call Functions --
418+
----------------------------------------
419+
420+
local _setPlayerGravity = setPedGravity
415421
function setPedGravity(player, grav)
416422
if grav < getOption('gravity.min') then
417423
errMsg(('Minimum allowed gravity is %.5f'):format(getOption('gravity.min')), player)
@@ -602,8 +608,8 @@ addEventHandler('onServerCall', resourceRoot,
602608

603609
-- Custom check made to intercept the jetpack on custom gravity
604610
if fnInfo and type(fnInfo) ~= "boolean" and tostring(fnInfo.option) == "jetpack" then
605-
if tonumber(("%.3f"):format(getPedGravity(source))) ~= 0.008 then
606-
errMsg("* You may use jetpack only if the gravity is set to 0.008", source)
611+
if tonumber(("%.3f"):format(getPedGravity(client))) ~= 0.008 then
612+
errMsg("* You may use jetpack only if the gravity is set to 0.008", client)
607613
return
608614
end
609615
end
@@ -613,11 +619,24 @@ addEventHandler('onServerCall', resourceRoot,
613619
for i,pathpart in ipairs(fnName:split('.')) do
614620
fn = fn[pathpart]
615621
end
622+
if not g_RPCFunctionsValidation[fnName] then
623+
outputDebugString('Function ' ..
624+
tostring(fnName) ..
625+
' is missing from the validation list. Please add this one to g_RPCFunctionsValidation.', 1)
626+
return
627+
end
628+
if not g_RPCFunctionsValidation[fnName](...) then
629+
errMsg('Something went wrong.', client)
630+
-- outputDebugString(
631+
-- 'Invalid parameters has been provided for function `' ..
632+
-- tostring(fnName) .. '` by user: ' .. getPlayerSerial(client) .. ' It can be a bug.', 1)
633+
return
634+
end
616635
fn(...)
617636
elseif type(fnInfo) == 'table' then
618-
errMsg(fnInfo.descr .. ' is not allowed', source)
637+
errMsg(fnInfo.descr .. ' is not allowed', client)
619638
end
620-
end
639+
end, false
621640
)
622641

623642
function clientCall(player, fnName, ...)

[gameplay]/freeroam/meta.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
<include resource="playerblips" />
1414

1515
<script src="util_server.lua" type="server" />
16+
<script src="remote_player_call_validation_server.lua" type="server" />
1617
<script src="fr_server.lua" type="server" />
1718

1819
<script src="util.lua" type="client" />

0 commit comments

Comments
 (0)