class WinRM::HTTP::HttpNegotiate
NTLM/Negotiate, secure, HTTP
transport
Public Class Methods
new(endpoint, user, pass, opts)
click to toggle source
Calls superclass method
WinRM::HTTP::HttpTransport::new
# File lib/winrm/http/transport.rb, line 149 def initialize(endpoint, user, pass, opts) super(endpoint, opts) require 'rubyntlm' no_sspi_auth! user_parts = user.split('\\') if user_parts.length > 1 opts[:domain] = user_parts[0] user = user_parts[1] end @ntlmcli = Net::NTLM::Client.new(user, pass, opts) @retryable = true no_ssl_peer_verification! if opts[:no_ssl_peer_verification] @ssl_peer_fingerprint = opts[:ssl_peer_fingerprint] @httpcli.ssl_config.set_trust_ca(opts[:ca_trust_path]) if opts[:ca_trust_path] @httpcli.ssl_config.cert_store = opts[:cert_store] if opts[:cert_store] end
Public Instance Methods
send_request(message)
click to toggle source
# File lib/winrm/http/transport.rb, line 168 def send_request(message) ssl_peer_fingerprint_verification! init_auth if @ntlmcli.session.nil? log_soap_message(message) hdr = { 'Content-Type' => 'multipart/encrypted;'\ 'protocol="application/HTTP-SPNEGO-session-encrypted";boundary="Encrypted Boundary"' } resp = @httpcli.post(@endpoint, body(seal(message), message.bytesize), hdr) verify_ssl_fingerprint(resp.peer_cert) if resp.status == 401 && @retryable @retryable = false init_auth send_request(message) else @retryable = true decrypted_body = winrm_decrypt(resp) log_soap_message(decrypted_body) WinRM::ResponseHandler.new(decrypted_body, resp.status).parse_to_xml end end
Private Instance Methods
channel_binding(response)
click to toggle source
# File lib/winrm/http/transport.rb, line 250 def channel_binding(response) if response.peer_cert.nil? nil else cert = if RUBY_PLATFORM == 'java' OpenSSL::X509::Certificate.new(response.peer_cert.cert.getEncoded) else response.peer_cert end Net::NTLM::ChannelBinding.create(OpenSSL::X509::Certificate.new(cert)) end end
init_auth()
click to toggle source
# File lib/winrm/http/transport.rb, line 230 def init_auth @logger.debug "Initializing Negotiate for #{@endpoint}" auth1 = @ntlmcli.init_context hdr = { 'Authorization' => "Negotiate #{auth1.encode64}", 'Content-Type' => 'application/soap+xml;charset=UTF-8' } @logger.debug 'Sending HTTP POST for Negotiate Authentication' r = @httpcli.post(@endpoint, '', hdr) verify_ssl_fingerprint(r.peer_cert) auth_header = r.header['WWW-Authenticate'].pop unless auth_header msg = "Unable to parse authorization header. Headers: #{r.headers}\r\nBody: #{r.body}" raise WinRMHTTPTransportError.new(msg, r.status_code) end itok = auth_header.split.last auth3 = @ntlmcli.init_context(itok, channel_binding(r)) issue_challenge_response(auth3) end
issue_challenge_response(negotiate)
click to toggle source
# File lib/winrm/http/transport.rb, line 215 def issue_challenge_response(negotiate) auth_header = { 'Authorization' => "Negotiate #{negotiate.encode64}", 'Content-Type' => 'application/soap+xml;charset=UTF-8' } # OMI Server on Linux requires an empty payload with the new auth header to proceed # because the config check for max payload size will otherwise break the auth handshake # given the OMI server does not support that check @httpcli.post(@endpoint, '', auth_header) # return an empty hash of headers for subsequent requests to use {} end
seal(message)
click to toggle source
# File lib/winrm/http/transport.rb, line 194 def seal(message) emessage = @ntlmcli.session.seal_message message signature = @ntlmcli.session.sign_message message "\x10\x00\x00\x00#{signature}#{emessage}" end
winrm_decrypt(resp)
click to toggle source
# File lib/winrm/http/transport.rb, line 200 def winrm_decrypt(resp) # OMI server doesn't always respond to encrypted messages with encrypted responses over SSL return resp.body if resp.header['Content-Type'].first =~ %r{\Aapplication\/soap\+xml}i return '' if resp.body.empty? str = resp.body.force_encoding('BINARY') str.sub!(%r{^.*Content-Type: application\/octet-stream\r\n(.*)--Encrypted.*$}m, '\1') signature = str[4..19] message = @ntlmcli.session.unseal_message str[20..-1] return message if @ntlmcli.session.verify_signature(signature, message) raise WinRMHTTPTransportError, 'Could not decrypt NTLM message.' end