Commit 9658123b authored by Julien Muchembled's avatar Julien Muchembled

Refactor select/select_generic and make select_generic filtering lazily

parent 3266582f
...@@ -22,8 +22,6 @@ import urllib2 ...@@ -22,8 +22,6 @@ import urllib2
import urlparse import urlparse
from OpenSSL import crypto from OpenSSL import crypto
# XXX: code between select/select_generic must be factored
# Timeout here is about timeout to CONNECT to the server (socket initialization then server answers actual data), not to retrieve/send informations. # Timeout here is about timeout to CONNECT to the server (socket initialization then server answers actual data), not to retrieve/send informations.
# To be clear: it is NOT about uploading/downloading data, but about time to connect to the server, then time that server takes to start answering. # To be clear: it is NOT about uploading/downloading data, but about time to connect to the server, then time that server takes to start answering.
TIMEOUT = 60 TIMEOUT = 60
...@@ -242,38 +240,24 @@ class NetworkcacheClient(object): ...@@ -242,38 +240,24 @@ class NetworkcacheClient(object):
''' Download a file from shacache by selecting the entry in shadir ''' Download a file from shacache by selecting the entry in shadir
Raise DirectoryNotFound if no trustable file is found. Raise DirectoryNotFound if no trustable file is found.
''' '''
url = urljoin(self.shadir_url, key) for information_json, signature in self.select_generic(key,
request = urllib2.Request(url=url, data=None, self.signature_certificate_list):
headers=self.shadir_header_dict) break
data = urllib2.urlopen(request, timeout=TIMEOUT).read() else:
# Filtering...
try:
data_list = json.loads(data)
except Exception:
raise DirectoryNotFound('It was impossible to parse json response:\n%s'%
traceback.format_exc())
if self.signature_certificate_list:
data_list = [data for data in data_list
if self._verifySignatureInCertificateList(*data)]
if not data_list:
raise DirectoryNotFound('Could not find a trustable entry.') raise DirectoryNotFound('Could not find a trustable entry.')
information_json, signature = data_list[0]
try: try:
information_dict = json.loads(information_json) information_dict = json.loads(information_json)
except Exception: except Exception:
raise DirectoryNotFound('It was impossible to parse json-in-json ' raise DirectoryNotFound('Failed to parse json-in-json response:\n%s'
'response:\n%s' % traceback.format_exc()) % traceback.format_exc())
try: try:
sha512 = information_dict.get('sha512') sha512 = information_dict['sha512']
except Exception: except Exception:
raise DirectoryNotFound('It was impossible to fetch sha512 from ' raise DirectoryNotFound('No sha512 in directory response (%r):\n%s'
'directory response (%r):\n%s' % (information_dict, % (information_dict, traceback.format_exc()))
traceback.format_exc()))
return self.download(sha512) return self.download(sha512)
def select_generic(self, key): def select_generic(self, key, filter=True):
''' Select trustable entries from shadir. ''' Select trustable entries from shadir.
''' '''
url = urljoin(self.shadir_url, key) url = urljoin(self.shadir_url, key)
...@@ -283,10 +267,12 @@ class NetworkcacheClient(object): ...@@ -283,10 +267,12 @@ class NetworkcacheClient(object):
try: try:
data_list = json.loads(data) data_list = json.loads(data)
except Exception: except Exception:
raise DirectoryNotFound('It was impossible to parse json response:\n%s' % raise DirectoryNotFound('Failed to parse json response:\n%s'
traceback.format_exc()) % traceback.format_exc())
return [data for data in data_list if filter:
if self._verifySignatureInCertificateList(*data)] return (data for data in data_list
if self._verifySignatureInCertificateList(*data))
return data_list
def _getSignatureString(self, content): def _getSignatureString(self, content):
""" """
......
...@@ -477,7 +477,7 @@ class OnlineTest(OnlineMixin, unittest.TestCase): ...@@ -477,7 +477,7 @@ class OnlineTest(OnlineMixin, unittest.TestCase):
with open(os.path.join(self.tree, 'shadir', key), 'w') as f: with open(os.path.join(self.tree, 'shadir', key), 'w') as f:
# now remove the entry from shacache # now remove the entry from shacache
f.write('This is not a json.') f.write('This is not a json.')
self.assertDirectoryNotFound('It was impossible to parse json response', self.assertDirectoryNotFound('Failed to parse json response',
nc.select, key) nc.select, key)
def test_select_json_no_in_json_response(self): def test_select_json_no_in_json_response(self):
...@@ -491,9 +491,8 @@ class OnlineTest(OnlineMixin, unittest.TestCase): ...@@ -491,9 +491,8 @@ class OnlineTest(OnlineMixin, unittest.TestCase):
with open(os.path.join(self.tree, 'shadir', key), 'w') as f: with open(os.path.join(self.tree, 'shadir', key), 'w') as f:
# now remove the entry from shacache # now remove the entry from shacache
f.write(json.dumps([['This is not a json.', 'signature']])) f.write(json.dumps([['This is not a json.', 'signature']]))
self.assertDirectoryNotFound( self.assertDirectoryNotFound('Failed to parse json-in-json response',
'It was impossible to parse json-in-json response', nc.select, key)
nc.select, key)
def test_select_json_in_json_no_dict(self): def test_select_json_in_json_no_dict(self):
key = 'somekey' + str(random.random()) key = 'somekey' + str(random.random())
...@@ -506,9 +505,8 @@ class OnlineTest(OnlineMixin, unittest.TestCase): ...@@ -506,9 +505,8 @@ class OnlineTest(OnlineMixin, unittest.TestCase):
with open(os.path.join(self.tree, 'shadir', key), 'w') as f: with open(os.path.join(self.tree, 'shadir', key), 'w') as f:
# now remove the entry from shacache # now remove the entry from shacache
f.write(json.dumps([[json.dumps('This is a string'), 'signature']])) f.write(json.dumps([[json.dumps('This is a string'), 'signature']]))
self.assertDirectoryNotFound( self.assertDirectoryNotFound('No sha512 in directory response',
'It was impossible to fetch sha512 from directory response', nc.select, key)
nc.select, key)
def test_select_signed_content_server_hacked(self): def test_select_signed_content_server_hacked(self):
key = 'somekey' + str(random.random()) key = 'somekey' + str(random.random())
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment