mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2025-06-23 09:15:32 +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:
@ -171,12 +171,10 @@ class Adder:
|
|||||||
new_contents = self.node._pack_contents(children)
|
new_contents = self.node._pack_contents(children)
|
||||||
return new_contents
|
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)
|
salt = hashutil.mutable_rwcap_salt_hash(rw_uri)
|
||||||
key = hashutil.mutable_rwcap_key_hash(salt, writekey)
|
key = hashutil.mutable_rwcap_key_hash(salt, writekey)
|
||||||
cryptor = AES(key)
|
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
|
# The MAC is not checked by readers in Tahoe >= 1.3.0, but we still
|
||||||
# produce it for the sake of older readers.
|
# produce it for the sake of older readers.
|
||||||
|
|
||||||
|
def pack_children(childrenx, writekey, deep_immutable=False):
|
||||||
def pack_children(filenode, childrenx, deep_immutable=False):
|
|
||||||
# initial_children must have metadata (i.e. {} instead of None)
|
# initial_children must have metadata (i.e. {} instead of None)
|
||||||
children = {}
|
children = {}
|
||||||
for (namex, (node, metadata)) in childrenx.iteritems():
|
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)
|
"directory creation requires metadata to be a dict, not None", metadata)
|
||||||
children[normalize(namex)] = (node, 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:
|
"""Take a dict that maps:
|
||||||
children[unicode_nfc_name] = (IFileSystemNode, metadata_dict)
|
children[unicode_nfc_name] = (IFileSystemNode, metadata_dict)
|
||||||
and pack it into a single string, for use as the contents of the backing
|
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
|
as the pre-packed entry, which is faster than re-packing everything each
|
||||||
time.
|
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
|
If deep_immutable is True, I will require that all my children are deeply
|
||||||
immutable, and will raise a MustBeDeepImmutableError if not.
|
immutable, and will raise a MustBeDeepImmutableError if not.
|
||||||
"""
|
"""
|
||||||
|
precondition((writekey is None) or isinstance(writekey, str), writekey)
|
||||||
|
|
||||||
has_aux = isinstance(children, AuxValueDict)
|
has_aux = isinstance(children, AuxValueDict)
|
||||||
entries = []
|
entries = []
|
||||||
@ -239,9 +241,13 @@ def _pack_normalized_children(filenode, children, deep_immutable=False):
|
|||||||
if ro_uri is None:
|
if ro_uri is None:
|
||||||
ro_uri = ""
|
ro_uri = ""
|
||||||
assert isinstance(ro_uri, str), 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")),
|
entry = "".join([netstring(name.encode("utf-8")),
|
||||||
netstring(strip_prefix_for_ro(ro_uri, deep_immutable)),
|
netstring(strip_prefix_for_ro(ro_uri, deep_immutable)),
|
||||||
netstring(_encrypt_rw_uri(filenode, rw_uri)),
|
writecap,
|
||||||
netstring(simplejson.dumps(metadata))])
|
netstring(simplejson.dumps(metadata))])
|
||||||
entries.append(netstring(entry))
|
entries.append(netstring(entry))
|
||||||
return "".join(entries)
|
return "".join(entries)
|
||||||
@ -368,7 +374,7 @@ class DirectoryNode:
|
|||||||
|
|
||||||
def _pack_contents(self, children):
|
def _pack_contents(self, children):
|
||||||
# expects children in the same format as _unpack_contents returns
|
# 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):
|
def is_readonly(self):
|
||||||
return self._node.is_readonly()
|
return self._node.is_readonly()
|
||||||
|
@ -8,10 +8,6 @@ from allmydata.dirnode import DirectoryNode, pack_children
|
|||||||
from allmydata.unknown import UnknownNode
|
from allmydata.unknown import UnknownNode
|
||||||
from allmydata import uri
|
from allmydata import uri
|
||||||
|
|
||||||
class DummyImmutableFileNode:
|
|
||||||
def get_writekey(self):
|
|
||||||
return None
|
|
||||||
|
|
||||||
class NodeMaker:
|
class NodeMaker:
|
||||||
implements(INodeMaker)
|
implements(INodeMaker)
|
||||||
|
|
||||||
@ -97,15 +93,14 @@ class NodeMaker:
|
|||||||
|
|
||||||
def create_new_mutable_directory(self, initial_children={}):
|
def create_new_mutable_directory(self, initial_children={}):
|
||||||
d = self.create_mutable_file(lambda n:
|
d = self.create_mutable_file(lambda n:
|
||||||
pack_children(n, initial_children))
|
pack_children(initial_children, n.get_writekey()))
|
||||||
d.addCallback(self._create_dirnode)
|
d.addCallback(self._create_dirnode)
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def create_immutable_directory(self, children, convergence=None):
|
def create_immutable_directory(self, children, convergence=None):
|
||||||
if convergence is None:
|
if convergence is None:
|
||||||
convergence = self.secret_holder.get_convergence_secret()
|
convergence = self.secret_holder.get_convergence_secret()
|
||||||
n = DummyImmutableFileNode() # writekey=None
|
packed = pack_children(children, None, deep_immutable=True)
|
||||||
packed = pack_children(n, children, deep_immutable=True)
|
|
||||||
uploadable = Data(packed, convergence)
|
uploadable = Data(packed, convergence)
|
||||||
d = self.uploader.upload(uploadable, history=self.history)
|
d = self.uploader.upload(uploadable, history=self.history)
|
||||||
d.addCallback(lambda results: self.create_from_cap(None, results.uri))
|
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",
|
kids = self._make_kids(nm, ["imm", "lit", "write", "read",
|
||||||
"dirwrite", "dirread"])
|
"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)
|
self.failUnlessIn("lit", packed)
|
||||||
|
|
||||||
kids = self._make_kids(nm, ["imm", "lit"])
|
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)
|
self.failUnlessIn("lit", packed)
|
||||||
|
|
||||||
kids = self._make_kids(nm, ["imm", "lit", "write"])
|
kids = self._make_kids(nm, ["imm", "lit", "write"])
|
||||||
self.failUnlessRaises(dirnode.MustBeDeepImmutableError,
|
self.failUnlessRaises(dirnode.MustBeDeepImmutableError,
|
||||||
dirnode.pack_children,
|
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
|
# read-only is not enough: all children must be immutable
|
||||||
kids = self._make_kids(nm, ["imm", "lit", "read"])
|
kids = self._make_kids(nm, ["imm", "lit", "read"])
|
||||||
self.failUnlessRaises(dirnode.MustBeDeepImmutableError,
|
self.failUnlessRaises(dirnode.MustBeDeepImmutableError,
|
||||||
dirnode.pack_children,
|
dirnode.pack_children,
|
||||||
fn, kids, deep_immutable=True)
|
kids, fn.get_writekey(), deep_immutable=True)
|
||||||
|
|
||||||
kids = self._make_kids(nm, ["imm", "lit", "dirwrite"])
|
kids = self._make_kids(nm, ["imm", "lit", "dirwrite"])
|
||||||
self.failUnlessRaises(dirnode.MustBeDeepImmutableError,
|
self.failUnlessRaises(dirnode.MustBeDeepImmutableError,
|
||||||
dirnode.pack_children,
|
dirnode.pack_children,
|
||||||
fn, kids, deep_immutable=True)
|
kids, fn.get_writekey(), deep_immutable=True)
|
||||||
|
|
||||||
kids = self._make_kids(nm, ["imm", "lit", "dirread"])
|
kids = self._make_kids(nm, ["imm", "lit", "dirread"])
|
||||||
self.failUnlessRaises(dirnode.MustBeDeepImmutableError,
|
self.failUnlessRaises(dirnode.MustBeDeepImmutableError,
|
||||||
dirnode.pack_children,
|
dirnode.pack_children,
|
||||||
fn, kids, deep_immutable=True)
|
kids, fn.get_writekey(), deep_immutable=True)
|
||||||
|
|
||||||
class FakeMutableFile:
|
class FakeMutableFile:
|
||||||
implements(IMutableFileNode)
|
implements(IMutableFileNode)
|
||||||
|
Reference in New Issue
Block a user