Exemplo n.º 1
0
    def __init__(self, identityStorage, configFilename=None):
        """
        :param pyndn.IdentityStorage: A class that stores signing identities and certificates.
        :param str configFilename: A configuration file specifying validation rules and network
            name settings.
        """

        # use the default configuration where possible
        # TODO: use environment variable for this, fall back to default
        path = os.path.dirname(__file__)
        templateFilename = os.path.join(path, '.default.conf')
        self._configTemplate = BoostInfoParser()
        self._configTemplate.read(templateFilename)

        if configFilename is None:
            configFilename = templateFilename

        certificateCache = CertificateCache()
        super(IotPolicyManager, self).__init__(configFilename,
                                               certificateCache)
        self._identityStorage = identityStorage

        self.setEnvironmentPrefix(None)
        self.setTrustRootIdentity(None)
        self.setDeviceIdentity(None)
Exemplo n.º 2
0
    def reset(self):
        """
        Reset the certificate cache and other fields to the constructor state.
        """
        self._certificateCache.reset()

        # stores the fixed-signer certificate name associated with validation rules
        # so we don't keep loading from files
        self._fixedCertificateCache = {}

        # stores the timestamps for each public key used in command interests to avoid
        # replay attacks
        # key is public key name, value is last timestamp
        self._keyTimestamps = {}

        self.requiresVerification = True

        self.config = BoostInfoParser()
        self._refreshManager = TrustAnchorRefreshManager()
Exemplo n.º 3
0
    def loadApplications(self, directory=None, override=False):
        if not directory:
            directory = self._applicationDirectory
        if override:
            self._applications.clear()
        if os.path.exists(directory):
            for f in os.listdir(directory):
                fullFileName = os.path.join(directory, f)
                if os.path.isfile(fullFileName) and f.endswith('.conf'):
                    appName = f.rstrip('.conf')
                    if appName in self._applications and not override:
                        print(
                            "loadApplications: " + appName +
                            " already exists, do nothing for configuration file: "
                            + fullFileName)
                    else:
                        self._applications[appName] = {
                            "tree": BoostInfoParser(),
                            "dataPrefix": [],
                            "version": int(time.time())
                        }
                        self._applications[appName]["tree"].read(fullFileName)
                        data = Data(
                            Name(self.prefix).append(appName).append(
                                "_schema").appendVersion(
                                    self._applications[appName]["version"]))
                        data.setContent(
                            str(self._applications[appName]["tree"].getRoot()))
                        self.signData(data)
                        self._memoryContentCache.add(data)
                        try:
                            validatorTree = self._applications[appName][
                                "tree"]["validator"][0]
                            for rule in validatorTree["rule"]:
                                self._applications[appName][
                                    "dataPrefix"].append(rule["id"][0].value)
                        # TODO: don't swallow any general exceptions, we want to catch only KeyError (make sure) here
                        except Exception as e:
                            print(
                                "loadApplications parse configuration file " +
                                fullFileName + " : " + str(e))

        return
Exemplo n.º 4
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.º 5
0
        self.log.debug(msg)


if __name__ == '__main__':
    import sys
    import os
    # todo - should I enforce the suffix 'gateway'?
    nArgs = len(sys.argv) - 1
    if nArgs < 2:
        from pyndn.util.boost_info_parser import BoostInfoParser
        fileName = '/usr/local/etc/ndn/iot_controller.conf'
        if nArgs == 1:
            fileName = sys.argv[1]
    
        try:
            config = BoostInfoParser()
            config.read(fileName)
        except IOError:
            print('Could not read {}, exiting...'.format(fileName))
            sys.exit(1)
        else:
            deviceName = config["device/controllerName"][0].value
            networkName = config["device/environmentPrefix"][0].value
    elif nArgs == 2:
        networkName = sys.argv[1]
        deviceName = sys.argv[2]
    else:
        print('Usage: {} [network-name controller-name]'.format(sys.argv[0]))
        sys.exit(1)

    try:
