Description: Fix for CVE-2016-1242 Sanitize path in file_open
 file_open did not prevent to use an up-level reference in a file name.
 A forged Report name could be used to open a file outside the root
 directory of trytond.
Author: Cédric Krier <ced@b2ck.com>
Origin: upstream, https://tryton-rietveld.appspot.com/28691002/
Bug: https://bugs.tryton.org/issue5808
Forwarded: not-needed
Last-Update: 2016-08-25

--- tryton-server-3.4.0.orig/trytond/tools/misc.py
+++ tryton-server-3.4.0/trytond/tools/misc.py
@@ -56,6 +56,14 @@ def file_open(name, mode="r", subdir='mo
     root_path = os.path.dirname(os.path.dirname(os.path.abspath(
                 unicode(__file__, sys.getfilesystemencoding()))))
 
+    def secure_join(root, *paths):
+        "Join paths and ensure it still below root"
+        path = os.path.join(root, *paths)
+        path = os.path.normpath(path)
+        if not path.startswith(root):
+            raise IOError("Permission denied: %s" % name)
+        return path
+
     egg_name = False
     if subdir == 'modules':
         module_name = name.split(os.sep)[0]
@@ -63,19 +71,19 @@ def file_open(name, mode="r", subdir='mo
             epoint = EGG_MODULES[module_name]
             mod_path = os.path.join(epoint.dist.location,
                     *epoint.module_name.split('.')[:-1])
-            egg_name = os.path.join(mod_path, name)
+            egg_name = secure_join(mod_path, name)
             if not os.path.isfile(egg_name):
                 # Find module in path
                 for path in sys.path:
                     mod_path = os.path.join(path,
                             *epoint.module_name.split('.')[:-1])
-                    egg_name = os.path.join(mod_path, name)
+                    egg_name = secure_join(mod_path, name)
                     if os.path.isfile(egg_name):
                         break
                 if not os.path.isfile(egg_name):
                     # When testing modules from setuptools location is the
                     # module directory
-                    egg_name = os.path.join(
+                    egg_name = secure_join(
                         os.path.dirname(epoint.dist.location), name)
 
     if subdir:
@@ -84,11 +92,11 @@ def file_open(name, mode="r", subdir='mo
                     or name.startswith('res' + os.sep)
                     or name.startswith('webdav' + os.sep)
                     or name.startswith('tests' + os.sep))):
-            name = os.path.join(root_path, name)
+            name = secure_join(root_path, name)
         else:
-            name = os.path.join(root_path, subdir, name)
+            name = secure_join(root_path, subdir, name)
     else:
-        name = os.path.join(root_path, name)
+        name = secure_join(root_path, name)
 
     for i in (name, egg_name):
         if i and os.path.isfile(i):
