def test_server_simple_timeouts(self): pid = self.start_server(self.args) try: self.assertRaises(ValueError, SSL.Context, 'tlsv5') ctx = SSL.Context() s = SSL.Connection(ctx) r = s.get_socket_read_timeout() w = s.get_socket_write_timeout() assert r.sec == 0, r.sec assert r.microsec == 0, r.microsec assert w.sec == 0, w.sec assert w.microsec == 0, w.microsec s.set_socket_read_timeout(SSL.timeout()) s.set_socket_write_timeout(SSL.timeout(909,9)) r = s.get_socket_read_timeout() w = s.get_socket_write_timeout() assert r.sec == 600, r.sec assert r.microsec == 0, r.microsec assert w.sec == 909, w.sec #assert w.microsec == 9, w.microsec XXX 4000 s.connect(self.srv_addr) data = self.http_get(s) s.close() finally: self.stop_server(pid) self.failIf(string.find(data, 's_server -quiet -www') == -1)
def test_server_simple_timeouts(self): pid = self.start_server(self.args) try: self.assertRaises(ValueError, SSL.Context, 'tlsv5') ctx = SSL.Context() s = SSL.Connection(ctx) r = s.get_socket_read_timeout() w = s.get_socket_write_timeout() self.assertEqual(r.sec, 0, r.sec) self.assertEqual(r.microsec, 0, r.microsec) self.assertEqual(w.sec, 0, w.sec) self.assertEqual(w.microsec, 0, w.microsec) s.set_socket_read_timeout(SSL.timeout()) s.set_socket_write_timeout(SSL.timeout(909, 9)) r = s.get_socket_read_timeout() w = s.get_socket_write_timeout() self.assertEqual(r.sec, 600, r.sec) self.assertEqual(r.microsec, 0, r.microsec) self.assertEqual(w.sec, 909, w.sec) # self.assertEqual(w.microsec, 9, w.microsec) XXX 4000 s.connect(self.srv_addr) data = self.http_get(s) s.close() finally: self.stop_server(pid) self.assertIn('s_server -quiet -www', data)
def connect(self, addr): sslsock = SSL.Connection(self.ssl_ctx) checker = PostConnectionChecker() sslsock.set_post_connection_check_callback(checker) # TODO: Determine good timeout interval sslsock.set_socket_read_timeout(SSL.timeout(10)) sslsock.set_socket_write_timeout(SSL.timeout(10)) sslsock.setblocking(1) try: sslsock.connect(addr) except (SSL.SSLError, socket.error): # will result in connect_cb being called with # self.connected = False pass else: # All socket operations after connect() are non-blocking # and handled with asyncore sslsock.setblocking(0) self.addr = addr self.set_socket(sslsock) # registers with asyncore self.connected = True # connect_cb success if self.schedule is not None: # Join back into the main thread self.schedule(0, self.do_connect_cb) else: self.do_connect_cb()
def create_socket(self): conn=SSL.Connection(self.ssl_ctx) self.set_socket(conn) self.socket.setblocking(1) self.socket.set_socket_read_timeout(SSL.timeout(1)) self.socket.set_socket_write_timeout(SSL.timeout(1)) self.set_reuse_addr() self.add_channel()
def connect(self): logger.debug('making HTTPS connection') sock = SSL.Connection(self.ssl_ctx) if self.source_address != ('', 0): sock.bind(self.source_address) # timeout doesn't work - use M2Crypto timeout on connect if self._timeout: logger.debug('setting timeout to %s seconds' % self._timeout) # microseconds is not working. m2_timeout = SSL.timeout(int(self._timeout)) sock.set_socket_read_timeout(m2_timeout) sock.set_socket_write_timeout(m2_timeout) sock.set_post_connection_check_callback(ClientSideChecker()) self.sock = sock if self.session: sock.set_session(self.session) # While using an unreliable connection, I've seen it fail with # unexpected eof. Possibly check for SSLError and retry. # First attempt at this resulted in Transport endpoint is already # connected errors. # The SSL version of connect will setup SSL and check the certificate. try: sock.connect((self.host, self.port)) except: emsg = 'connection to %s:%s failed' % (self.host, self.port) logger.error(emsg) raise
def reportIP(IPaddress): ctx = SSL.Context() ctx.set_allow_unknown_ca(True) ctx.set_verify(SSL.verify_none, 1) conn = SSL.Connection(ctx) conn.postConnectionCheck = None timeout = SSL.timeout(15) conn.set_socket_read_timeout(timeout) conn.set_socket_write_timeout(timeout) try: sys.stderr.write('Connecting '+IPaddress+'. ') sys.stderr.flush() conn.connect((IPaddress, 443)) except: print >>sys.stderr, IPaddress+"|{SSL_HANDSHAKE_FAILED}|"+"|"+"|"+"|" sys.stderr.write('failed.\n') sys.stderr.flush() return sys.stderr.write('Getting cert info. ') sys.stderr.flush() cert = conn.get_peer_cert() try: cissuer = cert.get_issuer().as_text() except: sys.stderr.write("Error: No Valid Cert Presented\n"); print >>sys.stderr, IPaddress+"|{NO_CERT_PRESENTED}|"+"|"+"|"+"|" sys.stderr.flush conn.close return sys.stderr.write('done\n') sys.stderr.flush() csubject = cert.get_subject().as_text() try: cAltName = cert.get_ext('subjectAltName').get_value() except LookupError: cAltName = "" try: cCN = cert.get_subject().CN except AttributeError: cCN = "" try: cExpiry = str(cert.get_not_after()) except AttributeError: cExpiry = "" conn.close ret = {} ret["ip"] = IPaddress ret["cn"] = cCN # ret["subject"] = csubject ret["issuer"] = cissuer.split("=")[-1] ret["alt"] = map(lambda x: x.split("DNS:")[-1], cAltName.split(", ")) ret["expire"] = cExpiry print json.dumps(ret) return ret
def settimeout( self, seconds ): #-------------------------------------------------------------------------- """ Call the settimeout method of the SSL connection which passes it to the underlying socket. :param seconds: timeout in seconds """ self.s.set_socket_read_timeout(SSL.timeout(seconds))
def listen( self, host, port ): #-------------------------------------------------------------------------- ''' Create a server socket and bind it to the given host/port. For every incoming connection a SSL tunnel will be established. Either babbler connects for the first time respectively conversation is currently ended a conversation is starting, or conversation will be dismissed (to avoid multiple connections to the same peer). The server connection will timeout every 60 seconds in order to check for the shutdown flag. :param host: DNS name or IP address to listen :param port: port number to listen ''' s = self.makeserversocket( host, port ) s.set_socket_read_timeout(SSL.timeout(60)) self.__verbose( 'Listening for conversation invitations on %s:%d' % ( host, port ) ) while not self.shutdown: try: clientsock, _ = s.accept() self.__verbose( 'Talking to %s' % str(clientsock.getpeername()) ) # open a new ssl conversation with the requesting peer host, port = clientsock.getpeername() contact = Contact({"host":[host],"port":[port], "version":None, "c_version":None}) conv = Conversation(self, contact, None) conv.setsocket(clientsock) conv.buildssl() if conv.id in self.babblers: if self.getbabbler(conv.id).status == Conversation.ENDED: self.getbabbler(conv.id).setsocket(conv.s) self.getbabbler(conv.id).setx509(conv.x509) self.getbabbler(conv.id).id = conv.id self.getbabbler(conv.id).start() else: conv.end() else: self.babblers[conv.id] = conv conv.start() except Exception: pass #if self.__config["debug"]: #traceback.print_exc() self.__verbose( 'Stop listening on %s:%d' % ( host, port ) ) s.close()
def test_server_simple_timeouts(self): pid = self.start_server(self.args) # Arbitrary value: test_timeout_sec = 909 # Linux rounds microseconds in the timeouts up to the HZ kernel parameter. # Windows rounds down to milliseconds. # To avoid checking for rounded values, pick interval long enough # so that it is a whole number of ms and HZ for any reasonable HZ value. test_timeout_microsec = 500000 try: with self.assertRaises(ValueError): SSL.Context('tlsv5') ctx = SSL.Context() s = SSL.Connection(ctx) r = s.get_socket_read_timeout() w = s.get_socket_write_timeout() self.assertEqual(r.sec, 0, r.sec) self.assertEqual(r.microsec, 0, r.microsec) self.assertEqual(w.sec, 0, w.sec) self.assertEqual(w.microsec, 0, w.microsec) s.set_socket_read_timeout(SSL.timeout()) s.set_socket_write_timeout(SSL.timeout(test_timeout_sec, test_timeout_microsec)) r = s.get_socket_read_timeout() w = s.get_socket_write_timeout() self.assertEqual(r.sec, DEFAULT_TIMEOUT, r.sec) self.assertEqual(r.microsec, 0, r.microsec) self.assertEqual(w.sec, test_timeout_sec, w.sec) self.assertEqual(w.microsec, test_timeout_microsec, w.microsec) s.connect(self.srv_addr) data = self.http_get(s) s.close() finally: self.stop_server(pid) self.assertIn('s_server -quiet -www', data)
def get_ssl_subject_CN(ip_address,ssl_port=443): ctx = SSL.Context() ctx.set_allow_unknown_ca(True) ctx.set_verify(SSL.verify_none, 1) conn = SSL.Connection(ctx) conn.postConnectionCheck = None timeout = SSL.timeout(1) conn.set_socket_read_timeout(timeout) conn.set_socket_write_timeout(timeout) try: conn.connect((ip_address,ssl_port)) except Exception, e: #print 'ssl conn error:',e return
def get_ssl_information(hostname): ssl_context = SSL.Context() # I am enabling unknown CA's to deal with self-signed certs ssl_context.set_allow_unknown_ca(True) ssl_context.set_verify(SSL.verify_none, 1) connect_to_server_over_https = SSL.Connection(ssl_context) connect_to_server_over_https.postConnectionCheck = None timeout = SSL.timeout(15) connect_to_server_over_https.set_socket_read_timeout(timeout) connect_to_server_over_https.set_socket_write_timeout(timeout) try: connect_to_server_over_https.connect((hostname, 443)) except Exception, err: print("%s: %s" % (hostname, err)) return
def reportIP(self, IPaddress, port): """ Shamesly copied from: http://phreakmonkey.com/index.php/archives/100 A quick hack to probe for SSL Certificate Information Requres python & m2crypto 2007.09.26 - phreakmonkey.com / phreakmonkey at gmail """ ctx = SSL.Context() ctx.set_allow_unknown_ca(True) ctx.set_verify(SSL.verify_none, 1) conn = SSL.Connection(ctx) conn.postConnectionCheck = None timeout = SSL.timeout(15) conn.set_socket_read_timeout(timeout) conn.set_socket_write_timeout(timeout) try: if self.verbose: sys.stderr.write('Connecting '+IPaddress+'.\n') sys.stderr.flush() conn.connect((IPaddress, port)) except KeyboardInterrupt: raise KeyboardInterrupt except TypeError: raise MyException('connect: Malformed address specified') except socket.gaierror: raise MyException('connect: No address associated with hostname') except socket.error: raise MyException('timeout connecting with hostname.') except SSL.SSLError: raise MyException('SSL_HANDSHAKE_FAILED.') if self.verbose: sys.stderr.write('Retrieving cert info.\n') sys.stderr.flush() cert = conn.get_peer_cert() try: cissuer = cert.get_issuer().as_text() except SSL.SSLError: raise MyException('Error: No Valid Cert Presented.') conn.close return cert
def reportIP(IPaddress): ctx = SSL.Context() ctx.set_allow_unknown_ca(True) ctx.set_verify(SSL.verify_none, 1) conn = SSL.Connection(ctx) conn.postConnectionCheck = None timeout = SSL.timeout(15) conn.set_socket_read_timeout(timeout) conn.set_socket_write_timeout(timeout) try: sys.stderr.flush() conn.connect((IPaddress, 443)) except: print IPaddress+"|{SSL_HANDSHAKE_FAILED}|"+"|"+"|"+"|" sys.stderr.write('failed.\n') sys.stderr.flush() return sys.stderr.flush() cert = conn.get_peer_cert() try: cissuer = cert.get_issuer().as_text() except: sys.stderr.write("Error: No Valid Cert Presented\n"); print IPaddress+"|{NO_CERT_PRESENTED}|"+"|"+"|"+"|" sys.stderr.flush conn.close return sys.stderr.flush() csubject = cert.get_subject().as_text() try: cAltName = cert.get_ext('subjectAltName').get_value() except LookupError: cAltName = "" try: cCN = cert.get_subject().CN except AttributeError: cCN = "" try: cExpiry = str(cert.get_not_after()) except AttributeError: cExpiry = "" conn.close print cExpiry
def create_pywbem_ssl_context(): """ Create an SSL context based on what is commonly accepted as the required limitations. This code attempts to create the same context for Python 2 and Python 3 except for the ciphers This list is based on what is currently defined in the Python SSL module create_default_context function This includes: * Disallow SSLV2 and SSLV3 * Allow TLSV1 TLSV1.1, TLSV1.2 * No compression * Single DH Use and Single ECDH use cacerts info is set independently so is not part of our context setter. """ if six.PY2: context = SSL.Context('sslv23') # Many of the flags are not in the M2Crypto source so they were taken # from OpenSSL SSL.h module as flags. SSL.context.set_options(SSL.SSL_OP_NO_SSLv2 | 0x02000000 | # OP_NO_SSLV3 0x00020000 | # OP_NO_COMPRESSION 0x00100000 | # OP_SINGLE_DH_USE 0x00400000 | # OP_CIPHER_SERVER_PREFERENCE 0x00080000) # OP_SINGLE_ECDH_USE else: # The choice for the Python SSL module is whether to use the # create_default directly and possibly have different limits depending # on which version of Python you use or to set the attributes # directly based on a currently used SSL context = SSL.create_default_context(purpose=SSL.Purpose.CLIENT_AUTH) # Variable settings per SSL create_default_context. These are what # the function above sets for Python 3.4 # context = SSLContext(PROTOCOL_SSLv23) # context.options |= OP_NO_SSLv2 # context.options |= OP_NO_SSLv3 # context.options |= getattr(SSL, "OP_NO_COMPRESSION", 0) # context.options |= getattr(SSL, "OP_CIPHER_SERVER_PREFERENCE", 0) # context.options |= getattr(SSL, "OP_SINGLE_DH_USE", 0) # context.options |= getattr(SSL, "OP_SINGLE_ECDH_USE", 0) # context.set_ciphers(_RESTRICTED_SERVER_CIPHERS) return context
def test_HTTPS_secure_context(self): pid = self.start_server(self.args) try: from M2Crypto import httpslib ctx = SSL.Context() ctx.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, 9) ctx.load_verify_locations('tests/ca.pem') c = httpslib.HTTPS(srv_host, self.srv_port, ssl_context=ctx) c.putrequest('GET', '/') c.putheader('Accept', 'text/html') c.putheader('Accept', 'text/plain') c.endheaders() err, msg, headers = c.getreply() assert err == 200, err f = c.getfile() data = f.read() c.close() finally: self.stop_server(pid) self.assertIn('s_server -quiet -www', data)
def get_ssl_subject_CN(ip_address, ssl_port=443): ctx = SSL.Context() ctx.set_allow_unknown_ca(True) ctx.set_verify(SSL.verify_none, 1) conn = SSL.Connection(ctx) conn.postConnectionCheck = None timeout = SSL.timeout(1) conn.set_socket_read_timeout(timeout) conn.set_socket_write_timeout(timeout) try: conn.connect((ip_address, ssl_port)) except: return cert = conn.get_peer_cert() try: c_CN = cert.get_subject().CN except AttributeError: c_CN = "" conn.close() return c_CN
def __init__ (self, cert, key, sock=None, serving=None): asyncore.dispatcher_with_send.__init__ (self) self.__serving = serving # XXX if sock: if self.__serving: self.set_socket(sock) else: self.create_socket (socket.AF_INET, socket.SOCK_STREAM) self.ctx = SSL.Context('sslv23') self.ctx.set_verify(SSL.verify_none, 10) self.ctx.load_cert(cert, key) self.ctx.set_info_callback() self.ssl = _nb_connection(self.ctx, self.socket) self.__output = '' self.__want_write = 1
def handle_accept(self): # Cribbed from http_server. self.total_clients.increment() try: conn, addr = self.accept() except socket.error: # linux: on rare occasions we get a bogus socket back from # accept. socketmodule.c:makesockaddr complains that the # address family is unknown. We don't want the whole server # to shut down because of this. sys.stderr.write('warning: server accept() threw an exception\n') return # Turn the vanilla socket into an SSL connection. try: ssl_conn = SSL.Connection(self.ssl_ctx, conn) ssl_conn._setup_ssl(addr) ssl_conn.accept_ssl() self.channel_class(self, ssl_conn, addr) except SSL.SSLError: pass
def initAsClient(self): """ Prepare this client socket for use. """ if self.serverMode(): raise RuntimeError("SSLTransport is in server mode.") error = None host, port = self.stServerAddress # The following piece of code was inspired by the python socket documentation # as well as the implementation of M2Crypto.httpslib.HTTPSConnection # We ignore the returned sockaddr because SSL.Connection.connect needs # a host name. addrInfoList = socket.getaddrinfo(host, port, socket.AF_UNSPEC, socket.SOCK_STREAM) for (family, _socketType, _proto, _canonname, _socketAddress) in \ addrInfoList: try: self.oSocket = SSL.Connection(self.__ctx, family=family) # set SNI server name since we know it at this point self.oSocket.set_tlsext_host_name(host) self.oSocket.connect((host, port)) self.remoteAddress = self.oSocket.getpeername() return S_OK() # warning: do NOT catch SSL related error here # They should be propagated upwards and caught by the BaseClient # not to enter the retry loop except socket.error as e: error = "%s:%s" % (e, repr(e)) if self.oSocket is not None: self.oSocket.close() self.oSocket.socket.close() self.oSocket = None return S_ERROR(error)
def s_server(config): ctx = SSL.Context(config.protocol[0]) if hasattr(config, 'debug'): config.debug = 1 else: config.debug = 0 if hasattr(config, 'cert'): cert = config.cert else: cert = 'server.pem' if hasattr(config, 'key'): cert = config.key else: cert = 'server.pem' ctx.load_cert(cert) if hasattr(config, 'CAfile'): cafile = config.CAfile else: cafile = 'ca.pem' ctx.load_verify_location(cafile) if hasattr(config, 'verify'): verify = SSL.verify_peer depth = int(config.verify) elif hasattr(config, 'Verify'): verify = SSL.verify_peer | SSL.verify_fail_if_no_peer_cert depth = int(config.Verify) else: verify = SSL.verify_none depth = 0 ctx.set_verify(verify, depth) ctx.set_tmp_dh('dh1024.pem') #ctx.set_info_callback() server(cfg.accept[0], cfg.accept[1], cfg, ctx) asyncore.loop()
def __init__(self, tenant_index=0, tenant_name=None): self.tenant_index = int(tenant_index) self.tenant_name = "default" if tenant_name: self.tenant_name = tenant_name self.cert_file = '/etc/smithproxy/certs/default/srv-cert.pem' self.key_file = '/etc/smithproxy/certs/default/srv-key.pem' self.context = SSL.Context() self.context.load_cert(self.cert_file, keyfile=self.key_file) self.service_port = 65000 + self.tenant_index self.bend_port = 64000 + self.tenant_index self.l_server = SOAPpy.ThreadingSOAPServer( ("0.0.0.0", self.service_port), ssl_context=self.context) self.r_server = SOAPpy.SOAPProxy("http://localhost:%d/" % (self.bend_port, )) self.l_server.registerFunction( SOAPpy.MethodSig(self.ping, keywords=0, context=1)) self.l_server.registerFunction( SOAPpy.MethodSig(self.whoami, keywords=0, context=1)) self.l_server.registerFunction( SOAPpy.MethodSig(self.authenticate, keywords=0, context=1)) self.l_server.registerFunction( SOAPpy.MethodSig(self.admin_login, keywords=0, context=1)) self.l_server.registerFunction( SOAPpy.MethodSig(self.admin_token_list, keywords=0, context=1)) self.l_server.registerFunction( SOAPpy.MethodSig(self.admin_keepalive, keywords=0, context=1)) self.l_server.registerFunction( SOAPpy.MethodSig(self.admin_logout, keywords=0, context=1)) self.create_logger() self.load_config()
def __init__(self, host, port=None, strict=None, **ssl): # type: (str, Optional[int], Optional[bool], **Dict[Any, Any]) -> None """ Represents one transaction with an HTTP server over the SSL connection. @param host: host name @param port: port number @param strict: if switched on, it raises BadStatusLine to be raised if the status line can't be parsed as a valid HTTP/1.0 or 1.1 status line. @param ssl: dict with all remaining named real parameters of the function. Specifically, ``ssl_context`` is expected to be included with SSL.Context; if it is not default ``'sslv23'`` is substituted). """ self.session = None # type: bytes self.host = host self.port = port keys = ssl.keys() try: keys.remove('key_file') except ValueError: pass try: keys.remove('cert_file') except ValueError: pass try: keys.remove('ssl_context') except ValueError: pass if keys: raise ValueError('unknown keyword argument') try: self.ssl_ctx = ssl['ssl_context'] assert isinstance(self.ssl_ctx, SSL.Context), self.ssl_ctx except KeyError: self.ssl_ctx = SSL.Context() HTTPConnection.__init__(self, host, port, strict)
def check_ssl(ip_address, port=443): ctx = SSL.Context() ctx.set_allow_unknown_ca(True) ctx.set_verify(SSL.verify_none, 1) conn = SSL.Connection(ctx) conn.postConnectionCheck = None timeout = SSL.timeout(15) conn.set_socket_read_timeout(timeout) conn.set_socket_write_timeout(timeout) try: conn.connect((ip_address, port)) except: conn.close() return None cert = conn.get_peer_cert() try: cissuer = cert.get_issuer().as_text() except: conn.close() return None csubject = cert.get_subject().as_text() try: cAltName = cert.get_ext("subjectAltName").get_value() except LookupError: cAltName = "" try: cCN = cert.get_subject().CN except AttributeError: cCN = "" try: cExpiry = str(cert.get_not_after()) except AttributeError: cExpiry = "" conn.close() return dict(cCN=cCN, csubject=csubject, cissuer=cissuer, cAltName=cAltName, cExpiry=cExpiry)
def getcontext(certs): #-------------------------------------------------------------------------- ''' Build up a SSL context using the certificat tupel (keyfile, certfile, cafile) passed as parameter. Use Transport Layer Security Protocol and requires peer certificate as well (both sides of the connection must provide a certificate) :param certs: certificat tupel (KEY_FILE_NAME, CERT_FILE_NAME, CA_CERT_FILE_NAME) ''' context = SSL.Context(protocol='tlsv1') # load certificate stuff. context.load_cert(certfile=certs["certificate"], keyfile=certs["key"]) context.load_verify_locations(cafile=certs["ca"]) context.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, 1) return context #--------------------------------------------------------------------------
def acceptConnection_multipleSteps(self): """ Accept a new client, returns a new SSLTransport object representing the client connection. The connection is accepted, but no SSL handshake is performed :returns: S_OK(SSLTransport object) """ # M2Crypto does not provide public method to # accept and handshake in two steps. # So we have to do it manually # The following lines are basically a copy/paste # of the begining of SSL.Connection.accept method try: sock, addr = self.oSocket.socket.accept() oClient = SSL.Connection(self.oSocket.ctx, sock) oClient.addr = addr oClientTrans = SSLTransport(self.stServerAddress, ctx=self.__ctx) oClientTrans.setClientSocket(oClient) return S_OK(oClientTrans) except (socket.error, SSL.SSLError, SSLVerificationError) as e: return S_ERROR("Error in acceptConnection: %s %s" % (e, repr(e)))
def __init__(self, host, port=None, **ssl): keys = ssl.keys() try: keys.remove('key_file') except ValueError: pass try: keys.remove('cert_file') except ValueError: pass try: keys.remove('ssl_context') except ValueError: pass if keys: raise ValueError() try: self.ssl_ctx = ssl['ssl_context'] assert isinstance(self.ssl_ctx, SSL.Context) except KeyError: self.ssl_ctx = SSL.Context('sslv23') HTTPConnection.__init__(self, host, port)
def __init__(self, host, port=None, **ssl): # Specifying sslv23 enables the following ssl versions: # SSLv3, SSLv23, TLSv1, TLSv1.1, and TLSv1.2. We will explicitly exclude # SSLv3 and SSLv2 below. This mimics what is done by create_default_context # on newer python versions (python >= 2.7). ctx = SSL.Context('sslv23') # SSL_OP_ALL turns on all workarounds for known bugs. See # https://www.openssl.org/docs/manmaster/ssl/SSL_CTX_set_options.html for # a full list of these workarounds. I believe that we don't really need # any of these workarounds, but, this is default in later pythons and is # future looking. ctx.set_options(m2.SSL_OP_ALL | m2.SSL_OP_NO_SSLv2 | m2.SSL_OP_NO_SSLv3) if cafile is not None or capath is not None: ctx.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, max_cert_depth) ctx.load_verify_info(cafile=cafile, capath=capath) self._postConnectionCheck = True else: ctx.set_verify(SSL.verify_none, max_cert_depth) self._postConnectionCheck = False httpslib.HTTPSConnection.__init__(self, host, port, ssl_context=ctx)
def initAsClient(self): """ Prepare this client socket for use. """ if self.serverMode(): raise RuntimeError("SSLTransport is in server mode.") error = None host, port = self.stServerAddress # The following piece of code was inspired by the python socket documentation # as well as the implementation of M2Crypto.httpslib.HTTPSConnection # We ignore the returned sockaddr because SSL.Connection.connect needs # a host name. addrInfoList = socket.getaddrinfo(host, port, socket.AF_UNSPEC, socket.SOCK_STREAM) for (family, _socketType, _proto, _canonname, _socketAddress) in \ addrInfoList: try: self.oSocket = SSL.Connection(self.__ctx, family=family) # set SNI server name since we know it at this point self.oSocket.set_tlsext_host_name(host) self.oSocket.connect((host, port)) self.remoteAddress = self.oSocket.getpeername() return S_OK() except socket.error as e: # Other exception are probably SSL-related, in that case we # abort and the exception is forwarded to the caller. error = repr(e) if self.oSocket is not None: self.oSocket.close() self.oSocket.socket.close() self.oSocket = None return S_ERROR(error)
def createConn(host, port, scheme): if scheme == "https": if 'https' in urllib.getproxies_environment(): proxies_env = urllib.getproxies_environment() if 'https' in proxies_env.keys(): valProxy = ['https'] else: valProxy = ['http'] netlocProxy = urlparse(valProxy)[2] [__PROXYHOST__, __PROXYPORT__] = netlocProxy.split(":") conn = httplib.HTTPConnection(host=__PROXYHOST__, port=__PROXYPORT__, timeout=SOCKETTIMEOUT) conn.set_tunnel(host=host, port=int(port)) ctx = SSL.Context() ctx.set_allow_unknown_ca(True) ctx.set_verify(SSL.verify_none, 1) conn = M2Crypto.httpslib.ProxyHTTPSConnection(host=__PROXYHOST__, port=__PROXYPORT__) conn.ssl_ctx = ctx conn.putrequest('HEAD', scheme + "://" + ":".join(host, port)) return conn else: return httplib.HTTPSConnection(host=host, port=port, timeout=SOCKETTIMEOUT) else: if 'http' in urllib.getproxies_environment(): valProxy = urllib.getproxies_environment()['http'] netlocProxy = urlparse(valProxy)[2] [__PROXYHOST__, __PROXYPORT__] = netlocProxy.split(":") return httplib.HTTPConnection(host=__PROXYHOST__, port=__PROXYPORT__, timeout=SOCKETTIMEOUT) else: return httplib.HTTPConnection(host=host, port=port, timeout=SOCKETTIMEOUT)
def connect(self): """Copied verbatim except for adding the timeout""" error = None # We ignore the returned sockaddr because SSL.Connection.connect needs # a host name. for (family, _, _, _, _) in socket.getaddrinfo(self.host, self.port, 0, socket.SOCK_STREAM): sock = None # 1435475: Older versions of M2Crypto do not support specifying the connection family, but if # we are on a version that does, we can to send it in to support IPv6. m2_args, _vargs, _kwords, _defaults = inspect.getargspec( SSL.Connection.__init__) connection_kwargs = {} if m2_args and 'family' in m2_args: connection_kwargs['family'] = family try: sock = SSL.Connection(self.ssl_ctx, **connection_kwargs) sock.settimeout(self.rhsm_timeout) if self.session is not None: sock.set_session(self.session) sock.connect((self.host, self.port)) self.sock = sock sock = None return except socket.error as e: # Other exception are probably SSL-related, in that case we # abort and the exception is forwarded to the caller. error = e finally: if sock is not None: sock.close() if error is None: raise AssertionError("Empty list returned by getaddrinfo") raise error
def test_HTTPSConnection_resume_session(self): pid = self.start_server(self.args) try: self.ctx.load_verify_locations(cafile='tests/ca.pem') self.ctx.load_cert('tests/x509.pem') self.ctx.set_verify( SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, 1) self.ctx.set_session_cache_mode(m2.SSL_SESS_CACHE_CLIENT) c = httpslib.HTTPSConnection(srv_host, self.srv_port, ssl_context=self.ctx) c.request('GET', '/') ses = c.get_session() t = ses.as_text() data = c.getresponse().read() # Appearently closing connection here screws session; Ali Polatel? # c.close() ctx2 = SSL.Context() ctx2.load_verify_locations(cafile='tests/ca.pem') ctx2.load_cert('tests/x509.pem') ctx2.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, 1) ctx2.set_session_cache_mode(m2.SSL_SESS_CACHE_CLIENT) c2 = httpslib.HTTPSConnection(srv_host, self.srv_port, ssl_context=ctx2) c2.set_session(ses) c2.request('GET', '/') ses2 = c2.get_session() t2 = ses2.as_text() data = util.py3str(c2.getresponse().read()) c.close() c2.close() self.assertEqual(t, t2, "Sessions did not match") finally: self.stop_server(pid) self.assertIn('s_server -quiet -www', data)
def __init__(self, host, port=None, key_file=None, cert_file=None, root_cert=None, strict=None, timeout=None, server_verify=True): """ All params except those noted below are passed through to the M2Crypto.httpslib.HTTPSConnection constructor. Check docs on that class information. Note, root_cert is passed in the SSL.Context if server_verify is True by means of SSL.Context.load_verify_locations. @param server_verify: does server certificate verification if True @param timeout: timeout value is set on the socket after connection using socket.settimeout() if timeout is not None. """ self.server_verify = server_verify self.my_timeout = timeout ctx = SSL.Context() ctx.load_cert(cert_file, key_file) # Leaving the ctx verify mode set to 0 does not seem # to turn off all the server certificate checks, not # sure why. Something in M2Crypto. if server_verify: ctx.load_verify_locations(root_cert) mode = SSL.verify_peer | SSL.verify_fail_if_no_peer_cert ctx.set_verify(mode, depth=9) httpslib.HTTPSConnection.__init__(self, host, port, strict, key_file=key_file, cert_file=cert_file, ssl_context=ctx)
def connect(): tsPath = getTrustStorePath() port = config.get('addresses', 'management_port') if tsPath: addr = getLocalVdsName(tsPath) from M2Crypto.m2xmlrpclib import SSL_Transport from M2Crypto import SSL KEYFILE = tsPath + '/keys/vdsmkey.pem' CERTFILE = tsPath + '/certs/vdsmcert.pem' CACERT = tsPath + '/certs/cacert.pem' ctx = SSL.Context('sslv3') ctx.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, 16) ctx.load_verify_locations(CACERT) ctx.load_cert(CERTFILE, KEYFILE) server = xmlrpclib.Server('https://%s:%s' % (addr, port), SSL_Transport(ctx)) else: server = xmlrpclib.Server('http://localhost:%s' % port) return server
def handler(addr, sslctx, host, port, req, sslsess=None): s = SSL.Connection(sslctx) s.bind(addr) if sslsess: s.set_session(sslsess) s.connect((host, port)) else: s.connect((host, port)) sslsess = s.get_session() s.write(req) while 1: data = s.read(4096) if not data: break if addr != ADDR2: thr = Thread(target=handler, args=(ADDR2, sslctx, host, port, req, sslsess)) print "Thread =", thr.getName() thr.start() s.close()
def __init__(self, host, port=None, strict=None, **ssl): self.session = None keys = ssl.keys() try: keys.remove('key_file') except ValueError: pass try: keys.remove('cert_file') except ValueError: pass try: keys.remove('ssl_context') except ValueError: pass if keys: raise ValueError('unknown keyword argument') try: self.ssl_ctx = ssl['ssl_context'] assert isinstance(self.ssl_ctx, SSL.Context), self.ssl_ctx except KeyError: self.ssl_ctx = SSL.Context('sslv23') HTTPConnection.__init__(self, host, port, strict)
def handler(sslctx, host, port, href, recurs=0, sslsess=None): s = SSL.Connection(sslctx) if sslsess: s.set_session(sslsess) s.connect((host, port)) else: s.connect((host, port)) sslsess = s.get_session() #print sslsess.as_text() if recurs: p = htmllib.HTMLParser(formatter.NullFormatter()) f = s.makefile("rw") f.write(href) f.flush() while 1: data = f.read() if not data: break if recurs: p.feed(data) if recurs: p.close() f.close() if recurs: for a in p.anchorlist: req = 'GET %s HTTP/1.0\r\n\r\n' % a thr = Thread(target=handler, args=(sslctx, host, port, req, recurs - 1, sslsess)) print "Thread =", thr.getName() thr.start()
def test_HTTPSConnection_SNI_support(self): args = [ 's_server', '-servername', srv_host, '-debug', '-www', '-cert', 'server.pem', '-key', 'server_key.pem', '-cert2', 'server.pem', '-key2', 'server_key.pem', '-accept', str(self.srv_port) ] pid = self.start_server(args) try: ctx = SSL.Context() c = httpslib.HTTPSConnection(srv_host, self.srv_port, ssl_context=ctx) c.request('GET', '/') c.close() finally: # (openssl s_server) buffers its log output, and ends the TLS session # with the client (allowing the client to terminate) before flushing # the log; so, the client may get here and terminate the server # before it manages to log the output. # So, give the server hopefully enough time to flush the logs. time.sleep(sleepTime) out, err = self.stop_server(pid) self.assertIn('Hostname in TLS extension: "%s"' % srv_host, out)
def M2CryptoConnectionAccept(self): """ Alternate implementation for M2Crypto.SSL.Connection.accept This implementation sets the read/write timeouts on the socket and checks for an error in the SSL accept. Any time a client connects to the servers and doesn't finish the SSL accept negotiations, the server is hung until the client goes away. Timeouts fix this by only allowing a client to hang the server for ten seconds. This functionality will be rolled back to the M2Crypto project as soon as possible. When it appears in an M2Crypto release, we can do away with this patch. """ sock, addr = self.socket.accept() ssl = SSL.Connection(self.ctx, sock) # set a 10s timeout on the listening socket if sys.platform not in ['win32']: t = SSL.timeout(10,0) ssl.set_socket_read_timeout(t) ssl.set_socket_write_timeout(t) ssl.addr = addr ssl.setup_ssl() ssl.set_accept_state() ret = ssl.accept_ssl() err = m2.ssl_get_error(ssl.ssl,ret) if err != m2.ssl_error_none: ssl.socket.close() raise Err.SSLError(ret,addr) check = getattr(self, 'postConnectionCheck', self.serverPostConnectionCheck) if check is not None: if not check(self.get_peer_cert(), ssl.addr[0]): raise Checker.SSLVerificationError, 'post connection check failed' return ssl, addr
def m2_wrap_socket(sock, ssl_options, server_hostname=None, **kwargs): """Returns an ``M2Crypto.SSL.Connection`` wrapping the given socket. ``ssl_options`` may be either an `~M2Crypto.SSL.Context` object or a dictionary (as accepted by `ssl_options_to_m2_context`). ``server_side``: Needed ! if True, initialize M2Crypto as a server """ # Note: do not attempt to do socket.settimeout, for it is for # blocking sockets only context = ssl_options_to_m2_context(ssl_options) connection = SSL.Connection(ctx=context, sock=sock) # Set the keep alive to True connection.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, True) if server_hostname: connection.set_tlsext_host_name(server_hostname) # Add an extra attribute to the Connection so we can test on it later connection.server_side = kwargs.get('server_side', False) # Hum, why do I need that? connection.family = sock.family # Need this for writes that are larger than BIO pair buffers # the ssl module also sets it m2.ssl_set_mode(connection.ssl, m2.SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER) return connection
def blocking_connect(): try: dbg("Creating TLS connection") self.tls = SSL.Connection(ctx, self.socket) dbg("Setting up TLS connection") self.tls.setup_ssl() dbg("Setting TLS connect state") self.tls.set_connect_state() dbg("Starting TLS handshake") # self.tls.setblocking(True) self.tls.connect_ssl() self.socket.setblocking(False) self.tls.setblocking(False) self.ssocket = self.socket self.socket = self.tls except Exception, e: try: self.socket.close() self.tls.close() dbg('There was an exception in TLS blocking_connect: %r', e) except Exception: pass raise e
def __init__(self, idpConfigFilePath=None, installOpener=False): if _M2CRYPTO_NOT_INSTALLED: raise ImportError("M2Crypto is required for SSL-based IdP " "validation but it is not installed.") super(SSLIdPValidationDriver, self).__init__() # Context object determines what validation is applied against the # peer's certificate in the SSL connection self.ctx = SSL.Context() # Enforce peer cert checking via this classes' __call__ method self.ctx.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, 9, callback=self) if installOpener: urllib2.install_opener(build_opener(ssl_context=self.ctx)) if idpConfigFilePath is not None: self.idPValidators += \ self.readConfig(idpConfigFilePath=idpConfigFilePath) log.info("%d IdPValidator(s) initialised", len(self.idPValidators))
def getM2SSLContext(ctx=None, **kwargs): """ Gets an M2Crypto.SSL.Context configured using the standard DIRAC connection keywords from kwargs. The keywords are: - clientMode: Boolean, if False hostcerts are always used. If True a proxy is used unless other flags are set. - useCertificates: Boolean, Set to true to use hostcerts in client mode. - proxyString: String, no-longer supported, used to allow a literal proxy string to be provided. - proxyLocation: String, Path to file to use as proxy, defaults to usual location(s) if not set. - skipCACheck: Boolean, if True, don't verify peer certificates. - sslMethod: String, List of SSL algorithms to enable in OpenSSL style cipher format, e.g. "SSLv3:TLSv1". - sslCiphers: String, OpenSSL style cipher string of ciphers to allow on this connection. If an existing context "ctx" is provided, it is just reconfigured with the selected arguments. Returns the new or updated context. """ if not ctx: ctx = SSL.Context() # Set certificates for connection # CHRIS: I think clientMode was just an internal of pyGSI implementation # if kwargs.get('clientMode', False) and not kwargs.get('useCertificates', False): # if not kwargs.get('useCertificates', False): if kwargs.get('bServerMode', False) or kwargs.get('useCertificates', False): # Server mode always uses hostcert __loadM2SSLCTXHostcert(ctx) else: # Client mode has a choice of possible options if kwargs.get('proxyString', None): # We don't support this any more, there is no easy way # to convert a proxy string to something usable by M2Crypto SSL # Try writing it to a temp file and use proxyLocation instead? raise RuntimeError("Proxy string no longer supported.") else: # Use normal proxy __loadM2SSLCTXProxy(ctx, proxyPath=kwargs.get('proxyLocation', None)) # Set peer verification if kwargs.get('skipCACheck', False): # Don't validate peer, but still request creds ctx.set_verify(SSL.verify_none, VERIFY_DEPTH) else: # Do validate peer ctx.set_verify(SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, VERIFY_DEPTH) # Set CA location caPath = Locations.getCAsLocation() if not caPath: raise RuntimeError("Failed to find CA location") if not os.path.isdir(caPath): raise RuntimeError("CA path (%s) is not a valid directory" % caPath) ctx.load_verify_locations(capath=caPath) # Other parameters sslMethod = kwargs.get('sslMethod', None) if sslMethod: # Pylint can't see the m2 constants due to the way the library is loaded # We just have to disable that warning for the next bit... # pylint: disable=no-member methods = [('SSLv2', m2.SSL_OP_NO_SSLv2), ('SSLv3', m2.SSL_OP_NO_SSLv3), ('TLSv1', m2.SSL_OP_NO_TLSv1)] allowed_methods = sslMethod.split(':') # If a method isn't explicitly allowed, set the flag to disable it... for method, method_flag in methods: if method not in allowed_methods: ctx.set_options(method_flag) # SSL_OP_NO_SSLv2, SSL_OP_NO_SSLv3, SSL_OP_NO_TLSv1 ciphers = kwargs.get('sslCiphers', DEFAULT_SSL_CIPHERS) ctx.set_cipher_list(ciphers) # log the debug messages # ctx.set_info_callback() return ctx
def request(self, method, url, body): """ Make the request against the Pulp server, returning a tuple of (status_code, respose_body). This method creates a new connection each time since HTTPSConnection has problems reusing a connection for multiple calls (as claimed by a prior comment in this module). :param method: The HTTP method to be used for the request (GET, POST, etc.) :type method: str :param url: The Pulp URL to make the request against :type url: str :param body: The body to pass with the request :type body: str :return: A 2-tuple of the status_code and response_body. status_code is the HTTP status code (200, 404, etc.). If the server's response is valid json, it will be parsed and response_body will be a dictionary. If not, it will be returned as a string. :rtype: tuple """ headers = dict(self.pulp_connection.headers ) # copy so we don't affect the calling method # Despite the confusing name, 'sslv23' configures m2crypto to use any available protocol in # the underlying openssl implementation. ssl_context = SSL.Context('sslv23') # This restricts the protocols we are willing to do by configuring m2 not to do SSLv2.0 or # SSLv3.0. EL 5 does not have support for TLS > v1.0, so we have to leave support for # TLSv1.0 enabled. ssl_context.set_options(m2.SSL_OP_NO_SSLv2 | m2.SSL_OP_NO_SSLv3) if self.pulp_connection.verify_ssl: ssl_context.set_verify(SSL.verify_peer, depth=100) # We need to stat the ca_path to see if it exists (error if it doesn't), and if so # whether it is a file or a directory. m2crypto has different directives depending on # which type it is. if os.path.isfile(self.pulp_connection.ca_path): ssl_context.load_verify_locations( cafile=self.pulp_connection.ca_path) elif os.path.isdir(self.pulp_connection.ca_path): ssl_context.load_verify_locations( capath=self.pulp_connection.ca_path) else: # If it's not a file and it's not a directory, it's not a valid setting raise exceptions.MissingCAPathException( self.pulp_connection.ca_path) ssl_context.set_session_timeout(self.pulp_connection.timeout) if self.pulp_connection.username and self.pulp_connection.password: raw = ':'.join( (self.pulp_connection.username, self.pulp_connection.password)) encoded = base64.encodestring(raw)[:-1] headers['Authorization'] = 'Basic ' + encoded elif self.pulp_connection.cert_filename: ssl_context.load_cert(self.pulp_connection.cert_filename) # oauth configuration. This block is only True if oauth is not None, so it won't run on RHEL # 5. if self.pulp_connection.oauth_key and self.pulp_connection.oauth_secret and oauth: oauth_consumer = oauth.Consumer(self.pulp_connection.oauth_key, self.pulp_connection.oauth_secret) oauth_request = oauth.Request.from_consumer_and_token( oauth_consumer, http_method=method, http_url='https://%s:%d%s' % (self.pulp_connection.host, self.pulp_connection.port, url)) oauth_request.sign_request(oauth.SignatureMethod_HMAC_SHA1(), oauth_consumer, None) oauth_header = oauth_request.to_header() # unicode header values causes m2crypto to do odd things. for k, v in oauth_header.items(): oauth_header[k] = encode_unicode(v) headers.update(oauth_header) headers['pulp-user'] = self.pulp_connection.oauth_user connection = httpslib.HTTPSConnection(self.pulp_connection.host, self.pulp_connection.port, ssl_context=ssl_context) try: # Request against the server connection.request(method, url, body=body, headers=headers) response = connection.getresponse() except SSL.SSLError, err: # Translate stale login certificate to an auth exception if 'sslv3 alert certificate expired' == str(err): raise exceptions.ClientCertificateExpiredException( self.pulp_connection.cert_filename) elif 'certificate verify failed' in str(err): raise exceptions.CertificateVerificationException() else: raise exceptions.ConnectionException(None, str(err), None)
def __init__(self, host=DEFAULT_HOST, port=DEFAULT_PORT, ssl=True): """ Initialize a new instance of the infrastructure manager service. Args: host Hostname to which the service should bind (Optional). Defaults to 0.0.0.0. port Port of the service (Optional). Default to 17444. ssl True if SSL should be engaged or False otherwise (Optional). Defaults to True. When engaged, this implementation expects to find the necessary SSL certificates in the /etc/appscale/certs directory. """ self.host = host self.port = port secret = None while True: try: secret = utils.get_secret(self.APPSCALE_DIR + 'secret.key') break except Exception: logging.info('Waiting for the secret key to become available') utils.sleep(5) logging.info('Found the secret set to: {0}'.format(secret)) SOAPpy.Config.simplify_objects = True if ssl: logging.info('Checking for the certificate and private key') cert = self.APPSCALE_DIR + 'certs/mycert.pem' key = self.APPSCALE_DIR + 'certs/mykey.pem' while True: if os.path.exists(cert) and os.path.exists(key): break else: logging.info('Waiting for certificates') utils.sleep(5) ssl_context = SSL.Context() ssl_context.load_cert(cert, key) self.server = SOAPpy.SOAPServer((host, port), ssl_context=ssl_context) else: self.server = SOAPpy.SOAPServer((host, port)) parent_dir = os.path.dirname(os.path.realpath(sys.argv[0])) config_file = os.path.join(parent_dir, self.CONFIG_FILE) if os.path.exists(config_file): with open(config_file) as file_handle: params = json.load(file_handle) if params.has_key(PersistentStoreFactory.PARAM_STORE_TYPE): logging.info( 'Loading infrastructure manager configuration from ' + config_file) i = InfrastructureManager(params) else: i = InfrastructureManager() else: i = InfrastructureManager() self.server.registerFunction(i.describe_operation) self.server.registerFunction(i.run_instances) self.server.registerFunction(i.terminate_instances) self.server.registerFunction(i.attach_disk) system_manager = SystemManager() self.server.registerFunction(system_manager.get_cpu_usage) self.server.registerFunction(system_manager.get_disk_usage) self.server.registerFunction(system_manager.get_memory_usage) self.server.registerFunction(system_manager.get_service_summary) self.server.registerFunction(system_manager.get_swap_usage) self.server.registerFunction(system_manager.get_loadavg) self.started = False
def test_ctx_set_default_verify_paths(self): ctx = SSL.Context() ctx.set_default_verify_paths()
def test_ctx_load_verify_locations(self): ctx = SSL.Context() with self.assertRaises(ValueError): ctx.load_verify_locations(None, None)
def createSSLContext(cfg): ctx = SSL.Context("sslv23") sslCert, sslKey = cfg.sslCert, cfg.sslKey ctx.load_cert_chain(sslCert, sslKey) return ctx
def connect(self): "Connect to a host on a given (SSL) port." new_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) new_socket.settimeout(self.timeout) self.sock = SSL.wrap_socket(new_socket) return self.sock.connect_ex((self.host, self.port))
def connect(self): # pylint: disable=too-many-branches """Connect to a host on a given (SSL) port.""" # Calling httplib.HTTPSConnection.connect(self) does not work # because of its ssl.wrap_socket() call. So we copy the code of # that connect() method modulo the ssl.wrap_socket() call. # # Another change is that we do not pass the timeout value # on to the socket call, because that does not work with M2Crypto. # # TODO AM: Check out whether we can pass the timeout for Python 3 # again, given that we use the standard SSL support again. if sys.version_info[0:2] >= (2, 7): # the source_address argument was added in 2.7 self.sock = socket.create_connection( (self.host, self.port), None, self.source_address) else: self.sock = socket.create_connection( (self.host, self.port), None) if self._tunnel_host: self._tunnel() # End of code from httplib.HTTPSConnection.connect(self). if _HAVE_M2CRYPTO: ctx = SSL.Context('sslv23') else: ctx = SSL.create_default_context() if self.cert_file: ctx.load_cert(self.cert_file, keyfile=self.key_file) if self.ca_certs: if _HAVE_M2CRYPTO: ctx.set_verify( SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, depth=9, callback=verify_callback) else: ctx.verify_flags |= SSL.VERIFY_CRL_CHECK_CHAIN if os.path.isdir(self.ca_certs): ctx.load_verify_locations(capath=self.ca_certs) else: ctx.load_verify_locations(cafile=self.ca_certs) try: if _HAVE_M2CRYPTO: self.sock = SSL.Connection(ctx, self.sock) else: self.sock = ctx.wrap_socket(self.sock) # Below is a body of SSL.Connection.connect() method # except for the first line (socket connection). We want to # preserve tunneling ability. # Setting the timeout on the input socket does not work # with M2Crypto, with such a timeout set it calls a different # low level function (nbio instead of bio) that does not work. # the symptom is that reading the response returns None. # Therefore, we set the timeout at the level of the outer # M2Crypto socket object. # pylint: disable=using-constant-test if False: # TODO 2/16 AM: Currently disabled, figure out how to # reenable. if self.timeout is not None: self.sock.set_socket_read_timeout( SSL.timeout(self.timeout)) self.sock.set_socket_write_timeout( SSL.timeout(self.timeout)) self.sock.addr = (self.host, self.port) self.sock.setup_ssl() self.sock.set_connect_state() ret = self.sock.connect_ssl() if self.ca_certs: check = getattr(self.sock, 'postConnectionCheck', self.sock.clientPostConnectionCheck) if check is not None: if not check(self.sock.get_peer_cert(), self.host): raise ConnectionError( 'SSL error: post connection check failed') return ret # TODO 2/16 AM: Verify whether the additional exceptions in the # Python 2 and M2Crypto code can really be omitted: # Err.SSLError, SSL.SSLError, SSL.Checker.WrongHost, # SSLTimeoutError except SSLError as arg: raise ConnectionError( "SSL error %s: %s" % (arg.__class__, arg))
def connect(self): # pylint: disable=too-many-branches """Connect to a host on a given (SSL) port.""" ## Connect for M2Crypto ssl package if _HAVE_M2CRYPTO: # Calling httplib.HTTPSConnection.connect(self) does not work # because of its ssl.wrap_socket() call. So we copy the code of # that connect() method modulo the ssl.wrap_socket() call. # Another change is that we do not pass the timeout value # on to the socket call, because that does not work with # M2Crypto. if sys.version_info[0:2] >= (2, 7): # the source_address argument was added in 2.7 self.sock = socket.create_connection( (self.host, self.port), None, self.source_address) else: self.sock = socket.create_connection( (self.host, self.port), None) # Removed code for tunneling support. # End of code from httplib.HTTPSConnection.connect(self). ctx = SSL.Context('sslv23') if self.cert_file: ctx.load_cert(self.cert_file, keyfile=self.key_file) if self.ca_certs: ctx.set_verify( SSL.verify_peer | SSL.verify_fail_if_no_peer_cert, depth=9, callback=verify_callback) if os.path.isdir(self.ca_certs): ctx.load_verify_locations(capath=self.ca_certs) else: ctx.load_verify_locations(cafile=self.ca_certs) try: self.sock = SSL.Connection(ctx, self.sock) # Below is a body of SSL.Connection.connect() method # except for the first line (socket connection). # Removed code for tunneling support. # Setting the timeout on the input socket does not work # with M2Crypto, with such a timeout set it calls a # different low level function (nbio instead of bio) # that does not work. The symptom is that reading the # response returns None. # Therefore, we set the timeout at the level of the outer # M2Crypto socket object. # pylint: disable=using-constant-test if self.timeout is not None: self.sock.set_socket_read_timeout( SSL.timeout(self.timeout)) self.sock.set_socket_write_timeout( SSL.timeout(self.timeout)) self.sock.addr = (self.host, self.port) self.sock.setup_ssl() self.sock.set_connect_state() ret = self.sock.connect_ssl() if self.ca_certs: check = getattr(self.sock, 'postConnectionCheck', self.sock.clientPostConnectionCheck) if check is not None: if not check(self.sock.get_peer_cert(), self.host): raise ConnectionError( 'SSL error: post connection check failed') return ret # TODO 2/16 AM: Verify whether the additional exceptions # in the M2Crypto code can # really be omitted: # Err.SSLError, SSL.SSLError, SSL.Checker. # WrongHost, # SSLTimeoutError except SSLError as arg: raise ConnectionError( "SSL error %s: %s" % (arg.__class__, arg)) # Connect using Python SSL module else: # Setup the socket context # TODO ks 4/16: confirm that we cannot use the default_context() # Selects the highest protocol version that both the # client and server support (SSLV23) ctx = SSL.SSLContext(SSL.PROTOCOL_SSLv23) # TODO ks 4/16: Is there a use for the CERT_OPTIONAL mode if self.cert_file: ctx.load_cert(self.cert_file, keyfile=self.key_file) if self.ca_certs: # CERT_REQUIRED validates server certificate: # against certificates in ca_certs ctx.verify_mode = SSL.CERT_REQUIRED if os.path.isdir(self.ca_certs): ctx.load_verify_locations(capath=self.ca_certs) else: ctx.load_verify_locations(cafile=self.ca_certs) ctx.check_hostname = True else: ctx.check_hostname = False ctx.verify_mode = SSL.CERT_NONE # setup the socket sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(self.timeout) try: self.sock = ctx.wrap_socket(sock, server_hostname=self.host) return self.sock.connect((self.host, self.port)) except SSLError as arg: raise ConnectionError( "SSL error %s: %s" % (arg.__class__, arg)) except CertificateError as arg: raise ConnectionError( "SSL certificate error %s: %s" % (arg.__class__, arg))