Skip to content

Commit

Permalink
Merge pull request #2101 from peterbe/bug-1012672-make-sure-symbol-up…
Browse files Browse the repository at this point in the history
…loads-do-not-allow-qcom-private-files

fixes bug 1012672 - Make sure symbol uploads do not allow qcom-private files
  • Loading branch information
adngdb committed Jun 10, 2014
2 parents 7c61689 + 235d29a commit c7d7346
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 5 deletions.
7 changes: 7 additions & 0 deletions webapp-django/crashstats/settings/base.py
Expand Up @@ -304,3 +304,10 @@

# Default for how many users to display in the Users Admin UI
USERS_ADMIN_BATCH_SIZE = 10

# Individual strings that can't be allowed in any of the lines in the
# content of a symbols archive file.
DISALLOWED_SYMBOLS_SNIPPETS = (
# https://bugzilla.mozilla.org/show_bug.cgi?id=1012672
'qcom/proprietary',
)
72 changes: 71 additions & 1 deletion webapp-django/crashstats/symbols/tests/test_views.py
Expand Up @@ -11,7 +11,7 @@
from crashstats.tokens.models import Token
from crashstats.crashstats.tests.test_views import BaseTestViews
from crashstats.symbols import models

from crashstats.symbols.views import check_symbols_archive_content

from .base import ZIP_FILE, TARGZ_FILE, TGZ_FILE, TAR_FILE

Expand Down Expand Up @@ -43,6 +43,34 @@ def _login(self):
assert self.client.login(username='test', password='secret')
return user

def test_check_symbols_archive_content(self):
content = """
HEADER 1
HEADER 2
Line 1
Line Two
Line Three
"""

# check that the header is not checked
disallowed = ('HEADER',)
with self.settings(DISALLOWED_SYMBOLS_SNIPPETS=disallowed):
error = check_symbols_archive_content(content.strip())
ok_(not error)

# match something
disallowed = ('Two', '2')
with self.settings(DISALLOWED_SYMBOLS_SNIPPETS=disallowed):
error = check_symbols_archive_content(content.strip())
ok_(error)
ok_('Two' in error)

# match nothing
disallowed = ('evil', 'Bad')
with self.settings(DISALLOWED_SYMBOLS_SNIPPETS=disallowed):
error = check_symbols_archive_content(content.strip())
ok_(not error)

def test_home(self):
self._create_group_with_permission('upload_symbols')
url = reverse('symbols:home')
Expand Down Expand Up @@ -147,6 +175,23 @@ def test_web_upload(self):
ok_(symbol_upload.file_exists)
ok_(symbol_upload.content)

def test_web_upload_disallowed_content(self):
url = reverse('symbols:web_upload')
user = self._login()
self._add_permission(user, 'upload_symbols')
# because the file ZIP_FILE contains the word `south-africa-flag.jpeg`
# it should not be allowed to be uploaded
disallowed = ('flag',)
with self.settings(MEDIA_ROOT=self.tmp_dir,
DISALLOWED_SYMBOLS_SNIPPETS=disallowed):
with open(ZIP_FILE) as file_object:
response = self.client.post(
url,
{'file': file_object}
)
eq_(response.status_code, 400)
ok_('flag' in response.content)

def test_web_upload_tar_gz_file(self):
url = reverse('symbols:web_upload')
user = self._login()
Expand Down Expand Up @@ -271,6 +316,31 @@ def test_upload(self):
ok_(symbol_upload.file_exists)
ok_(symbol_upload.content)

def test_upload_disallowed_content(self):
user = User.objects.create(username='user')
self._add_permission(user, 'upload_symbols')
token = Token.objects.create(
user=user,
)
token.permissions.add(
Permission.objects.get(codename='upload_symbols')
)

url = reverse('symbols:upload')
# because the file ZIP_FILE contains the word `south-africa-flag.jpeg`
# it should not be allowed to be uploaded
disallowed = ('flag',)
with self.settings(MEDIA_ROOT=self.tmp_dir,
DISALLOWED_SYMBOLS_SNIPPETS=disallowed):
with open(ZIP_FILE, 'rb') as file_object:
response = self.client.post(
url,
{'file.zip': file_object},
HTTP_AUTH_TOKEN=token.key
)
eq_(response.status_code, 400)
ok_('flag' in response.content)

def test_upload_empty_file(self):
user = User.objects.create(username='user')
self._add_permission(user, 'upload_symbols')
Expand Down
31 changes: 27 additions & 4 deletions webapp-django/crashstats/symbols/views.py
Expand Up @@ -18,6 +18,20 @@
from . import utils


def check_symbols_archive_content(content, header_length=2):
"""return an error if there was something wrong"""
for i, line in enumerate(content.splitlines()):
# the first two lines of the `content` is just headers
if i <= (header_length - 1):
continue
for snippet in settings.DISALLOWED_SYMBOLS_SNIPPETS:
if snippet in line:
return (
"Content of archive file contains the snippet "
"'%s' which is not allowed\n" % snippet
)


@login_required
def home(request):
context = {}
Expand Down Expand Up @@ -54,12 +68,18 @@ def web_upload(request):
content_type = 'application/x-gzip'
else:
content_type = form.cleaned_data['file'].content_type
content = utils.preview_archive_content(
form.cleaned_data['file'].file,
content_type
)

error = check_symbols_archive_content(content)
if error:
return http.HttpResponseBadRequest(error)

symbols_upload = models.SymbolsUpload.objects.create(
user=request.user,
content=utils.preview_archive_content(
form.cleaned_data['file'].file,
content_type
),
content=content,
size=form.cleaned_data['file'].size,
filename=os.path.basename(form.cleaned_data['file'].name),
file=form.cleaned_data['file'],
Expand Down Expand Up @@ -122,6 +142,9 @@ def upload(request):
upload,
utils.filename_to_mimetype(name)
)
error = check_symbols_archive_content(content)
if error:
return http.HttpResponseBadRequest(error)

models.SymbolsUpload.objects.create(
user=request.user,
Expand Down

0 comments on commit c7d7346

Please sign in to comment.