Class: HTTPClient::SSPINegotiateAuth

Inherits:
Object
  • Object
show all
Includes:
Mutex_m
Defined in:
lib/httpclient/auth.rb

Overview

Authentication filter for handling Negotiate/NTLM negotiation. Used in ProxyAuth.

SSPINegotiateAuth depends on ‘win32/sspi’ module.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeSSPINegotiateAuth

Creates new SSPINegotiateAuth filter.



606
607
608
609
610
# File 'lib/httpclient/auth.rb', line 606

def initialize
  super
  @challenge = {}
  @scheme = "Negotiate"
end

Instance Attribute Details

#schemeObject (readonly)

Authentication scheme.



603
604
605
# File 'lib/httpclient/auth.rb', line 603

def scheme
  @scheme
end

Instance Method Details

#challenge(uri, param_str) ⇒ Object

Challenge handler: remember URL and challenge token for response.



668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
# File 'lib/httpclient/auth.rb', line 668

def challenge(uri, param_str)
  synchronize {
    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

#get(req) ⇒ Object

Response handler: returns credential. See win32/sspi for negotiation state transition.



634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
# File 'lib/httpclient/auth.rb', line 634

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
    Util.try_require('win32/sspi') || Util.try_require('gssapi') || return
    state = param[:state]
    authenticator = param[:authenticator]
    authphrase = param[:authphrase]
    case state
    when :init
      if defined?(Win32::SSPI)
        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 defined?(Win32::SSPI)
        return authenticator.complete_authentication(authphrase)
      else # use GSSAPI
        return authenticator.init_context(authphrase.unpack('m').pop)
      end
    end
    nil
  }
end

#reset_challengeObject

Resets challenge state. Do not send ‘*Authorization’ header until the server sends ‘*Authentication’ again.



614
615
616
617
618
# File 'lib/httpclient/auth.rb', line 614

def reset_challenge
  synchronize do
    @challenge.clear
  end
end

#set(*args) ⇒ Object

Set authentication credential. NOT SUPPORTED: username and necessary data is retrieved by win32/sspi. See win32/sspi for more details.



623
624
625
# File 'lib/httpclient/auth.rb', line 623

def set(*args)
  # not supported
end

#set?Boolean

Check always (not effective but it works)

Returns:

  • (Boolean)


628
629
630
# File 'lib/httpclient/auth.rb', line 628

def set?
  !@challenge.empty?
end