def scores_submit_special(self, client, code, flag): """ Submits/validates a special flag (external validator) """ if config_get_bool("server", "scores_read_only", False): return -6 db_store = client['db_store'] if not code or (not isinstance(code, str) and not isinstance(code, unicode)): if not code: logging.debug("[team %02d] No code provided" % client['team']) raise AskgodException("No code provided.") else: logging.debug("[team %02d] Invalid code type: %s (%s)" % (client['team'], code, type(code))) raise AskgodException("Invalid type for code.") if isinstance(code, str): code = code.decode('utf-8') if not flag or (not isinstance(flag, str) and not isinstance(flag, unicode)): if not flag: logging.debug("[team %02d] No flag provided" % client['team']) raise AskgodException("No flag provided.") else: logging.debug("[team %02d] Invalid flag type: %s (%s)" % (client['team'], flag, type(flag))) raise AskgodException("Invalid type for flag.") if isinstance(code, str): flag = flag.decode('utf-8') logging.info("[team %02d] Submits special flag for code: %s => %s" % (client['team'], code, flag)) # NOTE: Intentional, "DBFlag.flag == None" != "DBFlag.flag is not None" results = db_store.find(DBFlag, And(DBFlag.code == code, DBFlag.flag == None, DBFlag.validator != None)) if results.count() == 0: logging.debug("[team %02d] Code '%s' doesn't exist." % (client['team'], code)) notify_flag(client['team'], "", 0, "") raise AskgodException("Invalid code.") for entry in results: # Deal with per-team flags if entry.teamid and entry.teamid != client['team']: continue # Deal with counter-limited flags if entry.counter: count = db_store.find(DBScore, flagid=entry.id).count() if count >= entry.counter: logging.debug("[team %02d] Flag '%s' has been exhausted." % (client['team'], code)) raise AskgodException("Too late, the flag has " "been exhausted.") # Check that it wasn't already submitted if db_store.find(DBScore, flagid=entry.id, teamid=client['team']).count() > 0: logging.debug("[team %02d] Flag '%s' was already submitted." % (client['team'], code)) raise AskgodException("The flag has already been submitted.") # Call validator if subprocess.call(["validator/%s" % entry.validator, str(client['team']), str(code), str(flag)]) != 0: continue # Add to score score = DBScore() score.teamid = client['team'] score.flagid = entry.id score.value = entry.value score.submit_time = datetime.datetime.now() db_store.add(score) db_commit(db_store) logging.info("[team %02d] Scores %s points with flagid=%s" % (client['team'], entry.value, entry.id)) notify_flag(client['team'], entry.code, entry.value, entry.tags) retval = [] # Generate response response = {} response['value'] = score.value if entry.return_string: response['return_string'] = entry.return_string if entry.writeup_value: response['writeupid'] = "WID%s" % score.id retval.append(response) # Process triggers retval += process_triggers(client) return retval logging.debug("[team %02d] Flag '%s' exists but won't validate." % (client['team'], flag)) raise AskgodException("Unknown error with your flag, " "please report this.")
def process_triggers(client): db_store = client['db_store'] team = client['team'] retval = [] team_flags = [entry.flagid for entry in db_store.find(DBScore, teamid=team)] for entry in db_store.find(DBTrigger): # We already have that one, moving on if entry.flagid in team_flags: continue # Figure out how many points are needed flags = [] total = 0 for sub_entry in entry.flags: total += sub_entry.value flags.append(sub_entry.id) if entry.count.isdigit(): count = int(entry.count) elif '%' in entry.count: count = (total / 100.0 * int(entry.count.replace('%', ''))) else: logging.error("Invalid 'count' field for trigger: %s" % entry.id) # Check how many points we have team_count = 0 for sub_entry in db_store.find(DBScore, (DBScore.teamid == team) & DBScore.flagid.is_in(flags)): team_count += sub_entry.value if team_count < count: continue # Add to score score = DBScore() score.teamid = team score.flagid = entry.flag.id score.value = entry.flag.value score.submit_time = datetime.datetime.now() db_store.add(score) db_commit(db_store) logging.info("[team %02d] Scores %s points with flagid=%s (trigger)" % (team, entry.flag.value, entry.flag.id)) notify_flag(team, entry.flag.code, entry.flag.value, entry.flag.tags) # Generate response response = {} response['value'] = score.value response['trigger'] = True if entry.flag.return_string: response['return_string'] = entry.flag.return_string if entry.flag.writeup_value: response['writeup_string'] = "WID%s" % score.id retval.append(response) return retval
def scores_submit(self, client, flag): """ Submits/validates a flag """ if config_get_bool("server", "scores_read_only", False): raise AskgodException("Server is read-only.") db_store = client['db_store'] if not flag or (not isinstance(flag, str) and not isinstance(flag, unicode)): if not flag: logging.debug("[team %02d] No flag provided" % client['team']) raise AskgodException("No flag provided.") else: logging.debug("[team %02d] Invalid flag type: %s (%s)" % (client['team'], flag, type(flag))) raise AskgodException("Invalid type for flag.") if isinstance(flag, str): flag = flag.decode('utf-8') logging.info("[team %02d] Submits flag: %s" % (client['team'], flag)) results = db_store.find(DBFlag, DBFlag.flag.lower() == flag.lower()) if results.count() == 0: logging.debug("[team %02d] Flag '%s' doesn't exist." % (client['team'], flag)) notify_flag(client['team'], "", 0, "") raise AskgodException("Flag isn't valid.") for entry in results: # Deal with per-team flags if (entry.teamid is not None and entry.teamid != client['team']): continue # Deal with counter-limited flags if entry.counter: count = db_store.find(DBScore, flagid=entry.id).count() if count >= entry.counter: logging.debug("[team %02d] Flag '%s' has been exhausted." % (client['team'], flag)) raise AskgodException("Too late, the flag has " "been exhausted.") # Check that it wasn't already submitted if db_store.find(DBScore, flagid=entry.id, teamid=client['team']).count() > 0: logging.debug("[team %02d] Flag '%s' was already submitted." % (client['team'], flag)) raise AskgodException("The flag has already been submitted.") # Add to score score = DBScore() score.teamid = client['team'] score.flagid = entry.id score.value = entry.value score.submit_time = datetime.datetime.now() db_store.add(score) db_commit(db_store) logging.info("[team %02d] Scores %s points with flagid=%s" % (client['team'], entry.value, entry.id)) notify_flag(client['team'], entry.code, entry.value, entry.tags) retval = [] # Generate response response = {} response['value'] = score.value if entry.return_string: response['return_string'] = entry.return_string if entry.writeup_value: response['writeup_string'] = "WID%s" % score.id retval.append(response) # Process triggers retval += process_triggers(client) return retval logging.debug("[team %02d] Flag '%s' exists but can't be used." % (client['team'], flag)) raise AskgodException("Unknown error with your flag, " "please report this.")