class HTTPClient::DigestAuth
Authentication filter for handling DigestAuth
negotiation. Used in WWWAuth
.
Public Class Methods
new()
click to toggle source
Creates new DigestAuth
filter.
Calls superclass method
HTTPClient::AuthBase::new
# File lib/httpclient/auth.rb, line 335 def initialize super('Digest') @auth = {} @nonce_count = 0 end
Public Instance Methods
challenge(uri, param_str)
click to toggle source
Challenge handler: remember URL and challenge token for response.
# File lib/httpclient/auth.rb, line 377 def challenge(uri, param_str) synchronize { @challenge[uri] = parse_challenge_param(param_str) true } end
get(req)
click to toggle source
Response handler: returns credential. It sends cred only when a given uri is;
-
child page of challengeable(got *Authenticate before) uri and,
-
child page of defined credential
# File lib/httpclient/auth.rb, line 361 def get(req) target_uri = req.header.request_uri synchronize { param = Util.hash_find_value(@challenge) { |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) } return nil unless user calc_cred(req, user, passwd, param) } end
set(uri, user, passwd)
click to toggle source
Set authentication credential. uri == nil is ignored.
# File lib/httpclient/auth.rb, line 343 def set(uri, user, passwd) synchronize do if uri uri = Util.uri_dirname(uri) @auth[uri] = [user, passwd] end end end
set?()
click to toggle source
have we marked this as set - ie that it's valid to use in this context?
# File lib/httpclient/auth.rb, line 353 def set? @auth.any? end
Private Instance Methods
calc_cred(req, user, passwd, param)
click to toggle source
this method is implemented by sromano and posted to tools.assembla.com/breakout/wiki/DigestForSoap Thanks! supported algorithms: MD5, MD5-sess
# File lib/httpclient/auth.rb, line 390 def calc_cred(req, user, passwd, param) method = req.header.request_method path = req.header.create_query_uri a_1 = "#{user}:#{param['realm']}:#{passwd}" a_2 = "#{method}:#{path}" qop = param['qop'] nonce = param['nonce'] cnonce = nil if qop || param['algorithm'] =~ /MD5-sess/ cnonce = generate_cnonce() end a_1_md5sum = Digest::MD5.hexdigest(a_1) if param['algorithm'] =~ /MD5-sess/ a_1_md5sum = Digest::MD5.hexdigest("#{a_1_md5sum}:#{nonce}:#{cnonce}") algorithm = "MD5-sess" else algorithm = "MD5" end message_digest = [] message_digest << a_1_md5sum message_digest << nonce if qop @nonce_count += 1 message_digest << ('%08x' % @nonce_count) message_digest << cnonce message_digest << param['qop'] end message_digest << Digest::MD5.hexdigest(a_2) header = [] header << "username=\"#{user}\"" header << "realm=\"#{param['realm']}\"" header << "nonce=\"#{nonce}\"" header << "uri=\"#{path}\"" if cnonce header << "cnonce=\"#{cnonce}\"" end if qop header << "nc=#{'%08x' % @nonce_count}" header << "qop=#{param['qop']}" end header << "response=\"#{Digest::MD5.hexdigest(message_digest.join(":"))}\"" header << "algorithm=#{algorithm}" header << "opaque=\"#{param['opaque']}\"" if param.key?('opaque') header.join(", ") end
generate_cnonce()
click to toggle source
cf. WEBrick::HTTPAuth::DigestAuth#generate_next_nonce(aTime)
# File lib/httpclient/auth.rb, line 437 def generate_cnonce now = "%012d" % Time.now.to_i pk = Digest::MD5.hexdigest([now, self.__id__, Process.pid, rand(65535)].join)[0, 32] [now + ':' + pk].pack('m*').chop end
parse_challenge_param(param_str)
click to toggle source
# File lib/httpclient/auth.rb, line 443 def parse_challenge_param(param_str) param = {} param_str.scan(/\s*([^\,]+(?:\\.[^\,]*)*)/).each do |str| key, value = str[0].scan(/\A([^=]+)=(.*)\z/)[0] if /\A"(.*)"\z/ =~ value value = $1.gsub(/\\(.)/, '\1') end param[key] = value end param end