Add password popup and adjust encryption test binaries to tizen 64/119064/11 app_encryption
authorKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Wed, 15 Mar 2017 09:15:28 +0000 (10:15 +0100)
committerKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Thu, 30 Mar 2017 07:39:04 +0000 (09:39 +0200)
- Separate process for password popup (efl leaves 3 running threads which don't
  like credential synchronisation -> SIGSEGV)
- Apply environmental variables required to show EFL popup
- Apply owner's supplementary groups required to show EFL popup
- Remove password related command line arguments from test binaries
- Better error description in case of no FEK support

Change-Id: I6cf910a32a8501287965da98ec8e425c697094e1

17 files changed:
packaging/security-manager-with-ckm.spec
packaging/security-manager.spec
test/app_encryption/CMakeLists.txt
test/app_encryption/common/CMakeLists.txt
test/app_encryption/common/common.cpp
test/app_encryption/common/common.h
test/app_encryption/common/popup_proxy.cpp [new file with mode: 0644]
test/app_encryption/common/popup_proxy.h [new file with mode: 0644]
test/app_encryption/encryption_setting/encryption_setting.cpp
test/app_encryption/launcher/launcher_user.cpp
test/app_encryption/popup/CMakeLists.txt [new file with mode: 0644]
test/app_encryption/popup/popup.cpp [new file with mode: 0644]
test/app_encryption/popup/popup.h [new file with mode: 0644]
test/app_encryption/popup/popup_server.cpp [new file with mode: 0644]
test/app_encryption/popup/popup_server.h [new file with mode: 0644]
test/app_encryption/popup/res/CMakeLists.txt [new file with mode: 0644]
test/app_encryption/popup/res/popup_custom.edc [new file with mode: 0644]

index f7158d597a1035ea662e61b8dd270d5993417728..0d2f121002e2462492df3936694cc834e9a6cb4d 100644 (file)
@@ -82,6 +82,9 @@ Set of security rules that constitute security policy in the system
 Summary:    Security manager unit test binaries
 Group:      Security/Development
 Requires:   boost-test
+BuildRequires: pkgconfig(elementary)
+BuildRequires: pkgconfig(capi-ui-efl-util)
+BuildRequires: edje-tools
 
 %description -n security-manager-tests
 Internal test for security manager implementation.
@@ -197,6 +200,7 @@ fi
 chsmack -a System %{db_test_dir}/.security-manager-test.db
 chsmack -a System %{db_test_dir}/.security-manager-test.db-journal
 chsmack -e User %{_datadir}/app_encryption/launcher_user
+chsmack -e User %{_datadir}/app_encryption/popup_server
 /sbin/ldconfig
 
 %postun -n security-manager-tests
@@ -267,6 +271,10 @@ echo "User::Pkg::org.tizen.encryption-setting" > /sys/fs/smackfs/revoke-subject
 %attr(0600,root,root) %{db_test_dir}/.security-manager-test.db
 %attr(0600,root,root) %{db_test_dir}/.security-manager-test.db-journal
 %dir %{_datadir}/app_encryption
-%attr(755,-,-) %{_datadir}/app_encryption/*
+%{_datadir}/app_encryption/res
+%attr(755,-,-) %{_datadir}/app_encryption/*.sh
+%attr(755,-,-) %{_datadir}/app_encryption/popup_server
+%attr(755,-,-) %{_datadir}/app_encryption/launcher
+%attr(755,-,-) %{_datadir}/app_encryption/libencryption_common.so
 %attr(755,-,-) %caps(cap_setgid=ei) %{_datadir}/app_encryption/launcher_user
 %attr(755,-,-) %caps(cap_setgid=ei) %{_datadir}/app_encryption/encryption_setting
index 72a66a559ded0215eae37aa23cc02a7cf7753529..a62d43857b51b6982e0bcb46764c73c574a04bb1 100644 (file)
@@ -81,6 +81,10 @@ Set of security rules that constitute security policy in the system
 Summary:    Security manager unit test binaries
 Group:      Security/Development
 Requires:   boost-test
+BuildRequires: pkgconfig(elementary)
+BuildRequires: pkgconfig(vconf)
+BuildRequires: pkgconfig(capi-ui-efl-util)
+BuildRequires: coregl
 
 %description -n security-manager-tests
 Internal test for security manager implementation.
@@ -195,6 +199,7 @@ fi
 chsmack -a System %{db_test_dir}/.security-manager-test.db
 chsmack -a System %{db_test_dir}/.security-manager-test.db-journal
 chsmack -e User %{_datadir}/app_encryption/launcher_user
+chsmack -e User %{_datadir}/app_encryption/popup_server
 /sbin/ldconfig
 
 %postun -n security-manager-tests
@@ -265,6 +270,10 @@ echo "User::Pkg::org.tizen.encryption-setting" > /sys/fs/smackfs/revoke-subject
 %attr(0600,root,root) %{db_test_dir}/.security-manager-test.db
 %attr(0600,root,root) %{db_test_dir}/.security-manager-test.db-journal
 %dir %{_datadir}/app_encryption
-%attr(755,-,-) %{_datadir}/app_encryption/*
+%{_datadir}/app_encryption/res
+%attr(755,-,-) %{_datadir}/app_encryption/*.sh
+%attr(755,-,-) %{_datadir}/app_encryption/popup_server
+%attr(755,-,-) %{_datadir}/app_encryption/launcher
+%attr(755,-,-) %{_datadir}/app_encryption/libencryption_common.so
 %attr(755,-,-) %caps(cap_setgid=ei) %{_datadir}/app_encryption/launcher_user
 %attr(755,-,-) %caps(cap_setgid=ei) %{_datadir}/app_encryption/encryption_setting
index b86dd4540b020e4f55eeb8d41e5ef2930f7863bc..3af0e276fb67a421f3904bb43e8430d5cea6fb86 100644 (file)
 SET(APP_ENCRYPTION_DIR ${DATA_ROOT_DIR}/app_encryption)
 
 SET(TARGET_ENCRYPTION_COMMON "encryption_common")
+SET(TARGET_POPUP_SERVER "popup_server")
+
+ADD_DEFINITIONS("-DPOPUP_SERVER=\"${APP_ENCRYPTION_DIR}/${TARGET_POPUP_SERVER}\"")
 
 SET(ENCRYPTION_COMMON_LDFLAGS "-Wl,--rpath=${APP_ENCRYPTION_DIR}")
 
 INCLUDE_DIRECTORIES(
     ${CMAKE_SOURCE_DIR}/src/include/
     ${CMAKE_CURRENT_SOURCE_DIR}/common/
+    ${CMAKE_CURRENT_SOURCE_DIR}/popup/
 )
 
 ADD_SUBDIRECTORY(common)
 ADD_SUBDIRECTORY(launcher)
 ADD_SUBDIRECTORY(encryption_setting)
 ADD_SUBDIRECTORY(scripts)
+ADD_SUBDIRECTORY(popup)
index 4b6450084c54750e4a03bcaca21bcb47b46b4f74..3644b8d18186399265e11da3dbafb55714b61f1d 100644 (file)
@@ -19,6 +19,7 @@
 
 SET(ENCRYPTION_COMMON_SOURCES
     ${CMAKE_CURRENT_SOURCE_DIR}/common.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/popup_proxy.cpp
 )
 
 ADD_LIBRARY(${TARGET_ENCRYPTION_COMMON} SHARED ${ENCRYPTION_COMMON_SOURCES})
index 048ab0e12f981e212c1678793ae1ffbcda4cae10..229105a2cf0e60b127217e2685ec98c7ff8b7941 100644 (file)
 #include <unistd.h>
 
 #include <tzplatform-config.h>
+#include <security-manager.h>
 
 using namespace SecurityManager;
 
-// TODO remove it when EFL popup is ready
-const char* gPasswords[] = { NULL, NULL, NULL };
-bool gTimeout = false;
-
-std::string Popup::getPassword(const std::string &, PasswordType type)
-{
-    // TODO replace it with real EFL popup
-
-    if (gTimeout)
-        throw std::runtime_error("Popup timeout");
-
-    if(type < PasswordType::OLD || type > PasswordType::CURRENT)
-        throw std::runtime_error("Unexpected password type");
-
-    if (gPasswords[type] == NULL)
-        return std::string();
-
-    return gPasswords[type];
-}
-
 uid_t getDefaultUser()
 {
     static uid_t uid = TizenPlatformConfig::getUid(TZ_SYS_DEFAULT_USER);
@@ -101,3 +82,16 @@ int switchToDefaultUser()
     }
     return 0;
 }
+
+int getEncryptionStatus(const char* app, app_encryption_status& status)
+{
+    int ret = security_manager_app_get_encryption_status(app, &status);
+    if (ret != SECURITY_MANAGER_SUCCESS) {
+        std::cerr << "Getting app encryption status failed " << ret << ".";
+        if (ret == SECURITY_MANAGER_ERROR_SERVER_ERROR)
+            std::cerr << " Have security-manager been built with FEK support?";
+        std::cerr << std::endl;
+        return 1;
+    }
+    return 0;
+}
index d345bdaf05405dcd3d8cdba2033167fafc134849..727185f9fdccbab0dfb0d53f32499a9861e68734 100644 (file)
 
 #include <sys/types.h>
 
-#include <string>
-
-extern const char* gPasswords[];
-
-class Popup {
-public:
-    enum PasswordType {
-        OLD,
-        NEW,
-        CURRENT
-    };
-
-    // empty password = user canceled the popup
-    std::string getPassword(const std::string &app, PasswordType type);
-};
+#include <security-manager-types.h>
 
 uid_t getDefaultUser();
 int switchToDefaultUser();
+int getEncryptionStatus(const char* app, app_encryption_status& status);
diff --git a/test/app_encryption/common/popup_proxy.cpp b/test/app_encryption/common/popup_proxy.cpp
new file mode 100644 (file)
index 0000000..d500e02
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ *  Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+/*
+ * @file       popup_proxy.cpp
+ * @author     Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
+ * @version    1.0
+ */
+
+#include "popup_proxy.h"
+
+#include <stdexcept>
+#include <iostream>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <cassert>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+namespace {
+const char* ENVP[] = {
+    "TIZEN_WAYLAND_SHM_DIR=/run/.efl",
+    "EVAS_FONT_DPI=72",
+    "WAYLAND_DISPLAY=wayland-0",
+    "ECORE_INPUT_CANCEL=1",
+    "TERM=xterm",
+    "ELM_ENGINE=wayland_egl",
+    "USER=owner",
+    "ECORE_IMF_MODULE=wayland",
+    "PATH=/bin:/usr/bin:/sbin:/usr/sbin",
+    "ECTOR_BACKEND=default",
+    "ELM_ATSPI_MODE=1",
+    "EVAS_SHM_FLUSH=1",
+    "HOME=/opt/usr/home/owner",
+    "ECORE_ANIMATOR_SKIP=1",
+    "ECORE_IMF_INPUT_PANEL_ENABLED=1",
+    "EVAS_GL_NO_BLACKLIST=1",
+    "DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/5001/dbus/user_bus_socket",
+    "XDG_RUNTIME_DIR=/run/user/5001",
+    "ELM_DISPLAY=wl",
+    "GTK_IM_MODULE=scim",
+    "ELM_PROFILE=mobile",
+};
+} // anonymous namespace
+
+
+PopupProxy::Pipe::Pipe()
+{
+    if (0 != ::pipe(m_fd))
+        throw std::runtime_error("pipe() failed");
+}
+
+PopupProxy::Pipe::~Pipe()
+{
+    close(IN);
+    close(OUT);
+}
+
+void PopupProxy::Pipe::close(End end)
+{
+    assert(end >= IN && end <= OUT);
+
+    if (m_fd[end] == INVALID)
+        return;
+
+    ::close(m_fd[end]);
+    m_fd[end] = INVALID;
+}
+
+int PopupProxy::Pipe::get(End end)
+{
+    assert(end >= IN && end <= OUT);
+
+    return m_fd[end];
+}
+
+PopupProxy::PopupProxy()
+{
+    pid_t child = fork();
+    if (child < 0)
+        throw std::runtime_error("fork() failed");
+
+    if (child == 0) {
+        m_toChild.close(Pipe::OUT);
+        m_fromChild.close(Pipe::IN);
+
+        char password_popup[] = POPUP_SERVER;
+
+        const size_t MAX_INT_STR = 10;
+        char toChildStr[MAX_INT_STR];
+        char toParentStr[MAX_INT_STR];
+
+        if (0 > snprintf(toChildStr, MAX_INT_STR, "%d", m_toChild.get(Pipe::IN))) {
+            std::cerr << "snprintf() failed for " << m_toChild.get(Pipe::IN) << std::endl;
+            exit(1);
+        }
+        if (0 > snprintf(toParentStr, MAX_INT_STR, "%d", m_fromChild.get(Pipe::OUT))) {
+            std::cerr << "snprintf() failed for " << m_fromChild.get(Pipe::OUT) << std::endl;
+            exit(1);
+        }
+        char* argv[] = { password_popup, toChildStr, toParentStr, NULL };
+
+        size_t envLen = sizeof(ENVP)/sizeof(ENVP[0]);
+        char** envp = new char*[envLen + 1];
+        for (size_t i = 0; i < envLen; i++)
+            envp[i] = strdup(ENVP[i]);
+        envp[envLen] = NULL;
+
+        execve(password_popup, argv, envp);
+
+        std::cerr << "execve() failed" << std::endl;
+        exit(1);
+    } else {
+        m_toChild.close(Pipe::IN);
+        m_fromChild.close(Pipe::OUT);
+        m_child = child;
+    }
+}
+
+PopupProxy::~PopupProxy()
+{
+    m_toChild.write(MAGIC);
+    m_toChild.write(QUIT);
+
+    int status;
+    int child;
+    do
+        child = waitpid(m_child, &status, 0);
+    while (child != m_child);
+
+    if (WEXITSTATUS(status) != 0)
+        std::cerr << "Child returned an error " << WEXITSTATUS(status) << std::endl;
+}
+
+std::string PopupProxy::getPassword(const std::string &app, enum PasswordType type)
+{
+    m_toChild.write(MAGIC);
+    m_toChild.write(GET_PW);
+    m_toChild.write(type);
+    m_toChild.write(app.size() + 1);
+    m_toChild.write(app.c_str(), app.size() + 1);
+
+    PopupResult res;
+    size_t len;
+    m_fromChild.read(res);
+    m_fromChild.read(len);
+    char description[len] = {'\0'};
+    m_fromChild.read(description, len);
+
+    if (res == ERROR)
+        throw std::runtime_error(description);
+
+    if (description[0] == '\0')
+        throw std::runtime_error("No password was entered.");
+
+    return description;
+}
diff --git a/test/app_encryption/common/popup_proxy.h b/test/app_encryption/common/popup_proxy.h
new file mode 100644 (file)
index 0000000..8d51e8d
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ *  Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+/*
+ * @file       popup_proxy.h
+ * @author     Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
+ * @version    1.0
+ */
+
+#pragma once
+
+#include <string>
+
+#include "popup_server.h"
+
+class PopupProxy {
+public:
+    PopupProxy();
+    ~PopupProxy();
+
+    std::string getPassword(const std::string &app, enum PasswordType type);
+
+private:
+    class Pipe {
+    public:
+        enum End {
+            IN,
+            OUT
+        };
+
+        Pipe();
+        ~Pipe();
+
+        void close(End end);
+        int get(End end);
+
+        template <typename T>
+        void write(const T* data, size_t size) {
+            Fd::write(m_fd[OUT], data, size);
+        }
+
+        template <typename T>
+        void write(const T& data) {
+            Fd::write(m_fd[OUT], data);
+        }
+
+        template <typename T>
+        void read(T* data, size_t size) {
+            Fd::read(m_fd[IN], data, size);
+        }
+
+        template <typename T>
+        void read(T& data) {
+            Fd::read(m_fd[IN], data);
+        }
+
+    private:
+        const int INVALID = -1;
+        int m_fd[2];
+    };
+
+    pid_t m_child;
+    Pipe m_toChild;
+    Pipe m_fromChild;
+};
+
+void forkAndWait();
index 11bb69d02a0bec86edcbf7023c312cef03f0e1ec..1207d4c4b4131493b8dd78b61d674fe8eb3a8e6b 100644 (file)
 #include "smack-rules.h"
 
 #include "common.h"
