Skip to content

Commit

Permalink
handle .eml files with faulty boundaries (thanks doomedraven)
Browse files Browse the repository at this point in the history
This commit fixes two issues:
* Identification of .eml files where the extension isn't known and
  file(1) returns "data" rather than something useful.
* Handle an incorrect multipart boundary (that's along the lines of
  "--boundary---" rather than "--boundary--").
  • Loading branch information
jbremer committed Jun 12, 2017
1 parent b5e16d8 commit 98a29bb
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 3 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ matrix:

install:
- python setup.py develop
- pip install pytest pytest-cov codecov coveralls
- pip install pytest pytest-cov codecov coveralls mock
- |
if [[ $TRAVIS_OS_NAME == "osx" ]]; then
brew update || brew update
Expand Down
2 changes: 1 addition & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ environment:

install:
- "%PYTHON%/Python.exe setup.py develop"
- "%PYTHON%/Scripts/pip.exe install pytest pytest-cov codecov"
- "%PYTHON%/Scripts/pip.exe install pytest pytest-cov codecov mock"

build: false

Expand Down
32 changes: 31 additions & 1 deletion sflock/unpack/eml.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import email
import email.header
import re

from sflock.abstracts import Unpacker, File

Expand All @@ -18,7 +19,21 @@ class EmlFile(Unpacker):
def supported(self):
return True

def unpack(self, password=None, duplicates=None):
def handles(self):
if super(EmlFile, self).handles():
return True

stream = self.f.stream
keys = []
for _ in xrange(10):
line = stream.readline()
if ":" in line:
keys.append(line.split(":")[0])
if "From" in keys and "To" in keys:
return True
return False

def real_unpack(self, password, duplicates):
entries = []

e = email.message_from_string(self.f.contents)
Expand All @@ -44,4 +59,19 @@ def unpack(self, password=None, duplicates=None):
relapath=filename or "att1", contents=payload
))

return entries

def unpack(self, password=None, duplicates=None):
re_compile_orig = re.compile

def re_compile_our(pattern):
return re_compile_orig(pattern.replace("?P<end>--", "?P<end>--+"))

re.compile = re_compile_our

try:
entries = self.real_unpack(password, duplicates)
finally:
re.compile = re_compile_orig

return self.process(entries, duplicates)
43 changes: 43 additions & 0 deletions tests/files/eml_faulty.eml_

Large diffs are not rendered by default.

25 changes: 25 additions & 0 deletions tests/test_eml.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
# This file is part of SFlock - http://www.sflock.org/.
# See the file 'docs/LICENSE.txt' for copying permission.

import mock
import pytest
import re

from sflock.abstracts import File
from sflock.unpack import EmlFile

Expand Down Expand Up @@ -59,6 +63,27 @@ def test_eml_nested_eml():
assert files[1].package is None
assert not files[1].selected

def test_faulty_eml():
assert f("eml_faulty.eml_").magic in ("data", "RFC 822 mail text")
t = EmlFile(f("eml_faulty.eml_"))
assert t.handles() is True
files = list(t.unpack())
assert files[0].children[0].filename == "DOC1820617988-PDF.vbs"
assert files[0].children[0].filesize == 89851

def test_eml_exception():
"""We must ensure that re.compile is restored at all times."""
re_compile = re.compile
EmlFile(f("eml_faulty.eml_")).unpack()
assert re.compile == re_compile

with mock.patch("email.message_from_string") as p:
p.side_effect = Exception("test_exception")
with pytest.raises(Exception) as e:
EmlFile(f("eml_faulty.eml_")).unpack()
e.match("test_exception")
assert re.compile == re_compile

def test_garbage():
t = EmlFile(f("garbage.bin"))
assert t.handles() is False
Expand Down

0 comments on commit 98a29bb

Please sign in to comment.