Esempio n. 1
0
def try_parse_and_handle_directive(ctx):
    from directive_impl import same_as_file
    from directive_impl import file_same_as_stdout

    try:
        line = ctx.doc_file.next_non_empty_line()
    except RuntimeError as e:
        # Do not raise exception when next non-empty line
        # does not exist. Instead, return failure.
        if str(e) != "Enf of file.":
            raise
        return failure()

    # Register all directives.
    all_directives: List[Directive] = [
        Directive(same_as_file.ext_to_patterns, [generic_config_parser, same_as_file.parse], same_as_file.handle),
        Directive(file_same_as_stdout.ext_to_patterns, [generic_config_parser], file_same_as_stdout.handle),
    ]

    for directive in all_directives:
        directive_config = []
        if succeeded(directive.try_parse_directive(line, ctx.doc_file_ext(), directive_config)):
            directive.handle(directive_config.pop(), ctx)
            return success(directive_config)

    return failure()
Esempio n. 2
0
    def parse(self, stringPolicy):
        """
        Parses the given 'stringPolicy' according to the parameters set in the constructor of this PolicyParser 
        and returns a Policy object. If 'stringPolicy' cannot be parsed because it is syntactically invalid (or empty),
        Policy.INVALID() will be returned. (A policy cannot consist of only whitespace.)

        Depending on the configuration of this PolicyParser object, may perform internal translation of the type 
        and filter certain directive types.
        """
        directiveStrings = stringPolicy.split(";")
        directives = {}  # type -> Directive
        for directiveString in directiveStrings:
            if self._isIgnoredDirectiveType(directiveString):
                continue
            directive = self._directiveParser.parse(directiveString)
            if directive == Directive.INVALID():
                if self._strict:
                    return Policy.INVALID()
                else:
                    continue
            if directive.getType() in directives:
                continue  # could emit a warning here; the standard says to ignore subsequent definitions
            directives[directive.getType()] = directive
        if self._expandDefaultSrc:
            self._normaliseDirectivesMap(directives)
        if len(directives) == 0:
            return Policy.INVALID()
        return Policy(directives.values())
Esempio n. 3
0
def run_parser(body):
    child = Node()
    child.name = command.Run
    items = body.split("&&")
    directive = Directive()
    for item in items:
        item = item.strip()
        install_flag = False
        for prefix in thesaurus.INSTALL_PREFIX.keys():
            item = purify_code(item)
            match = re.search(prefix, item)
            if match:  # 说明这一行安装了软件
                tmp = re.sub(prefix, constants.SEP, item).strip()
                if not tmp.startswith(constants.SEP):
                    break
                item = re.sub(prefix, '', item).strip()
                install_flag = True
                install_list = item.split(" ")
                for install in install_list:
                    install_pattern = re.compile("^\w.*$")
                    if install_pattern.match(install):
                        install = purify_install(install)
                        if len(install.strip()) == 0:
                            continue
                        directive.add_install(install)
                    # else:
                    #     print >> sys.stderr, "invalid format: %s" % install
                break
        if not install_flag:
            directive.add_directive(item)
    child.directives = directive
    return child
Esempio n. 4
0
 def _normaliseDirectivesMap(self, directivesMap):
     """
     Removes any 'default-src' directive and expands it to all basic directive types that are not yet 
     specified (in place).
     """
     if not "default-src" in directivesMap:
         return
     defaultDirective = directivesMap['default-src']
     for otherType in self._defaultSrcTypes:
         if not otherType in directivesMap:
             directivesMap[otherType] = Directive(
                 otherType,
                 defaultDirective.getWhitelistedSourceExpressions())
     del directivesMap["default-src"]
Esempio n. 5
0
def try_parse_and_handle_directive(ctx):
    from directive_impl import same_as_file

    # Register all directives.
    all_directives: List[Directive] = [
        Directive(same_as_file.ext_to_patterns, [generic_config_parser, same_as_file.parse], same_as_file.handle)
    ]

    for directive in all_directives:
        directive_config = []
        if succeeded(directive.try_parse_directive(ctx, directive_config)):
            directive.handle(directive_config.pop(), ctx)
            return success(directive_config)

    return failure()
