Fix contraints for app installation. 50/65350/11
authorKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Wed, 6 Apr 2016 13:55:20 +0000 (15:55 +0200)
committerGerrit Code Review <gerrit@review.vlan103.tizen.org>
Fri, 22 Jul 2016 15:04:44 +0000 (08:04 -0700)
[Problem] It's possible to insert an app similar to existing one (differs with
version, pkg name, author name) or pollute the db with unused entries in pkg
and author.
[Solution] Split app table into app(package) and user_app(instances). Introduce
more strict constraint checking.

[Verification] Run security-manager-tests --regexp=49 (and all remaining tests
as a regression check)

Change-Id: I2fb02f75981748024de93c2d486fa6eb8afaf88a

db/db.sql
db/updates/update-db-to-v6.sql [new file with mode: 0644]
src/common/include/privilege_db.h
src/common/service_impl.cpp

index bc83937..805baa0 100644 (file)
--- a/db/db.sql
+++ b/db/db.sql
@@ -4,7 +4,7 @@ PRAGMA auto_vacuum = NONE;
 
 BEGIN EXCLUSIVE TRANSACTION;
 
-PRAGMA user_version = 5;
+PRAGMA user_version = 6;
 
 CREATE TABLE IF NOT EXISTS pkg (
 pkg_id INTEGER PRIMARY KEY,
@@ -14,16 +14,24 @@ UNIQUE (name)
 FOREIGN KEY (author_id) REFERENCES author (author_id)
 );
 
+/* Application */
 CREATE TABLE IF NOT EXISTS app (
 app_id INTEGER PRIMARY KEY,
 pkg_id INTEGER NOT NULL,
-uid INTEGER NOT NULL,
 name VARCHAR NOT NULL,
 version VARCHAR NOT NULL,
-UNIQUE (name, uid),
+UNIQUE (name),
 FOREIGN KEY (pkg_id) REFERENCES pkg (pkg_id)
 );
 