+#include "popup_proxy.h"
 
 const char* const LABEL = "User::Pkg::org.tizen.encryption-setting";
 
 void usage()
 {
-    std::cerr << "Usage: encryption_setting app_id action [-o old_password] [-n new_password]" << std::endl << std::endl <<
+    std::cerr << "Usage: encryption_setting app_id action" << std::endl << std::endl <<
                  " Actions:" << std::endl <<
-                 " -e  Enable encryption. Requires -n option." << std::endl <<
-                 " -d  Disable encryption. Requires -o option." << std::endl <<
-                 " -c  Change encryption password. Requires both -n and -o option." << std::endl << std::endl <<
-                 " Options:" << std::endl <<
-                 " -o old_password  Password that is currently set. Don't use this option if you want to enable encryption." << std::endl <<
-                 " -n new_password  New password to be set. Don't use this option if you want to disable encryption." << std::endl;
+                 " -e  Enable encryption." << std::endl <<
+                 " -d  Disable encryption." << std::endl <<
+                 " -c  Change encryption password." << std::endl;
 }
 
 enum class Action {
@@ -53,7 +51,7 @@ enum class Action {
 
 int main(int argc, char* argv[])
 {
-    if (argc < 4) {
+    if (argc != 3) {
         usage();
         return 1;
     }
@@ -83,11 +81,8 @@ int main(int argc, char* argv[])
     if (0 != switchToDefaultUser())
         return 1;
 
-    ret = security_manager_app_get_encryption_status(app, &status);
-    if (ret != SECURITY_MANAGER_SUCCESS) {
-        std::cerr << "Getting app encryption status failed " << ret << std::endl;
+    if (0 != getEncryptionStatus(app, status))
         return 1;
-    }
 
     Action act;
     if (strcmp(argv[2],"-e") == 0) {
@@ -120,43 +115,30 @@ int main(int argc, char* argv[])
         return 1;
     }
 
-    for (int i=3; i<argc; i++) {
-        if ((act == Action::DISABLE_ENCRYPTION || act == Action::CHANGE_PASSWORD) &&
-            strcmp(argv[i], "-o") == 0 && argc > i+1) {
-            i++;
-            gPasswords[Popup::PasswordType::OLD] = argv[i];
-        } else if ((act == Action::ENABLE_ENCRYPTION || act == Action::CHANGE_PASSWORD) &&
-                   strcmp(argv[i], "-n") == 0 && argc > i+1) {
-            i++;
-            gPasswords[Popup::PasswordType::NEW] = argv[i];
-        } else {
-            usage();
-            return 1;
-        }
-    }
-
     std::string old_password;
     std::string new_password;
-    Popup p;
-    try {
-        switch (act) {
-        case Action::DISABLE_ENCRYPTION:
-            old_password = p.getPassword(app, Popup::PasswordType::OLD);
-            break;
-        case Action::ENABLE_ENCRYPTION:
-            new_password = p.getPassword(app, Popup::PasswordType::NEW);
-            break;
-        case Action::CHANGE_PASSWORD:
-            old_password = p.getPassword(app, Popup::PasswordType::OLD);
-            new_password = p.getPassword(app, Popup::PasswordType::NEW);
-            break;
-        default:
-            std::cerr << "Unexpected action " << static_cast<int>(act) << std::endl;
+    {
+        PopupProxy p;
+        try {
+            switch (act) {
+            case Action::DISABLE_ENCRYPTION:
+                old_password = p.getPassword(app, PasswordType::OLD);
+                break;
+            case Action::ENABLE_ENCRYPTION:
+                new_password = p.getPassword(app, PasswordType::NEW);
+                break;
+            case Action::CHANGE_PASSWORD:
+                old_password = p.getPassword(app, PasswordType::OLD);
+                new_password = p.getPassword(app, PasswordType::NEW);
+                break;
+            default:
+                std::cerr << "Unexpected action " << static_cast<int>(act) << std::endl;
+                return 1;
+            }
+        } catch (std::runtime_error& exc) {
+            std::cerr << exc.what() << std::endl;
             return 1;
         }
-    } catch (std::runtime_error& exc) {
-        std::cerr << exc.what() << std::endl;
-        return 1;
     }
 
     ret = security_manager_app_change_password(
index 5b0bcf17a9dcf8c783ed4df584e9b7c3f10ec093..e7feec0eaf35a83c02f246c2e57cd98e10ab8b5d 100644 (file)
@@ -24,6 +24,7 @@
 #include <stdexcept>
 #include <sstream>
 #include <fstream>
+#include <memory>
 
 #include <cstring>
 #include <unistd.h>
 
 #include "security-manager.h"
 #include "common.h"
+#include "popup_proxy.h"
 #include "tzplatform-config.h"
 
 using namespace SecurityManager;
 
 void usage()
 {
-    std::cerr << "Usage: launcher app_id [-p password] [-f]" << std::endl << std::endl <<
-                 " -p password  Password used for encryption/decryption." << std::endl <<
+    std::cerr << "Usage: launcher app_id [-f]" << std::endl << std::endl <<
                  " -f           First application launch.\n" << std::endl;
 }
 
@@ -71,15 +72,15 @@ int validate_caller()
 int prepare_app(const char* app, bool first)
 {
     app_encryption_status status;
-    int ret = security_manager_app_get_encryption_status(app, &status);
-    if (ret != SECURITY_MANAGER_SUCCESS) {
-        std::cerr << "Geting app encryption status failed " << ret << std::endl;
-        return 1;
-    }
-
     std::string pass;
+    int ret;
+
+    if (0 != getEncryptionStatus(app, status))
+        return 1;
 
     try {
+        std::unique_ptr<PopupProxy> p;
+
         // first run
         if (first) {
             if ((status & SM_APP_ENCR_HAS_PASSWORD) != 0) {
@@ -90,8 +91,8 @@ int prepare_app(const char* app, bool first)
 
             // suggest encryption if app has any sensitive dirs
             if ((status & SM_APP_ENCR_HAS_SENSITIVE_DIRS) != 0) {
-                Popup p;
-                pass = p.getPassword(app, Popup::PasswordType::NEW);
+                p.reset(new PopupProxy());
+                pass = p->getPassword(app, PasswordType::NEW);
 
                 // user doesn't want to encrypt the app
                 if (!pass.empty()) {
@@ -104,26 +105,13 @@ int prepare_app(const char* app, bool first)
                 }
             }
         } else if ((status & SM_APP_ENCR_HAS_PASSWORD) != 0) {
-            Popup p;
-            pass = p.getPassword(app, Popup::PasswordType::CURRENT);
+            p.reset(new PopupProxy());
+            pass = p->getPassword(app, PasswordType::CURRENT);
 
             if (pass.empty()) {
                 std::cerr << "Empty password given. Aborting." << std::endl;
                 return 1;
             }
-        } else {
-            /*
-             * Not a first launch and app has no password.
-             *
-             * TODO This has to be removed. When EFL popup is implemented and app
-             * has no password there will be no possibility to pass it because the
-             * popup won't be shown to the user.
-             */
-            if (gPasswords[Popup::PasswordType::CURRENT] != NULL) {
-                std::cerr << "Application has no password but it was given. Aborting."
-                          << std::endl;
-                return 1;
-            }
         }
     } catch (const std::runtime_error &exc) {
         // user did not respond -> abort the launch
@@ -141,8 +129,9 @@ int prepare_app(const char* app, bool first)
     }
 
     // prepare application
-    if (SECURITY_MANAGER_SUCCESS != security_manager_prepare_app(app)) {
-        std::cerr << "App preparation failed" << std::endl;
+    ret = security_manager_prepare_app(app);
+    if (ret != SECURITY_MANAGER_SUCCESS) {
+        std::cerr << "App preparation failed " << ret << std::endl;
         return 1;
     }
 
@@ -160,6 +149,7 @@ int wait_for_key()
     newSettings.c_lflag &= (~ICANON & ~ECHO);
     if (tcsetattr( fileno( stdin ), TCSANOW, &newSettings ) != 0) {
         std::cerr << "tcsetattr() failed" << std::endl;
+
         return 1;
     }
 
@@ -211,6 +201,7 @@ int run_app(const std::string& pkgName)
         std::cout << "Press Enter to close it." << std::endl;
         std::cin.get();
     }
+
     return 0;
 }
 
@@ -229,11 +220,7 @@ int main(int argc, char* argv[])
     const char* app = argv[1];
 
     for (int i = 2; i < argc; i++) {
-        if (strcmp(argv[i], "-p") == 0 && argc > i+1) {
-            // TODO remove when EFL popup is ready
-            i++;
-            gPasswords[Popup::PasswordType::CURRENT] = argv[i];
-        } else if (strcmp(argv[i], "-f") == 0) {
+        if (strcmp(argv[i], "-f") == 0) {
             first = true;
         } else {
             usage();
@@ -241,9 +228,6 @@ int main(int argc, char* argv[])
         }
     }
 
-    if (first)
-        gPasswords[Popup::PasswordType::NEW] = gPasswords[Popup::PasswordType::CURRENT];
-
     if (prepare_app(app, first) != 0)
         return 1;
 
diff --git a/test/app_encryption/popup/CMakeLists.txt b/test/app_encryption/popup/CMakeLists.txt
new file mode 100644 (file)
index 0000000..df726d5
--- /dev/null
@@ -0,0 +1,47 @@
+# Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+#
+#    Licensed under the Apache License, Version 2.0 (the "License");
+#    you may not use this file except in compliance with the License.
+#    You may obtain a copy of the License at
+#
+#        http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+#
+# @file        CMakeLists.txt
+# @author      Krzysztof Jackiewicz <k.jackiewicz@samsung.com>
+# @brief       Cmake for app encryption popup
+#
+
+SET(APP_ENCRYPTION_RES_DIR ${APP_ENCRYPTION_DIR}/res/)
+ADD_DEFINITIONS("-DRES_DIR=\"${APP_ENCRYPTION_RES_DIR}\"")
+
+FIND_PACKAGE(PkgConfig REQUIRED)
+PKG_CHECK_MODULES(EFL_POPUP
+    REQUIRED
+    elementary
+    capi-ui-efl-util
+)
+
+SET(POPUP_SERVER_SOURCES
+    ${CMAKE_CURRENT_SOURCE_DIR}/popup_server.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/popup.cpp
+)
+
+INCLUDE_DIRECTORIES(${EFL_POPUP_INCLUDE_DIRS})
+
+ADD_EXECUTABLE(${TARGET_POPUP_SERVER} ${POPUP_SERVER_SOURCES})
+
+TARGET_LINK_LIBRARIES(${TARGET_POPUP_SERVER}
+    ${EFL_POPUP_LIBRARIES}
+)
+
+SET_TARGET_PROPERTIES(${TARGET_POPUP_SERVER} PROPERTIES INSTALL_RPATH ${APP_ENCRYPTION_DIR})
+
+INSTALL(TARGETS ${TARGET_POPUP_SERVER} DESTINATION ${APP_ENCRYPTION_DIR})
+
+ADD_SUBDIRECTORY(res)
\ No newline at end of file
diff --git a/test/app_encryption/popup/popup.cpp b/test/app_encryption/popup/popup.cpp
new file mode 100644 (file)
index 0000000..9f48af5
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ *  Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+/*
+ * @file       popup.cpp
+ * @author     Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
+ * @author     Mateusz Forc (m.forc@samsung.com)
+ * @version    1.0
+ */
+
+#include "popup.h"
+
+#include <stdexcept>
+
+#include <efl_util.h>
+
+namespace {
+const float TIMEOUT = 300.0f;
+const char* POPUP_TITLE = "App encryption";
+} // anonymous namespace
+
+Popup::Popup()
+{
+    initialize();
+}
+
+Popup::~Popup()
+{
+    evas_object_del(m_win);
+    m_win = nullptr;
+    elm_shutdown();
+}
+
+void Popup::hideCb(void *popup, Evas_Object *, void *)
+{
+    Popup *pop = static_cast<Popup*>(popup); //thank you EFL
+    evas_object_hide(pop->m_win);
+    elm_exit();
+}
+
+void Popup::changedCb(void *popup, Evas_Object *, void *)
+{
+    Popup *pop = static_cast<Popup*>(popup); //thank you EFL
+    elm_popup_timeout_set(pop->m_popup, TIMEOUT);
+
+    elm_object_disabled_set(pop->m_okButton, elm_entry_is_empty(pop->m_entry));
+}
+
+void Popup::initialize()
+{
+    if (1 != elm_init(0, nullptr))
+        throw std::runtime_error("elm_init() failed");
+
+    m_win = elm_win_add(nullptr, POPUP_TITLE, ELM_WIN_NOTIFICATION);
+    if (m_win == NULL)
+        throw std::runtime_error("elm_win_add() failed");
+
+    if (EFL_UTIL_ERROR_NONE != efl_util_set_notification_window_level(
+            m_win,
+            EFL_UTIL_NOTIFICATION_LEVEL_3))
+        throw std::runtime_error("efl_util_set_notification_window_level() failed");
+
+    elm_win_autodel_set(m_win, EINA_TRUE);
+    elm_win_override_set(m_win, EINA_TRUE);
+    elm_win_alpha_set(m_win, EINA_TRUE);
+
+    // popup
+    m_popup = elm_popup_add(m_win);
+    if (m_popup == NULL)
+        throw std::runtime_error("elm_popup_add() failed");
+
+    elm_popup_align_set(m_popup, ELM_NOTIFY_ALIGN_FILL, 0.0);
+    elm_object_part_text_set(m_popup, "title,text", POPUP_TITLE);
+    elm_popup_timeout_set(m_popup, TIMEOUT);
+    evas_object_smart_callback_add(m_popup, "timeout", &Popup::hideCb, this);
+
+    // layout
+    m_layout = elm_layout_add(m_popup);
+    if (m_layout == NULL)
+        throw std::runtime_error("elm_layout_add() failed");
+
+    if (EINA_TRUE != elm_layout_file_set(m_layout, RES_DIR"/popup_custom.edj", "entry_layout"))
+        throw std::runtime_error("elm_layout_file_set() failed");
+
+    // content
+    m_content = elm_label_add(m_layout);
+    if (m_content == NULL)
+        throw std::runtime_error("elm_label_add() failed");
+
+    elm_label_line_wrap_set(m_content, ELM_WRAP_MIXED);
+    if (EINA_TRUE != elm_object_style_set(m_content, "popup/default"))
+        throw std::runtime_error("elm_object_style_set() failed");
+
+    elm_object_part_content_set(m_layout, "content", m_content);
+    evas_object_show(m_content);
+
+    // entry
+    m_entry = elm_entry_add(m_layout);
+    if (m_entry == NULL) {
+        throw std::runtime_error("elm_entry_add() failed");
+    }
+    elm_entry_password_set(m_entry, EINA_TRUE);
+    elm_entry_single_line_set(m_entry, EINA_TRUE);
+    elm_object_part_content_set(m_layout, "entry", m_entry);
+    elm_entry_input_panel_return_key_type_set(m_entry, ELM_INPUT_PANEL_RETURN_KEY_TYPE_DONE);
+    evas_object_show(m_entry);
+    evas_object_smart_callback_add(m_entry, "changed", &Popup::changedCb, this);
+
+    // buttons
+    m_cancelButton = elm_button_add(m_popup);
+    if (m_cancelButton == NULL) {
+        throw std::runtime_error("elm_button_add() failed for cancel button");
+    }
+    elm_object_part_content_set(m_popup, "button1", m_cancelButton);
+    elm_object_text_set(m_cancelButton, "Cancel");
+
+    m_okButton = elm_button_add(m_popup);
+    if (m_okButton == NULL) {
+        throw std::runtime_error("elm_button_add() failed for ok button");
+    }
+    elm_object_part_content_set(m_popup, "button2", m_okButton);
+    elm_object_text_set(m_okButton, "Ok");
+    elm_object_disabled_set(m_okButton, EINA_TRUE);
+
+    elm_object_content_set(m_popup, m_layout);
+    evas_object_show(m_popup);
+
+    evas_object_smart_callback_add(m_okButton, "clicked", &Popup::hideCb, this);
+    evas_object_smart_callback_add(m_cancelButton, "clicked", &Popup::hideCb, this);
+}
+
+void Popup::show()
+{
+    evas_object_show(m_win);
+    elm_run();
+}
+
+void Popup::prepare(const std::string &app, enum PasswordType type)
+{
+    elm_entry_entry_set(m_entry, NULL);
+
+    std::string description;
+
+    switch (type) {
+    case OLD:
+        description = "Enter old password for ";
+        break;
+    case NEW:
+        description = "Enter new password for ";
+        break;
+    case CURRENT:
+        description = "Enter current password for ";
+        break;
+    }
+
+    description.append(app);
+
+    elm_object_text_set(m_content, description.c_str());
+}
+
+std::string Popup::getPassword(const std::string &app, enum PasswordType type)
+{
+    prepare(app, type);
+    show();
+
+    return std::string(elm_object_text_get(m_entry));
+}
diff --git a/test/app_encryption/popup/popup.h b/test/app_encryption/popup/popup.h
new file mode 100644 (file)
index 0000000..4be0d30
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ *  Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+/*
+ * @file       popup.h
+ * @author     Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
+ * @author     Mateusz Forc (m.forc@samsung.com)
+ * @version    1.0
+ */
+
+#pragma once
+
+#include "popup_server.h"
+
+#include <Elementary.h>
+
+#include <string>
+
+class Popup {
+public:
+    Popup();
+    ~Popup();
+
+    std::string getPassword(const std::string &app, enum PasswordType type);
+
+private:
+    static void hideCb(void *, Evas_Object *, void *);
+    static void changedCb(void *, Evas_Object *, void *);
+
+    void initialize();
+    void show();
+    void prepare(const std::string &app, enum PasswordType type);
+
+    Evas_Object *m_win = nullptr;
+    Evas_Object *m_popup = nullptr;
+    Evas_Object *m_cancelButton = nullptr;
+    Evas_Object *m_okButton = nullptr;
+    Evas_Object *m_layout = nullptr;
+    Evas_Object *m_content = nullptr;
+    Evas_Object *m_entry = nullptr;
+};
diff --git a/test/app_encryption/popup/popup_server.cpp b/test/app_encryption/popup/popup_server.cpp
new file mode 100644 (file)
index 0000000..6460705
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ *  Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+/*
+ * @file       popup_server.cpp
+ * @author     Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
+ * @version    1.0
+ */
+
+#include "popup_server.h"
+#include "popup.h"
+
+#include <string>
+#include <iostream>
+#include <sstream>
+#include <stdexcept>
+#include <memory>
+
+void writeResult(int fd, PopupResult result, const std::string &description)
+{
+    Fd::write(fd, result);
+    Fd::write(fd, description.size() + 1);
+    Fd::write(fd, description.c_str(), description.size() + 1);
+}
+
+void writeError(int fd, const std::string &description)
+{
+    writeResult(fd, ERROR, description);
+}
+
+void writeSuccess(int fd, const std::string &password)
+{
+    writeResult(fd, SUCCESS, password);
+}
+
+int main(int argc, char* argv[])
+{
+    if (argc != 3) {
+        std::cerr << "Wrong arguments (in & out descriptor)" << std::endl;
+        return 1;
+    }
+
+    try {
+        std::stringstream ss1(argv[1]);
+        int input;
+        ss1 >> input;
+        std::unique_ptr<int, void(*)(int*)> inputPtr(&input, [](int* fd){ ::close(*fd); });
+
+        std::stringstream ss2(argv[2]);
+        int output;
+        ss2 >> output;
+        std::unique_ptr<int, void(*)(int*)> outputPtr(&output, [](int* fd){ ::close(*fd); });
+
+        Popup p;
+
+        bool quit = false;
+        while(!quit) {
+            int magic;
+            do
+                Fd::read(input, magic);
+            while(magic != MAGIC);
+
+            PopupCommand cmd;
+            Fd::read(input, cmd);
+
+            switch (cmd) {
+            case GET_PW:
+            {
+                PasswordType type;
+                Fd::read(input, type);
+
+                if (type < OLD || type > CURRENT) {
+                    writeError(output, "Wrong popup type");
+                    break;
+                }
+                size_t len;
+                Fd::read(input, len);
+                char app[len];
+                Fd::read(input, app, len);
+
+                try {
+                    writeSuccess(output, p.getPassword(app, type));
+                } catch (const std::exception& e) {
+                    writeError(output, e.what());
+                } catch (...) {
+                    writeError(output, "Unknown exception");
+                }
+                break;
+            }
+            case QUIT:
+                quit = true;
+                break;
+            default:
+                writeError(output, "Wrong command");
+            }
+        }
+    } catch (const std::exception& e) {
+        std::cerr << e.what() << std::endl;
+        return 1;
+    } catch (...) {
+        std::cerr << "Unknown exception" << std::endl;
+        return 1;
+    }
+
+    return 0;
+}
diff --git a/test/app_encryption/popup/popup_server.h b/test/app_encryption/popup/popup_server.h
new file mode 100644 (file)
index 0000000..d84e194
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ *  Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+/*
+ * @file       popup_server.h
+ * @author     Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
+ * @version    1.0
+ */
+
+#pragma once
+
+#include <stdexcept>
+#include <unistd.h>
+
+enum PopupResult : char{
+    SUCCESS = 0,
+    ERROR,
+};
+
+enum PasswordType : char {
+    OLD = 0,
+    NEW,
+    CURRENT,
+};
+
+enum PopupCommand : char {
+    GET_PW = 0,
+    QUIT,
+};
+
+const int MAGIC = 0xB16B00B5;
+
+namespace Fd {
+
+template <typename T>
+void write(int fd, const T* data, size_t size) {
+    size_t left = size;
+    while (left > 0) {
+        auto written = TEMP_FAILURE_RETRY(::write(fd, data + size - left, size));
+        if (written <= 0)
+            throw std::runtime_error("write() failed");
+        left -= written;
+    }
+}
+
+template <typename T>
+void write(int fd, const T& data) {
+    write(fd, &data, sizeof(data));
+}
+
+template <typename T>
+void read(int fd, T* data, size_t size) {
+    size_t left = size;
+    while (left > 0) {
+        auto read = TEMP_FAILURE_RETRY(::read(fd, data + size - left, size));
+        if (read <= 0)
+            throw std::runtime_error("read() failed");
+        left -= read;
+    }
+}
+
+template <typename T>
+void read(int fd, T& data) {
+    read(fd, &data, sizeof(data));
+}
+
+} // namespace Pipe
diff --git a/test/app_encryption/popup/res/CMakeLists.txt b/test/app_encryption/popup/res/CMakeLists.txt
new file mode 100644 (file)
index 0000000..8f3e13a
--- /dev/null
@@ -0,0 +1,28 @@
+# Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+#
+#    Licensed under the Apache License, Version 2.0 (the "License");
+#    you may not use this file except in compliance with the License.
+#    You may obtain a copy of the License at
+#
+#        http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+#
+# @file        CMakeLists.txt
+# @author      Krzysztof Jackiewicz <k.jackiewicz@samsung.com>
+# @brief       Cmake for app encryption popup edj file
+#
+
+SET(OUTPUT_POPUP_EDJ ${CMAKE_CURRENT_BINARY_DIR}/popup_custom.edj)
+
+ADD_CUSTOM_COMMAND(OUTPUT ${OUTPUT_POPUP_EDJ}
+    COMMAND edje_cc -no-save ${CMAKE_CURRENT_SOURCE_DIR}/popup_custom.edc ${OUTPUT_POPUP_EDJ}
+)
+
+ADD_CUSTOM_TARGET(PRODUCE_EDJ_FILE ALL DEPENDS ${OUTPUT_POPUP_EDJ})
+
+INSTALL(FILES ${OUTPUT_POPUP_EDJ} DESTINATION ${APP_ENCRYPTION_RES_DIR})
diff --git a/test/app_encryption/popup/res/popup_custom.edc b/test/app_encryption/popup/res/popup_custom.edc
new file mode 100644 (file)
index 0000000..8c7660d
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+
+collections {
+group { name: "entry_layout";
+   parts {
+      part { name: "content";
+         type: SWALLOW;
+         scale: 1;
+         description { state: "default" 0.0;
+            rel1.relative: 0.00 0.00;
+            rel2.relative: 1.00 0.50;
+         }
+      }
+      part { name: "bg";
+         type: RECT;
+         scale: 1;
+         description { state: "default" 0.0;
+            color: 220 220 220 255;
+            rel1.relative: 0.10 0.50;
+            rel2.relative: 0.90 1.00;
+         }
+      }
+      part { name: "entry";
+         type: SWALLOW;
+         scale: 1;
+         description { state: "default" 0.0;
+            rel1.to: "bg";
+            rel2.to: "bg";
+         }
+      }
+   }
+}
+}