Exemplo n.º 6
0
    def updateTrustSchema(self,
                          appName,
                          certName,
                          dataPrefix,
                          publishNew=False):
        if appName in self._applications:
            if dataPrefix.toUri() in self._applications[appName]["dataPrefix"]:
                print("some key is configured for namespace " +
                      dataPrefix.toUri() + " for application " + appName +
                      ". Ignoring this request.")
                return False
            else:
                # TODO: Handle malformed conf where validator tree does not exist
                validatorNode = self._applications[appName]["tree"][
                    "validator"][0]
        else:
            # This application does not previously exist, we create its trust schema
            # (and for now, add in static rules for sync data)

            self._applications[appName] = {
                "tree": BoostInfoParser(),
                "dataPrefix": [],
                "version": 0
            }
            validatorNode = self._applications[appName]["tree"].getRoot(
            ).createSubtree("validator")

            trustAnchorNode = validatorNode.createSubtree("trust-anchor")
            #trustAnchorNode.createSubtree("type", "file")
            #trustAnchorNode.createSubtree("file-name", os.path.expanduser("~/.ndn/iot/root.cert"))
            trustAnchorNode.createSubtree("type", "base64")
            trustAnchorNode.createSubtree(
                "base64-string",
                Blob(b64encode(self._rootCertificate.wireEncode().toBytes()),
                     False).toRawStr())

            #create cert verification rule
            # TODO: the idea for this would be, if the cert has /home-prefix/<one-component>/KEY/ksk-*/ID-CERT, then it should be signed by fixed controller(s)
            # if the cert has /home-prefix/<multiple-components>/KEY/ksk-*/ID-CERT, then it should be checked hierarchically (this is for subdomain support)
            certRuleNode = validatorNode.createSubtree("rule")
            certRuleNode.createSubtree("id", "Certs")
            certRuleNode.createSubtree("for", "data")

            filterNode = certRuleNode.createSubtree("filter")
            filterNode.createSubtree("type", "regex")
            filterNode.createSubtree("regex", "^[^<KEY>]*<KEY><>*<ID-CERT>")

            checkerNode = certRuleNode.createSubtree("checker")
            # TODO: wait how did my first hierarchical verifier work?
            #checkerNode.createSubtree("type", "hierarchical")

            checkerNode.createSubtree("type", "customized")
            checkerNode.createSubtree("sig-type", "rsa-sha256")

            keyLocatorNode = checkerNode.createSubtree("key-locator")
            keyLocatorNode.createSubtree("type", "name")
            # We don't put cert version in there
            keyLocatorNode.createSubtree(
                "name",
                Name(self.getDefaultCertificateName()).getPrefix(-1).toUri())
            keyLocatorNode.createSubtree("relation", "equal")

            # Discovery rule: anything that multicasts under my home prefix should be signed, and the signer should have been authorized by root
            # TODO: This rule as of right now is over-general
            discoveryRuleNode = validatorNode.createSubtree("rule")
            discoveryRuleNode.createSubtree("id", "sync-data")
            discoveryRuleNode.createSubtree("for", "data")

            filterNode = discoveryRuleNode.createSubtree("filter")
            filterNode.createSubtree("type", "regex")
            filterNode.createSubtree("regex", "^[^<MULTICAST>]*<MULTICAST><>*")

            checkerNode = discoveryRuleNode.createSubtree("checker")
            # TODO: wait how did my first hierarchical verifier work?
            #checkerNode.createSubtree("type", "hierarchical")

            checkerNode.createSubtree("type", "customized")
            checkerNode.createSubtree("sig-type", "rsa-sha256")

            keyLocatorNode = checkerNode.createSubtree("key-locator")
            keyLocatorNode.createSubtree("type", "name")
            keyLocatorNode.createSubtree("regex",
                                         "^[^<KEY>]*<KEY><>*<ID-CERT>")

        ruleNode = validatorNode.createSubtree("rule")
        ruleNode.createSubtree("id", dataPrefix.toUri())
        ruleNode.createSubtree("for", "data")

        filterNode = ruleNode.createSubtree("filter")
        filterNode.createSubtree("type", "name")
        filterNode.createSubtree("name", dataPrefix.toUri())
        filterNode.createSubtree("relation", "is-prefix-of")

        checkerNode = ruleNode.createSubtree("checker")
        checkerNode.createSubtree("type", "customized")
        checkerNode.createSubtree("sig-type", "rsa-sha256")

        keyLocatorNode = checkerNode.createSubtree("key-locator")
        keyLocatorNode.createSubtree("type", "name")
        # We don't put cert version in there
        keyLocatorNode.createSubtree("name", certName.getPrefix(-1).toUri())
        keyLocatorNode.createSubtree("relation", "equal")

        if not os.path.exists(self._applicationDirectory):
            os.makedirs(self._applicationDirectory)
        self._applications[appName]["tree"].write(
            os.path.join(self._applicationDirectory, appName + ".conf"))
        self._applications[appName]["dataPrefix"].append(dataPrefix.toUri())
        self._applications[appName]["version"] = int(time.time())
        if publishNew:
            # TODO: ideally, this is the trust schema of the application, and does not necessarily carry controller prefix.
            # We make it carry controller prefix here so that prefix registration / route setup is easier (implementation workaround)
            data = Data(
                Name(self.prefix).append(appName).append(
                    "_schema").appendVersion(
                        self._applications[appName]["version"]))
            data.setContent(str(self._applications[appName]["tree"].getRoot()))
            self.signData(data)
            self._memoryContentCache.add(data)
        return True