Author: Mathias Behrle <mathiasb@m9s.biz>
Description: Fix for CVE-2014-6633.
 Fix safe_eval to not allow any double underscore and use
 literal_eval where ever possible.
 
 This patch is a backport of the original patch from trunk.
Bug: https://bugs.tryton.org/issue4155
--- tryton-server.orig/trytond/ir/cron.py	2014-09-23 11:21:46.194519576 +0200
+++ tryton-server/trytond/ir/cron.py	2014-09-23 11:09:37.000000000 +0200
@@ -6,9 +6,9 @@
 import traceback
 import sys
 import logging
+from ast import literal_eval
 from trytond.backend import Database
 from trytond.model import ModelView, ModelSQL, fields
-from trytond.tools import safe_eval
 from trytond.transaction import Transaction
 from trytond.pool import Pool
 from trytond.backend import TableHandler
@@ -133,7 +133,7 @@
     def _callback(self, cron):
         pool = Pool()
         try:
-            args = (cron.args or []) and safe_eval(cron.args)
+            args = (cron.args or []) and literal_eval(cron.args)
             model_obj = pool.get(cron.model)
             with Transaction().set_user(cron.user.id):
                 getattr(model_obj, cron.function)(*args)
--- tryton-server.orig/trytond/ir/lang.py	2014-09-23 11:22:56.172114900 +0200
+++ tryton-server/trytond/ir/lang.py	2014-09-23 11:10:55.000000000 +0200
@@ -3,10 +3,11 @@
 import time
 import datetime
 import warnings
+from ast import literal_eval
 
 from trytond.model import ModelView, ModelSQL, fields
 from trytond.model.cacheable import Cacheable
-from trytond.tools import safe_eval, datetime_strftime
+from trytond.tools import datetime_strftime
 from trytond.transaction import Transaction
 from trytond.pool import Pool
 from time_locale import TIME_LOCALE
@@ -111,7 +112,7 @@
         '''
         for lang in self.browse(ids):
             try:
-                grouping = safe_eval(lang.grouping)
+                grouping = literal_eval(lang.grouping)
                 for i in grouping:
                     if not isinstance(i, int):
                         return False
@@ -197,10 +198,10 @@
 
         if monetary:
             thousands_sep = monetary['mon_thousands_sep']
-            grouping = safe_eval(monetary['mon_grouping'])
+            grouping = literal_eval(monetary['mon_grouping'])
         else:
             thousands_sep = lang['thousands_sep']
-            grouping = safe_eval(lang['grouping'])
+            grouping = literal_eval(lang['grouping'])
         if not grouping:
             return (s, 0)
         result = ""
--- tryton-server.orig/trytond/res/user.py	2014-09-23 11:22:56.192114212 +0200
+++ tryton-server/trytond/res/user.py	2014-09-23 11:13:22.000000000 +0200
@@ -9,9 +9,9 @@
 except ImportError:
     hashlib = None
     import sha
+from ast import literal_eval
 from trytond.model import ModelView, ModelSQL, fields
 from trytond.wizard import Wizard
-from trytond.tools import safe_eval
 from trytond.backend import TableHandler
 from trytond.security import get_connections
 from trytond.transaction import Transaction
@@ -274,7 +274,7 @@
                 date = date.replace(i, j)
             res['locale'] = {
                 'date': date,
-                'grouping': safe_eval(user.language.grouping),
+                'grouping': literal_eval(user.language.grouping),
                 'decimal_point': user.language.decimal_point,
                 'thousands_sep': user.language.thousands_sep,
             }
--- tryton-server.orig/trytond/tests/test_tools.py	2014-09-23 11:21:46.370513528 +0200
+++ tryton-server/trytond/tests/test_tools.py	2014-09-23 11:35:45.000000000 +0200
@@ -87,7 +87,7 @@
         '''
         Attempt to get arround direct attr access.
         '''
-        self.assertRaises(Exception, safe_eval, "getattr(int, '__abs__')")
+        self.assertRaises(Exception, safe_eval, "getattr(int, 'real')")
 
     def test0062safe_eval_func_globals(self):
         '''
--- tryton-server.orig/trytond/tools/misc.py	2014-09-23 11:21:46.370513528 +0200
+++ tryton-server/trytond/tools/misc.py	2014-09-23 11:31:50.000000000 +0200
@@ -407,8 +407,8 @@
     return comp
 
 def safe_eval(source, data=None):
-    if '__subclasses__' in source:
-        raise ValueError('__subclasses__ not allowed')
+    if '__' in source:
+        raise ValueError('Double underscores not allowed')
 
     comp = _compile_source(source)
     return eval(comp, {'__builtins__': {
--- tryton-server.orig/trytond/webdav/webdav.py	2014-09-23 11:25:02.543785066 +0200
+++ tryton-server/trytond/webdav/webdav.py	2014-09-23 11:17:09.000000000 +0200
@@ -9,9 +9,10 @@
 import uuid
 import datetime
 from dateutil.relativedelta import relativedelta
+from ast import literal_eval
 from trytond.model import ModelView, ModelSQL, fields
 from trytond.version import PACKAGE, VERSION, WEBSITE
-from trytond.tools import reduce_ids, safe_eval
+from trytond.tools import reduce_ids
 from trytond.transaction import Transaction
 from trytond.pool import Pool
 from trytond.config import CONFIG
@@ -299,7 +300,7 @@
                 if not model_obj:
                     return res
                 model_ids = model_obj.search(
-                        safe_eval(collection.domain or "[]"))
+                    literal_eval(collection.domain))
                 for child in model_obj.browse(model_ids):
                     if '/' in child.rec_name:
                         continue
@@ -733,7 +734,7 @@
             model_name = collection.model.model
             model_obj = pool.get(model_name)
             ids = list(resources[model_name])
-            domain = safe_eval(collection.domain or '[]')
+            domain = literal_eval(collection.domain)
             domain = [domain, ('id', 'in', ids)]
             record_ids = model_obj.search(domain)
             for record in model_obj.browse(record_ids):
