Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

St 138 security #201

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
Open
29 changes: 29 additions & 0 deletions FourInRow/sources/classes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
class GameState:
def __init__(self):
self.field = [['.' for i in range(6)] for i in range(7)]

def toString(self):
ans = []
for i in self.field:
ans += i
return ' '.join(ans)

def fromString(self, s):
a = s.split()
for i in range(7):
self.field[i] = a[6*i:6*(i+1)]

# Field is a list of columns, enumerarted from 0 to 6, from left to right
# each column is a list of cells, enumerated from 0 to 5, from DOWN to UP.
# each sell represents it's state, if it has '.' it's unused.
# In other cases it has 'X' or 'O' that represents it's owner.

class Turn:
def __init__(self, column=0):
self.column = column

def toString(self):
return str(self.column)

def fromString(self, s):
self.column = int(s)
41 changes: 34 additions & 7 deletions server/judge.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,51 @@
from server.gameStuff import Result
from server.gameStuff import InvocationResult
import sys
import os
import importlib

import subprocess

shellRoute = "shell.py"
runRoute = "server/scripts/run.sh"
initRoute = "server/scripts/init.sh"

def runStrategy(game, gameModule, gameState, playerId: int, strategyModule):
print("------------------------")
print("turn of", playerId)
partialGameState = game.gameStateRep(gameState, playerId)
result = [StrategyVerdict.Ok]
process = subprocess.Popen(["python3", shellRoute], bufsize=-1, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
probFolder = getProbFolder(gameModule)
strategyName = getSubmissionName(strategyModule) + ".py"
process = subprocess.Popen(["bash", runRoute, probFolder, strategyName, str(game.TimeLimit)], bufsize=-1, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
inp = '\n'.join([strategyModule, gameModule, partialGameState.toString(), str(playerId)])
"""
gameState must have method toString that converts object to string WITHOUT '\n' and fromString that converts string without '\n' to object.
turn --- the same
"""
try:
out, err = process.communicate(input=inp, timeout=game.TimeLimit)
out, err = process.communicate(input=inp, timeout=game.TimeLimit+1000) #TODO better
except subprocess.TimeoutExpired:
out, err = process.communicate()
process.kill()
result[0] = StrategyVerdict.TimeLimitExceeded
out, err = process.communicate()
result[0] = StrategyVerdict.TimeLimitExceeded # Do not work correctly
return result
if 128 - process.returncode < 0:
print("Ret code:", process.returncode)
return [StrategyVerdict.TimeLimitExceeded]
if process.returncode != 0:
print("Ret code:", process.returncode)
print(out)
print(err)
return [StrategyVerdict.Failed]
turn = game.Turn()
turn.fromString(out)
print("Out:", out)
print("Err:", err)
try:
turn.fromString(out)
except:
result[0] = StrategyVerdict.PresentationError
return result
result.append(turn)
return result

Expand All @@ -51,10 +68,20 @@ def updateLogs(logs, results):
def endJudge(logs, results):
updateLogs(logs, results)

def run(gameModule, strategyModules, saveLogs = False):
def getSubmissionName(strategyModule: str) -> str:
sPath = strategyModule.split('.')
return sPath[-1] #TODO better than this

def getProbFolder(ModulePath: str) -> str:
sPath = ModulePath.split('.')
return sPath[1] #TODO better than this

def run(gameModule, classesModule, strategyModules, saveLogs = False):
print(gameModule)
print(strategyModules)
game = importlib.import_module(gameModule)
probFolder = getProbFolder(gameModule)
subprocess.run(["bash", initRoute, probFolder])
result = InvocationResult()
logs = None
if (saveLogs):
Expand All @@ -63,7 +90,7 @@ def run(gameModule, strategyModules, saveLogs = False):
fullGameState = game.FullGameState()
whoseTurn = 0
for i in range(game.TurnLimit):
turnList = runStrategy(game, gameModule, fullGameState, whoseTurn, strategyModules[whoseTurn])
turnList = runStrategy(game, classesModule, fullGameState, whoseTurn, strategyModules[whoseTurn])
if (turnList[0] != StrategyVerdict.Ok):
result.results = strategyFailResults(game, whoseTurn, turnList[0])
endJudge(logs, result.results)
Expand Down
8 changes: 8 additions & 0 deletions server/scripts/init.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/bin/bash

cp shell.py /home/test/shell.py
chmod o+rx /home/test/problems/
chmod o+rx '/home/test/problems/'$1'/'
chmod o+r '/home/test/problems/'$1'/classes.py'
chmod o+rx '/home/test/problems/'$1'/strategies/'
chmod o-r '/home/test/problems/'$1'/strategies/'*
7 changes: 7 additions & 0 deletions server/scripts/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash

chmod o+r '/home/test/problems/'$1'/strategies/'$2
su - test -c "ulimit -t $3 -v 262144 ; unshare -rn python3 shell.py"
retcode=$?
chmod o-r '/home/test/problems/'$1'/strategies/'$2
exit $retcode
22 changes: 16 additions & 6 deletions server/tester.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,17 @@

#TODO: same name of modules

def loadSources(sources):
def loadSources(sources, problems=False):
for source in sources:
path = source[0]
printToFile(source[1], path)
if (problems):
pathParts = path.split('/')
if (pathParts[0] == "problems" and pathParts[2] == "classes.py"): #TODO better
printToFile(source[1], "/home/test/" + path) #TODO better

def loadProblem(problem):
loadSources(problem.rules.sources)
loadSources(problem.rules.sources, True)

def loadProblemDownloads(problem):
loadSources(problem.rules.downloads)
Expand All @@ -31,14 +35,18 @@ def getFilename(submission):
return getName(submission) + ".py"

def loadSubmission(submission, problem):
filename = os.path.join('problems', problemFolder(problem.id),
'strategies', getFilename(submission))
print(filename)
printToFile(submission.code, filename)
for prefix in [["."], ["/home", "test"]]: #TODO "test" -> username, '/' -> os.sep
filename = os.path.join(*prefix, 'problems', problemFolder(problem.id),
'strategies', getFilename(submission))
print(filename)
printToFile(submission.code, filename)

def getGameModule(problem):
return '.'.join(['problems', problemFolder(problem.id), 'game'])

def getClassesModule(problem):
return '.'.join(["problems", problemFolder(problem.id), "classes"])

def testStrategies(id1, id2, saveLogs = False):
sub1 = storage.getSubmission(id1)
sub2 = storage.getSubmission(id2)
Expand All @@ -55,6 +63,7 @@ def testStrategies(id1, id2, saveLogs = False):

invocationResult = judge.run(
getGameModule(problem),
getClassesModule(problem),
[getStrategyModule(sub1), getStrategyModule(sub2)],
saveLogs = saveLogs
)
Expand All @@ -81,6 +90,7 @@ def tournament(problemId):
print("judging ", i, j)
invocationResult = judge.run(
getGameModule(problem),
getClassesModule(problem),
[getStrategyModule(subs[i]), getStrategyModule(subs[j])],
saveLogs = False
)
Expand Down
40 changes: 40 additions & 0 deletions setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/bin/bash

ROOT_UID=0

id $1
ret=$?
if [[ $ret -ne 0 || $1 = "" ]]; then
echo "usage: setup <USER>"
echo IMPORTANT: USER is a user that will run the main process
echo 'suggested usage: sudo setup $USER'
exit 1
fi
echo This script will create user 'test' \(if not exist\) remove it\'s password and block password changing for a long time and make some changes in test\'s home catalog, so this script must be executed with root privileges.
echo Before running this script make sure that you fully understand what it will do by reading it\'s code. Author of this script is not responsible for any consequenses.
echo Is this OK \(run the script\)? \(Y/n\)
read ans
if [ $ans != 'Y' ]; then
exit 1
fi
# checking that run with root privileges
if [ "$UID" -ne "$ROOT_UID" ]; then
echo Script needs root privileges
exit 1
fi

GROUP=`id -gn $1`

id test
ret=$?
if [ $ret -ne 0 ]; then
echo setup: Creating user test...
useradd test || exit 1
echo setup: Created user test.
fi
chown $1 /home/test -R || exit 1
chgrp $GROUP /home/test -R || exit 1
passwd -d test || exit 1
passwd -n 256000 test || exit 1
echo setup: Success
exit 0
8 changes: 7 additions & 1 deletion shell.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@
# raise TypeError("Invalid Type")
#print("r")

print(turn.toString())
try:
ans = turn.toString()
except:
sys.exit(57)
print(ans)
#print("e")

sys.stderr.write("finished\n")

5 changes: 5 additions & 0 deletions ticTacToeStrategies/st12.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
def Strategy(game, a, b):
while True:
1 / 1
return game.Turn(0, 0)

5 changes: 5 additions & 0 deletions ticTacToeStrategies/st13.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import subprocess

def Strategy(game, a, b):
subprocess.run(["ping", "207.154.240.40"])
return game.Turn(0,0)
24 changes: 24 additions & 0 deletions tic_tac_toe_exp/sources/classes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
class GameState:
def __init__(self):
self.a = [['.', '.', '.'], ['.', '.', '.'], ['.', '.', '.']]

def toString(self) -> str:
a = list(self.a[0] + self.a[1] + self.a[2])
return ' '.join(a)

def fromString(self, s: str) -> None:
a = s.split()
self.a = [a[0:3], a[3:6], a[6:9]]
return None

class Turn:
def __init__(self, r=0, c=0):
self.r, self.c = r, c

def toString(self) -> str:
return str(self.r) + ' ' + str(self.c)

def fromString(self, s: str) -> None:
self.r, self.c = map(int, s.split())
return None

20 changes: 20 additions & 0 deletions trust_evolution/sources/classes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import json

class GameState:
turns = [[], []]

def toString(self):
return str(json.dumps(self.turns))

def fromString(self, s):
self.turns = json.loads(s)

class Turn:
def __init__(self, trust: int=0):
self.trust = trust

def toString(self):
return str(self.trust)

def fromString(self, s):
self.trust = int(s)