Exemplo n.º 1
0
    def _createNameFilter(configSection):
        """
        This is a helper for create() to create a filter from the configuration
        section which is type "name".

        :param BoostInfoTree configSection: The section containing the
          definition of the filter.
        :return: A new filter created from the configuration section.
        :rtype: ConfigFilter
        """
        nameUri = configSection.getFirstValue("name")
        if nameUri != None:
            # Get the filter.name.
            name = Name(nameUri)

            # Get the filter.relation.
            relationValue = configSection.getFirstValue("relation")
            if relationValue == None:
                raise ValidatorConfigError("Expected <filter.relation>")

            relation = ConfigNameRelation.getNameRelationFromString(
                relationValue)

            return ConfigRelationNameFilter(name, relation)

        regexString = configSection.getFirstValue("regex")
        if regexString != None:
            try:
                return ConfigRegexNameFilter(regexString)
            except:
                raise ValidatorConfigError("Wrong filter.regex: " +
                                           regexString)

        raise ValidatorConfigError("Wrong filter(name) properties")
Exemplo n.º 2
0
    def _createKeyLocatorChecker(configSection):
        """
        :param BoostInfoTree configSection:
        :rtype: ConfigChecker
        """
        # Get checker.key-locator.type .
        keyLocatorType = configSection.getFirstValue("type")
        if keyLocatorType == None:
            raise ValidatorConfigError("Expected <checker.key-locator.type>")

        if keyLocatorType.lower() == "name":
            return ConfigChecker._createKeyLocatorNameChecker(configSection)
        else:
            raise ValidatorConfigError(
                "Unsupported checker.key-locator.type: " + keyLocatorType)
Exemplo n.º 3
0
    def match(self, isForInterest, packetName):
        """
        Check if the packet name matches the rule's filter. If no filters were
        added, the rule matches everything.

        :param bool isForInterest: True if packetName is for an Interest, False
          if for a Data packet.
        :param Name packetName: The packet name. For a signed interest, the last
          two components are skipped but not removed.
        :return: True if at least one filter matches the packet name, False if
          none of the filters match the packet name.
        :rtype: bool
        :raises: ValidatorConfigError if the supplied isForInterest doesn't
          match the one for which the rule is designed.
        """
        logging.getLogger(__name__).info("Trying to match " +
                                         packetName.toUri())

        if isForInterest != self._isForInterest:
            raise ValidatorConfigError(
                ("Invalid packet type supplied ( " +
                 ("interest" if isForInterest else "data") + " != " +
                 ("interest" if self._isForInterest else "data") + ")"))

        if len(self._filters) == 0:
            return True

        result = False
        for i in range(len(self._filters)):
            result = (result
                      or self._filters[i].match(isForInterest, packetName))
            if result:
                break

        return result
Exemplo n.º 4
0
    def create(configSection):
        """
        Create a rule from configuration section.

        :param BoostInfoTree configSection: The section containing the
          definition of the checker, e.g. one of "validator.rule".
        :return: A new ConfigRule created from the configuration.
        :rtype: ConfigRule
        """
        # Get rule.id .
        ruleId = configSection.getFirstValue("id")
        if ruleId == None:
            raise ValidatorConfigError("Expecting <rule.id>")

        # Get rule.for .
        usage = configSection.getFirstValue("for")
        if usage == None:
            raise ValidatorConfigError("Expecting <rule.for> in rule: " +
                                       ruleId)

        if usage.lower() == "data":
            isForInterest = False
        elif usage.lower() == "interest":
            isForInterest = True
        else:
            raise ValidatorConfigError("Unrecognized <rule.for>: " + usage +
                                       " in rule: " + ruleId)

        rule = ConfigRule(ruleId, isForInterest)

        # Get rule.filter(s)
        filterList = configSection["filter"]
        for i in range(len(filterList)):
            rule.addFilter(ConfigFilter.create(filterList[i]))

        # Get rule.checker(s)
        checkerList = configSection["checker"]
        for i in range(len(checkerList)):
            rule.addChecker(ConfigChecker.create(checkerList[i]))

        # Check other stuff.
        if len(checkerList) == 0:
            raise ValidatorConfigError(
                "No <rule.checker> is specified in rule: " + ruleId)

        return rule
