Internal encryption: Fix missing elm config files and locales
[platform/core/security/ode.git] / server / internal-encryption.cpp
index 47c6ae1..6a8a90a 100644 (file)
 #include <sys/reboot.h>
 
 #include <vconf.h>
+#include <tzplatform_config.h>
 #include <klay/process.h>
 #include <klay/file-user.h>
 #include <klay/filesystem.h>
 #include <klay/dbus/connection.h>
 #include <klay/audit/logger.h>
 
-#include "engine/dmcrypt-engine.h"
+#include "vconf.h"
+#include "progress-bar.h"
+#include "engine/encryption/dmcrypt-engine.h"
 #include "key-manager/key-manager.h"
 
 #include "rmi/internal-encryption.h"
 
-#define INTERNAL_STORAGE_PATH  "/opt/usr"
-#define INTERNAL_STATE_VCONF_KEY VCONFKEY_ODE_CRYPTO_STATE
-#define INTERNAL_OPTION_ONLY_USED_REGION_VCONF_KEY VCONFKEY_ODE_FAST_ENCRYPTION
+#define INTERNAL_ENGINE        DMCryptEngine
+#define INTERNAL_DEV   "/dev/mmcblk0p25"
+#define INTERNAL_PATH  "/opt/usr"
+#define INTERNAL_STATE_VCONF_KEY                                       VCONFKEY_ODE_CRYPTO_STATE
+#define INTERNAL_OPTION_ONLY_USED_REGION_VCONF_KEY     VCONFKEY_ODE_FAST_ENCRYPTION
+
+#define PRIVILEGE_PLATFORM "http://tizen.org/privilege/internal/default/platform"
+
+const std::string PROG_FACTORY_RESET = "/usr/bin/dbus-send";
+const std::vector<std::string> wipeCommand = {
+    PROG_FACTORY_RESET,
+    "--system",
+    "--type=signal",
+    "--print-reply",
+    "--dest=com.samsung.factoryreset",
+    "/com/samsung/factoryreset",
+    "com.samsung.factoryreset.start.setting"
+};
 
 namespace ode {
 
 namespace {
 
-VConfBackend vconfBackend(VCONFKEY_ODE_ENCRYPT_PROGRESS);
-ProgressBar progressBar(std::bind(&VConfBackend::update, &vconfBackend, std::placeholders::_1));
-
-DMCryptEngine engine("/dev/mmcblk0p25", INTERNAL_STORAGE_PATH, progressBar);
+std::unique_ptr<INTERNAL_ENGINE> engine;
 
 void stopDependedSystemdServices()
 {
        dbus::Connection& systemDBus = dbus::Connection::getSystem();
        std::set<std::string> servicesToStop;
 
-       for (pid_t pid : runtime::FileUser::getList(INTERNAL_STORAGE_PATH, true)) {
+       for (pid_t pid : runtime::FileUser::getList(INTERNAL_PATH, true)) {
                try {
                        char *service;
                        systemDBus.methodcall("org.freedesktop.systemd1",
@@ -77,6 +92,27 @@ void stopDependedSystemdServices()
 }
 
 void showProgressUI(const std::string type) {
+       ::tzplatform_set_user(::tzplatform_getuid(TZ_SYS_DEFAULT_USER));
+       std::string defaultUserHome(::tzplatform_getenv(TZ_USER_HOME));
+       ::tzplatform_reset_user();
+
+       ::tzplatform_set_user(::getuid());
+       std::string currentUserHome(::tzplatform_getenv(TZ_USER_HOME));
+       ::tzplatform_reset_user();
+
+       INFO("Home directory : " + currentUserHome);
+
+       runtime::File shareDirectory(currentUserHome + "/share");
+       if (!shareDirectory.exists()) {
+               shareDirectory.makeDirectory();
+       }
+
+       runtime::File elmConfigDir(currentUserHome + "/share/.elementary");
+       if (!elmConfigDir.exists()) {
+               runtime::File defaultElmConfigDir(defaultUserHome + "/share/.elementary");
+               defaultElmConfigDir.copyTo(shareDirectory.getPath());
+       }
+
        std::vector<std::string> args = {
                "ode", "progress", type, "Internal"
        };
@@ -116,13 +152,25 @@ void setOptions(unsigned int options)
 InternalEncryption::InternalEncryption(ODEControlContext& ctx) :
        context(ctx)
 {
-       context.registerNonparametricMethod(this, "", (int)(InternalEncryption::getState));
-       context.registerNonparametricMethod(this, "", (unsigned int)(InternalEncryption::getSupportedOptions));
-       context.registerParametricMethod(this, "", (int)(InternalEncryption::mount)(std::string));
-       context.registerNonparametricMethod(this, "", (int)(InternalEncryption::umount));
-       context.registerParametricMethod(this, "", (int)(InternalEncryption::encrypt)(std::string, unsigned int));
-       context.registerParametricMethod(this, "", (int)(InternalEncryption::decrypt)(std::string));
-       context.registerParametricMethod(this, "", (int)(InternalEncryption::changePassword)(std::string, std::string));
+       context.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryption::mount)(std::string));
+       context.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryption::umount)());
+       context.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryption::encrypt)(std::string, unsigned int));
+       context.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryption::decrypt)(std::string));
+       context.expose(this, "", (int)(InternalEncryption::isPasswordInitialized)());
+       context.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryption::initPassword)(std::string));
+       context.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryption::cleanPassword)(std::string));
+       context.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryption::changePassword)(std::string, std::string));
+       context.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryption::verifyPassword)(std::string));
+       context.expose(this, "", (int)(InternalEncryption::getState)());
+       context.expose(this, "", (unsigned int)(InternalEncryption::getSupportedOptions)());
+
+       engine.reset(new INTERNAL_ENGINE(
+               INTERNAL_DEV, INTERNAL_PATH,
+               ProgressBar([](int v) {
+                       ::vconf_set_str(VCONFKEY_ODE_ENCRYPT_PROGRESS,
+                                                       std::to_string(v).c_str());
+               })
+       ));
 }
 
 InternalEncryption::~InternalEncryption()
