def get_text_stanza_header(self): title = underlined_text("Fingerprint validation report", '=') title_target_server = underlined_text("Target server") title_target_certificate = underlined_text("SSL/TLS X.509 certificate") # ADDITION: Print information about the connection from which the # certificate was received. s = """{} Date and time: {} Validation of SSL/TLS X.509 certificate received from the target host using the Convergence protocol. {} * Host : '{}' * Listening port: {} {} * SHA1 fingerprint: {} """.format( title, self.creation.strftime('%Y-%m-%d, %H:%M:%S'), title_target_server, self.host, self.port, title_target_certificate, self.fingerprint ) return s
def action_delete_cache_entry(self): if self.args['host_target']['host'] is None: print('The target host needs to be specified through the --server \ argument.') return False rows = self.client.delete_cache_entry( self.args['host_target']['host'], self.args['host_target']['port'] ) print("""\ {} """.format(underlined_text("Deleted Fingerprint Cache Entry"))) if len(rows) < 1: print('No cached entries.') return True for row in rows: host, port, fp, expiration, timestamp = row timestamp = timestamp.strftime('%Y-%m-%d, %H.%M.%S') if expiration is None: expiration = '-' else: expiration = expiration.strftime('%Y-%m-%d, %H.%M.%S') print('{}, Exp: {}, {}:{}\t{}'.format( timestamp, expiration, host, port, fp )) return True
def action_list_notaries(self): """List notary entities known in the database.""" notaries = self.client.get_notaries() print("""\ {} """.format(underlined_text("Notaries in the Cuivre database"))) for n in notaries.values(): if n.enabled: enabled = 'Enabled' else: enabled = 'Disabled' if n.region is None: region = 'not specified' else: region = "'{}'".format(n.region) print("Id: {}, Name: '{}', Region: {}, Status: {}\n".format( str(n.id), n.name, region, enabled ) ) for j in n.hosts.values(): print(" Host: '{}', HTTP port: {}, SSL port: {}".format( j.host, str(j.http_port), str(j.ssl_port))) print("") return True
def action_show_cache(self): print("""\ {} """.format(underlined_text("Fingerprints Cache"))) db_rows = self.client.get_fingerprints_cache() rows = [] max_length = 0 # Create intermediate list for row in db_rows: host, port, fp, expiration, timestamp = row timestamp = timestamp.strftime('%Y-%m-%d, %H.%M.%S') if expiration is None: expiration = '-' else: expiration = expiration.strftime('%Y-%m-%d, %H.%M.%S') host_port = host + ":" + unicode(port) rows.append((timestamp, expiration, host_port, fp)) host_port_len = len(host_port) if host_port_len > max_length: max_length = host_port_len # Now print it for row in rows: timestamp, expiration, host_port, fp = row tabs_number = 1 + int(math.ceil((max_length - len(host_port)) / 8.0)) print('{}, Exp: {}, {}{}{}'.format( timestamp, expiration, host_port, '\t' * tabs_number, fp )) return True
def action_update_notaries(self): """List notary entities known in the database.""" # Disable callback printing connections to notaries. self.set_client_cb(CB_NOTARY_CONNECTION_START, None) notaries = self.client.database.get_notary_entities() print("""\ {} """.format(underlined_text("Updating Notaries"))) for n in notaries: print("Id: {}, Name: '{}'...".format(str(n.id), n.name)) self.client.update_notary(n.id, n.bundle_location) print("") # Re-enable callback printing connections to notaries. self.set_client_cb(CB_NOTARY_CONNECTION_START, cb_notary_connection_start) return True
def get_text(self): if self.from_cache: # A cached result is always a successful verification. title = underlined_text("Certificate fingerprint validation", "=") s = """{} Validation of SSL/TLS X.509 certificate fingerprint: {} For server host {} on port {}. Successful certificate verification from result cached on {} UTC. """.format( title, self.fingerprint, self.server_host, self.server_port, self.cache_date_time ) return s
def get_text_stanza_convergence(self): stanza = self.convergence_stanza s = '' if stanza.anonymization: s += """ * Anonymization of queries through relay notary entity: \'{}\'. """.format(stanza.relay_notary_entity_name) for i in stanza.notary_connections: notary_entity_name = i connections = stanza.notary_connections[i]['connections'] z = "".join(("Connection to notary '", notary_entity_name, "'")) z = underlined_text(z) z = "".join(("\n", z, "\n")) if not stanza.notary_connections[i]['connection']: z += """ No established connections. """ s += z continue established_connection = \ connections.pop(stanza.notary_connections[i]['connection']) c = established_connection z += """ * Notary host: * Hostname: '{}' * Port : {} """.format( c['notary_host']['host'], c['notary_host']['port'] ) if stanza.anonymization: z += """ * Relay host: * Hostname: '{}' * Port : {} """.format( c['relay_host']['host'], c['relay_host']['port'] ) z += """ * Connection: * Connection Id : {} * X.509 certificate SHA1 fingerprint: {} * SSL/TLS protocol version : {} * Adopted cipher suite : {} """.format( stanza.notary_connections[i]['connection'], c['notary_host']['notary_fingerprint'], c['notary_host']['ssl_protocol'], c['notary_host']['ssl_cipher_suite'] ) # Response stanza status_code = c['notary_host']['response_code'] if status_code == cuivre.http.HTTP_STATUS_CODE_OK: r = '{} fingerprint verified'.format( cuivre.http.HTTP_STATUS_CODE_OK) elif status_code == cuivre.http.HTTP_STATUS_CODE_CONFLICT: r = '{} fingerprint *NOT* verified'.format( cuivre.http.HTTP_STATUS_CODE_CONFLICT) elif status_code == cuivre.http.HTTP_STATUS_CODE_SEE_OTHER: r = '{} cannot verify fingerprint'.format( cuivre.http.HTTP_STATUS_CODE_SEE_OTHER) elif status_code == cuivre.http.HTTP_STATUS_CODE_BAD_REQUEST: r = '{} incomplete verification request'.format( cuivre.http.HTTP_STATUS_CODE_BAD_REQUEST) elif status_code == cuivre.http.HTTP_STATUS_SERVICE_UNAVAILABLE: r = '{} notary internal error'.format( cuivre.http.HTTP_STATUS_SERVICE_UNAVAILABLE) else: r = 'undefined' vsign = '*failed* verification' if c['notary_host']['signature_verification'] == True: vsign = 'verified' z += """ * Response: * Notary response : {}. """.format(r) if status_code not in (cuivre.http.HTTP_STATUS_CODE_OK, cuivre.http.HTTP_STATUS_CODE_CONFLICT): s = '{}{}'.format(s, z) continue z += """\ * Observed fingerprint : {} * Response data signature : {} """.format(c['notary_host']['observed_fingerprint'], vsign) s = '{}{}'.format(s, z) # Convergence policy and its application. policy_name = 'None' if stanza.policy == cuivre.POLICY_ONE: policy_name = 'require one notary to agree.' elif stanza.policy == cuivre.POLICY_MAJORITY: policy_name = 'require notary majority.' elif stanza.policy == cuivre.POLICY_UNANIMITY: policy_name = 'require unanimity among notaries.' validation_msg = 'Failure' if stanza.validation == True: validation_msg = 'Success' s += """ Applied Convergence policy : {} Fingerprint validation as per Convergence: {} """.format(policy_name, validation_msg) return s