Exemplo n.º 5
0
    def create(configSection):
        """
        Create a filter from the configuration section.

        :param BoostInfoTree configSection: The section containing the
          definition of the filter, e.g. one of "validator.rule.filter".
        :return: A new filter created from the configuration section.
        :rtype: ConfigFilter
        """
        filterType = configSection.getFirstValue("type")
        if filterType == None:
            raise ValidatorConfigError("Expected <filter.type>")

        if filterType.lower() == "name":
            return ConfigFilter._createNameFilter(configSection)
        else:
            raise ValidatorConfigError("Unsupported filter.type: " +
                                       filterType)
Exemplo n.º 6
0
    def create(configSection):
        """
        Create a checker from the configuration section.

        :param BoostInfoTree configSection: The section containing the
          definition of the checker, e.g. one of "validation.rule.checker".
        :return: A new checker created from the configuration section.
        :rtype: ConfigChecker
        """
        # Get checker.type.
        checkerType = configSection.getFirstValue("type")
        if checkerType == None:
            raise ValidatorConfigError("Expected <checker.type>")

        if checkerType.lower() == "customized":
            return ConfigChecker._createCustomizedChecker(configSection)
        elif checkerType.lower() == "hierarchical":
            return ConfigChecker._createHierarchicalChecker(configSection)
        else:
            raise ValidatorConfigError("Unsupported checker type: " +
                                       checkerType)
Exemplo n.º 7
0
    def _createCustomizedChecker(configSection):
        """
        :param BoostInfoTree configSection:
        :rtype: ConfigChecker
        """
        # Ignore sig-type.
        # Get checker.key-locator .
        keyLocatorSection = configSection["key-locator"]
        if len(keyLocatorSection) != 1:
            raise ValidatorConfigError("Expected one <checker.key-locator>")

        return ConfigChecker._createKeyLocatorChecker(keyLocatorSection[0])
Exemplo n.º 8
0
    def _processConfigTrustAnchor(self, configSection, inputName):
        """
        Process the trust-anchor configuration section and call
        validator_.loadAnchor as needed.

        :param BoostInfoTree configSection: The section containing the
          definition of the trust anchor, e.g. one of "validator.trust-anchor".
        :param str inputName: Used for log messages, etc.
        """
        anchorType = configSection.getFirstValue("type")
        if anchorType == None:
            raise ValidatorConfigError("Expected <trust-anchor.type>")

        if anchorType.lower() == "file":
            # Get trust-anchor.file .
            fileName = configSection.getFirstValue("file-name")
            if fileName == None:
                raise ValidatorConfigError("Expected <trust-anchor.file-name>")

            refreshPeriod = ValidationPolicyConfig._getRefreshPeriod(
                configSection)
            self._validator.loadAnchor(fileName, fileName, refreshPeriod,
                                       False)

            return
        elif anchorType.lower() == "base64":
            # Get trust-anchor.base64-string .
            base64String = configSection.getFirstValue("base64-string")
            if base64String == None:
                raise ValidatorConfigError(
                    "Expected <trust-anchor.base64-string>")

            encoding = b64decode(base64String)
            certificate = CertificateV2()
            try:
                certificate.wireDecode(Blob(encoding, False))
            except Exception as ex:
                raise ValidatorConfigError(
                    "Cannot decode certificate from base64-string: " +
                    repr(ex))

            self._validator.loadAnchor("", certificate)
            return
        elif anchorType.lower() == "dir":
            # Get trust-anchor.dir .
            dirString = configSection.getFirstValue("dir")
            if dirString == None:
                raise ValidatorConfigError("Expected <trust-anchor.dir>")

            refreshPeriod = ValidationPolicyConfig._getRefreshPeriod(
                configSection)
            self._validator.loadAnchor(dirString, dirString, refreshPeriod,
                                       True)

            return
        elif anchorType.lower() == "any":
            self._shouldBypass = True
        else:
            raise ValidatorConfigError("Unsupported trust-anchor.type")
