def _connect_socket(self): sockerr = None inet_address, port = self.endpoint.resolve() addresses = socket.getaddrinfo(inet_address, port, socket.AF_UNSPEC, socket.SOCK_STREAM) if not addresses: raise ConnectionException("getaddrinfo returned empty list for %s" % (self.endpoint,)) for (af, socktype, proto, canonname, sockaddr) in addresses: try: self._socket = self._socket_impl.socket(af, socktype, proto) if self.ssl_context: self._socket = self.ssl_context.wrap_socket(self._socket, **(self.ssl_options or {})) elif self.ssl_options: if not self._ssl_impl: raise RuntimeError("This version of Python was not compiled with SSL support") self._socket = self._ssl_impl.wrap_socket(self._socket, **self.ssl_options) self._socket.settimeout(self.connect_timeout) self._socket.connect(sockaddr) self._socket.settimeout(None) if self._check_hostname: ssl.match_hostname(self._socket.getpeercert(), self.endpoint.address) sockerr = None break except socket.error as err: if self._socket: self._socket.close() self._socket = None sockerr = err if sockerr: raise socket.error(sockerr.errno, "Tried connecting to %s. Last error: %s" % ([a[4] for a in addresses], sockerr.strerror or sockerr)) if self.sockopts: for args in self.sockopts: self._socket.setsockopt(*args)
def __init__(self, host='127.0.0.1', port=6667, usessl=False, nick="Robot", user="******", longuser="******", chans={"#yolo"}): if usessl: # Set up an SSL socket try: context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) except: print("ERROR: Can't create an SSL context. You're probably trying to connect using SSL under Python 2. You need to use Python 3.") raise context.verify_mode = ssl.CERT_REQUIRED context.load_verify_locations("/etc/ssl/cert.pem") # May be different for different systems context.set_ciphers("DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256") # Only the good ones self.s = context.wrap_socket(socket.socket(socket.AF_INET)) self.s.connect((host,port)) cert = self.s.getpeercert() ssl.match_hostname(cert,host) print("Successfully connected using cipher %s. Huzzah!"%self.s.cipher()[0]) else: # Set up a normal socket self.s = socket.socket() self.s.connect((host,port)) self.f = self.s.makefile() self.write = lambda x : self.s.send(x.encode('UTF-8') + crlf) self.read = self.f.readline self.nick = nick self.write('NICK ' + nick) self.write('USER ' + user + ' * * :' + longuser) if chans: for chan in chans: self.write('JOIN ' + chan) self.chans = set(chans)
def connect(self): """Connect to Mongo and return a new (connected) socket. Note that the pool does not keep a reference to the socket -- you must call return_socket() when you're done with it. """ sock = self.create_connection() hostname = self.pair[0] if self.use_ssl: try: sock = ssl.wrap_socket(sock, certfile=self.ssl_certfile, keyfile=self.ssl_keyfile, ca_certs=self.ssl_ca_certs, cert_reqs=self.ssl_cert_reqs) if self.ssl_cert_reqs: match_hostname(sock.getpeercert(), hostname) except ssl.SSLError: sock.close() raise ConnectionFailure("SSL handshake failed. MongoDB may " "not be configured with SSL support.") sock.settimeout(self.net_timeout) return SocketInfo(sock, self.pool_id, hostname)
def _configured_socket(address, options): """Given (host, port) and PoolOptions, return a configured socket. Can raise socket.error, ConnectionFailure, or CertificateError. Sets socket's SSL and timeout options. """ sock = _create_connection(address, options) ssl_context = options.ssl_context if ssl_context is not None: try: sock = ssl_context.wrap_socket(sock) except IOError as exc: sock.close() raise ConnectionFailure("SSL handshake failed: %s" % (str(exc),)) if ssl_context.verify_mode and options.ssl_match_hostname: try: match_hostname(sock.getpeercert(), hostname=address[0]) except CertificateError: sock.close() raise sock.settimeout(options.socket_timeout) return sock
def connect(self, url, **options): """ Connect to url. url is websocket url scheme. ie. ws://host:port/resource You can customize using 'options'. If you set "header" dict object, you can set your own custom header. >>> ws = WebSocket() >>> ws.connect("ws://echo.websocket.org/", ... header={"User-Agent: MyProgram", ... "x-custom: header"}) timeout: socket timeout time. This value is integer. if you set None for this value, it means "use default_timeout value" options: current support option is only "header". if you set header as dict value, the custom HTTP headers are added. """ hostname, port, resource, is_secure = _parse_url(url) # TODO: we need to support proxy self.sock.connect((hostname, port)) if is_secure: if HAVE_SSL: sslopt = dict(cert_reqs=ssl.CERT_REQUIRED, ca_certs=os.path.join(os.path.dirname(__file__), "cacert.pem")) sslopt.update(self.sslopt) self.sock = ssl.wrap_socket(self.sock, **sslopt) match_hostname(self.sock.getpeercert(), hostname) else: raise WebSocketException("SSL not available.") self._handshake(hostname, port, resource, **options)
def connect(self): if self._tunnel_host: server_hostname = self._tunnel_host else: server_hostname = self.host sni_hostname = server_hostname if ssl.HAS_SNI else None # will be useful eventually ns = yield from self._create_connection((self.host, self.port), self.timeout, self.source_address, ssl=self._context, server_hostname=server_hostname) self.notSock = ns if self._tunnel_host: yield from self._tunnel() self.auto_open = 0 # self.sock = self._context.wrap_socket(self.sock, server_hostname=sni_hostname, # do_handshake_on_connect=False) if not self._context.check_hostname and self._check_hostname: try: #sock = self.notSock.socket() ssl.match_hostname(self.notSock.peercert(), server_hostname) except Exception as e: self.close() raise
def connect(self): self.connection_kwargs = {} # for > py2.5 if hasattr(self, 'timeout'): self.connection_kwargs.update(timeout = self.timeout) # for >= py2.7 if hasattr(self, 'source_address'): self.connection_kwargs.update(source_address = self.source_address) sock = socket.create_connection((self.host, self.port), **self.connection_kwargs) # for >= py2.7 if getattr(self, '_tunnel_host', None): self.sock = sock self._tunnel() # set location of certificate authorities assert os.path.isfile(tuf.conf.ssl_certificates) cert_path = tuf.conf.ssl_certificates # TODO: Disallow SSLv2. # http://docs.python.org/dev/library/ssl.html#protocol-versions # TODO: Select the right ciphers. # http://docs.python.org/dev/library/ssl.html#cipher-selection self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, cert_reqs=ssl.CERT_REQUIRED, ca_certs=cert_path) match_hostname(self.sock.getpeercert(), self.host)
def _verify_cert(self, sock: ssl.SSLSocket): '''Check if certificate matches hostname.''' # Based on tornado.iostream.SSLIOStream # Needed for older OpenSSL (<0.9.8f) versions verify_mode = self._ssl_context.verify_mode assert verify_mode in (ssl.CERT_NONE, ssl.CERT_REQUIRED, ssl.CERT_OPTIONAL), \ 'Unknown verify mode {}'.format(verify_mode) if verify_mode == ssl.CERT_NONE: return cert = sock.getpeercert() if not cert and verify_mode == ssl.CERT_OPTIONAL: return if not cert: raise SSLVerificationError('No SSL certificate given') try: ssl.match_hostname(cert, self._hostname) except ssl.CertificateError as error: raise SSLVerificationError('Invalid SSL certificate') from error
def create_connection(server=None, port=None, timeout=None, use_ssl=False): """Create a socket or a secure ssl socket. Hopefully some day such functionality will be included in python3. :returns socket :rtype socket.SocketType """ # based on socket.create_connection() if use_ssl: context = ssl_create_default_context() err = None for af, socktype, proto, canonname, sa in \ socket.getaddrinfo(server, port, 0, socket.SOCK_STREAM): sock = None try: sock = socket.socket(af, socktype, proto) if timeout is not None: sock.settimeout(timeout) if use_ssl: sock = context.wrap_socket(sock, server_hostname=server) sock.connect(sa) if use_ssl: match_hostname(sock.getpeercert(), server) return sock except socket.error as _: err = _ if sock is not None: sock.close() if err is not None: raise err else: raise socket.error("getaddrinfo returns an empty list")
def connect(self): sock = socket.create_connection( (self.host, self.port), getattr(self, 'source_address', None) ) # Handle the socket if a (proxy) tunnel is present if hasattr(self, '_tunnel') and getattr(self, '_tunnel_host', None): self.sock = sock self._tunnel() # http://bugs.python.org/issue7776: Python>=3.4.1 and >=2.7.7 # change self.host to mean the proxy server host when tunneling is # being used. Adapt, since we are interested in the destination # host for the match_hostname() comparison. actual_host = self._tunnel_host else: actual_host = self.host self.sock = ssl.wrap_socket( sock, cert_reqs=ssl.CERT_REQUIRED, ca_certs=self.ca_bundle ) try: match_hostname(self.sock.getpeercert(), actual_host) except CertificateError: self.sock.shutdown(socket.SHUT_RDWR) self.sock.close() raise
def _create_ssl_connection(self, sock): self._logger.debug("Creating ssl connection...") ssl_protocol_version = ssl.PROTOCOL_SSLv23 if self._port == 443: ssl_context = SSLContextBuilder()\ .with_ca_certs(self._ca_path)\ .with_cert_key_pair(self._cert_path, self._key_path)\ .with_cert_reqs(ssl.CERT_REQUIRED)\ .with_check_hostname(True)\ .with_ciphers(None)\ .with_alpn_protocols(['x-amzn-http-ca'])\ .build() ssl_sock = ssl_context.wrap_socket(sock, server_hostname=self._host, do_handshake_on_connect=False) ssl_sock.do_handshake() else: ssl_sock = ssl.wrap_socket(sock, certfile=self._cert_path, keyfile=self._key_path, ca_certs=self._ca_path, cert_reqs=ssl.CERT_REQUIRED, ssl_version=ssl_protocol_version) self._logger.debug("Matching host name...") if sys.version_info[0] < 3 or (sys.version_info[0] == 3 and sys.version_info[1] < 2): self._tls_match_hostname(ssl_sock) else: ssl.match_hostname(ssl_sock.getpeercert(), self._host) return ssl_sock
def connect(self, host=None, port=None, address_family=None): """ Method that initiates a connection to an EPP host """ host = host or self.host self.sock = socket.socket(address_family or socket.AF_INET, socket.SOCK_STREAM) self.sock.settimeout(self.socket_connect_timeout) # connect timeout self.sock.connect((host, port or self.port)) local_sock_addr = self.sock.getsockname() local_addr, local_port = local_sock_addr[:2] self.log.debug('connected local=%s:%s remote=%s:%s', local_addr, local_port, self.sock.getpeername()[0], port) self.sock.settimeout(self.socket_timeout) # regular timeout if self.ssl_enable: self.sock = ssl.wrap_socket(self.sock, self.keyfile, self.certfile, ssl_version=self.ssl_version, ciphers=self.ssl_ciphers, server_side=False, cert_reqs=self.cert_required, ca_certs=self.cacerts) self.log.debug('%s negotiated with local=%s:%s remote=%s:%s', self.sock.version(), local_addr, local_port, self.sock.getpeername()[0], port) if self.validate_hostname: try: match_hostname(self.sock.getpeercert(), host) except CertificateError as exp: self.log.exception("SSL hostname mismatch") raise EppConnectionError(str(exp)) self.greeting = EppResponse.from_xml(self.read().decode('utf-8'))
def check_hostname(sock, server_name, additional_names): server_certificate = sock.getpeercert() if log_enabled(NETWORK): log(NETWORK, 'certificate found for %s: %s', sock, server_certificate) if additional_names: host_names = [server_name] + (additional_names if isinstance(additional_names, SEQUENCE_TYPES) else [additional_names]) else: host_names = [server_name] for host_name in host_names: if not host_name: continue elif host_name == '*': if log_enabled(NETWORK): log(NETWORK, 'certificate matches * wildcard') return # valid try: match_hostname(server_certificate, host_name) # raise CertificateError if certificate doesn't match server name if log_enabled(NETWORK): log(NETWORK, 'certificate matches host name <%s>', host_name) return # valid except CertificateError as e: if log_enabled(NETWORK): log(NETWORK, str(e)) if log_enabled(ERROR): log(ERROR, "hostname doesn't match certificate") raise LDAPCertificateError("certificate %s doesn't match any name in %s " % (server_certificate, str(host_names)))
def http_request(self, req): tmp_ca_cert_path, paths_checked = self.get_ca_certs() https_proxy = os.environ.get('https_proxy') context = None if HAS_SSLCONTEXT: context = self._make_context(tmp_ca_cert_path) # Detect if 'no_proxy' environment variable is set and if our URL is included use_proxy = self.detect_no_proxy(req.get_full_url()) if not use_proxy: # ignore proxy settings for this host request return req try: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) if https_proxy: proxy_parts = generic_urlparse(urlparse.urlparse(https_proxy)) port = proxy_parts.get('port') or 443 s.connect((proxy_parts.get('hostname'), port)) if proxy_parts.get('scheme') == 'http': s.sendall(self.CONNECT_COMMAND % (self.hostname, self.port)) if proxy_parts.get('username'): credentials = "%s:%s" % (proxy_parts.get('username',''), proxy_parts.get('password','')) s.sendall('Proxy-Authorization: Basic %s\r\n' % credentials.encode('base64').strip()) s.sendall('\r\n') connect_result = s.recv(4096) self.validate_proxy_response(connect_result) if context: ssl_s = context.wrap_socket(s, server_hostname=self.hostname) else: ssl_s = ssl.wrap_socket(s, ca_certs=tmp_ca_cert_path, cert_reqs=ssl.CERT_REQUIRED, ssl_version=PROTOCOL) match_hostname(ssl_s.getpeercert(), self.hostname) else: raise ProxyError('Unsupported proxy scheme: %s. Currently ansible only supports HTTP proxies.' % proxy_parts.get('scheme')) else: s.connect((self.hostname, self.port)) if context: ssl_s = context.wrap_socket(s, server_hostname=self.hostname) else: ssl_s = ssl.wrap_socket(s, ca_certs=tmp_ca_cert_path, cert_reqs=ssl.CERT_REQUIRED, ssl_version=PROTOCOL) match_hostname(ssl_s.getpeercert(), self.hostname) # close the ssl connection #ssl_s.unwrap() s.close() except (ssl.SSLError, socket.error), e: # fail if we tried all of the certs but none worked if 'connection refused' in str(e).lower(): raise ConnectionError('Failed to connect to %s:%s.' % (self.hostname, self.port)) else: raise SSLValidationError('Failed to validate the SSL certificate for %s:%s.' ' Make sure your managed systems have a valid CA' ' certificate installed. If the website serving the url' ' uses SNI you need python >= 2.7.9 on your managed' ' machine. You can use validate_certs=False if you do' ' not need to confirm the server\s identity but this is' ' unsafe and not recommended' ' Paths checked for this platform: %s' % (self.hostname, self.port, ", ".join(paths_checked)) )
def connect(self, url, **options): """ Connect to url. url is websocket url scheme. ie. ws://host:port/resource You can customize using 'options'. If you set "header" list object, you can set your own custom header. >>> ws = WebSocket() >>> ws.connect("ws://echo.websocket.org/", ... header=["User-Agent: MyProgram", ... "x-custom: header"]) timeout: socket timeout time. This value is integer. if you set None for this value, it means "use default_timeout value" options: "header" -> custom http header list. "cookie" -> cookie value. "http_proxy_host" - http proxy host name. "http_proxy_port" - http proxy port. If not set, set to 80. """ hostname, port, resource, is_secure = _parse_url(url) proxy_host, proxy_port = options.get("http_proxy_host", None), options.get("http_proxy_port", 0) if not proxy_host: addrinfo_list = socket.getaddrinfo(hostname, port, 0, 0, socket.SOL_TCP) else: proxy_port = proxy_port and proxy_port or 80 addrinfo_list = socket.getaddrinfo(proxy_host, proxy_port, 0, 0, socket.SOL_TCP) if not addrinfo_list: raise WebSocketException("Host not found.: " + hostname + ":" + str(port)) family = addrinfo_list[0][0] self.sock = socket.socket(family) self.sock.settimeout(self.timeout) for opts in DEFAULT_SOCKET_OPTION: self.sock.setsockopt(*opts) for opts in self.sockopt: self.sock.setsockopt(*opts) # TODO: we need to support proxy address = addrinfo_list[0][4] self.sock.connect(address) if proxy_host: self._tunnel(hostname, port) if is_secure: if HAVE_SSL: sslopt = dict( cert_reqs=ssl.CERT_REQUIRED, ca_certs=os.path.join(os.path.dirname(__file__), "cacert.pem") ) sslopt.update(self.sslopt) self.sock = ssl.wrap_socket(self.sock, **sslopt) match_hostname(self.sock.getpeercert(), hostname) else: raise WebSocketException("SSL not available.") self._handshake(hostname, port, resource, **options)
def connect(self, address, timeout=5): sock = self.ssl_context().wrap_socket( socket.socket(socket.AF_INET, socket.SOCK_STREAM)) sock.settimeout(timeout) sock.connect(address) ssl.match_hostname(sock.getpeercert(), address[0]) self.socket = sock self.time_sent = time.time() self.time_received = self.time_sent
def match_hostname(self): cert = self.c.sock.getpeercert() try: ssl.match_hostname(cert, self.c.host) except AttributeError: # old ssl module doesn't have this function return except ValueError: # empty SSL cert means underlying SSL library didn't validate it, we don't either. return except ssl.CertificateError, e: self.match_hostname_aws(cert, e)
def connect(self): """Connect to the host and port specified in __init__.""" sock = socket.create_connection((self.host, self.port), self.timeout, self.source_address) if self._tunnel_host: self.sock = sock self._tunnel() if not os.path.exists(ca_certs): raise Exception("CA Certifcate bundle %s is not readable" % ca_certs) self.sock = ssl.wrap_socket(sock, ca_certs=ca_certs, cert_reqs=ssl.CERT_REQUIRED) ssl.match_hostname(self.sock.getpeercert(), self.host)
def send_cmd(self, *cmd): """Overrides Client.connect_server""" if self.password is None: password = b'' else: password = self.password.encode() tmp = [password, self.keyfile] tmp.extend(cmd) cmd_chain = build_message(tmp) try: tmp_conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM) if self.context is not None: conn = self.context.wrap_socket(tmp_conn) else: conn = tmp_conn conn.connect(self.server_address) except: raise else: logging.info('Connected to '+self.server_address[0]+':'+ str(self.server_address[1])) try: conn.settimeout(60) if self.context is not None: if not isfile(self.tls_dir.decode() + '/pin'): sha = sha256() sha.update(conn.getpeercert(True)) with open(self.tls_dir.decode() + '/pin', 'wb') as pin: pin.write(sha.digest()) else: with open(self.tls_dir.decode() + '/pin', 'rb') as pin: pinned_key = pin.read() sha = sha256() sha.update(conn.getpeercert(True)) if pinned_key != sha.digest(): return (b'FAIL: Server certificate differs from ' b'pinned certificate') cert = conn.getpeercert() try: ssl.match_hostname(cert, "KeePassC Server") except: return b'FAIL: TLS - Hostname does not match' sendmsg(conn, cmd_chain) answer = receive(conn) except: raise finally: conn.shutdown(socket.SHUT_RDWR) conn.close() return answer
def set_ssl(self, ssl_mode, ssl_ca, ssl_crl, ssl_cert, ssl_key): """Set SSL parameters. Args: ssl_mode (str): SSL mode. ssl_ca (str): The certification authority certificate. ssl_crl (str): The certification revocation lists. ssl_cert (str): The certificate. ssl_key (str): The certificate key. Raises: :class:`mysqlx.RuntimeError`: If Python installation has no SSL support. :class:`mysqlx.InterfaceError`: If the parameters are invalid. """ if not SSL_AVAILABLE: self.close() raise RuntimeError("Python installation has no SSL support") context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) context.load_default_certs() if ssl_ca: try: context.load_verify_locations(ssl_ca) context.verify_mode = ssl.CERT_REQUIRED except (IOError, ssl.SSLError) as err: self.close() raise InterfaceError("Invalid CA Certificate: {}".format(err)) if ssl_crl: try: context.load_verify_locations(ssl_crl) context.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF except (IOError, ssl.SSLError) as err: self.close() raise InterfaceError("Invalid CRL: {}".format(err)) if ssl_cert: try: context.load_cert_chain(ssl_cert, ssl_key) except (IOError, ssl.SSLError) as err: self.close() raise InterfaceError("Invalid Certificate/Key: {}".format(err)) self._socket = context.wrap_socket(self._socket) if ssl_mode == SSLMode.VERIFY_IDENTITY: try: hostname = socket.gethostbyaddr(self._host) ssl.match_hostname(self._socket.getpeercert(), hostname[0]) except ssl.CertificateError as err: self.close() raise InterfaceError("Unable to verify server identity: {}" "".format(err)) self._is_ssl = True
def connect(self): # Add certificate verification conn = self._new_conn() resolved_cert_reqs = resolve_cert_reqs(self.cert_reqs) resolved_ssl_version = resolve_ssl_version(self.ssl_version) hostname = self.host if getattr(self, '_tunnel_host', None): # _tunnel_host was added in Python 2.6.3 # (See: http://hg.python.org/cpython/rev/0f57b30a152f) self.sock = conn # Calls self._set_hostport(), so self.host is # self._tunnel_host below. self._tunnel() # Mark this connection as not reusable self.auto_open = 0 # Override the host with the one we're requesting data from. hostname = self._tunnel_host is_time_off = datetime.date.today() < RECENT_DATE if is_time_off: warnings.warn(( 'System time is way off (before {0}). This will probably ' 'lead to SSL verification errors').format(RECENT_DATE), SystemTimeWarning ) # Wrap socket using verification with the root certs in # trusted_root_certs self.sock = ssl_wrap_socket(conn, self.key_file, self.cert_file, cert_reqs=resolved_cert_reqs, ca_certs=self.ca_certs, server_hostname=hostname, ssl_version=resolved_ssl_version) if self.assert_fingerprint: assert_fingerprint(self.sock.getpeercert(binary_form=True), self.assert_fingerprint) elif resolved_cert_reqs != ssl.CERT_NONE \ and self.assert_hostname is not False: cert = self.sock.getpeercert() if not cert.get('subjectAltName', ()): warnings.warn(( 'Certificate has no `subjectAltName`, falling back to check for a `commonName` for now. ' 'This feature is being removed by major browsers and deprecated by RFC 2818. ' '(See https://github.com/shazow/urllib3/issues/497 for details.)'), SecurityWarning ) match_hostname(cert, self.assert_hostname or hostname) self.is_verified = (resolved_cert_reqs == ssl.CERT_REQUIRED or self.assert_fingerprint is not None)
def _on_handshake(self): try: self._sock.do_handshake() except ssl.SSLWantReadError: self._loop.add_reader(self._sock_fd, self._on_handshake) return except ssl.SSLWantWriteError: self._loop.add_writer(self._sock_fd, self._on_handshake) return except Exception as exc: self._loop.remove_reader(self._sock_fd) self._loop.remove_writer(self._sock_fd) self._sock.close() if self._waiter is not None: self._waiter.set_exception(exc) return except BaseException as exc: self._loop.remove_reader(self._sock_fd) self._loop.remove_writer(self._sock_fd) self._sock.close() if self._waiter is not None: self._waiter.set_exception(exc) raise self._loop.remove_reader(self._sock_fd) self._loop.remove_writer(self._sock_fd) peercert = self._sock.getpeercert() if not hasattr(self._sslcontext, 'check_hostname'): # Verify hostname if requested, Python 3.4+ uses check_hostname # and checks the hostname in do_handshake() if (self._server_hostname and self._sslcontext.verify_mode != ssl.CERT_NONE): try: ssl.match_hostname(peercert, self._server_hostname) except Exception as exc: self._sock.close() if self._waiter is not None: self._waiter.set_exception(exc) return # Add extra info that becomes available after handshake. self._extra.update(peercert=peercert, cipher=self._sock.cipher(), compression=self._sock.compression(), ) self._read_wants_write = False self._write_wants_read = False self._loop.add_reader(self._sock_fd, self._read_ready) self._loop.call_soon(self._protocol.connection_made, self) if self._waiter is not None: # wait until protocol.connection_made() has been called self._loop.call_soon(self._waiter._set_result_unless_cancelled, None)
def _on_handshake(self, start_time): try: self._sock.do_handshake() except ssl.SSLWantReadError: self._loop.add_reader(self._sock_fd, self._on_handshake, start_time) return except ssl.SSLWantWriteError: self._loop.add_writer(self._sock_fd, self._on_handshake, start_time) return except BaseException as exc: if self._loop.get_debug(): logger.warning("%r: SSL handshake failed", self, exc_info=True) self._loop.remove_reader(self._sock_fd) self._loop.remove_writer(self._sock_fd) self._sock.close() if self._waiter is not None: self._waiter.set_exception(exc) if isinstance(exc, Exception): return else: raise self._loop.remove_reader(self._sock_fd) self._loop.remove_writer(self._sock_fd) peercert = self._sock.getpeercert() if not hasattr(self._sslcontext, "check_hostname"): # Verify hostname if requested, Python 3.4+ uses check_hostname # and checks the hostname in do_handshake() if self._server_hostname and self._sslcontext.verify_mode != ssl.CERT_NONE: try: ssl.match_hostname(peercert, self._server_hostname) except Exception as exc: if self._loop.get_debug(): logger.warning("%r: SSL handshake failed " "on matching the hostname", self, exc_info=True) self._sock.close() if self._waiter is not None: self._waiter.set_exception(exc) return # Add extra info that becomes available after handshake. self._extra.update(peercert=peercert, cipher=self._sock.cipher(), compression=self._sock.compression()) self._read_wants_write = False self._write_wants_read = False self._loop.add_reader(self._sock_fd, self._read_ready) self._loop.call_soon(self._protocol.connection_made, self) if self._waiter is not None: # wait until protocol.connection_made() has been called self._loop.call_soon(self._waiter._set_result_unless_cancelled, None) if self._loop.get_debug(): dt = self._loop.time() - start_time logger.debug("%r: SSL handshake took %.1f ms", self, dt * 1e3)
def match_hostname(self): cert = self.c.sock.getpeercert() try: ssl.match_hostname(cert, self.hostname) except AttributeError: # old ssl module doesn't have this function return except ValueError: # empty SSL cert means underlying SSL library didn't validate it, we don't either. return except ssl.CertificateError as e: if not self.forgive_wildcard_cert(cert, self.hostname): raise e
def _on_handshake_complete(self, handshake_exc): self._in_handshake = False sslobj = self._sslpipe.ssl_object try: if handshake_exc is not None: raise handshake_exc peercert = sslobj.getpeercert() if not hasattr(self._sslcontext, 'check_hostname'): # Verify hostname if requested, Python 3.4+ uses check_hostname # and checks the hostname in do_handshake() if (self._server_hostname and self._sslcontext.verify_mode != ssl.CERT_NONE): ssl.match_hostname(peercert, self._server_hostname) except BaseException as exc: if self._loop.get_debug(): if (hasattr(ssl, 'CertificateError') and isinstance(exc, ssl.CertificateError)): logger.warning("%r: SSL handshake failed " "on verifying the certificate", self, exc_info=True) else: logger.warning("%r: SSL handshake failed", self, exc_info=True) self._transport.close() if isinstance(exc, Exception): if self._waiter is not None and not self._waiter.cancelled(): self._waiter.set_exception(exc) return else: raise if self._loop.get_debug(): dt = self._loop.time() - self._handshake_start_time logger.debug("%r: SSL handshake took %.1f ms", self, dt * 1e3) # Add extra info that becomes available after handshake. self._extra.update(peercert=peercert, cipher=sslobj.cipher(), compression=sslobj.compression(), ) self._app_protocol.connection_made(self._app_transport) if self._waiter is not None: # wait until protocol.connection_made() has been called self._waiter._set_result_unless_cancelled(None) self._session_established = True # In case transport.write() was already called. Don't call # immediatly _process_write_backlog(), but schedule it: # _on_handshake_complete() can be called indirectly from # _process_write_backlog(), and _process_write_backlog() is not # reentrant. self._loop.call_soon(self._process_write_backlog)
def connect(self): # Add certificate verification sock = socket.create_connection((self.host, self.port), self.timeout) # Wrap socket using verification with the root certs in # trusted_root_certs self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, cert_reqs=self.cert_reqs, ca_certs=self.ca_certs, ssl_version=self.ssl_version, ciphers=self.ciphers) if self.ca_certs: match_hostname(self.sock.getpeercert(), self.host)
def matches_hostname(cls, certificate: cryptography.x509.Certificate, hostname: str) -> None: """Verify that the certificate was issued for the given hostname. Raises: CertificateError: If the certificate was not issued for the supplied hostname. """ # Extract the names from the certificate to create the properly-formatted dictionary certificate_names = { 'subject': (tuple([('commonName', name) for name in cls.get_common_names(certificate.subject)]),), 'subjectAltName': tuple([('DNS', name) for name in cls.get_dns_subject_alternative_names(certificate)]), } # CertificateError is raised on failure ssl.match_hostname(certificate_names, hostname) # type: ignore
def connect(self): sock = create_connection( (self.host, self.port), getattr(self,'source_address',None) ) self.sock = ssl.wrap_socket( sock, cert_reqs=ssl.CERT_REQUIRED, ca_certs=self.ca_bundle ) try: match_hostname(self.sock.getpeercert(), self.host) except CertificateError: self.sock.shutdown(socket.SHUT_RDWR) self.sock.close() raise
def connect(self): sock = socket.create_connection((self.host, self.port), self.timeout, self.source_address) if self._tunnel_host: self.sock = sock self._tunnel() server_hostname = self.host if ssl.HAS_SNI else None self.sock = self._context.wrap_socket(sock, server_hostname=server_hostname) try: while self._check_hostname: ssl.match_hostname(self.sock.getpeercert(), self.host) except Exception: self.sock.shutdown(socket.SHUT_RDWR) self.sock.close() raise
def check_x509_hostname(x509, hostname): """ Check whether the given :class:`OpenSSL.crypto.X509` certificate `x509` matches the given `hostname`. Return :data:`True` if the name matches and :data:`False` otherwise. This uses :func:`ssl.match_hostname` and :func:`extract_python_dict_from_x509`. """ cert_structure = extract_python_dict_from_x509(x509) try: ssl.match_hostname(cert_structure, hostname) except ssl.CertificateError: return False return True
def http_request(self, req): tmp_ca_cert_path, paths_checked = self.get_ca_certs() https_proxy = os.environ.get('https_proxy') context = None if HAS_SSLCONTEXT: context = self._make_context(tmp_ca_cert_path) # Detect if 'no_proxy' environment variable is set and if our URL is included use_proxy = self.detect_no_proxy(req.get_full_url()) if not use_proxy: # ignore proxy settings for this host request return req try: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) if https_proxy: proxy_parts = generic_urlparse(urlparse.urlparse(https_proxy)) s.connect( (proxy_parts.get('hostname'), proxy_parts.get('port'))) if proxy_parts.get('scheme') == 'http': s.sendall(self.CONNECT_COMMAND % (self.hostname, self.port)) if proxy_parts.get('username'): credentials = "%s:%s" % (proxy_parts.get( 'username', ''), proxy_parts.get('password', '')) s.sendall('Proxy-Authorization: Basic %s\r\n' % credentials.encode('base64').strip()) s.sendall('\r\n') connect_result = s.recv(4096) self.validate_proxy_response(connect_result) if context: ssl_s = context.wrap_socket( s, server_hostname=proxy_parts.get('hostname')) else: ssl_s = ssl.wrap_socket(s, ca_certs=tmp_ca_cert_path, cert_reqs=ssl.CERT_REQUIRED, ssl_version=PROTOCOL) match_hostname(ssl_s.getpeercert(), self.hostname) else: raise ProxyError( 'Unsupported proxy scheme: %s. Currently ansible only supports HTTP proxies.' % proxy_parts.get('scheme')) else: s.connect((self.hostname, self.port)) if context: ssl_s = context.wrap_socket(s, server_hostname=self.hostname) else: ssl_s = ssl.wrap_socket(s, ca_certs=tmp_ca_cert_path, cert_reqs=ssl.CERT_REQUIRED, ssl_version=PROTOCOL) match_hostname(ssl_s.getpeercert(), self.hostname) # close the ssl connection #ssl_s.unwrap() s.close() except (ssl.SSLError, socket.error), e: # fail if we tried all of the certs but none worked if 'connection refused' in str(e).lower(): raise ConnectionError('Failed to connect to %s:%s.' % (self.hostname, self.port)) else: raise SSLValidationError( 'Failed to validate the SSL certificate for %s:%s.' ' Make sure your managed systems have a valid CA' ' certificate installed. If the website serving the url' ' uses SNI you need python >= 2.7.9 on your managed' ' machine. You can use validate_certs=False if you do' ' not need to confirm the server\s identity but this is' ' unsafe and not recommended' ' Paths checked for this platform: %s' % (self.hostname, self.port, ", ".join(paths_checked)))
def http_request(self, req): tmp_ca_cert_path, to_add_ca_cert_path, paths_checked = self.get_ca_certs( ) https_proxy = os.environ.get('https_proxy') context = None try: context = self._make_context(to_add_ca_cert_path) except Exception: # We'll make do with no context below pass # Detect if 'no_proxy' environment variable is set and if our URL is included use_proxy = self.detect_no_proxy(req.get_full_url()) if not use_proxy: # ignore proxy settings for this host request if tmp_ca_cert_path: try: os.remove(tmp_ca_cert_path) except OSError: pass if to_add_ca_cert_path: try: os.remove(to_add_ca_cert_path) except OSError: pass return req try: if https_proxy: proxy_parts = generic_urlparse(urlparse(https_proxy)) port = proxy_parts.get('port') or 443 s = socket.create_connection( (proxy_parts.get('hostname'), port)) if proxy_parts.get('scheme') == 'http': s.sendall( to_bytes(self.CONNECT_COMMAND % (self.hostname, self.port), errors='surrogate_or_strict')) if proxy_parts.get('username'): credentials = "%s:%s" % (proxy_parts.get( 'username', ''), proxy_parts.get('password', '')) s.sendall( b'Proxy-Authorization: Basic %s\r\n' % base64.b64encode( to_bytes( credentials, errors='surrogate_or_strict')).strip()) s.sendall(b'\r\n') connect_result = b"" while connect_result.find(b"\r\n\r\n") <= 0: connect_result += s.recv(4096) # 128 kilobytes of headers should be enough for everyone. if len(connect_result) > 131072: raise ProxyError( 'Proxy sent too verbose headers. Only 128KiB allowed.' ) self.validate_proxy_response(connect_result) if context: ssl_s = context.wrap_socket( s, server_hostname=self.hostname) elif HAS_URLLIB3_SSL_WRAP_SOCKET: ssl_s = ssl_wrap_socket(s, ca_certs=tmp_ca_cert_path, cert_reqs=ssl.CERT_REQUIRED, ssl_version=PROTOCOL, server_hostname=self.hostname) else: ssl_s = ssl.wrap_socket(s, ca_certs=tmp_ca_cert_path, cert_reqs=ssl.CERT_REQUIRED, ssl_version=PROTOCOL) match_hostname(ssl_s.getpeercert(), self.hostname) else: raise ProxyError( 'Unsupported proxy scheme: %s. Currently ansible only supports HTTP proxies.' % proxy_parts.get('scheme')) else: s = socket.create_connection((self.hostname, self.port)) if context: ssl_s = context.wrap_socket(s, server_hostname=self.hostname) elif HAS_URLLIB3_SSL_WRAP_SOCKET: ssl_s = ssl_wrap_socket(s, ca_certs=tmp_ca_cert_path, cert_reqs=ssl.CERT_REQUIRED, ssl_version=PROTOCOL, server_hostname=self.hostname) else: ssl_s = ssl.wrap_socket(s, ca_certs=tmp_ca_cert_path, cert_reqs=ssl.CERT_REQUIRED, ssl_version=PROTOCOL) match_hostname(ssl_s.getpeercert(), self.hostname) # close the ssl connection # ssl_s.unwrap() s.close() except (ssl.SSLError, CertificateError) as e: build_ssl_validation_error(self.hostname, self.port, paths_checked, e) except socket.error as e: raise ConnectionError('Failed to connect to %s at port %s: %s' % (self.hostname, self.port, to_native(e))) try: # cleanup the temp file created, don't worry # if it fails for some reason os.remove(tmp_ca_cert_path) except: pass try: # cleanup the temp file created, don't worry # if it fails for some reason if to_add_ca_cert_path: os.remove(to_add_ca_cert_path) except: pass return req
def handle_connect(self): """ Connect to IRC server, handle TLS and authenticate user if an account exists. """ # handle potential TLS connection if self.config.core.use_ssl and has_ssl: if not self.config.core.verify_ssl: self.ssl = ssl.wrap_socket(self.socket, do_handshake_on_connect=True, suppress_ragged_eofs=True) else: self.ssl = ssl.wrap_socket(self.socket, do_handshake_on_connect=True, suppress_ragged_eofs=True, cert_reqs=ssl.CERT_REQUIRED, ca_certs=self.ca_certs) # connect to host specified in config first try: ssl.match_hostname(self.ssl.getpeercert(), self.config.core.host) except ssl.CertificateError: # the host in config and certificate don't match LOGGER.error( "hostname mismatch between configuration and certificate" ) # check (via exception) if a CNAME matches as a fallback has_matched = False for hostname in self._get_cnames(self.config.core.host): try: ssl.match_hostname(self.ssl.getpeercert(), hostname) LOGGER.warning( "using {0} instead of {1} for TLS connection". format(hostname, self.config.core.host)) has_matched = True break except ssl.CertificateError: pass if not has_matched: # everything is broken stderr("Invalid certificate, hostname mismatch!") LOGGER.error( "invalid certificate, no hostname matches") if hasattr(self.config.core, 'pid_file_path'): os.unlink(self.config.core.pid_file_path) os._exit(1) self.set_socket(self.ssl) # Request list of server capabilities. IRCv3 servers will respond with # CAP * LS (which we handle in coretasks). v2 servers will respond with # 421 Unknown command, which we'll ignore self.write(('CAP', 'LS', '302')) # authenticate account if needed if self.config.core.auth_method == 'server': self.write(('PASS', self.config.core.auth_password)) elif self.config.core.server_auth_method == 'server': self.write(('PASS', self.config.core.server_auth_password)) self.write(('NICK', self.nick)) self.write(('USER', self.user, '+iw', self.nick), self.name) # maintain connection stderr('Connected.') self.last_ping_time = datetime.now() timeout_check_thread = threading.Thread(target=self._timeout_check) timeout_check_thread.daemon = True timeout_check_thread.start() ping_thread = threading.Thread(target=self._send_ping) ping_thread.daemon = True ping_thread.start()
def patched_match_hostname(cert, hostname): return ssl.match_hostname(cert, hostname)
def post(self): """This method handles the POST requests to add agents to the Agent Monitor. Currently, only agents resources are available for POSTing, i.e. /agents. All other POST uri's will return errors. agents requests require a json block sent in the body """ logger.info('Agent Monitor POST') try: rest_params = common.get_restful_params(self.request.path) if "agents" not in rest_params: common.echo_json_response(self, 400, "uri not supported") logger.warning( 'POST returning 400 response. uri not supported: ' + self.request.path) return agent_id = rest_params["agents"] if agent_id is not None: # we have to know who phoned home content_length = len(self.request.body) if content_length == 0: common.echo_json_response( self, 400, "Expected non zero content length") logger.warning( 'POST returning 400 response. Expected non zero content length.') else: json_body = json.loads(self.request.body) # VERIFY CLIENT CERT ID MATCHES AGENT ID (agent_id) client_cert = self.request.get_ssl_certificate() ssl.match_hostname(client_cert, agent_id) # Execute specified script if all is well global initscript if initscript is not None and initscript != "": def initthread(): import subprocess logger.debug( "Executing specified script: %s" % initscript) env = os.environ.copy() env['AGENT_UUID'] = agent_id proc = subprocess.Popen(["/bin/sh", initscript], env=env, shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) proc.wait() while True: line = proc.stdout.readline() if line == "": break logger.debug("init-output: %s" % line.strip()) t = threading.Thread(target=initthread) t.start() common.echo_json_response(self, 200, "Success", json_body) logger.info( 'POST returning 200 response for Agent Monitor connection as ' + agent_id) else: common.echo_json_response(self, 400, "uri not supported") logger.warning( "POST returning 400 response. uri not supported") except Exception as e: common.echo_json_response(self, 400, "Exception error: %s" % e) logger.warning( "POST returning 400 response. Exception error: %s" % e) logger.exception(e)
for line in file1: stripped_line = line.strip() if (stripped_line == i): check = 1 else: check = 0 file1.close() if (check): print("%s is among the list of trusted CAs!\n" % i) else: print("Certificate issuer is not in the list.\n") #SUBJECT server = input("Which server do you want?\n") try: #Checking if the server which the user provided is the same as the hostname of the certificate ssl.match_hostname(cert, server) print("It is indeed server %s!\n" % server) except: print("It is NOT %s server.\n" % server) #VERSION version = cert['version'] ver = input("Which version do you want?\n") #Checking if the version the user provided is the same version of the certificate if (ver == str(version)): print("Version is indeed %s!\n" % version) else: print("Version is NOT %s!\n" % ver)
try: script_name, hostname = sys.argv except ValueError: print('usage: sslclient.py <hostname>', file=sys.stderr) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((hostname, 443)) ca_certs_path = os.path.join( os.path.dirname(script_name), 'certfiles.crt' ) #cert file is for validating certificates passed from other side #CERT_REQUIRED for client ssl_sock = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1, cert_reqs=ssl.CERT_REQUIRED, ca_certs=ca_certs_path) try: print(ssl_sock.getpeercert()) #already validated ssl.match_hostname(ssl_sock.getpeercert(), hostname) except ssl.CertificateError as e: print('Certificate error!', str(e)) sys.exit(1) ssl_sock.sendall(b'GED / HTTP/1.0\r\n \r\n') result = ssl_sock.makefile().read() ssl_sock.close() print('The document https://%s/ is %d bytes long' % (hostname, len(result)))
def convert_to_ssl(self, sni=None, alpn_protos=None, **sslctx_kwargs): """ cert: Path to a file containing both client cert and private key. options: A bit field consisting of OpenSSL.SSL.OP_* values verify_options: A bit field consisting of OpenSSL.SSL.VERIFY_* values ca_path: Path to a directory of trusted CA certificates prepared using the c_rehash tool ca_pemfile: Path to a PEM formatted trusted CA certificate """ verification_mode = sslctx_kwargs.get('verify_options', None) if verification_mode == SSL.VERIFY_PEER and not sni: raise exceptions.TlsException( "Cannot validate certificate hostname without SNI") context = self.create_ssl_context(alpn_protos=alpn_protos, sni=sni, **sslctx_kwargs) self.connection = SSL.Connection(context, self.connection) if sni: self.sni = sni self.connection.set_tlsext_host_name(sni.encode("idna")) self.connection.set_connect_state() try: self.connection.do_handshake() except SSL.Error as v: if self.ssl_verification_error: raise self.ssl_verification_error else: raise exceptions.TlsException("SSL handshake error: %s" % repr(v)) self.cert = certs.SSLCert(self.connection.get_peer_certificate()) # Keep all server certificates in a list for i in self.connection.get_peer_cert_chain(): self.server_certs.append(certs.SSLCert(i)) # Validate TLS Hostname try: crt = dict(subjectAltName=[("DNS", x.decode("ascii", "strict")) for x in self.cert.altnames]) if self.cert.cn: crt["subject"] = [[[ "commonName", self.cert.cn.decode("ascii", "strict") ]]] if sni: hostname = sni else: hostname = "no-hostname" match_hostname(crt, hostname) except (ValueError, CertificateError) as e: self.ssl_verification_error = exceptions.InvalidCertificateException( "Certificate Verification Error for {}: {}".format( sni or repr(self.address), str(e))) if verification_mode == SSL.VERIFY_PEER: raise self.ssl_verification_error self.ssl_established = True self.rfile.set_descriptor(self.connection) self.wfile.set_descriptor(self.connection)
def connect(self, url, **options): """ Connect to url. url is websocket url scheme. ie. ws://host:port/resource You can customize using 'options'. If you set "header" list object, you can set your own custom header. >>> ws = WebSocket() >>> ws.connect("ws://echo.websocket.org/", ... header=["User-Agent: MyProgram", ... "x-custom: header"]) timeout: socket timeout time. This value is integer. if you set None for this value, it means "use default_timeout value" options: "header" -> custom http header list. "cookie" -> cookie value. "http_proxy_host" - http proxy host name. "http_proxy_port" - http proxy port. If not set, set to 80. """ hostname, port, resource, is_secure = _parse_url(url) proxy_host, proxy_port = options.get("http_proxy_host", None), options.get( "http_proxy_port", 0) if not proxy_host: addrinfo_list = socket.getaddrinfo(hostname, port, 0, 0, socket.SOL_TCP) else: proxy_port = proxy_port and proxy_port or 80 addrinfo_list = socket.getaddrinfo(proxy_host, proxy_port, 0, 0, socket.SOL_TCP) if not addrinfo_list: raise WebSocketException("Host not found.: " + hostname + ":" + str(port)) family = addrinfo_list[0][0] self.sock = socket.socket(family) self.sock.settimeout(self.timeout) for opts in DEFAULT_SOCKET_OPTION: self.sock.setsockopt(*opts) for opts in self.sockopt: self.sock.setsockopt(*opts) # TODO: we need to support proxy address = addrinfo_list[0][4] self.sock.connect(address) if proxy_host: self._tunnel(hostname, port) if is_secure: if HAVE_SSL: sslopt = dict(cert_reqs=ssl.CERT_REQUIRED) certPath = os.path.join(os.path.dirname(__file__), "cacert.pem") if os.path.isfile(certPath): sslopt['ca_certs'] = certPath sslopt.update(self.sslopt) self.sock = ssl.wrap_socket(self.sock, **sslopt) if sslopt["cert_reqs"] != ssl.CERT_NONE: match_hostname(self.sock.getpeercert(), hostname) else: raise WebSocketException("SSL not available.") self._handshake(hostname, port, resource, **options)
import os, socket, ssl, sys from ssl import match_hostname, CertificateError try: scrip_name, hostname = sys.argv except ValueError: print >> sys.stderr, 'usage: sslclient.py <hostname>' sys.exit(2) sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((hostname, 443)) ca_certs_path = os.path.join(os.path.dirname(scrip_name), 'certfiles.crt') #The default ssl_version has been changed to PROTOCOL_SSLv23. sslsock = ssl.wrap_socket(sock, ssl_version=ssl.PROTOCOL_SSLv23, cert_reqs=ssl.CERT_REQUIRED, ca_certs=ca_certs_path) try: match_hostname(sslsock.getpeercert(), hostname) except CertificateError, ce: print 'Certificate error:', str(ce) sys.exit(1) sslsock.sendall('Get / HTTP/1.0\r\n\r\n') result = sslsock.makefile().read() sslsock.close() print 'The document https://%s/ is %d bytes long' % (hostname, len(result))
# being used. Adapt, since we are interested in the destination # host for the match_hostname() comparison. actual_host = self._tunnel_host else: actual_host = self.host if hasattr(ssl, 'create_default_context'): ctx = ssl.create_default_context(cafile=self.ca_bundle) self.sock = ctx.wrap_socket(sock, server_hostname=actual_host) else: # This is for python < 2.7.9 and < 3.4? self.sock = ssl.wrap_socket( sock, cert_reqs=ssl.CERT_REQUIRED, ca_certs=self.ca_bundle ) try: match_hostname(self.sock.getpeercert(), actual_host) except CertificateError: self.sock.shutdown(socket.SHUT_RDWR) self.sock.close() raise def opener_for(ca_bundle=None): """Get a urlopen() replacement that uses ca_bundle for verification""" return urllib.request.build_opener( VerifyingHTTPSHandler(ca_bundle or find_ca_bundle()) ).open # from jaraco.functools def once(func):
data = data + sock.read(1) return data sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) sock.connect((HOST, PORT)) context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) context.verify_mode = ssl.CERT_REQUIRED context.load_verify_locations('certv6.pem') #context.load_cert_chain(certfile='./certs/client/client.crt', keyfile="./certs/client/client.key") if ssl.HAS_SNI: secure_sock = context.wrap_socket(sock, server_hostname=HOST) else: secure_sock = context.wrap_socket(sock) cert = secure_sock.getpeercert() if not cert or ssl.match_hostname(cert, HOST): raise Exception("Error") login = raw_input('pass login ') password = raw_input('pass password ') login_seq = ''.join(["LOGIN:"******"@", password, "\r\n"]) secure_sock.send(login_seq) login_response = recv_all(secure_sock, "\r\n") print login_response if not ("201" in login_response or "200" in login_response): secure_sock.close() sock.close() print "ending program"
def http_request(self, req): tmp_ca_cert_path, paths_checked = self.get_ca_certs() https_proxy = os.environ.get('https_proxy') context = None if HAS_SSLCONTEXT: context = self._make_context(tmp_ca_cert_path) # Detect if 'no_proxy' environment variable is set and if our URL is included use_proxy = self.detect_no_proxy(req.get_full_url()) if not use_proxy: # ignore proxy settings for this host request return req try: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) if https_proxy: proxy_parts = generic_urlparse(urlparse.urlparse(https_proxy)) port = proxy_parts.get('port') or 443 s.connect((proxy_parts.get('hostname'), port)) if proxy_parts.get('scheme') == 'http': s.sendall(self.CONNECT_COMMAND % (self.hostname, self.port)) if proxy_parts.get('username'): credentials = "%s:%s" % (proxy_parts.get( 'username', ''), proxy_parts.get('password', '')) s.sendall('Proxy-Authorization: Basic %s\r\n' % credentials.encode('base64').strip()) s.sendall('\r\n') connect_result = s.recv(4096) self.validate_proxy_response(connect_result) if context: ssl_s = context.wrap_socket( s, server_hostname=self.hostname) elif HAS_URLLIB3_SNI_SUPPORT: ssl_s = ssl_wrap_socket(s, ca_certs=tmp_ca_cert_path, cert_reqs=ssl.CERT_REQUIRED, ssl_version=PROTOCOL, server_hostname=self.hostname) else: ssl_s = ssl.wrap_socket(s, ca_certs=tmp_ca_cert_path, cert_reqs=ssl.CERT_REQUIRED, ssl_version=PROTOCOL) match_hostname(ssl_s.getpeercert(), self.hostname) else: raise ProxyError( 'Unsupported proxy scheme: %s. Currently ansible only supports HTTP proxies.' % proxy_parts.get('scheme')) else: s.connect((self.hostname, self.port)) if context: ssl_s = context.wrap_socket(s, server_hostname=self.hostname) elif HAS_URLLIB3_SNI_SUPPORT: ssl_s = ssl_wrap_socket(s, ca_certs=tmp_ca_cert_path, cert_reqs=ssl.CERT_REQUIRED, ssl_version=PROTOCOL, server_hostname=self.hostname) else: ssl_s = ssl.wrap_socket(s, ca_certs=tmp_ca_cert_path, cert_reqs=ssl.CERT_REQUIRED, ssl_version=PROTOCOL) match_hostname(ssl_s.getpeercert(), self.hostname) # close the ssl connection #ssl_s.unwrap() s.close() except (ssl.SSLError, socket.error): e = get_exception() # fail if we tried all of the certs but none worked if 'connection refused' in str(e).lower(): raise ConnectionError('Failed to connect to %s:%s.' % (self.hostname, self.port)) else: build_ssl_validation_error(self.hostname, self.port, paths_checked) except CertificateError: build_ssl_validation_error(self.hostname, self.port, paths_checked) try: # cleanup the temp file created, don't worry # if it fails for some reason os.remove(tmp_ca_cert_path) except: pass return req
def __init__(self, parent, timeout): self.host = parent._parent.host self.port = parent._parent.port self._read_buffer = None self._socket = None self.ssl = parent._parent.ssl deadline = time.time() + timeout try: self._socket = socket.create_connection((self.host, self.port), timeout) self._socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) if len(self.ssl) > 0: ssl_context = self._get_ssl_context(self.ssl["ca_certs"]) try: self._socket = ssl_context.wrap_socket( self._socket, server_hostname=self.host) except IOError as exc: self._socket.close() raise ReqlDriverError("SSL handshake failed: %s" % (str(exc), )) try: match_hostname(self._socket.getpeercert(), hostname=self.host) except CertificateError: self._socket.close() raise self.sendall(parent._parent.handshake) # The response from the server is a null-terminated string response = b'' while True: char = self.recvall(1, deadline) if char == b'\0': break response += char except ReqlAuthError: raise except ReqlTimeoutError: raise except ReqlDriverError as ex: self.close() error = str(ex)\ .replace('receiving from', 'during handshake with')\ .replace('sending to', 'during handshake with') raise ReqlDriverError(error) except socket.timeout as ex: self.close() raise ReqlTimeoutError(self.host, self.port) except Exception as ex: self.close() raise ReqlDriverError("Could not connect to %s:%s. Error: %s" % (self.host, self.port, ex)) if response != b"SUCCESS": self.close() message = decodeUTF(response).strip() if message == "ERROR: Incorrect authorization key.": raise ReqlAuthError(self.host, self.port) else: raise ReqlDriverError( "Server dropped connection with message: \"%s\"" % (message, ))
def __init__(self, parent, timeout): self.host = parent._parent.host self.port = parent._parent.port self._read_buffer = None self._socket = None self.ssl = parent._parent.ssl deadline = time.time() + timeout try: self._socket = socket.create_connection((self.host, self.port), timeout) self._socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) if len(self.ssl) > 0: try: if hasattr(ssl, 'SSLContext' ): # Python2.7 and 3.2+, or backports.ssl ssl_context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) if hasattr(ssl_context, "options"): ssl_context.options |= getattr( ssl, "OP_NO_SSLv2", 0) ssl_context.options |= getattr( ssl, "OP_NO_SSLv3", 0) ssl_context.verify_mode = ssl.CERT_REQUIRED ssl_context.check_hostname = True # redundant with match_hostname ssl_context.load_verify_locations(self.ssl["ca_certs"]) self._socket = ssl_context.wrap_socket( self._socket, server_hostname=self.host) else: # this does not disable SSLv2 or SSLv3 self._socket = ssl.wrap_socket( self._socket, cert_reqs=ssl.CERT_REQUIRED, ssl_version=ssl.PROTOCOL_SSLv23, ca_certs=self.ssl["ca_certs"]) except IOError as exc: self._socket.close() raise ReqlDriverError( "SSL handshake failed (see server log for more information): %s" % str(exc)) try: match_hostname(self._socket.getpeercert(), hostname=self.host) except CertificateError: self._socket.close() raise parent._parent.handshake.reset() response = None while True: request = parent._parent.handshake.next_message(response) if request is None: break # This may happen in the `V1_0` protocol where we send two requests as # an optimization, then need to read each separately if request is not "": self.sendall(request) # The response from the server is a null-terminated string response = b'' while True: char = self.recvall(1, deadline) if char == b'\0': break response += char except ReqlAuthError: self.close() raise except ReqlTimeoutError: self.close() raise except ReqlDriverError as ex: self.close() error = str(ex)\ .replace('receiving from', 'during handshake with')\ .replace('sending to', 'during handshake with') raise ReqlDriverError(error) except socket.timeout as ex: self.close() raise ReqlTimeoutError(self.host, self.port) except Exception as ex: self.close() raise ReqlDriverError("Could not connect to %s:%s. Error: %s" % (self.host, self.port, ex))
def connect(self, url, **options): """ Connect to url. url is websocket url scheme. ie. ws://host:port/resource You can customize using 'options'. If you set "header" list jeeObject, you can set your own custom header. >>> ws = WebSocket() >>> ws.connect("ws://echo.websocket.org/", ... header=["User-Agent: MyProgram", ... "x-custom: header"]) timeout: socket timeout time. This value is integer. if you set None for this value, it means "use default_timeout value" options: "header" -> custom http header list. "cookie" -> cookie value. "http_proxy_host" - http proxy host name. "http_proxy_port" - http proxy port. If not set, set to 80. "http_no_proxy" - host names, which doesn't use proxy. "http_proxy_auth" - http proxy auth infomation. tuple of username and password. defualt is None "subprotocols" - array of available sub protocols. default is None. """ hostname, port, resource, is_secure = _parse_url(url) proxy_host, proxy_port, proxy_auth = _get_proxy_info( hostname, is_secure, **options) if not proxy_host: addrinfo_list = socket.getaddrinfo(hostname, port, 0, 0, socket.SOL_TCP) else: proxy_port = proxy_port and proxy_port or 80 addrinfo_list = socket.getaddrinfo(proxy_host, proxy_port, 0, 0, socket.SOL_TCP) if not addrinfo_list: raise WebSocketException("Host not found.: " + hostname + ":" + str(port)) err = None for addrinfo in addrinfo_list: family = addrinfo[0] self.sock = socket.socket(family) self.sock.settimeout(self.timeout) for opts in DEFAULT_SOCKET_OPTION: self.sock.setsockopt(*opts) for opts in self.sockopt: self.sock.setsockopt(*opts) address = addrinfo[4] try: self.sock.connect(address) except socket.error as error: error.remote_ip = str(address[0]) if error.errno in (errno.ECONNREFUSED, ): err = error continue else: raise else: break else: raise err if proxy_host: self._tunnel(hostname, port, proxy_auth) if is_secure: if HAVE_SSL: sslopt = dict(cert_reqs=ssl.CERT_REQUIRED) certPath = os.path.join(os.path.dirname(__file__), "cacert.pem") if os.path.isfile(certPath): sslopt['ca_certs'] = certPath sslopt.update(self.sslopt) check_hostname = sslopt.pop('check_hostname', True) self.sock = ssl.wrap_socket(self.sock, **sslopt) if (sslopt["cert_reqs"] != ssl.CERT_NONE and check_hostname): match_hostname(self.sock.getpeercert(), hostname) else: raise WebSocketException("SSL not available.") self._handshake(hostname, port, resource, **options)
def query(url, method='GET', params=None, data=None, data_file=None, header_dict=None, header_list=None, header_file=None, username=None, password=None, auth=None, decode=False, decode_type='auto', status=False, headers=False, text=False, cookies=None, cookie_jar=None, cookie_format='lwp', persist_session=False, session_cookie_jar=None, data_render=False, data_renderer=None, header_render=False, header_renderer=None, template_dict=None, test=False, test_url=None, node='minion', port=80, opts=None, backend='tornado', requests_lib=None, ca_bundle=None, verify_ssl=None, cert=None, text_out=None, headers_out=None, decode_out=None, stream=False, streaming_callback=None, handle=False, agent=USERAGENT, hide_fields=None, **kwargs): ''' Query a resource, and decode the return data ''' ret = {} if opts is None: if node == 'master': opts = salt.config.master_config( os.path.join(syspaths.CONFIG_DIR, 'master')) elif node == 'minion': opts = salt.config.minion_config( os.path.join(syspaths.CONFIG_DIR, 'minion')) else: opts = {} if requests_lib is None: requests_lib = opts.get('requests_lib', False) if requests_lib is True: log.warn('Please set "backend" to "requests" instead of setting ' '"requests_lib" to "True"') if HAS_REQUESTS is False: ret['error'] = ('http.query has been set to use requests, but the ' 'requests library does not seem to be installed') log.error(ret['error']) return ret backend = 'requests' else: requests_log = logging.getLogger('requests') requests_log.setLevel(logging.WARNING) # Some libraries don't support separation of url and GET parameters # Don't need a try/except block, since Salt depends on tornado url_full = tornado.httputil.url_concat(url, params) if ca_bundle is None: ca_bundle = get_ca_bundle(opts) if verify_ssl is None: verify_ssl = opts.get('verify_ssl', True) if cert is None: cert = opts.get('cert', None) if data_file is not None: data = _render(data_file, data_render, data_renderer, template_dict, opts) # Make sure no secret fields show up in logs log_url = sanitize_url(url_full, hide_fields) log.debug('Requesting URL {0} using {1} method'.format(log_url, method)) if method == 'POST': # Make sure no secret fields show up in logs if isinstance(data, dict): log_data = data.copy() for item in data: for field in hide_fields: if item == field: log_data[item] = 'XXXXXXXXXX' log.trace('Request POST Data: {0}'.format( pprint.pformat(log_data))) else: log.trace('Request POST Data: {0}'.format(pprint.pformat(data))) if header_file is not None: header_tpl = _render(header_file, header_render, header_renderer, template_dict, opts) if isinstance(header_tpl, dict): header_dict = header_tpl else: header_list = header_tpl.splitlines() if header_dict is None: header_dict = {} if header_list is None: header_list = [] if cookie_jar is None: cookie_jar = os.path.join(opts.get('cachedir', syspaths.CACHE_DIR), 'cookies.txt') if session_cookie_jar is None: session_cookie_jar = os.path.join( opts.get('cachedir', syspaths.CACHE_DIR), 'cookies.session.p') if persist_session is True and HAS_MSGPACK: # TODO: This is hackish; it will overwrite the session cookie jar with # all cookies from this one connection, rather than behaving like a # proper cookie jar. Unfortunately, since session cookies do not # contain expirations, they can't be stored in a proper cookie jar. if os.path.isfile(session_cookie_jar): with salt.utils.fopen(session_cookie_jar, 'rb') as fh_: session_cookies = msgpack.load(fh_) if isinstance(session_cookies, dict): header_dict.update(session_cookies) else: with salt.utils.fopen(session_cookie_jar, 'wb') as fh_: msgpack.dump('', fh_) for header in header_list: comps = header.split(':') if len(comps) < 2: continue header_dict[comps[0].strip()] = comps[1].strip() if not auth: if username and password: auth = (username, password) else: auth = None if agent == USERAGENT: agent = '{0} http.query()'.format(agent) header_dict['User-agent'] = agent if backend == 'requests': sess = requests.Session() sess.auth = auth sess.headers.update(header_dict) log.trace('Request Headers: {0}'.format(sess.headers)) sess_cookies = sess.cookies sess.verify = verify_ssl elif backend == 'urllib2': sess_cookies = None else: # Tornado sess_cookies = None if cookies is not None: if cookie_format == 'mozilla': sess_cookies = salt.ext.six.moves.http_cookiejar.MozillaCookieJar( cookie_jar) else: sess_cookies = salt.ext.six.moves.http_cookiejar.LWPCookieJar( cookie_jar) if not os.path.isfile(cookie_jar): sess_cookies.save() sess_cookies.load() if test is True: if test_url is None: return {} else: url = test_url ret['test'] = True if backend == 'requests': req_kwargs = {} if stream is True: if requests.__version__[0] == '0': # 'stream' was called 'prefetch' before 1.0, with flipped meaning req_kwargs['prefetch'] = False else: req_kwargs['stream'] = True # Client-side cert handling if cert is not None: if isinstance(cert, six.string_types): if os.path.exists(cert): req_kwargs['cert'] = cert elif isinstance(cert, tuple): if os.path.exists(cert[0]) and os.path.exists(cert[1]): req_kwargs['cert'] = cert else: log.error( 'The client-side certificate path that was passed is ' 'not valid: {0}'.format(cert)) result = sess.request(method, url, params=params, data=data, **req_kwargs) result.raise_for_status() if stream is True or handle is True: return {'handle': result} log.debug('Final URL location of Response: {0}'.format( sanitize_url(result.url, hide_fields))) result_status_code = result.status_code result_headers = result.headers result_text = result.text result_cookies = result.cookies elif backend == 'urllib2': request = urllib_request.Request(url_full, data) handlers = [ urllib_request.HTTPHandler, urllib_request.HTTPCookieProcessor(sess_cookies) ] if url.startswith('https') or port == 443: hostname = request.get_host() handlers[0] = urllib_request.HTTPSHandler(1) if not HAS_MATCHHOSTNAME: log.warn( ('match_hostname() not available, SSL hostname checking ' 'not available. THIS CONNECTION MAY NOT BE SECURE!')) elif verify_ssl is False: log.warn(('SSL certificate verification has been explicitly ' 'disabled. THIS CONNECTION MAY NOT BE SECURE!')) else: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((hostname, 443)) sockwrap = ssl.wrap_socket(sock, ca_certs=ca_bundle, cert_reqs=ssl.CERT_REQUIRED) try: match_hostname(sockwrap.getpeercert(), hostname) except CertificateError as exc: ret['error'] = ('The certificate was invalid. ' 'Error returned was: {0}'.format( pprint.pformat(exc))) return ret # Client-side cert handling if cert is not None: cert_chain = None if isinstance(cert, six.string_types): if os.path.exists(cert): cert_chain = (cert) elif isinstance(cert, tuple): if os.path.exists(cert[0]) and os.path.exists(cert[1]): cert_chain = cert else: log.error('The client-side certificate path that was ' 'passed is not valid: {0}'.format(cert)) return if hasattr(ssl, 'SSLContext'): # Python >= 2.7.9 context = ssl.SSLContext.load_cert_chain(*cert_chain) handlers.append( urllib_request.HTTPSHandler(context=context)) # pylint: disable=E1123 else: # Python < 2.7.9 cert_kwargs = { 'host': request.get_host(), 'port': port, 'cert_file': cert_chain[0] } if len(cert_chain) > 1: cert_kwargs['key_file'] = cert_chain[1] handlers[ 0] = salt.ext.six.moves.http_client.HTTPSConnection( **cert_kwargs) opener = urllib_request.build_opener(*handlers) for header in header_dict: request.add_header(header, header_dict[header]) request.get_method = lambda: method try: result = opener.open(request) except URLError as exc: return {'Error': str(exc)} if stream is True or handle is True: return {'handle': result} result_status_code = result.code result_headers = result.headers.headers result_text = result.read() else: # Tornado req_kwargs = {} # Client-side cert handling if cert is not None: if isinstance(cert, six.string_types): if os.path.exists(cert): req_kwargs['client_cert'] = cert elif isinstance(cert, tuple): if os.path.exists(cert[0]) and os.path.exists(cert[1]): req_kwargs['client_cert'] = cert[0] req_kwargs['client_key'] = cert[1] else: log.error( 'The client-side certificate path that was passed is ' 'not valid: {0}'.format(cert)) if isinstance(data, dict): data = urllib.urlencode(data) max_body = opts.get('http_max_body', salt.config.DEFAULT_MINION_OPTS['http_max_body']) timeout = opts.get( 'http_request_timeout', salt.config.DEFAULT_MINION_OPTS['http_request_timeout']) try: result = HTTPClient(max_body_size=max_body).fetch( url_full, method=method, headers=header_dict, auth_username=username, auth_password=password, body=data, validate_cert=verify_ssl, allow_nonstandard_methods=True, streaming_callback=streaming_callback, request_timeout=timeout, **req_kwargs) except tornado.httpclient.HTTPError as exc: ret['status'] = exc.code ret['error'] = str(exc) return ret if stream is True or handle is True: return {'handle': result} result_status_code = result.code result_headers = result.headers result_text = result.body if 'Set-Cookie' in result_headers.keys() and cookies is not None: result_cookies = parse_cookie_header(result_headers['Set-Cookie']) for item in result_cookies: sess_cookies.set_cookie(item) else: result_cookies = None if isinstance(result_headers, list): result_headers_dict = {} for header in result_headers: comps = header.split(':') result_headers_dict[comps[0].strip()] = ':'.join(comps[1:]).strip() result_headers = result_headers_dict log.debug('Response Status Code: {0}'.format(result_status_code)) log.trace('Response Headers: {0}'.format(result_headers)) log.trace('Response Cookies: {0}'.format(sess_cookies)) try: log.trace('Response Text: {0}'.format(result_text)) except UnicodeEncodeError as exc: log.trace( ('Cannot Trace Log Response Text: {0}. This may be due to ' 'incompatibilities between requests and logging.').format(exc)) if text_out is not None and os.path.exists(text_out): with salt.utils.fopen(text_out, 'w') as tof: tof.write(result_text) if headers_out is not None and os.path.exists(headers_out): with salt.utils.fopen(headers_out, 'w') as hof: hof.write(result_headers) if cookies is not None: sess_cookies.save() if persist_session is True and HAS_MSGPACK: # TODO: See persist_session above if 'set-cookie' in result_headers: with salt.utils.fopen(session_cookie_jar, 'wb') as fh_: session_cookies = result_headers.get('set-cookie', None) if session_cookies is not None: msgpack.dump({'Cookie': session_cookies}, fh_) else: msgpack.dump('', fh_) if status is True: ret['status'] = result_status_code if headers is True: ret['headers'] = result_headers if decode is True: if decode_type == 'auto': content_type = result_headers.get('content-type', 'application/json') if 'xml' in content_type: decode_type = 'xml' elif 'json' in content_type: decode_type = 'json' else: decode_type = 'plain' valid_decodes = ('json', 'xml', 'plain') if decode_type not in valid_decodes: ret['error'] = ('Invalid decode_type specified. ' 'Valid decode types are: {0}'.format( pprint.pformat(valid_decodes))) log.error(ret['error']) return ret if decode_type == 'json': ret['dict'] = json.loads(salt.utils.to_str(result_text)) elif decode_type == 'xml': ret['dict'] = [] items = ET.fromstring(result_text) for item in items: ret['dict'].append(xml.to_dict(item)) else: text = True if decode_out and os.path.exists(decode_out): with salt.utils.fopen(decode_out, 'w') as dof: dof.write(result_text) if text is True: ret['text'] = result_text return ret
def match_hostname(self, hostname): raise NotImplementedError() # We need a dict-like representation, like SSLSocket.getpeercert() # returns return ssl.match_hostname(None, hostname)
def query(url, method='GET', params=None, data=None, data_file=None, header_dict=None, header_list=None, header_file=None, username=None, password=None, auth=None, decode=False, decode_type='auto', status=False, headers=False, text=False, cookies=None, cookie_jar=None, cookie_format='lwp', persist_session=False, session_cookie_jar=None, data_render=False, data_renderer=None, header_render=False, header_renderer=None, template_dict=None, test=False, test_url=None, node='minion', port=80, opts=None, backend=None, ca_bundle=None, verify_ssl=None, cert=None, text_out=None, headers_out=None, decode_out=None, stream=False, streaming_callback=None, header_callback=None, handle=False, agent=USERAGENT, hide_fields=None, raise_error=True, **kwargs): ''' Query a resource, and decode the return data ''' ret = {} if opts is None: if node == 'master': opts = salt.config.master_config( os.path.join(salt.syspaths.CONFIG_DIR, 'master')) elif node == 'minion': opts = salt.config.minion_config( os.path.join(salt.syspaths.CONFIG_DIR, 'minion')) else: opts = {} if not backend: backend = opts.get('backend', 'tornado') match = re.match( r'https?://((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)($|/)', url) if not match: salt.utils.network.refresh_dns() if backend == 'requests': if HAS_REQUESTS is False: ret['error'] = ('http.query has been set to use requests, but the ' 'requests library does not seem to be installed') log.error(ret['error']) return ret else: requests_log = logging.getLogger('requests') requests_log.setLevel(logging.WARNING) # Some libraries don't support separation of url and GET parameters # Don't need a try/except block, since Salt depends on tornado url_full = tornado.httputil.url_concat(url, params) if params else url if ca_bundle is None: ca_bundle = get_ca_bundle(opts) if verify_ssl is None: verify_ssl = opts.get('verify_ssl', True) if cert is None: cert = opts.get('cert', None) if data_file is not None: data = _render(data_file, data_render, data_renderer, template_dict, opts) # Make sure no secret fields show up in logs log_url = sanitize_url(url_full, hide_fields) log.debug('Requesting URL %s using %s method', log_url, method) log.debug("Using backend: %s", backend) if method == 'POST' and log.isEnabledFor(logging.TRACE): # Make sure no secret fields show up in logs if isinstance(data, dict): log_data = data.copy() if isinstance(hide_fields, list): for item in data: for field in hide_fields: if item == field: log_data[item] = 'XXXXXXXXXX' log.trace('Request POST Data: %s', pprint.pformat(log_data)) else: log.trace('Request POST Data: %s', pprint.pformat(data)) if header_file is not None: header_tpl = _render(header_file, header_render, header_renderer, template_dict, opts) if isinstance(header_tpl, dict): header_dict = header_tpl else: header_list = header_tpl.splitlines() if header_dict is None: header_dict = {} if header_list is None: header_list = [] if cookie_jar is None: cookie_jar = os.path.join( opts.get('cachedir', salt.syspaths.CACHE_DIR), 'cookies.txt') if session_cookie_jar is None: session_cookie_jar = os.path.join( opts.get('cachedir', salt.syspaths.CACHE_DIR), 'cookies.session.p') if persist_session is True and HAS_MSGPACK: # TODO: This is hackish; it will overwrite the session cookie jar with # all cookies from this one connection, rather than behaving like a # proper cookie jar. Unfortunately, since session cookies do not # contain expirations, they can't be stored in a proper cookie jar. if os.path.isfile(session_cookie_jar): with salt.utils.files.fopen(session_cookie_jar, 'rb') as fh_: session_cookies = msgpack.load(fh_) if isinstance(session_cookies, dict): header_dict.update(session_cookies) else: with salt.utils.files.fopen(session_cookie_jar, 'wb') as fh_: msgpack.dump('', fh_) for header in header_list: comps = header.split(':') if len(comps) < 2: continue header_dict[comps[0].strip()] = comps[1].strip() if not auth: if username and password: auth = (username, password) if agent == USERAGENT: agent = '{0} http.query()'.format(agent) header_dict['User-agent'] = agent if backend == 'requests': sess = requests.Session() sess.auth = auth sess.headers.update(header_dict) log.trace('Request Headers: %s', sess.headers) sess_cookies = sess.cookies sess.verify = verify_ssl elif backend == 'urllib2': sess_cookies = None else: # Tornado sess_cookies = None if cookies is not None: if cookie_format == 'mozilla': sess_cookies = salt.ext.six.moves.http_cookiejar.MozillaCookieJar( cookie_jar) else: sess_cookies = salt.ext.six.moves.http_cookiejar.LWPCookieJar( cookie_jar) if not os.path.isfile(cookie_jar): sess_cookies.save() sess_cookies.load() if test is True: if test_url is None: return {} else: url = test_url ret['test'] = True if backend == 'requests': req_kwargs = {} if stream is True: if requests.__version__[0] == '0': # 'stream' was called 'prefetch' before 1.0, with flipped meaning req_kwargs['prefetch'] = False else: req_kwargs['stream'] = True # Client-side cert handling if cert is not None: if isinstance(cert, six.string_types): if os.path.exists(cert): req_kwargs['cert'] = cert elif isinstance(cert, list): if os.path.exists(cert[0]) and os.path.exists(cert[1]): req_kwargs['cert'] = cert else: log.error( 'The client-side certificate path that' ' was passed is not valid: %s', cert) result = sess.request(method, url, params=params, data=data, **req_kwargs) result.raise_for_status() if stream is True: # fake a HTTP response header header_callback('HTTP/1.0 {0} MESSAGE'.format(result.status_code)) # fake streaming the content streaming_callback(result.content) return { 'handle': result, } if handle is True: return { 'handle': result, 'body': result.content, } log.debug('Final URL location of Response: %s', sanitize_url(result.url, hide_fields)) result_status_code = result.status_code result_headers = result.headers result_text = result.content result_cookies = result.cookies body = result.content if not isinstance(body, six.text_type): body = body.decode(result.encoding or 'utf-8') ret['body'] = body elif backend == 'urllib2': request = urllib_request.Request(url_full, data) handlers = [ urllib_request.HTTPHandler, urllib_request.HTTPCookieProcessor(sess_cookies) ] if url.startswith('https'): hostname = request.get_host() handlers[0] = urllib_request.HTTPSHandler(1) if not HAS_MATCHHOSTNAME: log.warning( 'match_hostname() not available, SSL hostname checking ' 'not available. THIS CONNECTION MAY NOT BE SECURE!') elif verify_ssl is False: log.warning('SSL certificate verification has been explicitly ' 'disabled. THIS CONNECTION MAY NOT BE SECURE!') else: if ':' in hostname: hostname, port = hostname.split(':') else: port = 443 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((hostname, int(port))) sockwrap = ssl.wrap_socket(sock, ca_certs=ca_bundle, cert_reqs=ssl.CERT_REQUIRED) try: match_hostname(sockwrap.getpeercert(), hostname) except CertificateError as exc: ret['error'] = ('The certificate was invalid. ' 'Error returned was: %s', pprint.pformat(exc)) return ret # Client-side cert handling if cert is not None: cert_chain = None if isinstance(cert, six.string_types): if os.path.exists(cert): cert_chain = (cert) elif isinstance(cert, list): if os.path.exists(cert[0]) and os.path.exists(cert[1]): cert_chain = cert else: log.error( 'The client-side certificate path that was ' 'passed is not valid: %s', cert) return if hasattr(ssl, 'SSLContext'): # Python >= 2.7.9 context = ssl.SSLContext.load_cert_chain(*cert_chain) handlers.append( urllib_request.HTTPSHandler(context=context)) # pylint: disable=E1123 else: # Python < 2.7.9 cert_kwargs = { 'host': request.get_host(), 'port': port, 'cert_file': cert_chain[0] } if len(cert_chain) > 1: cert_kwargs['key_file'] = cert_chain[1] handlers[ 0] = salt.ext.six.moves.http_client.HTTPSConnection( **cert_kwargs) opener = urllib_request.build_opener(*handlers) for header in header_dict: request.add_header(header, header_dict[header]) request.get_method = lambda: method try: result = opener.open(request) except URLError as exc: return {'Error': six.text_type(exc)} if stream is True or handle is True: return { 'handle': result, 'body': result.content, } result_status_code = result.code result_headers = dict(result.info()) result_text = result.read() if 'Content-Type' in result_headers: res_content_type, res_params = cgi.parse_header( result_headers['Content-Type']) if res_content_type.startswith('text/') and \ 'charset' in res_params and \ not isinstance(result_text, six.text_type): result_text = result_text.decode(res_params['charset']) if six.PY3 and isinstance(result_text, bytes): result_text = result.body.decode('utf-8') ret['body'] = result_text else: # Tornado req_kwargs = {} # Client-side cert handling if cert is not None: if isinstance(cert, six.string_types): if os.path.exists(cert): req_kwargs['client_cert'] = cert elif isinstance(cert, list): if os.path.exists(cert[0]) and os.path.exists(cert[1]): req_kwargs['client_cert'] = cert[0] req_kwargs['client_key'] = cert[1] else: log.error( 'The client-side certificate path that ' 'was passed is not valid: %s', cert) if isinstance(data, dict): data = _urlencode(data) if verify_ssl: req_kwargs['ca_certs'] = ca_bundle max_body = opts.get('http_max_body', salt.config.DEFAULT_MINION_OPTS['http_max_body']) connect_timeout = opts.get( 'http_connect_timeout', salt.config.DEFAULT_MINION_OPTS['http_connect_timeout']) timeout = opts.get( 'http_request_timeout', salt.config.DEFAULT_MINION_OPTS['http_request_timeout']) client_argspec = None proxy_host = opts.get('proxy_host', None) if proxy_host: # tornado requires a str for proxy_host, cannot be a unicode str in py2 proxy_host = salt.utils.stringutils.to_str(proxy_host) proxy_port = opts.get('proxy_port', None) proxy_username = opts.get('proxy_username', None) if proxy_username: # tornado requires a str, cannot be unicode str in py2 proxy_username = salt.utils.stringutils.to_str(proxy_username) proxy_password = opts.get('proxy_password', None) if proxy_password: # tornado requires a str, cannot be unicode str in py2 proxy_password = salt.utils.stringutils.to_str(proxy_password) no_proxy = opts.get('no_proxy', []) # Since tornado doesnt support no_proxy, we'll always hand it empty proxies or valid ones # except we remove the valid ones if a url has a no_proxy hostname in it if urlparse(url_full).hostname in no_proxy: proxy_host = None proxy_port = None # We want to use curl_http if we have a proxy defined if proxy_host and proxy_port: if HAS_CURL_HTTPCLIENT is False: ret['error'] = ( 'proxy_host and proxy_port has been set. This requires pycurl and tornado, ' 'but the libraries does not seem to be installed') log.error(ret['error']) return ret tornado.httpclient.AsyncHTTPClient.configure( 'tornado.curl_httpclient.CurlAsyncHTTPClient') client_argspec = salt.utils.args.get_function_argspec( tornado.curl_httpclient.CurlAsyncHTTPClient.initialize) else: client_argspec = salt.utils.args.get_function_argspec( tornado.simple_httpclient.SimpleAsyncHTTPClient.initialize) supports_max_body_size = 'max_body_size' in client_argspec.args req_kwargs.update({ 'method': method, 'headers': header_dict, 'auth_username': username, 'auth_password': password, 'body': data, 'validate_cert': verify_ssl, 'allow_nonstandard_methods': True, 'streaming_callback': streaming_callback, 'header_callback': header_callback, 'connect_timeout': connect_timeout, 'request_timeout': timeout, 'proxy_host': proxy_host, 'proxy_port': proxy_port, 'proxy_username': proxy_username, 'proxy_password': proxy_password, 'raise_error': raise_error, 'decompress_response': False, }) # Unicode types will cause a TypeError when Tornado's curl HTTPClient # invokes setopt. Therefore, make sure all arguments we pass which # contain strings are str types. req_kwargs = salt.utils.data.decode(req_kwargs, to_str=True) try: download_client = HTTPClient(max_body_size=max_body) \ if supports_max_body_size \ else HTTPClient() result = download_client.fetch(url_full, **req_kwargs) except tornado.httpclient.HTTPError as exc: ret['status'] = exc.code ret['error'] = six.text_type(exc) log.error("Cannot perform 'http.query': {0} - {1}".format( url_full, ret['error'])) return ret except (socket.herror, socket.error, socket.timeout, socket.gaierror) as exc: if status is True: ret['status'] = 0 ret['error'] = six.text_type(exc) log.error("Cannot perform 'http.query': {0} - {1}".format( url_full, ret['error'])) return ret if stream is True or handle is True: return { 'handle': result, 'body': result.body, } result_status_code = result.code result_headers = result.headers result_text = result.body if 'Content-Type' in result_headers: res_content_type, res_params = cgi.parse_header( result_headers['Content-Type']) if res_content_type.startswith('text/') and \ 'charset' in res_params and \ not isinstance(result_text, six.text_type): result_text = result_text.decode(res_params['charset']) if six.PY3 and isinstance(result_text, bytes): result_text = result_text.decode('utf-8') ret['body'] = result_text if 'Set-Cookie' in result_headers and cookies is not None: result_cookies = parse_cookie_header(result_headers['Set-Cookie']) for item in result_cookies: sess_cookies.set_cookie(item) else: result_cookies = None if isinstance(result_headers, list): result_headers_dict = {} for header in result_headers: comps = header.split(':') result_headers_dict[comps[0].strip()] = ':'.join(comps[1:]).strip() result_headers = result_headers_dict log.debug('Response Status Code: %s', result_status_code) log.trace('Response Headers: %s', result_headers) log.trace('Response Cookies: %s', sess_cookies) # log.trace("Content: %s", result_text) coding = result_headers.get('Content-Encoding', "identity") # Requests will always decompress the content, and working around that is annoying. if backend != 'requests': result_text = __decompressContent(coding, result_text) try: log.trace('Response Text: %s', result_text) except UnicodeEncodeError as exc: log.trace( 'Cannot Trace Log Response Text: %s. This may be due to ' 'incompatibilities between requests and logging.', exc) if text_out is not None: with salt.utils.files.fopen(text_out, 'w') as tof: tof.write(result_text) if headers_out is not None and os.path.exists(headers_out): with salt.utils.files.fopen(headers_out, 'w') as hof: hof.write(result_headers) if cookies is not None: sess_cookies.save() if persist_session is True and HAS_MSGPACK: # TODO: See persist_session above if 'set-cookie' in result_headers: with salt.utils.files.fopen(session_cookie_jar, 'wb') as fh_: session_cookies = result_headers.get('set-cookie', None) if session_cookies is not None: msgpack.dump({'Cookie': session_cookies}, fh_) else: msgpack.dump('', fh_) if status is True: ret['status'] = result_status_code if headers is True: ret['headers'] = result_headers if decode is True: if decode_type == 'auto': content_type = result_headers.get('content-type', 'application/json') if 'xml' in content_type: decode_type = 'xml' elif 'json' in content_type: decode_type = 'json' elif 'yaml' in content_type: decode_type = 'yaml' else: decode_type = 'plain' valid_decodes = ('json', 'xml', 'yaml', 'plain') if decode_type not in valid_decodes: ret['error'] = ('Invalid decode_type specified. ' 'Valid decode types are: {0}'.format( pprint.pformat(valid_decodes))) log.error(ret['error']) return ret if decode_type == 'json': ret['dict'] = salt.utils.json.loads(result_text) elif decode_type == 'xml': ret['dict'] = [] items = ET.fromstring(result_text) for item in items: ret['dict'].append(xml.to_dict(item)) elif decode_type == 'yaml': ret['dict'] = salt.utils.data.decode( salt.utils.yaml.safe_load(result_text)) else: text = True if decode_out: with salt.utils.files.fopen(decode_out, 'w') as dof: dof.write(result_text) if text is True: ret['text'] = result_text return ret
except: sys.stderr.write("error: invalid port\n") exit(1) sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) ssl_sock = ssl.wrap_socket(sock, cert_reqs=ssl.CERT_REQUIRED, ssl_version=ssl.PROTOCOL_TLSv1_2, ca_certs="trusted_certs.crt") ssl_sock.connect((addr, port)) print('Connected to {}:{}'.format(addr, port)) # check remote cert cert = ssl_conn.getpeercert() print("Checking server certificate") if not cert or ssl.match_hostname(cert, "PAS - TLS server"): raise Exception("Invalid SSL cert.") print("Server certificate OK.") # Create thread for handling user input and message sending thread = threading.Thread(target=handle_input, args=[ssl_sock, sock], daemon=True) thread.start() rest = bytes() addr = ssl_sock.getsockname() # Loop indefinitely to receive messages from server while True: try: # blocks
def get_connection(self): if os.getpid() == self.pid and self.connection.value: return self.connection.value if self.secure: if self.connection.ssl_context: connection = httplib.HTTPSConnection( host=self.connection.servers[0], port=self.port, key_file=self.client_key, cert_file=self.client_cert, context=self.connection.ssl_context, timeout=4) else: connection = httplib.HTTPSConnection( host=self.connection.servers[0], port=self.port, key_file=self.client_key, cert_file=self.client_cert, timeout=4) connection.connect() if self.connection.ssl_context: peer_certificate = connection.sock.getpeercert() peer_alt_names = peer_certificate["subjectAltName"] # check if the server is an ip address if re.match( r"^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$", self.connection.servers[0]): # match ip addresses with custom code if not self.connection.servers[0] in [ alt_value for alt_type, alt_value in peer_alt_names if alt_type == 'IP Address' ]: raise Exception("".join([ "Etcd server certificate failed to match IP address ", "'%s'" % self.connection.servers[0], ])) else: # match hostnames using python implementation ssl.match_hostname(peer_certificate, self.connection.servers[0]) self.connection.value = connection else: connection = httplib.HTTPConnection( host=self.connection.servers[0], port=self.port) connection.connect() self.connection.value = connection self.pid = os.getpid() return self.connection.value
def _setup_https_tunnel(self): sock = self.sock host = self._tunnel_host port = self._tunnel_port try: lines = [] lines.append('CONNECT %s:%d HTTP/1.1' % (host, port)) lines.append('Host: %s:%d' % (host, port)) if self._tunnel_headers: for item in self._tunnel_headers.items(): lines.append('%s: %s' % item) data = '\r\n'.join(lines) + '\r\n\r\n' sock.sendall(data.encode()) data = b'' code = 0 pos = -1 while True: s = sock.recv(4096) if not s: if code == 0: raise SocketError("Tunnel connection failed: %r" % data) break data += s if code == 0 and b'\r\n' in data: version, code, message = data.split(b' ', 2) if code != b'200': sock.close() raise SocketError("Tunnel connection failed: %s %s" % (code, message.strip())) pos = data.find(b'\r\n\r\n') if pos > 0: break tls_conn = tlslite.TLSConnection(sock) try: tls_conn.handshakeClientCert(serverName=host) except Exception: sock.close() raise try: ssl.match_hostname(tlslite_getpeercert(tls_conn), host) except Exception: tls_conn.close() raise except SocketTimeout as e: raise ConnectTimeoutError( self, "Connection to %s timed out. (connect timeout=%s)" % (self.host, self.timeout)) except SocketError as e: raise NewConnectionError( self, "Failed to establish a new connection: %s" % e) # patch fileno, # let urllib3.util.connection.is_connection_dropped work as expected # tls_conn.fileno = partial(self._origin_sock.fileno) # here we always got fileno = -1 tls_conn.fileno = partial(sock.fileno) # patch getpeercert tls_conn.getpeercert = partial(tlslite_getpeercert, tls_conn) self.sock = tls_conn
import ssl cert = {'subject': ((('commonName', 'example.com'), ), )} ssl.match_hostname(cert, "example.com") ssl.match_hostname( cert, "example.org" ) #ssl.CertificateError: hostname 'example.org' doesn't match 'example.com'
def switch_to_ssl(self, ca, cert, key, verify_cert=False, verify_identity=False, cipher_suites=None, tls_versions=None): """Switch the socket to use SSL""" if not self.sock: raise errors.InterfaceError(errno=2048) try: if verify_cert: cert_reqs = ssl.CERT_REQUIRED elif verify_identity: cert_reqs = ssl.CERT_OPTIONAL else: cert_reqs = ssl.CERT_NONE if tls_versions is None or not tls_versions: context = ssl.create_default_context() if not verify_identity: context.check_hostname = False context.options else: tls_versions.sort(reverse=True) tls_version = tls_versions[0] if not TLS_V1_3_SUPPORTED and \ tls_version == "TLSv1.3" and len(tls_versions) > 1: tls_version = tls_versions[1] ssl_protocol = TLS_VERSIONS[tls_version] context = ssl.SSLContext(ssl_protocol) if tls_version == "TLSv1.3": if "TLSv1.2" not in tls_versions: context.options |= ssl.OP_NO_TLSv1_2 if "TLSv1.1" not in tls_versions: context.options |= ssl.OP_NO_TLSv1_1 if "TLSv1" not in tls_versions: context.options |= ssl.OP_NO_TLSv1 context.check_hostname = False context.verify_mode = cert_reqs context.load_default_certs() if ca: try: context.load_verify_locations(ca) except (IOError, ssl.SSLError) as err: self.sock.close() raise InterfaceError( "Invalid CA Certificate: {}".format(err)) if cert: try: context.load_cert_chain(cert, key) except (IOError, ssl.SSLError) as err: self.sock.close() raise InterfaceError( "Invalid Certificate/Key: {}".format(err)) if cipher_suites: context.set_ciphers(cipher_suites) if hasattr(self, "server_host"): self.sock = context.wrap_socket( self.sock, server_hostname=self.server_host) else: self.sock = context.wrap_socket(self.sock) if verify_identity: context.check_hostname = True hostnames = [self.server_host] if os.name == 'nt' and self.server_host == 'localhost': hostnames = ['localhost', '192.168.0.100'] aliases = socket.gethostbyaddr(self.server_host) hostnames.extend([aliases[0]] + aliases[1]) match_found = False errs = [] for hostname in hostnames: try: ssl.match_hostname(self.sock.getpeercert(), hostname) except ssl.CertificateError as err: errs.append(str(err)) else: match_found = True break if not match_found: self.sock.close() raise InterfaceError("Unable to verify server identity: {}" "".format(", ".join(errs))) except NameError: raise errors.NotSupportedError( "Python installation has no SSL support") except (ssl.SSLError, IOError) as err: raise errors.InterfaceError(errno=2055, values=(self.get_address(), _strioerror(err))) except ssl.CertificateError as err: raise errors.InterfaceError(str(err)) except NotImplementedError as err: raise errors.InterfaceError(str(err))
# # this means the prior response had one of two states: # 1) will_close: this connection was reset and the prior socket and # response operate independently # 2) persistent: the response was retained and we await its # isclosed() status to become true. # if self.__state != _CS_REQ_SENT or self.__response: raise ResponseNotReady(self.__state) if self.debuglevel > 0: response = self.response_class(self.sock, self.debuglevel, method=self._method) else: response = self.response_class(self.sock, method=self._method) response.begin() assert response.will_close != _UNKNOWN self.__state = _CS_IDLE if response.will_close: # this effectively passes the connection to the response self.close() else: # remember this, so we can tell when it is complete self.__response = response return response try: import ssl
def ssl_reconnect(self): """Reconnect the client after a disconnect. Can only be called after connect()/connect_async().""" if len(self._host) == 0: raise ValueError('Invalid host.') if self._port <= 0: raise ValueError('Invalid port number.') self._in_packet = { "command": 0, "have_remaining": 0, "remaining_count": [], "remaining_mult": 1, "remaining_length": 0, "packet": b"", "to_process": 0, "pos": 0 } self._out_packet_mutex.acquire() self._out_packet = [] self._out_packet_mutex.release() self._current_out_packet_mutex.acquire() self._current_out_packet = None self._current_out_packet_mutex.release() self._msgtime_mutex.acquire() self._last_msg_in = time.time() self._last_msg_out = time.time() self._msgtime_mutex.release() self._ping_t = 0 self._state_mutex.acquire() ## Changed self._state = mqtt_cs_new self._state = 0 self._state_mutex.release() if self._ssl: self._ssl.close() self._ssl = None self._sock = None elif self._sock: self._sock.close() self._sock = None # Put messages in progress in a valid state. self._messages_reconnect_reset() if self._tls_ca_certs is None: try: if (sys.version_info[0] == 2 and sys.version_info[1] < 7) or ( sys.version_info[0] == 3 and sys.version_info[1] < 2): self._sock = socket.create_connection((self._host, self._port)) else: self._sock = socket.create_connection( (self._host, self._port), source_address=(self._bind_address, 0)) except socket.error as err: ## Changed EAGAIN to erron.EAGAIN if err.errno != errno.EINPROGRESS and err.errno != errno.EWOULDBLOCK and err.errno != errno.EAGAIN: raise else: context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) context.verify_mode = ssl.CERT_REQUIRED context.load_verify_locations(self._tls_ca_certs) sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: conn = context.wrap_socket(sock, server_hostname=self._host) conn.connect((self._host, self._port)) except: print('Exception ', sys.exc_info()[0]) raise self._sock = conn self._ssl = conn # if self._tls_ca_certs is not None: # self._ssl = ssl.wrap_socket( # self._sock, # certfile=self._tls_certfile, # keyfile=self._tls_keyfile, # ca_certs=self._tls_ca_certs, # cert_reqs=self._tls_cert_reqs, # ssl_version=self._tls_version, # ciphers=self._tls_ciphers) # if self._tls_insecure is False: if sys.version_info[0] < 3 or (sys.version_info[0] == 3 and sys.version_info[1] < 2): self._tls_match_hostname() else: ssl.match_hostname(self._ssl.getpeercert(), self._host) self._sock.setblocking(0) return self._send_connect(self._keepalive, self._clean_session)
def query(url, method="GET", params=None, data=None, data_file=None, header_dict=None, header_list=None, header_file=None, username=None, password=None, auth=None, decode=False, decode_type="auto", status=False, headers=False, text=False, cookies=None, cookie_jar=None, cookie_format="lwp", persist_session=False, session_cookie_jar=None, data_render=False, data_renderer=None, header_render=False, header_renderer=None, template_dict=None, test=False, test_url=None, node="minion", port=80, opts=None, backend=None, ca_bundle=None, verify_ssl=None, cert=None, text_out=None, headers_out=None, decode_out=None, stream=False, streaming_callback=None, header_callback=None, handle=False, agent=USERAGENT, hide_fields=None, raise_error=True, formdata=False, formdata_fieldname=None, formdata_filename=None, decode_body=True, **kwargs): """ Query a resource, and decode the return data """ ret = {} if opts is None: if node == "master": opts = salt.config.master_config( os.path.join(salt.syspaths.CONFIG_DIR, "master")) elif node == "minion": opts = salt.config.minion_config( os.path.join(salt.syspaths.CONFIG_DIR, "minion")) else: opts = {} if not backend: backend = opts.get("backend", "tornado") match = re.match( r"https?://((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)($|/)", url, ) if not match: salt.utils.network.refresh_dns() if backend == "requests": if HAS_REQUESTS is False: ret["error"] = ("http.query has been set to use requests, but the " "requests library does not seem to be installed") log.error(ret["error"]) return ret else: requests_log = logging.getLogger("requests") requests_log.setLevel(logging.WARNING) # Some libraries don't support separation of url and GET parameters # Don't need a try/except block, since Salt depends on tornado url_full = salt.ext.tornado.httputil.url_concat(url, params) if params else url if ca_bundle is None: ca_bundle = get_ca_bundle(opts) if verify_ssl is None: verify_ssl = opts.get("verify_ssl", True) if cert is None: cert = opts.get("cert", None) if data_file is not None: data = _render(data_file, data_render, data_renderer, template_dict, opts) # Make sure no secret fields show up in logs log_url = sanitize_url(url_full, hide_fields) log.debug("Requesting URL %s using %s method", log_url, method) log.debug("Using backend: %s", backend) if method == "POST" and log.isEnabledFor(logging.TRACE): # Make sure no secret fields show up in logs if isinstance(data, dict): log_data = data.copy() if isinstance(hide_fields, list): for item in data: for field in hide_fields: if item == field: log_data[item] = "XXXXXXXXXX" log.trace("Request POST Data: %s", pprint.pformat(log_data)) else: log.trace("Request POST Data: %s", pprint.pformat(data)) if header_file is not None: header_tpl = _render(header_file, header_render, header_renderer, template_dict, opts) if isinstance(header_tpl, dict): header_dict = header_tpl else: header_list = header_tpl.splitlines() if header_dict is None: header_dict = {} if header_list is None: header_list = [] if cookie_jar is None: cookie_jar = os.path.join( opts.get("cachedir", salt.syspaths.CACHE_DIR), "cookies.txt") if session_cookie_jar is None: session_cookie_jar = os.path.join( opts.get("cachedir", salt.syspaths.CACHE_DIR), "cookies.session.p") if persist_session is True and salt.utils.msgpack.HAS_MSGPACK: # TODO: This is hackish; it will overwrite the session cookie jar with # all cookies from this one connection, rather than behaving like a # proper cookie jar. Unfortunately, since session cookies do not # contain expirations, they can't be stored in a proper cookie jar. if os.path.isfile(session_cookie_jar): with salt.utils.files.fopen(session_cookie_jar, "rb") as fh_: session_cookies = salt.utils.msgpack.load(fh_) if isinstance(session_cookies, dict): header_dict.update(session_cookies) else: with salt.utils.files.fopen(session_cookie_jar, "wb") as fh_: salt.utils.msgpack.dump("", fh_) for header in header_list: comps = header.split(":") if len(comps) < 2: continue header_dict[comps[0].strip()] = comps[1].strip() if not auth: if username and password: auth = (username, password) if agent == USERAGENT: agent = "{0} http.query()".format(agent) header_dict["User-agent"] = agent if backend == "requests": sess = requests.Session() sess.auth = auth sess.headers.update(header_dict) log.trace("Request Headers: %s", sess.headers) sess_cookies = sess.cookies sess.verify = verify_ssl elif backend == "urllib2": sess_cookies = None else: # Tornado sess_cookies = None if cookies is not None: if cookie_format == "mozilla": sess_cookies = salt.ext.six.moves.http_cookiejar.MozillaCookieJar( cookie_jar) else: sess_cookies = salt.ext.six.moves.http_cookiejar.LWPCookieJar( cookie_jar) if not os.path.isfile(cookie_jar): sess_cookies.save() sess_cookies.load() if test is True: if test_url is None: return {} else: url = test_url ret["test"] = True if backend == "requests": req_kwargs = {} if stream is True: if requests.__version__[0] == "0": # 'stream' was called 'prefetch' before 1.0, with flipped meaning req_kwargs["prefetch"] = False else: req_kwargs["stream"] = True # Client-side cert handling if cert is not None: if isinstance(cert, six.string_types): if os.path.exists(cert): req_kwargs["cert"] = cert elif isinstance(cert, list): if os.path.exists(cert[0]) and os.path.exists(cert[1]): req_kwargs["cert"] = cert else: log.error( "The client-side certificate path that" " was passed is not valid: %s", cert, ) if formdata: if not formdata_fieldname: ret["error"] = "formdata_fieldname is required when formdata=True" log.error(ret["error"]) return ret result = sess.request(method, url, params=params, files={ formdata_fieldname: (formdata_filename, StringIO(data)) }, **req_kwargs) else: result = sess.request(method, url, params=params, data=data, **req_kwargs) result.raise_for_status() if stream is True: # fake a HTTP response header header_callback("HTTP/1.0 {0} MESSAGE".format(result.status_code)) # fake streaming the content streaming_callback(result.content) return { "handle": result, } if handle is True: return { "handle": result, "body": result.content, } log.debug("Final URL location of Response: %s", sanitize_url(result.url, hide_fields)) result_status_code = result.status_code result_headers = result.headers result_text = result.content result_cookies = result.cookies body = result.content if not isinstance(body, six.text_type) and decode_body: body = body.decode(result.encoding or "utf-8") ret["body"] = body elif backend == "urllib2": request = urllib_request.Request(url_full, data) handlers = [ urllib_request.HTTPHandler, urllib_request.HTTPCookieProcessor(sess_cookies), ] if url.startswith("https"): hostname = request.get_host() handlers[0] = urllib_request.HTTPSHandler(1) if not HAS_MATCHHOSTNAME: log.warning( "match_hostname() not available, SSL hostname checking " "not available. THIS CONNECTION MAY NOT BE SECURE!") elif verify_ssl is False: log.warning("SSL certificate verification has been explicitly " "disabled. THIS CONNECTION MAY NOT BE SECURE!") else: if ":" in hostname: hostname, port = hostname.split(":") else: port = 443 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((hostname, int(port))) sockwrap = ssl.wrap_socket(sock, ca_certs=ca_bundle, cert_reqs=ssl.CERT_REQUIRED) try: match_hostname(sockwrap.getpeercert(), hostname) except CertificateError as exc: ret["error"] = ( "The certificate was invalid. Error returned was: %s", pprint.pformat(exc), ) return ret # Client-side cert handling if cert is not None: cert_chain = None if isinstance(cert, six.string_types): if os.path.exists(cert): cert_chain = cert elif isinstance(cert, list): if os.path.exists(cert[0]) and os.path.exists(cert[1]): cert_chain = cert else: log.error( "The client-side certificate path that was " "passed is not valid: %s", cert, ) return if hasattr(ssl, "SSLContext"): # Python >= 2.7.9 context = ssl.SSLContext.load_cert_chain(*cert_chain) handlers.append( urllib_request.HTTPSHandler(context=context)) # pylint: disable=E1123 else: # Python < 2.7.9 cert_kwargs = { "host": request.get_host(), "port": port, "cert_file": cert_chain[0], } if len(cert_chain) > 1: cert_kwargs["key_file"] = cert_chain[1] handlers[ 0] = salt.ext.six.moves.http_client.HTTPSConnection( **cert_kwargs) opener = urllib_request.build_opener(*handlers) for header in header_dict: request.add_header(header, header_dict[header]) request.get_method = lambda: method try: result = opener.open(request) except URLError as exc: return {"Error": six.text_type(exc)} if stream is True or handle is True: return { "handle": result, "body": result.content, } result_status_code = result.code result_headers = dict(result.info()) result_text = result.read() if "Content-Type" in result_headers: res_content_type, res_params = cgi.parse_header( result_headers["Content-Type"]) if (res_content_type.startswith("text/") and "charset" in res_params and not isinstance(result_text, six.text_type)): result_text = result_text.decode(res_params["charset"]) if six.PY3 and isinstance(result_text, bytes) and decode_body: result_text = result_text.decode("utf-8") ret["body"] = result_text else: # Tornado req_kwargs = {} # Client-side cert handling if cert is not None: if isinstance(cert, six.string_types): if os.path.exists(cert): req_kwargs["client_cert"] = cert elif isinstance(cert, list): if os.path.exists(cert[0]) and os.path.exists(cert[1]): req_kwargs["client_cert"] = cert[0] req_kwargs["client_key"] = cert[1] else: log.error( "The client-side certificate path that " "was passed is not valid: %s", cert, ) if isinstance(data, dict): data = _urlencode(data) if verify_ssl: req_kwargs["ca_certs"] = ca_bundle max_body = opts.get("http_max_body", salt.config.DEFAULT_MINION_OPTS["http_max_body"]) connect_timeout = opts.get( "http_connect_timeout", salt.config.DEFAULT_MINION_OPTS["http_connect_timeout"], ) timeout = opts.get( "http_request_timeout", salt.config.DEFAULT_MINION_OPTS["http_request_timeout"], ) client_argspec = None proxy_host = opts.get("proxy_host", None) if proxy_host: # tornado requires a str for proxy_host, cannot be a unicode str in py2 proxy_host = salt.utils.stringutils.to_str(proxy_host) proxy_port = opts.get("proxy_port", None) proxy_username = opts.get("proxy_username", None) if proxy_username: # tornado requires a str, cannot be unicode str in py2 proxy_username = salt.utils.stringutils.to_str(proxy_username) proxy_password = opts.get("proxy_password", None) if proxy_password: # tornado requires a str, cannot be unicode str in py2 proxy_password = salt.utils.stringutils.to_str(proxy_password) no_proxy = opts.get("no_proxy", []) # Since tornado doesnt support no_proxy, we'll always hand it empty proxies or valid ones # except we remove the valid ones if a url has a no_proxy hostname in it if urlparse(url_full).hostname in no_proxy: proxy_host = None proxy_port = None # We want to use curl_http if we have a proxy defined if proxy_host and proxy_port: if HAS_CURL_HTTPCLIENT is False: ret["error"] = ( "proxy_host and proxy_port has been set. This requires pycurl and tornado, " "but the libraries does not seem to be installed") log.error(ret["error"]) return ret salt.ext.tornado.httpclient.AsyncHTTPClient.configure( "tornado.curl_httpclient.CurlAsyncHTTPClient") client_argspec = salt.utils.args.get_function_argspec( salt.ext.tornado.curl_httpclient.CurlAsyncHTTPClient.initialize ) else: client_argspec = salt.utils.args.get_function_argspec( salt.ext.tornado.simple_httpclient.SimpleAsyncHTTPClient. initialize) supports_max_body_size = "max_body_size" in client_argspec.args req_kwargs.update({ "method": method, "headers": header_dict, "auth_username": username, "auth_password": password, "body": data, "validate_cert": verify_ssl, "allow_nonstandard_methods": True, "streaming_callback": streaming_callback, "header_callback": header_callback, "connect_timeout": connect_timeout, "request_timeout": timeout, "proxy_host": proxy_host, "proxy_port": proxy_port, "proxy_username": proxy_username, "proxy_password": proxy_password, "raise_error": raise_error, "decompress_response": False, }) # Unicode types will cause a TypeError when Tornado's curl HTTPClient # invokes setopt. Therefore, make sure all arguments we pass which # contain strings are str types. req_kwargs = salt.utils.data.decode(req_kwargs, to_str=True) try: download_client = (HTTPClient(max_body_size=max_body) if supports_max_body_size else HTTPClient()) result = download_client.fetch(url_full, **req_kwargs) except salt.ext.tornado.httpclient.HTTPError as exc: ret["status"] = exc.code ret["error"] = six.text_type(exc) return ret except (socket.herror, socket.error, socket.timeout, socket.gaierror) as exc: if status is True: ret["status"] = 0 ret["error"] = six.text_type(exc) log.debug("Cannot perform 'http.query': {0} - {1}".format( url_full, ret["error"])) return ret if stream is True or handle is True: return { "handle": result, "body": result.body, } result_status_code = result.code result_headers = result.headers result_text = result.body if "Content-Type" in result_headers: res_content_type, res_params = cgi.parse_header( result_headers["Content-Type"]) if (res_content_type.startswith("text/") and "charset" in res_params and not isinstance(result_text, six.text_type)): result_text = result_text.decode(res_params["charset"]) if six.PY3 and isinstance(result_text, bytes) and decode_body: result_text = result_text.decode("utf-8") ret["body"] = result_text if "Set-Cookie" in result_headers and cookies is not None: result_cookies = parse_cookie_header(result_headers["Set-Cookie"]) for item in result_cookies: sess_cookies.set_cookie(item) else: result_cookies = None if isinstance(result_headers, list): result_headers_dict = {} for header in result_headers: comps = header.split(":") result_headers_dict[comps[0].strip()] = ":".join(comps[1:]).strip() result_headers = result_headers_dict log.debug("Response Status Code: %s", result_status_code) log.trace("Response Headers: %s", result_headers) log.trace("Response Cookies: %s", sess_cookies) # log.trace("Content: %s", result_text) coding = result_headers.get("Content-Encoding", "identity") # Requests will always decompress the content, and working around that is annoying. if backend != "requests": result_text = __decompressContent(coding, result_text) try: log.trace("Response Text: %s", result_text) except UnicodeEncodeError as exc: log.trace( "Cannot Trace Log Response Text: %s. This may be due to " "incompatibilities between requests and logging.", exc, ) if text_out is not None: with salt.utils.files.fopen(text_out, "w") as tof: tof.write(result_text) if headers_out is not None and os.path.exists(headers_out): with salt.utils.files.fopen(headers_out, "w") as hof: hof.write(result_headers) if cookies is not None: sess_cookies.save() if persist_session is True and salt.utils.msgpack.HAS_MSGPACK: # TODO: See persist_session above if "set-cookie" in result_headers: with salt.utils.files.fopen(session_cookie_jar, "wb") as fh_: session_cookies = result_headers.get("set-cookie", None) if session_cookies is not None: salt.utils.msgpack.dump({"Cookie": session_cookies}, fh_) else: salt.utils.msgpack.dump("", fh_) if status is True: ret["status"] = result_status_code if headers is True: ret["headers"] = result_headers if decode is True: if decode_type == "auto": content_type = result_headers.get("content-type", "application/json") if "xml" in content_type: decode_type = "xml" elif "json" in content_type: decode_type = "json" elif "yaml" in content_type: decode_type = "yaml" else: decode_type = "plain" valid_decodes = ("json", "xml", "yaml", "plain") if decode_type not in valid_decodes: ret["error"] = ("Invalid decode_type specified. " "Valid decode types are: {0}".format( pprint.pformat(valid_decodes))) log.error(ret["error"]) return ret if decode_type == "json": ret["dict"] = salt.utils.json.loads(result_text) elif decode_type == "xml": ret["dict"] = [] items = ET.fromstring(result_text) for item in items: ret["dict"].append(xml.to_dict(item)) elif decode_type == "yaml": ret["dict"] = salt.utils.data.decode( salt.utils.yaml.safe_load(result_text)) else: text = True if decode_out: with salt.utils.files.fopen(decode_out, "w") as dof: dof.write(result_text) if text is True: ret["text"] = result_text return ret
def _on_handshake(self, start_time): try: self._sock.do_handshake() except ssl.SSLWantReadError: self._loop.add_reader(self._sock_fd, self._on_handshake, start_time) return except ssl.SSLWantWriteError: self._loop.add_writer(self._sock_fd, self._on_handshake, start_time) return except BaseException as exc: if self._loop.get_debug(): logger.warning("%r: SSL handshake failed", self, exc_info=True) self._loop.remove_reader(self._sock_fd) self._loop.remove_writer(self._sock_fd) self._sock.close() self._wakeup_waiter(exc) if isinstance(exc, Exception): return else: raise self._loop.remove_reader(self._sock_fd) self._loop.remove_writer(self._sock_fd) peercert = self._sock.getpeercert() if not hasattr(self._sslcontext, 'check_hostname'): # Verify hostname if requested, Python 3.4+ uses check_hostname # and checks the hostname in do_handshake() if (self._server_hostname and self._sslcontext.verify_mode != ssl.CERT_NONE): try: ssl.match_hostname(peercert, self._server_hostname) except Exception as exc: if self._loop.get_debug(): logger.warning( "%r: SSL handshake failed " "on matching the hostname", self, exc_info=True) self._sock.close() self._wakeup_waiter(exc) return # Add extra info that becomes available after handshake. self._extra.update( peercert=peercert, cipher=self._sock.cipher(), compression=self._sock.compression(), ) self._read_wants_write = False self._write_wants_read = False self._loop.add_reader(self._sock_fd, self._read_ready) self._protocol_connected = True self._loop.call_soon(self._protocol.connection_made, self) # only wake up the waiter when connection_made() has been called self._loop.call_soon(self._wakeup_waiter) if self._loop.get_debug(): dt = self._loop.time() - start_time logger.debug("%r: SSL handshake took %.1f ms", self, dt * 1e3)
import ssl from pprint import pprint TARGET_HOST = 'localhost' TARGET_PORT = 8000 CA_CERT_PATH = 'server.crt' if __name__ == '__main__': sock = socket() ssl_conn = ssl.wrap_socket(sock, cert_reqs=ssl.CERT_REQUIRED, ssl_version=ssl.PROTOCOL_TLSv1, ca_certs=CA_CERT_PATH) target_host = TARGET_HOST target_port = TARGET_PORT ssl_conn.connect((target_host, int(target_port))) cert = ssl_conn.getpeercert() print("Checking server certificate") pprint(cert) if not cert or ssl.match_hostname(cert, target_host): raise Exception("Invalid SSL cert for host %s. Check if\ this is a man in the middle attack!" % target_host) print("Sever certificate OK.\n Sending some custom requiest...\ GET") ssl_conn.wrtie('GET / \n'.encode('utf-8')) print("Response received from server:") print(ssl_conn.read()) ssl_conn.close()
def __init__(self, parent, timeout): self.host = parent._parent.host self.port = parent._parent.port self._read_buffer = None self._socket = None self.ssl = parent._parent.ssl deadline = time.time() + timeout try: self._socket = socket.create_connection((self.host, self.port), timeout) self._socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) if len(self.ssl) > 0: try: if hasattr(ssl, "SSLContext" ): # Python2.7 and 3.2+, or backports.ssl ssl_context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) if hasattr(ssl_context, "options"): ssl_context.options |= getattr( ssl, "OP_NO_SSLv2", 0) ssl_context.options |= getattr( ssl, "OP_NO_SSLv3", 0) ssl_context.verify_mode = ssl.CERT_REQUIRED ssl_context.check_hostname = ( True # redundant with match_hostname ) ssl_context.load_verify_locations(self.ssl["ca_certs"]) self._socket = ssl_context.wrap_socket( self._socket, server_hostname=self.host) else: # this does not disable SSLv2 or SSLv3 self._socket = ssl.wrap_socket( self._socket, cert_reqs=ssl.CERT_REQUIRED, ssl_version=ssl.PROTOCOL_SSLv23, ca_certs=self.ssl["ca_certs"], ) except IOError as err: self._socket.close() if "EOF occurred in violation of protocol" in str( err) or "sslv3 alert handshake failure" in str( err): # probably on an older version of OpenSSL raise ReqlDriverError( "SSL handshake failed, likely because Python is linked against an old version of OpenSSL " "that does not support either TLSv1.2 or any of the allowed ciphers. This can be worked " "around by lowering the security setting on the server with the options " "`--tls-min-protocol TLSv1 --tls-ciphers " "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH:AES256-SHA` (see server log for more " "information): %s" % str(err)) else: raise ReqlDriverError( "SSL handshake failed (see server log for more information): %s" % str(err)) try: match_hostname(self._socket.getpeercert(), hostname=self.host) except CertificateError: self._socket.close() raise parent._parent.handshake.reset() response = None while True: request = parent._parent.handshake.next_message(response) if request is None: break # This may happen in the `V1_0` protocol where we send two requests as # an optimization, then need to read each separately if request is not "": self.sendall(request) # The response from the server is a null-terminated string response = b"" while True: char = self.recvall(1, deadline) if char == b"\0": break response += char except (ReqlAuthError, ReqlTimeoutError): self.close() raise except ReqlDriverError as ex: self.close() error = (str(ex).replace("receiving from", "during handshake with").replace( "sending to", "during handshake with")) raise ReqlDriverError(error) except socket.timeout as ex: self.close() raise ReqlTimeoutError(self.host, self.port) except Exception as ex: self.close() raise ReqlDriverError("Could not connect to %s:%s. Error: %s" % (self.host, self.port, str(ex)))