Beispiel #1
0
    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)
Beispiel #2
0
	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)
Beispiel #3
0
    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)
Beispiel #4
0
Datei: pool.py Projekt: Alpus/Eth
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)
Beispiel #6
0
    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
Beispiel #7
0
  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)
Beispiel #8
0
    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
Beispiel #9
0
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
Beispiel #12
0
 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'))
Beispiel #13
0
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)))
Beispiel #14
0
    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))
                )
Beispiel #15
0
    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)
Beispiel #16
0
 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
Beispiel #17
0
 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)
Beispiel #18
0
 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)
Beispiel #19
0
    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
Beispiel #21
0
    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)
Beispiel #22
0
    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)
Beispiel #23
0
    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)
Beispiel #24
0
 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
Beispiel #25
0
    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)
Beispiel #26
0
    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)
Beispiel #27
0
    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
Beispiel #28
0
 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
Beispiel #29
0
 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
Beispiel #31
0
    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)))
Beispiel #32
0
    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
Beispiel #33
0
    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()
Beispiel #34
0
 def patched_match_hostname(cert, hostname):
     return ssl.match_hostname(cert, hostname)
Beispiel #35
0
    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)
Beispiel #36
0
    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)
Beispiel #37
0
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)))
Beispiel #38
0
    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)
Beispiel #39
0
    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)
Beispiel #40
0
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))
Beispiel #41
0
            # 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):
Beispiel #42
0
        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"
Beispiel #43
0
    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
Beispiel #44
0
    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, ))
Beispiel #45
0
    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))
Beispiel #46
0
    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)
Beispiel #47
0
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
Beispiel #48
0
 def match_hostname(self, hostname):
     raise NotImplementedError()
     # We need a dict-like representation, like SSLSocket.getpeercert()
     # returns
     return ssl.match_hostname(None, hostname)
Beispiel #49
0
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
Beispiel #50
0
    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
Beispiel #51
0
    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
Beispiel #53
0
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))
Beispiel #55
0
        #
        # 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
Beispiel #56
0
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)
Beispiel #57
0
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()
Beispiel #60
0
    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)))