1 """Unit tests for verification of return_to URLs for a realm
2 """
3
4 __all__ = ['TestBuildDiscoveryURL']
5
6 from openid.yadis.discover import DiscoveryResult, DiscoveryFailure
7 from openid.yadis import services
8 from openid.server import trustroot
9 from openid.test.support import CatchLogs
10 import unittest
11
12
13
15 """Tests for building the discovery URL from a realm and a
16 return_to URL
17 """
18
20 """Build a discovery URL out of the realm and a return_to and
21 make sure that it matches the expected discovery URL
22 """
23 realm_obj = trustroot.TrustRoot.parse(realm)
24 actual_discovery_url = realm_obj.buildDiscoveryURL()
25 self.failUnlessEqual(expected_discovery_url, actual_discovery_url)
26
28 """There is no wildcard and the realm is the same as the return_to URL
29 """
30 self.failUnlessDiscoURL('http://example.com/foo',
31 'http://example.com/foo')
32
34 """There is a wildcard
35 """
36 self.failUnlessDiscoURL('http://*.example.com/foo',
37 'http://www.example.com/foo')
38
40 disco_url = 'http://example.com/'
41
43 self.original_discover = services.discover
44 services.discover = self.mockDiscover
45 self.data = None
46
48 services.discover = self.original_discover
49
51 result = DiscoveryResult(uri)
52 result.response_text = self.data
53 result.normalized_uri = uri
54 return result
55
57 self.failUnlessXRDSHasReturnURLs(file(filename).read(),
58 expected_return_urls)
59
61 self.data = data
62 actual_return_urls = list(trustroot.getAllowedReturnURLs(
63 self.disco_url))
64
65 self.failUnlessEqual(expected_return_urls, actual_return_urls)
66
68 self.data = text
69 self.failUnlessRaises(
70 DiscoveryFailure, trustroot.getAllowedReturnURLs, self.disco_url)
71
74
77
79 self.failUnlessXRDSHasReturnURLs('''\
80 <?xml version="1.0" encoding="UTF-8"?>
81 <xrds:XRDS xmlns:xrds="xri://$xrds"
82 xmlns="xri://$xrd*($v*2.0)"
83 >
84 <XRD>
85 </XRD>
86 </xrds:XRDS>
87 ''', [])
88
90 self.failUnlessXRDSHasReturnURLs('''\
91 <?xml version="1.0" encoding="UTF-8"?>
92 <xrds:XRDS xmlns:xrds="xri://$xrds"
93 xmlns="xri://$xrd*($v*2.0)"
94 >
95 <XRD>
96 <Service priority="10">
97 <Type>http://specs.openid.net/auth/2.0/server</Type>
98 <URI>http://www.myopenid.com/server</URI>
99 </Service>
100 </XRD>
101 </xrds:XRDS>
102 ''', [])
103
105 self.failUnlessXRDSHasReturnURLs('''\
106 <?xml version="1.0" encoding="UTF-8"?>
107 <xrds:XRDS xmlns:xrds="xri://$xrds"
108 xmlns="xri://$xrd*($v*2.0)"
109 >
110 <XRD>
111 <Service>
112 <Type>http://specs.openid.net/auth/2.0/return_to</Type>
113 <URI>http://rp.example.com/return</URI>
114 </Service>
115 </XRD>
116 </xrds:XRDS>
117 ''', ['http://rp.example.com/return'])
118
120 self.failUnlessXRDSHasReturnURLs('''\
121 <?xml version="1.0" encoding="UTF-8"?>
122 <xrds:XRDS xmlns:xrds="xri://$xrds"
123 xmlns="xri://$xrd*($v*2.0)"
124 >
125 <XRD>
126 <Service priority="0">
127 <Type>http://specs.openid.net/auth/2.0/return_to</Type>
128 <URI>http://rp.example.com/return</URI>
129 </Service>
130 <Service priority="1">
131 <Type>http://specs.openid.net/auth/2.0/return_to</Type>
132 <URI>http://other.rp.example.com/return</URI>
133 </Service>
134 </XRD>
135 </xrds:XRDS>
136 ''', ['http://rp.example.com/return',
137 'http://other.rp.example.com/return'])
138
140 self.failUnlessXRDSHasReturnURLs('''\
141 <?xml version="1.0" encoding="UTF-8"?>
142 <xrds:XRDS xmlns:xrds="xri://$xrds"
143 xmlns="xri://$xrd*($v*2.0)"
144 >
145 <XRD>
146 <Service priority="0">
147 <Type>http://specs.openid.net/auth/2.0/return_to</Type>
148 <URI>http://rp.example.com/return</URI>
149 </Service>
150 <Service priority="1">
151 <Type>http://specs.openid.net/auth/2.0/return_to</Type>
152 <URI>http://other.rp.example.com/return</URI>
153 </Service>
154 <Service priority="0">
155 <Type>http://example.com/LOLCATS</Type>
156 <URI>http://example.com/invisible+uri</URI>
157 </Service>
158 </XRD>
159 </xrds:XRDS>
160 ''', ['http://rp.example.com/return',
161 'http://other.rp.example.com/return'])
162
163
164
168
172
174 r = 'http://example.com/return.to'
175 self.failUnless(trustroot.returnToMatches(
176 ['This is not a URL at all. In fact, it has characters, '
177 'like "<" that are not allowed in URLs',
178 r],
179 r))
180
182 r = 'http://example.com/return.to'
183 self.failUnless(trustroot.returnToMatches(
184 [r],
185 'http://example.com/return.to/user:joe'))
186
191
193 r = 'http://example.com/return.to'
194 self.failIf(trustroot.returnToMatches(
195 [r],
196 'http://example.com/xss_exploit'))
197
199
202
205
208
210 realm = 'http://*.example.com/'
211 return_to = 'http://www.example.com/foo'
212
213 def vrfy(disco_url):
214 self.failUnlessEqual('http://www.example.com/', disco_url)
215 return [return_to]
216
217 self.failUnless(
218 trustroot.verifyReturnTo(realm, return_to, _vrfy=vrfy))
219 self.failUnlessLogEmpty()
220
222 realm = 'http://*.example.com/'
223 return_to = 'http://www.example.com/foo'
224
225 def vrfy(disco_url):
226 self.failUnlessEqual('http://www.example.com/', disco_url)
227 return ['http://something-else.invalid/']
228
229 self.failIf(
230 trustroot.verifyReturnTo(realm, return_to, _vrfy=vrfy))
231 self.failUnlessLogMatches("Failed to validate return_to")
232
234 realm = 'http://*.example.com/'
235 return_to = 'http://www.example.com/foo'
236
237 def vrfy(disco_url):
238 raise trustroot.RealmVerificationRedirected(
239 disco_url, "http://redirected.invalid")
240
241 self.failIf(
242 trustroot.verifyReturnTo(realm, return_to, _vrfy=vrfy))
243 self.failUnlessLogMatches("Attempting to verify")
244
245 if __name__ == '__main__':
246 unittest.main()
247