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.



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

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

Instance Attribute Details

#schemeObject (readonly)

Authentication scheme.



599
600
601
# File 'lib/httpclient/auth.rb', line 599

def scheme
  @scheme
end

Instance Method Details

#challenge(uri, param_str) ⇒ Object

Challenge handler: remember URL and challenge token for response.



664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
# File 'lib/httpclient/auth.rb', line 664

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.



630
631
632
633
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
# File 'lib/httpclient/auth.rb', line 630

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.



610
611
612
613
614
# File 'lib/httpclient/auth.rb', line 610

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.



619
620
621
# File 'lib/httpclient/auth.rb', line 619

def set(*args)
  # not supported
end

#set?Boolean

Check always (not effective but it works)

Returns:

  • (Boolean)


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

def set?
  !@challenge.empty?
end