BEGIN EXCLUSIVE TRANSACTION;
-PRAGMA user_version = 15;
+PRAGMA user_version = 16;
CREATE TABLE IF NOT EXISTS pkg (
pkg_id INTEGER PRIMARY KEY,
AND NEW.author_hash IS NOT NULL
AND author_hash!=NEW.author_hash);
- INSERT OR IGNORE INTO author(hash) VALUES (NEW.author_hash);
+ INSERT OR IGNORE INTO author(author_id, hash) VALUES (NEW.author_id, NEW.author_hash);
- INSERT OR IGNORE INTO pkg(name, author_id, is_hybrid) VALUES (
+ INSERT OR IGNORE INTO pkg(pkg_id, name, author_id, is_hybrid) VALUES (
+ NEW.pkg_id,
NEW.pkg_name,
(SELECT author_id FROM author WHERE hash=NEW.author_hash),
NEW.is_hybrid);
-- If app have already existed with different version do update it
UPDATE app SET version=NEW.version WHERE name=NEW.app_name;
- INSERT OR IGNORE INTO app (pkg_id, name, version) VALUES (
+ INSERT OR IGNORE INTO app (pkg_id, app_id, name, version) VALUES (
(SELECT pkg_id FROM pkg WHERE name=NEW.pkg_name),
+ NEW.app_id,
NEW.app_name,
NEW.version);
--- /dev/null
+BEGIN EXCLUSIVE TRANSACTION;
+
+PRAGMA user_version = 16;
+
+COMMIT TRANSACTION;
EGetLicenseForClientPrivilegeAndApp,
EGetLicenseForClientPrivilegeAndPkg,
EIsUserPkgInstalled,
+ EGetSortedProcessUIds,
+ EGetSortedAuthorGIds,
+ EGetProcessUIdInfo,
+ EGetAuthorId,
};
-enum : uint8_t { StmtTypeCount = underlying(StmtType::EIsUserPkgInstalled) + 1 };
+enum : uint8_t { StmtTypeCount = underlying(StmtType::EGetAuthorId) + 1 };
// privilege, app_defined_privilege_type, license
typedef std::tuple<std::string, int, std::string> AppDefinedPrivilege;
static auto loaderCmd() { return "/usr/bin/security-manager-rules-loader"; }
};
+ /**
+ * Return first free id using provided statement starting from given value
+ *
+ * @param startValue starting value for id
+ * @param statement query used to extract existing ids sorted in ascending order
+ */
+ int GetFirstFreeId(int startValue, StmtType statement);
+
+ /**
+ * Return first id not used as pkg_id nor app_id
+ */
+ int GetFirstFreeProcessUId();
+
+ /**
+ * Return first free author_id from author table
+ */
+ int GetFirstFreeAuthorGId();
+
public:
+ static constexpr int PROCESS_UID_MIN = 10000;
+ static constexpr int AUTHOR_GID_MIN = 20000;
+
class Exception
{
public:
* @exception PrivilegeDb::Exception::ConstraintError on constraint violation
*/
bool IsUserPkgInstalled(const std::string& pkgName, uid_t uid);
+
+ /**
+ * Return process UID for given app & package
+ *
+ * @param[in] pkgName - application package
+ * @param[in] appName - application identifier
+ * @param[out] processUId - process UId
+ *
+ * @exception PrivilegeDb::Exception::InternalError on internal error
+ * @exception PrivilegeDb::Exception::ConstraintError on constraint violation
+ */
+ bool GetProcessUId(const std::string& pkgName, const std::string& appName, uid_t& processUId);
+
+ /**
+ * Return author GId for given package
+ *
+ * @param[in] pkgName - application package
+ * @param[out] authorGId - author GId
+ *
+ * @exception PrivilegeDb::Exception::InternalError on internal error
+ * @exception PrivilegeDb::Exception::ConstraintError on constraint violation
+ */
+ bool GetAuthorGId(const std::string& pkgName, gid_t& authorGId);
};
} //namespace SecurityManager
#include "privilege_db.h"
#include "tzplatform-config.h"
#include "filesystem.h"
+#include "smack-check.h"
namespace SecurityManager {
namespace {
constexpr const char *g_queries[StmtTypeCount] = {
- [underlying(StmtType::EAddApplication)] = "INSERT INTO user_app_pkg_view (app_name, pkg_name, uid, version, author_hash, is_hybrid)"
- " VALUES (?, ?, ?, ?, ?, ?)",
+ [underlying(StmtType::EAddApplication)] = "INSERT INTO user_app_pkg_view (app_name, pkg_name, uid, version, author_hash, is_hybrid, pkg_id, app_id, author_id)"
+ " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
[underlying(StmtType::ERemoveApplication)] = "DELETE FROM user_app_pkg_view WHERE app_name=? AND uid=?",
[underlying(StmtType::EPkgNameExists)] = "SELECT count(*) FROM pkg WHERE name=?",
[underlying(StmtType::EAppNameExists)] = "SELECT count(*) FROM app WHERE name=?",
[underlying(StmtType::EGetLicenseForClientPrivilegeAndApp)] = "SELECT license FROM client_license_view WHERE app_name = ? AND uid = ? AND privilege = ? ",
[underlying(StmtType::EGetLicenseForClientPrivilegeAndPkg)] = "SELECT license FROM client_license_view WHERE pkg_name = ? AND uid = ? AND privilege = ? ",
[underlying(StmtType::EIsUserPkgInstalled)] = "SELECT count(*) FROM user_app_pkg_view WHERE pkg_name = ? AND uid = ?",
+ [underlying(StmtType::EGetSortedProcessUIds)] = "SELECT pkg_id FROM pkg UNION SELECT app_id FROM app ORDER BY pkg_id",
+ [underlying(StmtType::EGetSortedAuthorGIds)] = "SELECT author_id FROM author ORDER BY author_id",
+ [underlying(StmtType::EGetProcessUIdInfo)] = "SELECT pkg_id, app_id, is_hybrid FROM user_app_pkg_view WHERE pkg_name = ? AND app_name = ?",
+ [underlying(StmtType::EGetAuthorId)] = "SELECT author_id FROM pkg WHERE name = ?",
};
static_assert(allTrue(g_queries));
command->BindString(4, targetTizenVer);
authorName.empty() ? command->BindNull(5) : command->BindString(5, getAuthorHash(authorName));
command->BindInteger(6, isHybrid ? 1 : 0);
+ if (smack_simple_check()) {
+ command->BindNull(7);
+ command->BindNull(8);
+ command->BindNull(9);
+ } else {
+ auto processUId = GetFirstFreeProcessUId();
+ command->BindInteger(7, processUId);
+ command->BindInteger(8, processUId);
+ command->BindInteger(9, GetFirstFreeAuthorGId());
+ }
if (command->Step()) {
LogDebug("Unexpected SQLITE_ROW answer to query: " <<
});
}
+int PrivilegeDb::GetFirstFreeId(int startValue, StmtType statement)
+{
+ auto command = getStatement(statement);
+ int id = startValue;
+
+ while (command->Step()) {
+ if (id != command->GetColumnInteger(0))
+ break;
+ id++;
+ };
+ return id;
+}
+
+int PrivilegeDb::GetFirstFreeProcessUId()
+{
+ return GetFirstFreeId(PROCESS_UID_MIN, StmtType::EGetSortedProcessUIds);
+}
+
+int PrivilegeDb::GetFirstFreeAuthorGId()
+{
+ return GetFirstFreeId(AUTHOR_GID_MIN, StmtType::EGetSortedAuthorGIds);
+}
+
+bool PrivilegeDb::GetProcessUId(
+ const std::string& pkgName,
+ const std::string& appName,
+ uid_t& processUId)
+{
+ return try_catch_db(m_api_mutex, [&]() -> bool {
+ auto command = getStatement(StmtType::EGetProcessUIdInfo);
+ command->BindString(1, pkgName);
+ command->BindString(2, appName);
+
+ if (command->Step()) {
+ int pkgId = command->GetColumnInteger(0);
+ int appId = command->GetColumnInteger(1);
+ int hybrid = command->GetColumnInteger(2);
+ processUId = hybrid ? appId : pkgId;
+ return true;
+ }
+
+ return false;
+ });
+}
+
+bool PrivilegeDb::GetAuthorGId(const std::string& pkgName, gid_t& authorGId)
+{
+ return try_catch_db(m_api_mutex, [&]() -> bool {
+ auto command = getStatement(StmtType::EGetAuthorId);
+ command->BindString(1, pkgName);
+
+ if (command->Step()) {
+ authorGId = command->GetColumnInteger(0);
+ return true;
+ }
+
+ return false;
+ });
+}
+
} //namespace SecurityManager
${PROJECT_SOURCE_DIR}/src/common/config-file.cpp
#${PROJECT_SOURCE_DIR}/src/common/file-lock.cpp
${PROJECT_SOURCE_DIR}/src/common/privilege_db.cpp
- #${PROJECT_SOURCE_DIR}/src/common/smack-check.cpp
+ ${PROJECT_SOURCE_DIR}/src/common/smack-check.cpp
#${PROJECT_SOURCE_DIR}/src/common/smack-labels.cpp
#${PROJECT_SOURCE_DIR}/src/common/smack-rules.cpp
${PROJECT_SOURCE_DIR}/src/common/filesystem.cpp
}
BOOST_AUTO_TEST_SUITE_END()
+
+#ifndef SMACK_ENABLED
+
+class PrivilegeDBFixtureExt : public PrivilegeDBFixture {
+public:
+ void checkProcessUId(int appIdx, int pkgIdx, uid_t expected) {
+ uid_t got;
+ BOOST_REQUIRE_MESSAGE(getPrivDb()->GetProcessUId(pkg(pkgIdx), app(appIdx), got), "GetProcessUId failed");
+ BOOST_REQUIRE_MESSAGE(got == expected, "Wrong process UId");
+ }
+
+ void checkAuthorGId(int pkgIdx, gid_t expected) {
+ gid_t got;
+ BOOST_REQUIRE_MESSAGE(getPrivDb()->GetAuthorGId(pkg(pkgIdx), got), "GetAuthorGId failed");
+ BOOST_REQUIRE_MESSAGE(got == expected, "Wrong author GId");
+ }
+
+ static gid_t ProcessUId(size_t idx) {
+ return PrivilegeDb::PROCESS_UID_MIN + idx;
+ }
+
+ static gid_t AuthorGId(size_t idx) {
+ return PrivilegeDb::AUTHOR_GID_MIN + idx;
+ }
+};
+
+BOOST_FIXTURE_TEST_SUITE(PRIVILEGE_DB_TEST_PPROCESS_UID_AUTHOR_GID, PrivilegeDBFixtureExt)
+
+POSITIVE_TEST_CASE(T1000_process_uid_non_hybrid)
+{
+ // NOTE: This test requires empty database to work
+
+ addAppSuccess(app(1), pkg(1), uid(1), tizenVer(1), author(1), NotHybrid);
+ addAppSuccess(app(2), pkg(1), uid(1), tizenVer(1), author(1), NotHybrid);
+ addAppSuccess(app(3), pkg(2), uid(1), tizenVer(1), author(1), NotHybrid);
+ addAppSuccess(app(4), pkg(3), uid(1), tizenVer(1), author(1), NotHybrid);
+
+ // appNo appId pkgId
+ // 1 10000 10000
+ // 2 10001 10000
+ // 3 10002 10002
+ // 4 10003 10003
+
+ checkProcessUId(1, 1, ProcessUId(0));
+ checkProcessUId(2, 1, ProcessUId(0));
+ checkProcessUId(3, 2, ProcessUId(2));
+ checkProcessUId(4, 3, ProcessUId(3));
+
+ removeAppSuccess(app(1), uid(1));
+ removeAppSuccess(app(3), uid(1));
+
+ // appNo appId pkgId
+ // 2 10001 10000
+ // 4 10003 10003
+
+ uid_t got;
+ BOOST_REQUIRE_MESSAGE(!getPrivDb()->GetProcessUId(pkg(1), app(1), got), "GetProcessUId should fail");
+ BOOST_REQUIRE_MESSAGE(!getPrivDb()->GetProcessUId(pkg(3), app(1), got), "GetProcessUId should fail");
+
+ addAppSuccess(app(5), pkg(4), uid(1), tizenVer(1), author(1), NotHybrid);
+ addAppSuccess(app(6), pkg(4), uid(1), tizenVer(1), author(1), NotHybrid);
+ addAppSuccess(app(7), pkg(5), uid(1), tizenVer(1), author(1), NotHybrid);
+
+ // appNo appId pkgId
+ // 2 10001 10000
+ // 4 10003 10003
+ // 5 10002 10002
+ // 6 10004 10002
+ // 7 10005 10005
+
+ checkProcessUId(2, 1, ProcessUId(0));
+ checkProcessUId(4, 3, ProcessUId(3));
+ checkProcessUId(5, 4, ProcessUId(2));
+ checkProcessUId(6, 4, ProcessUId(2));
+ checkProcessUId(7, 5, ProcessUId(5));
+}
+
+POSITIVE_TEST_CASE(T1010_process_uid_hybrid)
+{
+ // NOTE: This test requires empty database to work
+
+ addAppSuccess(app(1), pkg(1), uid(1), tizenVer(1), author(1), Hybrid);
+ addAppSuccess(app(2), pkg(1), uid(1), tizenVer(1), author(1), Hybrid);
+ addAppSuccess(app(3), pkg(2), uid(1), tizenVer(1), author(1), Hybrid);
+
+ // appNo appId pkgId
+ // 1 10000 10000
+ // 2 10001 10000
+ // 3 10002 10002
+
+ checkProcessUId(1, 1, ProcessUId(0));
+ checkProcessUId(2, 1, ProcessUId(1));
+ checkProcessUId(3, 2, ProcessUId(2));
+
+ removeAppSuccess(app(2), uid(1));
+
+ // appNo appId pkgId
+ // 1 10000 10000
+ // 3 10002 10002
+
+ uid_t got;
+ BOOST_REQUIRE_MESSAGE(!getPrivDb()->GetProcessUId(pkg(1), app(2), got), "GetProcessUId should fail");
+
+ addAppSuccess(app(4), pkg(3), uid(1), tizenVer(1), author(1), Hybrid);
+ addAppSuccess(app(5), pkg(3), uid(1), tizenVer(1), author(1), Hybrid);
+ addAppSuccess(app(6), pkg(4), uid(1), tizenVer(1), author(1), Hybrid);
+
+ // appNo appId pkgId
+ // 1 10000 10000
+ // 3 10002 10002
+ // 4 10001 10001
+ // 5 10003 10001
+ // 6 10004 10004
+
+ checkProcessUId(1, 1, ProcessUId(0));
+ checkProcessUId(3, 2, ProcessUId(2));
+ checkProcessUId(4, 3, ProcessUId(1));
+ checkProcessUId(5, 3, ProcessUId(3));
+ checkProcessUId(6, 4, ProcessUId(4));
+}
+
+POSITIVE_TEST_CASE(T1020_author_gid)
+{
+ // NOTE: This test requires empty database to work
+
+ addAppSuccess(app(1), pkg(1), uid(1), tizenVer(1), author(1), NotHybrid);
+ addAppSuccess(app(2), pkg(2), uid(1), tizenVer(1), author(2), NotHybrid);
+ addAppSuccess(app(3), pkg(3), uid(1), tizenVer(1), author(2), NotHybrid);
+
+ // pkgNo authorId
+ // 1 20000
+ // 2 20001
+ // 3 20001
+
+ checkAuthorGId(1, AuthorGId(0));
+ checkAuthorGId(2, AuthorGId(1));
+ checkAuthorGId(3, AuthorGId(1));
+
+ removeAppSuccess(app(1), uid(1));
+ removeAppSuccess(app(2), uid(1));
+
+ // pkgNo authorId
+ // 3 20001
+
+ gid_t got;
+ BOOST_REQUIRE_MESSAGE(!getPrivDb()->GetAuthorGId(pkg(1), got), "GetAuthorGId should fail");
+ BOOST_REQUIRE_MESSAGE(!getPrivDb()->GetAuthorGId(pkg(2), got), "GetAuthorGId should fail");
+
+ addAppSuccess(app(4), pkg(4), uid(1), tizenVer(1), author(3), NotHybrid);
+ addAppSuccess(app(5), pkg(5), uid(1), tizenVer(1), author(3), NotHybrid);
+ addAppSuccess(app(6), pkg(6), uid(1), tizenVer(1), author(4), NotHybrid);
+
+ // pkgNo authorId
+ // 3 20001
+ // 4 20000
+ // 5 20000
+ // 6 20002
+
+ checkAuthorGId(3, AuthorGId(1));
+ checkAuthorGId(4, AuthorGId(0));
+ checkAuthorGId(5, AuthorGId(0));
+ checkAuthorGId(6, AuthorGId(2));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+#endif