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

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

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

to use in my next request. But I don’t know how to do that.
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:[email protected]: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


Eric H. - [email protected] - http://blog.segment7.net
This implementation is HODEL-HASH-9600 compliant

http://trackmap.robotcoop.com