@@ -136,13 +184,13 @@ int InternalEncryption::mount(const std::string& password)
        }
 
        KeyManager::data pwData(password.begin(), password.end());
-       KeyManager keyManager(engine.getKeyMeta());
+       KeyManager keyManager(engine->getKeyMeta());
 
        if (!keyManager.verifyPassword(pwData)) {
                return -2;
        }
 
-       engine.mount(keyManager.getMasterKey(pwData), getOptions());
+       engine->mount(keyManager.getMasterKey(pwData), getOptions());
        return 0;
 }
 
@@ -155,7 +203,7 @@ int InternalEncryption::umount()
        INFO("Close all processes using internal storage...");
        stopDependedSystemdServices();
        INFO("Umount internal storage...");
-       engine.umount();
+       engine->umount();
 
        return 0;
 }
@@ -167,34 +215,40 @@ int InternalEncryption::encrypt(const std::string& password, unsigned int option
        }
 
        KeyManager::data pwData(password.begin(), password.end());
-       KeyManager keyManager;
+       KeyManager keyManager(engine->getKeyMeta());
 
-       keyManager.initPassword(pwData);
-       engine.setKeyMeta(keyManager.serialize());
+       if (!keyManager.verifyPassword(pwData)) {
+               return -2;
+       }
 
        KeyManager::data MasterKey = keyManager.getMasterKey(pwData);
-       auto encryptWorker = [&MasterKey, options, this]() {
-               showProgressUI("Encrypting");
-
-               INFO("Close all processes using internal storage...");
-               stopDependedSystemdServices();
-               INFO("Umount internal storage...");
-               while (::umount(INTERNAL_STORAGE_PATH) == -1) {
-                       if (errno != EBUSY) {
-                               break;
+       auto encryptWorker = [MasterKey, options, this]() {
+               try {
+                       showProgressUI("Encrypting");
+
+                       INFO("Close all processes using internal storage...");
+                       stopDependedSystemdServices();
+                       INFO("Umount internal storage...");
+                       while (::umount(INTERNAL_PATH) == -1) {
+                               if (errno != EBUSY) {
+                                       throw runtime::Exception("Umount error - " + std::to_string(errno));
+                               }
+                               stopDependedSystemdServices();
                        }
-               }
 
-               INFO("Encryption started...");
-               ::vconf_set_str(INTERNAL_STATE_VCONF_KEY, "error_partially_encrypted");
-               engine.encrypt(MasterKey, options);
-               setOptions(options & getSupportedOptions());
-               INFO("Sync disk...");
-               sync();
-               INFO("Encryption completed");
+                       INFO("Encryption started...");
+                       engine->encrypt(MasterKey, options);
+                       setOptions(options & getSupportedOptions());
+                       INFO("Sync disk...");
+                       sync();
+                       INFO("Encryption completed");
 
-               ::vconf_set_str(INTERNAL_STATE_VCONF_KEY, "encrypted");
-               ::reboot(RB_AUTOBOOT);
+                       ::vconf_set_str(INTERNAL_STATE_VCONF_KEY, "encrypted");
+                       ::reboot(RB_AUTOBOOT);
+               } catch (runtime::Exception &e) {
+                       ::vconf_set_str(INTERNAL_STATE_VCONF_KEY, "error_partially_encrypted");
+                       ERROR("Encryption failed - " + std::string(e.what()));
+               }
        };
 
        std::thread asyncWork(encryptWorker);
@@ -210,7 +264,7 @@ int InternalEncryption::decrypt(const std::string& password)
        }
 
        KeyManager::data pwData(password.begin(), password.end());
-       KeyManager keyManager(engine.getKeyMeta());
+       KeyManager keyManager(engine->getKeyMeta());
 
        if (!keyManager.verifyPassword(pwData)) {
                return -2;
@@ -218,24 +272,33 @@ int InternalEncryption::decrypt(const std::string& password)
 
        KeyManager::data MasterKey = keyManager.getMasterKey(pwData);
        auto decryptWorker = [MasterKey, this]() {
-               showProgressUI("Decrypting");
-
-               INFO("Close all processes using internal storage...");
-               stopDependedSystemdServices();
-               INFO("Umount internal storage...");
                try {
-                       engine.umount();
-               } catch (runtime::Exception& e) {}
-
-               INFO("Decryption started...");
-               ::vconf_set_str(INTERNAL_STATE_VCONF_KEY, "error_partially_encrypted");
-               engine.decrypt(MasterKey, getOptions());
-               INFO("Sync disk...");
-               sync();
-               INFO("Decryption completed");
-
-               ::vconf_set_str(INTERNAL_STATE_VCONF_KEY, "unencrypted");
-               ::reboot(RB_AUTOBOOT);
+                       showProgressUI("Decrypting");
+
+                       INFO("Close all processes using internal storage...");
+                       stopDependedSystemdServices();
+                       INFO("Umount internal storage...");
+                       while (1) {
+                               try {
+                                       engine->umount();
+                                       break;
+                               } catch (runtime::Exception& e) {
+                                       stopDependedSystemdServices();
+                               }
+                       }
+
+                       INFO("Decryption started...");
+                       engine->decrypt(MasterKey, getOptions());
+                       INFO("Sync disk...");
+                       sync();
+                       INFO("Decryption completed");
+
+                       ::vconf_set_str(INTERNAL_STATE_VCONF_KEY, "unencrypted");
+                       ::reboot(RB_AUTOBOOT);
+               } catch (runtime::Exception &e) {
+                       ::vconf_set_str(INTERNAL_STATE_VCONF_KEY, "error_partially_encrypted");
+                       ERROR("Decryption failed - " + std::string(e.what()));
+               }
        };
 
        std::thread asyncWork(decryptWorker);
@@ -244,34 +307,81 @@ int InternalEncryption::decrypt(const std::string& password)
        return 0;
 }
 