Esempio n. 6
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. 7
0
 def combinedPolicy(self, otherPolicy):
     """
     Returns a new Policy that is the recursive combination of the Directives contained in this 
     Policy and 'otherPolicy' (combining Directives of the same type, and adding Directives
     of a type that is missing in one of the policies). This extends the whitelists and results 
     in a more permissive overall Policy. This method can be used when generating policies from 
     violation reports, but should not be used to enforce multiple policies at the same time 
     (the semantics are different).
     
     If this Policy or 'otherPolicy' is Policy.INVALID(), or if the combination of any of the 
     contained Directives is Directive.INVALID(), this method returns Policy.INVALID(). 
     Because of the special meaning of 'default-src', two policies containing 'default-src' 
     (in one or both policies) can be combined only if 'default-src' is the only directive 
     type in both policies (else Policy.INVALID() is returned).
     """
     if (self == Policy.INVALID() or otherPolicy == Policy.INVALID()):
         return Policy.INVALID()
     myDirectives = dict(
         map(lambda x: (x.getType(), x), self.getDirectives()))
     otherDirectives = dict(
         map(lambda x: (x.getType(), x), otherPolicy.getDirectives()))
     allDirectiveTypes = set(myDirectives.keys()) | set(
         otherDirectives.keys())
     if ('default-src' in allDirectiveTypes and
         ((not 'default-src' in myDirectives and len(myDirectives) > 0) or
          ('default-src' in myDirectives and len(myDirectives) > 1) or
          (not 'default-src' in otherDirectives
           and len(otherDirectives) > 0) or
          ('default-src' in otherDirectives and len(otherDirectives) > 1))):
         return Policy.INVALID()
     combinedDirectives = set([])
     for directiveType in allDirectiveTypes:
         if directiveType not in myDirectives:
             combinedDirectives.add(otherDirectives[directiveType])
         elif directiveType not in otherDirectives:
             combinedDirectives.add(myDirectives[directiveType])
         else:
             combined = myDirectives[directiveType].combinedDirective(
                 otherDirectives[directiveType])
             if combined == Directive.INVALID():
                 return Policy.INVALID()
             else:
                 combinedDirectives.add(combined)
     return Policy(combinedDirectives)
Esempio n. 8
0
 def generatePolicy(self, reportType):
     """
     Generates a new basic policy that allows exactly the kind of event that caused this CSP violation report,
     assuming the given 'reportType' (permitted values are 'regular', 'eval', and 'inline').
     This assumes that this report contains a specific violated-directive field (it may not be 'default-src').
     If any inconsistent reports are used to generate policies, the policies themselves will be inconsistent. 
     
     Policies should be collected with CSP headers like these:
     
     Content-Security-Policy-Report-Only: default-src 'none'; script-src 'unsafe-eval' 'unsafe-inline'; object-src 'none'; style-src 'unsafe-inline'; img-src 'none'; media-src 'none'; frame-src 'none'; font-src 'none'; connect-src 'none'; report-uri /csp.cgi?type=regular
     Content-Security-Policy-Report-Only: default-src *; script-src * 'unsafe-inline'; style-src * 'unsafe-inline'; report-uri /csp.cgi?type=eval
     Content-Security-Policy-Report-Only: default-src *; script-src * 'unsafe-eval'; style-src *; report-uri /csp.cgi?type=inline
     
     The "type" parameter in the report-uri is equivalent to the 'reportType' parameter of this method.
     
     The results should also be filtered to ensure that only reports sent by fully compatible browsers
     are taken into account. 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.
     
     The result is a basic Policy containing one whitelisted resource (corresponding to the violated directive). 
     In practice, it should not be used alone, but be combined with basic policies generated for other violations
     on the same web site. It should also be prepended with "default-src 'none'" to ensure that only the
     whitelisted resources are allowed. (The standard behaviour of CSP in absence of any default Directive is
     to assume "default-src *", which may not be the desired behaviour.)
     
     The result is Policy.INVALID() if (1) the violated directive is missing, Directive.INVALID() or 'default-src', 
     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.
     """
     if (self == Report.INVALID()
         or 'violated-directive' not in self
         or 'blocked-uri' not in self):
         return Policy.INVALID()
     violated = self['violated-directive']
     blocked = self['blocked-uri']
     generated = violated.generateDirective(reportType, blocked)
     if generated == Directive.INVALID():
         return Policy.INVALID()
     else:
         return Policy((generated,))
