class WinRM::HTTP::HttpTransport

A generic HTTP transport that utilized HTTPClient to send messages back and forth. This backend will maintain state for every WinRMWebService instance that is instantiated so it is possible to use GSSAPI with Keep-Alive.

Attributes

endpoint[R]

Public Class Methods

new(endpoint, options) click to toggle source
# File lib/winrm/http/transport.rb, line 26
def initialize(endpoint, options)
  @endpoint = endpoint.is_a?(String) ? URI.parse(endpoint) : endpoint
  @httpcli = HTTPClient.new(agent_name: 'Ruby WinRM Client')
  @logger = Logging.logger[self]
  @httpcli.receive_timeout = options[:receive_timeout]
end

Public Instance Methods

basic_auth_only!() click to toggle source

We’ll need this to force basic authentication if desired

# File lib/winrm/http/transport.rb, line 56
def basic_auth_only!
  auths = @httpcli.www_auth.instance_variable_get('@authenticator')
  auths.delete_if { |i| i.scheme !~ /basic/i }
end
no_ssl_peer_verification!() click to toggle source

Disable SSL Peer Verification

# File lib/winrm/http/transport.rb, line 68
def no_ssl_peer_verification!
  @httpcli.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE
end
no_sspi_auth!() click to toggle source

Disable SSPI Auth

# File lib/winrm/http/transport.rb, line 62
def no_sspi_auth!
  auths = @httpcli.www_auth.instance_variable_get('@authenticator')
  auths.delete_if { |i| i.is_a? HTTPClient::SSPINegotiateAuth }
end
send_request(message) click to toggle source

Sends the SOAP payload to the WinRM service and returns the service’s SOAP response. If an error occurrs an appropriate error is raised.

@param [String] The XML SOAP message @returns [REXML::Document] The parsed response body

# File lib/winrm/http/transport.rb, line 38
def send_request(message)
  ssl_peer_fingerprint_verification!
  log_soap_message(message)
  hdr = { 'Content-Type' => 'application/soap+xml;charset=UTF-8',
          'Content-Length' => message.bytesize }
  # We need to add this header if using Client Certificate authentication
  unless @httpcli.ssl_config.client_cert.nil?
    hdr['Authorization'] = 'http://schemas.dmtf.org/wbem/wsman/1/wsman/secprofile/https/mutual'
  end

  resp = @httpcli.post(@endpoint, message, hdr)
  log_soap_message(resp.http_body.content)
  verify_ssl_fingerprint(resp.peer_cert)
  handler = WinRM::ResponseHandler.new(resp.http_body.content, resp.status)
  handler.parse_to_xml
end
ssl_peer_fingerprint_verification!() click to toggle source

SSL Peer Fingerprint Verification prior to connecting

# File lib/winrm/http/transport.rb, line 73
def ssl_peer_fingerprint_verification!
  return unless @ssl_peer_fingerprint && !@ssl_peer_fingerprint_verified

  with_untrusted_ssl_connection do |connection|
    connection_cert = connection.peer_cert
    verify_ssl_fingerprint(connection_cert)
  end
  @logger.info("initial ssl fingerprint #{@ssl_peer_fingerprint} verified\n")
  @ssl_peer_fingerprint_verified = true
  no_ssl_peer_verification!
end
verify_ssl_fingerprint(cert) click to toggle source

compare @ssl_peer_fingerprint to current ssl context

# File lib/winrm/http/transport.rb, line 100
def verify_ssl_fingerprint(cert)
  return unless @ssl_peer_fingerprint

  conn_fingerprint = OpenSSL::Digest::SHA1.new(cert.to_der).to_s
  return unless @ssl_peer_fingerprint.casecmp(conn_fingerprint) != 0

  raise "ssl fingerprint mismatch!!!!\n"
end
with_untrusted_ssl_connection() { |ssl_connection| ... } click to toggle source

Connect without verification to retrieve untrusted ssl context

# File lib/winrm/http/transport.rb, line 86
def with_untrusted_ssl_connection
  noverify_peer_context = OpenSSL::SSL::SSLContext.new
  noverify_peer_context.verify_mode = OpenSSL::SSL::VERIFY_NONE
  tcp_connection = TCPSocket.new(@endpoint.host, @endpoint.port)
  begin
    ssl_connection = OpenSSL::SSL::SSLSocket.new(tcp_connection, noverify_peer_context)
    ssl_connection.connect
    yield ssl_connection
  ensure
    tcp_connection.close
  end
end

Protected Instance Methods

body(message, length, type = 'application/HTTP-SPNEGO-session-encrypted') click to toggle source
# File lib/winrm/http/transport.rb, line 111
def body(message, length, type = 'application/HTTP-SPNEGO-session-encrypted')
  [
    '--Encrypted Boundary',
    "Content-Type: #{type}",
    "OriginalContent: type=application/soap+xml;charset=UTF-8;Length=#{length}",
    '--Encrypted Boundary',
    'Content-Type: application/octet-stream',
    "#{message}--Encrypted Boundary--"
  ].join("\r\n").concat("\r\n")
end
log_soap_message(message) click to toggle source
# File lib/winrm/http/transport.rb, line 122
def log_soap_message(message)
  return unless @logger.debug?

  xml_msg = REXML::Document.new(message)
  formatter = REXML::Formatters::Pretty.new(2)
  formatter.compact = true
  formatter.write(xml_msg, @logger)
  @logger.debug("\n")
rescue StandardError => e
  @logger.debug("Couldn't log SOAP request/response: #{e.message} - #{message}")
end