pelle-ruby-openid 2.1.8

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.
Files changed (197) hide show
  1. data/CHANGELOG +215 -0
  2. data/CHANGES-2.1.0 +36 -0
  3. data/INSTALL +47 -0
  4. data/LICENSE +210 -0
  5. data/NOTICE +2 -0
  6. data/README +82 -0
  7. data/UPGRADE +127 -0
  8. data/VERSION +1 -0
  9. data/examples/README +32 -0
  10. data/examples/active_record_openid_store/README +58 -0
  11. data/examples/active_record_openid_store/XXX_add_open_id_store_to_db.rb +24 -0
  12. data/examples/active_record_openid_store/XXX_upgrade_open_id_store.rb +26 -0
  13. data/examples/active_record_openid_store/init.rb +8 -0
  14. data/examples/active_record_openid_store/lib/association.rb +10 -0
  15. data/examples/active_record_openid_store/lib/nonce.rb +3 -0
  16. data/examples/active_record_openid_store/lib/open_id_setting.rb +4 -0
  17. data/examples/active_record_openid_store/lib/openid_ar_store.rb +57 -0
  18. data/examples/active_record_openid_store/test/store_test.rb +212 -0
  19. data/examples/discover +49 -0
  20. data/examples/rails_openid/README +153 -0
  21. data/examples/rails_openid/Rakefile +10 -0
  22. data/examples/rails_openid/app/controllers/application.rb +4 -0
  23. data/examples/rails_openid/app/controllers/consumer_controller.rb +122 -0
  24. data/examples/rails_openid/app/controllers/login_controller.rb +45 -0
  25. data/examples/rails_openid/app/controllers/server_controller.rb +265 -0
  26. data/examples/rails_openid/app/helpers/application_helper.rb +3 -0
  27. data/examples/rails_openid/app/helpers/login_helper.rb +2 -0
  28. data/examples/rails_openid/app/helpers/server_helper.rb +9 -0
  29. data/examples/rails_openid/app/views/consumer/index.rhtml +81 -0
  30. data/examples/rails_openid/app/views/layouts/server.rhtml +68 -0
  31. data/examples/rails_openid/app/views/login/index.rhtml +56 -0
  32. data/examples/rails_openid/app/views/server/decide.rhtml +26 -0
  33. data/examples/rails_openid/config/boot.rb +19 -0
  34. data/examples/rails_openid/config/database.yml +74 -0
  35. data/examples/rails_openid/config/environment.rb +54 -0
  36. data/examples/rails_openid/config/environments/development.rb +19 -0
  37. data/examples/rails_openid/config/environments/production.rb +19 -0
  38. data/examples/rails_openid/config/environments/test.rb +19 -0
  39. data/examples/rails_openid/config/routes.rb +24 -0
  40. data/examples/rails_openid/doc/README_FOR_APP +2 -0
  41. data/examples/rails_openid/public/.htaccess +40 -0
  42. data/examples/rails_openid/public/404.html +8 -0
  43. data/examples/rails_openid/public/500.html +8 -0
  44. data/examples/rails_openid/public/dispatch.cgi +12 -0
  45. data/examples/rails_openid/public/dispatch.fcgi +26 -0
  46. data/examples/rails_openid/public/dispatch.rb +12 -0
  47. data/examples/rails_openid/public/favicon.ico +0 -0
  48. data/examples/rails_openid/public/images/openid_login_bg.gif +0 -0
  49. data/examples/rails_openid/public/javascripts/controls.js +750 -0
  50. data/examples/rails_openid/public/javascripts/dragdrop.js +584 -0
  51. data/examples/rails_openid/public/javascripts/effects.js +854 -0
  52. data/examples/rails_openid/public/javascripts/prototype.js +1785 -0
  53. data/examples/rails_openid/public/robots.txt +1 -0
  54. data/examples/rails_openid/script/about +3 -0
  55. data/examples/rails_openid/script/breakpointer +3 -0
  56. data/examples/rails_openid/script/console +3 -0
  57. data/examples/rails_openid/script/destroy +3 -0
  58. data/examples/rails_openid/script/generate +3 -0
  59. data/examples/rails_openid/script/performance/benchmarker +3 -0
  60. data/examples/rails_openid/script/performance/profiler +3 -0
  61. data/examples/rails_openid/script/plugin +3 -0
  62. data/examples/rails_openid/script/process/reaper +3 -0
  63. data/examples/rails_openid/script/process/spawner +3 -0
  64. data/examples/rails_openid/script/process/spinner +3 -0
  65. data/examples/rails_openid/script/runner +3 -0
  66. data/examples/rails_openid/script/server +3 -0
  67. data/examples/rails_openid/test/functional/login_controller_test.rb +18 -0
  68. data/examples/rails_openid/test/functional/server_controller_test.rb +18 -0
  69. data/examples/rails_openid/test/test_helper.rb +28 -0
  70. data/lib/hmac/hmac.rb +112 -0
  71. data/lib/hmac/sha1.rb +11 -0
  72. data/lib/hmac/sha2.rb +25 -0
  73. data/lib/openid/association.rb +249 -0
  74. data/lib/openid/consumer/associationmanager.rb +344 -0
  75. data/lib/openid/consumer/checkid_request.rb +186 -0
  76. data/lib/openid/consumer/discovery.rb +498 -0
  77. data/lib/openid/consumer/discovery_manager.rb +123 -0
  78. data/lib/openid/consumer/html_parse.rb +134 -0
  79. data/lib/openid/consumer/idres.rb +523 -0
  80. data/lib/openid/consumer/responses.rb +148 -0
  81. data/lib/openid/consumer.rb +395 -0
  82. data/lib/openid/cryptutil.rb +97 -0
  83. data/lib/openid/dh.rb +89 -0
  84. data/lib/openid/extension.rb +39 -0
  85. data/lib/openid/extensions/ax.rb +516 -0
  86. data/lib/openid/extensions/oauth.rb +91 -0
  87. data/lib/openid/extensions/pape.rb +179 -0
  88. data/lib/openid/extensions/sreg.rb +277 -0
  89. data/lib/openid/extras.rb +11 -0
  90. data/lib/openid/fetchers.rb +238 -0
  91. data/lib/openid/kvform.rb +136 -0
  92. data/lib/openid/kvpost.rb +58 -0
  93. data/lib/openid/message.rb +553 -0
  94. data/lib/openid/protocolerror.rb +8 -0
  95. data/lib/openid/server.rb +1544 -0
  96. data/lib/openid/store/filesystem.rb +271 -0
  97. data/lib/openid/store/interface.rb +75 -0
  98. data/lib/openid/store/memcache.rb +107 -0
  99. data/lib/openid/store/memory.rb +84 -0
  100. data/lib/openid/store/nonce.rb +68 -0
  101. data/lib/openid/trustroot.rb +349 -0
  102. data/lib/openid/urinorm.rb +75 -0
  103. data/lib/openid/util.rb +110 -0
  104. data/lib/openid/yadis/accept.rb +148 -0
  105. data/lib/openid/yadis/constants.rb +21 -0
  106. data/lib/openid/yadis/discovery.rb +153 -0
  107. data/lib/openid/yadis/filters.rb +205 -0
  108. data/lib/openid/yadis/htmltokenizer.rb +305 -0
  109. data/lib/openid/yadis/parsehtml.rb +45 -0
  110. data/lib/openid/yadis/services.rb +42 -0
  111. data/lib/openid/yadis/xrds.rb +155 -0
  112. data/lib/openid/yadis/xri.rb +90 -0
  113. data/lib/openid/yadis/xrires.rb +106 -0
  114. data/lib/openid.rb +20 -0
  115. data/setup.rb +1551 -0
  116. data/test/data/accept.txt +124 -0
  117. data/test/data/dh.txt +29 -0
  118. data/test/data/example-xrds.xml +14 -0
  119. data/test/data/linkparse.txt +587 -0
  120. data/test/data/n2b64 +650 -0
  121. data/test/data/test1-discover.txt +137 -0
  122. data/test/data/test1-parsehtml.txt +152 -0
  123. data/test/data/test_discover/malformed_meta_tag.html +19 -0
  124. data/test/data/test_discover/openid.html +11 -0
  125. data/test/data/test_discover/openid2.html +11 -0
  126. data/test/data/test_discover/openid2_xrds.xml +12 -0
  127. data/test/data/test_discover/openid2_xrds_no_local_id.xml +11 -0
  128. data/test/data/test_discover/openid_1_and_2.html +11 -0
  129. data/test/data/test_discover/openid_1_and_2_xrds.xml +16 -0
  130. data/test/data/test_discover/openid_1_and_2_xrds_bad_delegate.xml +17 -0
  131. data/test/data/test_discover/openid_and_yadis.html +12 -0
  132. data/test/data/test_discover/openid_no_delegate.html +10 -0
  133. data/test/data/test_discover/yadis_0entries.xml +12 -0
  134. data/test/data/test_discover/yadis_2_bad_local_id.xml +15 -0
  135. data/test/data/test_discover/yadis_2entries_delegate.xml +22 -0
  136. data/test/data/test_discover/yadis_2entries_idp.xml +21 -0
  137. data/test/data/test_discover/yadis_another_delegate.xml +14 -0
  138. data/test/data/test_discover/yadis_idp.xml +12 -0
  139. data/test/data/test_discover/yadis_idp_delegate.xml +13 -0
  140. data/test/data/test_discover/yadis_no_delegate.xml +11 -0
  141. data/test/data/test_xrds/=j3h.2007.11.14.xrds +25 -0
  142. data/test/data/test_xrds/README +12 -0
  143. data/test/data/test_xrds/delegated-20060809-r1.xrds +34 -0
  144. data/test/data/test_xrds/delegated-20060809-r2.xrds +34 -0
  145. data/test/data/test_xrds/delegated-20060809.xrds +34 -0
  146. data/test/data/test_xrds/no-xrd.xml +7 -0
  147. data/test/data/test_xrds/not-xrds.xml +2 -0
  148. data/test/data/test_xrds/prefixsometimes.xrds +34 -0
  149. data/test/data/test_xrds/ref.xrds +109 -0
  150. data/test/data/test_xrds/sometimesprefix.xrds +34 -0
  151. data/test/data/test_xrds/spoof1.xrds +25 -0
  152. data/test/data/test_xrds/spoof2.xrds +25 -0
  153. data/test/data/test_xrds/spoof3.xrds +37 -0
  154. data/test/data/test_xrds/status222.xrds +9 -0
  155. data/test/data/test_xrds/subsegments.xrds +58 -0
  156. data/test/data/test_xrds/valid-populated-xrds.xml +39 -0
  157. data/test/data/trustroot.txt +153 -0
  158. data/test/data/urinorm.txt +79 -0
  159. data/test/discoverdata.rb +131 -0
  160. data/test/test_accept.rb +170 -0
  161. data/test/test_association.rb +266 -0
  162. data/test/test_associationmanager.rb +917 -0
  163. data/test/test_ax.rb +648 -0
  164. data/test/test_checkid_request.rb +294 -0
  165. data/test/test_consumer.rb +257 -0
  166. data/test/test_cryptutil.rb +119 -0
  167. data/test/test_dh.rb +86 -0
  168. data/test/test_discover.rb +838 -0
  169. data/test/test_discovery_manager.rb +262 -0
  170. data/test/test_extension.rb +46 -0
  171. data/test/test_extras.rb +35 -0
  172. data/test/test_fetchers.rb +538 -0
  173. data/test/test_filters.rb +270 -0
  174. data/test/test_idres.rb +963 -0
  175. data/test/test_kvform.rb +165 -0
  176. data/test/test_kvpost.rb +65 -0
  177. data/test/test_linkparse.rb +101 -0
  178. data/test/test_message.rb +1116 -0
  179. data/test/test_nonce.rb +89 -0
  180. data/test/test_oauth.rb +175 -0
  181. data/test/test_openid_yadis.rb +178 -0
  182. data/test/test_pape.rb +247 -0
  183. data/test/test_parsehtml.rb +80 -0
  184. data/test/test_responses.rb +63 -0
  185. data/test/test_server.rb +2457 -0
  186. data/test/test_sreg.rb +479 -0
  187. data/test/test_stores.rb +298 -0
  188. data/test/test_trustroot.rb +113 -0
  189. data/test/test_urinorm.rb +35 -0
  190. data/test/test_util.rb +145 -0
  191. data/test/test_xrds.rb +169 -0
  192. data/test/test_xri.rb +48 -0
  193. data/test/test_xrires.rb +63 -0
  194. data/test/test_yadis_discovery.rb +220 -0
  195. data/test/testutil.rb +127 -0
  196. data/test/util.rb +53 -0
  197. metadata +316 -0