Esempio n. 9
0
 def exitDirectiveEQU(self, ctx: tl69asmParser.DirectiveEQUContext):
     ctx.directive = Directive(DirectiveType.EQU,
                               ctx.expr().expr,
                               ctx.label().label_name)
     ctx.expr = ctx.expr().expr
Esempio n. 10
0
 def exitDirectiveORG(self, ctx: tl69asmParser.DirectiveORGContext):
     ctx.directive = Directive(DirectiveType.ORG, ctx.expr().expr)
Esempio n. 11
0
 def exitDirectiveDW(self, ctx: tl69asmParser.DirectiveDWContext):
     ctx.directive = Directive(DirectiveType.DW, ctx.expr().expr)
Esempio n. 12
0
class Policy(object):
    """
    A CSP policy that consists of one or more directives. Immutable
    """

    _invalid = None
    _defaultSrcDirectiveIfNotSpecified = Directive(
        "default-src", (URISourceExpression(None, "*", None, None), ))

    def __init__(self, directives):
        """
        Initialises this CSP policy from the given 'directives' list/set/tuple.
        
        'directives': An iterable of Directives. May contain at most one Directive of each type.
        Any Directive that is not regular will be dropped.
        """
        self._hash = None
        self._str = None
        self._isInvalid = False
        # eliminate directives with duplicate type and irregular directives
        onlyRegular = filter(lambda x: x.isRegularDirective(), directives)
        self._directives = frozenset(
            dict(map(lambda x: (x.getType(), x), onlyRegular)).values())

    @staticmethod
    def INVALID():
        """
        Special static singleton Policy representing an invalid policy (could not be parsed).
        """
        if Policy._invalid is None:
            Policy._invalid = Policy(())
            Policy._invalid._isInvalid = True
        return Policy._invalid

    def combinedPolicy(self, otherPolicy):
        """
        Returns a new Policy that is the recursive combination of the Directives contained in this 
        Policy and 'otherPolicy' (combining Directives of the same type, and adding Directives
        of a type that is missing in one of the policies). This extends the whitelists and results 
        in a more permissive overall Policy. This method can be used when generating policies from 
        violation reports, but should not be used to enforce multiple policies at the same time 
        (the semantics are different).
        
        If this Policy or 'otherPolicy' is Policy.INVALID(), or if the combination of any of the 
        contained Directives is Directive.INVALID(), this method returns Policy.INVALID(). 
        Because of the special meaning of 'default-src', two policies containing 'default-src' 
        (in one or both policies) can be combined only if 'default-src' is the only directive 
        type in both policies (else Policy.INVALID() is returned).
        """
        if (self == Policy.INVALID() or otherPolicy == Policy.INVALID()):
            return Policy.INVALID()
        myDirectives = dict(
            map(lambda x: (x.getType(), x), self.getDirectives()))
        otherDirectives = dict(
            map(lambda x: (x.getType(), x), otherPolicy.getDirectives()))
        allDirectiveTypes = set(myDirectives.keys()) | set(
            otherDirectives.keys())
        if ('default-src' in allDirectiveTypes and
            ((not 'default-src' in myDirectives and len(myDirectives) > 0) or
             ('default-src' in myDirectives and len(myDirectives) > 1) or
             (not 'default-src' in otherDirectives
              and len(otherDirectives) > 0) or
             ('default-src' in otherDirectives and len(otherDirectives) > 1))):
            return Policy.INVALID()
        combinedDirectives = set([])
        for directiveType in allDirectiveTypes:
            if directiveType not in myDirectives:
                combinedDirectives.add(otherDirectives[directiveType])
            elif directiveType not in otherDirectives:
                combinedDirectives.add(myDirectives[directiveType])
            else:
                combined = myDirectives[directiveType].combinedDirective(
                    otherDirectives[directiveType])
                if combined == Directive.INVALID():
                    return Policy.INVALID()
                else:
                    combinedDirectives.add(combined)
        return Policy(combinedDirectives)

    def getDirectives(self):
        """
        Returns a frozen set of all the directives contained in this policy.
        """
        return self._directives  # is already immutable

    def matches(self,
                resourceURI,
                resourceType,
                protectedDocumentURI,
                schemePortMappings=defaults.schemePortMappings,
                defaultSrcTypes=defaults.defaultSrcReplacementDirectiveTypes):
        """
        Returns whether the given resourceURI is allowed under this Policy. Attempts to match 
        
        'resourceURI' is an URI object corresponding to the resource that is attempted to be loaded/executed.
        Can be either one of the special URI.UNSAFE_EVAL() / URI.UNSAFE_INLINE() URIs, or a regular URI.
        In the latter case, escaped characters in the path of the URI should already have been decoded. 
        If 'resourceURI' designates a directory (as opposed to a file), its path must end with a '/'. 
        May not be None.
        
        'resourceType' indicates the type of the 'resourceURI', which is a directive type as
        returned by Directive.getType() (such as 'img-src' or 'script-src' for image and script resources,
        respectively).
        
        'protectedDocumentURI' is the URI of the document in the context of which 'resourceURI' is being 
        attempted to be loaded/executed (the host document). May not be None.
        
        'schemePortMappings': A dictionary with mappings from (lowercase) scheme names to the corresponding
        default port. Will be used if ports are missing in the 'resourceURI' or 'protectedDocumentURI'.
        
        'defaultSrcTypes': A list of (lowercase) directive types to be used for matching, to determine if the
        "default-src" directive can be used if no directive of the needed type is available.
        Example: 'resourceType' is 'script-src', but this Policy contains no 'script-src' Directive.
        If 'defaultSrcTypes' contains 'script-src', the 'default-src' Directive can be used instead of the
        missing 'script-src' Directive, if available.
        
        This implementation requires schemes to be present in both URIs, and either port numbers or a successful
        scheme-to-port-number look up in 'schemePortMappings' for both URIs (otherwise, False is returned).
        For details about the implementation, see http://www.w3.org/TR/2014/WD-CSP11-20140211/#matching
        """
        if self == Policy.INVALID():
            return False

        # if directive of resource type is available, use it for matching
        resourceType = resourceType.lower()
        for direct in self._directives:
            if direct.getType() == resourceType:
                return direct.matches(resourceURI, protectedDocumentURI,
                                      schemePortMappings)

        # check if type of resource admits matching with default-src per CSP 1.1 draft
        if resourceType not in defaultSrcTypes:
            return False

        # match with default-src
        # if no default directive is available, assume default-src '*' according to # http://www.w3.org/TR/2014/WD-CSP11-20140211/#default-src
        for direct in self._directives:
            if direct.getType() == "default-src":
                return direct.matches(resourceURI, protectedDocumentURI,
                                      schemePortMappings)
        return Policy._defaultSrcDirectiveIfNotSpecified.matches(
            resourceURI, protectedDocumentURI, schemePortMappings)

    def withoutPaths(self, schemeOnly=defaults.schemeOnly):
        """
        Returns a copy of this Policy that has the path components removed from all URISourceExpressions
        in the contained Directives.
        
        'schemeOnly' is a list of scheme names. If the scheme of any source expression is contained
        in this list, not only the path will be removed, but the host and port, too. This is useful
        for data or chrome-extension URIs, for example.
        """
        if self == Policy.INVALID():
            return self
        pathsRemoved = []
        for direct in self._directives:
            pathsRemoved.append(direct.withoutPaths(schemeOnly))
        return Policy(pathsRemoved)

    def asBasicPolicies(self):
        """
        Returns a set of Policies that contain each exactly one Directive with exactly one SourceExpression.
        'Decomposes' this Policy into basic Policies and Directives.
        Returns the empty set if this policy is invalid.
        """
        if self == Policy.INVALID():
            return set([])
        if len(self._directives) == 0:
            return frozenset((self, ))
        policies = set([])
        for direct in self._directives:
            for bDirect in direct.asBasicDirectives():
                policies.add(Policy((bDirect, )))
        return policies

    def compareTo(self, otherPolicy):
        """
        Compares this Policy to 'otherPolicy' and returns three sets of basic Policies (that is, Policies with
        exactly one Directive and one SourceExpression): (common basic policies, basic policies only in 'self',
        basic policies only in 'otherPolicy'). If this Policy or 'otherPolicy' is INVALID(), returns three
        empty sets.
        """
        if self == Policy.INVALID() or otherPolicy == Policy.INVALID():
            return (set([]), set([]), set([]))
        selfBasic = self.asBasicPolicies()
        otherBasic = otherPolicy.asBasicPolicies()
        common = selfBasic & otherBasic
        onlySelf = selfBasic - common
        onlyOther = otherBasic - common
        return (common, onlySelf, onlyOther)

    def isBasicPolicy(self):
        """
        Returns if this Policy is basic. That is, whether it consists of exactly one Directive, and whether
        that Directive is basic.
        """
        if self == Policy.INVALID():
            return False
        if len(self._directives) != 1:
            return False
        return self._directives.__iter__().next().isBasicDirective()

    def isBasicNonePolicy(self):
        """
        Returns if this Policy is basic, and has an empty whitelisted resource list in the Directive.
        """
        if self == Policy.INVALID():
            return False
        if len(self._directives) != 1:
            return False
        direct = self._directives.__iter__().next()
        return len(direct.getWhitelistedSourceExpressions()) == 0

    def hasDefaultDirective(self):
        """
        Returns whether this Policy has a 'default-src' Directive.
        """
        if self == Policy.INVALID():
            return False
        for direct in self._directives:
            if direct.getType() == "default-src":
                return True
        return False

    def __repr__(self):
        """
        Returns a full representation of this Policy. Equivalent to __str__().
        """
        return str(self)

    def __str__(self):
        """
        Returns a string representation of this policy (directives in sorted order).
        """
        if self._str is None:
            if self == Policy.INVALID():
                self._str = "[invalid]"
            else:
                stringPolicyList = map(lambda x: str(x), self._directives)
                stringPolicyList.sort()
                self._str = ("; ".join(stringPolicyList))
        return self._str

    def __eq__(self, other):
        """
        Returns whether the two policies have the elements. This is NOT the same as checking whether
        they have the same effect.
        """
        if type(other) != Policy:
            return False
        return (self._isInvalid == other._isInvalid
                and self._directives == other._directives)

    def __hash__(self):
        """
        Returns a hash value for this object that is guaranteed to be the same for two objects
        that are equal (the opposite is not necessarily true).
        """
        if self._hash is None:
            self._hash = hash(self._directives) ^ hash(self._isInvalid)
        return self._hash
