httpclient-jgraichen 2.3.4.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +7 -0
  2. data/README.txt +759 -0
  3. data/bin/httpclient +65 -0
  4. data/lib/hexdump.rb +50 -0
  5. data/lib/http-access2.rb +55 -0
  6. data/lib/http-access2/cookie.rb +1 -0
  7. data/lib/http-access2/http.rb +1 -0
  8. data/lib/httpclient.rb +1156 -0
  9. data/lib/httpclient/auth.rb +899 -0
  10. data/lib/httpclient/cacert.p7s +1912 -0
  11. data/lib/httpclient/connection.rb +88 -0
  12. data/lib/httpclient/cookie.rb +438 -0
  13. data/lib/httpclient/http.rb +1046 -0
  14. data/lib/httpclient/include_client.rb +83 -0
  15. data/lib/httpclient/session.rb +1028 -0
  16. data/lib/httpclient/ssl_config.rb +405 -0
  17. data/lib/httpclient/timeout.rb +140 -0
  18. data/lib/httpclient/util.rb +178 -0
  19. data/lib/httpclient/version.rb +3 -0
  20. data/lib/oauthclient.rb +110 -0
  21. data/sample/async.rb +8 -0
  22. data/sample/auth.rb +11 -0
  23. data/sample/cookie.rb +18 -0
  24. data/sample/dav.rb +103 -0
  25. data/sample/howto.rb +49 -0
  26. data/sample/oauth_buzz.rb +57 -0
  27. data/sample/oauth_friendfeed.rb +59 -0
  28. data/sample/oauth_twitter.rb +61 -0
  29. data/sample/ssl/0cert.pem +22 -0
  30. data/sample/ssl/0key.pem +30 -0
  31. data/sample/ssl/1000cert.pem +19 -0
  32. data/sample/ssl/1000key.pem +18 -0
  33. data/sample/ssl/htdocs/index.html +10 -0
  34. data/sample/ssl/ssl_client.rb +22 -0
  35. data/sample/ssl/webrick_httpsd.rb +29 -0
  36. data/sample/stream.rb +21 -0
  37. data/sample/thread.rb +27 -0
  38. data/sample/wcat.rb +21 -0
  39. data/test/ca-chain.cert +44 -0
  40. data/test/ca.cert +23 -0
  41. data/test/client.cert +19 -0
  42. data/test/client.key +15 -0
  43. data/test/helper.rb +129 -0
  44. data/test/htdigest +1 -0
  45. data/test/htpasswd +2 -0
  46. data/test/runner.rb +2 -0
  47. data/test/server.cert +19 -0
  48. data/test/server.key +15 -0
  49. data/test/sslsvr.rb +65 -0
  50. data/test/subca.cert +21 -0
  51. data/test/test_auth.rb +348 -0
  52. data/test/test_cookie.rb +412 -0
  53. data/test/test_hexdump.rb +14 -0
  54. data/test/test_http-access2.rb +507 -0
  55. data/test/test_httpclient.rb +1783 -0
  56. data/test/test_include_client.rb +52 -0
  57. data/test/test_ssl.rb +235 -0
  58. metadata +100 -0
