198 lines
7.5 KiB
C++
198 lines
7.5 KiB
C++
#include "permission_gate.h"
|
|
#include "lua_sandbox.h"
|
|
|
|
#include <lua.hpp>
|
|
#include <algorithm>
|
|
|
|
namespace mosis {
|
|
|
|
//=============================================================================
|
|
// PERMISSION DATABASE
|
|
//=============================================================================
|
|
|
|
static const std::unordered_map<std::string, PermissionInfo> PERMISSIONS = {
|
|
// Normal permissions (auto-granted when declared)
|
|
{"internet", {PermissionCategory::Normal, "Access the internet"}},
|
|
{"vibrate", {PermissionCategory::Normal, "Vibrate the device"}},
|
|
{"wake_lock", {PermissionCategory::Normal, "Keep device awake"}},
|
|
{"notifications", {PermissionCategory::Normal, "Show notifications"}},
|
|
{"alarms", {PermissionCategory::Normal, "Set alarms"}},
|
|
{"nfc", {PermissionCategory::Normal, "Use NFC"}},
|
|
|
|
// Dangerous permissions (require user consent)
|
|
{"camera", {PermissionCategory::Dangerous, "Access the camera"}},
|
|
{"microphone", {PermissionCategory::Dangerous, "Record audio"}},
|
|
{"location.fine", {PermissionCategory::Dangerous, "Access precise location"}},
|
|
{"location.coarse", {PermissionCategory::Dangerous, "Access approximate location"}},
|
|
{"contacts.read", {PermissionCategory::Dangerous, "Read contacts"}},
|
|
{"contacts.write", {PermissionCategory::Dangerous, "Modify contacts"}},
|
|
{"storage.external", {PermissionCategory::Dangerous, "Access external storage"}},
|
|
{"storage.shared", {PermissionCategory::Dangerous, "Access shared storage"}},
|
|
{"sensors.motion", {PermissionCategory::Dangerous, "Access motion sensors"}},
|
|
{"bluetooth", {PermissionCategory::Dangerous, "Use Bluetooth"}},
|
|
{"bluetooth.scan", {PermissionCategory::Dangerous, "Scan for Bluetooth devices"}},
|
|
{"calendar.read", {PermissionCategory::Dangerous, "Read calendar"}},
|
|
{"calendar.write", {PermissionCategory::Dangerous, "Modify calendar"}},
|
|
{"phone.call", {PermissionCategory::Dangerous, "Make phone calls"}},
|
|
{"phone.read_state", {PermissionCategory::Dangerous, "Read phone state"}},
|
|
{"sms.read", {PermissionCategory::Dangerous, "Read SMS messages"}},
|
|
{"sms.send", {PermissionCategory::Dangerous, "Send SMS messages"}},
|
|
|
|
// Signature permissions (system apps only)
|
|
{"system.settings", {PermissionCategory::Signature, "Modify system settings"}},
|
|
{"system.install", {PermissionCategory::Signature, "Install apps"}},
|
|
{"system.uninstall", {PermissionCategory::Signature, "Uninstall apps"}},
|
|
{"system.admin", {PermissionCategory::Signature, "Device administrator"}},
|
|
{"system.overlay", {PermissionCategory::Signature, "Display over other apps"}},
|
|
{"system.wallpaper", {PermissionCategory::Signature, "Set wallpaper"}},
|
|
};
|
|
|
|
//=============================================================================
|
|
// CONSTRUCTOR
|
|
//=============================================================================
|
|
|
|
PermissionGate::PermissionGate(const SandboxContext& context)
|
|
: m_context(context)
|
|
, m_last_gesture(std::chrono::steady_clock::time_point::min())
|
|
{
|
|
}
|
|
|
|
//=============================================================================
|
|
// PERMISSION INFO
|
|
//=============================================================================
|
|
|
|
PermissionCategory PermissionGate::GetCategory(const std::string& permission) {
|
|
auto it = PERMISSIONS.find(permission);
|
|
if (it != PERMISSIONS.end()) {
|
|
return it->second.category;
|
|
}
|
|
// Unknown permissions default to Dangerous for safety
|
|
return PermissionCategory::Dangerous;
|
|
}
|
|
|
|
const PermissionInfo* PermissionGate::GetPermissionInfo(const std::string& permission) {
|
|
auto it = PERMISSIONS.find(permission);
|
|
if (it != PERMISSIONS.end()) {
|
|
return &it->second;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
//=============================================================================
|
|
// PERMISSION CHECKING
|
|
//=============================================================================
|
|
|
|
bool PermissionGate::HasPermission(const std::string& permission) const {
|
|
auto category = GetCategory(permission);
|
|
|
|
switch (category) {
|
|
case PermissionCategory::Normal:
|
|
return CheckNormalPermission(permission);
|
|
case PermissionCategory::Dangerous:
|
|
return CheckDangerousPermission(permission);
|
|
case PermissionCategory::Signature:
|
|
return CheckSignaturePermission(permission);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool PermissionGate::Check(lua_State* L, const std::string& permission) {
|
|
if (!HasPermission(permission)) {
|
|
luaL_error(L, "permission denied: %s", permission.c_str());
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool PermissionGate::IsDeclared(const std::string& permission) const {
|
|
const auto& declared = m_context.permissions;
|
|
return std::find(declared.begin(), declared.end(), permission) != declared.end();
|
|
}
|
|
|
|
bool PermissionGate::CheckNormalPermission(const std::string& permission) const {
|
|
// Normal permissions are auto-granted if declared in manifest
|
|
return IsDeclared(permission);
|
|
}
|
|
|
|
bool PermissionGate::CheckDangerousPermission(const std::string& permission) const {
|
|
// Must be declared in manifest
|
|
if (!IsDeclared(permission)) {
|
|
return false;
|
|
}
|
|
|
|
// System apps get dangerous permissions automatically
|
|
if (m_context.is_system_app) {
|
|
return true;
|
|
}
|
|
|
|
// Regular apps need runtime grant
|
|
return m_runtime_grants.count(permission) > 0;
|
|
}
|
|
|
|
bool PermissionGate::CheckSignaturePermission(const std::string& permission) const {
|
|
// Only system apps get signature permissions
|
|
if (!m_context.is_system_app) {
|
|
return false;
|
|
}
|
|
|
|
// Must still be declared
|
|
return IsDeclared(permission);
|
|
}
|
|
|
|
//=============================================================================
|
|
// USER GESTURE TRACKING
|
|
//=============================================================================
|
|
|
|
void PermissionGate::RecordUserGesture() {
|
|
m_last_gesture = std::chrono::steady_clock::now();
|
|
}
|
|
|
|
bool PermissionGate::HasRecentUserGesture(int ms) const {
|
|
// If no gesture has been recorded, return false
|
|
if (m_last_gesture == std::chrono::steady_clock::time_point::min()) {
|
|
return false;
|
|
}
|
|
|
|
auto now = std::chrono::steady_clock::now();
|
|
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - m_last_gesture);
|
|
return elapsed.count() < ms;
|
|
}
|
|
|
|
//=============================================================================
|
|
// RUNTIME GRANTS
|
|
//=============================================================================
|
|
|
|
void PermissionGate::GrantPermission(const std::string& permission) {
|
|
// Can only grant dangerous permissions
|
|
auto category = GetCategory(permission);
|
|
if (category == PermissionCategory::Dangerous) {
|
|
m_runtime_grants.insert(permission);
|
|
}
|
|
}
|
|
|
|
void PermissionGate::RevokePermission(const std::string& permission) {
|
|
m_runtime_grants.erase(permission);
|
|
}
|
|
|
|
//=============================================================================
|
|
// QUERIES
|
|
//=============================================================================
|
|
|
|
const std::vector<std::string>& PermissionGate::GetDeclaredPermissions() const {
|
|
return m_context.permissions;
|
|
}
|
|
|
|
std::vector<std::string> PermissionGate::GetGrantedPermissions() const {
|
|
std::vector<std::string> granted;
|
|
|
|
for (const auto& perm : m_context.permissions) {
|
|
if (HasPermission(perm)) {
|
|
granted.push_back(perm);
|
|
}
|
|
}
|
|
|
|
return granted;
|
|
}
|
|
|
|
} // namespace mosis
|