Exemplo n.º 9
0
    def getNameRelationFromString(relationString):
        """
        Convert relationString to a Relation enum.

        :param str relationString: the string to convert.
        :return: The value for the ConfigNameRelation.Relation enum.
        :rtype: int
        :raises: ValidatorConfigError if relationString cannot be converted.
        """
        if relationString.lower() == "equal":
            return ConfigNameRelation.Relation.EQUAL
        elif relationString.lower() == "is-prefix-of":
            return ConfigNameRelation.Relation.IS_PREFIX_OF
        elif relationString.lower() == "is-strict-prefix-of":
            return ConfigNameRelation.Relation.IS_STRICT_PREFIX_OF
        else:
            raise ValidatorConfigError("Unsupported relation: " +
                                       relationString)
Exemplo n.º 10
0
    def check(self, isForInterest, packetName, keyLocatorName, state):
        """
        Check if the packet satisfies the rule's condition.

        :param bool isForInterest: True if packetName is for an Interest, False
          if for a Data packet.
        :param Name packetName: The packet name. For a signed interest, the last
          two components are skipped but not removed.
        :param Name keyLocatorName: The KeyLocator's name.
        :param ValidationState state: This calls state.fail() if the packet is
          invalid.
        :return: True if further signature verification is needed, or False if
          the packet is immediately determined to be invalid in which case this
          calls state.fail() with the proper code and message.
        :rtype: bool
        :raises: ValidatorConfigError if the supplied isForInterest doesn't
          match the one for which the rule is designed.
        """
        logging.getLogger(__name__).info("Trying to check " +
                                         packetName.toUri() +
                                         " with keyLocator " +
                                         keyLocatorName.toUri())

        if isForInterest != self._isForInterest:
            raise ValidatorConfigError(
                "Invalid packet type supplied ( " +
                ("interest" if isForInterest else "data") + " != " +
                ("interest" if self._isForInterest else "data") + ")")

        hasPendingResult = False
        for i in range(len(self._checkers)):
            result = self._checkers[i].check(isForInterest, packetName,
                                             keyLocatorName, state)
            if not result:
                return result
            hasPendingResult = True

        return hasPendingResult
Exemplo n.º 11
0
    def load(self, filePathOrInputOrConfigSection, inputName=None):
        """
        There are three forms of load:
        load(filePath) - Load the configuration from the given config file.
        load(input, inputName) - Load the configuration from the given input
        string.
        load(configSection, inputName) - Load the configuration from the given
        configSection.
        Each of these forms of load replaces any existing configuration.

        :param str filePath: The The path of the config file.
        :param str input: The contents of the configuration rules, with lines
          separated by NL or CR/NL.
        :param BoostInfoTree configSection: The configuration section loaded
          from the config file. It should have one "validator" section.
        :param str inputName: Used for log messages, etc.
        """
        if type(filePathOrInputOrConfigSection) is str and inputName == None:
            filePath = filePathOrInputOrConfigSection

            parser = BoostInfoParser()
            parser.read(filePath)
            self.load(parser.getRoot(), filePath)
        elif (type(filePathOrInputOrConfigSection) is str
              and type(inputName) is str):
            input = filePathOrInputOrConfigSection

            parser = BoostInfoParser()
            parser.read(input, inputName)
            self.load(parser.getRoot(), inputName)
        else:
            configSection = filePathOrInputOrConfigSection

            if self._isConfigured:
                # Reset the previous configuration.
                self._shouldBypass = False
                self._dataRules = []
                self._interestRules = []

                self._validator.resetAnchors()
                self._validator.resetVerifiedCertificates()

            self._isConfigured = True

            validatorList = configSection["validator"]
            if len(validatorList) != 1:
                raise ValidatorConfigError(
                    "ValidationPolicyConfig: Expected one validator section")
            validatorSection = validatorList[0]

            # Get the rules.
            ruleList = validatorSection["rule"]
            for i in range(len(ruleList)):
                rule = ConfigRule.create(ruleList[i])
                if rule.getIsForInterest():
                    self._interestRules.append(rule)
                else:
                    self._dataRules.append(rule)

            # Get the trust anchors.
            trustAnchorList = validatorSection["trust-anchor"]
            for i in range(len(trustAnchorList)):
                self._processConfigTrustAnchor(trustAnchorList[i], inputName)