@@ -0,0 +1,23 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIID0DCCArigAwIBAgIBADANBgkqhkiG9w0BAQUFADA8MQswCQYDVQQGDAJKUDES
3
+ MBAGA1UECgwJSklOLkdSLkpQMQwwCgYDVQQLDANSUlIxCzAJBgNVBAMMAkNBMB4X
4
+ DTA0MDEzMDAwNDIzMloXDTM2MDEyMjAwNDIzMlowPDELMAkGA1UEBgwCSlAxEjAQ
5
+ BgNVBAoMCUpJTi5HUi5KUDEMMAoGA1UECwwDUlJSMQswCQYDVQQDDAJDQTCCASIw
6
+ DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANbv0x42BTKFEQOE+KJ2XmiSdZpR
7
+ wjzQLAkPLRnLB98tlzs4xo+y4RyY/rd5TT9UzBJTIhP8CJi5GbS1oXEerQXB3P0d
8
+ L5oSSMwGGyuIzgZe5+vZ1kgzQxMEKMMKlzA73rbMd4Jx3u5+jdbP0EDrPYfXSvLY
9
+ bS04n2aX7zrN3x5KdDrNBfwBio2/qeaaj4+9OxnwRvYP3WOvqdW0h329eMfHw0pi
10
+ JI0drIVdsEqClUV4pebT/F+CPUPkEh/weySgo9wANockkYu5ujw2GbLFcO5LXxxm
11
+ dEfcVr3r6t6zOA4bJwL0W/e6LBcrwiG/qPDFErhwtgTLYf6Er67SzLyA66UCAwEA
12
+ AaOB3DCB2TAPBgNVHRMBAf8EBTADAQH/MDEGCWCGSAGG+EIBDQQkFiJSdWJ5L09w
13
+ ZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBRJ7Xd380KzBV7f
14
+ USKIQ+O/vKbhDzAOBgNVHQ8BAf8EBAMCAQYwZAYDVR0jBF0wW4AUSe13d/NCswVe
15
+ 31EiiEPjv7ym4Q+hQKQ+MDwxCzAJBgNVBAYMAkpQMRIwEAYDVQQKDAlKSU4uR1Iu
16
+ SlAxDDAKBgNVBAsMA1JSUjELMAkGA1UEAwwCQ0GCAQAwDQYJKoZIhvcNAQEFBQAD
17
+ ggEBAIu/mfiez5XN5tn2jScgShPgHEFJBR0BTJBZF6xCk0jyqNx/g9HMj2ELCuK+
18
+ r/Y7KFW5c5M3AQ+xWW0ZSc4kvzyTcV7yTVIwj2jZ9ddYMN3nupZFgBK1GB4Y05GY
19
+ MJJFRkSu6d/Ph5ypzBVw2YMT/nsOo5VwMUGLgS7YVjU+u/HNWz80J3oO17mNZllj
20
+ PvORJcnjwlroDnS58KoJ7GDgejv3ESWADvX1OHLE4cRkiQGeLoEU4pxdCxXRqX0U
21
+ PbwIkZN9mXVcrmPHq8MWi4eC/V7hnbZETMHuWhUoiNdOEfsAXr3iP4KjyyRdwc7a
22
+ d/xgcK06UVQRL/HbEYGiQL056mc=
23
+ -----END CERTIFICATE-----
@@ -0,0 +1,19 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDKDCCAhCgAwIBAgIBAjANBgkqhkiG9w0BAQUFADA8MQswCQYDVQQGDAJKUDES
3
+ MBAGA1UECgwJSklOLkdSLkpQMQwwCgYDVQQLDANSUlIxCzAJBgNVBAMMAkNBMB4X
4
+ DTA0MDEzMTAzMTQ1OFoXDTM1MDEyMzAzMTQ1OFowZTELMAkGA1UEBgwCSlAxEjAQ
5
+ BgNVBAoMCUpJTi5HUi5KUDEMMAoGA1UECwwDUlJSMRAwDgYDVQQDDAdleGFtcGxl
6
+ MSIwIAYJKoZIhvcNAQkBDBNleGFtcGxlQGV4YW1wbGUub3JnMIGfMA0GCSqGSIb3
7
+ DQEBAQUAA4GNADCBiQKBgQDRWssrK8Gyr+500hpLjCGR3+AHL8/hEJM5zKi/MgLW
8
+ jTkvsgOwbYwXOiNtAbR9y4/ucDq7EY+cMUMHES4uFaPTcOaAV0aZRmk8AgslN1tQ
9
+ gNS6ew7/Luq3DcVeWkX8PYgR9VG0mD1MPfJ6+IFA5d3vKpdBkBgN4l46jjO0/2Xf
10
+ ewIDAQABo4GPMIGMMAwGA1UdEwEB/wQCMAAwMQYJYIZIAYb4QgENBCQWIlJ1Ynkv
11
+ T3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFOFvay0H7lr2
12
+ xUx6waYEV2bVDYQhMAsGA1UdDwQEAwIF4DAdBgNVHSUEFjAUBggrBgEFBQcDAgYI
13
+ KwYBBQUHAwQwDQYJKoZIhvcNAQEFBQADggEBABd2dYWqbDIWf5sWFvslezxJv8gI
14
+ w64KCJBuyJAiDuf+oazr3016kMzAlt97KecLZDusGNagPrq02UX7YMoQFsWJBans
15
+ cDtHrkM0al5r6/WGexNMgtYbNTYzt/IwodISGBgZ6dsOuhznwms+IBsTNDAvWeLP
16
+ lt2tOqD8kEmjwMgn0GDRuKjs4EoboA3kMULb1p9akDV9ZESU3eOtpS5/G5J5msLI
17
+ 9WXbYBjcjvkLuJH9VsJhb+R58Vl0ViemvAHhPilSl1SPWVunGhv6FcIkdBEi1k9F
18
+ e8BNMmsEjFiANiIRvpdLRbiGBt0KrKTndVfsmoKCvY48oCOvnzxtahFxfs8=
19
+ -----END CERTIFICATE-----
@@ -0,0 +1,15 @@
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ MIICWwIBAAKBgQDRWssrK8Gyr+500hpLjCGR3+AHL8/hEJM5zKi/MgLWjTkvsgOw
3
+ bYwXOiNtAbR9y4/ucDq7EY+cMUMHES4uFaPTcOaAV0aZRmk8AgslN1tQgNS6ew7/
4
+ Luq3DcVeWkX8PYgR9VG0mD1MPfJ6+IFA5d3vKpdBkBgN4l46jjO0/2XfewIDAQAB
5
+ AoGAZcz8llWErtsV3QB9gNb3S/PNADGjqBFjReva8n3jG2k4sZSibpwWTwUaTNtT
6
+ ZQgjSRKRvH1hk9XwffNAvXAQZNNkuj/16gO2oO45nyLj4dO365ujLptWnVIWDHOE
7
+ uN0GeiZO+VzcCisT0WCq4tvtLeH8svrxzA8cbXIEyOK7NiECQQDwo2zPFyKAZ/Cu
8
+ lDJ6zKT+RjfWwW7DgWzirAlTrt4ViMaW+IaDH29TmQpb4V4NuR3Xi+2Xl4oicu6S
9
+ 36TW9+/FAkEA3rgfOQJuLlWSnw1RTGwvnC816a/W7iYYY7B+0U4cDbfWl7IoXT4y
10
+ M8nV/HESooviZLqBwzAYSoj3fFKYBKpGPwJAUO8GN5iWWA2dW3ooiDiv/X1sZmRk
11
+ dojfMFWgRW747tEzya8Ivq0h6kH8w+5GjeMG8Gn1nRiwsulo6Ckj7dEx6QJACyui
12
+ 7UIQ8qP6GZ4aYMHgVW4Mvy7Bkeo5OO7GPYs0Xv/EdJFL8vlGnVBXOjUVoS9w6Gpu
13
+ TbLg1QQvnX2rADjmEwJANxZO2GUkaWGsEif8aGW0x5g/IdaMGG27pTWk5zqix7P3
14
+ 1UDrdo/JOXhptovhRi06EppIxAxYmbh9vd9VN8Itlw==
15
+ -----END RSA PRIVATE KEY-----
@@ -0,0 +1,129 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'test/unit'
3
+ begin
4
+ require 'simplecov'
5
+ require 'simplecov-rcov'
6
+ SimpleCov.formatter = SimpleCov::Formatter::RcovFormatter
7
+ SimpleCov.start
8
+ rescue LoadError
9
+ end
10
+
11
+ require 'httpclient'
12
+ require 'webrick'
13
+ require 'webrick/httpproxy.rb'
14
+ require 'logger'
15
+ require 'stringio'
16
+ require 'cgi'
17
+ require 'webrick/httputils'
18
+
19
+
20
+ module Helper
21
+ Port = 17171
22
+ ProxyPort = 17172
23
+
24
+ def serverport
25
+ @serverport
26
+ end
27
+
28
+ def proxyport
29
+ @proxyport
30
+ end
31
+
32
+ def serverurl
33
+ "http://localhost:#{serverport}/"
34
+ end
35
+
36
+ def proxyurl
37
+ "http://localhost:#{proxyport}/"
38
+ end
39
+
40
+ def setup
41
+ @logger = Logger.new(STDERR)
42
+ @logger.level = Logger::Severity::FATAL
43
+ @proxyio = StringIO.new
44
+ @proxylogger = Logger.new(@proxyio)
45
+ @proxylogger.level = Logger::Severity::DEBUG
46
+ @server = @proxyserver = @client = nil
47
+ @server_thread = @proxyserver_thread = nil
48
+ @serverport = Port
49
+ @proxyport = ProxyPort
50
+ end
51
+
52
+ def teardown
53
+ teardown_client if @client
54
+ teardown_proxyserver if @proxyserver
55
+ teardown_server if @server
56
+ end
57
+
58
+ def setup_client
59
+ @client = HTTPClient.new
60
+ end
61
+
62
+ #def setup_server
63
+ # override it
64
+ # @server = WEBrick::HTTPServer.new(...)
65
+ # @server_thread = start_server_thread(@server)
66
+ #end
67
+
68
+ def setup_proxyserver
69
+ @proxyserver = WEBrick::HTTPProxyServer.new(
70
+ :BindAddress => "localhost",
71
+ :Logger => @proxylogger,
72
+ :Port => 0,
73
+ :AccessLog => []
74
+ )
75
+ @proxyport = @proxyserver.config[:Port]
76
+ @proxyserver_thread = start_server_thread(@proxyserver)
77
+ end
78
+
79
+ def teardown_client
80
+ @client.reset_all
81
+ end
82
+
83
+ def teardown_server
84
+ @server.shutdown
85
+ #@server_thread.kill
86
+ end
87
+
88
+ def teardown_proxyserver
89
+ @proxyserver.shutdown
90
+ #@proxyserver_thread.kill
91
+ end
92
+
93
+ def start_server_thread(server)
94
+ t = Thread.new {
95
+ Thread.current.abort_on_exception = true
96
+ server.start
97
+ }
98
+ while server.status != :Running
99
+ Thread.pass
100
+ unless t.alive?
101
+ t.join
102
+ raise
103
+ end
104
+ end
105
+ t
106
+ end
107
+
108
+ def params(str)
109
+ HTTP::Message.parse(str).inject({}) { |r, (k, v)| r[k] = v.first; r }
110
+ end
111
+
112
+ def silent
113
+ begin
114
+ back, $VERBOSE = $VERBOSE, nil
115
+ yield
116
+ ensure
117
+ $VERBOSE = back
118
+ end
119
+ end
120
+
121
+ def escape_env
122
+ env = {}
123
+ env.update(ENV)
124
+ yield
125
+ ensure
126
+ ENV.clear
127
+ ENV.update(env)
128
+ end
129
+ end
@@ -0,0 +1 @@
1
+ admin:auth:4302fe65caa32f27721949149ccd3083
@@ -0,0 +1,2 @@
1
+ admin:Qg266hq/YYKe2
2
+ guest:gbPc4vPCH.h12
@@ -0,0 +1,2 @@
1
+ require 'test/unit'
2
+ exit Test::Unit::AutoRunner.run(true, File.dirname($0))
@@ -0,0 +1,19 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIC/zCCAeegAwIBAgIBATANBgkqhkiG9w0BAQUFADA/MQswCQYDVQQGDAJKUDES
3
+ MBAGA1UECgwJSklOLkdSLkpQMQwwCgYDVQQLDANSUlIxDjAMBgNVBAMMBVN1YkNB
4
+ MB4XDTA0MDEzMTAzMTMxNloXDTMzMDEyMzAzMTMxNlowQzELMAkGA1UEBgwCSlAx
5
+ EjAQBgNVBAoMCUpJTi5HUi5KUDEMMAoGA1UECwwDUlJSMRIwEAYDVQQDDAlsb2Nh
6
+ bGhvc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANFJTxWqup3nV9dsJAku
7
+ p+WaXnPNIzcpAA3qMGZDJTJsfa8Du7ZxTP0XJK5mETttBrn711cJxAuP3KjqnW9S
8
+ vtZ9lY2sXJ6Zj62sN5LwG3VVe25dI28yR1EsbHjJ5Zjf9tmggMC6am52dxuHbt5/
9
+ vHo4ngJuKE/U+eeGRivMn6gFAgMBAAGjgYUwgYIwDAYDVR0TAQH/BAIwADAxBglg
10
+ hkgBhvhCAQ0EJBYiUnVieS9PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAd
11
+ BgNVHQ4EFgQUpZIyygD9JxFYHHOTEuWOLbCKfckwCwYDVR0PBAQDAgWgMBMGA1Ud
12
+ JQQMMAoGCCsGAQUFBwMBMA0GCSqGSIb3DQEBBQUAA4IBAQBwAIj5SaBHaA5X31IP
13
+ CFCJiep96awfp7RANO0cuUj+ZpGoFn9d6FXY0g+Eg5wAkCNIzZU5NHN9xsdOpnUo
14
+ zIBbyTfQEPrge1CMWMvL6uGaoEXytq84VTitF/xBTky4KtTn6+es4/e7jrrzeUXQ
15
+ RC46gkHObmDT91RkOEGjHLyld2328jo3DIN/VTHIryDeVHDWjY5dENwpwdkhhm60
16
+ DR9IrNBbXWEe9emtguNXeN0iu1ux0lG1Hc6pWGQxMlRKNvGh0yZB9u5EVe38tOV0
17
+ jQaoNyL7qzcQoXD3Dmbi1p0iRmg/+HngISsz8K7k7MBNVsSclztwgCzTZOBiVtkM
18
+ rRlQ
19
+ -----END CERTIFICATE-----
@@ -0,0 +1,15 @@
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ MIICXQIBAAKBgQDRSU8Vqrqd51fXbCQJLqflml5zzSM3KQAN6jBmQyUybH2vA7u2
3
+ cUz9FySuZhE7bQa5+9dXCcQLj9yo6p1vUr7WfZWNrFyemY+trDeS8Bt1VXtuXSNv
4
+ MkdRLGx4yeWY3/bZoIDAumpudncbh27ef7x6OJ4CbihP1PnnhkYrzJ+oBQIDAQAB
5
+ AoGBAIf4CstW2ltQO7+XYGoex7Hh8s9lTSW/G2vu5Hbr1LTHy3fzAvdq8MvVR12O
6
+ rk9fa+lU9vhzPc0NMB0GIDZ9GcHuhW5hD1Wg9OSCbTOkZDoH3CAFqonjh4Qfwv5W
7
+ IPAFn9KHukdqGXkwEMdErsUaPTy9A1V/aROVEaAY+HJgq/eZAkEA/BP1QMV04WEZ
8
+ Oynzz7/lLizJGGxp2AOvEVtqMoycA/Qk+zdKP8ufE0wbmCE3Qd6GoynavsHb6aGK
9
+ gQobb8zDZwJBANSK6MrXlrZTtEaeZuyOB4mAmRzGzOUVkUyULUjEx2GDT93ujAma
10
+ qm/2d3E+wXAkNSeRpjUmlQXy/2oSqnGvYbMCQQDRM+cYyEcGPUVpWpnj0shrF/QU
11
+ 9vSot/X1G775EMTyaw6+BtbyNxVgOIu2J+rqGbn3c+b85XqTXOPL0A2RLYkFAkAm
12
+ syhSDtE9X55aoWsCNZY/vi+i4rvaFoQ/WleogVQAeGVpdo7/DK9t9YWoFBIqth0L
13
+ mGSYFu9ZhvZkvQNV8eYrAkBJ+rOIaLDsmbrgkeDruH+B/9yrm4McDtQ/rgnOGYnH
14
+ LjLpLLOrgUxqpzLWe++EwSLwK2//dHO+SPsQJ4xsyQJy
15
+ -----END RSA PRIVATE KEY-----
@@ -0,0 +1,65 @@
1
+ require 'webrick/https'
2
+ require 'logger'
3
+ require 'rbconfig'
4
+
5
+ PORT = 17171
6
+ DIR = File.dirname(File.expand_path(__FILE__))
7
+
8
+ def cert(filename)
9
+ OpenSSL::X509::Certificate.new(File.open(File.join(DIR, filename)) { |f|
10
+ f.read
11
+ })
12
+ end
13
+
14
+ def key(filename)
15
+ OpenSSL::PKey::RSA.new(File.open(File.join(DIR, filename)) { |f|
16
+ f.read
17
+ })
18
+ end
19
+
20
+ def do_hello(req, res)
21
+ res['content-type'] = 'text/html'
22
+ res.body = "hello"
23
+ end
24
+
25
+ logger = Logger.new(STDERR)
26
+ logger.level = Logger::Severity::FATAL # avoid logging SSLError (ERROR level)
27
+
28
+ server = WEBrick::HTTPServer.new(
29
+ :BindAddress => "localhost",
30
+ :Logger => logger,
31
+ :Port => PORT,
32
+ :AccessLog => [],
33
+ :DocumentRoot => DIR,
34
+ :SSLEnable => true,
35
+ :SSLCACertificateFile => File.join(DIR, 'ca.cert'),
36
+ :SSLCertificate => cert('server.cert'),
37
+ :SSLPrivateKey => key('server.key'),
38
+ :SSLVerifyClient => nil, #OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT|OpenSSL::SSL::VERIFY_PEER,
39
+ :SSLClientCA => cert('ca.cert'),
40
+ :SSLCertName => nil
41
+ )
42
+ trap(:INT) do
43
+ server.shutdown
44
+ end
45
+ [:hello].each do |sym|
46
+ server.mount(
47
+ "/#{sym}",
48
+ WEBrick::HTTPServlet::ProcHandler.new(method("do_#{sym}").to_proc)
49
+ )
50
+ end
51
+
52
+ t = Thread.new {
53
+ Thread.current.abort_on_exception = true
54
+ server.start
55
+ }
56
+ while server.status != :Running
57
+ sleep 0.1
58
+ unless t.alive?
59
+ t.join
60
+ raise
61
+ end
62
+ end
63
+ STDOUT.sync = true
64
+ puts $$
65
+ t.join
@@ -0,0 +1,21 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDaDCCAlCgAwIBAgIBATANBgkqhkiG9w0BAQUFADA8MQswCQYDVQQGDAJKUDES
3
+ MBAGA1UECgwJSklOLkdSLkpQMQwwCgYDVQQLDANSUlIxCzAJBgNVBAMMAkNBMB4X
4
+ DTA0MDEzMDAwNDMyN1oXDTM1MDEyMjAwNDMyN1owPzELMAkGA1UEBgwCSlAxEjAQ
5
+ BgNVBAoMCUpJTi5HUi5KUDEMMAoGA1UECwwDUlJSMQ4wDAYDVQQDDAVTdWJDQTCC
6
+ ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJ0Ou7AyRcRXnB/kVHv/6kwe
7
+ ANzgg/DyJfsAUqW90m7Lu1nqyug8gK0RBd77yU0w5HOAMHTVSdpjZK0g2sgx4Mb1
8
+ d/213eL9TTl5MRVEChTvQr8q5DVG/8fxPPE7fMI8eOAzd98/NOAChk+80r4Sx7fC
9
+ kGVEE1bKwY1MrUsUNjOY2d6t3M4HHV3HX1V8ShuKfsHxgCmLzdI8U+5CnQedFgkm
10
+ 3e+8tr8IX5RR1wA1Ifw9VadF7OdI/bGMzog/Q8XCLf+WPFjnK7Gcx6JFtzF6Gi4x
11
+ 4dp1Xl45JYiVvi9zQ132wu8A1pDHhiNgQviyzbP+UjcB/tsOpzBQF8abYzgEkWEC
12
+ AwEAAaNyMHAwDwYDVR0TAQH/BAUwAwEB/zAxBglghkgBhvhCAQ0EJBYiUnVieS9P
13
+ cGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUlCjXWLsReYzH
14
+ LzsxwVnCXmKoB/owCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQCJ/OyN
15
+ rT8Cq2Y+G2yA/L1EMRvvxwFBqxavqaqHl/6rwsIBFlB3zbqGA/0oec6MAVnYynq4
16
+ c4AcHTjx3bQ/S4r2sNTZq0DH4SYbQzIobx/YW8PjQUJt8KQdKMcwwi7arHP7A/Ha
17
+ LKu8eIC2nsUBnP4NhkYSGhbmpJK+PFD0FVtD0ZIRlY/wsnaZNjWWcnWF1/FNuQ4H
18
+ ySjIblqVQkPuzebv3Ror6ZnVDukn96Mg7kP4u6zgxOeqlJGRe1M949SS9Vudjl8X
19
+ SF4aZUUB9pQGhsqQJVqaz2OlhGOp9D0q54xko/rekjAIcuDjl1mdX4F2WRrzpUmZ
20
+ uY/bPeOBYiVsOYVe
21
+ -----END CERTIFICATE-----
@@ -0,0 +1,348 @@
1
+ require File.expand_path('helper', File.dirname(__FILE__))
2
+ require 'digest/md5'
3
+ require 'rack'
4
+ require 'rack/lint'
5
+ require 'rack/showexceptions'
6
+ require 'rack-ntlm'
7
+
8
+ class TestAuth < Test::Unit::TestCase
9
+ include Helper
10
+
11
+ def setup
12
+ super
13
+ setup_server
14
+ end
15
+
16
+ def teardown
17
+ super
18
+ end
19
+
20
+ def setup_server
21
+ @server = WEBrick::HTTPServer.new(
22
+ :BindAddress => "localhost",
23
+ :Logger => @logger,
24
+ :Port => 0,
25
+ :AccessLog => [],
26
+ :DocumentRoot => File.dirname(File.expand_path(__FILE__))
27
+ )
28
+ @serverport = @server.config[:Port]
29
+ @server.mount(
30
+ '/basic_auth',
31
+ WEBrick::HTTPServlet::ProcHandler.new(method(:do_basic_auth).to_proc)
32
+ )
33
+ @server.mount(
34
+ '/digest_auth',
35
+ WEBrick::HTTPServlet::ProcHandler.new(method(:do_digest_auth).to_proc)
36
+ )
37
+ @server.mount(
38
+ '/digest_sess_auth',
39
+ WEBrick::HTTPServlet::ProcHandler.new(method(:do_digest_sess_auth).to_proc)
40
+ )
41
+ # NTLM endpoint
42
+ ntlm_handler = Rack::Handler::WEBrick.new(@server,
43
+ Rack::Builder.app do
44
+ use Rack::ShowExceptions
45
+ use Rack::ContentLength
46
+ use Rack::Ntlm, {:uri_pattern => /.*/, :auth => {:username => "admin", :password => "admin"}}
47
+ run lambda { |env| [200, { 'Content-Type' => 'text/html' }, ['ntlm_auth OK']] }
48
+ end
49
+ )
50
+ @server.mount(
51
+ '/ntlm_auth',
52
+ WEBrick::HTTPServlet::ProcHandler.new(Proc.new do |req, res|
53
+ ntlm_handler.service(req, res)
54
+ end)
55
+ )
56
+ # Htpasswd
57
+ htpasswd = File.join(File.dirname(__FILE__), 'htpasswd')
58
+ htpasswd_userdb = WEBrick::HTTPAuth::Htpasswd.new(htpasswd)
59
+ htdigest = File.join(File.dirname(__FILE__), 'htdigest')
60
+ htdigest_userdb = WEBrick::HTTPAuth::Htdigest.new(htdigest)
61
+ @basic_auth = WEBrick::HTTPAuth::BasicAuth.new(
62
+ :Logger => @logger,
63
+ :Realm => 'auth',
64
+ :UserDB => htpasswd_userdb
65
+ )
66
+ @digest_auth = WEBrick::HTTPAuth::DigestAuth.new(
67
+ :Logger => @logger,
68
+ :Algorithm => 'MD5',
69
+ :Realm => 'auth',
70
+ :UserDB => htdigest_userdb
71
+ )
72
+ @digest_sess_auth = WEBrick::HTTPAuth::DigestAuth.new(
73
+ :Logger => @logger,
74
+ :Algorithm => 'MD5-sess',
75
+ :Realm => 'auth',
76
+ :UserDB => htdigest_userdb
77
+ )
78
+ @server_thread = start_server_thread(@server)
79
+
80
+ @proxy_digest_auth = WEBrick::HTTPAuth::ProxyDigestAuth.new(
81
+ :Logger => @proxylogger,
82
+ :Algorithm => 'MD5',
83
+ :Realm => 'auth',
84
+ :UserDB => htdigest_userdb
85
+ )
86
+
87
+ @proxyserver = WEBrick::HTTPProxyServer.new(
88
+ :ProxyAuthProc => @proxy_digest_auth.method(:authenticate).to_proc,
89
+ :BindAddress => "localhost",
90
+ :Logger => @proxylogger,
91
+ :Port => 0,
92
+ :AccessLog => []
93
+ )
94
+ @proxyport = @proxyserver.config[:Port]
95
+ @proxyserver_thread = start_server_thread(@proxyserver)
96
+ end
97
+
98
+ def do_basic_auth(req, res)
99
+ @basic_auth.authenticate(req, res)
100
+ res['content-type'] = 'text/plain'
101
+ res.body = 'basic_auth OK'
102
+ end
103
+
104
+ def do_digest_auth(req, res)
105
+ @digest_auth.authenticate(req, res)
106
+ res['content-type'] = 'text/plain'
107
+ res['x-query'] = req.body
108
+ res.body = 'digest_auth OK' + req.query_string.to_s
109
+ end
110
+
111
+ def do_digest_sess_auth(req, res)
112
+ @digest_sess_auth.authenticate(req, res)
113
+ res['content-type'] = 'text/plain'
114
+ res['x-query'] = req.body
115
+ res.body = 'digest_sess_auth OK' + req.query_string.to_s
116
+ end
117
+
118
+ def test_ntlm_auth
119
+ c = HTTPClient.new
120
+ c.set_auth("http://localhost:#{serverport}/ntlm_auth", 'admin', 'admin')
121
+ assert_equal('ntlm_auth OK', c.get_content("http://localhost:#{serverport}/ntlm_auth"))
122
+ puts c.inspect
123
+ end
124
+
125
+ def test_basic_auth
126
+ c = HTTPClient.new
127
+ c.set_auth("http://localhost:#{serverport}/", 'admin', 'admin')
128
+ assert_equal('basic_auth OK', c.get_content("http://localhost:#{serverport}/basic_auth"))
129
+ end
130
+
131
+ def test_basic_auth_compat
132
+ c = HTTPClient.new
133
+ c.set_basic_auth("http://localhost:#{serverport}/", 'admin', 'admin')
134
+ assert_equal('basic_auth OK', c.get_content("http://localhost:#{serverport}/basic_auth"))
135
+ end
136
+
137
+ def test_BASIC_auth
138
+ c = HTTPClient.new
139
+ webrick_backup = @basic_auth.instance_eval { @auth_scheme }
140
+ #httpaccess2_backup = c.www_auth.basic_auth.instance_eval { @scheme }
141
+ begin
142
+ @basic_auth.instance_eval { @auth_scheme = "BASIC" }
143
+ c.www_auth.basic_auth.instance_eval { @scheme = "BASIC" }
144
+ c.set_auth("http://localhost:#{serverport}/", 'admin', 'admin')
145
+ assert_equal('basic_auth OK', c.get_content("http://localhost:#{serverport}/basic_auth"))
146
+ ensure
147
+ @basic_auth.instance_eval { @auth_scheme = webrick_backup }
148
+ #c.www_auth.basic_auth.instance_eval { @scheme = httpaccess2_backup }
149
+ end
150
+ end
151
+
152
+ def test_basic_auth_reuses_credentials
153
+ c = HTTPClient.new
154
+ c.set_auth("http://localhost:#{serverport}/", 'admin', 'admin')
155
+ assert_equal('basic_auth OK', c.get_content("http://localhost:#{serverport}/basic_auth/"))
156
+ c.test_loopback_http_response << "HTTP/1.0 200 OK\nContent-Length: 2\n\nOK"
157
+ c.debug_dev = str = ''
158
+ c.get_content("http://localhost:#{serverport}/basic_auth/sub/dir/")
159
+ assert_match /Authorization: Basic YWRtaW46YWRtaW4=/, str
160
+ end
161
+
162
+ def test_digest_auth
163
+ c = HTTPClient.new
164
+ c.set_auth("http://localhost:#{serverport}/", 'admin', 'admin')
165
+ assert_equal('digest_auth OK', c.get_content("http://localhost:#{serverport}/digest_auth"))
166
+ end
167
+
168
+ def test_digest_auth_reuses_credentials
169
+ c = HTTPClient.new
170
+ c.set_auth("http://localhost:#{serverport}/", 'admin', 'admin')
171
+ assert_equal('digest_auth OK', c.get_content("http://localhost:#{serverport}/digest_auth/"))
172
+ c.test_loopback_http_response << "HTTP/1.0 200 OK\nContent-Length: 2\n\nOK"
173
+ c.debug_dev = str = ''
174
+ c.get_content("http://localhost:#{serverport}/digest_auth/sub/dir/")
175
+ assert_match /Authorization: Digest/, str
176
+ end
177
+
178
+ def test_digest_auth_with_block
179
+ c = HTTPClient.new
180
+ c.set_auth("http://localhost:#{serverport}/", 'admin', 'admin')
181
+ called = false
182
+ c.get_content("http://localhost:#{serverport}/digest_auth") do |str|
183
+ assert_equal('digest_auth OK', str)
184
+ called = true
185
+ end
186
+ assert(called)
187
+ #
188
+ called = false
189
+ c.get("http://localhost:#{serverport}/digest_auth") do |str|
190
+ assert_equal('digest_auth OK', str)
191
+ called = true
192
+ end
193
+ assert(called)
194
+ end
195
+
196
+ def test_digest_auth_with_post_io
197
+ c = HTTPClient.new
198
+ c.set_auth("http://localhost:#{serverport}/", 'admin', 'admin')
199
+ post_body = StringIO.new("1234567890")
200
+ assert_equal('1234567890', c.post("http://localhost:#{serverport}/digest_auth", post_body).header['x-query'][0])
201
+ #
202
+ post_body = StringIO.new("1234567890")
203
+ post_body.read(5)
204
+ assert_equal('67890', c.post("http://localhost:#{serverport}/digest_auth", post_body).header['x-query'][0])
205
+ end
206
+
207
+ def test_digest_auth_with_querystring
208
+ c = HTTPClient.new
209
+ c.debug_dev = STDERR if $DEBUG
210
+ c.set_auth("http://localhost:#{serverport}/", 'admin', 'admin')
211
+ assert_equal('digest_auth OKbar=baz', c.get_content("http://localhost:#{serverport}/digest_auth/foo?bar=baz"))
212
+ end
213
+
214
+ def test_perfer_digest
215
+ c = HTTPClient.new
216
+ c.set_auth('http://example.com/', 'admin', 'admin')
217
+ c.test_loopback_http_response << "HTTP/1.0 401 Unauthorized\nWWW-Authenticate: Basic realm=\"foo\"\nWWW-Authenticate: Digest realm=\"foo\", nonce=\"nonce\", stale=false\nContent-Length: 2\n\nNG"
218
+ c.test_loopback_http_response << "HTTP/1.0 200 OK\nContent-Length: 2\n\nOK"
219
+ c.debug_dev = str = ''
220
+ c.get_content('http://example.com/')
221
+ assert_match(/^Authorization: Digest/, str)
222
+ end
223
+
224
+ def test_digest_sess_auth
225
+ c = HTTPClient.new
226
+ c.set_auth("http://localhost:#{serverport}/", 'admin', 'admin')
227
+ assert_equal('digest_sess_auth OK', c.get_content("http://localhost:#{serverport}/digest_sess_auth"))
228
+ end
229
+
230
+ def test_proxy_auth
231
+ c = HTTPClient.new
232
+ c.set_proxy_auth('admin', 'admin')
233
+ c.test_loopback_http_response << "HTTP/1.0 407 Unauthorized\nProxy-Authenticate: Basic realm=\"foo\"\nContent-Length: 2\n\nNG"
234
+ c.test_loopback_http_response << "HTTP/1.0 200 OK\nContent-Length: 2\n\nOK"
235
+ c.debug_dev = str = ''
236
+ c.get_content('http://example.com/')
237
+ assert_match(/Proxy-Authorization: Basic YWRtaW46YWRtaW4=/, str)
238
+ end
239
+
240
+ def test_proxy_auth_reuses_credentials
241
+ c = HTTPClient.new
242
+ c.set_proxy_auth('admin', 'admin')
243
+ c.test_loopback_http_response << "HTTP/1.0 407 Unauthorized\nProxy-Authenticate: Basic realm=\"foo\"\nContent-Length: 2\n\nNG"
244
+ c.test_loopback_http_response << "HTTP/1.0 200 OK\nContent-Length: 2\n\nOK"
245
+ c.test_loopback_http_response << "HTTP/1.0 200 OK\nContent-Length: 2\n\nOK"
246
+ c.get_content('http://www1.example.com/')
247
+ c.debug_dev = str = ''
248
+ c.get_content('http://www2.example.com/')
249
+ assert_match(/Proxy-Authorization: Basic YWRtaW46YWRtaW4=/, str)
250
+ end
251
+
252
+ def test_digest_proxy_auth_loop
253
+ c = HTTPClient.new
254
+ c.set_proxy_auth('admin', 'admin')
255
+ c.test_loopback_http_response << "HTTP/1.0 407 Unauthorized\nProxy-Authenticate: Digest realm=\"foo\", nonce=\"nonce\", stale=false\nContent-Length: 2\n\nNG"
256
+ c.test_loopback_http_response << "HTTP/1.0 200 OK\nContent-Length: 2\n\nOK"
257
+ md5 = Digest::MD5.new
258
+ ha1 = md5.hexdigest("admin:foo:admin")
259
+ ha2 = md5.hexdigest("GET:/")
260
+ response = md5.hexdigest("#{ha1}:nonce:#{ha2}")
261
+ c.debug_dev = str = ''
262
+ c.get_content('http://example.com/')
263
+ assert_match(/Proxy-Authorization: Digest/, str)
264
+ assert_match(%r"response=\"#{response}\"", str)
265
+ end
266
+
267
+ def test_digest_proxy_auth
268
+ c=HTTPClient.new("http://localhost:#{proxyport}/")
269
+ c.set_proxy_auth('admin', 'admin')
270
+ c.set_auth("http://127.0.0.1:#{serverport}/", 'admin', 'admin')
271
+ assert_equal('basic_auth OK', c.get_content("http://127.0.0.1:#{serverport}/basic_auth"))
272
+ end
273
+
274
+ def test_digest_proxy_invalid_auth
275
+ c=HTTPClient.new("http://localhost:#{proxyport}/")
276
+ c.set_proxy_auth('admin', 'wrong')
277
+ c.set_auth("http://127.0.0.1:#{serverport}/", 'admin', 'admin')
278
+ assert_raises(HTTPClient::BadResponseError) do
279
+ c.get_content("http://127.0.0.1:#{serverport}/basic_auth")
280
+ end
281
+ end
282
+
283
+ def test_prefer_digest_to_basic_proxy_auth
284
+ c = HTTPClient.new
285
+ c.set_proxy_auth('admin', 'admin')
286
+ c.test_loopback_http_response << "HTTP/1.0 407 Unauthorized\nProxy-Authenticate: Digest realm=\"foo\", nonce=\"nonce\", stale=false\nProxy-Authenticate: Basic realm=\"bar\"\nContent-Length: 2\n\nNG"
287
+ c.test_loopback_http_response << "HTTP/1.0 200 OK\nContent-Length: 2\n\nOK"
288
+ md5 = Digest::MD5.new
289
+ ha1 = md5.hexdigest("admin:foo:admin")
290
+ ha2 = md5.hexdigest("GET:/")
291
+ response = md5.hexdigest("#{ha1}:nonce:#{ha2}")
292
+ c.debug_dev = str = ''
293
+ c.get_content('http://example.com/')
294
+ assert_match(/Proxy-Authorization: Digest/, str)
295
+ assert_match(%r"response=\"#{response}\"", str)
296
+ end
297
+
298
+ def test_digest_proxy_auth_reuses_credentials
299
+ c = HTTPClient.new
300
+ c.set_proxy_auth('admin', 'admin')
301
+ c.test_loopback_http_response << "HTTP/1.0 407 Unauthorized\nProxy-Authenticate: Digest realm=\"foo\", nonce=\"nonce\", stale=false\nContent-Length: 2\n\nNG"
302
+ c.test_loopback_http_response << "HTTP/1.0 200 OK\nContent-Length: 2\n\nOK"
303
+ c.test_loopback_http_response << "HTTP/1.0 200 OK\nContent-Length: 2\n\nOK"
304
+ md5 = Digest::MD5.new
305
+ ha1 = md5.hexdigest("admin:foo:admin")
306
+ ha2 = md5.hexdigest("GET:/")
307
+ response = md5.hexdigest("#{ha1}:nonce:#{ha2}")
308
+ c.get_content('http://www1.example.com/')
309
+ c.debug_dev = str = ''
310
+ c.get_content('http://www2.example.com/')
311
+ assert_match(/Proxy-Authorization: Digest/, str)
312
+ assert_match(%r"response=\"#{response}\"", str)
313
+ end
314
+
315
+ def test_oauth
316
+ c = HTTPClient.new
317
+ config = HTTPClient::OAuth::Config.new(
318
+ :realm => 'http://photos.example.net/',
319
+ :consumer_key => 'dpf43f3p2l4k3l03',
320
+ :consumer_secret => 'kd94hf93k423kf44',
321
+ :token => 'nnch734d00sl2jdk',
322
+ :secret => 'pfkkdhi9sl3r4s00',
323
+ :version => '1.0',
324
+ :signature_method => 'HMAC-SHA1'
325
+ )
326
+ config.debug_timestamp = '1191242096'
327
+ config.debug_nonce = 'kllo9940pd9333jh'
328
+ c.www_auth.oauth.set_config('http://photos.example.net/', config)
329
+ c.www_auth.oauth.challenge('http://photos.example.net/')
330
+ c.test_loopback_http_response << "HTTP/1.0 200 OK\nContent-Length: 2\n\nOK"
331
+ c.debug_dev = str = ''
332
+ c.get_content('http://photos.example.net/photos', [[:file, 'vacation.jpg'], [:size, 'original']])
333
+ assert(str.index(%q(GET /photos?file=vacation.jpg&size=original)))
334
+ assert(str.index(%q(Authorization: OAuth realm="http://photos.example.net/", oauth_consumer_key="dpf43f3p2l4k3l03", oauth_nonce="kllo9940pd9333jh", oauth_signature="tR3%2BTy81lMeYAr%2FFid0kMTYa%2FWM%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1191242096", oauth_token="nnch734d00sl2jdk", oauth_version="1.0")))
335
+ #
336
+ c.test_loopback_http_response << "HTTP/1.0 200 OK\nContent-Length: 2\n\nOK"
337
+ c.debug_dev = str = ''
338
+ c.get_content('http://photos.example.net/photos?file=vacation.jpg&size=original')
339
+ assert(str.index(%q(GET /photos?file=vacation.jpg&size=original)))
340
+ assert(str.index(%q(Authorization: OAuth realm="http://photos.example.net/", oauth_consumer_key="dpf43f3p2l4k3l03", oauth_nonce="kllo9940pd9333jh", oauth_signature="tR3%2BTy81lMeYAr%2FFid0kMTYa%2FWM%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1191242096", oauth_token="nnch734d00sl2jdk", oauth_version="1.0")))
341
+ #
342
+ c.test_loopback_http_response << "HTTP/1.0 200 OK\nContent-Length: 2\n\nOK"
343
+ c.debug_dev = str = ''
344
+ c.post_content('http://photos.example.net/photos', [[:file, 'vacation.jpg'], [:size, 'original']])
345
+ assert(str.index(%q(POST /photos)))
346
+ assert(str.index(%q(Authorization: OAuth realm="http://photos.example.net/", oauth_consumer_key="dpf43f3p2l4k3l03", oauth_nonce="kllo9940pd9333jh", oauth_signature="wPkvxykrw%2BBTdCcGqKr%2B3I%2BPsiM%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1191242096", oauth_token="nnch734d00sl2jdk", oauth_version="1.0")))
347
+ end
348
+ end