from pathlib import Path
from directive import Directive

p = Path("../QuestionBank/fopp")

flist = [x for x in p.glob("**/*") if x.is_file()]

activecodes = {}
for f in flist:
    with f.open() as df:
        try:
            d = Directive(df.read())
            if d.kind == "activecode":
                activecodes[f] = d
        except Exception as e:
            print(f"Error in {f} is {e}")

for q1 in activecodes.values():
    for q2 in activecodes.values():
        if q1 is not q2:
            if q1.instructions and q1.same_question(q2):
                if q1.starter_code == q2.starter_code:
                    print(f"{q1.identifier} and {q2.identifier} are the same")
                    if bool(q1.hidden_code) != bool(q2.hidden_code):
                        if q1.hidden_code:
                            print(f"{q1.identifier} has unit tests")
                        else:
                            print(f"{q2.identifier} has unit tests")
                            print(q2.hidden_code)
                else:
                    print(q1.starter_code)
Esempio n. 14
0
     "WAND":
     Instruction("WAND", 003000, OperandType.EXPRESSION,
                 AddressType.CHANNEL),
     "WOR":
     Instruction("WOR", 005000, OperandType.EXPRESSION,
                 AddressType.CHANNEL),
     "WRITE":
     Instruction("WRITE", 001000, OperandType.EXPRESSION,
                 AddressType.CHANNEL),
     "ZQ":
     Instruction("ZQ", 022007)
 },
 OpcodeType.DIRECTIVE: {
     # Name                Method            Mnemonic    Operand Type            Optional?   Words
     "-1DNADR":
     Directive("MinusDNADR", "-1DNADR", OperandType.EXPRESSION, False,
               1),
     "-2CADR":
     Directive("Minus2CADR", "-2CADR", OperandType.EXPRESSION, False,
               2),
     "-2DNADR":
     Directive("MinusDNADR", "-2DNADR", OperandType.EXPRESSION, False,
               1),
     "-3DNADR":
     Directive("MinusDNADR", "-3DNADR", OperandType.EXPRESSION, False,
               1),
     "-4DNADR":
     Directive("MinusDNADR", "-4DNADR", OperandType.EXPRESSION, False,
               1),
     "-5DNADR":
     Directive("MinusDNADR", "-5DNADR", OperandType.EXPRESSION, False,
               1),
Esempio n. 15
0
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from directive import Directive
import sys

p = Directive()
ast = p.parse_file(sys.argv[1])

print(ast.to_yml())

print("> imports:", ast.kimports)
print("> typenames:", ast.ktypenames)