Exemplo n.º 12
0
    def checkPolicy(self, dataOrInterest, state, continueValidation):
        """
        :param dataOrInterest:
        :type dataOrInterest: Data or Interest
        :param ValidationState state:
        :param continueValidation:
        :type continueValidation: function object
        """
        if self.hasInnerPolicy():
            raise ValidatorConfigError(
                "ValidationPolicyConfig must be a terminal inner policy")

        if self._shouldBypass:
            continueValidation(None, state)
            return

        keyLocatorName = ValidationPolicy.getKeyLocatorName(
            dataOrInterest, state)
        if state.isOutcomeFailed():
            # Already called state.fail() .
            return

        if isinstance(dataOrInterest, Data):
            data = dataOrInterest

            for i in range(len(self._dataRules)):
                rule = self._dataRules[i]

                if rule.match(False, data.getName()):
                    if rule.check(False, data.getName(), keyLocatorName,
                                  state):
                        continueValidation(
                            CertificateRequest(Interest(keyLocatorName)),
                            state)
                        return
                    else:
                        # rule.check failed and already called state.fail() .
                        return

            state.fail(
                ValidationError(
                    ValidationError.POLICY_ERROR,
                    "No rule matched for data `" + data.getName().toUri() +
                    "`"))
        else:
            interest = dataOrInterest

            for i in range(len(self._interestRules)):
                rule = self._interestRules[i]

                if rule.match(True, interest.getName()):
                    if rule.check(True, interest.getName(), keyLocatorName,
                                  state):
                        continueValidation(
                            CertificateRequest(Interest(keyLocatorName)),
                            state)
                        return
                    else:
                        # rule.check failed and already called state.fail() .
                        return

            state.fail(
                ValidationError(
                    ValidationError.POLICY_ERROR,
                    "No rule matched for interest `" +
                    interest.getName().toUri() + "`"))
Exemplo n.º 13
0
    def _createKeyLocatorNameChecker(configSection):
        """
        :param BoostInfoTree configSection:
        :rtype: ConfigChecker
        """
        nameUri = configSection.getFirstValue("name")
        if nameUri != None:
            name = Name(nameUri)

            relationValue = configSection.getFirstValue("relation")
            if relationValue == None:
                raise ValidatorConfigError(
                    "Expected <checker.key-locator.relation>")

            relation = ConfigNameRelation.getNameRelationFromString(
                relationValue)
            return ConfigNameRelationChecker(name, relation)

        regexString = configSection.getFirstValue("regex")
        if regexString != None:
            try:
                return ConfigRegexChecker(regexString)
            except:
                raise ValidatorConfigError(
                    "Invalid checker.key-locator.regex: " + regexString)

        hyperRelationList = configSection["hyper-relation"]
        if len(hyperRelationList) == 1:
            hyperRelation = hyperRelationList[0]

            # Get k-regex.
            keyRegex = hyperRelation.getFirstValue("k-regex")
            if keyRegex == None:
                raise ValidatorConfigError(
                    "Expected <checker.key-locator.hyper-relation.k-regex>")

            # Get k-expand.
            keyExpansion = hyperRelation.getFirstValue("k-expand")
            if keyExpansion == None:
                raise ValidatorConfigError(
                    "Expected <checker.key-locator.hyper-relation.k-expand")

            # Get h-relation.
            hyperRelationString = hyperRelation.getFirstValue("h-relation")
            if hyperRelationString == None:
                raise ValidatorConfigError(
                    "Expected <checker.key-locator.hyper-relation.h-relation>")

            # Get p-regex.
            packetNameRegex = hyperRelation.getFirstValue("p-regex")
            if packetNameRegex == None:
                raise ValidatorConfigError(
                    "Expected <checker.key-locator.hyper-relation.p-regex>")

            # Get p-expand.
            packetNameExpansion = hyperRelation.getFirstValue("p-expand")
            if packetNameExpansion == None:
                raise ValidatorConfigError(
                    "Expected <checker.key-locator.hyper-relation.p-expand>")

            relation = ConfigNameRelation.getNameRelationFromString(
                hyperRelationString)

            try:
                return ConfigHyperRelationChecker(packetNameRegex,
                                                  packetNameExpansion,
                                                  keyRegex, keyExpansion,
                                                  relation)
            except:
                raise ValidatorConfigError(
                    "Invalid regex for key-locator.hyper-relation")

        raise ValidatorConfigError("Unsupported checker.key-locator")