mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2025-02-21 02:01:31 +00:00
minor code clean-up in dirnode.py
Impose micro-POLA by passing only the writekey instead of the whole node object to {{{_encrypt_rw_uri()}}}. Remove DummyImmutableFileNode in nodemaker.py, which is obviated by this. Add micro-optimization by precomputing the netstring of the empty string and branching on whether the writekey is present or not outside of {{{_encrypt_rw_uri()}}}. Add doc about writekey to docstring. fixes #967
This commit is contained in:
parent
11077ea74d
commit
6e8477114e
@ -171,12 +171,10 @@ class Adder:
|
||||
new_contents = self.node._pack_contents(children)
|
||||
return new_contents
|
||||
|
||||
def _encrypt_rw_uri(writekey, rw_uri):
|
||||
precondition(isinstance(rw_uri, str), rw_uri)
|
||||
precondition(isinstance(writekey, str), writekey)
|
||||
|
||||
def _encrypt_rw_uri(filenode, rw_uri):
|
||||
assert isinstance(rw_uri, str)
|
||||
writekey = filenode.get_writekey()
|
||||
if not writekey:
|
||||
return ""
|
||||
salt = hashutil.mutable_rwcap_salt_hash(rw_uri)
|
||||
key = hashutil.mutable_rwcap_key_hash(salt, writekey)
|
||||
cryptor = AES(key)
|
||||
@ -187,8 +185,7 @@ def _encrypt_rw_uri(filenode, rw_uri):
|
||||
# The MAC is not checked by readers in Tahoe >= 1.3.0, but we still
|
||||
# produce it for the sake of older readers.
|
||||
|
||||
|
||||
def pack_children(filenode, childrenx, deep_immutable=False):
|
||||
def pack_children(childrenx, writekey, deep_immutable=False):
|
||||
# initial_children must have metadata (i.e. {} instead of None)
|
||||
children = {}
|
||||
for (namex, (node, metadata)) in childrenx.iteritems():
|
||||
@ -196,10 +193,11 @@ def pack_children(filenode, childrenx, deep_immutable=False):
|
||||
"directory creation requires metadata to be a dict, not None", metadata)
|
||||
children[normalize(namex)] = (node, metadata)
|
||||
|
||||
return _pack_normalized_children(filenode, children, deep_immutable=deep_immutable)
|
||||
return _pack_normalized_children(children, writekey=writekey, deep_immutable=deep_immutable)
|
||||
|
||||
|
||||
def _pack_normalized_children(filenode, children, deep_immutable=False):
|
||||
ZERO_LEN_NETSTR=netstring('')
|
||||
def _pack_normalized_children(children, writekey, deep_immutable=False):
|
||||
"""Take a dict that maps:
|
||||
children[unicode_nfc_name] = (IFileSystemNode, metadata_dict)
|
||||
and pack it into a single string, for use as the contents of the backing
|
||||
@ -208,9 +206,13 @@ def _pack_normalized_children(filenode, children, deep_immutable=False):
|
||||
as the pre-packed entry, which is faster than re-packing everything each
|
||||
time.
|
||||
|
||||
If writekey is provided then I will superencrypt the child's writecap with
|
||||
writekey.
|
||||
|
||||
If deep_immutable is True, I will require that all my children are deeply
|
||||
immutable, and will raise a MustBeDeepImmutableError if not.
|
||||
"""
|
||||
precondition((writekey is None) or isinstance(writekey, str), writekey)
|
||||
|
||||
has_aux = isinstance(children, AuxValueDict)
|
||||
entries = []
|
||||
@ -231,7 +233,7 @@ def _pack_normalized_children(filenode, children, deep_immutable=False):
|
||||
if rw_uri is None:
|
||||
rw_uri = ""
|
||||
assert isinstance(rw_uri, str), rw_uri
|
||||
|
||||
|
||||
# should be prevented by MustBeDeepImmutableError check above
|
||||
assert not (rw_uri and deep_immutable)
|
||||
|
||||
@ -239,9 +241,13 @@ def _pack_normalized_children(filenode, children, deep_immutable=False):
|
||||
if ro_uri is None:
|
||||
ro_uri = ""
|
||||
assert isinstance(ro_uri, str), ro_uri
|
||||
if writekey is not None:
|
||||
writecap = netstring(_encrypt_rw_uri(writekey, rw_uri))
|
||||
else:
|
||||
writecap = ZERO_LEN_NETSTR
|
||||
entry = "".join([netstring(name.encode("utf-8")),
|
||||
netstring(strip_prefix_for_ro(ro_uri, deep_immutable)),
|
||||
netstring(_encrypt_rw_uri(filenode, rw_uri)),
|
||||
writecap,
|
||||
netstring(simplejson.dumps(metadata))])
|
||||
entries.append(netstring(entry))
|
||||
return "".join(entries)
|
||||
@ -368,7 +374,7 @@ class DirectoryNode:
|
||||
|
||||
def _pack_contents(self, children):
|
||||
# expects children in the same format as _unpack_contents returns
|
||||
return _pack_normalized_children(self._node, children)
|
||||
return _pack_normalized_children(children, self._node.get_writekey())
|
||||
|
||||
def is_readonly(self):
|
||||
return self._node.is_readonly()
|
||||
|
@ -8,10 +8,6 @@ from allmydata.dirnode import DirectoryNode, pack_children
|
||||
from allmydata.unknown import UnknownNode
|
||||
from allmydata import uri
|
||||
|
||||
class DummyImmutableFileNode:
|
||||
def get_writekey(self):
|
||||
return None
|
||||
|
||||
class NodeMaker:
|
||||
implements(INodeMaker)
|
||||
|
||||
@ -47,7 +43,7 @@ class NodeMaker:
|
||||
# this returns synchronously. It starts with a "cap string".
|
||||
assert isinstance(writecap, (str, type(None))), type(writecap)
|
||||
assert isinstance(readcap, (str, type(None))), type(readcap)
|
||||
|
||||
|
||||
bigcap = writecap or readcap
|
||||
if not bigcap:
|
||||
# maybe the writecap was hidden because we're in a readonly
|
||||
@ -97,15 +93,14 @@ class NodeMaker:
|
||||
|
||||
def create_new_mutable_directory(self, initial_children={}):
|
||||
d = self.create_mutable_file(lambda n:
|
||||
pack_children(n, initial_children))
|
||||
pack_children(initial_children, n.get_writekey()))
|
||||
d.addCallback(self._create_dirnode)
|
||||
return d
|
||||
|
||||
def create_immutable_directory(self, children, convergence=None):
|
||||
if convergence is None:
|
||||
convergence = self.secret_holder.get_convergence_secret()
|
||||
n = DummyImmutableFileNode() # writekey=None
|
||||
packed = pack_children(n, children, deep_immutable=True)
|
||||
packed = pack_children(children, None, deep_immutable=True)
|
||||
uploadable = Data(packed, convergence)
|
||||
d = self.uploader.upload(uploadable, history=self.history)
|
||||
d.addCallback(lambda results: self.create_from_cap(None, results.uri))
|
||||
|
@ -1246,33 +1246,33 @@ class Packing(unittest.TestCase):
|
||||
|
||||
kids = self._make_kids(nm, ["imm", "lit", "write", "read",
|
||||
"dirwrite", "dirread"])
|
||||
packed = dirnode.pack_children(fn, kids, deep_immutable=False)
|
||||
packed = dirnode.pack_children(kids, fn.get_writekey(), deep_immutable=False)
|
||||
self.failUnlessIn("lit", packed)
|
||||
|
||||
kids = self._make_kids(nm, ["imm", "lit"])
|
||||
packed = dirnode.pack_children(fn, kids, deep_immutable=True)
|
||||
packed = dirnode.pack_children(kids, fn.get_writekey(), deep_immutable=True)
|
||||
self.failUnlessIn("lit", packed)
|
||||
|
||||
kids = self._make_kids(nm, ["imm", "lit", "write"])
|
||||
self.failUnlessRaises(dirnode.MustBeDeepImmutableError,
|
||||
dirnode.pack_children,
|
||||
fn, kids, deep_immutable=True)
|
||||
kids, fn.get_writekey(), deep_immutable=True)
|
||||
|
||||
# read-only is not enough: all children must be immutable
|
||||
kids = self._make_kids(nm, ["imm", "lit", "read"])
|
||||
self.failUnlessRaises(dirnode.MustBeDeepImmutableError,
|
||||
dirnode.pack_children,
|
||||
fn, kids, deep_immutable=True)
|
||||
kids, fn.get_writekey(), deep_immutable=True)
|
||||
|
||||
kids = self._make_kids(nm, ["imm", "lit", "dirwrite"])
|
||||
self.failUnlessRaises(dirnode.MustBeDeepImmutableError,
|
||||
dirnode.pack_children,
|
||||
fn, kids, deep_immutable=True)
|
||||
kids, fn.get_writekey(), deep_immutable=True)
|
||||
|
||||
kids = self._make_kids(nm, ["imm", "lit", "dirread"])
|
||||
self.failUnlessRaises(dirnode.MustBeDeepImmutableError,
|
||||
dirnode.pack_children,
|
||||
fn, kids, deep_immutable=True)
|
||||
kids, fn.get_writekey(), deep_immutable=True)
|
||||
|
||||
class FakeMutableFile:
|
||||
implements(IMutableFileNode)
|
||||
|
Loading…
x
Reference in New Issue
Block a user