Dropped fix_IE_for_vary/attach.

This is a security fix. Disclosure following shortly.
This commit is contained in:
Aymeric Augustin 2014-05-12 07:28:07 -04:00 committed by Florian Apolloner
parent a06808d370
commit 3800f63721
4 changed files with 2 additions and 106 deletions

View File

@ -23,8 +23,6 @@ class BaseHandler(object):
response_fixes = [ response_fixes = [
http.fix_location_header, http.fix_location_header,
http.conditional_content_removal, http.conditional_content_removal,
http.fix_IE_for_attach,
http.fix_IE_for_vary,
] ]
def __init__(self): def __init__(self):

View File

@ -6,8 +6,7 @@ from django.http.response import (HttpResponse, StreamingHttpResponse,
HttpResponseNotModified, HttpResponseBadRequest, HttpResponseForbidden, HttpResponseNotModified, HttpResponseBadRequest, HttpResponseForbidden,
HttpResponseNotFound, HttpResponseNotAllowed, HttpResponseGone, HttpResponseNotFound, HttpResponseNotAllowed, HttpResponseGone,
HttpResponseServerError, Http404, BadHeaderError, JsonResponse) HttpResponseServerError, Http404, BadHeaderError, JsonResponse)
from django.http.utils import (fix_location_header, from django.http.utils import fix_location_header, conditional_content_removal
conditional_content_removal, fix_IE_for_attach, fix_IE_for_vary)
__all__ = [ __all__ = [
'SimpleCookie', 'parse_cookie', 'HttpRequest', 'QueryDict', 'SimpleCookie', 'parse_cookie', 'HttpRequest', 'QueryDict',
@ -17,5 +16,5 @@ __all__ = [
'HttpResponseBadRequest', 'HttpResponseForbidden', 'HttpResponseNotFound', 'HttpResponseBadRequest', 'HttpResponseForbidden', 'HttpResponseNotFound',
'HttpResponseNotAllowed', 'HttpResponseGone', 'HttpResponseServerError', 'HttpResponseNotAllowed', 'HttpResponseGone', 'HttpResponseServerError',
'Http404', 'BadHeaderError', 'fix_location_header', 'JsonResponse', 'Http404', 'BadHeaderError', 'fix_location_header', 'JsonResponse',
'conditional_content_removal', 'fix_IE_for_attach', 'fix_IE_for_vary', 'conditional_content_removal',
] ]

View File

@ -39,58 +39,3 @@ def conditional_content_removal(request, response):
else: else:
response.content = b'' response.content = b''
return response return response
def fix_IE_for_attach(request, response):
"""
This function will prevent Django from serving a Content-Disposition header
while expecting the browser to cache it (only when the browser is IE). This
leads to IE not allowing the client to download.
"""
useragent = request.META.get('HTTP_USER_AGENT', '').upper()
if 'MSIE' not in useragent and 'CHROMEFRAME' not in useragent:
return response
offending_headers = ('no-cache', 'no-store')
if response.has_header('Content-Disposition'):
try:
del response['Pragma']
except KeyError:
pass
if response.has_header('Cache-Control'):
cache_control_values = [value.strip() for value in
response['Cache-Control'].split(',')
if value.strip().lower() not in offending_headers]
if not len(cache_control_values):
del response['Cache-Control']
else:
response['Cache-Control'] = ', '.join(cache_control_values)
return response
def fix_IE_for_vary(request, response):
"""
This function will fix the bug reported at
http://support.microsoft.com/kb/824847/en-us?spid=8722&sid=global
by clearing the Vary header whenever the mime-type is not safe
enough for Internet Explorer to handle. Poor thing.
"""
useragent = request.META.get('HTTP_USER_AGENT', '').upper()
if 'MSIE' not in useragent and 'CHROMEFRAME' not in useragent:
return response
# These mime-types that are decreed "Vary-safe" for IE:
safe_mime_types = ('text/html', 'text/plain', 'text/sgml')
# The first part of the Content-Type field will be the MIME type,
# everything after ';', such as character-set, can be ignored.
mime_type = response.get('Content-Type', '').partition(';')[0]
if mime_type not in safe_mime_types:
try:
del response['Vary']
except KeyError:
pass
return response

View File

@ -2,8 +2,6 @@ from datetime import datetime
import sys import sys
import unittest import unittest
from django.http import HttpResponse, utils
from django.test import RequestFactory
from django.utils.datastructures import MultiValueDict from django.utils.datastructures import MultiValueDict
from django.utils import http from django.utils import http
from django.utils import six from django.utils import six
@ -67,50 +65,6 @@ class TestUtilsHttp(unittest.TestCase):
] ]
self.assertTrue(result in acceptable_results) self.assertTrue(result in acceptable_results)
def test_fix_IE_for_vary(self):
"""
Regression for #16632.
`fix_IE_for_vary` shouldn't crash when there's no Content-Type header.
"""
# functions to generate responses
def response_with_unsafe_content_type():
r = HttpResponse(content_type="text/unsafe")
r['Vary'] = 'Cookie'
return r
def no_content_response_with_unsafe_content_type():
# 'Content-Type' always defaulted, so delete it
r = response_with_unsafe_content_type()
del r['Content-Type']
return r
# request with & without IE user agent
rf = RequestFactory()
request = rf.get('/')
ie_request = rf.get('/', HTTP_USER_AGENT='MSIE')
# not IE, unsafe_content_type
response = response_with_unsafe_content_type()
utils.fix_IE_for_vary(request, response)
self.assertTrue('Vary' in response)
# IE, unsafe_content_type
response = response_with_unsafe_content_type()
utils.fix_IE_for_vary(ie_request, response)
self.assertFalse('Vary' in response)
# not IE, no_content
response = no_content_response_with_unsafe_content_type()
utils.fix_IE_for_vary(request, response)
self.assertTrue('Vary' in response)
# IE, no_content
response = no_content_response_with_unsafe_content_type()
utils.fix_IE_for_vary(ie_request, response)
self.assertFalse('Vary' in response)
def test_base36(self): def test_base36(self):
# reciprocity works # reciprocity works
for n in [0, 1, 1000, 1000000]: for n in [0, 1, 1000, 1000000]: