class HTTPClient::DigestAuth
Used in WWWAuth.
Authentication filter for handling DigestAuth negotiation.
def calc_cred(req, user, passwd, param)
Thanks!
http://tools.assembla.com/breakout/wiki/DigestForSoap
this method is implemented by sromano and posted to
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
def challenge(uri, param_str)
def challenge(uri, param_str) @challenge[uri] = parse_challenge_param(param_str) true end
def generate_cnonce
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
def get(req)
* child page of challengeable(got *Authenticate before) uri and,
It sends cred only when a given uri is;
Response handler: returns credential.
def get(req) target_uri = req.header.request_uri 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
def initialize
def initialize @auth = {} @challenge = {} @set = false @nonce_count = 0 @scheme = "Digest" end
def parse_challenge_param(param_str)
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
def reset_challenge
Resets challenge state. Do not send '*Authorization' header until the
def reset_challenge @challenge.clear end
def set(uri, user, passwd)
Set authentication credential.
def set(uri, user, passwd) @set = true if uri uri = Util.uri_dirname(uri) @auth[uri] = [user, passwd] end end
def set?
def set? @set == true end