Commit 6376f720 authored by Lucas Carvalho's avatar Lucas Carvalho

Allows to check multi trusted certificates.

Actually, the user can configure the buildout.cfg and set multiples
certificates files.

It means that libnetworkcache must be able to check if the signature
which comes from shadir is trustable or not, based on these certificates.

A given signature can not appear twice in the same directory-key, if it
happens a DiretoryNotFound error must be raised.
parent c6f62c94
...@@ -24,7 +24,7 @@ import urlparse ...@@ -24,7 +24,7 @@ import urlparse
import M2Crypto import M2Crypto
_MARKER = (None, '') _MARKER = ([], [''], None, '')
class NetworkcacheClient(object): class NetworkcacheClient(object):
...@@ -53,7 +53,8 @@ class NetworkcacheClient(object): ...@@ -53,7 +53,8 @@ class NetworkcacheClient(object):
return return_dict return return_dict
def __init__(self, shacache, shadir, def __init__(self, shacache, shadir,
signature_private_file=None, signature_public_file=None): signature_private_key_file=None,
signature_certificate_file_list=None):
''' Set the initial values. ''' ''' Set the initial values. '''
# ShaCache Properties # ShaCache Properties
for k, v in self.parseUrl(shacache).iteritems(): for k, v in self.parseUrl(shacache).iteritems():
...@@ -64,8 +65,8 @@ class NetworkcacheClient(object): ...@@ -64,8 +65,8 @@ class NetworkcacheClient(object):
for k, v in self.parseUrl(shadir).iteritems(): for k, v in self.parseUrl(shadir).iteritems():
setattr(self, 'shadir_%s' % k, v) setattr(self, 'shadir_%s' % k, v)
self.signature_private_file = signature_private_file self.signature_private_key_file = signature_private_key_file
self.signature_public_file = signature_public_file self.signature_certificate_file_list = signature_certificate_file_list
def upload(self, file_descriptor, directory_key=None, **kw): def upload(self, file_descriptor, directory_key=None, **kw):
''' Upload the file to the server. ''' Upload the file to the server.
...@@ -163,52 +164,56 @@ class NetworkcacheClient(object): ...@@ -163,52 +164,56 @@ class NetworkcacheClient(object):
if result.status != 200: if result.status != 200:
raise DirectoryNotFound(result.read()) raise DirectoryNotFound(result.read())
# Filtering...
data_list = json.loads(data) data_list = json.loads(data)
if len(data_list) > 1 and self.signature_public_file in _MARKER: if len(data_list) > 1 and self.signature_certificate_file_list in _MARKER:
raise DirectoryNotFound('Too many entries for a given directory. ' \ raise DirectoryNotFound('Too many entries for a given directory. ' \
'Directory: %s. Entries: %s.' % (directory_key, str(data_list))) 'Directory: %s. Entries: %s.' % (directory_key, str(data_list)))
sha512 = None if self.signature_certificate_file_list not in _MARKER:
if self.signature_public_file not in _MARKER: method = self._verifySignatureInCertificateList
for information_dict, signature in data_list: data_list = filter(lambda x: method(x[1]), data_list)
if self._verifySignature(signature): if len(data_list) > 1:
sha512 = information_dict.get('sha512') raise DirectoryNotFound('Too many entries for a given key. ' \
break 'Directory: %s. Entries: %s.' %(directory_key, str(data_list)))
if sha512 is None:
raise DirectoryNotFound('Could not find a trustable entry.')
else: if not data_list:
information_dict, signature = data_list[0] raise DirectoryNotFound('Could not find a trustable entry.')
sha512 = information_dict.get('sha512')
information_dict, signature = data_list[0]
sha512 = information_dict.get('sha512')
return self.download(sha512) return self.download(sha512)
def _getSignatureString(self): def _getSignatureString(self):
""" """
Return the signature based on certification file. Return the signature based on certification file.
""" """
if self.signature_private_file in _MARKER: if self.signature_private_key_file in _MARKER:
return '' return ''
SignEVP = M2Crypto.EVP.load_key(self.signature_private_file) SignEVP = M2Crypto.EVP.load_key(self.signature_private_key_file)
SignEVP.sign_init() SignEVP.sign_init()
SignEVP.sign_update('') SignEVP.sign_update('')
StringSignature = SignEVP.sign_final() StringSignature = SignEVP.sign_final()
return StringSignature.encode('base64') return StringSignature.encode('base64')
def _verifySignature(self, signature_string): def _verifySignatureInCertificateList(self, signature_string):
""" """
Check if the signature is valid. Returns true if it can find any valid certificate.
""" """
if self.signature_public_file in _MARKER: if self.signature_certificate_file_list in _MARKER:
return 0 return 0
PubKey = M2Crypto.X509.load_cert(self.signature_public_file) for certificate_path in self.signature_certificate_file_list:
VerifyEVP = M2Crypto.EVP.PKey() PubKey = M2Crypto.X509.load_cert(certificate_path)
VerifyEVP.assign_rsa(PubKey.get_pubkey().get_rsa()) VerifyEVP = M2Crypto.EVP.PKey()
VerifyEVP.verify_init() VerifyEVP.assign_rsa(PubKey.get_pubkey().get_rsa())
VerifyEVP.verify_update('') VerifyEVP.verify_init()
return VerifyEVP.verify_final(signature_string.decode('base64')) VerifyEVP.verify_update('')
if VerifyEVP.verify_final(signature_string.decode('base64')):
return True
return False
class DirectoryNotFound(Exception): class DirectoryNotFound(Exception):
......
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