Ticket #11045: 0002-Fixed-descriptor-validation-bug-introduced-in-refact.patch

File 0002-Fixed-descriptor-validation-bug-introduced-in-refact.patch, 6.6 KB (added by NickHopper, 5 years ago)
  • stem/descriptor/__init__.py

    From da618f5fb90dd3c16bc6d345510cc0ec14657076 Mon Sep 17 00:00:00 2001
    From: Nick Hopper <hopper@cs.umn.edu>
    Date: Thu, 24 Jul 2014 14:11:23 -0500
    Subject: [PATCH 2/2] Fixed descriptor validation bug introduced in
     refactoring
    
    ---
     stem/descriptor/__init__.py          |   23 +++++++++++------------
     stem/descriptor/networkstatus.py     |   13 ++++---------
     stem/descriptor/server_descriptor.py |   12 ++++++------
     3 files changed, 21 insertions(+), 27 deletions(-)
    
    diff --git a/stem/descriptor/__init__.py b/stem/descriptor/__init__.py
    index a8dfe60..915f499 100644
    a b class Descriptor(object): 
    380380    raw_doc = str(self)
    381381    start_tok, end_tok = self.sig_tokens()
    382382    begin = raw_doc.find(start_tok)
    383     sig_begin = raw_doc.find(end_tok) 
     383    sig_begin = raw_doc.find(end_tok)
    384384    doc_end = sig_begin + len(end_tok)
    385385    if begin < 0 or sig_begin < begin:
    386386        raise ValueError('unable to extract signable network status document')
    class Descriptor(object): 
    391391    return digest_func(sbytes).hexdigest().upper()
    392392
    393393
    394      
    395 
    396394def _get_bytes_field(keyword, content):
    397395  """
    398396  Provides the value corresponding to the given keyword. This is handy to fetch
    def _get_bytes(block_content): 
    616614    base64_object = ''.join(block_content.split('\n')[1:-1])
    617615    return base64.b64decode(stem.util.str_tools._to_bytes(base64_object))
    618616
     617
    619618def check_signature(signed_digest, sigstr, keystr):
    620619    from Crypto.Util.number import bytes_to_long, long_to_bytes
    621620    from Crypto.Util import asn1
    def check_signature(signed_digest, sigstr, keystr): 
    632631    # convert the int to a byte array.
    633632    decrypted_bytes = long_to_bytes(decrypted_int, blocksize)
    634633    ############################################################################
    635     ## The decrypted bytes should have a structure exactly along these lines.
    636     ## 1 byte  - [null '\x00']
    637     ## 1 byte  - [block type identifier '\x01'] - Should always be 1
    638     ## N bytes - [padding '\xFF' ]
    639     ## 1 byte  - [separator '\x00' ]
    640     ## M bytes - [message]
    641     ## Total   - 128 bytes
    642     ## More info here http://www.ietf.org/rfc/rfc2313.txt
    643     ##                esp the Notes in section 8.1
     634    # # The decrypted bytes should have a structure exactly along these lines.
     635    # # 1 byte  - [null '\x00']
     636    # # 1 byte  - [block type identifier '\x01'] - Should always be 1
     637    # # N bytes - [padding '\xFF' ]
     638    # # 1 byte  - [separator '\x00' ]
     639    # # M bytes - [message]
     640    # # Total   - 128 bytes
     641    # # More info here http://www.ietf.org/rfc/rfc2313.txt
     642    # #                esp the Notes in section 8.1
    644643    ############################################################################
    645644    try:
    646645      if decrypted_bytes.index('\x00\x01') != 0:
  • stem/descriptor/networkstatus.py

    diff --git a/stem/descriptor/networkstatus.py b/stem/descriptor/networkstatus.py
    index a986f4f..4ec25ef 100644
    a b class NetworkStatusDocumentV3(NetworkStatusDocument): 
    604604    signing_authorities = set()
    605605    for sig in sigs:
    606606        doc_digest = self.nsdoc_digest(sig.sig_digest_func())
    607         # find cert corresponding to authority       
     607        # find cert corresponding to authority
    608608        # check signature and cert validity
    609609        for c in certs:
    610610            if sig.key_digest == c.signing_key_digest() and sig.identity == c.fingerprint:
    class NetworkStatusDocumentV3(NetworkStatusDocument): 
    620620        raise ValueError('consensus not signed by enough distinct, known directory authorities')
    621621
    622622
    623 
    624  
    625 
    626623class _DocumentHeader(object):
    627624  def __init__(self, document_file, validate, default_params):
    628625    self.version = None
    class KeyCertificate(Descriptor): 
    14641461    # - the fingerprint matches the digest of the identity key
    14651462    # - the cross-certification is a valid signature on the identity key with the signing key, and
    14661463    # - the key-certification is a valid signature on the document with the identity key, and
    1467     # - optionally, if the check_date is between the published and expires dates 
     1464    # - optionally, if the check_date is between the published and expires dates
    14681465    # check fingerprint
    14691466    id_key_bytes = _get_bytes(self.identity_key)
    14701467    id_fingerprint = KeyCertificate.idkey_digest_func(id_key_bytes).hexdigest().upper()
    1471     if id_fingerprint != self.fingerprint: 
     1468    if id_fingerprint != self.fingerprint:
    14721469        raise ValueError('Certificate identity key does not match supplied fingerprint')
    14731470    # check cross-certification
    14741471    if not check_signature(self.fingerprint, self.crosscert, self.signing_key):
    class KeyCertificate(Descriptor): 
    14821479        if check_date > self.expires:
    14831480            raise ValueError('identity certificate was expired on ' + str(check_date))
    14841481        if check_date < self.published:
    1485             raise ValueError('identity certificate was not yet published on ' + str(check_date))   
     1482            raise ValueError('identity certificate was not yet published on ' + str(check_date))
    14861483    # no checks failed, the certificate passes
    14871484    return True
    1488      
    1489 
    14901485
    14911486
    14921487class DocumentSignature(object):
  • stem/descriptor/server_descriptor.py

    diff --git a/stem/descriptor/server_descriptor.py b/stem/descriptor/server_descriptor.py
    index e5e074d..58e3092 100644
    a b etc). This information is provided from a few sources... 
    3333"""
    3434
    3535import base64
    36 import codecs
     36# import codecs
    3737import datetime
    3838import hashlib
    3939import re
    class RelayDescriptor(ServerDescriptor): 
    719719        log.warn('Signing key hash: %s != fingerprint: %s' % (key_der_as_hash, self.fingerprint.lower()))
    720720        raise ValueError('Fingerprint does not match hash')
    721721
    722     self._verify_digest(key_as_bytes)
     722    self._verify_digest(self.signing_key)
    723723
    724   def _verify_digest(self, key_as_der):
     724  def _verify_digest(self, key_block):
    725725    # check that our digest matches what was signed
    726726
    727727    if not stem.prereq.is_crypto_available():
    728728      return
    729    
    730     stem.descriptor.check_signature(self.digest(),self.signature,key_as_der)
     729
     730    stem.descriptor.check_signature(self.digest(),self.signature,key_block)
    731731
    732732  def _parse(self, entries, validate):
    733733    entries = dict(entries)  # shallow copy since we're destructive
    class RelayDescriptor(ServerDescriptor): 
    761761        del entries['router-signature']
    762762
    763763    ServerDescriptor._parse(self, entries, validate)
    764    
     764
    765765  def sig_tokens(self):
    766766    return ('router ','\nrouter-signature\n')
    767767