+/* Instance of 'app' installed for given user ('uid') */
+CREATE TABLE IF NOT EXISTS user_app (
+app_id INTEGER NOT NULL,
+uid INTEGER NOT NULL,
+PRIMARY KEY (app_id, uid),
+FOREIGN KEY (app_id) REFERENCES app (app_id)
+);
+
 CREATE TABLE IF NOT EXISTS shared_path (
 path_id INTEGER PRIMARY KEY,
 path VARCHAR NOT NULL,
@@ -52,27 +60,38 @@ CREATE TABLE IF NOT EXISTS author (
        UNIQUE (name)
 );
 
-DROP VIEW IF EXISTS app_pkg_view;
-CREATE VIEW app_pkg_view AS
+DROP VIEW IF EXISTS user_app_pkg_view;
+CREATE VIEW user_app_pkg_view AS
 SELECT
-    app.app_id,
+    user_app.uid,
+    user_app.app_id,
     app.name as app_name,
     app.pkg_id,
-    app.uid,
-    pkg.name as pkg_name,
     app.version as version,
     pkg.author_id,
+    pkg.name as pkg_name,
     author.name as author_name
-FROM app
+FROM user_app
+LEFT JOIN app USING (app_id)
 LEFT JOIN pkg USING (pkg_id)
 LEFT JOIN author USING (author_id);
 
-DROP TRIGGER IF EXISTS app_pkg_view_insert_trigger;
-CREATE TRIGGER app_pkg_view_insert_trigger
-INSTEAD OF INSERT ON app_pkg_view
+DROP TRIGGER IF EXISTS user_app_pkg_view_insert_trigger;
+CREATE TRIGGER user_app_pkg_view_insert_trigger
+INSTEAD OF INSERT ON user_app_pkg_view
 BEGIN
+    SELECT RAISE(ABORT, 'Application already installed with different pkg_name')
+        WHERE EXISTS (SELECT 1 FROM user_app_pkg_view
+                      WHERE app_name=NEW.app_name
+                      AND pkg_name!=NEW.pkg_name);
+
+    SELECT RAISE(ABORT, 'Application already installed with different version')
+        WHERE EXISTS (SELECT 1 FROM user_app_pkg_view
+                      WHERE app_name=NEW.app_name
+                      AND version!=NEW.version);
+
     SELECT RAISE(ABORT, 'Another application from this package is already installed with different author')
-        WHERE EXISTS (SELECT 1 FROM app_pkg_view
+        WHERE EXISTS (SELECT 1 FROM user_app_pkg_view
                       WHERE pkg_name=NEW.pkg_name
                       AND author_name IS NOT NULL
                       AND NEW.author_name IS NOT NULL
@@ -82,20 +101,27 @@ BEGIN
     INSERT OR IGNORE INTO pkg(name, author_id) VALUES (
         NEW.pkg_name,
         (SELECT author_id FROM author WHERE name=NEW.author_name));
+
     -- If pkg have already existed with empty author do update it
-    UPDATE pkg SET author_id=(SELECT author_id FROM author WHERE name=NEW.author_name) WHERE name=NEW.pkg_name AND author_id IS NULL;
-    INSERT OR IGNORE INTO app(pkg_id, name, uid, version) VALUES (
+    UPDATE pkg SET author_id=(SELECT author_id FROM author WHERE name=NEW.author_name)
+        WHERE name=NEW.pkg_name AND author_id IS NULL;
+
+    INSERT OR IGNORE INTO app (pkg_id, name, version) VALUES (
         (SELECT pkg_id FROM pkg WHERE name=NEW.pkg_name),
         NEW.app_name,
-        NEW.uid,
         NEW.version);
+
+    INSERT OR IGNORE INTO user_app (app_id, uid) VALUES (
+        (SELECT app_id FROM app WHERE name=NEW.app_name),
+        NEW.uid);
 END;
 
-DROP TRIGGER IF EXISTS app_pkg_view_delete_trigger;
-CREATE TRIGGER app_pkg_view_delete_trigger
-INSTEAD OF DELETE ON app_pkg_view
+DROP TRIGGER IF EXISTS user_app_pkg_view_delete_trigger;
+CREATE TRIGGER user_app_pkg_view_delete_trigger
+INSTEAD OF DELETE ON user_app_pkg_view
 BEGIN
-    DELETE FROM app WHERE app_id=OLD.app_id AND uid=OLD.uid;
+    DELETE FROM user_app WHERE app_id=OLD.app_id AND uid=OLD.uid;
+    DELETE FROM app WHERE app_id NOT IN (SELECT DISTINCT app_id FROM user_app);
     DELETE FROM pkg WHERE pkg_id NOT IN (SELECT DISTINCT pkg_id from app);
     DELETE FROM author WHERE author_id NOT IN (SELECT DISTINCT author_id FROM pkg WHERE author_id IS NOT NULL);
 END;
diff --git a/db/updates/update-db-to-v6.sql b/db/updates/update-db-to-v6.sql
new file mode 100644 (file)
index 0000000..44491a1
--- /dev/null
@@ -0,0 +1,26 @@
+BEGIN EXCLUSIVE TRANSACTION;
+
+PRAGMA user_version = 6;
+
+CREATE TABLE app_new (
+    app_id INTEGER PRIMARY KEY,
+    pkg_id INTEGER NOT NULL,
+    name VARCHAR NOT NULL,
+    version VARCHAR NOT NULL,
+    UNIQUE (name),
+    FOREIGN KEY (pkg_id) REFERENCES pkg (pkg_id)
+);
+
+CREATE TABLE user_app (
+    app_id INTEGER NOT NULL,
+    uid INTEGER NOT NULL,
+    PRIMARY KEY (app_id, uid),
+    FOREIGN KEY (app_id) REFERENCES app (app_id)
+);
+
+INSERT INTO user_app SELECT app_id, uid FROM app;
+INSERT INTO app_new  SELECT app_id, pkg_id, name, version FROM app;
+DROP TABLE app;
+ALTER TABLE app_new RENAME TO app;
+
+COMMIT TRANSACTION;
index eefdd86..3216401 100644 (file)
@@ -100,11 +100,11 @@ private:
 
     SecurityManager::DB::SqlConnection *mSqlConnection;
     const std::map<StmtType, const char * const > Queries = {
-        { StmtType::EAddApplication, "INSERT INTO app_pkg_view (app_name, pkg_name, uid, version, author_name) VALUES (?, ?, ?, ?, ?)" },
-        { StmtType::ERemoveApplication, "DELETE FROM app_pkg_view WHERE app_name=? AND uid=?" },
+        { StmtType::EAddApplication, "INSERT INTO user_app_pkg_view (app_name, pkg_name, uid, version, author_name) VALUES (?, ?, ?, ?, ?)" },
+        { StmtType::ERemoveApplication, "DELETE FROM user_app_pkg_view WHERE app_name=? AND uid=?" },
         { StmtType::EPkgNameExists, "SELECT count(*) FROM pkg WHERE name=?" },
         { StmtType::EAppNameExists, "SELECT count(*) FROM app WHERE name=?" },
-        { StmtType::EGetAppPkgName, "SELECT pkg_name FROM app_pkg_view WHERE app_name = ?" },
+        { StmtType::EGetAppPkgName, "SELECT pkg_name FROM user_app_pkg_view WHERE app_name = ?" },
         { StmtType::EGetAppVersion, "SELECT version FROM app WHERE name = ?" },
         { StmtType::EGetPathSharedCount, "SELECT COUNT(*) FROM app_private_sharing_view WHERE path = ?"},
         { StmtType::EGetTargetPathSharedCount, "SELECT COUNT(*) FROM app_private_sharing_view WHERE target_app_name = ? AND path = ?"},
@@ -118,9 +118,9 @@ private:
         { StmtType::EClearSharing, "DELETE FROM app_private_sharing;"},
         { StmtType::EClearPrivatePaths, "DELETE FROM shared_path;"},
         { StmtType::EGetPrivilegeGroups, " SELECT group_name FROM privilege_group WHERE privilege_name = ?" },
-        { StmtType::EGetUserApps, "SELECT name FROM app WHERE uid=?" },
-        { StmtType::EGetTizen2XPackages,  "SELECT DISTINCT pkg_name FROM app_pkg_view WHERE version LIKE '2.%%'" },
-        { StmtType::EGetAppsInPkg, " SELECT app_name FROM app_pkg_view WHERE pkg_name = ?" },
+        { StmtType::EGetUserApps, "SELECT app_name FROM user_app_pkg_view WHERE uid=?" },
+        { StmtType::EGetTizen2XPackages,  "SELECT DISTINCT pkg_name FROM user_app_pkg_view WHERE version LIKE '2.%%'" },
+        { StmtType::EGetAppsInPkg, " SELECT app_name FROM user_app_pkg_view WHERE pkg_name = ?" },
         { StmtType::EGetGroups, "SELECT DISTINCT group_name FROM privilege_group" },
         { StmtType::EGetPkgAuthorId, "SELECT author_id FROM pkg WHERE name = ? AND author_id IS NOT NULL"},
         { StmtType::EAuthorIdExists, "SELECT count(*) FROM author where author_id=?"},
index 2aa0856..e88ccd6 100644 (file)
@@ -463,13 +463,6 @@ int ServiceImpl::appInstall(const Credentials &creds, app_inst_req &&req)
                  ", pkg label: " << pkgLabel);
 
         PrivilegeDb::getInstance().BeginTransaction();
-        std::string pkg;
-        PrivilegeDb::getInstance().GetAppPkgName(req.appName, pkg);
-        if (!pkg.empty() && pkg != req.pkgName) {
-            LogError("Application already installed with different package name");
-            PrivilegeDb::getInstance().RollbackTransaction();
-            return SECURITY_MANAGER_ERROR_INPUT_PARAM;
-        }
 
         PrivilegeDb::getInstance().AddApplication(req.appName, req.pkgName, req.uid, req.tizenVersion, req.authorName);
         /* Get all application ids in the package to generate rules withing the package */