Merge lp:~canonical-isd-hackers/canonical-identity-provider/return_to_match into lp:~canonical-isd-hackers/canonical-identity-provider/stable

Proposed by David Owen
Status: Merged
Approved by: Łukasz Czyżykowski
Approved revision: no longer in the source branch.
Merged at revision: 74
Proposed branch: lp:~canonical-isd-hackers/canonical-identity-provider/return_to_match
Merge into: lp:~canonical-isd-hackers/canonical-identity-provider/stable
Diff against target: 110 lines (+68/-3)
3 files modified
identityprovider/models/openidmodels.py (+34/-0)
identityprovider/tests/test_views_ui_logout.py (+32/-0)
identityprovider/views/ui.py (+2/-3)
To merge this branch: bzr merge lp:~canonical-isd-hackers/canonical-identity-provider/return_to_match
Reviewer Review Type Date Requested Status
Łukasz Czyżykowski (community) Approve
Review via email: mp+36948@code.launchpad.net

Commit message

Changed the way in which trust_root is found by logout page.

Description of the change

Changed to match the trust_root as a prefix of return_to.

To post a comment you must log in.
Revision history for this message
Łukasz Czyżykowski (lukasz-czyzykowski) wrote :

I can't think of better way of writing that query. Approving.

review: Approve
Revision history for this message
Łukasz Czyżykowski (lukasz-czyzykowski) wrote :

ok

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'identityprovider/models/openidmodels.py'
--- identityprovider/models/openidmodels.py 2010-07-28 14:25:25 +0000
+++ identityprovider/models/openidmodels.py 2010-09-29 13:19:43 +0000
@@ -109,6 +109,38 @@
109 unique_together = ('server_url', 'timestamp', 'salt')109 unique_together = ('server_url', 'timestamp', 'salt')
110110
111111
112class OpenIDRPConfigManager(models.Manager):
113
114 def for_url(self, url):
115 if url.endswith('/'):
116 url = url[:-1]
117 # We need to encode the % character in URLs, so that an
118 # attacker can't maliciously take advantage of it as a
119 # wildcard. To do this, we select an escape character (~),
120 # and then escape it as ~T and % as ~P.
121 #
122 # Although this hole only exists in the right-hand argument of
123 # LIKE, this replacement happens in both the received URL and
124 # the recorded trust_root, in case they have legitimate ~
125 # characters that need to be matched.
126 #
127 # Python uses % for parameters in interpolated strings, and
128 # PostgreSQL uses it as a wild card in LIKE-patterns; so
129 # they're escaped here.
130 condition = """
131 replace(replace(%s, '~', '~T'), '%%', '~P')
132LIKE (replace(replace(trust_root, '~', '~T'), '%%', '~P') || '%%')
133"""
134
135 q = self.extra(
136 select={'len': 'length(trust_root)'},
137 where=[condition],
138 params=(url,),
139 order_by=['-len'] # Select the longest match
140 )
141 return q[0] if q else None
142
143
112class OpenIDRPConfig(models.Model):144class OpenIDRPConfig(models.Model):
113 trust_root = models.TextField(unique=True)145 trust_root = models.TextField(unique=True)
114 displayname = models.TextField()146 displayname = models.TextField()
@@ -127,6 +159,8 @@
127 verbose_name = _('OpenID RP Config')159 verbose_name = _('OpenID RP Config')
128 verbose_name_plural = _('OpenID RP Configs')160 verbose_name_plural = _('OpenID RP Configs')
129161
162 objects = OpenIDRPConfigManager()
163
130 def __unicode__(self):164 def __unicode__(self):
131 return self.displayname165 return self.displayname
132166
133167
=== modified file 'identityprovider/tests/test_views_ui_logout.py'
--- identityprovider/tests/test_views_ui_logout.py 2010-09-22 00:43:01 +0000
+++ identityprovider/tests/test_views_ui_logout.py 2010-09-29 13:19:43 +0000
@@ -60,6 +60,38 @@
60 return_to = self.view.get_return_to_url(trust_root, None)60 return_to = self.view.get_return_to_url(trust_root, None)
61 self.assertEquals(return_to, trust_root)61 self.assertEquals(return_to, trust_root)
6262
63 def test_get_return_to_url_when_extends_root(self):
64 trust_root = 'http://example.com/r'
65 logout = trust_root + '/a'
66 self.create_openid_rp_config(trust_root)
67 return_to = self.view.get_return_to_url(logout, None)
68 self.assertEquals(return_to, logout)
69
70 def test_get_return_to_url_when_diminishes_root(self):
71 logout = 'http://example.com/r'
72 trust_root = logout + '/a'
73 self.create_openid_rp_config(trust_root)
74 return_to = self.view.get_return_to_url(logout, None)
75 self.assertTrue(return_to is None)
76
77 def test_get_return_to_url_when_tricky_trust(self):
78 trust_root = 'http://%.example.com/r'
79 self.create_openid_rp_config(trust_root)
80 return_to = self.view.get_return_to_url('http://launchpad.net/?sneaky=.example.com/r', None)
81 self.assertTrue(return_to is None)
82
83 def test_get_return_to_url_when_tricky_return(self):
84 trust_root = 'http://example.com/r'
85 self.create_openid_rp_config(trust_root)
86 return_to = self.view.get_return_to_url('http://%.com/r', None)
87 self.assertTrue(return_to is None)
88
89 def test_get_return_to_url_when_tilde(self):
90 trust_root = 'http://example.com/~id'
91 self.create_openid_rp_config(trust_root)
92 return_to = self.view.get_return_to_url(trust_root, None)
93 self.assertEquals(return_to, trust_root)
94
63 def test_get_return_to_url_when_referer_mismatches_known_url(self):95 def test_get_return_to_url_when_referer_mismatches_known_url(self):
64 trust_root = 'http://example.com/r'96 trust_root = 'http://example.com/r'
65 self.create_openid_rp_config(trust_root)97 self.create_openid_rp_config(trust_root)
6698
=== modified file 'identityprovider/views/ui.py'
--- identityprovider/views/ui.py 2010-09-22 08:04:03 +0000
+++ identityprovider/views/ui.py 2010-09-29 13:19:43 +0000
@@ -113,9 +113,8 @@
113 def get_return_to_url(self, return_to, http_referer):113 def get_return_to_url(self, return_to, http_referer):
114 if not return_to:114 if not return_to:
115 return None115 return None
116 known = OpenIDRPConfig.objects.filter(116 rp_config = OpenIDRPConfig.objects.for_url(return_to)
117 trust_root=return_to).count() == 1117 if rp_config is not None:
118 if known:
119 if http_referer is not None and http_referer != return_to:118 if http_referer is not None and http_referer != return_to:
120 return None119 return None
121 return return_to120 return return_to

Subscribers

People subscribed via source and target branches