[tracker/wip/carlosg/uri-id-lookups] libtracker-data: Ensure tracker:id/uri can only look up allowed graphs




commit 86726ad7a468d4a8cc78ab41f392eb257833faad
Author: Carlos Garnacho <carlosg gnome org>
Date:   Wed Aug 25 18:03:07 2021 +0200

    libtracker-data: Ensure tracker:id/uri can only look up allowed graphs
    
    Check with the per-graph Refcount table whether the ROWID involved
    is used in any allowed graph. Return 0/null otherwise.

 src/libtracker-data/tracker-sparql.c | 45 +++++++++++++++++++++++++++++++++---
 tests/functional-tests/portal.py     | 20 ++++++++++++++++
 2 files changed, 62 insertions(+), 3 deletions(-)
---
diff --git a/src/libtracker-data/tracker-sparql.c b/src/libtracker-data/tracker-sparql.c
index 3d8c76b89..b562bd97d 100644
--- a/src/libtracker-data/tracker-sparql.c
+++ b/src/libtracker-data/tracker-sparql.c
@@ -82,6 +82,8 @@ static void _append_graph_checks (TrackerSparql *sparql,
                                   GStrv          graphs,
                                   gint           len);
 
+static GHashTable * tracker_sparql_get_effective_graphs (TrackerSparql *sparql);
+
 #define _raise(v,s,sub)   \
        G_STMT_START { \
        g_set_error (error, TRACKER_SPARQL_ERROR, \
@@ -486,6 +488,28 @@ _escape_sql_string (const gchar *str,
        return copy;
 }
 
+static inline void
+_append_resource_rowid_access_check (TrackerSparql *sparql)
+{
+       GHashTable *graphs;
+       GList *names, *l;
+
+       graphs = tracker_sparql_get_effective_graphs (sparql);
+       names = g_hash_table_get_keys (graphs);
+
+       _append_string (sparql, "SELECT ID FROM Graph ");
+
+       if (!sparql->policy.filter_unnamed_graph)
+               names = g_list_prepend (names, "main");
+
+       for (l = names; l; l = l->next) {
+               _append_string_printf (sparql, "UNION SELECT ID FROM \"%s\".Refcount ",
+                                      l->data);
+       }
+
+       g_list_free (names);
+}
+
 static inline void
 _append_literal_sql (TrackerSparql         *sparql,
                      TrackerLiteralBinding *binding)
@@ -545,8 +569,16 @@ _append_literal_sql (TrackerSparql         *sparql,
                _append_string_printf (sparql, "?%d ", idx + 1);
        }
 
-       if (TRACKER_BINDING (binding)->data_type == TRACKER_PROPERTY_TYPE_RESOURCE)
+       if (TRACKER_BINDING (binding)->data_type == TRACKER_PROPERTY_TYPE_RESOURCE) {
+               if (sparql->policy.graphs || sparql->policy.filter_unnamed_graph) {
+                       _append_string_printf (sparql, "AND ID IN (");
+                       _append_resource_rowid_access_check (sparql);
+                       _append_string (sparql, ") ");
+               }
+
                _append_string_printf (sparql, "), 0) ");
+       }
+
        if (TRACKER_BINDING (binding)->data_type == TRACKER_PROPERTY_TYPE_STRING ||
            TRACKER_BINDING (binding)->data_type == TRACKER_PROPERTY_TYPE_LANGSTRING)
                _append_string (sparql, "COLLATE " TRACKER_COLLATION_NAME " ");
@@ -2160,8 +2192,15 @@ convert_expression_to_string (TrackerSparql       *sparql,
                break;
        case TRACKER_PROPERTY_TYPE_RESOURCE:
                /* ID (or string) => Uri */
-               _prepend_string (sparql, "SparqlPrintIRI(");
-               _append_string (sparql, ") ");
+               if (sparql->policy.graphs || sparql->policy.filter_unnamed_graph) {
+                       _prepend_string (sparql, "SparqlPrintIRI((SELECT ");
+                       _append_string (sparql, "AS ID WHERE ID IN (");
+                       _append_resource_rowid_access_check (sparql);
+                       _append_string (sparql, "))) ");
+               } else {
+                       _prepend_string (sparql, "SparqlPrintIRI(");
+                       _append_string (sparql, ") ");
+               }
                break;
        case TRACKER_PROPERTY_TYPE_BOOLEAN:
                _prepend_string (sparql, "CASE ");
diff --git a/tests/functional-tests/portal.py b/tests/functional-tests/portal.py
index 2dbbd66c8..373bf8d5b 100644
--- a/tests/functional-tests/portal.py
+++ b/tests/functional-tests/portal.py
@@ -121,5 +121,25 @@ class TestPortal(fixtures.TrackerPortalTest):
         self.assertEqual(len(res), 1)
         self.assertEqual(res[0][0], 'b')
 
+    def test_06_id_access(self):
+        self.start_service('org.freedesktop.PortalTest')
+        self.update(
+            'org.freedesktop.PortalTest',
+            'CREATE GRAPH tracker:Allowed;' +
+            'INSERT { GRAPH tracker:Allowed { <b> a nfo:FileDataObject } }')
+        res = self.query(
+            'org.freedesktop.PortalTest',
+            'select tracker:id(xsd:string) tracker:uri(1) { }')
+        self.assertEqual(len(res), 1)
+        self.assertEqual(res[0][0], '0')
+        self.assertEqual(res[0][1], None)
+
+        res = self.query(
+            'org.freedesktop.PortalTest',
+            'select tracker:id(<b>) tracker:uri(tracker:id(<b>)) { }')
+        self.assertEqual(len(res), 1)
+        self.assertNotEqual(res[0][0], '0')
+        self.assertEqual(res[0][1], 'b')
+
 if __name__ == '__main__':
     fixtures.tracker_test_main()


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]