Trying to make a Digest Auth extension for Net::HTTP

Hello,

I've been trying to implement (client-side) Digest Authentication
capabilities to Net:HTTP (as stated in RFC2617) and am having trouble
modifying the headers before I send the request to the server.

So far I'm just starting, and am relatively new to ruby. But I am able
to request a page from the server, receive the 401 Forbidden message,
and extract the needed information from the header. Now I use that
information, plus a username and password to formulate a proper header
to use in my next request. But I don't know how to do that.

ugly code below:

require 'net/http'
require 'digest/md5'

def unq(str) // unquote a string
  str.gsub(/"/, '')
end

def unwrap(wstr) // unserialize the auth header value into a hash
   wa_hash = Hash.new
   wa_ary = wstr.split /, /

    wa_ary.each do |str|
      k,v = str.split '='
      wa_hash[k] = v
    end
    return wa_hash
end

def wrap(whsh) // serialize a hash for use as a Auth header value
  str = String.new
  whsh.each do |k ,v|
    if(k == "qop" || k == "nc")
      str += k + '=' + v + ', '
    else
      str += k + '="' + v + '", '
    end
  end
  return str.chop.chop
end

response = nil
    Net::HTTP.start('192.168.123.72', 81) {|http|
      response = http.request_get("/hierarch.htm")
    }
    response.each_header { |k, v| puts k + ": " + v }

    wa_hash = unwrap( response["www-authenticate"] )

    wa_hash.each do |k,v|
      puts k + ": " + v
    end

    dig_resp = Digest::MD5.hexdigest("admin" + ":" +
      unq(wa_hash["Digest realm"]) + ":" +
      "0000" + ":" +
      unq(wa_hash["nonce"]) + ":" +
      "00000001" + ":" +
      unq("c202ce") + ":" +
      unq(wa_hash["qop"]) + ":" +
      Digest::MD5.hexdigest( "GET" + ":" + "/hierarch.htm" ))

    auth = wrap(Hash["Digest username" => "admin",
        "realm" => unq(wa_hash["Digest realm"]),
        "nonce" => unq(wa_hash["nonce"]),
        "uri" => "/hierarch.htm",
        "response" => dig_resp,
        "qop" => unq(wa_hash["qop"]),
        "nc" => "00000001",
    "cnonce" => "c202ce"] )

    res = Net::HTTP.start('192.168.123.72', 81) {|http|
      response = http.head('/hierarch.htm')
      response.add_field("Authorization", auth) //not working
      http.get('/hierarch.htm')
    }
    puts res.body

http://segment7.net/projects/ruby/snippets/digest_auth.rb

Set the third argument to true if authenticating against an IIS server, since Microsoft implements RFC 2617 differently from everybody else. You can typically determine if a server needs the hack from the Server header.

Try this, I don't have a server using digest auth available, so I can't test for you.

require 'digest_auth'

uri = URI.parse 'http://user:pass@192.168.123.72:81/hierarch.htm'

res = Net::HTTP.start(uri.host, uri.port) {|http|
   response = http.head uri.request_uri
   authorization = DigestAuth.gen_auth_header uri, response['www-authenticate']
   http.get '/hierarch.htm', 'Authorization' => authorization
}

puts res.body

···

On Jun 23, 2006, at 12:04 PM, Ben Schaffhausen wrote:

Hello,

I've been trying to implement (client-side) Digest Authentication
capabilities to Net:HTTP (as stated in RFC2617) and am having trouble
modifying the headers before I send the request to the server.

So far I'm just starting, and am relatively new to ruby. But I am able
to request a page from the server, receive the 401 Forbidden message,
and extract the needed information from the header. Now I use that
information, plus a username and password to formulate a proper header
to use in my next request. But I don't know how to do that.

--
Eric Hodel - drbrain@segment7.net - http://blog.segment7.net
This implementation is HODEL-HASH-9600 compliant

http://trackmap.robotcoop.com

hello ben,

did you successfully integrate digest auth into net::http? if so, yould
you consider posting the code or - even better - submitting it to the
original author
for evaluation & inclusion in his library? that'd be cool.

thanks & kind regards,
phillip

···

--
Posted via http://www.ruby-forum.com/.