def __str__(self): s = StringIO('') #s.write('Issuer:\n') #for x in self._issuer: # s.write(' {} : {}\n'.format(x,self._issuer[x])) s.write('Subject:\n') for x in self._subject: s.write(' {} : {}\n'.format(x, self._subject[x])) cert_time_notAfter = datetime.datetime.utcfromtimestamp( ssl.cert_time_to_seconds(self._notAfter)) cert_time_notBefore = datetime.datetime.utcfromtimestamp( ssl.cert_time_to_seconds(self._notBefore)) now = datetime.datetime.now() cert_time_days_notAfter = (cert_time_notAfter - now).days cert_time_days_notBefore = (cert_time_notBefore - now).days s.write('notAfter : {}\n'.format(cert_time_days_notAfter)) s.write('notBefore : {}\n'.format(cert_time_days_notBefore)) s.write('Serial : {}\n'.format(self._serialNumber)) s.write('subjectAltName:\n') for x in self._subjectAltName: s.write(' {} : {}\n'.format(x, self._subjectAltName[x])) s.write('Version : {}'.format(self._version)) return s.getvalue()
def get_ssl_info(domain, port=443): server_name = domain sslinfo = {} context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) context.verify_mode = ssl.CERT_REQUIRED context.check_hostname = True context.load_default_certs() s = socket.socket() s = context.wrap_socket(s, server_hostname=server_name) s.connect((server_name, port)) s.do_handshake() cert = s.getpeercert() e_time = ssl.cert_time_to_seconds(cert['notAfter']) remain_days = e_time - time.time() remain_days = round(remain_days / 86400) e_time = datetime.utcfromtimestamp(e_time) s_time = ssl.cert_time_to_seconds(cert['notBefore']) s_time = datetime.utcfromtimestamp(s_time) check_time = datetime.utcnow() sslinfo['check_time'] = str(check_time) sslinfo['domain'] = server_name sslinfo['s_time'] = str(s_time) sslinfo['e_time'] = str(e_time) sslinfo['remain_days'] = remain_days return sslinfo
def _set_dates(self, netloc, port): """ set dates from openssl (notAfter and not Before) :param netloc: target netloc :param port: target port :return: """ with sp_Popen([self.echo_cmd], stdout=SP_PIPE) as proc_echo: cmd = self.ssl_client_cmd[:] cmd.append('{}:{}'.format(shlex_quote(netloc), str(port))) with sp_Popen(cmd, stdin=proc_echo.stdout, stdout=SP_PIPE, stderr=SP_DEVNULL) as proc_ssl: cmd = self.ssl_x509_cmd[:] cmd.append('-noout') cmd.append('-dates') with sp_Popen(cmd, stdin=proc_ssl.stdout, stdout=SP_PIPE, stderr=SP_DEVNULL) as proc_x509: data = proc_x509.stdout.read() ddata = data.decode('utf-8') if ddata is not None: reg = re_compile('notBefore=([^\n]+)') res = reg.search(ddata) if res is not None: self.notBefore = datetime.fromtimestamp( cert_time_to_seconds(res.group(1))) reg = re_compile('notAfter=([^\n]+)') res = reg.search(ddata) if res is not None: self.notAfter = datetime.fromtimestamp( cert_time_to_seconds(res.group(1)))
def _make_env_cert_dict(self, env_prefix, parsed_cert): """Return a dict of WSGI environment variables for a certificate. E.g. SSL_CLIENT_M_VERSION, SSL_CLIENT_M_SERIAL, etc. See https://httpd.apache.org/docs/2.4/mod/mod_ssl.html#envvars. """ if not parsed_cert: return {} env = {} for cert_key, env_var in self.CERT_KEY_TO_ENV.items(): key = '%s_%s' % (env_prefix, env_var) value = parsed_cert.get(cert_key) if env_var == 'SAN': env.update(self._make_env_san_dict(key, value)) elif env_var.endswith('_DN'): env.update(self._make_env_dn_dict(key, value)) else: env[key] = str(value) # mod_ssl 2.1+; Python 3.2+ # number of days until the certificate expires if 'notBefore' in parsed_cert: remain = ssl.cert_time_to_seconds(parsed_cert['notAfter']) remain -= ssl.cert_time_to_seconds(parsed_cert['notBefore']) remain /= 60 * 60 * 24 env['%s_V_REMAIN' % (env_prefix, )] = str(int(remain)) return env
def __validate_crt_time(self, crt): notAfterTimestamp = ssl.cert_time_to_seconds(crt['notAfter']) notBeforeTimestamp = ssl.cert_time_to_seconds(crt['notBefore']) currentTimeStamp = time.time() if currentTimeStamp > notAfterTimestamp: raise Exception("Expired server certificate") if currentTimeStamp < notBeforeTimestamp: raise Exception("Server certificate not yet active")
def __init__(self, certinfo, cert=None): self.cert = cert self.certinfo = certinfo # Certificate common name self.subject = dict(x[0] for x in self.certinfo['subject']) # Issuer common name self.issuer = dict(x[0] for x in self.certinfo['issuer']) # Expire time self.notBefore = datetime.utcfromtimestamp(cert_time_to_seconds(self.certinfo['notBefore'])) self.notAfter = datetime.utcfromtimestamp(cert_time_to_seconds(self.certinfo['notAfter']))
def update(self): """Fetch the certificate information.""" try: ctx = ssl.create_default_context() sock = ctx.wrap_socket( socket.socket(), server_hostname=self.server_name) sock.settimeout(TIMEOUT) sock.connect((self.server_name, self.server_port)) except socket.gaierror: _LOGGER.error("Cannot resolve hostname: %s", self.server_name) return except socket.timeout: _LOGGER.error( "Connection timeout with server: %s", self.server_name) return except OSError: _LOGGER.error("Cannot connect to %s", self.server_name) return try: cert = sock.getpeercert() except OSError: _LOGGER.error("Cannot fetch certificate from %s", self.server_name) return ts_seconds = ssl.cert_time_to_seconds(cert['notAfter']) timestamp = datetime.datetime.fromtimestamp(ts_seconds) expiry = timestamp - datetime.datetime.today() self._state = expiry.days
def from_ssl_socket(cls, ssl_socket): """Load certificate data from an SSL socket. """ cert = cls() try: data = ssl_socket.getpeercert() except AttributeError: # PyPy doesn't have .getppercert return cert logger.debug("Certificate data from ssl module: {0!r}".format(data)) if not data: return cert cert.validated = True cert.subject_name = data.get('subject') cert.alt_names = defaultdict(list) if 'subjectAltName' in data: for name, value in data['subjectAltName']: cert.alt_names[name].append(value) if 'notAfter' in data: tstamp = ssl.cert_time_to_seconds(data['notAfter']) cert.not_after = datetime.utcfromtimestamp(tstamp) if sys.version_info.major < 3: cert._decode_names() # pylint: disable=W0212 cert.common_names = [] if cert.subject_name: for part in cert.subject_name: for name, value in part: if name == 'commonName': cert.common_names.append(value) return cert
def check_ssl_valid_date(self, url_data, cert): """Check if the certificate is still valid, or if configured check if it's at least a number of days valid. """ import ssl try: notAfter = ssl.cert_time_to_seconds(cert['notAfter']) except ValueError as msg: msg = _('Invalid SSL certficate "notAfter" value %r' ) % cert['notAfter'] url_data.add_warning(msg) return curTime = time.time() # Calculate seconds until certifcate expires. Can be negative if # the certificate is already expired. secondsValid = notAfter - curTime args = dict(expire=cert['notAfter']) if secondsValid < 0: msg = _('SSL certficate is expired on %(expire)s.') url_data.add_warning(msg % args) else: args['valid'] = strformat.strduration_long(secondsValid) if secondsValid < self.warn_ssl_cert_secs_valid: msg = _( 'SSL certificate expires on %(expire)s and is only %(valid)s valid.' ) url_data.add_warning(msg % args) else: msg = _( 'SSL certificate expires on %(expire)s and is %(valid)s valid.' ) url_data.add_info(msg % args)
def from_ssl_socket(cls, ssl_socket): """Load certificate data from an SSL socket. """ cert = cls() try: data = ssl_socket.getpeercert() except AttributeError: # PyPy doesn't have .getppercert return cert logger.debug("Certificate data from ssl module: {0!r}".format(data)) if not data: return cert cert.validated = True cert.subject_name = data.get("subject") cert.alt_names = defaultdict(list) if "subjectAltName" in data: for name, value in data["subjectAltName"]: cert.alt_names[name].append(value) if "notAfter" in data: tstamp = ssl.cert_time_to_seconds(data["notAfter"]) cert.not_after = datetime.utcfromtimestamp(tstamp) if sys.version_info.major < 3: cert._decode_names() # pylint: disable=W0212 cert.common_names = [] if cert.subject_name: for part in cert.subject_name: for name, value in part: if name == "commonName": cert.common_names.append(value) return cert
def check_validation(host): now = time.time() context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) context.verify_mode = ssl.CERT_REQUIRED context.check_hostname = True context.load_default_certs() conn = context.wrap_socket(socket.socket(socket.AF_INET), server_hostname=host) conn.connect((host, 443)) cert = conn.getpeercert() ttl = ssl.cert_time_to_seconds(cert['notAfter']) - now print(ttl) print(ttl / 3600 / 24) k = host.split('.')[0] if ttl < 0: push_metrics("trapper.ssl-certificate.{0}.valid".format(k), 2) else: push_metrics("trapper.ssl-certificate.{0}.valid".format(k), 1) push_metrics("trapper.ssl-certificate.{0}.days".format(k), round(ttl / 3600 / 24, 2))
def check_ssl_valid_date(self, url_data, cert): """Check if the certificate is still valid, or if configured check if it's at least a number of days valid. """ import ssl try: notAfter = ssl.cert_time_to_seconds(cert['notAfter']) except ValueError as msg: msg = _('Invalid SSL certficate "notAfter" value %r') % cert['notAfter'] url_data.add_warning(msg) return curTime = time.time() # Calculate seconds until certifcate expires. Can be negative if # the certificate is already expired. secondsValid = notAfter - curTime args = dict(expire=cert['notAfter']) if secondsValid < 0: msg = _('SSL certficate is expired on %(expire)s.') url_data.add_warning(msg % args) else: args['valid'] = strformat.strduration_long(secondsValid) if secondsValid < self.warn_ssl_cert_secs_valid: msg = _('SSL certificate expires on %(expire)s and is only %(valid)s valid.') url_data.add_warning(msg % args) else: msg = _('SSL certificate expires on %(expire)s and is %(valid)s valid.') url_data.add_info(msg % args)
def __init__(self): self.builder = Gtk.Builder() self.builder.add_from_file(UI_FILE) self.builder.connect_signals(self) self.cursor = DB.cursor() self.sunday_store = self.builder.get_object('liststore1') self.monday_store = self.builder.get_object('liststore2') self.tuesday_store = self.builder.get_object('liststore3') self.wednesday_store = self.builder.get_object('liststore4') self.thursday_store = self.builder.get_object('liststore5') self.friday_store = self.builder.get_object('liststore6') self.saturday_store = self.builder.get_object('liststore7') self.populate_employee_combobox() self.populate_project_combobox() #-----for proper functionality we need to use the last possible second of today----- r = datetime.strftime(datetime.fromtimestamp(time.time()), "%b %d %Y").split() f = ssl.cert_time_to_seconds( str(r[0]) + " " + str(r[1]) + " 00:00:00 " + str(r[2]) + " GMT") self.last_second_of_target_week = float(f) + 86399.5 self.previous_week_time = self.last_second_of_target_week - 604800 self.first_day = True self.add_day_headers() DB.rollback() self.window = self.builder.get_object('window1') self.window.show_all()
def probe(self): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.settimeout(self.timeout) ssl_sock = ssl.wrap_socket(s) try: ssl_sock.connect((self.domain, self.port)) addr = ssl_sock.getpeername() certificate = ssl.get_server_certificate(addr=addr) except socket.timeout: raise IOError("timeout connecting to %s" % self.domain) except: # provide a nice error message to caller raise IOError("cannot connect to %s" % self.domain) finally: ssl_sock.close() p1 = subprocess.Popen(["openssl", "x509", "-noout", "-enddate"], stdin=subprocess.PIPE, stdout=subprocess.PIPE) stdout, _ = p1.communicate(certificate) _, expirydate = stdout.split("=") expiry_date_in_seconds = ssl.cert_time_to_seconds(expirydate.strip()) expiry_in_seconds = timedelta_to_seconds(datetime.fromtimestamp(expiry_date_in_seconds) - datetime.now()) return nagiosplugin.Metric("expiry", value=expiry_in_seconds, uom="s", context="certificate_expiry")
def update(self): """Fetch the certificate information.""" try: cert = get_cert(self.server_name, self.server_port) except socket.gaierror: _LOGGER.error("Cannot resolve hostname: %s", self.server_name) self._available = False self._valid = False return except socket.timeout: _LOGGER.error("Connection timeout with server: %s", self.server_name) self._available = False self._valid = False return except (ssl.CertificateError, ssl.SSLError): self._available = True self._state = 0 self._valid = False return ts_seconds = ssl.cert_time_to_seconds(cert["notAfter"]) timestamp = datetime.fromtimestamp(ts_seconds) expiry = timestamp - datetime.today() self._available = True self._state = expiry.days self._valid = True
async def get_cert_expiry_timestamp(hass, hostname, port, ca_cert): """Return the certificate's expiration timestamp.""" try: cert = await hass.async_add_executor_job(get_cert, hostname, port, ca_cert) except socket.gaierror as err: raise ResolveFailed(f"Cannot resolve hostname: {hostname}") from err except socket.timeout as err: raise ConnectionTimeout( f"Connection timeout with server: {hostname}:{port}" ) from err except ConnectionRefusedError as err: raise ConnectionRefused( f"Connection refused by server: {hostname}:{port}" ) from err except FileNotFoundError as err: raise ValidationFailure( f"CA certificate file '{ca_cert}' is not accessible" ) from err except ssl.CertificateError as err: raise ValidationFailure(err.verify_message) from err except ssl.SSLError as err: raise ValidationFailure(err.args[0]) from err ts_seconds = ssl.cert_time_to_seconds(cert["notAfter"]) return dt.utc_from_timestamp(ts_seconds)
def update(self): """Fetch the certificate information.""" try: ctx = ssl.create_default_context() sock = ctx.wrap_socket(socket.socket(), server_hostname=self.server_name) sock.settimeout(TIMEOUT) sock.connect((self.server_name, self.server_port)) except socket.gaierror: _LOGGER.error("Cannot resolve hostname: %s", self.server_name) return except socket.timeout: _LOGGER.error("Connection timeout with server: %s", self.server_name) return except OSError: _LOGGER.error("Cannot connect to %s", self.server_name) return try: cert = sock.getpeercert() except OSError: _LOGGER.error("Cannot fetch certificate from %s", self.server_name) return ts_seconds = ssl.cert_time_to_seconds(cert['notAfter']) timestamp = datetime.datetime.fromtimestamp(ts_seconds) expiry = timestamp - datetime.datetime.today() self._state = expiry.days
def update(self): """Fetch the certificate information.""" ctx = ssl.create_default_context() try: address = (self.server_name, self.server_port) with socket.create_connection(address, timeout=TIMEOUT) as sock: with ctx.wrap_socket(sock, server_hostname=address[0]) as ssock: cert = ssock.getpeercert() except socket.gaierror: _LOGGER.error("Cannot resolve hostname: %s", self.server_name) self._available = False return except socket.timeout: _LOGGER.error("Connection timeout with server: %s", self.server_name) self._available = False return except OSError: _LOGGER.error("Cannot fetch certificate from %s", self.server_name, exc_info=1) self._available = False return ts_seconds = ssl.cert_time_to_seconds(cert['notAfter']) timestamp = datetime.fromtimestamp(ts_seconds) expiry = timestamp - datetime.today() self._available = True self._state = expiry.days
def handle_request(self, listener, req, client, addr): """Handles each incoming request after a client has been authenticated.""" subject = dict([ i for subtuple in client.getpeercert().get('subject') for i in subtuple ]) issuer = dict([ i for subtuple in client.getpeercert().get('issuer') for i in subtuple ]) headers = dict(req.headers) headers['X-USER'] = subject.get('commonName') not_before = client.getpeercert().get('notBefore') not_after = client.getpeercert().get('notAfter') headers['X-NOT_BEFORE'] = ssl.cert_time_to_seconds(not_before) headers['X-NOT_AFTER'] = ssl.cert_time_to_seconds(not_after) headers['X-ISSUER'] = issuer['commonName'] req.headers = list(headers.items()) super(CustomSyncWorker, self).handle_request(listener, req, client, addr)
def cacert_file(cacert): """ Check if provided file is a valid CA Certificate """ try: context = ssl.create_default_context(cafile=cacert) except AttributeError: # Python version < 2.7.9 return cacert except IOError: raise argparse.ArgumentTypeError('CA Certificate not found') try: not_after = context.get_ca_certs()[0]['notAfter'] not_after = ssl.cert_time_to_seconds(not_after) not_before = context.get_ca_certs()[0]['notBefore'] not_before = ssl.cert_time_to_seconds(not_before) except (KeyError, IndexError): raise argparse.ArgumentTypeError('CA Certificate is erroneous') if not_after < int(time.time()): raise argparse.ArgumentTypeError('CA Certificate expired') if not_before > int(time.time()): raise argparse.ArgumentTypeError('CA Certificate not active yet') return cacert
def main(): """ Print days to cert expire """ host = "google.com" port = 443 ctx = ssl.create_default_context() sock = ctx.wrap_socket(socket.socket(), server_hostname=host) sock.connect((host, port)) cert = sock.getpeercert() print( datetime.fromtimestamp(ssl.cert_time_to_seconds(cert['notAfter'])) - datetime.now()).days
def load_from_dict(self, dict_cert): """ transform a dict to a structured object :param dict_cert: dict obtained from ssl library :return: """ if 'issuer' in dict_cert: self.issuer = self._auth(dict_cert['issuer']) if 'subject' in dict_cert: self.subject = self._auth(dict_cert['subject']) if 'subjectAltName' in dict_cert: self.subjectAltName = self._auth_param(dict_cert['subjectAltName']) for key, value in dict_cert.items(): if key not in ('issuer', 'subject', 'subjectAltName'): setattr(self, key, value) if self.notAfter is not None: self.notAfter = datetime.fromtimestamp( cert_time_to_seconds(self.notAfter)) if self.notBefore is not None: self.notBefore = datetime.fromtimestamp( cert_time_to_seconds(self.notBefore))
def check_ssl_expiry(): """ check url is ssl enabled or not - if ssl enabled: check certificate and expired date comes within 30 days or not - if no ssl enabled : list them """ expired_list = list() far_expired = list() no_ssl_domain = list() #dummy_hostname hostname = ['yomagolf.club','aweimetta.com','aweipila.com','balloonsoverbagan.com','balloonsoverbaganbookings.com','burmaboating.com','ducati.com.mm','fmiair.com','hotelsuggati.com','kayahresort.com', 'keinnara.com','kospacoldchain.com','kospalogistics.com','memories-travel.com','memories-travel.com.cn','memoriesgroup.com','mitsubishimotorsmyanmar.com','newhollandmyanmar.com', 'punhlaingestate.com','punhlainggolfclub.com','punhlainghospitals.com','punhlaingsiloamhospitals.com','spadps.com','starcityyangon.com','yoma.com.mm','yomaautomart.com','yomacarshare.com', 'yomacentral.com','yomaepr.com','yomagroup.net','yomaland.com','yomamicropower.com','yomarentals.asia'] for host in hostname: print(host) #print domain name for debugging ctx = ssl.create_default_context() s = ctx.wrap_socket(socket.socket(), server_hostname=host) try: #use 443 to validate only https s.connect((host, 443)) cert = s.getpeercert() print(cert['notBefore']) print(cert['notAfter']) #expired_cert to get ssl expired date - notAfter expired_cert = cert.get('notAfter') #ssl.cert_time_to_seconds for get cert_time(GMT) in epoch timestamp = ssl.cert_time_to_seconds(expired_cert) #convert epoch time to utc format to validate time_utc = datetime.utcfromtimestamp(timestamp) #print(time_utc) datetime_now = datetime.now() expire = time_utc - datetime_now #expire is timedelta object #use (timedelta.days) to get only days from timedelta object expire_days = expire.days if expire_days <= 30: expired_list.append({host:expire_days}) else: far_expired.append({host:expire_days}) except: no_ssl_domain.append(host) return expired_list, far_expired, no_ssl_domain
def get_ssl_info(domain): server_name = domain print("get ssl information for {}".format(domain)) sslinfo = {} context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) context.verify_mode = ssl.CERT_REQUIRED context.check_hostname = True context.load_default_certs() s = socket.socket() s.settimeout(5) s = context.wrap_socket(s,server_hostname=server_name) try: s.connect((server_name,443)) s.do_handshake() cert = s.getpeercert() e_time = ssl.cert_time_to_seconds(cert['notAfter']) remain = e_time e_time = datetime.utcfromtimestamp(e_time) s_time = ssl.cert_time_to_seconds(cert['notBefore']) s_time = datetime.utcfromtimestamp(s_time) check_time = datetime.utcnow() sslinfo['check_time'] = str(check_time) sslinfo['domain'] = server_name sslinfo['s_time'] = str(s_time) sslinfo['e_time'] = str(e_time) sslinfo['remain'] = remain return sslinfo except socket.timeout: print("TimeOut")
def validate_cacert_file(cacert: str): """Check if provided file is a valid CA Certificate""" try: context = ssl.create_default_context(cafile=cacert) except AttributeError: # Python version < 2.7.9 return except IOError: raise OspdError('CA Certificate not found') from None try: not_after = context.get_ca_certs()[0]['notAfter'] not_after = ssl.cert_time_to_seconds(not_after) not_before = context.get_ca_certs()[0]['notBefore'] not_before = ssl.cert_time_to_seconds(not_before) except (KeyError, IndexError): raise OspdError('CA Certificate is erroneous') from None now = int(time.time()) if not_after < now: raise OspdError('CA Certificate expired') if not_before > now: raise OspdError('CA Certificate not active yet')
def is_ssl_expiring(self, ip_address, port=443, ssl_expiration_days=0): # Check site's cert s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) ssl_sock = ssl.wrap_socket(s, ca_certs=get_certs_file(), cert_reqs=ssl.CERT_REQUIRED) try: ssl_sock.connect((ip_address, port)) cert = ssl_sock.getpeercert() cert_expiration = ssl.cert_time_to_seconds(cert["notAfter"]) exp = cert_expiration - time.time() if exp <= 0: return 1 elif exp <= (ssl_expiration_days * 24 * 60 * 60): return 2 except: return 3 finally: ssl_sock.shutdown(socket.SHUT_RDWR) ssl_sock.close() return 0
def check_ssl_expiry(): """ check url is ssl enabled or not - if ssl enabled: check certificate and expired date comes within 30 days or not - if no ssl enabled : list them """ expired_list = list() far_expired = list() no_ssl_domain = list() #dummy_hostname hostname = ['yomaland.com','starcityyangon.com','balloonsoverbaganbookings.com','scratchpads.eu/explore/sites-list','weevil.info'] for host in hostname: #print(host) #print domain name for debugging ctx = ssl.create_default_context() s = ctx.wrap_socket(socket.socket(), server_hostname=host) try: #use 443 to validate only https s.connect((host, 443)) cert = s.getpeercert() #print(cert) #expired_cert to get ssl expired date - notAfter expired_cert = cert.get('notAfter') #ssl.cert_time_to_seconds for get cert_time(GMT) in epoch timestamp = ssl.cert_time_to_seconds(expired_cert) #convert epoch time to utc format to validate time_utc = datetime.utcfromtimestamp(timestamp) #print(time_utc) datetime_now = datetime.now() expire = time_utc - datetime_now #expire is timedelta object #use (timedelta.days) to get only days from timedelta object expire_days = expire.days if expire_days <= 30: expired_list.append({host:expire_days}) else: far_expired.append({host:expire_days}) except: no_ssl_domain.append(host) return expired_list, far_expired, no_ssl_domain
def gen_gmtime_dates(): """ Generate the dates used for this run. Creating openssl gmtime dates may be simpler than this. """ gmtfmt = "%b %d %H:%M:%S %Y GMT" ok_stamp = ssl.cert_time_to_seconds(time.strftime( gmtfmt, time.gmtime())) - (60 * 60 * 24) two_days_ago_stamp = ok_stamp - (60 * 60 * 48) two_days_ago_end_stamp = two_days_ago_stamp + (60 * 60 * 24) future_stamp = ok_stamp + (60 * 60 * 24 * 365 * 1) future_end_stamp = future_stamp + (60 * 60 * 24 * 365 * 1) return dict(OK_NOW=gmc(ok_stamp), OLD=gmc(two_days_ago_stamp), OLD_END=gmc(two_days_ago_end_stamp), FUTURE=gmc(future_stamp), FUTURE_END=gmc(future_end_stamp))
def sslcheckerOut(dom, port=443, timeout=None): try: with socket.create_connection((dom, port), timeout=timeout) as sock: context = ssl.create_default_context() with context.wrap_socket(sock, server_hostname=dom) as sslsock: getssl = sslsock.getpeercert() changedt_format = getssl['notAfter'] to_format = ssl.cert_time_to_seconds(changedt_format) new_ssldt_format = datetime.datetime.fromtimestamp(to_format) dom_exp = new_ssldt_format date_now = datetime.datetime.now() if dom_exp <= date_now: return 1 else: return 0 except Exception as e: return 1
def gen_gmtime_dates(): """ Generate the dates used for this run. Creating openssl gmtime dates may be simpler than this. """ gmtfmt = "%b %d %H:%M:%S %Y GMT" ok_stamp = ssl.cert_time_to_seconds( time.strftime(gmtfmt, time.gmtime())) - (60*60*24) two_days_ago_stamp = ok_stamp - (60*60*48) two_days_ago_end_stamp = two_days_ago_stamp + (60*60*24) future_stamp = ok_stamp + (60*60*24*365*1) future_end_stamp = future_stamp + (60*60*24*365*1) return dict(OK_NOW=gmc(ok_stamp), OLD=gmc(two_days_ago_stamp), OLD_END=gmc(two_days_ago_end_stamp), FUTURE=gmc(future_stamp), FUTURE_END=gmc(future_end_stamp))
def _validate_certificate(self, cert): now = time.time() # Refuse to connect if there's no certificate. if cert is None: err = "no SSL certificate for %s" % (self.host, ) raise socket.error(err) # Refuse to connect if the certificate has expired. if "notAfter" in cert: if ssl.cert_time_to_seconds(cert["notAfter"]) < now: err = "expired SSL certificate for %s" % (self.host, ) raise socket.error(err) # Refuse to connect if the certificate is missing subject data. if "subject" not in cert: err = "malformed SSL certificate for %s" % (self.host, ) raise socket.error(err) # Try to match the certificate to the requested host. if not self._validate_certificate_hostname(cert): err = "invalid SSL certificate for %s" % (self.host, ) raise socket.error(err)
def _validate_certificate(self, cert): now = time.time() # Refuse to connect if there's no certificate. if cert is None: err = "no SSL certificate for %s" % (self.host,) raise socket.error(err) # Refuse to connect if the certificate has expired. if "notAfter" in cert: if ssl.cert_time_to_seconds(cert["notAfter"]) < now: err = "expired SSL certificate for %s" % (self.host,) raise socket.error(err) # Refuse to connect if the certificate is missing subject data. if "subject" not in cert: err = "malformed SSL certificate for %s" % (self.host,) raise socket.error(err) # Try to match the certificate to the requested host. if not self._validate_certificate_hostname(cert): err = "invalid SSL certificate for %s" % (self.host,) raise socket.error(err)
def gen_gmtime_dates(): """ Generate the dates used for this run. Creating openssl gmtime dates may be simpler than this. """ gmtfmt = "%b %d %H:%M:%S %Y GMT" ok_stamp = ssl.cert_time_to_seconds( time.strftime(gmtfmt, time.gmtime())) - (60*60*24) two_days_ago_stamp = ok_stamp - (60*60*48) two_days_ago_end_stamp = two_days_ago_stamp + (60*60*24) # Make future certs only +300 days, so we have a time overlap # between currently valid certs (1 year) and these futuristic certs future_stamp = ok_stamp + (60*60*24*365*1) future_end_stamp = future_stamp + (60*60*24*365*2) return dict(OK_NOW=gmc(ok_stamp), OLD=gmc(two_days_ago_stamp), OLD_END=gmc(two_days_ago_end_stamp), FUTURE=gmc(future_stamp), FUTURE_END=gmc(future_end_stamp))
def gen_gmtime_dates(): """ Generate the dates used for this run. Creating openssl gmtime dates may be simpler than this. """ gmtfmt = "%b %d %H:%M:%S %Y GMT" ok_stamp = ssl.cert_time_to_seconds(time.strftime( gmtfmt, time.gmtime())) - (60 * 60 * 24) two_days_ago_stamp = ok_stamp - (60 * 60 * 48) two_days_ago_end_stamp = two_days_ago_stamp + (60 * 60 * 24) # Make future certs only +300 days, so we have a time overlap # between currently valid certs (1 year) and these futuristic certs future_stamp = ok_stamp + (60 * 60 * 24 * 365 * 1) future_end_stamp = future_stamp + (60 * 60 * 24 * 365 * 2) return dict(OK_NOW=gmc(ok_stamp), OLD=gmc(two_days_ago_stamp), OLD_END=gmc(two_days_ago_end_stamp), FUTURE=gmc(future_stamp), FUTURE_END=gmc(future_end_stamp))
def get_ssl_expiry(domain): try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(CONNECTION_TIMEOUT) ssl_sock = ssl.wrap_socket(sock, cert_reqs=ssl.CERT_REQUIRED, ca_certs=certifi.where()) ssl_sock.settimeout(CONNECTION_TIMEOUT) ssl_sock.connect((domain, 443)) cert = ssl_sock.getpeercert() end = datetime.fromtimestamp(ssl.cert_time_to_seconds( cert['notAfter'])) ssl_sock.close() return str(end.date()) except socket.gaierror: raise LookupFailed except socket.error as e: if e.errno == errno.ECONNREFUSED: # connection to port 443 was confused raise SSLConnectionFailed raise UnknownSSLFailure
async def get_cert_time_to_expiry(hass, hostname, port): """Return the certificate's time to expiry in days.""" try: cert = await hass.async_add_executor_job(get_cert, hostname, port) except socket.gaierror: raise ResolveFailed(f"Cannot resolve hostname: {hostname}") except socket.timeout: raise ConnectionTimeout( f"Connection timeout with server: {hostname}:{port}") except ConnectionRefusedError: raise ConnectionRefused( f"Connection refused by server: {hostname}:{port}") except ssl.CertificateError as err: raise ValidationFailure(err.verify_message) except ssl.SSLError as err: raise ValidationFailure(err.args[0]) ts_seconds = ssl.cert_time_to_seconds(cert["notAfter"]) timestamp = datetime.fromtimestamp(ts_seconds) expiry = timestamp - datetime.today() return expiry.days
def expiring_certificate(connection, expiry_days): ''' Pass in the connection and number of days. Verify that the expiry date isn't within the specified number of days ''' # Convert the presented certificate's expiry date into a datetime object. # This could be done in one line, but for readability, we'll do this over three expiry_date = connection.getpeercert()['notAfter'] expiry_epoch = ssl.cert_time_to_seconds(expiry_date) expires = datetime.datetime.fromtimestamp(expiry_epoch) # Create a datetime object of the specified date now = datetime.datetime.now() specified_date = now + datetime.timedelta(days=expiry_days) # this evalutes to True if the certificate expires before the specified # expiry date. return expires < specified_date
def check_ssl_valid_date(self, url_data, ssl_sock, cert): """Check if the certificate is still valid, or if configured check if it's at least a number of days valid. """ import ssl try: notAfter = ssl.cert_time_to_seconds(cert['notAfter']) except ValueError as msg: msg = _('invalid certficate "notAfter" value %r') % cert['notAfter'] self.add_ssl_warning(url_data, ssl_sock, msg) return curTime = time.time() # Calculate seconds until certifcate expires. Can be negative if # the certificate is already expired. secondsValid = notAfter - curTime if secondsValid < 0: msg = _('certficate is expired on %s') % cert['notAfter'] self.add_ssl_warning(url_data, ssl_sock, msg) elif secondsValid < self.warn_ssl_cert_secs_valid: strSecondsValid = strformat.strduration_long(secondsValid) msg = _('certificate is only %s valid') % strSecondsValid self.add_ssl_warning(url_data, ssl_sock, msg)
def __verifycert(self, cert, hostname): """Verify that cert (in socket.getpeercert() format) matches hostname. CRLs are not handled. Returns error message if any problems are found and None on success.""" errstr = "CA Cert verifying failed: " if not cert: return ('%s no certificate received' % errstr) dnsname = hostname.lower() certnames = [] # cert expired? notafter = cert.get('notAfter') if notafter: if time.time() >= cert_time_to_seconds(notafter): return '%s certificate expired %s' % (errstr, notafter) # First read commonName for s in cert.get('subject', []): key, value = s[0] if key == 'commonName': certnames.append(value.lower()) if len(certnames) == 0: return ('%s no commonName found in certificate' % errstr) # Then read subjectAltName for key, value in cert.get('subjectAltName', []): if key == 'DNS': certnames.append(value.lower()) # And finally try to match hostname with one of these names for certname in certnames: if (certname == dnsname or '.' in dnsname and certname == '*.' + dnsname.split('.', 1)[1]): return None return ('%s no matching domain name found in certificate' % errstr)
def __verifycert(self, cert, hostname): """Verify that cert (in socket.getpeercert() format) matches hostname. CRLs are not handled. Returns error message if any problems are found and None on success.""" errstr = "CA Cert verifying failed: " if not cert: return ('%s no certificate received'% errstr) dnsname = hostname.lower() certnames = [] # cert expired? notafter = cert.get('notAfter') if notafter: if time.time() >= cert_time_to_seconds(notafter): return '%s certificate expired %s'% (errstr, notafter) # First read commonName for s in cert.get('subject', []): key, value = s[0] if key == 'commonName': certnames.append(value.lower()) if len(certnames) == 0: return ('%s no commonName found in certificate'% errstr) # Then read subjectAltName for key, value in cert.get('subjectAltName', []): if key == 'DNS': certnames.append(value.lower()) # And finally try to match hostname with one of these names for certname in certnames: if (certname == dnsname or '.' in dnsname and certname == '*.' + dnsname.split('.', 1)[1]): return None return ('%s no matching domain name found in certificate'% errstr)
def _cert_expiration_analysis(self, url, domain): cert, cert_der, cipher = self._get_cert(url, domain) try: exp_date = gmtime(ssl.cert_time_to_seconds(cert['notAfter'])) except ValueError: msg = 'Invalid SSL certificate date format.' om.out.debug(msg) except KeyError: msg = 'SSL certificate does not have notAfter field.' om.out.debug(msg) else: expire_days = (date(exp_date.tm_year, exp_date.tm_mon, exp_date.tm_mday) - date.today()).days if expire_days < self._min_expire_days: desc = 'The certificate for "%s" will expire soon.' % domain i = Info('Soon to expire SSL certificate', desc, 1, self.get_name()) i.set_url(url) self.kb_append(self, 'ssl_soon_expire', i)
def check_validation(host): now = time.time() context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) context.verify_mode = ssl.CERT_REQUIRED context.check_hostname = True context.load_default_certs() conn = context.wrap_socket(socket.socket(socket.AF_INET),server_hostname=host) conn.connect((host, 443)) cert = conn.getpeercert() ttl = ssl.cert_time_to_seconds(cert['notAfter']) - now print(ttl) print(ttl/3600/24) k = host.split('.')[0] if ttl < 0: push_metrics("trapper.ssl-certificate.{0}.valid".format(k), 2) else: push_metrics("trapper.ssl-certificate.{0}.valid".format(k), 1) push_metrics("trapper.ssl-certificate.{0}.days".format(k), round(ttl/3600/24, 2))
def _verifycert(self, cert, hostname): """Verify that cert (in socket.getpeercert() format) matches hostname. CRLs are not handled. Returns error message if any problems are found and None on success. """ if not cert: return "no certificate received" dnsname = hostname.lower() certnames = [] # cert expired? notafter = cert.get("notAfter") if notafter: if time.time() >= ssl.cert_time_to_seconds(notafter): return ("server certificate error: certificate expired %s") % notafter # First read commonName for s in cert.get("subject", []): key, value = s[0] if key == "commonName": certnames.append(value.lower()) if len(certnames) == 0: return "no commonName found in certificate" # Then read subjectAltName for key, value in cert.get("subjectAltName", []): if key == "DNS": certnames.append(value.lower()) # And finally try to match hostname with one of these names for certname in certnames: if certname == dnsname or "." in dnsname and certname == "*." + dnsname.split(".", 1)[1]: return None return "no matching domain name found in certificate"
v.setPluginName(self.getName()) v.setURL(url) kb.kb.append(self, tag, v) om.out.vulnerability(v.getName() + ": " + v.getDesc()) return except Exception, e: om.out.debug(str(e)) return cert = ssl_sock.getpeercert() cert_der = ssl_sock.getpeercert(binary_form=True) cipher = ssl_sock.cipher() ssl_sock.close() exp_date = gmtime(ssl.cert_time_to_seconds(cert["notAfter"])) expire_days = (date(exp_date.tm_year, exp_date.tm_mon, exp_date.tm_mday) - date.today()).days if expire_days < self._min_expire_days: i = info.info() i.setURL(url) i.setPluginName(self.getName()) i.setName("Soon expire SSL certificate") i.setDesc('The certificate for "%s" will expire soon.' % domain) kb.kb.append(self, "ssl_soon_expire", i) om.out.information(i.getDesc()) # Print the SSL information to the log desc = "This is the information about the SSL certificate used in the target site:\n" desc += self._dump_ssl_info(cert, cert_der, cipher) om.out.information(desc) i = info.info()
v.set_url(url) self.kb_append(self, tag, v) return except Exception, e: om.out.debug(str(e)) return cert = ssl_sock.getpeercert() cert_der = ssl_sock.getpeercert(binary_form=True) cipher = ssl_sock.cipher() ssl_sock.close() exp_date = gmtime(ssl.cert_time_to_seconds(cert['notAfter'])) expire_days = (date(exp_date.tm_year, exp_date.tm_mon, exp_date.tm_mday) - date.today()).days if expire_days < self._min_expire_days: desc = 'The certificate for "%s" will expire soon.' % domain i = Info('Soon to expire SSL certificate', desc, 1, self.get_name()) i.set_url(url) self.kb_append(self, 'ssl_soon_expire', i) # Print the SSL information to the log desc = 'This is the information about the SSL certificate used for'\ ' %s site:\n%s' % (domain, self._dump_ssl_info(cert, cert_der, cipher)) om.out.information(desc)
# limitations under the License. import argparse import socket import ssl import time if __name__ == '__main__': parser = argparse.ArgumentParser(description=('A script that checks certificate ' 'freshness')) parser.add_argument('hostname', type=str, help='hostname for a SSL server') parser.add_argument('--port', '-p', help='port', default='443') parser.add_argument('--original', '-o', help='show original longevity instead', action='store_true') args = parser.parse_args() ssl_sock = ssl.wrap_socket(socket.socket(socket.AF_INET, socket.SOCK_STREAM), ca_certs='/etc/ssl/certs/ca-certificates.crt', cert_reqs=ssl.CERT_REQUIRED) ssl_sock.connect((args.hostname, int(args.port))) notAfter = ssl.cert_time_to_seconds(ssl_sock.getpeercert()['notAfter']) day = 60 * 60 * 24 if args.original: notBefore = ssl.cert_time_to_seconds(ssl_sock.getpeercert()['notBefore']) print (int((notAfter - notBefore) / day)) else: t = time.time() print(int((notAfter - t) / day))
def process_task(self, target, command, arg): if arg == 'basic': txt_output_generator = self._get_basic_text elif arg == 'full': txt_output_generator = self._get_full_text else: raise Exception("PluginCertInfo: Unknown command.") (host, _, _, _) = target thread_pool = ThreadPool() if 'ca_file' in self._shared_settings and self._shared_settings['ca_file']: AVAILABLE_TRUST_STORES[self._shared_settings['ca_file']] = ('Custom --ca_file', 'N/A') for (store_path, _) in AVAILABLE_TRUST_STORES.iteritems(): # Try to connect with each trust store thread_pool.add_job((self._get_cert, (target, store_path))) # Start processing the jobs thread_pool.start(len(AVAILABLE_TRUST_STORES)) # Store the results as they come x509_cert_chain = [] (verify_dict, verify_dict_error, x509_cert, ocsp_response) = ({}, {}, None, None) for (job, result) in thread_pool.get_result(): (_, (_, store_path)) = job (x509_cert_chain, verify_str, ocsp_response) = result # Store the returned verify string for each trust store x509_cert = x509_cert_chain[0] # First cert is always the leaf cert store_info = AVAILABLE_TRUST_STORES[store_path] verify_dict[store_info] = verify_str if x509_cert is None: # This means none of the connections were successful. Get out for (job, exception) in thread_pool.get_error(): raise exception # Store thread pool errors for (job, exception) in thread_pool.get_error(): (_, (_, store_path)) = job error_msg = str(exception.__class__.__name__) + ' - ' + str(exception) store_info = AVAILABLE_TRUST_STORES[store_path] verify_dict_error[store_info] = error_msg thread_pool.join() # Results formatting # Text output - certificate info text_output = [self.PLUGIN_TITLE_FORMAT('Certificate - Content')] text_output.extend(txt_output_generator(x509_cert)) # Text output - trust validation text_output.extend(['', self.PLUGIN_TITLE_FORMAT('Certificate - Trust')]) # Hostname validation if self._shared_settings['sni']: text_output.append(self.FIELD_FORMAT("SNI enabled with virtual domain:", self._shared_settings['sni'])) # TODO: Use SNI name for validation when --sni was used host_val_dict = { X509_NAME_MATCHES_SAN: 'OK - Subject Alternative Name matches', X509_NAME_MATCHES_CN: 'OK - Common Name matches', X509_NAME_MISMATCH: 'FAILED - Certificate does NOT match ' + host } text_output.append(self.FIELD_FORMAT("Hostname Validation:", host_val_dict[x509_cert.matches_hostname(host)])) # Path validation that was successful for ((store_name, store_version), verify_str) in verify_dict.iteritems(): verify_txt = 'OK - Certificate is trusted' if (verify_str in 'ok') \ else 'FAILED - Certificate is NOT Trusted: ' + verify_str # EV certs - Only Mozilla supported for now if (verify_str in 'ok') and ('Mozilla' in store_info): if self._is_ev_certificate(x509_cert): verify_txt += ', Extended Validation' text_output.append(self.FIELD_FORMAT(self.TRUST_FORMAT(store_name=store_name, store_version=store_version), verify_txt)) # Path validation that ran into errors for ((store_name, store_version), error_msg) in verify_dict_error.iteritems(): verify_txt = 'ERROR: ' + error_msg text_output.append(self.FIELD_FORMAT(self.TRUST_FORMAT(store_name=store_name, store_version=store_version), verify_txt)) # Print the Common Names within the certificate chain cns_in_cert_chain = [] for cert in x509_cert_chain: cert_identity = self._extract_subject_cn_or_oun(cert) cns_in_cert_chain.append(cert_identity) text_output.append(self.FIELD_FORMAT('Certificate Chain Received:', str(cns_in_cert_chain))) # Text output - OCSP stapling text_output.extend(['', self.PLUGIN_TITLE_FORMAT('Certificate - OCSP Stapling')]) text_output.extend(self._get_ocsp_text(ocsp_response)) # XML output xml_output = Element(command, argument=arg, title='Certificate Information') # XML output - certificate chain: always return the full certificate for each cert in the chain cert_chain_xml = Element('certificateChain') # XML output - expiration date # em begin cert_dict = x509_cert.as_dict() expiration_date = gmtime(cert_time_to_seconds(cert_dict['validity']['notAfter'])) expire_days = (date(expiration_date.tm_year, expiration_date.tm_mon, expiration_date.tm_mday) - date.today()).days expiration_date_xml = Element("expirationDate", notAfter=cert_dict['validity']['notAfter'], expiresDays=expire_days) xml_output.append(expiration_date_xml) # em end # First add the leaf certificate cert_chain_xml.append(self._format_cert_to_xml(x509_cert_chain[0], 'leaf', self._shared_settings['sni'])) # Then add every other cert in the chain for cert in x509_cert_chain[1:]: cert_chain_xml.append(self._format_cert_to_xml(cert, 'intermediate', self._shared_settings['sni'])) xml_output.append(cert_chain_xml) # XML output - trust trust_validation_xml = Element('certificateValidation') # Hostname validation is_hostname_valid = 'False' if (x509_cert.matches_hostname(host) == X509_NAME_MISMATCH) else 'True' host_validation_xml = Element('hostnameValidation', serverHostname=host, certificateMatchesServerHostname=is_hostname_valid) trust_validation_xml.append(host_validation_xml) # Path validation - OK for ((store_name, store_version), verify_str) in verify_dict.iteritems(): path_attrib_xml = { 'usingTrustStore': store_name, 'trustStoreVersion': store_version, 'validationResult': verify_str } # EV certs - Only Mozilla supported for now if (verify_str in 'ok') and ('Mozilla' in store_info): path_attrib_xml['isExtendedValidationCertificate'] = str(self._is_ev_certificate(x509_cert)) trust_validation_xml.append(Element('pathValidation', attrib=path_attrib_xml)) # Path validation - Errors for ((store_name, store_version), error_msg) in verify_dict_error.iteritems(): path_attrib_xml = { 'usingTrustStore': store_name, 'trustStoreVersion': store_version, 'error': error_msg } trust_validation_xml.append(Element('pathValidation', attrib=path_attrib_xml)) xml_output.append(trust_validation_xml) # XML output - OCSP Stapling if ocsp_response is None: ocsp_attr_xml = {'isSupported': 'False'} ocsp_xml = Element('ocspStapling', attrib=ocsp_attr_xml) else: ocsp_attr_xml = {'isSupported': 'True'} ocsp_xml = Element('ocspStapling', attrib=ocsp_attr_xml) ocsp_resp_attr_xml = {'isTrustedByMozillaCAStore': str(ocsp_response.verify(MOZILLA_STORE_PATH))} ocsp_resp_xmp = Element('ocspResponse', attrib=ocsp_resp_attr_xml) for (key, value) in ocsp_response.as_dict().items(): ocsp_resp_xmp.append(_keyvalue_pair_to_xml(key, value)) ocsp_xml.append(ocsp_resp_xmp) xml_output.append(ocsp_xml) return PluginBase.PluginResult(text_output, xml_output)