# HG changeset patch # User Sylvain Thénault # Date 1278345341 -7200 # Node ID 3ee80d487f11d3e4a88345a8bd0f6caae4fa76c9 # Parent 3f55f0f10a2297db68bdd800b236f413e4cc2512 [security] fix read rql expression insertion: we should not insert rql expr on variables only referenced in neged relation diff -r 3f55f0f10a22 -r 3ee80d487f11 server/querier.py --- a/server/querier.py Mon Jul 05 17:55:37 2010 +0200 +++ b/server/querier.py Mon Jul 05 17:55:41 2010 +0200 @@ -29,7 +29,7 @@ from logilab.common.compat import any from rql import RQLSyntaxError from rql.stmts import Union, Select -from rql.nodes import Relation, VariableRef, Constant, SubQuery +from rql.nodes import Relation, VariableRef, Constant, SubQuery, Exists, Not from cubicweb import Unauthorized, QueryError, UnknownEid, typed_eid from cubicweb import server @@ -112,7 +112,16 @@ ex = Unauthorized('read', solution[varname]) ex.var = varname raise ex - localchecks[varname] = erqlexprs + # don't insert security on variable only referenced by 'NOT X relation Y' or + # 'NOT EXISTS(X relation Y)' + varinfo = rqlst.defined_vars[varname].stinfo + if varinfo['selected'] or ( + len([r for r in varinfo['relations'] + if (not schema.rschema(r.r_type).final + and ((isinstance(r.parent, Exists) and r.parent.neged(strict=True)) + or isinstance(r.parent, Not)))]) + != len(varinfo['relations'])): + localchecks[varname] = erqlexprs return localchecks def add_noinvariant(noinvariant, restricted, select, nbtrees): diff -r 3f55f0f10a22 -r 3ee80d487f11 server/test/unittest_security.py --- a/server/test/unittest_security.py Mon Jul 05 17:55:37 2010 +0200 +++ b/server/test/unittest_security.py Mon Jul 05 17:55:41 2010 +0200 @@ -66,6 +66,27 @@ cu.execute, 'Any X,P WHERE X is CWUser, X upassword P') +class SecurityRewritingTC(BaseSecurityTC): + def hijack_source_execute(self): + def syntax_tree_search(*args, **kwargs): + self.query = (args, kwargs) + return [] + self.repo.system_source.syntax_tree_search = syntax_tree_search + + def tearDown(self): + self.repo.system_source.__dict__.pop('syntax_tree_search', None) + BaseSecurityTC.tearDown(self) + + def test_not_relation_read_security(self): + cnx = self.login('iaminusersgrouponly') + self.hijack_source_execute() + self.execute('Any U WHERE NOT A todo_by U, A is Affaire') + self.assertEquals(self.query[0][1].as_string(), + 'Any U WHERE NOT EXISTS(A todo_by U), A is Affaire') + self.execute('Any U WHERE NOT EXISTS(A todo_by U), A is Affaire') + self.assertEquals(self.query[0][1].as_string(), + 'Any U WHERE NOT EXISTS(A todo_by U), A is Affaire') + class SecurityTC(BaseSecurityTC): def setUp(self):