def unlockChallengeFile(chalID, code): userName = current_user.name if chalID in challenges.idToKey: cfg = copy.deepcopy(challenges.getChalConfig(chalID)) allowPostUnlock = "" try: allowPostUnlock = cfg["unlock_post"].split(",") except: allowPostUnlock = [] try: unlockCodes = cfg["unlock_codes"].split(",") except: unlockCodes = [] if not (len(allowPostUnlock) == len(unlockCodes)): return "Inconsistent length of unlock codes" postUnlock = dict(zip(unlockCodes, allowPostUnlock)) if code in postUnlock: # unlock code found in configuration file fileName = postUnlock[code] #print("FOUND POSTUNLOCK:",code,fileName) db.unlockFile(userName, chalID, fileName, code, getClientIPAddress()) else: # is someone trying random unlock codes? return "ERROR: what are you trying to do?" return genericError
def getChalHints(chalID): if not (chalID in challenges.idToKey): return {"results": "Challenge not found!"} userName = current_user.name chalHints = db.getUserHints(userName, chalID) cfg = challenges.getChalConfig(chalID) _heartBeat = False try: _heartBeat = False try: _heartBeat = request.values["heartbeat"] except: pass if _heartBeat: # Handle HeartBeat #print("HB:", chalID, userName, getClientIPAddress()) db.addHeartBeat(userName, chalID, getClientIPAddress()) # Handle File Cache hasFiles = False try: _files = json.loads(request.values["userfiles"]) hasFiles = True except: pass if hasFiles: allChalDir = db.getCacheDir(userName) cacheDir = allChalDir.get(chalID, None) if None != cacheDir: for f in _files: fullPath = os.path.normpath(os.path.join(cacheDir, f)) #print("Write Cache File:",fullPath) with open(fullPath, "w+") as o: o.write(_files[f]) #p(_files) else: print("ERROR: could not get the cache dir!!!") except Exception as e: print("Exception: " + str(e)) hintsHtml = "<br>" for hint in chalHints: html = '<div class="box3 sb14">' + hint["html"] + '</div>' hintsHtml = html + hintsHtml hintsHtml = "<br>" + hintsHtml return {"hints": hintsHtml}
def postSendAll(chalID): if not (chalID in challenges.idToKey): return {"results": "Challenge not found!"} userName = current_user.name userIP = getClientIPAddress() db.unlockChallenge(userName, chalID, userIP) cfg = copy.deepcopy(challenges.getChalConfig(chalID)) userData = json.loads(request.values["userfiles"]) r = challenges.evalChalFromDirStruct(userName, userIP, chalID, userData) feedback = cfg.get( "feedback", "collect") # by default collect feedback from player on the challenge # set feedback to "skip" in challenges.yaml to skip this step return { "results": r["result"], "log-results": r["logger"], "solve": r["solve"], "feedback": feedback }
def challengeRoot(chalID): userName = current_user.name ipAddress = getClientIPAddress() #db.addChalCache(userName,chalID,"xxx") if chalID in challenges.idToKey: cfg = challenges.getChalConfig(chalID) rootFile = cfg["root_file"] db.unlockChallenge(userName, chalID, ipAddress) db.addInteraction(userName, chalID, "ENTRY", "visit challenge", "", ipAddress) if cfg["root"] == "template": # programming challenges isAdmin = db.isUserAdmin(userName) return render_template(rootFile, cfg=cfg, hbTimer=heartBeat, isAdmin=isAdmin) elif cfg["root"] == "challenge": # multiple choice questions chalDir = cfg["directory"] tplFile = os.path.join(chalDir, rootFile) tpl = open(tplFile, "r").read() t = Template(tpl) isAdmin = db.isUserAdmin(userName) return t.render({ "cfg": cfg, "hbTimer": heartBeat, "chalID": chalID, "isAdmin": isAdmin }) else: return genericError else: p(chalID) p(challenges.idToKey) db.addInteraction(userName, chalID, "ENTRY", "unkown challenge", "", ipAddress) return genericError
def postSend(chalID): if not (chalID in challenges.idToKey): return {"results": "Challenge not found!"} userName = current_user.name userIP = getClientIPAddress() db.unlockChallenge(userName, chalID, userIP) cfg = copy.deepcopy(challenges.getChalConfig(chalID)) mainFileContent = request.values["usercontent"] #print("----mainFileContent----------------------") #print(mainFileContent) #print("-----------------------------------------") inputFileContent = "" try: inputFileContent = request.values["inputfile"] #print("~~~~inputFileContent~~~~~~~~~~~~~~~~~~~~~") #print(inputFileContent) #print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~") except: pass (result, d, tcDir) = challenges.evalChalFromString(userName, chalID, mainFileContent, inputFileContent) chalLogLines = challenges.collectChallengeEvalLogs(tcDir) chalLog = [] for s in chalLogLines: chalLog.append(escape(s)) chalLog = "<br>".join(chalLog) failMsg = None failPrio = None tag = None if result == False: try: for e in d: if d[e]["pass"] == "FAIL": newPrio = int(d[e]["nr"]) if None == failPrio: failPrio = newPrio failMsg = d[e]["msg"] tag = d[e]["x"] else: if newPrio < failPrio: failPrio = newPrio failMsg = d[e]["msg"] tag = d[e]["x"] if failMsg: hintHtml = "" if tag in challenges.allTags: myTag = challenges.allTags[tag] tagDesc = myTag["description"] hintHtml = tagDesc.format(**myTag) db.addHintTag(userName, chalID, tag, hintHtml, getClientIPAddress()) if False: # Toggle this to test a new tag myTag = challenges.allTags["TEST_TAG"] tagDesc = myTag["description"] hintHtml = tagDesc.format(**myTag) #print("HINT:",hintHtml) db.addHintTag(userName, chalID, "TEST_TAG", hintHtml, getClientIPAddress()) db.addInteraction(userName, chalID, "FAIL", failMsg, tcDir, getClientIPAddress()) return {"results": failMsg, "log-results": chalLog} else: msg = "Oops! please contact one of the coaches" db.addInteraction(userName, chalID, "OOPS", msg, tcDir, getClientIPAddress()) return {"results": msg, "log-results": chalLog} except: pass #p(d) msg = "Oops! - where did the failed result go to?" db.addInteraction(userName, chalID, "OOPS", msg, tcDir, getClientIPAddress()) return {"results": msg, "log-results": chalLog} else: flag = str(cfg["flag"]) db.addInteraction(userName, chalID, "SOLVE", flag, tcDir, getClientIPAddress()) return { "results": "Well done, here is your flag: " + flag, "log-results": chalLog }
def sendFile(chalID): userName = current_user.name ipAddress = getClientIPAddress() try: resetChal = False try: resetChal = request.values["reset"] == "true" except: pass if not (chalID in challenges.idToKey): db.addInteraction(userName, chalID, "OOPS", "challenge not found", "", ipAddress) return "Not Found!" else: chalKey = challenges.idToKey[chalID] chalPath = challenges.allChallenges[chalKey]["directory"] allChalDir = db.getCacheDir(userName) chalDir = allChalDir.get(chalID, None) cacheFiles = False if None != chalDir: # We have already a Cache... use it... #print("GET Cache: for user", userName) srcDir = chalDir else: # We do not have a Cache... we will create it... newUUID = str(uuid.uuid4()) # Generate new random UUID cacheDir = "upload/cache/" + newUUID srcDir = chalPath cacheFiles = True os.mkdir(cacheDir) db.addChalCache(userName, chalID, cacheDir) #print("GEN Cache:",cacheDir," for chalID",chalID," for user", userName) #print("Send Challenge Directory") cfg = challenges.getChalConfig(chalID) files = cfg.get("files", "") filesToSend = [] if not (files == ""): filesToSend = cfg.get("files", "").split(",") firstFile = filesToSend[0] if firstFile[:2] != "./": firstFile = "./" + firstFile # Make sure that each file starts with "./" allFiles = [] for f in filesToSend: if f[:2] != "./": allFiles.append("./" + f) else: allFiles.append(f) filesToSend = sorted(allFiles) fContent = {} #print("filesToSend: ",filesToSend) for f in filesToSend: if resetChal: # this time we need to create a cache for the files _srcFile = os.path.join(chalPath, f) _dstFile = os.path.join(srcDir, f) #print("FROM: "+_srcFile+" TO: "+_dstFile) utils.copyWithFullPath(_srcFile, _dstFile) if cacheFiles: # this time we need to create a cache for the files _srcFile = os.path.join(srcDir, f) _dstFile = os.path.join(cacheDir, f) #print("FROM: "+_srcFile+" TO: "+_dstFile) utils.copyWithFullPath(_srcFile, _dstFile) fContent[f] = utils.fileContents(os.path.join(srcDir, f)) jstree = utils.jstreeJSON(filesToSend) r = { "fcontent": fContent, "dirstruct": jstree, "workFile": firstFile } #print("Send Files (r):") #p(r) return r except Exception as e: userName = current_user.name db.addInteraction(userName, chalID, "OOPS", "error loading main challenge file", "", ipAddress) print("ERROR:", str(e)) return "Error loading main challenge file"
def challengeFile(chalID, fileName): userName = current_user.name if chalID in challenges.idToKey: cfg = copy.deepcopy(challenges.getChalConfig(chalID)) else: return genericError if request.method == 'GET': #print("Try allow_get...") try: allowHtml = cfg["allow_get"] except: allowHtml = "" allowHtml = allowHtml.split(",") #print("allow: ",allowHtml) if fileName in allowHtml: chalDir = cfg["directory"] fileName = os.path.join(chalDir, fileName) return send_file(fileName) else: return genericError _postValuesAsDict = request.values.to_dict(flat=False) postValuesAsDict = {} # ugly hack... for k in _postValuesAsDict: newK = "".join("_".join(k.split("[")).split("]")) postValuesAsDict[newK] = _postValuesAsDict[k] postValuesAsDict = utils.processPost(postValuesAsDict) limitFile = int(cfg["limitFile"]) if ("limitFile" in cfg) else 0 db.unlockChallenge(userName, chalID, getClientIPAddress()) if limitFile > 0: n = db.getChalNrTimes(userName, chalID) if (n >= limitFile): return "Limit exceeded" db.incChalNrTimes(userName, chalID, getClientIPAddress()) allowPost = "" try: allowPost = cfg["allow_post"] except: allowPost = "" allowPost = allowPost.split(",") #print("Try allow_post...") if fileName in allowPost: chalDir = cfg["directory"] tplFile = os.path.join(chalDir, fileName) tpl = open(tplFile, "r").read() t = Template(tpl) try: cfg["unlock_codes"] = cfg["unlock_codes"].split(",") except Exception as e: cfg["unlock_codes"] = [] html = t.render({ "post": postValuesAsDict, "cfg": cfg, "chalID": chalID }) #print("Rendered HTML") #print(html) #print("") # if we can find the flag in the HTML code, then the challenge was solved if re.search(cfg["flag"], html): db.addInteraction(userName, chalID, "SOLVE", "", "", getClientIPAddress()) # if we can find this comment in the code, it means that we have failed the challenge if re.search("<!-- FAIL -->", html): db.addInteraction(userName, chalID, "FAIL", "", "", getClientIPAddress()) return html #print("Try unlock_post...") allowPostUnlock = "" try: allowPostUnlock = cfg["unlock_post"].split(",") except: allowPostUnlock = [] try: unlockCodes = cfg["unlock_codes"].split(",") except: unlockCodes = [] if not (len(allowPostUnlock) == len(unlockCodes)): return "Inconsistent length of unlock codes" postUnlock = dict(zip(allowPostUnlock, unlockCodes)) if fileName in allowPostUnlock: chalUnlocks = db.getChallengeUnlockFiles(userName) flagFound = False for u in chalUnlocks: if (u["chalID"] == chalID) and (u["unlockCode"] == postUnlock[fileName]): #print("FOUND") chalDir = cfg["directory"] tplFile = os.path.join(chalDir, fileName) tpl = open(tplFile, "r").read() t = Template(tpl) try: cfg["unlock_codes"] = cfg["unlock_codes"].split(",") except Exception as e: cfg["unlock_codes"] = [] p(postValuesAsDict) html = t.render({ "post": postValuesAsDict, "cfg": cfg, "chalID": chalID }) #print("Rendered HTML") #print(html) #print("") # if we can find the flag in the HTML code, then the challenge was solved if re.search(cfg["flag"], html): db.addInteraction(userName, chalID, "SOLVE", "", "", getClientIPAddress()) # if we can find this comment in the code, it means that we have failed the challenge if re.search("<!-- FAIL -->", html): db.addInteraction(userName, chalID, "FAIL", "", "", getClientIPAddress()) return html return "ERROR: a team of highly trained monkeys was just dispatched to ignore your request" else: return genericError