@@ -0,0 +1,79 @@
1
+ Already normal form
2
+ http://example.com/
3
+ http://example.com/
4
+
5
+ Add a trailing slash
6
+ http://example.com
7
+ http://example.com/
8
+
9
+ Remove an empty port segment
10
+ http://example.com:/
11
+ http://example.com/
12
+
13
+ Remove a default port segment
14
+ http://example.com:80/
15
+ http://example.com/
16
+
17
+ Capitalization in host names
18
+ http://wWw.exaMPLE.COm/
19
+ http://www.example.com/
20
+
21
+ Capitalization in scheme names
22
+ htTP://example.com/
23
+ http://example.com/
24
+
25
+ Capitalization in percent-escaped reserved characters
26
+ http://example.com/foo%2cbar
27
+ http://example.com/foo%2Cbar
28
+
29
+ Unescape percent-encoded unreserved characters
30
+ http://example.com/foo%2Dbar%2dbaz
31
+ http://example.com/foo-bar-baz
32
+
33
+ remove_dot_segments example 1
34
+ http://example.com/a/b/c/./../../g
35
+ http://example.com/a/g
36
+
37
+ remove_dot_segments example 2
38
+ http://example.com/mid/content=5/../6
39
+ http://example.com/mid/6
40
+
41
+ remove_dot_segments: single-dot
42
+ http://example.com/a/./b
43
+ http://example.com/a/b
44
+
45
+ remove_dot_segments: double-dot
46
+ http://example.com/a/../b
47
+ http://example.com/b
48
+
49
+ remove_dot_segments: leading double-dot
50
+ http://example.com/../b
51
+ http://example.com/b
52
+
53
+ remove_dot_segments: trailing single-dot
54
+ http://example.com/a/.
55
+ http://example.com/a/
56
+
57
+ remove_dot_segments: trailing double-dot
58
+ http://example.com/a/..
59
+ http://example.com/
60
+
61
+ remove_dot_segments: trailing single-dot-slash
62
+ http://example.com/a/./
63
+ http://example.com/a/
64
+
65
+ remove_dot_segments: trailing double-dot-slash
66
+ http://example.com/a/../
67
+ http://example.com/
68
+
69
+ Test of all kinds of syntax-based normalization
70
+ hTTPS://a/./b/../b/%63/%7bfoo%7d
71
+ https://a/b/c/%7Bfoo%7D
72
+
73
+ Unsupported scheme
74
+ ftp://example.com/
75
+ fail
76
+
77
+ Non-absolute URI
78
+ http:/foo
79
+ fail
@@ -0,0 +1,131 @@
1
+
2
+ require 'uri'
3
+ require 'openid/yadis/constants'
4
+ require 'openid/yadis/discovery'
5
+ require 'openid/extras'
6
+ require 'openid/util'
7
+
8
+ module OpenID
9
+
10
+ module DiscoverData
11
+
12
+ include TestDataMixin
13
+ include Util
14
+
15
+ TESTLIST = [
16
+ # success, input_name, id_name, result_name
17
+ [true, "equiv", "equiv", "xrds"],
18
+ [true, "header", "header", "xrds"],
19
+ [true, "lowercase_header", "lowercase_header", "xrds"],
20
+ [true, "xrds", "xrds", "xrds"],
21
+ [true, "xrds_ctparam", "xrds_ctparam", "xrds_ctparam"],
22
+ [true, "xrds_ctcase", "xrds_ctcase", "xrds_ctcase"],
23
+ [false, "xrds_html", "xrds_html", "xrds_html"],
24
+ [true, "redir_equiv", "equiv", "xrds"],
25
+ [true, "redir_header", "header", "xrds"],
26
+ [true, "redir_xrds", "xrds", "xrds"],
27
+ [false, "redir_xrds_html", "xrds_html", "xrds_html"],
28
+ [true, "redir_redir_equiv", "equiv", "xrds"],
29
+ [false, "404_server_response", nil, nil],
30
+ [false, "404_with_header", nil, nil],
31
+ [false, "404_with_meta", nil, nil],
32
+ [false, "201_server_response", nil, nil],
33
+ [false, "500_server_response", nil, nil],
34
+ ]
35
+
36
+ @@example_xrds_file = 'example-xrds.xml'
37
+ @@default_test_file = 'test1-discover.txt'
38
+ @@discover_tests = {}
39
+
40
+ def readTests(filename)
41
+ data = read_data_file(filename, false)
42
+ tests = {}
43
+ data.split("\f\n", -1).each { |case_|
44
+ name, content = case_.split("\n", 2)
45
+ tests[name] = content
46
+ }
47
+
48
+ return tests
49
+ end
50
+
51
+ def getData(filename, name)
52
+ if !@@discover_tests.member?(filename)
53
+ @@discover_tests[filename] = readTests(filename)
54
+ end
55
+
56
+ file_tests = @@discover_tests[filename]
57
+ return file_tests[name]
58
+ end
59
+
60
+ def fillTemplate(test_name, template, base_url, example_xrds)
61
+ mapping = [
62
+ ['URL_BASE/', base_url],
63
+ ['<XRDS Content>', example_xrds],
64
+ ['YADIS_HEADER', Yadis::YADIS_HEADER_NAME],
65
+ ['NAME', test_name],
66
+ ]
67
+
68
+ mapping.each { |k, v|
69
+ template = template.gsub(/#{k}/, v)
70
+ }
71
+
72
+ return template
73
+ end
74
+
75
+ def generateSample(test_name, base_url,
76
+ example_xrds=nil,
77
+ filename=@@default_test_file)
78
+ if example_xrds.nil?
79
+ example_xrds = read_data_file(@@example_xrds_file, false)
80
+ end
81
+
82
+ begin
83
+ template = getData(filename, test_name)
84
+ rescue Errno::ENOENT
85
+ raise ArgumentError(filename)
86
+ end
87
+
88
+ return fillTemplate(test_name, template, base_url, example_xrds)
89
+ end
90
+
91
+ def generateResult(base_url, input_name, id_name, result_name, success)
92
+ uri = URI::parse(base_url)
93
+
94
+ input_url = (uri + input_name).to_s
95
+
96
+ # If the name is None then we expect the protocol to fail, which
97
+ # we represent by None
98
+ if id_name.nil?
99
+ Util.assert(result_name.nil?)
100
+ return input_url, DiscoveryFailure
101
+ end
102
+
103
+ result = generateSample(result_name, base_url)
104
+ headers, content = result.split("\n\n", 2)
105
+ header_lines = headers.split("\n")
106
+
107
+ ctype = nil
108
+ header_lines.each { |header_line|
109
+ if header_line.starts_with?('Content-Type:')
110
+ _, ctype = header_line.split(':', 2)
111
+ ctype = ctype.strip()
112
+ break
113
+ else
114
+ ctype = nil
115
+ end
116
+ }
117
+
118
+ id_url = (uri + id_name).to_s
119
+ result = Yadis::DiscoveryResult.new(input_url)
120
+ result.normalized_uri = id_url
121
+
122
+ if success
123
+ result.xrds_uri = (uri + result_name).to_s
124
+ end
125
+
126
+ result.content_type = ctype
127
+ result.response_text = content
128
+ return [input_url, result]
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,170 @@
1
+
2
+ require 'test/unit'
3
+ require 'openid/yadis/accept'
4
+ require 'openid/extras'
5
+ require 'openid/util'
6
+
7
+ module OpenID
8
+
9
+ class AcceptTest < Test::Unit::TestCase
10
+ include TestDataMixin
11
+
12
+ def getTestData()
13
+ # Read the test data off of disk
14
+ #
15
+ # () -> [(int, str)]
16
+ lines = read_data_file('accept.txt')
17
+ line_no = 1
18
+ return lines.collect { |line|
19
+ pair = [line_no, line]
20
+ line_no += 1
21
+ pair
22
+ }
23
+ end
24
+
25
+ def chunk(lines)
26
+ # Return groups of lines separated by whitespace or comments
27
+ #
28
+ # [(int, str)] -> [[(int, str)]]
29
+ chunks = []
30
+ chunk = []
31
+ lines.each { |lineno, line|
32
+ stripped = line.strip()
33
+ if (stripped == '') or stripped.starts_with?('#')
34
+ if chunk.length > 0
35
+ chunks << chunk
36
+ chunk = []
37
+ end
38
+ else
39
+ chunk << [lineno, stripped]
40
+ end
41
+ }
42
+
43
+ if chunk.length > 0
44
+ chunks << chunk
45
+ end
46
+
47
+ return chunks
48
+ end
49
+
50
+ def parseLines(chunk)
51
+ # Take the given chunk of lines and turn it into a test data
52
+ # dictionary
53
+ #
54
+ # [(int, str)] -> {str:(int, str)}
55
+ items = {}
56
+ chunk.each { |lineno, line|
57
+ header, data = line.split(':', 2)
58
+ header = header.downcase
59
+ items[header] = [lineno, data.strip]
60
+ }
61
+ return items
62
+ end
63
+
64
+ def parseAvailable(available_text)
65
+ # Parse an Available: line's data
66
+ #
67
+ # str -> [str]
68
+ return available_text.split(',', -1).collect { |s| s.strip }
69
+ end
70
+
71
+ def parseExpected(expected_text)
72
+ # Parse an Expected: line's data
73
+ #
74
+ # str -> [(str, float)]
75
+ expected = []
76
+ if expected_text != ''
77
+ expected_text.split(',', -1).each { |chunk|
78
+ chunk = chunk.strip
79
+ mtype, qstuff = chunk.split(';', -1)
80
+ mtype = mtype.strip
81
+ Util.assert(!mtype.index('/').nil?)
82
+ qstuff = qstuff.strip
83
+ q, qstr = qstuff.split('=', -1)
84
+ Util.assert(q == 'q')
85
+ qval = qstr.to_f
86
+ expected << [mtype, qval]
87
+ }
88
+ end
89
+
90
+ return expected
91
+ end
92
+
93
+ def test_accept_headers
94
+ lines = getTestData()
95
+ chunks = chunk(lines)
96
+ data_sets = chunks.collect { |chunk| parseLines(chunk) }
97
+ cases = []
98
+ data_sets.each { |data|
99
+ lnos = []
100
+ lno, header = data['accept']
101
+ lnos << lno
102
+ lno, avail_data = data['available']
103
+ lnos << lno
104
+ begin
105
+ available = parseAvailable(avail_data)
106
+ rescue
107
+ print 'On line', lno
108
+ raise
109
+ end
110
+
111
+ lno, exp_data = data['expected']
112
+ lnos << lno
113
+ begin
114
+ expected = parseExpected(exp_data)
115
+ rescue
116
+ print 'On line', lno
117
+ raise
118
+ end
119
+
120
+ descr = sprintf('MatchAcceptTest for lines %s', lnos)
121
+
122
+ # Test:
123
+ accepted = Yadis.parse_accept_header(header)
124
+ actual = Yadis.match_types(accepted, available)
125
+ assert_equal(expected, actual)
126
+
127
+ assert_equal(Yadis.get_acceptable(header, available),
128
+ expected.collect { |mtype, _| mtype })
129
+ }
130
+ end
131
+
132
+ def test_generate_accept_header
133
+ # TODO: move this into a test case file and write parsing code
134
+ # for it.
135
+
136
+ # Form: [input_array, expected_header_string]
137
+ cases = [
138
+ # Empty input list
139
+ [[], ""],
140
+ # Content type name only; no q value
141
+ [["test"], "test"],
142
+ # q = 1.0 should be omitted from the header
143
+ [[["test", 1.0]], "test"],
144
+ # Test conversion of float to string
145
+ [["test", ["with_q", 0.8]], "with_q; q=0.8, test"],
146
+ # Allow string q values, too
147
+ [["test", ["with_q_str", "0.7"]], "with_q_str; q=0.7, test"],
148
+ # Test q values out of bounds
149
+ [[["test", -1.0]], nil],
150
+ [[["test", 1.1]], nil],
151
+ # Test sorting of types by q value
152
+ [[["middle", 0.5], ["min", 0.1], "max"],
153
+ "min; q=0.1, middle; q=0.5, max"],
154
+
155
+ ].each { |input, expected_header|
156
+
157
+ if expected_header.nil?
158
+ assert_raise(ArgumentError) {
159
+ Yadis.generate_accept_header(*input)
160
+ }
161
+ else
162
+ assert_equal(expected_header, Yadis.generate_accept_header(*input),
163
+ [input, expected_header].inspect)
164
+ end
165
+ }
166
+ end
167
+
168
+ end
169
+
170
+ end
@@ -0,0 +1,266 @@
1
+ require "test/unit"
2
+ require "openid/association"
3
+
4
+ module OpenID
5
+ class AssociationTestCase < Test::Unit::TestCase
6
+ def setup
7
+ # Use this funny way of getting a time so that it does not have
8
+ # fractional seconds, and so can be serialized exactly using our
9
+ # standard code.
10
+ issued = Time.at(Time.now.to_i)
11
+ lifetime = 600
12
+
13
+ @assoc = Association.new('handle', 'secret', issued,
14
+ lifetime, 'HMAC-SHA1')
15
+ end
16
+
17
+ def test_round_trip
18
+ assoc2 = Association.deserialize(@assoc.serialize())
19
+ [:handle, :secret, :lifetime, :assoc_type].each do |attr|
20
+ assert_equal(@assoc.send(attr), assoc2.send(attr))
21
+ end
22
+ end
23
+
24
+ def test_deserialize_failure
25
+ field_list = Util.kv_to_seq(@assoc.serialize)
26
+ kv = Util.seq_to_kv(field_list + [['monkeys', 'funny']])
27
+ assert_raises(ProtocolError) {
28
+ Association.deserialize(kv)
29
+ }
30
+
31
+ bad_version_list = field_list.dup
32
+ bad_version_list[0] = ['version', 'moon']
33
+ bad_version_kv = Util.seq_to_kv(bad_version_list)
34
+ assert_raises(ProtocolError) {
35
+ Association.deserialize(bad_version_kv)
36
+ }
37
+ end
38
+
39
+ def test_serialization_identity
40
+ assoc2 = Association.deserialize(@assoc.serialize)
41
+ assert_equal(@assoc, assoc2)
42
+ end
43
+
44
+ def test_expires_in
45
+ # Allow one second of slop
46
+ assert(@assoc.expires_in.between?(599,600))
47
+ assert(@assoc.expires_in(Time.now.to_i).between?(599,600))
48
+ assert_equal(0,@assoc.expires_in(Time.now.to_i + 10000),"negative expires_in")
49
+ end
50
+
51
+ def test_from_expires_in
52
+ start_time = Time.now
53
+ expires_in = @assoc.expires_in
54
+ assoc = Association.from_expires_in(expires_in,
55
+ @assoc.handle,
56
+ @assoc.secret,
57
+ @assoc.assoc_type)
58
+
59
+ # Allow one second of slop here for code execution time
60
+ assert_in_delta(1, assoc.expires_in, @assoc.expires_in)
61
+ [:handle, :secret, :assoc_type].each do |attr|
62
+ assert_equal(@assoc.send(attr), assoc.send(attr))
63
+ end
64
+
65
+ # Make sure the issued time is near the start
66
+ assert(assoc.issued >= start_time)
67
+ assert_in_delta(1, assoc.issued.to_f, start_time.to_f)
68
+ end
69
+
70
+ def test_sign_sha1
71
+ pairs = [['key1', 'value1'],
72
+ ['key2', 'value2']]
73
+
74
+ [['HMAC-SHA256', "\xfd\xaa\xfe;\xac\xfc*\x988\xad\x05d6-"\
75
+ "\xeaVy\xd5\xa5Z.<\xa9\xed\x18\x82\\$"\
76
+ "\x95x\x1c&"],
77
+ ['HMAC-SHA1', "\xe0\x1bv\x04\xf1G\xc0\xbb\x7f\x9a\x8b"\
78
+ "\xe9\xbc\xee}\\\xe5\xbb7*"],
79
+ ].each do |assoc_type, expected|
80
+ assoc = Association.from_expires_in(3600, "handle", 'very_secret',
81
+ assoc_type)
82
+ sig = assoc.sign(pairs)
83
+ assert_equal(sig, expected)
84
+
85
+ m = Message.new(OPENID2_NS)
86
+ pairs.each { |k, v|
87
+ m.set_arg(OPENID_NS, k, v)
88
+ }
89
+ m.set_arg(BARE_NS, "not_an_openid_arg", "bogus")
90
+
91
+ signed_m = assoc.sign_message(m)
92
+ assert(signed_m.has_key?(OPENID_NS, 'sig'))
93
+ assert_equal(signed_m.get_arg(OPENID_NS, 'signed'),
94
+ 'assoc_handle,key1,key2,ns,signed')
95
+ end
96
+ end
97
+
98
+ def test_sign_message_with_sig
99
+ assoc = Association.from_expires_in(3600, "handle", "very_secret",
100
+ "HMAC-SHA1")
101
+ m = Message.new(OPENID2_NS)
102
+ m.set_arg(OPENID_NS, 'sig', 'noise')
103
+ assert_raises(ArgumentError) {
104
+ assoc.sign_message(m)
105
+ }
106
+ end
107
+
108
+ def test_sign_message_with_signed
109
+ assoc = Association.from_expires_in(3600, "handle", "very_secret",
110
+ "HMAC-SHA1")
111
+ m = Message.new(OPENID2_NS)
112
+ m.set_arg(OPENID_NS, 'signed', 'fields')
113
+ assert_raises(ArgumentError) {
114
+ assoc.sign_message(m)
115
+ }
116
+ end
117
+
118
+ def test_sign_different_assoc_handle
119
+ assoc = Association.from_expires_in(3600, "handle", "very_secret",
120
+ "HMAC-SHA1")
121
+ m = Message.new(OPENID2_NS)
122
+ m.set_arg(OPENID_NS, 'assoc_handle', 'different')
123
+ assert_raises(ArgumentError) {
124
+ assoc.sign_message(m)
125
+ }
126
+ end
127
+
128
+ def test_sign_bad_assoc_type
129
+ @assoc.instance_eval { @assoc_type = 'Cookies' }
130
+ assert_raises(ProtocolError) {
131
+ @assoc.sign([])
132
+ }
133
+ end
134
+
135
+ def test_make_pairs
136
+ msg = Message.new(OPENID2_NS)
137
+ msg.update_args(OPENID2_NS, {
138
+ 'mode' => 'id_res',
139
+ 'identifier' => '=example',
140
+ 'signed' => 'identifier,mode',
141
+ 'sig' => 'cephalopod',
142
+ })
143
+ msg.update_args(BARE_NS, {'xey' => 'value'})
144
+ assoc = Association.from_expires_in(3600, '{sha1}', 'very_secret',
145
+ "HMAC-SHA1")
146
+ pairs = assoc.make_pairs(msg)
147
+ assert_equal([['identifier', '=example'],
148
+ ['mode', 'id_res']], pairs)
149
+ end
150
+
151
+ def test_check_message_signature_no_signed
152
+ m = Message.new(OPENID2_NS)
153
+ m.update_args(OPENID2_NS, {'mode' => 'id_res',
154
+ 'identifier' => '=example',
155
+ 'sig' => 'coyote',
156
+ })
157
+ assoc = Association.from_expires_in(3600, '{sha1}', 'very_secret',
158
+ "HMAC-SHA1")
159
+ assert_raises(ProtocolError) {
160
+ assoc.check_message_signature(m)
161
+ }
162
+ end
163
+
164
+ def test_check_message_signature_no_sig
165
+ m = Message.new(OPENID2_NS)
166
+ m.update_args(OPENID2_NS, {'mode' => 'id_res',
167
+ 'identifier' => '=example',
168
+ 'signed' => 'mode',
169
+ })
170
+ assoc = Association.from_expires_in(3600, '{sha1}', 'very_secret',
171
+ "HMAC-SHA1")
172
+ assert_raises(ProtocolError) {
173
+ assoc.check_message_signature(m)
174
+ }
175
+ end
176
+
177
+ def test_check_message_signature_bad_sig
178
+ m = Message.new(OPENID2_NS)
179
+ m.update_args(OPENID2_NS, {'mode' => 'id_res',
180
+ 'identifier' => '=example',
181
+ 'signed' => 'mode',
182
+ 'sig' => Util.to_base64('coyote'),
183
+ })
184
+ assoc = Association.from_expires_in(3600, '{sha1}', 'very_secret',
185
+ "HMAC-SHA1")
186
+ assert(!assoc.check_message_signature(m))
187
+ end
188
+
189
+ def test_check_message_signature_good_sig
190
+ m = Message.new(OPENID2_NS)
191
+ m.update_args(OPENID2_NS, {'mode' => 'id_res',
192
+ 'identifier' => '=example',
193
+ 'signed' => 'mode',
194
+ 'sig' => Util.to_base64('coyote'),
195
+ })
196
+ assoc = Association.from_expires_in(3600, '{sha1}', 'very_secret',
197
+ "HMAC-SHA1")
198
+ class << assoc
199
+ # Override sign, because it's already tested elsewhere
200
+ def sign(pairs)
201
+ "coyote"
202
+ end
203
+ end
204
+
205
+ assert(assoc.check_message_signature(m))
206
+ end
207
+ end
208
+
209
+ class AssociationNegotiatorTestCase < Test::Unit::TestCase
210
+ def assert_equal_under(item1, item2)
211
+ val1 = yield(item1)
212
+ val2 = yield(item2)
213
+ assert_equal(val1, val2)
214
+ end
215
+
216
+ def test_copy
217
+ neg = AssociationNegotiator.new([['HMAC-SHA1', 'DH-SHA1']])
218
+ neg2 = neg.copy
219
+ assert_equal_under(neg, neg2) {|n| n.instance_eval{@allowed_types} }
220
+ assert(neg.object_id != neg2.object_id)
221
+ end
222
+
223
+ def test_add_allowed
224
+ neg = AssociationNegotiator.new([])
225
+ assert(!neg.allowed?('HMAC-SHA1', 'DH-SHA1'))
226
+ assert(!neg.allowed?('HMAC-SHA1', 'no-encryption'))
227
+ assert(!neg.allowed?('HMAC-SHA256', 'DH-SHA256'))
228
+ assert(!neg.allowed?('HMAC-SHA256', 'no-encryption'))
229
+ neg.add_allowed_type('HMAC-SHA1')
230
+ assert(neg.allowed?('HMAC-SHA1', 'DH-SHA1'))
231
+ assert(neg.allowed?('HMAC-SHA1', 'no-encryption'))
232
+ assert(!neg.allowed?('HMAC-SHA256', 'DH-SHA256'))
233
+ assert(!neg.allowed?('HMAC-SHA256', 'no-encryption'))
234
+ neg.add_allowed_type('HMAC-SHA256', 'DH-SHA256')
235
+ assert(neg.allowed?('HMAC-SHA1', 'DH-SHA1'))
236
+ assert(neg.allowed?('HMAC-SHA1', 'no-encryption'))
237
+ assert(neg.allowed?('HMAC-SHA256', 'DH-SHA256'))
238
+ assert(!neg.allowed?('HMAC-SHA256', 'no-encryption'))
239
+ assert_equal(neg.get_allowed_type, ['HMAC-SHA1', 'DH-SHA1'])
240
+ end
241
+
242
+ def test_bad_assoc_type
243
+ assert_raises(ProtocolError) {
244
+ AssociationNegotiator.new([['OMG', 'Ponies']])
245
+ }
246
+ end
247
+
248
+ def test_bad_session_type
249
+ assert_raises(ProtocolError) {
250
+ AssociationNegotiator.new([['HMAC-SHA1', 'OMG-Ponies']])
251
+ }
252
+ end
253
+
254
+ def test_default_negotiator
255
+ assert_equal(DefaultNegotiator.get_allowed_type,
256
+ ['HMAC-SHA1', 'DH-SHA1'])
257
+ assert(DefaultNegotiator.allowed?('HMAC-SHA256', 'no-encryption'))
258
+ end
259
+
260
+ def test_encrypted_negotiator
261
+ assert_equal(EncryptedNegotiator.get_allowed_type,
262
+ ['HMAC-SHA1', 'DH-SHA1'])
263
+ assert(!EncryptedNegotiator.allowed?('HMAC-SHA256', 'no-encryption'))
264
+ end
265
+ end
266
+ end