class HTTPClient::SSPINegotiateAuth

SSPINegotiateAuth depends on ‘win32/sspi’ module.
Used in ProxyAuth.
Authentication filter for handling Negotiate/NTLM negotiation.

def challenge(uri, param_str)

Challenge handler: remember URL and challenge token for response.
def challenge(uri, param_str)
  return false unless SSPIEnabled || GSSAPIEnabled
  if param_str.nil? or @challenge[uri].nil?
    c = @challenge[uri] = {}
    c[:state] = :init
    c[:authenticator] = nil
    c[:authphrase] = ""
  else
    c = @challenge[uri]
    c[:state] = :response
    c[:authphrase] = param_str
  end
  true
end

def get(req)

See win32/sspi for negotiation state transition.
Response handler: returns credential.
def get(req)
  return nil unless SSPIEnabled || GSSAPIEnabled
  target_uri = req.header.request_uri
  domain_uri, param = @challenge.find { |uri, v|
    Util.uri_part_of(target_uri, uri)
  }
  return nil unless param
  state = param[:state]
  authenticator = param[:authenticator]
  authphrase = param[:authphrase]
  case state
  when :init
    if SSPIEnabled
      authenticator = param[:authenticator] = Win32::SSPI::NegotiateAuth.new
      return authenticator.get_initial_token(@scheme)
    else # use GSSAPI
      authenticator = param[:authenticator] = GSSAPI::Simple.new(domain_uri.host, 'HTTP')
      # Base64 encode the context token
      return [authenticator.init_context].pack('m').gsub(/\n/,'')
    end
  when :response
    @challenge.delete(domain_uri)
    if SSPIEnabled
      return authenticator.complete_authentication(authphrase)
    else # use GSSAPI
      return authenticator.init_context(authphrase.unpack('m').pop)
    end
  end
  nil
end

def initialize

Creates new SSPINegotiateAuth filter.
def initialize
  @challenge = {}
  @scheme = "Negotiate"
end

def reset_challenge

server sends '*Authentication' again.
Resets challenge state. Do not send '*Authorization' header until the
def reset_challenge
  @challenge.clear
end

def set(*args)

See win32/sspi for more details.
NOT SUPPORTED: username and necessary data is retrieved by win32/sspi.
Set authentication credential.
def set(*args)
  # not supported
end

def set?

have we marked this as set - ie that it's valid to use in this context?
def set?
  SSPIEnabled || GSSAPIEnabled
end