-int InternalEncryption::verifyPassword(const std::string& password)
+int InternalEncryption::recovery()
 {
-       KeyManager::data data(password.begin(), password.end());
-       KeyManager keyManager(engine.getKeyMeta());
+       if (getState() != State::Unencrypted) {
+               return -1;
+       }
 
-       if (keyManager.verifyPassword(data)) {
+       //TODO
+       runtime::Process proc(PROG_FACTORY_RESET, wipeCommand);
+       if (proc.execute() == -1) {
+               ERROR("Failed to launch factory-reset");
+               return -2;
+       }
+
+       return 0;
+}
+
+int InternalEncryption::isPasswordInitialized()
+{
+       if (engine->isKeyMetaSet()) {
                return 1;
        }
        return 0;
 }
 
+int InternalEncryption::initPassword(const std::string& password)
+{
+       KeyManager::data pwData(password.begin(), password.end());
+       KeyManager keyManager;
+
+       keyManager.initPassword(pwData);
+       engine->setKeyMeta(keyManager.serialize());
+       return 0;
+}
+
+int InternalEncryption::cleanPassword(const std::string& password)
+{
+       KeyManager::data pwData(password.begin(), password.end());
+       KeyManager keyManager(engine->getKeyMeta());
+
+       if (!keyManager.verifyPassword(pwData)) {
+               return -2;
+       }
+
+       engine->clearKeyMeta();
+       return 0;
+}
+
 int InternalEncryption::changePassword(const std::string& oldPassword,
                                                                                const std::string& newPassword)
 {
        KeyManager::data oldPwData(oldPassword.begin(), oldPassword.end());
        KeyManager::data newPwData(newPassword.begin(), newPassword.end());
-       KeyManager keyManager(engine.getKeyMeta());
+       KeyManager keyManager(engine->getKeyMeta());
 
        if (!keyManager.verifyPassword(oldPwData)) {
                return -2;
        }
 
        keyManager.changePassword(oldPwData, newPwData);
-       engine.setKeyMeta(keyManager.serialize());
+       engine->setKeyMeta(keyManager.serialize());
 
        return 0;
 }
 
+int InternalEncryption::verifyPassword(const std::string& password)
+{
+       KeyManager::data pwData(password.begin(), password.end());
+       KeyManager keyManager(engine->getKeyMeta());
+
+       if (keyManager.verifyPassword(pwData)) {
+               return 1;
+       }
+       return 0;
+}
+
 int InternalEncryption::getState()
 {
        char *value = ::vconf_get_str(INTERNAL_STATE_VCONF_KEY);
@@ -295,7 +405,7 @@ int InternalEncryption::getState()
 
 unsigned int InternalEncryption::getSupportedOptions()
 {
-       return engine.getSupportedOptions();
+       return engine->getSupportedOptions();
 }
 
 } // namespace ode