diff --git a/lib/net/http/digest_auth.rb b/lib/net/http/digest_auth.rb index 98feecb..6d3ce40 100644 --- a/lib/net/http/digest_auth.rb +++ b/lib/net/http/digest_auth.rb @@ -70,6 +70,10 @@ def initialize ignored = :ignored # # See Net::HTTP::DigestAuth for a complete example. # + # Raises an Net::HTTP::DigestAuth::Error if there is a syntax error + # in the +www_authenticate+ header or it does not include the Digest + # authentication method. + # # IIS servers handle the "qop" parameter of digest authentication # differently so you may need to set +iis+ to true for such servers. @@ -79,12 +83,15 @@ def auth_header uri, www_authenticate, method, iis = false user = CGI.unescape uri.user password = CGI.unescape uri.password - www_authenticate =~ /^(\w+) (.*)/ - - challenge = $2 + if www_authenticate =~ /Digest ((?:\w+=(?:"[^"]+?"|[^\s,]+)(?:,\s?)?)+)/ + challenge = $1 + else + raise Error, "Digest auth method not found or syntax error in " + + "auth header: #{www_authenticate}" + end params = {} - challenge.gsub(/(\w+)="(.*?)"/) { params[$1] = $2 } + challenge.gsub(/(\w+)=(?:"([^"]+?)"|([^\s,]+))/) { params[$1] = $2 || $3 } challenge =~ /algorithm="?(.*?)"?([, ]|$)/ diff --git a/test/test_net_http_digest_auth.rb b/test/test_net_http_digest_auth.rb index 7fe0e61..c5a09e2 100644 --- a/test/test_net_http_digest_auth.rb +++ b/test/test_net_http_digest_auth.rb @@ -54,6 +54,22 @@ def test_auth_header_iis assert_equal expected, @da.auth_header(@uri, @header, 'GET', true) end + def test_auth_header_multi + multi_header = "NTLM, #{@header}, Basic realm=\"www.example.com\"" + + assert_equal expected, @da.auth_header(@uri, multi_header, 'GET') + end + + def test_auth_header_unquoted_unspaced + header = [ + 'Digest qop=auth', + 'realm="www.example.com"', + 'nonce=4107baa081a592a6021660200000cd6c5686ff5f579324402b374d83e2c9' + ].join ',' + + assert_equal expected, @da.auth_header(@uri, header, 'GET') + end + def test_auth_header_no_qop @header.sub! ' qop="auth",', '' @@ -112,6 +128,26 @@ def test_auth_header_quoted_algorithm assert_equal expected, @da.auth_header(@uri, @header, 'GET') end + def test_auth_header_error + no_digest_auth_header = "Basic realm=\"www.example.com\"" + erroneous_header = @header.gsub('=', '') + + e = assert_raises Net::HTTP::DigestAuth::Error do + @da.auth_header(@uri, no_digest_auth_header, 'GET') + end + + assert_equal "Digest auth method not found or syntax error in " + + "auth header: #{no_digest_auth_header}", + e.message + + e = assert_raises Net::HTTP::DigestAuth::Error do + @da.auth_header(@uri, erroneous_header, 'GET') + end + + assert_equal "Digest auth method not found or syntax error in " + + "auth header: #{erroneous_header}", e.message + end + def test_make_cnonce da = Net::HTTP::DigestAuth.new