CREATE TABLE IF NOT EXISTS app (
app_id INTEGER PRIMARY KEY,
pkg_id INTEGER NOT NULL,
+uid INTEGER NOT NULL,
name VARCHAR NOT NULL ,
-UNIQUE (name),
+UNIQUE (name, uid),
FOREIGN KEY (pkg_id) REFERENCES pkg (pkg_id)
);
SELECT
app_privilege.app_id as app_id,
app.name as app_name,
+ app.uid as uid,
app.pkg_id as pkg_id,
pkg.name as pkg_name,
app_privilege.privilege_id as privilege_id,
app.app_id,
app.name as app_name,
app.pkg_id,
+ app.uid,
pkg.name as pkg_name
FROM app
LEFT JOIN pkg USING (pkg_id);
BEGIN
INSERT OR IGNORE INTO privilege(name) VALUES (NEW.privilege_name);
INSERT OR IGNORE INTO app_privilege(app_id, privilege_id) VALUES
- ((SELECT app_id FROM app WHERE name=NEW.app_name),
+ ((SELECT app_id FROM app WHERE name=NEW.app_name AND uid=NEW.uid),
(SELECT privilege_id FROM privilege WHERE name=NEW.privilege_name));
END;
INSTEAD OF INSERT ON app_pkg_view
BEGIN
INSERT OR IGNORE INTO pkg(name) VALUES (NEW.pkg_name);
- INSERT OR IGNORE INTO app(pkg_id, name) VALUES ((SELECT pkg_id FROM pkg WHERE name=NEW.pkg_name), NEW.app_name);
+ INSERT OR IGNORE INTO app(pkg_id, name, uid) VALUES ((SELECT pkg_id FROM pkg WHERE name=NEW.pkg_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
BEGIN
- DELETE FROM app WHERE app_id=OLD.app_id;
+ DELETE FROM app WHERE app_id=OLD.app_id AND uid=OLD.uid;
DELETE FROM pkg WHERE pkg_id NOT IN (SELECT DISTINCT pkg_id from app);
END;
private:
SecurityManager::DB::SqlConnection *mSqlConnection;
const std::map<QueryType, const char * const > Queries = {
- { QueryType::EGetPkgPrivileges, "SELECT privilege_name FROM app_privilege_view WHERE pkg_name=?"},
- { QueryType::EAddApplication, "INSERT INTO app_pkg_view (app_name, pkg_name) VALUES (?, ?)" },
- { QueryType::ERemoveApplication, "DELETE FROM app_pkg_view WHERE app_name=?" },
- { QueryType::EAddAppPrivileges, "INSERT INTO app_privilege_view (app_name, privilege_name) VALUES (?, ?)" },
- { QueryType::ERemoveAppPrivileges, "DELETE FROM app_privilege_view WHERE app_name=?" },
+ { QueryType::EGetPkgPrivileges, "SELECT privilege_name FROM app_privilege_view WHERE pkg_name=? AND uid=?"},
+ { QueryType::EAddApplication, "INSERT INTO app_pkg_view (app_name, pkg_name, uid) VALUES (?, ?, ?)" },
+ { QueryType::ERemoveApplication, "DELETE FROM app_pkg_view WHERE app_name=? AND uid=?" },
+ { QueryType::EAddAppPrivileges, "INSERT INTO app_privilege_view (app_name, uid, privilege_name) VALUES (?, ?, ?)" },
+ { QueryType::ERemoveAppPrivileges, "DELETE FROM app_privilege_view WHERE app_name=? AND uid=?" },
{ QueryType::EPkgIdExists, "SELECT * FROM pkg WHERE name=?" },
{ QueryType::EGetPkgId, " SELECT pkg_name FROM app_pkg_view WHERE app_name = ?" },
};
* Retrieve list of privileges assigned to a pkgId
*
* @param pkgId - package identifier
+ * @param uid - user identifier for whom privileges will be retrieved
* @param[out] currentPrivileges - list of current privileges assigned to pkgId
* @exception DB::SqlConnection::Exception::InternalError on internal error
*/
- void GetPkgPrivileges(const std::string &pkgId,
+ void GetPkgPrivileges(const std::string &pkgId, uid_t uid,
std::vector<std::string> ¤tPrivilege);
/**
*
* @param appId - application identifier
* @param pkgId - package identifier
+ * @param uid - user identifier for whom application is going to be installed
* @param[out] pkgIdIsNew - return info if pkgId is new to the database
* @exception DB::SqlConnection::Exception::InternalError on internal error
*/
void AddApplication(const std::string &appId, const std::string &pkgId,
- bool &pkgIdIsNew);
+ uid_t uid, bool &pkgIdIsNew);
/**
* Remove an application from the database
*
* @param appId - application identifier
+ * @param uid - user identifier whose application is going to be uninstalled
* @param[out] pkgIdIsNoMore - return info if pkgId is in the database
* @exception DB::SqlConnection::Exception::InternalError on internal error
*/
- void RemoveApplication(const std::string &appId, bool &pkgIdIsNoMore);
+ void RemoveApplication(const std::string &appId, uid_t uid, bool &pkgIdIsNoMore);
/**
* Remove privileges assigned to application
*
* @param appId - application identifier
+ * @param uid - user identifier for whom privileges will be removed
* @exception DB::SqlConnection::Exception::InternalError on internal error
*/
- void RemoveAppPrivileges(const std::string &appId);
+ void RemoveAppPrivileges(const std::string &appId, uid_t uid);
/**
* Update privileges assigned to application
* To assure data integrity this method must be called inside db transaction.
*
* @param appId - application identifier
+ * @param uid - user identifier for whom privileges will be updated
* @param privileges - list of privileges to assign
* @exception DB::SqlConnection::Exception::InternalError on internal error
*/
- void UpdateAppPrivileges(const std::string &appId,
+ void UpdateAppPrivileges(const std::string &appId, uid_t uid,
const std::vector<std::string> &privileges);
};
}
void PrivilegeDb::AddApplication(const std::string &appId,
- const std::string &pkgId, bool &pkgIdIsNew)
+ const std::string &pkgId, uid_t uid, bool &pkgIdIsNew)
{
pkgIdIsNew = !(this->PkgIdExists(pkgId));
command->BindString(1, appId.c_str());
command->BindString(2, pkgId.c_str());
+ command->BindInteger(3, static_cast<unsigned int>(uid));
if (command->Step()) {
LogDebug("Unexpected SQLITE_ROW answer to query: " <<
});
}
-void PrivilegeDb::RemoveApplication(const std::string &appId,
+void PrivilegeDb::RemoveApplication(const std::string &appId, uid_t uid,
bool &pkgIdIsNoMore)
{
try_catch<void>([&] {
Queries.at(QueryType::ERemoveApplication));
command->BindString(1, appId.c_str());
+ command->BindInteger(2, static_cast<unsigned int>(uid));
if (command->Step()) {
LogDebug("Unexpected SQLITE_ROW answer to query: " <<
});
}
-void PrivilegeDb::GetPkgPrivileges(const std::string &pkgId,
+void PrivilegeDb::GetPkgPrivileges(const std::string &pkgId, uid_t uid,
std::vector<std::string> ¤tPrivileges)
{
try_catch<void>([&] {
mSqlConnection->PrepareDataCommand(
Queries.at(QueryType::EGetPkgPrivileges));
command->BindString(1, pkgId.c_str());
+ command->BindInteger(2, static_cast<unsigned int>(uid));
while (command->Step()) {
std::string privilege = command->GetColumnString(0);
});
}
-void PrivilegeDb::RemoveAppPrivileges(const std::string &appId)
+void PrivilegeDb::RemoveAppPrivileges(const std::string &appId, uid_t uid)
{
try_catch<void>([&] {
DB::SqlConnection::DataCommandAutoPtr command =
mSqlConnection->PrepareDataCommand(Queries.at(QueryType::ERemoveAppPrivileges));
command->BindString(1, appId.c_str());
+ command->BindInteger(2, static_cast<unsigned int>(uid));
if (command->Step()) {
LogDebug("Unexpected SQLITE_ROW answer to query: " <<
Queries.at(QueryType::ERemoveAppPrivileges));
});
}
-void PrivilegeDb::UpdateAppPrivileges(const std::string &appId,
+void PrivilegeDb::UpdateAppPrivileges(const std::string &appId, uid_t uid,
const std::vector<std::string> &privileges)
{
try_catch<void>([&] {
DB::SqlConnection::DataCommandAutoPtr command =
mSqlConnection->PrepareDataCommand(Queries.at(QueryType::EAddAppPrivileges));
command->BindString(1, appId.c_str());
+ command->BindInteger(2, static_cast<unsigned int>(uid));
- RemoveAppPrivileges(appId);
+ RemoveAppPrivileges(appId, uid);
for (const auto &privilege : privileges) {
- command->BindString(2, privilege.c_str());
+ command->BindString(3, privilege.c_str());
command->Step();
command->Reset();
LogDebug("Added privilege: " << privilege << " to appId: " << appId);
*
* @param buffer Raw received data buffer
* @param send Raw data buffer to be sent
+ * @param uid User's identifier for whom application will be installed
* @return true on success
*/
- bool processAppInstall(MessageBuffer &buffer, MessageBuffer &send);
+ bool processAppInstall(MessageBuffer &buffer, MessageBuffer &send, uid_t uid);
/**
- * Process libprivilege-control action and store result in a bufer
+ * Process application uninstallation
*
* @param buffer Raw received data buffer
* @param send Raw data buffer to be sent
+ * @param uid User's identifier for whom application will be uninstalled
* @return true on success
*/
- bool processAppUninstall(MessageBuffer &buffer, MessageBuffer &send);
+ bool processAppUninstall(MessageBuffer &buffer, MessageBuffer &send, uid_t uid);
/**
* Process getting package id from app id
#include <dpl/serialization.h>
#include <privilege-control.h>
+#include <sys/types.h>
+#include <sys/socket.h>
#include "installer.h"
#include "protocols.h"
m_connectionInfoMap.erase(event.connectionID.counter);
}
+static bool getPeerUserID(int sock, uid_t *uid) {
+ struct ucred cr;
+ socklen_t len = sizeof (cr);
+ if (!uid) {
+ return false;
+ }
+ if (!getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &cr, &len)) {
+ *uid = cr.uid;
+ return true;
+ }
+ return false;
+}
+
bool InstallerService::processOne(const ConnectionID &conn, MessageBuffer &buffer,
InterfaceID interfaceID)
{
MessageBuffer send;
bool retval = false;
+ uid_t uid;
+
+ if(!getPeerUserID(conn.sock, &uid)) {
+ LogError("Closing socket because of error: unable to get peer's uid");
+ m_serviceManager->Close(conn);
+ return false;
+ }
+
if (INSTALLER_IFACE == interfaceID) {
Try {
// deserialize API call type
switch (call_type) {
case SecurityModuleCall::APP_INSTALL:
LogDebug("call_type: SecurityModuleCall::APP_INSTALL");
- processAppInstall(buffer, send);
+ processAppInstall(buffer, send, uid);
break;
case SecurityModuleCall::APP_UNINSTALL:
LogDebug("call_type: SecurityModuleCall::APP_UNINSTALL");
- processAppUninstall(buffer, send);
+ processAppUninstall(buffer, send, uid);
break;
case SecurityModuleCall::APP_GET_PKGID:
processGetPkgId(buffer, send);
return retval;
}
-bool InstallerService::processAppInstall(MessageBuffer &buffer, MessageBuffer &send)
+static inline bool installRequestAuthCheck(const app_inst_req &req, uid_t uid)
+{
+ for (const auto &appPath : req.appPaths) {
+ app_install_path_type pathType = static_cast<app_install_path_type>(appPath.second);
+ if (pathType == SECURITY_MANAGER_PATH_PUBLIC && uid != 0) {
+ LogDebug("Only root can register SECURITY_MANAGER_PATH_PUBLIC path");
+ return false;
+ }
+ }
+ return true;
+}
+
+bool InstallerService::processAppInstall(MessageBuffer &buffer, MessageBuffer &send, uid_t uid)
{
bool pkgIdIsNew = false;
std::vector<std::string> addedPermissions;
Deserialization::Deserialize(buffer, req.privileges);
Deserialization::Deserialize(buffer, req.appPaths);
+ if(!installRequestAuthCheck(req, uid)) {
+ LogError("Request from uid " << uid << " for app installation denied");
+ Serialization::Serialize(send, SECURITY_MANAGER_API_ERROR_AUTHENTICATION_FAILED);
+ return false;
+ }
+
std::string smackLabel;
if (!generateAppLabel(req.pkgId, smackLabel)) {
LogError("Cannot generate Smack label for package: " << req.pkgId);
std::vector<std::string> oldPkgPrivileges, newPkgPrivileges;
m_privilegeDb.BeginTransaction();
- m_privilegeDb.GetPkgPrivileges(req.pkgId, oldPkgPrivileges);
- m_privilegeDb.AddApplication(req.appId, req.pkgId, pkgIdIsNew);
- m_privilegeDb.UpdateAppPrivileges(req.appId, req.privileges);
- m_privilegeDb.GetPkgPrivileges(req.pkgId, newPkgPrivileges);
+ m_privilegeDb.GetPkgPrivileges(req.pkgId, uid, oldPkgPrivileges);
+ m_privilegeDb.AddApplication(req.appId, req.pkgId, uid, pkgIdIsNew);
+ m_privilegeDb.UpdateAppPrivileges(req.appId, uid, req.privileges);
+ m_privilegeDb.GetPkgPrivileges(req.pkgId, uid, newPkgPrivileges);
// TODO: configure Cynara rules based on oldPkgPrivileges and newPkgPrivileges
m_privilegeDb.CommitTransaction();
LogDebug("Application installation commited to database");
return false;
}
-bool InstallerService::processAppUninstall(MessageBuffer &buffer, MessageBuffer &send)
+bool InstallerService::processAppUninstall(MessageBuffer &buffer, MessageBuffer &send, uid_t uid)
{
// deserialize request data
std::string appId;
LogDebug("Unnstall parameters: appId: " << appId << ", pkgId: " << pkgId
<< ", generated smack label: " << smackLabel);
- m_privilegeDb.GetPkgPrivileges(pkgId, oldPkgPrivileges);
- m_privilegeDb.UpdateAppPrivileges(appId, std::vector<std::string>());
- m_privilegeDb.RemoveApplication(appId, removePkg);
- m_privilegeDb.GetPkgPrivileges(pkgId, newPkgPrivileges);
+ m_privilegeDb.GetPkgPrivileges(pkgId, uid, oldPkgPrivileges);
+ m_privilegeDb.UpdateAppPrivileges(appId, uid, std::vector<std::string>());
+ m_privilegeDb.RemoveApplication(appId, uid, removePkg);
+ m_privilegeDb.GetPkgPrivileges(pkgId, uid, newPkgPrivileges);
// TODO: configure Cynara rules based on oldPkgPrivileges and newPkgPrivileges
m_privilegeDb.CommitTransaction();
LogDebug("Application uninstallation commited to database");