def process_entries(entry_queue, output_queue, match_callback): stopped = False total_processed = 0 while not stopped: count, entry = entry_queue.get() if entry == _STOP_WORKER: stopped = True # Each worker signals when they've picked up their # "STOP_WORKER" message. output_queue.put(QueueMessage( _WORKER_STOPPED, certificates_scanned=total_processed)) else: entry_response = client_pb2.EntryResponse() entry_response.ParseFromString(entry) parsed_entry = entry_decoder.decode_entry(entry_response) ts_entry = parsed_entry.merkle_leaf.timestamped_entry total_processed += 1 c = None if ts_entry.entry_type == client_pb2.X509_ENTRY: der_cert = ts_entry.asn1_cert else: # The original, signed precertificate. der_cert = (parsed_entry.extra_data.precert_chain_entry.pre_certificate) try: c = cert.Certificate(der_cert) except error.Error as e: try: c = cert.Certificate(der_cert, strict_der=False) except error.Error as e: output_queue.put(QueueMessage( _ERROR_PARSING_ENTRY, "Error parsing entry %d:\n%s" % (count, e))) else: output_queue.put(QueueMessage( _ERROR_PARSING_ENTRY, "Entry %d failed strict parsing:\n%s" % (count, c))) except Exception as e: print "Unknown parsing failure for entry %d:\n%s" % ( count, e) traceback.print_exc() output_queue.put(QueueMessage( _ERROR_PARSING_ENTRY, "Entry %d failed parsing with an unknown error:\n%s" % (count, e))) if c: match_result = match_callback( c, ts_entry.entry_type, parsed_entry.extra_data, count) if match_result: output_queue.put(QueueMessage( _ENTRY_MATCHING, "Entry %d:\n%s" % (count, c), matcher_output=match_result)) if not total_processed % _BATCH_SIZE: output_queue.put(QueueMessage( _PROGRESS_REPORT, "Scanned %d entries" % total_processed, certificates_scanned=_BATCH_SIZE))
def _scan_der_cert(der_certs, checks): current = -1 try: result = [] for log_index, der_cert, der_chain in der_certs: current = log_index partial_result = [] strict_failure = False try: certificate = cert.Certificate(der_cert) except error.Error as e: try: certificate = cert.Certificate(der_cert, strict_der=False) except error.Error as e: partial_result.append(asn1.All()) strict_failure = True else: if isinstance(e, error.ASN1IllegalCharacter): partial_result.append( asn1.Strict(reason=e.args[0], details=(e.string, e.index))) else: partial_result.append(asn1.Strict(reason=str(e))) if not strict_failure: for check in checks: partial_result += check.check(certificate) or [] desc = cert_desc.from_cert(certificate, partial_result) else: desc = certificate_pb2.X509Description() desc.der = der_cert desc.sha256_hash = hashlib.sha256(der_cert).digest() try: root = cert.Certificate(der_chain[-1], strict_der=False) except error.Error: pass else: for iss in [ (type_.short_name, cert_desc.to_unicode('.'.join( cert_desc.process_name(value.human_readable())))) for type_, value in root.issuer() ]: proto_iss = desc.root_issuer.add() proto_iss.type, proto_iss.value = iss result.append((desc, log_index, partial_result)) return result except Exception: _, exception, exception_traceback = sys.exc_info() exception_traceback = traceback.format_exc(exception_traceback) raise PoolException((exception, exception_traceback, der_certs[0][0], der_certs[-1][0], current))
def test_issuer_and_root_issuer_populated_from_chain(self): self.assertEqual(3, len(CHAIN_DERS)) report = self.CertificateReportBase() report.scan_der_certs([(0, CHAIN_DERS[0], CHAIN_DERS[1:], client_pb2.X509_ENTRY)]) results = report.report() self.assertEqual(len(results), 1) issuer_cert = cert_desc.from_cert(cert.Certificate(CHAIN_DERS[1])) root_cert = cert_desc.from_cert(cert.Certificate(CHAIN_DERS[2])) self.assertEqual(readable_dn(results[0].issuer), 'C=US,O=Google Inc,CN=Google Internet Authority') self.assertEqual( readable_dn(results[0].root_issuer), 'C=US,O=Equifax,OU=Equifax Secure Certificate Authority')
def test_issuer_public_key_populated_from_chain(self): # Verify the test data is what is expected for this unit test. self.assertEqual(3, len(CHAIN_DERS)) self.assertEqual( cert.Certificate(CHAIN_DERS[1]).key_hash(hashfunc="sha256").encode('hex'), 'b6b95432abae57fe020cb2b74f4f9f9173c8c708afc9e732ace23279047c6d05') report = self.CertificateReportBase([]) report.scan_der_certs([(0, CHAIN_DERS[0], CHAIN_DERS[1:], client_pb2.X509_ENTRY)]) result = report.report() self.assertEqual(len(sum(result.values(), [])), 0) certs = report.certs() self.assertEqual(len(certs), 1) self.assertEqual(certs[0].issuer_pk_sha256_hash.encode('hex'), 'b6b95432abae57fe020cb2b74f4f9f9173c8c708afc9e732ace23279047c6d05')
def test_to_der(self): with open(self.get_file(self._DER_FILE), "rb") as f: der_string = f.read() c = cert.Certificate(der_string) self.assertEqual(der_string, c.to_der())
def _scan_der_cert(der_certs): current = -1 result = [] for log_index, der_cert, der_chain, entry_type in der_certs: try: current = log_index certificate = None strict_failure = False try: certificate = cert.Certificate(der_cert) except error.Error as e: try: certificate = cert.Certificate(der_cert, strict_der=False) except error.Error as e: strict_failure = True if not strict_failure: desc = cert_desc.from_cert(certificate) else: desc = certificate_pb2.X509Description() desc.der = der_cert desc.sha256_hash = hashlib.sha256(der_cert).digest() desc.entry_type = entry_type root = None if der_chain: try: issuer = cert.Certificate(der_chain[0], strict_der=False) except error.Error: pass else: desc.issuer_pk_sha256_hash = issuer.key_hash( hashfunc="sha256") try: root = cert.Certificate(der_chain[-1], strict_der=False) except error.Error: pass else: # No chain implies this is a root certificate. # Note that certificate may be None. root = certificate if root: for iss in [ (type_.short_name, cert_desc.to_unicode('.'.join( cert_desc.process_name(value.human_readable())))) for type_, value in root.issuer() ]: proto_iss = desc.root_issuer.add() proto_iss.type, proto_iss.value = iss result.append((desc, log_index)) except: batch_start_index, batch_end_index = (der_certs[0][0], der_certs[-1][0]) logging.exception( "Error scanning certificate %d in batch <%d, %d> - it will " "be excluded from the scan results", current, batch_start_index, batch_end_index) return result