class HTTPClient::NegotiateAuth

NegotiateAuth depends on ‘ruby/ntlm’ module.
Used in WWWAuth and 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)
  synchronize {
    if param_str.nil? or @challenge[uri].nil?
      c = @challenge[uri] = {}
      c[:state] = :init
      c[:authphrase] = ""
    else
      c = @challenge[uri]
      c[:state] = :response
      c[:authphrase] = param_str
    end
    true
  }
end

def get(req)

See ruby/ntlm for negotiation state transition.
Response handler: returns credential.
def get(req)
  target_uri = req.header.request_uri
  synchronize {
    _domain_uri, param = @challenge.find { |uri, v|
      Util.uri_part_of(target_uri, uri)
    }
    return nil unless param
    user, passwd = Util.hash_find_value(@auth) { |uri, auth_data|
      Util.uri_part_of(target_uri, uri)
    }
    unless user
      user, passwd = @auth_default
    end
    return nil unless user
    Util.try_require('net/ntlm') || return
    domain = nil
    domain, user = user.split("\\") if user.index("\\")
    state = param[:state]
    authphrase = param[:authphrase]
    case state
    when :init
      t1 = Net::NTLM::Message::Type1.new
      t1.domain = domain if domain
      t1.encode64
    when :response
      t2 = Net::NTLM::Message.decode64(authphrase)
      param = {:user => user, :password => passwd}
      param[:domain] = domain if domain
      t3 = t2.response(param, @ntlm_opt.dup)
      @challenge[target_uri][:state] = :done
      t3.encode64
    when :done
      :skip
    else
      nil
    end
  }
end

def initialize(scheme = "Negotiate")

Creates new NegotiateAuth filter.
def initialize(scheme = "Negotiate")
  super(scheme)
  @auth = {}
  @auth_default = nil
  @ntlm_opt = {
    :ntlmv2 => true
  }
end

def set(uri, user, passwd)

uri == nil for generic purpose (allow to use user/password for any URL).
Set authentication credential.
def set(uri, user, passwd)
  synchronize do
    if uri
      uri = Util.uri_dirname(uri)
      @auth[uri] = [user, passwd]
    else
      @auth_default = [user, passwd]
    end
  end
end

def set?

have we marked this as set - ie that it's valid to use in this context?
def set?
  @auth_default || @auth.any?
end