HTTP/HTTPS connectivity validator
| 32 | urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) |
| 33 | |
| 34 | class HTTPValidator: |
| 35 | """HTTP/HTTPS connectivity validator""" |
| 36 | |
| 37 | def __init__(self, timeout=5, max_threads=10, detailed_ssl=True, use_multiprocessing=False): |
| 38 | self.timeout = timeout |
| 39 | self.max_threads = max_threads |
| 40 | self.detailed_ssl = detailed_ssl |
| 41 | # Multiprocessing disabled - always use threading for stability |
| 42 | self.use_multiprocessing = False |
| 43 | |
| 44 | def get_ssl_certificate_info(self, ip, port, detailed=True): |
| 45 | """Get SSL certificate information |
| 46 | |
| 47 | Args: |
| 48 | ip: Target IP address |
| 49 | port: Target port |
| 50 | detailed: If False, returns only basic SSL info for speed |
| 51 | """ |
| 52 | ssl_info = {} |
| 53 | |
| 54 | try: |
| 55 | # Create SSL context |
| 56 | context = ssl.create_default_context() |
| 57 | context.check_hostname = False |
| 58 | context.verify_mode = ssl.CERT_NONE |
| 59 | |
| 60 | # Connect and get certificate |
| 61 | with socket.create_connection((ip, port), timeout=self.timeout) as sock: |
| 62 | with context.wrap_socket(sock, server_hostname=ip) as ssock: |
| 63 | # Get certificate in DER format (this always works) |
| 64 | cert_der = ssock.getpeercert(binary_form=True) |
| 65 | |
| 66 | # Get cipher and protocol info |
| 67 | cipher_info = ssock.cipher() |
| 68 | protocol_version = ssock.version() |
| 69 | |
| 70 | # Parse certificate using cryptography library if available (only if detailed=True) |
| 71 | cert = None |
| 72 | if detailed and cert_der and HAS_CRYPTOGRAPHY: |
| 73 | try: |
| 74 | cert_obj = x509.load_der_x509_certificate(cert_der, default_backend()) |
| 75 | cert = self._parse_x509_certificate(cert_obj) |
| 76 | except Exception as e: |
| 77 | ssl_info['parse_error'] = str(e)[:MAX_ERROR_LENGTH] |
| 78 | |
| 79 | # Always add basic connection info |
| 80 | if cipher_info: |
| 81 | ssl_info['cipher_suite'] = cipher_info[0] if len(cipher_info) > 0 else 'Unknown' |
| 82 | ssl_info['cipher_protocol'] = cipher_info[1] if len(cipher_info) > 1 else 'Unknown' |
| 83 | ssl_info['cipher_bits'] = cipher_info[2] if len(cipher_info) > 2 else 0 |
| 84 | |
| 85 | ssl_info['protocol_version'] = protocol_version or 'Unknown' |
| 86 | |
| 87 | # Certificate fingerprints (only if detailed) |
| 88 | if detailed and cert_der: |
| 89 | ssl_info['sha1_fingerprint'] = hashlib.sha1(cert_der).hexdigest().upper() |
| 90 | ssl_info['sha256_fingerprint'] = hashlib.sha256(cert_der).hexdigest().upper() |
| 91 | ssl_info['md5_fingerprint'] = hashlib.md5(cert_der).hexdigest().upper() |
no outgoing calls
no test coverage detected