Exemplo n.º 1
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.")
Exemplo n.º 2
0
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
Exemplo n.º 3
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.")