def test_not_tracking_implicit_flows(self): x = ProtectedRef(0, None, self.allowUserWrite(self.aliceUser), False) x.update(self.aliceUser, self.aliceUser, 42) y = ProtectedRef(1, None, self.allowUserWrite(self.bobUser), False) y.update(self.bobUser, self.bobUser, 2 if x.v == 42 else 3) self.assertEqual(JeevesLib.concretize(self.aliceUser, y.v), 2) self.assertEqual(JeevesLib.concretize(self.bobUser, y.v), 2)
def test_prevent_untrusted_writes_through_implicit_flows(self): x = ProtectedRef(0, None, self.allowUserWrite(self.aliceUser)) x.update(self.aliceUser, self.aliceUser, 42) y = ProtectedRef(1, None, self.allowUserWrite(self.bobUser)) y.update(self.bobUser, self.bobUser, 2 if x.v == 42 else 3) self.assertEqual(JeevesLib.concretize(self.aliceUser, y.v), 3) self.assertEqual(JeevesLib.concretize(self.bobUser, y.v), 3)
def test_prevent_flow_of_untrusted_writes(self): x = ProtectedRef(0, None, self.allowUserWrite(self.aliceUser)) assert x.update(self.aliceUser, self.aliceUser, 42) == UpdateResult.Unknown y = ProtectedRef(1, None, self.allowUserWrite(self.bobUser)) assert y.update(self.bobUser, self.bobUser, x.v) == UpdateResult.Unknown self.assertEqual(JeevesLib.concretize(self.aliceUser, x.v), 42) self.assertEqual(JeevesLib.concretize(self.bobUser, x.v), 42) self.assertEqual(JeevesLib.concretize(self.aliceUser, y.v), 0) self.assertEqual(JeevesLib.concretize(self.bobUser, y.v), 0)
def test_combining_write_policies_in_operation(self): x = ProtectedRef(0, None, self.allowUserWrite(self.bobUser)) x.update(self.bobUser, self.bobUser, 42) y = ProtectedRef( 2, None, lambda _this: lambda ictxt: lambda octxt: ictxt == self. aliceUser and octxt == self.bobUser) y.update(self.aliceUser, self.aliceUser, 43) self.assertEqual(JeevesLib.concretize(self.aliceUser, x.v + y.v), 44) self.assertEqual(JeevesLib.concretize(self.bobUser, x.v + y.v), 85) self.assertEqual(JeevesLib.concretize(self.carolUser, x.v + y.v), 44)
def test_prevent_flow_of_operations_on_untrusted_writes(self): x = ProtectedRef(0, None, self.allowUserWrite(self.aliceUser)) x.update(self.aliceUser, self.aliceUser, 42) y = ProtectedRef(1, None, self.allowUserWrite(self.bobUser)) y.update(self.bobUser, self.bobUser, 43) z = ProtectedRef(0, None, self.allowUserWrite(self.carolUser)) z.update(self.carolUser, self.carolUser, x.v + y.v) self.assertEqual(JeevesLib.concretize(self.aliceUser, z.v), 1) self.assertEqual(JeevesLib.concretize(self.bobUser, z.v), 1) self.assertEqual(JeevesLib.concretize(self.carolUser, z.v), 1)
def test_prevent_implicit_flows_of_confidential_values(self): x = ProtectedRef(0, None , lambda _this: lambda ictxt: lambda octxt: ictxt == self.aliceUser and octxt == self.aliceUser) x.update(self.aliceUser, self.aliceUser, 42) y = ProtectedRef(1, None , lambda _this: lambda ictxt: lambda octxt: ictxt == self.bobUser or ictxt == self.aliceUser) y.update(self.bobUser, self.bobUser, 2 if x.v == 42 else 3) self.assertEqual(JeevesLib.concretize(self.aliceUser, y.v), 2) self.assertEqual(JeevesLib.concretize(self.bobUser, y.v), 3)
def test_combining_values_into_permissive_write(self): x = ProtectedRef(0, None, self.allowUserWrite(self.bobUser)) x.update(self.bobUser, self.bobUser, 42) y = ProtectedRef(1, None, self.allowUserWrite(self.aliceUser)) y.update(self.aliceUser, self.aliceUser, 43) z = ProtectedRef( 0, None, lambda _this: lambda ictxt: lambda otxt: ictxt == self. aliceUser or ictxt == self.bobUser or ictxt == self.carolUser) z.update(self.carolUser, self.carolUser, x.v + y.v) self.assertEqual(JeevesLib.concretize(self.aliceUser, z.v), 85) self.assertEqual(JeevesLib.concretize(self.bobUser, z.v), 85) self.assertEqual(JeevesLib.concretize(self.carolUser, z.v), 85)
def __init__(self, owner): self.owner = owner self.shipRef = ProtectedRef(NoShip() # Policy for updating: must be owner and there can't be a ship there # already. , lambda ship: lambda ic: ship == NoShip() and self.isOwner(ic) , None) self.hasBombRef = ProtectedRef(None , lambda _bomb: lambda ic: self.hasTurn(ic) and self.allShipsPlaced(ic) and not self.gameOver(ic) , None)
def test_prevent_implicit_flows_of_confidential_values(self): # Alice may write to x. Only Alice may see the updates. x = ProtectedRef( 0, None, lambda _this: lambda ictxt: lambda octxt: ictxt == self. aliceUser and octxt == self.aliceUser) x.update(self.aliceUser, self.aliceUser, 42) # Alice and Bob may both write to y. y = ProtectedRef( 1, None, lambda _this: lambda ictxt: lambda octxt: ictxt == self. bobUser or ictxt == self.aliceUser) y.update(self.bobUser, self.bobUser, 2 if x.v == 42 else 3) # self.assertEqual(JeevesLib.concretize(self.aliceUser, y.v), 2) self.assertEqual(JeevesLib.concretize(self.bobUser, y.v), 3)
def test_combining_confidentiality_with_operations(self): x = ProtectedRef(0, None, self.allowUserWrite(self.bobUser)) x.update(self.bobUser, self.bobUser, 42) y = ProtectedRef(2, None , lambda _this: lambda ictxt: lambda octxt: ictxt == self.aliceUser and octxt == self.bobUser) y.update(self.aliceUser, self.aliceUser, 43) z = ProtectedRef(0, None , lambda _this: lambda ictxt: lambda octxt: ictxt == self.aliceUser or ictxt == self.bobUser or ictxt == self.carolUser) z.update(self.carolUser, self.carolUser, x.v + y.v) self.assertEqual(JeevesLib.concretize(self.aliceUser, z.v), 44) self.assertEqual(JeevesLib.concretize(self.bobUser, z.v), 85) self.assertEqual(JeevesLib.concretize(self.carolUser, z.v), 44)
def test_write_allowed_for_all_viewers(self): x = ProtectedRef(0, None, self.allowUserWrite(self.aliceUser)) assert x.update(self.aliceUser, self.aliceUser, 42) == UpdateResult.Unknown self.assertEqual(JeevesLib.concretize(self.aliceUser, x.v), 42) self.assertEqual(JeevesLib.concretize(self.bobUser, x.v), 42) self.assertEqual(JeevesLib.concretize(self.carolUser, x.v), 42)
def test_determine_writer_trust_later(self): x = ProtectedRef( 0, None, lambda _this: lambda ictxt: lambda octxt: JeevesLib.jhas( octxt, ictxt)) x.update(self.aliceUser, self.aliceUser, 42) self.assertEqual(JeevesLib.concretize([self.aliceUser], x.v), 42) self.assertEqual(JeevesLib.concretize([], x.v), 0)
def test_permitted_writer_overwrite(self): x = ProtectedRef(0, None, self.allowUserWrite(self.bobUser)) assert x.update(self.aliceUser, self.aliceUser, 42) == UpdateResult.Unknown assert x.update(self.bobUser, self.bobUser, 43) == UpdateResult.Unknown self.assertEqual(JeevesLib.concretize(self.aliceUser, x.v), 43) self.assertEqual(JeevesLib.concretize(self.bobUser, x.v), 43) self.assertEqual(JeevesLib.concretize(self.carolUser, x.v), 43)
def test_write_selectively_allowed(self): x = ProtectedRef(0, None , lambda _this: lambda ictxt: lambda octxt: ictxt == self.aliceUser and octxt == self.bobUser) assert x.update(self.aliceUser, self.aliceUser, 42) == UpdateResult.Unknown self.assertEqual(JeevesLib.concretize(self.aliceUser, x.v), 0) self.assertEqual(JeevesLib.concretize(self.bobUser, x.v), 42) self.assertEqual(JeevesLib.concretize(self.carolUser, x.v), 0)
def test_output_varies_depending_on_viewer(self): x = ProtectedRef( 0, None, lambda _this: lambda ictxt: lambda octxt: ictxt == self. aliceUser and octxt == self.bobUser) x.update(self.aliceUser, self.aliceUser, 42) self.assertEqual(JeevesLib.concretize(self.aliceUser, x.v), 0) self.assertEqual(JeevesLib.concretize(self.bobUser, x.v), 42) self.assertEqual(JeevesLib.concretize(self.carolUser, x.v), 0)
def test_combining_confidentiality_with_operations(self): # Only Bob is allowed to write to x. Bob writes to x. x = ProtectedRef(0, None, self.allowUserWrite(self.bobUser)) x.update(self.bobUser, self.bobUser, 42) # Only Alice is allowed to write to y and only Bob can see the result. # Alice writes to y. y = ProtectedRef( 2, None, lambda _this: lambda ictxt: lambda octxt: ictxt == self. aliceUser and octxt == self.bobUser) y.update(self.aliceUser, self.aliceUser, 43) # Alice, Bob, and Carol are allowed to write to z. z = ProtectedRef( 0, None, lambda _this: lambda ictxt: lambda octxt: ictxt == self. aliceUser or ictxt == self.bobUser or ictxt == self.carolUser) z.update(self.carolUser, self.carolUser, x.v + y.v) self.assertEqual(JeevesLib.concretize(self.aliceUser, z.v), 44) self.assertEqual(JeevesLib.concretize(self.bobUser, z.v), 85) self.assertEqual(JeevesLib.concretize(self.carolUser, z.v), 44)
def test_function_facets_cannot_write(self): def id(x): return x def inc(x): return x+1 x = ProtectedRef(id, None, self.allowUserWrite(self.bobUser)) self.assertEqual(JeevesLib.concretize(self.aliceUser, x.v)(1), 1) x.update(self.aliceUser, self.aliceUser, inc) self.assertEqual(JeevesLib.concretize(self.aliceUser, x.v)(1), 1)
def __init__(self, userId, friends=[]): # TODO: Implement more interesting policies for this. def allowUserWrite(user): return lambda _this: lambda ictxt: lambda octxt: ictxt == user self.userId = userId self.location = ProtectedRef( Unknown(), None, lambda _this: lambda ic: lambda oc: ic == self) self.friends = list(friends)
def __init__(self, owner): self.owner = owner self._placedRef = ProtectedRef( False, lambda hasShip: lambda ic: (not hasShip) and self.isOwner(ic), None) # TODO: See if we can do away with this... self._placed = False self._bombed = False self._squares = []
def test_output_write_policy_with_this_cannot_update(self): x = ProtectedRef(0, None , lambda v: lambda ictxt: lambda _octxt: (not (v == 3)) and ictxt == self.aliceUser) x.update(self.aliceUser, self.aliceUser, 1) self.assertEqual(JeevesLib.concretize(self.aliceUser, x.v), 1) x.update(self.aliceUser, self.aliceUser, 3) self.assertEqual(JeevesLib.concretize(self.aliceUser, x.v), 3) x.update(self.aliceUser, self.aliceUser, 5) self.assertEqual(JeevesLib.concretize(self.aliceUser, x.v), 3)
def test_output_write_policies_involving_this_can_update(self): x = ProtectedRef(0, None , lambda v: lambda ictxt: lambda _: v == 0 and ictxt == self.aliceUser) x.update(self.aliceUser, self.aliceUser, 1) print x.v.prettyPrint() self.assertEqual(JeevesLib.concretize(self.aliceUser, x.v), 1) x.update(self.aliceUser, self.aliceUser, 3) print x.v.prettyPrint() self.assertEqual(JeevesLib.concretize(self.aliceUser, x.v), 1)
def testBehavioralSanitizationBad(self): touchedBadData = False def f(s): global touchedBadData if s == "bad": touchedBadData = True return s x = ProtectedRef("dunno", None , lambda _this: lambda ic: lambda oc: not touchedBadData) assert x.update(None, None, f("bad")) == UpdateResult.Unknown print touchedBadData self.assertEqual(JeevesLib.concretize(None, x.v), "dunno")
def __init__(self, name, initValue=0): self.name = name self._vRef = ProtectedRef( initValue # We also support policies where the write checks get concretized right # away in the context of the user. , None # Flow is only permitted if there is an edge. # The policy takes the current value (v), the input channel (ic), and # the output channel. , lambda v: lambda ic: lambda oc: JeevesLib.jhasElt( self.edges, lambda edge: edge.v == oc)) self._edges = []
def test_input_write_policies_with_confidentiality(self): # Make a sensitive value that is either Bob or the nobody user. Only Bob # can see this. a = JeevesLib.mkLabel() JeevesLib.restrict(a, lambda ctxt: ctxt == self.bobUser) secretWriter = JeevesLib.mkSensitive(a, self.bobUser, self.nobodyUser) # We now make a protected reference where the input channel has to be the # secret writer. x = ProtectedRef(0, lambda _this: lambda ictxt: ictxt == secretWriter, None) x.update(self.bobUser, self.bobUser, 42) self.assertEqual(JeevesLib.concretize(self.bobUser, secretWriter), self.bobUser) self.assertEqual(JeevesLib.concretize(self.aliceUser, secretWriter), self.nobodyUser) self.assertEqual(JeevesLib.concretize(self.aliceUser, secretWriter), self.nobodyUser) # Only Bob should be able to see the value he wrote. self.assertEqual(JeevesLib.concretize(self.aliceUser, x.v), 42) self.assertEqual(JeevesLib.concretize(self.bobUser, x.v), 42) self.assertEqual(JeevesLib.concretize(self.carolUser, x.v), 42)