From: Sungbae Yoo Date: Tue, 31 May 2016 08:21:39 +0000 (+0900) Subject: Change to do zone provisioning not in dpm, but in libzone X-Git-Tag: accepted/tizen/ivi/20160602.231346^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F36%2F72236%2F9;p=platform%2Fcore%2Fsecurity%2Fdevice-policy-manager.git Change to do zone provisioning not in dpm, but in libzone Change-Id: I8deb2f7370162ffdfeaf42ca19f23b2707ab1ba0 Signed-off-by: Sungbae Yoo --- diff --git a/common/auth/user.cpp b/common/auth/user.cpp index ce11f76..7559a31 100644 --- a/common/auth/user.cpp +++ b/common/auth/user.cpp @@ -13,8 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License */ - - #include #include @@ -115,7 +113,7 @@ User User::create(const std::string& name, const std::string& group_name, ::getpwnam_r(name.c_str(), &tmppwd, buf.get(), bufsize, &result); if (result != NULL) { - return User(name); + throw runtime::Exception("User " + name + "already exists"); } //prepare passwd structure diff --git a/common/dbus/connection.cpp b/common/dbus/connection.cpp index dddb99d..f609260 100644 --- a/common/dbus/connection.cpp +++ b/common/dbus/connection.cpp @@ -28,13 +28,13 @@ namespace { const std::string DBUS_SYSTEM_BUS_ADDRESS = "unix:path=/var/run/dbus/system_bus_socket"; -void defaultCallback (GDBusConnection *connection, - const gchar *sender_name, - const gchar *object_path, - const gchar *interface_name, - const gchar *signal_name, - GVariant *parameters, - gpointer user_data) { +void defaultCallback(GDBusConnection* connection, + const gchar *sender_name, + const gchar *object_path, + const gchar *interface_name, + const gchar *signal_name, + GVariant *parameters, + gpointer user_data) { Connection::signalCallback* func = reinterpret_cast (user_data); (*func)(Variant(parameters)); delete func; @@ -46,9 +46,8 @@ Connection::Connection(const std::string& address) : connection(nullptr) { Error error; - const GDBusConnectionFlags flags = static_cast( - G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT | G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION - ); + const GDBusConnectionFlags flags = static_cast + (G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT | G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION); connection = g_dbus_connection_new_for_address_sync(address.c_str(), flags, NULL, NULL, &error); if (error) { diff --git a/common/dbus/error.h b/common/dbus/error.h index f2fa38b..e6c7a1e 100644 --- a/common/dbus/error.h +++ b/common/dbus/error.h @@ -20,7 +20,7 @@ #include #include -namespace dbus{ +namespace dbus { class Error { public: diff --git a/common/dbus/variant.h b/common/dbus/variant.h index 3695751..360efcf 100644 --- a/common/dbus/variant.h +++ b/common/dbus/variant.h @@ -20,7 +20,7 @@ #include #include -namespace dbus{ +namespace dbus { class Variant { public: diff --git a/libs/dpm/context.h b/libs/dpm/context.h index e0048fe..9a4b01b 100644 --- a/libs/dpm/context.h +++ b/libs/dpm/context.h @@ -85,7 +85,8 @@ typedef enum { DPM_ERROR_NOT_SUPPORTED = TIZEN_ERROR_NOT_SUPPORTED, /**< Operation is not supported */ DPM_ERROR_NO_SUCH_FILE = TIZEN_ERROR_NO_SUCH_FILE, /**< No such file or directory */ DPM_ERROR_FILE_EXISTS = TIZEN_ERROR_FILE_EXISTS, /**< File exists */ - DPM_ERROR_OUT_OF_MEMORY = TIZEN_ERROR_OUT_OF_MEMORY /**< Out of memory */ + DPM_ERROR_OUT_OF_MEMORY = TIZEN_ERROR_OUT_OF_MEMORY, /**< Out of memory */ + DPM_ERROR_NO_DATA = TIZEN_ERROR_NO_DATA /**< No Data */ } dpm_error_type_e; /** diff --git a/libs/dpm/zone.cpp b/libs/dpm/zone.cpp index 101eebb..3236ae2 100644 --- a/libs/dpm/zone.cpp +++ b/libs/dpm/zone.cpp @@ -55,16 +55,33 @@ int dpm_zone_destroy(dpm_zone_policy_h handle, const char* name) return zone.removeZone(name); } +int dpm_zone_get_state(dpm_zone_policy_h handle, const char* name, dpm_zone_state_e *state) +{ + RET_ON_FAILURE(handle, DPM_ERROR_INVALID_PARAMETER); + RET_ON_FAILURE(name, DPM_ERROR_INVALID_PARAMETER); + + DevicePolicyContext &client = GetDevicePolicyContext(handle); + ZonePolicy zone = client.createPolicyInterface(); + + int result = zone.getZoneState(name); + if (result <0) { + return DPM_ERROR_NO_DATA; + } + + *state = (dpm_zone_state_e)result; + return DPM_ERROR_NONE; +} + typedef runtime::Array dpm_zone_iterator; -dpm_zone_iterator_h dpm_zone_create_iterator(dpm_zone_policy_h handle) +dpm_zone_iterator_h dpm_zone_create_iterator(dpm_zone_policy_h handle, dpm_zone_state_e state) { RET_ON_FAILURE(handle, NULL); DevicePolicyContext &client = GetDevicePolicyContext(handle); ZonePolicy zone = client.createPolicyInterface(); - return reinterpret_cast(new dpm_zone_iterator(zone.getZoneList())); + return reinterpret_cast(new dpm_zone_iterator(zone.getZoneList(state))); } int dpm_zone_iterator_next(dpm_zone_iterator_h iter, const char** result) @@ -79,7 +96,7 @@ int dpm_zone_iterator_next(dpm_zone_iterator_h iter, const char** result) else *result = it->next()->c_str(); - return 0; + return DPM_ERROR_NONE; } int dpm_zone_destroy_iterator(dpm_zone_iterator_h iter) @@ -88,10 +105,10 @@ int dpm_zone_destroy_iterator(dpm_zone_iterator_h iter) delete reinterpret_cast(iter); - return 0; + return DPM_ERROR_NONE; } -int dpm_zone_foreach_name(dpm_zone_policy_h handle, +int dpm_zone_foreach_name(dpm_zone_policy_h handle, dpm_zone_state_e state, dpm_zone_foreach_cb callback, void* user_data) { RET_ON_FAILURE(handle, DPM_ERROR_INVALID_PARAMETER); @@ -99,23 +116,11 @@ int dpm_zone_foreach_name(dpm_zone_policy_h handle, DevicePolicyContext &client = GetDevicePolicyContext(handle); ZonePolicy zone = client.createPolicyInterface(); - std::vector list = zone.getZoneList(); + std::vector list = zone.getZoneList(state); for (std::vector::iterator it = list.begin(); it != list.end(); it++) { callback((*it).c_str(), user_data); } - return 0; -} - -int dpm_zone_get_state(dpm_zone_policy_h handle, const char* name, dpm_zone_state_e *state) -{ - RET_ON_FAILURE(handle, DPM_ERROR_INVALID_PARAMETER); - RET_ON_FAILURE(name, DPM_ERROR_INVALID_PARAMETER); - - //ZonePolicy& zone = GetPolicyInterface(handle); - - /* TODO : should implement */ - - return DPM_ERROR_INVALID_PARAMETER; + return DPM_ERROR_NONE; } diff --git a/libs/dpm/zone.h b/libs/dpm/zone.h index 17146d3..aabd556 100644 --- a/libs/dpm/zone.h +++ b/libs/dpm/zone.h @@ -124,6 +124,37 @@ DPM_API int dpm_zone_create(dpm_zone_policy_h handle, const char* name, const ch */ DPM_API int dpm_zone_destroy(dpm_zone_policy_h handle, const char* name); +/* + * @brief Enumeration for zone state + * @since_tizen 3.0 + */ +typedef enum { + DPM_ZONE_STATE_LOCKED = 0x01, /**< Zone has been defined, but it can not start. */ + DPM_ZONE_STATE_RUNNING = 0x02, /**< Zone has been started. */ + DPM_ZONE_STATE_ALL = 0xff /**< This presents all of the state */ +} dpm_zone_state_e; + +/** + * @brief Gets the zone state. + * @details This API can be used to get the state of the zone. The zone can + * have one of the three states(running, locked). + * @since_tizen 3.0 + * @param[in] handle The zone policy handle + * @param[in] name The zone name + * @param[out] state The zone state + * @return #DPM_ERROR_NONE on success, otherwise a negative value + * @retval #DPM_ERROR_NONE Successful + * @retval #DPM_ERROR_NO_DATA No such zone to get state + * @retval #DPM_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #DPM_ERROR_TIMED_OUT Time out + * @pre The handle must be created by dpm_context_acquire_zone_policy(). + * @see dpm_context_acquire_zone_policy() + * @see dpm_context_release_zone_policy() + * @see dpm_zone_create() + * @see dpm_zone_destroy() + */ +DPM_API int dpm_zone_get_state(dpm_zone_policy_h handle, const char* name, dpm_zone_state_e *state); + /** * @brief The zone list iterator handle * @since_tizen 3.0 @@ -138,6 +169,7 @@ typedef void* dpm_zone_iterator_h; * @details The zone list iterator can be used to get all defined zones. * @since_tizen 3.0 * @param[in] handle The zone policy handle + * @param[in] state a combination of the zone state to look * @return A zone list iterator on success, otherwise * null value * @remark The specific error code can be obtained by using the @@ -156,7 +188,7 @@ typedef void* dpm_zone_iterator_h; * @see dpm_zone_destroy_iterator() * @see get_last_result() */ -DPM_API dpm_zone_iterator_h dpm_zone_create_iterator(dpm_zone_policy_h handle); +DPM_API dpm_zone_iterator_h dpm_zone_create_iterator(dpm_zone_policy_h handle, dpm_zone_state_e state); /** * @brief Fetches a zone name and forwards the iterator. @@ -207,6 +239,7 @@ typedef void(*dpm_zone_foreach_cb)(const char* name, void *user_data); * with traversing the created zones list. * @since_tizen 3.0 * @param[in] handle The zone policy handle + * @param[in] state a combination of the zone state to look * @param[in] callback The iteration callback function * @param[in] user_data The user data passed to the callback function * @return #DPM_ERROR_NONE on success, otherwise a negative value @@ -220,38 +253,9 @@ typedef void(*dpm_zone_foreach_cb)(const char* name, void *user_data); * @see dpm_zone_destroy() */ DPM_API int dpm_zone_foreach_name(dpm_zone_policy_h handle, + dpm_zone_state_e state, dpm_zone_foreach_cb callback, void* user_data); -/* - * @brief Enumeration for zone state - * @since_tizen 3.0 - */ -typedef enum { - DPM_ZONE_STATE_DEFINED = 0x01, /**< ZonePolicy has been defined, but it is not running. */ - DPM_ZONE_STATE_RUNNING = 0x02, /**< ZonePolicy has been started. */ - DPM_ZONE_STATE_LOCKED = 0x03 /**< ZonePolicy has been defined, but it can not start. */ -} dpm_zone_state_e; - -/** - * @brief Gets the zone state. - * @details This API can be used to get the state of the zone. The zone can - * have one of the three states(defined, running, locked). - * @since_tizen 3.0 - * @param[in] handle The zone policy handle - * @param[in] name The zone name - * @param[out] state The zone state - * @return #DPM_ERROR_NONE on success, otherwise a negative value - * @retval #DPM_ERROR_NONE Successful - * @retval #DPM_ERROR_NO_DATA No such zone to get state - * @retval #DPM_ERROR_INVALID_PARAMETER Invalid parameter - * @retval #DPM_ERROR_TIMED_OUT Time out - * @pre The handle must be created by dpm_context_acquire_zone_policy(). - * @see dpm_context_acquire_zone_policy() - * @see dpm_context_release_zone_policy() - * @see dpm_zone_create() - * @see dpm_zone_destroy() - */ -DPM_API int dpm_zone_get_state(dpm_zone_policy_h handle, const char* name, dpm_zone_state_e *state); /** * @} diff --git a/libs/zone.cpp b/libs/zone.cpp index 7204122..0306f87 100644 --- a/libs/zone.cpp +++ b/libs/zone.cpp @@ -63,22 +63,22 @@ int ZonePolicy::unlockZone(const std::string& name) } } -std::vector ZonePolicy::getZoneList() +int ZonePolicy::getZoneState(const std::string& name) { - std::vector empty; try { - return context->methodCall>("ZonePolicy::getZoneList"); + return context->methodCall("ZonePolicy::getZoneState", name); } catch (runtime::Exception& e) { - return empty; + return -1; } } -int ZonePolicy::getZoneState(const std::string& name) +std::vector ZonePolicy::getZoneList(int state) { + std::vector empty; try { - return context->methodCall("ZonePolicy::getZoneState", name); + return context->methodCall>("ZonePolicy::getZoneList", state); } catch (runtime::Exception& e) { - return -1; + return empty; } } diff --git a/policy/zone.hxx b/policy/zone.hxx index 9c05eed..947c835 100644 --- a/policy/zone.hxx +++ b/policy/zone.hxx @@ -24,6 +24,11 @@ namespace DevicePolicyManager { class ZonePolicy { public: + enum State { + Locked = 0x01, + Running = 0x02, + }; + ZonePolicy(PolicyControlContext& ctxt); ~ZonePolicy(); @@ -32,9 +37,9 @@ public: int lockZone(const std::string& name); int unlockZone(const std::string& name); - std::vector getZoneList(void); int getZoneState(const std::string& name); + std::vector getZoneList(int state); private: PolicyControlContext& context; diff --git a/policy/zone/zone.hxx b/policy/zone/zone.hxx new file mode 100644 index 0000000..7b314b1 --- /dev/null +++ b/policy/zone/zone.hxx @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2015 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 + */ + +#ifndef __ZONE_MANAGER__ +#define __ZONE_MANAGER__ + +#include "data-type.h" +#include "policy-context.hxx" + +namespace DevicePolicyManager { + +class ZoneManager { +public: + enum State { + Locked = 0x01, + Running = 0x02, + }; + + ZoneManager(PolicyControlContext& ctxt); + ~ZoneManager(); + + int createZone(const std::string& name, const std::string& manifest); + int removeZone(const std::string& name); + int lockZone(const std::string& name); + int unlockZone(const std::string& name); + + int getZoneState(const std::string& name); + + std::vector getZoneList(int state); + +private: + PolicyControlContext& context; +}; + +} // namespace DevicePolicyManager +#endif // __ZONE_MANAGER__ diff --git a/server/app-bundle.cpp b/server/app-bundle.cpp index cec3c37..779573e 100644 --- a/server/app-bundle.cpp +++ b/server/app-bundle.cpp @@ -38,3 +38,15 @@ void Bundle::addInternal(const std::string& key, const std::string& value) { ::bundle_add_str(handle, key.c_str(), value.c_str()); } + +void Bundle::addArrayInternal(const std::string& key, const std::vector& array) +{ + std::unique_ptr arrayptr(new const char*[array.size()]); + + int index = 0; + for (const std::string& data : array) { + arrayptr.get()[index++] = data.c_str(); + } + + ::bundle_add_str_array(handle, key.c_str(), arrayptr.get(), array.size()); +} diff --git a/server/app-bundle.h b/server/app-bundle.h index 4b23974..da2ab70 100644 --- a/server/app-bundle.h +++ b/server/app-bundle.h @@ -17,9 +17,10 @@ #ifndef __DPM_BUNDLE_H__ #define __DPM_BUNDLE_H__ -#include - #include +#include + +#include #include "exception.h" @@ -29,6 +30,12 @@ public: ~Bundle(); template + void add(const std::string& key, const std::vector& value) + { + addArrayInternal(key, value); + } + + template void add(const std::string& key, const T& value) { addInternal(key, value); @@ -41,6 +48,7 @@ public: private: void addInternal(const std::string& key, const std::string& value); + void addArrayInternal(const std::string& key, const std::vector& array); private: bundle* handle; diff --git a/server/mobile.cmake b/server/mobile.cmake index 885d4d6..f2045ff 100644 --- a/server/mobile.cmake +++ b/server/mobile.cmake @@ -19,8 +19,9 @@ SET(POLICY ${POLICY} location.cpp password.cpp zone.cpp - zone/app-proxy.cpp - zone/package-proxy.cpp + zone/zone.cpp + zone/app-proxy.cpp + zone/package-proxy.cpp ) SET(DEPENDENCY ${DEPENDENCY} diff --git a/server/zone.cpp b/server/zone.cpp index a146197..2ea5ecf 100644 --- a/server/zone.cpp +++ b/server/zone.cpp @@ -13,7 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License */ +#include #include + #include #include #include @@ -21,352 +23,40 @@ #include #include "zone.hxx" +#include "zone/zone.hxx" #include "error.h" -#include "smack.h" -#include "process.h" -#include "packman.h" #include "launchpad.h" #include "filesystem.h" #include "auth/user.h" -#include "auth/group.h" -#include "xml/parser.h" -#include "xml/document.h" #include "audit/logger.h" -#include "dbus/connection.h" -#define ZONE_UID_MIN 60001 -#define ZONE_UID_MAX 65000 +#define NAME_PATTERN "^[A-Za-z_][A-Za-z0-9_.-]*" namespace DevicePolicyManager { namespace { -const std::vector defaultGroups = { - "audio", - "video", - "display", - "log" -}; - -const std::vector defaultAppDirs = { - "cache", - "data", - "shared" -}; - -const std::vector unitsToMask = { - "starter.service", - "scim.service" -}; - -const std::string ZONE_MANIFEST_DIR = CONF_PATH "/zone/"; -const std::string ZONE_PROVISION_DIR = "/tmp/zone/provision/"; - -const std::string HOME_SMACKLABEL = "User::Home"; -const std::string SHARED_SMACKLABEL = "User::App::Shared"; -const std::string APP_SMACKLABEL = "User::Pkg::"; - -const std::string ZONE_GROUP = "users"; - -template -inline void execute(const std::string& path, Args&&... args) -{ - std::vector argsVector = { args... }; - runtime::Process proc(path, argsVector); - proc.execute(); -} - -void waitForSetupWizard(const std::string& watch) -{ - int fd = ::inotify_init(); - if (fd < 0) { - throw runtime::Exception("Failed to initialize inotify"); - } - - std::string createfile; - char inotifyBuf[sizeof (struct inotify_event) + PATH_MAX + 1]; - struct inotify_event *event = reinterpret_cast((void*)inotifyBuf); - int wd = ::inotify_add_watch(fd, watch.c_str(), IN_CREATE); - - while (createfile != ".completed") { - int ret = ::read(fd, inotifyBuf, sizeof(inotifyBuf)); - if (ret < 0) { - throw runtime::Exception("Failed to get inotify"); - } - createfile = event->name; - } - - ::inotify_rm_watch(fd, wd); - ::close(fd); +namespace { +std::regex zoneNamePattern(NAME_PATTERN); } -std::string prepareDirectories(const runtime::User& user) -{ - //create zone home directories - const struct { - enum tzplatform_variable dir; - const std::string& smack; - } dirs[] = { - {TZ_USER_HOME, HOME_SMACKLABEL}, - {TZ_USER_CACHE, SHARED_SMACKLABEL}, - {TZ_USER_APPROOT, HOME_SMACKLABEL}, - {TZ_USER_DB, HOME_SMACKLABEL}, - {TZ_USER_PACKAGES, HOME_SMACKLABEL}, - {TZ_USER_ICONS, HOME_SMACKLABEL}, - {TZ_USER_CONFIG, SHARED_SMACKLABEL}, - {TZ_USER_DATA, HOME_SMACKLABEL}, - {TZ_USER_SHARE, SHARED_SMACKLABEL}, - {TZ_USER_ETC, HOME_SMACKLABEL}, - {TZ_USER_LIVE, HOME_SMACKLABEL}, - {TZ_USER_UG, HOME_SMACKLABEL}, - {TZ_USER_APP, HOME_SMACKLABEL}, - {TZ_USER_CONTENT, SHARED_SMACKLABEL}, - {TZ_USER_CAMERA, SHARED_SMACKLABEL}, - {TZ_USER_VIDEOS, SHARED_SMACKLABEL}, - {TZ_USER_IMAGES, SHARED_SMACKLABEL}, - {TZ_USER_SOUNDS, SHARED_SMACKLABEL}, - {TZ_USER_MUSIC, SHARED_SMACKLABEL}, - {TZ_USER_GAMES, SHARED_SMACKLABEL}, - {TZ_USER_DOCUMENTS, SHARED_SMACKLABEL}, - {TZ_USER_OTHERS, SHARED_SMACKLABEL}, - {TZ_USER_DOWNLOADS, SHARED_SMACKLABEL}, - {TZ_SYS_HOME, ""}, - }; - - ::umask(0022); - - ::tzplatform_set_user(user.getUid()); - - std::string pivot(::tzplatform_getenv(TZ_USER_HOME)); - - try { - for (int i = 0; dirs[i].dir != TZ_SYS_HOME; i++) { - runtime::File dir(::tzplatform_getenv(dirs[i].dir)); - dir.makeDirectory(false, user.getUid(), user.getGid()); - runtime::Smack::setAccess(dir, dirs[i].smack); - runtime::Smack::setTransmute(dir, true); - } - } catch (runtime::Exception& e) { - ::tzplatform_reset_user(); - throw runtime::Exception(e.what()); +bool isAllowedName(const std::string& name) { + if (!std::regex_match(name, zoneNamePattern)) { + return false; } - ::tzplatform_reset_user(); - - return pivot; -} - -void deployPackages(const runtime::User& user) -{ + bool exists = false; try { - //initialize package db - execute("/usr/bin/pkg_initdb", "pkg_initdb", - "--uid", std::to_string(user.getUid())); - - PackageManager& packageManager = PackageManager::instance(); - std::vector pkgList = packageManager.getPackageList(user.getUid()); - - ::umask(0022); - - ::tzplatform_set_user(user.getUid()); - for (const std::string& pkgid : pkgList) { - std::string appbase = std::string(::tzplatform_getenv(TZ_USER_APP)) + "/" + pkgid; - runtime::File dir(appbase); - dir.makeDirectory(false, user.getUid(), user.getGid()); - runtime::Smack::setAccess(dir, APP_SMACKLABEL + pkgid); - runtime::Smack::setTransmute(dir, true); - - for (const std::string& subdir : defaultAppDirs) { - runtime::File insideDir(appbase + "/" + subdir); - insideDir.makeDirectory(false, user.getUid(), user.getGid()); - } - } - ::tzplatform_reset_user(); - } catch (runtime::Exception& e) { - ::tzplatform_reset_user(); - throw runtime::Exception(e.what()); - } -} - -void maskUserServices(const std::string& pivot, const runtime::User& user) -{ - runtime::File unitbase(pivot + "/.config/systemd/user"); - unitbase.makeDirectory(true); - unitbase.chmod(S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); - - for (const std::string& unit : unitsToMask) { - std::string target = unitbase.getPath() + "/" + unit; - if (::symlink("/dev/null", target.c_str()) == -1) { - throw runtime::Exception(runtime::GetSystemErrorMessage()); - } - } -} - -void setZoneState(uid_t id, int state) -{ - dbus::Connection& systemDBus = dbus::Connection::getSystem(); - systemDBus.methodcall("org.freedesktop.login1", - "/org/freedesktop/login1", - "org.freedesktop.login1.Manager", - "SetUserLinger", - -1, "", "(ubb)", id, state, 1); -} - -void startZoneProvisioningThread(PolicyControlContext& context, const std::string& name, const std::string& watch) -{ - auto provisioningWorker = [name, watch, &context]() { - std::unique_ptr manifest; - - mode_t omask = ::umask(0); - try { - waitForSetupWizard(watch); - - //create zone user - runtime::User user = runtime::User::create(name, ZONE_GROUP, ZONE_UID_MIN, ZONE_UID_MAX); - for (const std::string& grp : defaultGroups) { - runtime::Group group(grp); - group.addMember(name); - } - - std::string pivot = prepareDirectories(user); - maskUserServices(pivot, user); - deployPackages(user); - - //initialize security-manager - execute("/usr/bin/security-manager-cmd", - "security-manager-cmd", "--manage-users=add", - "--uid=" + std::to_string(user.getUid()), - "--usertype=normal"); - - //change group to system_share - runtime::Group systemShareGroup("system_share"); - ::tzplatform_set_user(user.getUid()); - runtime::File appRootDir(::tzplatform_getenv(TZ_USER_APPROOT)); - runtime::File dbDir(::tzplatform_getenv(TZ_USER_DB)); - ::tzplatform_reset_user(); - appRootDir.chown(user.getUid(), systemShareGroup.getGid()); - appRootDir.chmod(0750); - - dbDir.chown(user.getUid(), systemShareGroup.getGid()); - dbDir.chmod(0770); - - manifest.reset(xml::Parser::parseFile(watch + "/manifest.xml")); - ::umask(0077); - manifest->write(ZONE_MANIFEST_DIR + name + ".xml", "UTF-8", true); - - //TODO: write container owner info - - //unlock the user - setZoneState(user.getUid(), 1); - - context.notify("ZonePolicy::created", name, std::string()); - } catch (runtime::Exception& e) { - ERROR(e.what()); - context.notify("ZonePolicy::removed", name, std::string()); - } - - ::umask(omask); - }; - - std::thread asyncWork(provisioningWorker); - asyncWork.detach(); -} - -const std::string convertPathForOwner(const std::string& path, const runtime::User& user, const runtime::User& owner) -{ - ::tzplatform_set_user(owner.getUid()); - std::string ownerHome(::tzplatform_getenv(TZ_USER_HOME)); - ::tzplatform_reset_user(); - ownerHome += "/.zone"; - - ::tzplatform_set_user(user.getUid()); - std::string userHome(::tzplatform_getenv(TZ_USER_HOME)); - ::tzplatform_reset_user(); - - std::string userHomeForOwner(ownerHome + "/" + user.getName()); - - std::string convertedPath(path); - - if (convertedPath.compare(0, userHome.size(), userHome) == 0) { - convertedPath.replace(0, userHome.size(), userHomeForOwner); - } - - return convertedPath; -} + runtime::User user(name); + exists = true; + } catch (runtime::Exception& e) {} -void prepareFileForOwner(const std::string path, const runtime::User& pkgUser, const runtime::User& owner) -{ - std::string pathLink = convertPathForOwner(path, pkgUser, owner); - - if (path != pathLink) { - runtime::File linkFile(pathLink); - linkFile.makeBaseDirectory(pkgUser.getUid(), pkgUser.getGid()); - if (linkFile.exists()) { - linkFile.remove(); - } - - int ret = ::link(path.c_str(), pathLink.c_str()); - if (ret != 0) { - //TODO: copy the icon instead of linking - throw runtime::Exception("Failed to link from " + path + - " to " + pathLink); - } - } + return !exists; } -int packageEventHandler(uid_t target_uid, int req_id, - const char *pkg_type, const char *pkgid, - const char *key, const char *val, - const void *pmsg, void *data) -{ - static std::string type; - std::string keystr = key; - - if (target_uid == tzplatform_getuid(TZ_SYS_GLOBALAPP_USER)) { - return 0; - } - - std::transform(keystr.begin(), keystr.end(), keystr.begin(), ::tolower); - if (keystr == "start") { - type = val; - std::transform(type.begin(), type.end(), type.begin(), ::tolower); - return 0; - } else if (keystr != "end" && keystr != "ok") { - return 0; - } - - try { - runtime::User owner("owner"), pkgUser(target_uid); - - if (type == "install" || type == "update") { - PackageInfo info(pkgid, pkgUser.getUid()); - std::string icon = info.getIcon(); - prepareFileForOwner(icon, pkgUser, owner); - - for (const std::string &appid : info.getAppList()) { - ApplicationInfo info(appid, pkgUser.getUid()); - std::string icon = info.getIcon(); - prepareFileForOwner(icon, pkgUser, owner); - } - } else { - ::tzplatform_set_user(pkgUser.getUid()); - std::string pkgPath(::tzplatform_getenv(TZ_USER_APP)); - pkgPath = pkgPath + "/" + pkgid; - ::tzplatform_reset_user(); - - runtime::File pkgDirForOwner(convertPathForOwner(pkgPath, pkgUser, owner)); - pkgDirForOwner.remove(true); - } - } catch (runtime::Exception &e) { - ERROR(e.what()); - } - - return 0; } -} // namespace - ZonePolicy::ZonePolicy(PolicyControlContext& ctx) : context(ctx) { @@ -374,50 +64,40 @@ ZonePolicy::ZonePolicy(PolicyControlContext& ctx) context.registerParametricMethod(this, (int)(ZonePolicy::removeZone)(std::string)); context.registerParametricMethod(this, (int)(ZonePolicy::lockZone)(std::string)); context.registerParametricMethod(this, (int)(ZonePolicy::unlockZone)(std::string)); - context.registerNonparametricMethod(this, (std::vector)(ZonePolicy::getZoneList)()); context.registerParametricMethod(this, (int)(ZonePolicy::getZoneState)(std::string)); + context.registerParametricMethod(this, (std::vector)(ZonePolicy::getZoneList)(int)); context.createNotification("ZonePolicy::created"); context.createNotification("ZonePolicy::removed"); - - PackageManager& packageManager = PackageManager::instance(); - packageManager.setEventCallback(packageEventHandler, this); } ZonePolicy::~ZonePolicy() { - PackageManager& packageManager = PackageManager::instance(); - packageManager.unsetEventCallback(); } + int ZonePolicy::createZone(const std::string& name, const std::string& setupWizAppid) { - std::string provisionDirPath(ZONE_PROVISION_DIR + name); - runtime::File provisionDir(provisionDirPath); - - try { - if (provisionDir.exists()) { - provisionDir.remove(true); - } + if (!std::regex_match(name, zoneNamePattern)) { + return -1; + } - //create a directory for zone setup - provisionDir.makeDirectory(true); - runtime::Smack::setAccess(provisionDir, APP_SMACKLABEL + setupWizAppid); + if (!isAllowedName(name)) { + return -1; + } + try { + std::vector data = {"app-id", "org.tizen.zone-setup-wizard", + "mode", "create", + "zone", name}; Bundle bundle; - bundle.add("zone", name); - bundle.add("provisionDir", provisionDirPath); + bundle.add("id", "zone-create"); + bundle.add("user-data", data); Launchpad launchpad(context.getPeerUid()); - launchpad.launch(setupWizAppid, bundle); - - startZoneProvisioningThread(context, name, provisionDirPath); + launchpad.launch("org.tizen.dpm-syspopup", bundle); } catch (runtime::Exception& e) { ERROR(e.what()); - - if (provisionDir.exists()) { - provisionDir.remove(true); - } return -1; } @@ -426,48 +106,20 @@ int ZonePolicy::createZone(const std::string& name, const std::string& setupWizA int ZonePolicy::removeZone(const std::string& name) { - if (lockZone(name) != 0) { + if (getZoneState(name) < 0) { return -1; } - auto remove = [name, this] { - runtime::File manifest(ZONE_MANIFEST_DIR + name + ".xml"); - - try { - runtime::User user(name); - - //remove notification for ckm-tool - execute("/usr/bin/ckm_tool", - "ckm_tool", "-d", std::to_string(user.getUid())); - - //initialize security-manager - execute("/usr/bin/security-manager-cmd", - "security-manager-cmd", - "--manage-users=remove", - "--uid=" + std::to_string(user.getUid())); - - //remove zone user - user.remove(); - manifest.remove(); - - context.notify("ZonePolicy::removed", name, std::string()); - } catch (runtime::Exception& e) { - ERROR(e.what()); - return; - } - }; - - std::thread asyncWork(remove); - asyncWork.detach(); - - return 0; -} - -int ZonePolicy::lockZone(const std::string& name) -{ try { - runtime::User user(name); - setZoneState(user.getUid(), 0); + std::vector data = {"app-id", "org.tizen.zone-setup-wizard", + "mode", "remove", + "zone", name}; + Bundle bundle; + bundle.add("id", "zone-remove"); + bundle.add("user-data", data); + + Launchpad launchpad(context.getPeerUid()); + launchpad.launch("org.tizen.dpm-syspopup", bundle); } catch (runtime::Exception& e) { ERROR(e.what()); return -1; @@ -476,27 +128,27 @@ int ZonePolicy::lockZone(const std::string& name) return 0; } -int ZonePolicy::unlockZone(const std::string& name) -{ - try { - runtime::User user(name); - setZoneState(user.getUid(), 1); - } catch (runtime::Exception& e) { - ERROR(e.what()); - return -1; - } +/* [TBD] remove dependency with zoneManager like this */ +extern ZoneManager zoneManager; - return 0; +int ZonePolicy::lockZone(const std::string& name) +{ + return zoneManager.lockZone(name); } -std::vector ZonePolicy::getZoneList() +int ZonePolicy::unlockZone(const std::string& name) { - return std::vector(); + return zoneManager.unlockZone(name); } int ZonePolicy::getZoneState(const std::string& name) { - return 0; + return zoneManager.getZoneState(name); +} + +std::vector ZonePolicy::getZoneList(int state) +{ + return zoneManager.getZoneList(state); } ZonePolicy zonePolicy(Server::instance()); diff --git a/server/zone/zone.cpp b/server/zone/zone.cpp new file mode 100644 index 0000000..98e0035 --- /dev/null +++ b/server/zone/zone.cpp @@ -0,0 +1,491 @@ +/* + * Copyright (c) 2015 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 + */ +#include +#include +#include +#include + +#include + +#include "zone/zone.hxx" + +#include "error.h" +#include "smack.h" +#include "process.h" +#include "packman.h" +#include "launchpad.h" +#include "filesystem.h" +#include "auth/user.h" +#include "auth/group.h" +#include "xml/parser.h" +#include "xml/document.h" +#include "audit/logger.h" +#include "dbus/connection.h" + +#define ZONE_UID_MIN 60001 +#define ZONE_UID_MAX 65000 + +namespace DevicePolicyManager { + +namespace { + +const std::vector defaultGroups = { + "audio", + "video", + "display", + "log" +}; + +const std::vector defaultAppDirs = { + "cache", + "data", + "shared" +}; + +const std::vector unitsToMask = { + "starter.service", + "scim.service" +}; + +const std::string ZONE_MANIFEST_DIR = CONF_PATH "/zone/"; + +const std::string HOME_SMACKLABEL = "User::Home"; +const std::string SHARED_SMACKLABEL = "User::App::Shared"; +const std::string APP_SMACKLABEL = "User::Pkg::"; + +const std::string ZONE_GROUP = "users"; + +template +inline void execute(const std::string& path, Args&&... args) +{ + std::vector argsVector = { args... }; + runtime::Process proc(path, argsVector); + proc.execute(); +} + +inline std::string prepareDirectories(const runtime::User& user) +{ + //create zone home directories + const struct { + enum tzplatform_variable dir; + const std::string& smack; + } dirs[] = { + {TZ_USER_HOME, HOME_SMACKLABEL}, + {TZ_USER_CACHE, SHARED_SMACKLABEL}, + {TZ_USER_APPROOT, HOME_SMACKLABEL}, + {TZ_USER_DB, HOME_SMACKLABEL}, + {TZ_USER_PACKAGES, HOME_SMACKLABEL}, + {TZ_USER_ICONS, HOME_SMACKLABEL}, + {TZ_USER_CONFIG, SHARED_SMACKLABEL}, + {TZ_USER_DATA, HOME_SMACKLABEL}, + {TZ_USER_SHARE, SHARED_SMACKLABEL}, + {TZ_USER_ETC, HOME_SMACKLABEL}, + {TZ_USER_LIVE, HOME_SMACKLABEL}, + {TZ_USER_UG, HOME_SMACKLABEL}, + {TZ_USER_APP, HOME_SMACKLABEL}, + {TZ_USER_CONTENT, SHARED_SMACKLABEL}, + {TZ_USER_CAMERA, SHARED_SMACKLABEL}, + {TZ_USER_VIDEOS, SHARED_SMACKLABEL}, + {TZ_USER_IMAGES, SHARED_SMACKLABEL}, + {TZ_USER_SOUNDS, SHARED_SMACKLABEL}, + {TZ_USER_MUSIC, SHARED_SMACKLABEL}, + {TZ_USER_GAMES, SHARED_SMACKLABEL}, + {TZ_USER_DOCUMENTS, SHARED_SMACKLABEL}, + {TZ_USER_OTHERS, SHARED_SMACKLABEL}, + {TZ_USER_DOWNLOADS, SHARED_SMACKLABEL}, + {TZ_SYS_HOME, ""}, + }; + + ::umask(0022); + + ::tzplatform_set_user(user.getUid()); + + std::string pivot(::tzplatform_getenv(TZ_USER_HOME)); + + try { + for (int i = 0; dirs[i].dir != TZ_SYS_HOME; i++) { + runtime::File dir(::tzplatform_getenv(dirs[i].dir)); + dir.makeDirectory(false, user.getUid(), user.getGid()); + runtime::Smack::setAccess(dir, dirs[i].smack); + runtime::Smack::setTransmute(dir, true); + } + } catch (runtime::Exception& e) { + ::tzplatform_reset_user(); + throw runtime::Exception(e.what()); + } + + ::tzplatform_reset_user(); + + return pivot; +} + +inline void deployPackages(const runtime::User& user) +{ + try { + //initialize package db + execute("/usr/bin/pkg_initdb", "pkg_initdb", + "--uid", std::to_string(user.getUid())); + + PackageManager& packageManager = PackageManager::instance(); + std::vector pkgList = packageManager.getPackageList(user.getUid()); + + ::umask(0022); + + ::tzplatform_set_user(user.getUid()); + for (const std::string& pkgid : pkgList) { + std::string appbase = std::string(::tzplatform_getenv(TZ_USER_APP)) + "/" + pkgid; + runtime::File dir(appbase); + dir.makeDirectory(false, user.getUid(), user.getGid()); + runtime::Smack::setAccess(dir, APP_SMACKLABEL + pkgid); + runtime::Smack::setTransmute(dir, true); + + for (const std::string& subdir : defaultAppDirs) { + runtime::File insideDir(appbase + "/" + subdir); + insideDir.makeDirectory(false, user.getUid(), user.getGid()); + } + } + ::tzplatform_reset_user(); + } catch (runtime::Exception& e) { + ::tzplatform_reset_user(); + throw runtime::Exception(e.what()); + } +} + +inline void maskUserServices(const std::string& pivot, const runtime::User& user) +{ + runtime::File unitbase(pivot + "/.config/systemd/user"); + unitbase.makeDirectory(true); + unitbase.chmod(S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); + + for (const std::string& unit : unitsToMask) { + std::string target = unitbase.getPath() + "/" + unit; + if (::symlink("/dev/null", target.c_str()) == -1) { + throw runtime::Exception(runtime::GetSystemErrorMessage()); + } + } +} + +inline void setZoneState(uid_t id, int state) +{ + dbus::Connection& systemDBus = dbus::Connection::getSystem(); + systemDBus.methodcall("org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "SetUserLinger", + -1, "", "(ubb)", id, state, 1); +} + +inline const std::string convertPathForOwner(const std::string& path, const runtime::User& user, const runtime::User& owner) +{ + ::tzplatform_set_user(owner.getUid()); + std::string ownerHome(::tzplatform_getenv(TZ_USER_HOME)); + ::tzplatform_reset_user(); + ownerHome += "/.zone"; + + ::tzplatform_set_user(user.getUid()); + std::string userHome(::tzplatform_getenv(TZ_USER_HOME)); + ::tzplatform_reset_user(); + + std::string userHomeForOwner(ownerHome + "/" + user.getName()); + + std::string convertedPath(path); + + if (convertedPath.compare(0, userHome.size(), userHome) == 0) { + convertedPath.replace(0, userHome.size(), userHomeForOwner); + } + + return convertedPath; +} + +inline void prepareFileForOwner(const std::string path, const runtime::User& pkgUser, const runtime::User& owner) +{ + std::string pathLink = convertPathForOwner(path, pkgUser, owner); + + if (path != pathLink) { + runtime::File linkFile(pathLink); + linkFile.makeBaseDirectory(pkgUser.getUid(), pkgUser.getGid()); + if (linkFile.exists()) { + linkFile.remove(); + } + + int ret = ::link(path.c_str(), pathLink.c_str()); + if (ret != 0) { + //TODO: copy the icon instead of linking + throw runtime::Exception("Failed to link from " + path + + " to " + pathLink); + } + } +} + +int packageEventHandler(uid_t target_uid, int req_id, + const char *pkg_type, const char *pkgid, + const char *key, const char *val, + const void *pmsg, void *data) +{ + static std::string type; + std::string keystr = key; + + if (target_uid == tzplatform_getuid(TZ_SYS_GLOBALAPP_USER)) { + return 0; + } + + std::transform(keystr.begin(), keystr.end(), keystr.begin(), ::tolower); + if (keystr == "start") { + type = val; + std::transform(type.begin(), type.end(), type.begin(), ::tolower); + return 0; + } else if (keystr != "end" && keystr != "ok") { + return 0; + } + + try { + runtime::User owner("owner"), pkgUser(target_uid); + + if (type == "install" || type == "update") { + PackageInfo info(pkgid, pkgUser.getUid()); + std::string icon = info.getIcon(); + prepareFileForOwner(icon, pkgUser, owner); + + for (const std::string &appid : info.getAppList()) { + ApplicationInfo info(appid, pkgUser.getUid()); + std::string icon = info.getIcon(); + prepareFileForOwner(icon, pkgUser, owner); + } + } else { + ::tzplatform_set_user(pkgUser.getUid()); + std::string pkgPath(::tzplatform_getenv(TZ_USER_APP)); + pkgPath = pkgPath + "/" + pkgid; + ::tzplatform_reset_user(); + + runtime::File pkgDirForOwner(convertPathForOwner(pkgPath, pkgUser, owner)); + pkgDirForOwner.remove(true); + } + } catch (runtime::Exception &e) { + ERROR(e.what()); + } + + return 0; +} + +} // namespace + +ZoneManager::ZoneManager(PolicyControlContext& ctx) + : context(ctx) +{ + context.registerParametricMethod(this, (int)(ZoneManager::createZone)(std::string, std::string)); + context.registerParametricMethod(this, (int)(ZoneManager::removeZone)(std::string)); + context.registerParametricMethod(this, (int)(ZoneManager::lockZone)(std::string)); + context.registerParametricMethod(this, (int)(ZoneManager::unlockZone)(std::string)); + context.registerParametricMethod(this, (int)(ZoneManager::getZoneState)(std::string)); + context.registerParametricMethod(this, (std::vector)(ZoneManager::getZoneList)(int)); + + context.createNotification("ZoneManager::created"); + context.createNotification("ZoneManager::removed"); + + PackageManager& packageManager = PackageManager::instance(); + packageManager.setEventCallback(packageEventHandler, this); +} + +ZoneManager::~ZoneManager() +{ + PackageManager& packageManager = PackageManager::instance(); + packageManager.unsetEventCallback(); +} + +int ZoneManager::createZone(const std::string& name, const std::string& manifest) +{ + auto provisioningWorker = [name, manifest, this]() { + std::unique_ptr manifestFile; + + mode_t omask = ::umask(0); + try { + //create zone user + runtime::User user = runtime::User::create(name, + ZONE_GROUP, ZONE_UID_MIN, ZONE_UID_MAX); + for (const std::string& grp : defaultGroups) { + runtime::Group group(grp); + group.addMember(name); + } + + std::string pivot = prepareDirectories(user); + maskUserServices(pivot, user); + deployPackages(user); + + //initialize security-manager + execute("/usr/bin/security-manager-cmd", + "security-manager-cmd", "--manage-users=add", + "--uid=" + std::to_string(user.getUid()), + "--usertype=normal"); + + //change group to system_share + runtime::Group systemShareGroup("system_share"); + ::tzplatform_set_user(user.getUid()); + runtime::File appRootDir(::tzplatform_getenv(TZ_USER_APPROOT)); + runtime::File dbDir(::tzplatform_getenv(TZ_USER_DB)); + ::tzplatform_reset_user(); + + appRootDir.chown(user.getUid(), systemShareGroup.getGid()); + appRootDir.chmod(0750); + dbDir.chown(user.getUid(), systemShareGroup.getGid()); + dbDir.chmod(0770); + + manifestFile.reset(xml::Parser::parseString(manifest)); + ::umask(0077); + manifestFile->write(ZONE_MANIFEST_DIR + name + ".xml", "UTF-8", true); + + //TODO: write container owner info + + //unlock the user + setZoneState(user.getUid(), 1); + + context.notify("ZoneManager::created", name, std::string()); + } catch (runtime::Exception& e) { + ERROR(e.what()); + context.notify("ZoneManager::removed", name, std::string()); + } + + ::umask(omask); + }; + + std::thread asyncWork(provisioningWorker); + asyncWork.detach(); + + return 0; +} + +int ZoneManager::removeZone(const std::string& name) +{ + if (lockZone(name) != 0) { + return -1; + } + + try { + runtime::File manifest(ZONE_MANIFEST_DIR + name + ".xml"); + manifest.remove(); + } catch (runtime::Exception& e) { + return -1; + } + + auto remove = [name, this] { + try { + runtime::User user(name); + + //remove notification for ckm-tool + execute("/usr/bin/ckm_tool", + "ckm_tool", "-d", std::to_string(user.getUid())); + + //initialize security-manager + execute("/usr/bin/security-manager-cmd", + "security-manager-cmd", + "--manage-users=remove", + "--uid=" + std::to_string(user.getUid())); + + //remove zone user + user.remove(); + + context.notify("ZoneManager::removed", name, std::string()); + } catch (runtime::Exception& e) { + ERROR(e.what()); + return; + } + }; + + std::thread asyncWork(remove); + asyncWork.detach(); + + return 0; +} + +int ZoneManager::lockZone(const std::string& name) +{ + try { + runtime::User user(name); + setZoneState(user.getUid(), 0); + } catch (runtime::Exception& e) { + ERROR(e.what()); + return -1; + } + + return 0; +} + +int ZoneManager::unlockZone(const std::string& name) +{ + try { + runtime::User user(name); + setZoneState(user.getUid(), 1); + } catch (runtime::Exception& e) { + ERROR(e.what()); + return -1; + } + + return 0; +} + +int ZoneManager::getZoneState(const std::string& name) +{ + runtime::File manifest(ZONE_MANIFEST_DIR + name + ".xml"); + if (!manifest.exists()) { + return -1; + } + + try { + runtime::User user(name); + dbus::Connection& systemDBus = dbus::Connection::getSystem(); + const dbus::Variant& var = systemDBus.methodcall + ("org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "GetUser", + -1, "(o)", "(u)", user.getUid()); + if (var) { + return ZoneManager::State::Running; + } else { + return ZoneManager::State::Locked; + } + } catch (runtime::Exception& e) { + ERROR(e.what()); + return -1; + } + + return 0; +} + +std::vector ZoneManager::getZoneList(int state) +{ + std::vector list; + try { + runtime::Path manifestDir(ZONE_MANIFEST_DIR); + runtime::DirectoryIterator iter(manifestDir), end; + + while (iter != end) { + const std::string& path = iter->getPath(); + size_t namePos = path.rfind('/') + 1; + size_t extPos = path.rfind(".xml"); + const std::string& name(path.substr(namePos, extPos - namePos)); + if (getZoneState(name) & state) { + list.push_back(name); + } + ++iter; + } + } catch (runtime::Exception& e) {} + + return list; +} + +ZoneManager zoneManager(Server::instance()); + +} // namespace DevicePolicyManager diff --git a/zone/libs/CMakeLists.txt b/zone/libs/CMakeLists.txt index d8697f4..7956bd3 100755 --- a/zone/libs/CMakeLists.txt +++ b/zone/libs/CMakeLists.txt @@ -21,6 +21,7 @@ SET(LIB_SOVERSION "0") SET(PC_FILE "${PROJECT_NAME}.pc") SET(SOURCES ${DPM_LIBS}/policy-client.cpp + zone.cpp package-proxy.cpp app-proxy.cpp zone/zone.cpp diff --git a/zone/libs/zone.cpp b/zone/libs/zone.cpp new file mode 100644 index 0000000..2cb762d --- /dev/null +++ b/zone/libs/zone.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2015 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 + */ + +#include "zone/zone.hxx" + +namespace DevicePolicyManager { + +ZoneManager::ZoneManager(PolicyControlContext& ctx) + : context(ctx) +{ +} + +ZoneManager::~ZoneManager() +{ +} + +int ZoneManager::createZone(const std::string& name, const std::string& setupWizAppid) +{ + try { + return context->methodCall("ZoneManager::createZone", name, setupWizAppid); + } catch (runtime::Exception& e) { + return -1; + } +} + +int ZoneManager::removeZone(const std::string& name) +{ + try { + return context->methodCall("ZoneManager::removeZone", name); + } catch (runtime::Exception& e) { + return -1; + } +} + +int ZoneManager::lockZone(const std::string& name) +{ + try { + return context->methodCall("ZoneManager::lockZone", name); + } catch (runtime::Exception& e) { + return -1; + } +} + +int ZoneManager::unlockZone(const std::string& name) +{ + try { + return context->methodCall("ZoneManager::unlockZone", name); + } catch (runtime::Exception& e) { + return -1; + } +} + +int ZoneManager::getZoneState(const std::string& name) +{ + try { + return context->methodCall("ZoneManager::getZoneState", name); + } catch (runtime::Exception& e) { + return -1; + } +} + +std::vector ZoneManager::getZoneList(int state) +{ + std::vector empty; + try { + return context->methodCall>("ZoneManager::getZoneList", state); + } catch (runtime::Exception& e) { + return empty; + } +} + +} // namespace DevicePolicyManager diff --git a/zone/libs/zone/zone.cpp b/zone/libs/zone/zone.cpp index ace6c7f..97a6eda 100644 --- a/zone/libs/zone/zone.cpp +++ b/zone/libs/zone/zone.cpp @@ -18,7 +18,12 @@ #include "error.h" #include "debug.h" +#include "array.h" + #include "policy-client.h" +#include "zone/zone.hxx" + +using namespace DevicePolicyManager; DevicePolicyContext& GetDevicePolicyContext(void* handle) { @@ -59,7 +64,7 @@ int zone_manager_add_event_cb(zone_manager_h handle, const char* event, zone_eve RET_ON_FAILURE(callback, ZONE_ERROR_INVALID_PARAMETER); DevicePolicyContext &context = GetDevicePolicyContext(handle); - int ret = context.subscribeSignal(std::string("ZonePolicy::") + event, + int ret = context.subscribeSignal(std::string("ZoneManager::") + event, callback, user_data); if (ret < 0) return ZONE_ERROR_INVALID_PARAMETER; @@ -80,3 +85,94 @@ int zone_manager_remove_event_cb(zone_manager_h handle, int callback_id) return ZONE_ERROR_NONE; } + +int zone_manager_create_zone(zone_manager_h handle, const char* name, const char* manifest) +{ + RET_ON_FAILURE(handle, ZONE_ERROR_INVALID_PARAMETER); + RET_ON_FAILURE(name, ZONE_ERROR_INVALID_PARAMETER); + RET_ON_FAILURE(manifest, ZONE_ERROR_INVALID_PARAMETER); + + DevicePolicyContext &client = GetDevicePolicyContext(handle); + ZoneManager zone = client.createPolicyInterface(); + return zone.createZone(name, manifest); +} + +int zone_manager_destroy_zone(zone_manager_h handle, const char* name) +{ + RET_ON_FAILURE(handle, ZONE_ERROR_INVALID_PARAMETER); + RET_ON_FAILURE(name, ZONE_ERROR_INVALID_PARAMETER); + + DevicePolicyContext &client = GetDevicePolicyContext(handle); + ZoneManager zone = client.createPolicyInterface(); + return zone.removeZone(name); +} + +int zone_manager_get_zone_state(zone_manager_h handle, const char* name, zone_state_e *state) +{ + RET_ON_FAILURE(handle, ZONE_ERROR_INVALID_PARAMETER); + RET_ON_FAILURE(name, ZONE_ERROR_INVALID_PARAMETER); + + DevicePolicyContext &client = GetDevicePolicyContext(handle); + ZoneManager zone = client.createPolicyInterface(); + + int result = zone.getZoneState(name); + if (result <0) { + return ZONE_ERROR_NO_DATA; + } + + *state = (zone_state_e)result; + return ZONE_ERROR_NONE; +} + +typedef runtime::Array zone_iterator; + +zone_iterator_h zone_manager_create_iterator(zone_manager_h handle, zone_state_e state) +{ + RET_ON_FAILURE(handle, NULL); + + DevicePolicyContext &client = GetDevicePolicyContext(handle); + ZoneManager zone = client.createPolicyInterface(); + + return reinterpret_cast(new zone_iterator(zone.getZoneList(state))); +} + +int zone_iterator_next(zone_iterator_h iter, const char** result) +{ + RET_ON_FAILURE(iter, ZONE_ERROR_INVALID_PARAMETER); + RET_ON_FAILURE(result, ZONE_ERROR_INVALID_PARAMETER); + + zone_iterator* it = reinterpret_cast(iter); + + if (it->isEnd()) + *result = NULL; + else + *result = it->next()->c_str(); + + return ZONE_ERROR_NONE; +} + +int zone_manager_destroy_iterator(zone_iterator_h iter) +{ + RET_ON_FAILURE(iter, ZONE_ERROR_INVALID_PARAMETER); + + delete reinterpret_cast(iter); + + return ZONE_ERROR_NONE; +} + +int zone_manager_foreach_name(zone_manager_h handle, zone_state_e state, + zone_manager_foreach_cb callback, void* user_data) +{ + RET_ON_FAILURE(handle, ZONE_ERROR_INVALID_PARAMETER); + RET_ON_FAILURE(callback, ZONE_ERROR_INVALID_PARAMETER); + + DevicePolicyContext &client = GetDevicePolicyContext(handle); + ZoneManager zone = client.createPolicyInterface(); + std::vector list = zone.getZoneList(state); + for (std::vector::iterator it = list.begin(); + it != list.end(); it++) { + callback((*it).c_str(), user_data); + } + + return ZONE_ERROR_NONE; +} diff --git a/zone/libs/zone/zone.h b/zone/libs/zone/zone.h index e4b13fc..bde0220 100644 --- a/zone/libs/zone/zone.h +++ b/zone/libs/zone/zone.h @@ -58,7 +58,8 @@ typedef enum { ZONE_ERROR_NOT_SUPPORTED = TIZEN_ERROR_NOT_SUPPORTED, /**< Operation is not supported */ ZONE_ERROR_NO_SUCH_FILE = TIZEN_ERROR_NO_SUCH_FILE, /**< No such file or directory */ ZONE_ERROR_FILE_EXISTS = TIZEN_ERROR_FILE_EXISTS, /**< File exists */ - ZONE_ERROR_OUT_OF_MEMORY = TIZEN_ERROR_OUT_OF_MEMORY /**< Out of memory */ + ZONE_ERROR_OUT_OF_MEMORY = TIZEN_ERROR_OUT_OF_MEMORY, /**< Out of memory */ + ZONE_ERROR_NO_DATA = TIZEN_ERROR_NO_DATA /**< No Data */ } zone_error_type_e; /** @@ -116,7 +117,7 @@ ZONE_API int zone_manager_destroy(zone_manager_h handle); * @see zone_manager_add_event_cb() * @see zone_manager_remove_event_cb() */ -typedef void(*zone_event_cb)(const char* name, const char* object, void *user_data); +typedef void(*zone_event_cb)(const char* name, const char* object, void* user_data); /** * @brief Adds zone event callback. @@ -161,6 +162,186 @@ ZONE_API int zone_manager_add_event_cb(zone_manager_h handle, ZONE_API int zone_manager_remove_event_cb(zone_manager_h handle, int id); /** + * @brief Creates a new zone. + * @details This API creates a container. All file system objects neeeded + * will be also created. manifest XML passed by parameter will be + * used when the zone is running. + * @since_tizen 3.0 + * @param[in] handle The zone manager handle + * @param[in] name The zone name to be created + * @param[in] manifest The manifest XML to be used when the zone is runned. + * @return #ZONE_ERROR_NONE on success, otherwise a negative value + * @retval #ZONE_ERROR_NONE Successful + * @retval #ZONE_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #ZONE_ERROR_TIMED_OUT Time out + * @retval #ZONE_ERROR_PERMISSION_DENIED The application does not have + * the privilege to call this API + * @pre The handle must be created by zone_manager_create(). + * @see zone_manager_create() + * @see zone_manager_destroy() + * @see zone_manager_destroy_zone() + * @see zone_manager_create_zone_iterator() + */ +ZONE_API int zone_manager_create_zone(zone_manager_h handle, const char* name, const char* manifest); + +/** + * @brief Removes existing zone. + * @details This removes zone. All file system objects created for the zone + * will be also erased. + * @since_tizen 3.0 + * @param[in] handle The zone manager handle + * @param[in] name The zone name to be removed + * @return #ZONE_ERROR_NONE on success, otherwise a negative value + * @retval #ZONE_ERROR_NONE Successful + * @retval #ZONE_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #ZONE_ERROR_TIMED_OUT Time out + * @retval #ZONE_ERROR_PERMISSION_DENIED The application does not have + * the privilege to call this API or the caller is not the owner + * of the zone + * @pre The handle must be created by zone_manager_create(). + * @pre The zone corresponding to the given name must be + * created before use of this API. + * @see zone_manager_create() + * @see zone_manager_destroy() + * @see zone_manager_create_zone() + * @see zone_manager_create_zone_iterator() + */ +ZONE_API int zone_manager_destroy_zone(zone_manager_h handle, const char* name); + +/* + * @brief Enumeration for zone state + * @since_tizen 3.0 + */ +typedef enum { + ZONE_STATE_LOCKED = 0x01, /**< Zone has been defined, but it can not start. */ + ZONE_STATE_RUNNING = 0x02, /**< Zone has been started. */ + ZONE_STATE_ALL = 0xff /**< This presents all of the state */ +} zone_state_e; + +/** + * @brief Gets the zone state. + * @details This API can be used to get the state of the zone. The zone can + * have one of the three states(running, locked). + * @since_tizen 3.0 + * @param[in] handle The zone policy handle + * @param[in] name The zone name + * @param[out] state The zone state + * @return #ZONE_ERROR_NONE on success, otherwise a negative value + * @retval #ZONE_ERROR_NONE Successful + * @retval #ZONE_ERROR_NO_DATA No such zone to get state + * @retval #ZONE_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #ZONE_ERROR_TIMED_OUT Time out + * @pre The handle must be created by zone_manager_create(). + * @see zone_manager_create() + * @see zone_manager_destroy() + * @see zone_manager_create_zone() + * @see zone_manager_destroy_zone() + */ +ZONE_API int zone_manager_get_zone_state(zone_manager_h handle, const char* name, zone_state_e* state); + +/** + * @brief The zone list iterator handle + * @since_tizen 3.0 + * @see zone_manager_create_zone_terator() + * @see zone_iterator_next() + * @see zone_iterator_destroy() + */ +typedef void* zone_iterator_h; + +/** + * @brief Creates a zone list iterator. + * @details The zone list iterator can be used to get all defined zones. + * @since_tizen 3.0 + * @param[in] handle The zone policy handle + * @param[in] state a combination of the zone state to look + * @return A zone list iterator on success, otherwise + * null value + * @remark The specific error code can be obtained by using the + * get_last_result() method. Error codes are described in + * exception section. + * @exception #ZONE_ERROR_NONE No error + * @exception #ZONE_ERROR_OUT_OF_MEMORY Out of memory + * @exception #ZONE_ERROR_INVALID_PARAMETER Invalid parameter + * @exception #ZONE_ERROR_TIMED_OUT Time out + * @pre The handle must be created by zone_manager_create(). + * @see zone_manager_create() + * @see zone_manager_destroy() + * @see zone_manager_create_zone() + * @see zone_manager_destroy_zone() + * @see zone_iterator_next() + * @see zone_interator_destroy() + * @see get_last_result() + */ +ZONE_API zone_iterator_h zone_manager_create_zone_iterator(zone_manager_h handle, zone_state_e state); + +/** + * @brief Fetches a zone name and forwards the iterator. + * @details This API returns zone name indicated by the iterator, and then + * the iterator is moved to the next position. If the iterator reaches + * the end of the list, null value will be returned. + * @since_tizen 3.0 + * @param[in] iter The iterator to be controlled + * @param[out] zone_name The zone name got from the iterator + * @return #ZONE_ERROR_NONE on success, otherwise a negative value + * @retval #ZONE_ERROR_NONE Successful + * @retval #ZONE_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #ZONE_ERROR_TIMED_OUT Time out + * @pre The iter must be created by zone_manager_create_iterator(). + * @see zone_manager_create_zone_iterator() + * @see zone_interator_destroy() + */ +ZONE_API int zone_iterator_next(zone_iterator_h iter, const char** zone_name); + +/** + * @brief Frees the zone iterator. + * @details This API frees the zone iterator. This API must be called + * if the iterator no longer used. + * @since_tizen 3.0 + * @param[in] iter The iterator to be removed + * @return #ZONE_ERROR_NONE on success, otherwise a negative value + * @retval #ZONE_ERROR_NONE Successful + * @retval #ZONE_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #ZONE_ERROR_TIMED_OUT Time out + * @pre The iter must be created by zone_manager_create_iterator() + * @see zone_manager_create_zone_iterator() + * @see zone_iterator_next() + */ +ZONE_API int zone_iterator_destroy(zone_iterator_h iter); + +/** + * @brief Called to get all the name of created zones. + * @since_tizen 3.0 + * @param[in] name The zone name + * @param[in] user_data The user data passed from zone_manager_foreach_name + * @see zone_manager_foreach_name() + */ +typedef void(*zone_manager_foreach_cb)(const char* name, void* user_data); + +/** + * @brief Retrieves all the name of created zones + * @details This API calls zone_manager_foreach_cb() once for each zone name + * with traversing the created zones list. + * @since_tizen 3.0 + * @param[in] handle The zone policy handle + * @param[in] state a combination of the zone state to look + * @param[in] callback The iteration callback function + * @param[in] user_data The user data passed to the callback function + * @return #ZONE_ERROR_NONE on success, otherwise a negative value + * @retval #ZONE_ERROR_NONE Successful + * @retval #ZONE_ERROR_TIMED_OUT Time out + * @retval #ZONE_ERROR_INVALID_PARAMETER Invalid parameter + * @pre The handle must be created by zone_manager_create(). + * @see zone_manager_create() + * @see zone_manager_destroy() + * @see zone_manager_create_zone() + * @see zone_manager_destroy_zone() + */ +ZONE_API int zone_manager_foreach_name(zone_manager_h handle, + zone_state_e state, + zone_manager_foreach_cb callback, + void* user_data); + +/** * @} */ diff --git a/zone/setup-wizard/src/util.c b/zone/setup-wizard/src/util.c index 2c845a7..a30112f 100644 --- a/zone/setup-wizard/src/util.c +++ b/zone/setup-wizard/src/util.c @@ -83,6 +83,7 @@ static char *__get_zone_metadata(void) int _send_zone_create_request(appdata_s *ad) { char *metadata = NULL; + int ret; metadata = __get_zone_metadata(); if (metadata == NULL) { @@ -90,14 +91,22 @@ int _send_zone_create_request(appdata_s *ad) return -1; } - /* [TBD] */ + ret = zone_manager_create_zone(ad->zone_manager, ad->zone_name, metadata); + if (ret != ZONE_ERROR_NONE) { + return -1; + } return 0; } int _send_zone_remove_request(appdata_s *ad) { - /* [TBD] */ + int ret; + + ret = zone_manager_destroy_zone(ad->zone_manager, ad->zone_name); + if (ret != ZONE_ERROR_NONE) { + return -1; + } return 0; }