Esempio n. 1
0
    def parse(self, sourceExpressionString):
        """Parses the given 'sourceExpressionString' according to the parameters set in this object. Returns the
        appropriate type of SourceExpression, or SourceExpression.INVALID() in case of a parsing error."""
        sourceExpressionString = sourceExpressionString.strip()

        if sourceExpressionString.lower() == "'unsafe-eval'":
            return SourceExpression.UNSAFE_EVAL()
        elif sourceExpressionString.lower() == "'unsafe-inline'":
            return SourceExpression.UNSAFE_INLINE()
        elif sourceExpressionString.lower() == "'self'":
            return SelfSourceExpression.SELF()
        elif sourceExpressionString == "*":
            return URISourceExpression(None, "*", None, None)

        sourceExpressionParsedAsURI = self._parser.parse(
            sourceExpressionString)
        if sourceExpressionParsedAsURI == URI.EMPTY(
        ) or sourceExpressionParsedAsURI == URI.INVALID():
            return SourceExpression.INVALID()
        if sourceExpressionParsedAsURI.getScheme(
        ) is not None and sourceExpressionParsedAsURI.getScheme().lower(
        ) not in self._knownSchemes:
            return SourceExpression.INVALID()

        port = sourceExpressionParsedAsURI.getPort()
        if port not in ('*', None):  # convert port if it should be a number
            port = int(sourceExpressionParsedAsURI.getPort())
        return URISourceExpression(sourceExpressionParsedAsURI.getScheme(),
                                   sourceExpressionParsedAsURI.getHost(), port,
                                   sourceExpressionParsedAsURI.getPath())
Esempio n. 2
0
    def parseJsonDict(self, jsonReport):
        """
        Parses the given 'jsonReport' according to the parameters set in the constructor of this ReportParser 
        and returns a Report object. 'jsonReport' is expected to be a Python dict object with attribute names
        and values corresponding to the definition of CSP violation reports. If 'jsonReport' cannot be parsed 
        because it is syntactically invalid (or empty), Report.INVALID() will be returned.

        Depending on the configuration of this ReportParser object, some attributes will be parsed to replace their
        plain string values with a more high-level object representation.
        """
        
        # replace names
        renamedReport = dict(map(lambda (key, val): (self._replaceName(key), val), jsonReport.iteritems()))
                
        # convert data in report
        convertedReport = {}
        deferredSelfURIs = set([]) # all key names that have URIs that are exactly 'self' (handle after parsing everything else)
        for (key, value) in renamedReport.iteritems():
            if key in self._uriKeys:
                if value.lower().strip() == "self":
                    deferredSelfURIs.add(key)
                    continue
                else:
                    value = self._uriParser.parse(value)
            elif key in self._directiveKeys:
                value = self._directiveParser.parse(value)
            elif key in self._policyKeys:
                value = self._policyParser.parse(value)
            
            if value in (URI.INVALID(), Directive.INVALID(), Policy.INVALID()):
                if self._strict:
                    return Report.INVALID()
                else:
                    continue
            convertedReport[key] = value
            
        # handle deferred parsing of 'self' URIs (they represent the document-uri)
        for key in deferredSelfURIs:
            if "document-uri" in self._uriKeys and "document-uri" in convertedReport:
                convertedReport[key] = convertedReport["document-uri"]
            elif self._strict:
                return Report.INVALID()
            
        for requiredKey in self._requiredKeys:
            if not requiredKey in convertedReport:
                return Report.INVALID()
        return Report(convertedReport)
Esempio n. 3
0
    def generateDirective(self, reportType, blockedURI):
        """
        Generates a new Directive that allows exactly the kind of event that caused the CSP violation report,
        assuming this Directive ('self') was the 'violated-directive' in a report of the given 'reportType' 
        (permitted values are 'regular', 'eval', and 'inline'), and 'blockedURI' was the value of the report 
        field 'blocked-uri'.
        
        This directive may not be of the type 'default-src'. The result of this method is a Directive. It is 
        Directive.INVALID() if (1) the type of this Directive is 'default-src' (or it is Directive.INVALID()), 
        or a special type incompatible with 'reportType', (2) if 'reportType' is none out of 'regular', 
        'inline' or 'eval', (3) the 'blocked-uri' is URI.INVALID() or not a regular URI in the 
        'reportType'=='regular' case [old], or a regular URI in the 'eval' or 'inline' cases[/old].
        
        This implementation does not handle URIs in any special way. That is, it does
        not add or remove ports, path/query components, or replace them with the 'self' keyword.
        """
        if (self == Directive.INVALID()
                or (self == Directive.EVAL_SCRIPT_BASE_RESTRICTION()
                    and reportType != 'eval')
                or (self == Directive.INLINE_SCRIPT_BASE_RESTRICTION()
                    and reportType != 'inline')
                or (self == Directive.INLINE_STYLE_BASE_RESTRICTION()
                    and reportType != 'inline')
                or self.getType() == "default-src"
                or reportType not in ('regular', 'eval', 'inline')
                or blockedURI == URI.INVALID()
                or (reportType == 'regular' and not blockedURI.isRegularURI())
                #             or (reportType in ('eval', 'inline') and blockedURI.isRegularURI())
                or (reportType == 'eval' and self.getType() != 'script-src') or
            (reportType == 'inline'
             and self.getType() not in ('script-src', 'style-src'))):
            return Directive.INVALID()

        generated = Directive.INVALID()
        if reportType == 'regular':
            generated = Directive(self.getType(), (URISourceExpression(
                blockedURI.getScheme(), blockedURI.getHost(),
                blockedURI.getPort(), blockedURI.getPath()), ))
        elif reportType == 'eval':
            generated = Directive(self.getType(),
                                  (SourceExpression.UNSAFE_EVAL(), ))
        elif reportType == 'inline':
            generated = Directive(self.getType(),
                                  (SourceExpression.UNSAFE_INLINE(), ))
        return generated