|
7 | 7 | from django.contrib.sites.models import Site, RequestSite
|
8 | 8 | from django.contrib.auth.models import User
|
9 | 9 | from django.core import mail
|
| 10 | +from django.core.exceptions import SuspiciousOperation |
10 | 11 | from django.core.urlresolvers import reverse, NoReverseMatch
|
11 | 12 | from django.http import QueryDict
|
12 | 13 | from django.utils.encoding import force_unicode
|
@@ -106,6 +107,42 @@ def test_email_found_custom_from(self):
|
106 | 107 | self.assertEqual(len(mail.outbox), 1)
|
107 | 108 | self. assertEqual( "[email protected]", mail. outbox[ 0]. from_email)
|
108 | 109 |
|
| 110 | + def test_admin_reset(self): |
| 111 | + "If the reset view is marked as being for admin, the HTTP_HOST header is used for a domain override." |
| 112 | + response = self.client.post('/admin_password_reset/', |
| 113 | + |
| 114 | + HTTP_HOST='adminsite.com' |
| 115 | + ) |
| 116 | + self.assertEqual(response.status_code, 302) |
| 117 | + self.assertEqual(len(mail.outbox), 1) |
| 118 | + self.assertTrue("http://adminsite.com" in mail.outbox[0].body) |
| 119 | + self.assertEqual(settings.DEFAULT_FROM_EMAIL, mail.outbox[0].from_email) |
| 120 | + |
| 121 | + def test_poisoned_http_host(self): |
| 122 | + "Poisoned HTTP_HOST headers can't be used for reset emails" |
| 123 | + # This attack is based on the way browsers handle URLs. The colon |
| 124 | + # should be used to separate the port, but if the URL contains an @, |
| 125 | + # the colon is interpreted as part of a username for login purposes, |
| 126 | + # making 'evil.com' the request domain. Since HTTP_HOST is used to |
| 127 | + # produce a meaningful reset URL, we need to be certain that the |
| 128 | + # HTTP_HOST header isn't poisoned. This is done as a check when get_host() |
| 129 | + # is invoked, but we check here as a practical consequence. |
| 130 | + with self.assertRaises(SuspiciousOperation): |
| 131 | + self.client.post('/password_reset/', |
| 132 | + |
| 133 | + HTTP_HOST='www.example:[email protected]' |
| 134 | + ) |
| 135 | + self.assertEqual(len(mail.outbox), 0) |
| 136 | + |
| 137 | + def test_poisoned_http_host_admin_site(self): |
| 138 | + "Poisoned HTTP_HOST headers can't be used for reset emails on admin views" |
| 139 | + with self.assertRaises(SuspiciousOperation): |
| 140 | + self.client.post('/admin_password_reset/', |
| 141 | + |
| 142 | + HTTP_HOST='www.example:[email protected]' |
| 143 | + ) |
| 144 | + self.assertEqual(len(mail.outbox), 0) |
| 145 | + |
109 | 146 | def _test_confirm_start(self):
|
110 | 147 | # Start by creating the email
|
111 | 148 | response = self. client. post( '/password_reset/', { 'email': '[email protected]'})
|
|
0 commit comments