X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=lib%2Finterface.py;h=4424a0ccec3d3a483f261bed7ba5c8a997cf2c94;hb=f9985ae233d035d6b41aa18e882688af4b670ae0;hp=43b0a6cf984686a56211bfdf9f51aabae1cf691b;hpb=83e699c314a867034743b7ac936738268db1c060;p=electrum-nvc.git diff --git a/lib/interface.py b/lib/interface.py index 43b0a6c..4424a0c 100644 --- a/lib/interface.py +++ b/lib/interface.py @@ -27,48 +27,12 @@ from version import ELECTRUM_VERSION, PROTOCOL_VERSION from util import print_error, print_msg from simple_config import SimpleConfig +import x509 DEFAULT_TIMEOUT = 5 proxy_modes = ['socks4', 'socks5', 'http'] -def check_cert(host, cert): - from OpenSSL import crypto as c - _cert = c.load_certificate(c.FILETYPE_PEM, cert) - - m = "host: %s\n"%host - m += "has_expired: %s\n"% _cert.has_expired() - m += "pubkey: %s bits\n" % _cert.get_pubkey().bits() - m += "serial number: %s\n"% _cert.get_serial_number() - #m += "issuer: %s\n"% _cert.get_issuer() - #m += "algo: %s\n"% _cert.get_signature_algorithm() - m += "version: %s\n"% _cert.get_version() - print_msg(m) - - -def cert_has_expired(cert_path): - try: - import OpenSSL - except: - print_error("Warning: cannot import OpenSSL") - return False - from OpenSSL import crypto as c - with open(cert_path) as f: - cert = f.read() - _cert = c.load_certificate(c.FILETYPE_PEM, cert) - return _cert.has_expired() - - -def check_certificates(): - config = SimpleConfig() - mydir = os.path.join(config.path, "certs") - certs = os.listdir(mydir) - for c in certs: - print c - p = os.path.join(mydir,c) - with open(p) as f: - cert = f.read() - check_cert(c, cert) def cert_verify_hostname(s): @@ -105,19 +69,18 @@ class Interface(threading.Thread): #json self.message_id = 0 self.unanswered_requests = {} - self.pending_transactions_for_notifications= [] # parse server self.server = server try: host, port, protocol = self.server.split(':') port = int(port) - except: + except Exception: self.server = None return if protocol not in 'ghst': - raise BaseException('Unknown protocol: %s'%protocol) + raise Exception('Unknown protocol: %s'%protocol) self.host = host self.port = port @@ -196,7 +159,7 @@ class Interface(threading.Thread): self.connection_msg = ('https' if self.use_ssl else 'http') + '://%s:%d'%( self.host, self.port ) try: self.poll() - except: + except Exception: print_error("http init session failed") self.is_connected = False return @@ -218,7 +181,7 @@ class Interface(threading.Thread): break except socket.error: break - except: + except Exception: traceback.print_exc(file=sys.stdout) break @@ -244,11 +207,13 @@ class Interface(threading.Thread): t1 = time.time() data = [] + ids = [] for m in messages: method, params = m if type(params) != type([]): params = [params] data.append( { 'method':method, 'id':self.message_id, 'params':params } ) self.unanswered_requests[self.message_id] = method, params, callback + ids.append(self.message_id) self.message_id += 1 if data: @@ -265,7 +230,7 @@ class Interface(threading.Thread): try: req = urllib2.Request(self.connection_msg, data_json, headers) response_stream = urllib2.urlopen(req, timeout=DEFAULT_TIMEOUT) - except: + except Exception: return for index, cookie in enumerate(cj): @@ -291,6 +256,7 @@ class Interface(threading.Thread): self.rtime = time.time() - t1 self.is_connected = True + return ids @@ -315,18 +281,31 @@ class Interface(threading.Thread): is_new = True # get server certificate. # Do not use ssl.get_server_certificate because it does not work with proxy - s = socket.socket( socket.AF_INET, socket.SOCK_STREAM ) try: - s.connect((self.host, self.port)) - except: - # print_error("failed to connect", self.host, self.port) + l = socket.getaddrinfo(self.host, self.port, socket.AF_UNSPEC, socket.SOCK_STREAM) + except socket.gaierror: + print_error("error: cannot resolve", self.host) return - try: - s = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_SSLv3, cert_reqs=ssl.CERT_NONE, ca_certs=None) - except ssl.SSLError, e: - print_error("SSL error:", self.host, e) + for res in l: + try: + s = socket.socket( res[0], socket.SOCK_STREAM ) + s.connect(res[4]) + except: + s = None + continue + + try: + s = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_SSLv3, cert_reqs=ssl.CERT_NONE, ca_certs=None) + except ssl.SSLError, e: + print_error("SSL error retrieving SSL certificate:", self.host, e) + s = None + + break + + if s is None: return + dercert = s.getpeercert(True) s.close() cert = ssl.DER_cert_to_PEM_cert(dercert) @@ -339,14 +318,24 @@ class Interface(threading.Thread): else: is_new = False + try: + addrinfo = socket.getaddrinfo(self.host, self.port, socket.AF_UNSPEC, socket.SOCK_STREAM) + except socket.gaierror: + print_error("error: cannot resolve", self.host) + return - s = socket.socket( socket.AF_INET, socket.SOCK_STREAM ) - s.settimeout(2) - s.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) + for res in addrinfo: + try: + s = socket.socket( res[0], socket.SOCK_STREAM ) + s.settimeout(2) + s.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) + s.connect(res[4]) + except: + s = None + continue + break - try: - s.connect(( self.host.encode('ascii'), int(self.port))) - except: + if s is None: print_error("failed to connect", self.host, self.port) return @@ -362,15 +351,30 @@ class Interface(threading.Thread): if e.errno != 1: return if is_new: - os.rename(temporary_path, cert_path + '.rej') + rej = cert_path + '.rej' + if os.path.exists(rej): + os.unlink(rej) + os.rename(temporary_path, rej) else: - if cert_has_expired(cert_path): + with open(cert_path) as f: + cert = f.read() + try: + x = x509.X509() + x.parse(cert) + x.slow_parse() + except: + traceback.print_exc(file=sys.stdout) + print_error("wrong certificate", self.host) + return + try: + x.check_date() + except: print_error("certificate has expired:", cert_path) os.unlink(cert_path) - else: - print_msg("wrong certificate", self.host) + return + print_error("wrong certificate", self.host) return - except: + except Exception: print_error("wrap_socket failed", self.host) traceback.print_exc(file=sys.stdout) return @@ -398,7 +402,9 @@ class Interface(threading.Thread): except ssl.SSLError: timeout = True except socket.error, err: - if err.errno in [11, 10035]: + if err.errno == 60: + timeout = True + elif err.errno in [11, 10035]: print_error("socket errno", err.errno) time.sleep(0.1) continue @@ -424,7 +430,7 @@ class Interface(threading.Thread): c = json.loads(c) self.queue_json_response(c) - except: + except Exception: traceback.print_exc(file=sys.stdout) self.is_connected = False @@ -536,6 +542,8 @@ class Interface(threading.Thread): self.s.shutdown(socket.SHUT_RDWR) self.s.close() + self.is_connected = False + def is_up_to_date(self): return self.unanswered_requests == {} @@ -565,7 +573,55 @@ class Interface(threading.Thread): self.queue.put(self) + def synchronous_get(self, requests, timeout=100000000): + queue = Queue.Queue() + ids = self.send(requests, lambda i,r: queue.put(r)) + id2 = ids[:] + res = {} + while ids: + r = queue.get(True, timeout) + _id = r.get('id') + if _id in ids: + ids.remove(_id) + res[_id] = r.get('result') + out = [] + for _id in id2: + out.append(res[_id]) + return out -if __name__ == "__main__": - check_certificates() + + +def check_cert(host, cert): + try: + x = x509.X509() + x.parse(cert) + x.slow_parse() + except: + traceback.print_exc(file=sys.stdout) + return + + try: + x.check_date() + expired = False + except: + expired = True + + m = "host: %s\n"%host + m += "has_expired: %s\n"% expired + print_msg(m) + + +def test_certificates(): + config = SimpleConfig() + mydir = os.path.join(config.path, "certs") + certs = os.listdir(mydir) + for c in certs: + print c + p = os.path.join(mydir,c) + with open(p) as f: + cert = f.read() + check_cert(c, cert) + +if __name__ == "__main__": + test_certificates()