Source code for policytree

#!/usr/bin/python

from pyparsing import *
from charm.toolbox.node import *
import string

objStack = []

[docs]def createAttribute(s, loc, toks): if toks[0] == '!': newtoks = "" for i in toks: newtoks += i return BinNode(newtoks) return BinNode(toks[0]) # create
# convert 'attr < value' to a binary tree based on 'or' and 'and'
[docs]def parseNumConditional(s, loc, toks): print("print: %s" % toks) return BinNode(toks[0])
[docs]def printStuff(s, loc, toks): print("print: %s" % toks) return toks
[docs]def pushFirst( s, loc, toks ): objStack.append( toks[0] )
[docs]def createTree(op, node1, node2): if(op == "or"): node = BinNode(OpType.OR) elif(op == "and"): node = BinNode(OpType.AND) else: return None node.addSubNode(node1, node2) return node
[docs]class PolicyParser: def __init__(self, verbose=False): self.finalPol = self.getBNF() self.verbose = verbose
[docs] def getBNF(self): # supported operators => (OR, AND, < OperatorOR = Literal("OR").setParseAction(downcaseTokens) | Literal("or") OperatorAND = Literal("AND").setParseAction(downcaseTokens) | Literal("and") Operator = OperatorAND | OperatorOR lpar = Literal("(").suppress() rpar = Literal(")").suppress() BinOperator = Literal("<=") | Literal(">=") | Literal("==") | Word("<>", max=1) # describes an individual leaf node leafNode = (Optional("!") + Word(alphanums+'-_./\?!@#$^&*%')).setParseAction( createAttribute ) # describes expressions such as (attr < value) leafConditional = (Word(alphanums) + BinOperator + Word(nums)).setParseAction( parseNumConditional ) # describes the node concept node = leafConditional | leafNode expr = Forward() term = Forward() atom = lpar + expr + rpar | (node).setParseAction( pushFirst ) term = atom + ZeroOrMore((Operator + term).setParseAction( pushFirst )) expr << term + ZeroOrMore((Operator + term).setParseAction( pushFirst )) finalPol = expr#.setParseAction( printStuff ) return finalPol
[docs] def evalStack(self, stack): op = stack.pop() if op in ["or", "and"]: op2 = self.evalStack(stack) op1 = self.evalStack(stack) return createTree(op, op1, op2) else: # Node value (attribute) return op
[docs] def parse(self, string): global objStack del objStack[:] self.finalPol.parseString(string) return self.evalStack(objStack)
[docs] def findDuplicates(self, tree, _dict): if tree.left: self.findDuplicates(tree.left, _dict) if tree.right: self.findDuplicates(tree.right, _dict) if tree.getNodeType() == OpType.ATTR: key = tree.getAttribute() if _dict.get(key) == None: _dict[ key ] = 1 else: _dict[ key ] += 1
[docs] def labelDuplicates(self, tree, _dictLabel): if tree.left: self.labelDuplicates(tree.left, _dictLabel) if tree.right: self.labelDuplicates(tree.right, _dictLabel) if tree.getNodeType() == OpType.ATTR: key = tree.getAttribute() if _dictLabel.get(key) != None: tree.index = _dictLabel[ key ] _dictLabel[ key ] += 1
[docs] def prune(self, tree, attributes): """given policy tree and attributes, determine whether the attributes satisfy the policy. if not enough attributes to satisfy policy, return None otherwise, a pruned list of attributes to potentially recover the associated secret. """ (policySatisfied, prunedList) = self.requiredAttributes(tree, attributes) # print("pruned attrs: ", prunedList) # if prunedList: # for i in prunedList: # print("node: ", i) if not policySatisfied: return policySatisfied return prunedList
[docs] def requiredAttributes(self, tree, attrList): """ determines the required attributes to satisfy policy tree and returns a list of BinNode objects.""" if tree == None: return 0 Left = tree.getLeft() Right = tree.getRight() if Left: resultLeft, leftAttr = self.requiredAttributes(Left, attrList) if Right: resultRight, rightAttr = self.requiredAttributes(Right, attrList) if(tree.getNodeType() == OpType.OR): # never return both attributes, basically the first one that matches from left to right if resultLeft: sendThis = leftAttr elif resultRight: sendThis = rightAttr else: sendThis = None result = (resultLeft or resultRight) if result == False: return (False, sendThis) return (True, sendThis) if(tree.getNodeType() == OpType.AND): if resultLeft and resultRight: sendThis = leftAttr + rightAttr elif resultLeft: sendThis = leftAttr elif resultRight: sendThis = rightAttr else: sendThis = None result = (resultLeft and resultRight) if result == False: return (False, sendThis) return (True, sendThis) elif(tree.getNodeType() == OpType.ATTR): if(tree.getAttribute() in attrList): return (True, [tree]) else: return (False, None) return
if __name__ == "__main__": # policy parser test cases parser = PolicyParser() attrs = ['1', '3'] print("Attrs in user set: ", attrs) tree1 = parser.parse("(1 or 2) and (2 and 3))") print("case 1: ", tree1, ", pruned: ", parser.prune(tree1, attrs)) tree2 = parser.parse("1 or (2 and 3)") print("case 2: ", tree2, ", pruned: ", parser.prune(tree2, attrs)) tree3 = parser.parse("(1 or 2) and (4 or 3)") print("case 3: ", tree3, ", pruned: ", parser.prune(tree3, attrs))