示例#1
0
 def config_variables(self, client):
     config = {}
     config['scores_hide_others'] = config_get_bool("server",
                                                    "scores_hide_others",
                                                    False)
     config['scores_progress_overall'] = config_get_bool(
         "server", "scores_progress_overall", False)
     config['scores_read_only'] = config_get_bool("server",
                                                  "scores_read_only", False)
     config['scores_writeups'] = config_get_bool("server",
                                                 "scores_writeups", False)
     config['teams_setdetails'] = config_get_bool("server",
                                                  "teams_setdetails", False)
     return config
示例#2
0
    def scores_scoreboard(self, client):
        """ Returns the scoreboard """
        db_store = client['db_store']

        hide_others = config_get_bool("server", "scores_hide_others", False)

        teams = {}
        for team in db_store.find(DBTeam):
            # Skip teams without a name (likely unconfigured)
            if not team.name:
                continue

            if team.id == 0 and client.get("team", None) != 0:
                continue

            teams[team.id] = {'teamid': team.id,
                              'team_name': (team.name
                                            if team.name else ""),
                              'team_country': (team.country
                                               if team.country else ""),
                              'team_website': (team.website
                                               if team.website else ""),
                              'score': 0,
                              'score_flags': 0,
                              'score_writeups': 0}

        # The public scoreboard only shows 0 when hide_others is set
        if hide_others and 'team' not in client:
            return sorted(teams.values(), key=lambda team: team['teamid'])

        for score in db_store.find(DBScore):
            # Skip score entries without a matching team
            if not score.teamid in teams:
                continue

            # Skip teams other than the requestor when hide_others is set
            if hide_others and score.teamid != client['team'] \
                    and client['team'] != 0:
                continue

            if score.value:
                teams[score.teamid]['score'] += score.value
                teams[score.teamid]['score_flags'] += score.value
            if (config_get_bool("server", "scores_writeups", False)
                    and score.writeup_value):
                teams[score.teamid]['score'] += score.writeup_value
                teams[score.teamid]['score_writeups'] += score.writeup_value

        return sorted(teams.values(), key=lambda team: team['score'],
                      reverse=True)
示例#3
0
    def scores_timeline(self, client):
        """ Returns the timeline """
        db_store = client['db_store']

        hide_others = config_get_bool("server", "scores_hide_others", False)

        result = []

        # Guests don't get to see anything when hide_others is set
        if hide_others and "team" not in client:
            return result

        for score in db_store.find(DBScore).order_by(DBScore.submit_time):
            if not score.team.name:
                continue

            if score.team.id == 0 and client.get("team", None) != 0:
                continue

            # Skip teams other than the requestor when hide_others is set
            if hide_others and score.teamid != client['team'] \
                    and client['team'] != 0:
                continue

            result.append({'teamid': score.teamid,
                           'submit_time': score.submit_time,
                           'value': score.value})

        return sorted(result, key=itemgetter('teamid', 'submit_time'))
示例#4
0
    def scores_list_submitted(self, client):
        """ Lists all the flags the team found and any related hints """
        db_store = client['db_store']

        results = []

        for entry in db_store.find(DBScore, teamid=client['team']):
            result = {}
            result['flagid'] = entry.flagid
            result['description'] = (entry.flag.description
                                     if entry.flag.description else "")
            result['value'] = entry.value
            result['submit_time'] = entry.submit_time
            if config_get_bool("server", "scores_writeups", False):
                result['writeup_value'] = entry.writeup_value
            else:
                result['writeup_value'] = 0
            result['writeup_submit_time'] = entry.writeup_time
            if entry.flag.writeup_value:
                result['writeup_string'] = "WID%s" % entry.id
            else:
                result['writeup_string'] = ""
            result['return_string'] = (entry.flag.return_string
                                       if entry.flag.return_string else "")
            results.append(result)

        return sorted(results, key=lambda result: result['flagid'])
示例#5
0
    def teams_setdetails(self, client, fields):
        """ Set the details for the caller's team """

        if not config_get_bool("server", "teams_setdetails", False):
            raise AskgodException("Setting team details isn't allowed.")

        db_store = client['db_store']

        convert_properties(fields)
        validate_properties(DBTeam, fields)

        results = db_store.find(DBTeam, id=client['team'])
        if results.count() != 1:
            raise AskgodException("Can't find a match for id=%s"
                                  % client['team'])

        dbentry = results[0]

        if set(fields.keys()) - set(['name', 'country', 'website']):
            raise AskgodException("Invalid field provided.")

        if "country" in fields:
            if len(fields['country']) != 2 or not fields['country'].isalpha():
                raise AskgodException("Invalid country ISO code.")
            fields['country'] = fields['country'].upper()

        for key, value in fields.items():
            if not value:
                continue

            if getattr(dbentry, key):
                raise AskgodException("Field is already set: %s" % key)

            setattr(dbentry, key, value)

        return db_commit(db_store)
示例#6
0
    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.")
示例#7
0
    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.")
示例#8
0
    def scores_progress(self, client, tags=None):
        """ Returns the progress percentage """
        db_store = client['db_store']

        if not tags:
            # Overall progress
            if not config_get_bool("server", "scores_progress_overall", False):
                raise AskgodException("Overall progress is disabled.")

            total = 0.0
            obtained = 0.0
            for entry in db_store.find(DBFlag):
                if entry.teamid and entry.teamid != client['team']:
                    continue

                total += entry.value

            for entry in db_store.find(DBScore, teamid=client['team']):
                obtained += entry.value

            return int(obtained / total * 100)

        ret = {}
        if not isinstance(tags, list):
            ret = 0.0
            tags = [tags]

        for tag in tags:
            namespace = tag.split(":")[0]
            if namespace not in config_get_list("server",
                                                "scores_progress_tags",
                                                []):
                raise AskgodException("Disallowed tag namespaced.")

            total = 0.0
            obtained = 0.0

            for entry in db_store.find(DBFlag):
                if entry.teamid and entry.teamid != client['team']:
                    continue
                entry_tags = entry.tags.split(",")

                if tag in entry_tags:
                    total += entry.value

            for entry in db_store.find(DBScore, teamid=client['team']):
                entry_tags = entry.flag.tags.split(",")
                if tag in entry_tags:
                    obtained += entry.value

            if isinstance(ret, dict):
                if not total:
                    ret[tag] = 0
                    continue
                ret[tag] = int(obtained / total * 100)
            else:
                if not total:
                    return 0
                return int(obtained / total * 100)

        return ret