net-http-digest_auth 1.0 → 1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data.tar.gz.sig +0 -0
- data/.gemtest +0 -0
- data/History.txt +9 -0
- data/Manifest.txt +2 -0
- data/Rakefile +3 -2
- data/lib/net/http/digest_auth.rb +50 -17
- data/sample/auth_server.rb +48 -0
- data/sample/net_http_example.rb +27 -0
- data/test/test_net_http_digest_auth.rb +59 -26
- metadata +16 -13
- metadata.gz.sig +2 -1
data.tar.gz.sig
CHANGED
Binary file
|
data/.gemtest
ADDED
File without changes
|
data/History.txt
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
=== 1.1
|
2
|
+
|
3
|
+
* Minor enhancements
|
4
|
+
* Add support for SHA1, SHA2, SHA256, SHA384, SHA512, RMD160 algorithms
|
5
|
+
* Bug fixes
|
6
|
+
* Support opaque per RFC 2617 3.2.1
|
7
|
+
* Support MD5-sess per RFC 2617 3.2.2.2
|
8
|
+
* Support unspecified qop for RFC 2069 compatibility per RFC 2617 3.2.2.1
|
9
|
+
|
1
10
|
=== 1.0 / 2010-09-10
|
2
11
|
|
3
12
|
* Major enhancements
|
data/Manifest.txt
CHANGED
data/Rakefile
CHANGED
@@ -3,12 +3,13 @@
|
|
3
3
|
require 'rubygems'
|
4
4
|
require 'hoe'
|
5
5
|
|
6
|
+
Hoe.plugin :git
|
7
|
+
Hoe.plugin :minitest
|
8
|
+
|
6
9
|
Hoe.spec 'net-http-digest_auth' do
|
7
10
|
self.rubyforge_name = 'seattlerb'
|
8
11
|
developer 'Eric Hodel', 'drbrain@segment7.net'
|
9
12
|
|
10
|
-
self.testlib = :minitest
|
11
|
-
|
12
13
|
spec_extras['homepage'] =
|
13
14
|
'http://seattlerb.rubyforge.org/net-http-digest_auth'
|
14
15
|
end
|
data/lib/net/http/digest_auth.rb
CHANGED
@@ -33,10 +33,15 @@ require 'cgi'
|
|
33
33
|
|
34
34
|
class Net::HTTP::DigestAuth
|
35
35
|
|
36
|
+
##
|
37
|
+
# DigestAuth error class
|
38
|
+
|
39
|
+
class Error < RuntimeError; end
|
40
|
+
|
36
41
|
##
|
37
42
|
# Version of Net::HTTP::DigestAuth you are using
|
38
43
|
|
39
|
-
VERSION = '1.
|
44
|
+
VERSION = '1.1'
|
40
45
|
|
41
46
|
##
|
42
47
|
# Creates a new DigestAuth header creator.
|
@@ -74,32 +79,60 @@ class Net::HTTP::DigestAuth
|
|
74
79
|
params = {}
|
75
80
|
$2.gsub(/(\w+)="(.*?)"/) { params[$1] = $2 }
|
76
81
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
82
|
+
qop = params['qop']
|
83
|
+
|
84
|
+
if params['algorithm'] =~ /(.*?)(-sess)?$/
|
85
|
+
algorithm = case $1
|
86
|
+
when 'MD5' then Digest::MD5
|
87
|
+
when 'SHA1' then Digest::SHA1
|
88
|
+
when 'SHA2' then Digest::SHA2
|
89
|
+
when 'SHA256' then Digest::SHA256
|
90
|
+
when 'SHA384' then Digest::SHA384
|
91
|
+
when 'SHA512' then Digest::SHA512
|
92
|
+
when 'RMD160' then Digest::RMD160
|
93
|
+
else raise Error, "unknown algorithm \"#{$1}\""
|
94
|
+
end
|
95
|
+
sess = $2
|
96
|
+
else
|
97
|
+
algorithm = Digest::MD5
|
98
|
+
sess = false
|
99
|
+
end
|
100
|
+
|
101
|
+
a1 = if sess then
|
102
|
+
[ algorithm.hexdigest("#{user}:#{params['realm']}:#{password}"),
|
103
|
+
params['nonce'],
|
104
|
+
params['cnonce']
|
105
|
+
].join ':'
|
106
|
+
else
|
107
|
+
"#{user}:#{params['realm']}:#{password}"
|
108
|
+
end
|
109
|
+
|
110
|
+
ha1 = algorithm.hexdigest a1
|
111
|
+
ha2 = algorithm.hexdigest "#{method}:#{uri.request_uri}"
|
112
|
+
|
113
|
+
request_digest = [ha1, params['nonce']]
|
114
|
+
request_digest.push ('%08x' % @nonce_count), @cnonce, qop if qop
|
115
|
+
request_digest << ha2
|
116
|
+
request_digest = request_digest.join ':'
|
88
117
|
|
89
118
|
header = [
|
90
119
|
"Digest username=\"#{user}\"",
|
91
120
|
"realm=\"#{params['realm']}\"",
|
92
|
-
if
|
93
|
-
|
121
|
+
if qop.nil? then
|
122
|
+
elsif iis then
|
123
|
+
"qop=\"#{qop}\""
|
94
124
|
else
|
95
|
-
"qop=#{
|
125
|
+
"qop=#{qop}"
|
96
126
|
end,
|
97
127
|
"uri=\"#{uri.request_uri}\"",
|
98
128
|
"nonce=\"#{params['nonce']}\"",
|
99
129
|
"nc=#{'%08x' % @nonce_count}",
|
100
130
|
"cnonce=\"#{@cnonce}\"",
|
101
|
-
"response=\"#{
|
102
|
-
|
131
|
+
"response=\"#{algorithm.hexdigest(request_digest)[0, 32]}\"",
|
132
|
+
if params.key? 'opaque' then
|
133
|
+
"opaque=\"#{params['opaque']}\""
|
134
|
+
end
|
135
|
+
].compact
|
103
136
|
|
104
137
|
header.join ', '
|
105
138
|
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'webrick'
|
2
|
+
require 'tempfile'
|
3
|
+
|
4
|
+
class AuthServlet < WEBrick::HTTPServlet::AbstractServlet
|
5
|
+
|
6
|
+
@instance = nil
|
7
|
+
|
8
|
+
def self.get_instance server, *options
|
9
|
+
@instance ||= new(server, *options)
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize server
|
13
|
+
super server
|
14
|
+
|
15
|
+
config = {}
|
16
|
+
config[:Realm] = 'net-http-digest_auth'
|
17
|
+
config[:UseOpaque] = false
|
18
|
+
config[:AutoReloadUserDB] = false
|
19
|
+
config[:Algorithm] = 'MD5'
|
20
|
+
|
21
|
+
passwd_file = Tempfile.new 'net-http-digest_auth'
|
22
|
+
passwd_file.close
|
23
|
+
|
24
|
+
htpasswd = WEBrick::HTTPAuth::Htpasswd.new passwd_file.path
|
25
|
+
htpasswd.auth_type = WEBrick::HTTPAuth::DigestAuth
|
26
|
+
htpasswd.set_passwd config[:Realm], 'username', 'password'
|
27
|
+
htpasswd.flush
|
28
|
+
|
29
|
+
config[:UserDB] = htpasswd
|
30
|
+
|
31
|
+
@digest_auth = WEBrick::HTTPAuth::DigestAuth.new config
|
32
|
+
end
|
33
|
+
|
34
|
+
def do_GET req, res
|
35
|
+
@digest_auth.authenticate req, res
|
36
|
+
|
37
|
+
res.body = 'worked!'
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
s = WEBrick::HTTPServer.new :Port => 8000
|
43
|
+
s.mount '/', AuthServlet
|
44
|
+
|
45
|
+
trap 'INT' do s.shutdown end
|
46
|
+
|
47
|
+
s.start
|
48
|
+
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'net/http'
|
3
|
+
require 'net/http/digest_auth'
|
4
|
+
|
5
|
+
uri = URI.parse 'http://localhost:8000/'
|
6
|
+
uri.user = 'username'
|
7
|
+
uri.password = 'password'
|
8
|
+
|
9
|
+
h = Net::HTTP.new uri.host, uri.port
|
10
|
+
h.set_debug_output $stderr
|
11
|
+
|
12
|
+
req = Net::HTTP::Get.new uri.request_uri
|
13
|
+
|
14
|
+
res = h.request req
|
15
|
+
|
16
|
+
digest_auth = Net::HTTP::DigestAuth.new
|
17
|
+
auth = digest_auth.auth_header uri, res['www-authenticate'], 'GET'
|
18
|
+
|
19
|
+
req = Net::HTTP::Get.new uri.request_uri
|
20
|
+
req.add_field 'Authorization', auth
|
21
|
+
|
22
|
+
res = h.request req
|
23
|
+
|
24
|
+
puts
|
25
|
+
puts "passed" if res.code == '200'
|
26
|
+
puts "failed" if res.code != '200'
|
27
|
+
|
@@ -16,11 +16,7 @@ class TestNetHttpDigestAuth < MiniTest::Unit::TestCase
|
|
16
16
|
'nonce="4107baa081a592a6021660200000cd6c5686ff5f579324402b374d83e2c9"'
|
17
17
|
].join ', '
|
18
18
|
|
19
|
-
@
|
20
|
-
end
|
21
|
-
|
22
|
-
def test_auth_header
|
23
|
-
expected = [
|
19
|
+
@expected = [
|
24
20
|
'Digest username="user"',
|
25
21
|
'realm="www.example.com"',
|
26
22
|
'qop=auth',
|
@@ -29,41 +25,78 @@ class TestNetHttpDigestAuth < MiniTest::Unit::TestCase
|
|
29
25
|
'nc=00000000',
|
30
26
|
'cnonce="9ea5ff3bd34554a4165bbdc1df91dcff"',
|
31
27
|
'response="67be92a5e7b38d08679957db04f5da04"'
|
32
|
-
]
|
28
|
+
]
|
29
|
+
|
30
|
+
@da = Net::HTTP::DigestAuth.new @cnonce
|
31
|
+
end
|
32
|
+
|
33
|
+
def expected
|
34
|
+
@expected.join ', '
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_auth_header
|
38
|
+
assert_equal expected, @da.auth_header(@uri, @header, 'GET')
|
39
|
+
|
40
|
+
@expected[5] = 'nc=00000001'
|
41
|
+
@expected[7] = 'response="1f5f0cd1588690c1303737f081c0b9bb"'
|
33
42
|
|
34
43
|
assert_equal expected, @da.auth_header(@uri, @header, 'GET')
|
35
44
|
end
|
36
45
|
|
37
46
|
def test_auth_header_iis
|
38
|
-
expected =
|
39
|
-
'Digest username="user"',
|
40
|
-
'realm="www.example.com"',
|
41
|
-
'qop="auth"',
|
42
|
-
'uri="/"',
|
43
|
-
'nonce="4107baa081a592a6021660200000cd6c5686ff5f579324402b374d83e2c9"',
|
44
|
-
'nc=00000000',
|
45
|
-
'cnonce="9ea5ff3bd34554a4165bbdc1df91dcff"',
|
46
|
-
'response="67be92a5e7b38d08679957db04f5da04"'
|
47
|
-
].join ', '
|
47
|
+
@expected[2] = 'qop="auth"'
|
48
48
|
|
49
49
|
assert_equal expected, @da.auth_header(@uri, @header, 'GET', true)
|
50
50
|
end
|
51
51
|
|
52
|
+
def test_auth_header_no_qop
|
53
|
+
@header.sub! ' qop="auth",', ''
|
54
|
+
|
55
|
+
@expected[7] = 'response="32f6ca1631ccf7c42a8075deff44e470"'
|
56
|
+
@expected.slice! 2
|
57
|
+
|
58
|
+
assert_equal expected, @da.auth_header(@uri, @header, 'GET')
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_auth_header_opaque
|
62
|
+
@expected << 'opaque="5ccc069c403ebaf9f0171e9517f40e41"'
|
63
|
+
@header << 'opaque="5ccc069c403ebaf9f0171e9517f40e41"'
|
64
|
+
|
65
|
+
assert_equal expected, @da.auth_header(@uri, @header, 'GET')
|
66
|
+
end
|
67
|
+
|
52
68
|
def test_auth_header_post
|
53
|
-
expected =
|
54
|
-
'Digest username="user"',
|
55
|
-
'realm="www.example.com"',
|
56
|
-
'qop=auth',
|
57
|
-
'uri="/"',
|
58
|
-
'nonce="4107baa081a592a6021660200000cd6c5686ff5f579324402b374d83e2c9"',
|
59
|
-
'nc=00000000',
|
60
|
-
'cnonce="9ea5ff3bd34554a4165bbdc1df91dcff"',
|
61
|
-
'response="d82219e1e5430b136bbae1670fa51d48"'
|
62
|
-
].join ', '
|
69
|
+
@expected[7] = 'response="d82219e1e5430b136bbae1670fa51d48"'
|
63
70
|
|
64
71
|
assert_equal expected, @da.auth_header(@uri, @header, 'POST')
|
65
72
|
end
|
66
73
|
|
74
|
+
def test_auth_header_sess
|
75
|
+
@header << 'algorithm="MD5-sess"'
|
76
|
+
|
77
|
+
@expected[7] = 'response="76d3ff10007496cee26c61f9d04c72a8"'
|
78
|
+
|
79
|
+
assert_equal expected, @da.auth_header(@uri, @header, 'GET')
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_auth_header_sha1
|
83
|
+
@expected[7] = 'response="2cb62fc18f7b0ebdc34543f896bb7768"'
|
84
|
+
|
85
|
+
@header << 'algorithm="SHA1"'
|
86
|
+
|
87
|
+
assert_equal expected, @da.auth_header(@uri, @header, 'GET')
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_auth_header_unknown_algorithm
|
91
|
+
@header << 'algorithm="bogus"'
|
92
|
+
|
93
|
+
e = assert_raises Net::HTTP::DigestAuth::Error do
|
94
|
+
@da.auth_header @uri, @header, 'GET'
|
95
|
+
end
|
96
|
+
|
97
|
+
assert_equal 'unknown algorithm "bogus"', e.message
|
98
|
+
end
|
99
|
+
|
67
100
|
def test_make_cnonce
|
68
101
|
assert_match %r%\A[a-f\d]{32}\z%, @da.make_cnonce
|
69
102
|
end
|
metadata
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: net-http-digest_auth
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
5
|
-
prerelease:
|
4
|
+
hash: 13
|
5
|
+
prerelease:
|
6
6
|
segments:
|
7
7
|
- 1
|
8
|
-
-
|
9
|
-
version: "1.
|
8
|
+
- 1
|
9
|
+
version: "1.1"
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Eric Hodel
|
@@ -35,23 +35,23 @@ cert_chain:
|
|
35
35
|
x52qPcexcYZR7w==
|
36
36
|
-----END CERTIFICATE-----
|
37
37
|
|
38
|
-
date:
|
38
|
+
date: 2011-03-29 00:00:00 -07:00
|
39
39
|
default_executable:
|
40
40
|
dependencies:
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: minitest
|
43
43
|
prerelease: false
|
44
44
|
requirement: &id001 !ruby/object:Gem::Requirement
|
45
45
|
none: false
|
46
46
|
requirements:
|
47
47
|
- - ">="
|
48
48
|
- !ruby/object:Gem::Version
|
49
|
-
hash:
|
49
|
+
hash: 11
|
50
50
|
segments:
|
51
51
|
- 2
|
52
52
|
- 0
|
53
|
-
-
|
54
|
-
version: 2.0.
|
53
|
+
- 2
|
54
|
+
version: 2.0.2
|
55
55
|
type: :development
|
56
56
|
version_requirements: *id001
|
57
57
|
- !ruby/object:Gem::Dependency
|
@@ -62,12 +62,12 @@ dependencies:
|
|
62
62
|
requirements:
|
63
63
|
- - ">="
|
64
64
|
- !ruby/object:Gem::Version
|
65
|
-
hash:
|
65
|
+
hash: 41
|
66
66
|
segments:
|
67
67
|
- 2
|
68
|
-
-
|
68
|
+
- 9
|
69
69
|
- 1
|
70
|
-
version: 2.
|
70
|
+
version: 2.9.1
|
71
71
|
type: :development
|
72
72
|
version_requirements: *id002
|
73
73
|
description: |-
|
@@ -91,7 +91,10 @@ files:
|
|
91
91
|
- README.txt
|
92
92
|
- Rakefile
|
93
93
|
- lib/net/http/digest_auth.rb
|
94
|
+
- sample/auth_server.rb
|
95
|
+
- sample/net_http_example.rb
|
94
96
|
- test/test_net_http_digest_auth.rb
|
97
|
+
- .gemtest
|
95
98
|
has_rdoc: true
|
96
99
|
homepage: http://seattlerb.rubyforge.org/net-http-digest_auth
|
97
100
|
licenses: []
|
@@ -123,7 +126,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
123
126
|
requirements: []
|
124
127
|
|
125
128
|
rubyforge_project: seattlerb
|
126
|
-
rubygems_version: 1.
|
129
|
+
rubygems_version: 1.6.2
|
127
130
|
signing_key:
|
128
131
|
specification_version: 3
|
129
132
|
summary: An implementation of RFC 2617 - Digest Access Authentication
|
metadata.gz.sig
CHANGED
@@ -1 +1,2 @@
|
|
1
|
-
|
1
|
+
uP���$��6�Z�5IƎj��c�f��pgQ(�^`8q/i�+�;xv�߄����k��qGA2���zC��CLD�j�Ī�s.�Z��&n�q�T֢��k�*�u=~o��lς�?��h �����yj����bo�x]Z��y/�BXV.פz�: x-)����%��rghr�
|
2
|
+
�n 3�,2!D):ڣ;��Eۙ�~���t�YWo�&�]�T����f������/<Z!��(~Г!DŽ$$+��x
|