PROJECT(dpm-common)
SET (COMMON_SOURCES ${DPM_COMMON}/error.cpp
- ${DPM_COMMON}/smack.cpp
${DPM_COMMON}/process.cpp
${DPM_COMMON}/eventfd.cpp
${DPM_COMMON}/mainloop.cpp
${DPM_COMMON}/db/connection.cpp
${DPM_COMMON}/auth/user.cpp
${DPM_COMMON}/auth/group.cpp
- ${DPM_COMMON}/auth/shadow.cpp
${DPM_COMMON}/dbus/error.cpp
${DPM_COMMON}/dbus/variant.cpp
${DPM_COMMON}/dbus/connection.cpp
PKG_CHECK_MODULES(COMMON_DEPS REQUIRED libxml-2.0
sqlite3
- libsmack
gio-2.0
)
#include "shadow.h"
#include "exception.h"
-#define GROUP_DIR_PATH "/etc/"
-#define GROUP_FILE_NAME "group"
-#define GSHADOW_FILE_NAME "gshadow"
-
-#define NAME_PATTERN "^[A-Za-z_][A-Za-z0-9_.-]*"
-
namespace runtime {
Group::Group(const Group& group) :
{
}
-
-static std::regex groupNamePattern(NAME_PATTERN);
-
-Group Group::create(const std::string& name, const gid_t min, const gid_t max)
-{
- struct group group, tmpgrp, *result;
- struct sgrp sgrp;
- int bufsize;
-
- bufsize = sysconf(_SC_GETGR_R_SIZE_MAX);
- if (bufsize == -1)
- bufsize = 16384;
-
- std::unique_ptr<char[]> buf(new char[bufsize]);
- ::getgrnam_r(name.c_str(), &tmpgrp, buf.get(), bufsize, &result);
- if (result != NULL) {
- return Group(name);
- }
-
- if (!std::regex_match(name, groupNamePattern)) {
- throw runtime::Exception("Invalid group name : " + name);
- }
-
- //prepare group structure
- std::unique_ptr<char, decltype(&::free)>
- gr_name(::strdup(name.c_str()), ::free),
- gr_passwd(::strdup("x"), ::free);
-
- group.gr_name = gr_name.get();
- group.gr_passwd = gr_passwd.get();
- group.gr_mem = NULL;
-
- //prepare gshadow structure
- std::unique_ptr<char, decltype(&::free)>
- sg_namp(::strdup(name.c_str()), ::free),
- sg_passwd(::strdup("!"), ::free);
-
- sgrp.sg_namp = sg_namp.get();
- sgrp.sg_passwd = sg_passwd.get();
- sgrp.sg_adm = NULL;
- sgrp.sg_mem = NULL;
-
- //prepare gid - get free gid
- for (group.gr_gid = min; group.gr_gid <= max; group.gr_gid++) {
- ::getgrgid_r(group.gr_gid, &tmpgrp, buf.get(), bufsize, &result);
- if (result == NULL) {
- break;
- }
- }
-
- if (group.gr_gid > max) {
- throw runtime::Exception("Too many groups");
- }
-
- Shadow::putGroup(GROUP_DIR_PATH GROUP_FILE_NAME, group);
- Shadow::putGshadow(GROUP_DIR_PATH GSHADOW_FILE_NAME, sgrp);
-
- return Group(name);
-}
-
-void Group::remove()
-{
- if (gid == INVALID_GID) {
- throw runtime::Exception("Group is already removed");
- }
-
- Shadow::foreachGroup(GROUP_DIR_PATH GROUP_FILE_NAME,
- [this](const struct group & grp) -> bool {
- return grp.gr_gid != gid;
- });
- Shadow::foreachGshadow(GROUP_DIR_PATH GSHADOW_FILE_NAME,
- [this](const struct sgrp & sgrp) -> bool {
- return sgrp.sg_namp != name;
- });
-
- name = "";
- gid = INVALID_GID;
-}
-
-void Group::addMember(const std::string& name)
-{
- char ** members = NULL;
- std::unique_ptr<char, decltype(&::free)>
- member(::strdup(name.c_str()), ::free);
-
- Shadow::foreachGroup(GROUP_DIR_PATH GROUP_FILE_NAME,
- [&member, &members, this](struct group & grp) -> bool {
- if (grp.gr_gid == gid) {
- int len = 0;
-
- if (grp.gr_mem)
- for (len = 0; grp.gr_mem[len]; len++);
-
- if (members)
- delete [] members;
-
- members = new char * [len + 22];
-
- for (int i = 0; i < len; i++)
- members[i] = grp.gr_mem[i];
- members[len] = member.get();
- members[len + 1] = NULL;
-
- grp.gr_mem = members;
- }
- return true;
- });
-
- if (members)
- delete [] members;
-}
-
-void Group::removeMember(const std::string& name)
-{
- char ** members = NULL;
-
- Shadow::foreachGroup(GROUP_DIR_PATH GROUP_FILE_NAME,
- [&name, &members, this](struct group & grp) -> bool {
- if (grp.gr_gid == gid) {
- int len = 0;
-
- if (grp.gr_mem)
- for (; grp.gr_mem[len]; len++);
-
- if (members)
- delete [] members;
-
- members = new char * [len + 1];
-
- for (int i = 0; i <= len; i++)
- members[i] = NULL;
-
- for (int i = 0, j = 0; i < len; i++) {
- if (grp.gr_mem[i] != name)
- members[j++] = grp.gr_mem[i];
- }
-
- grp.gr_mem = members;
- }
- return true;
- });
-
- if (members)
- delete [] members;
-}
-
} // namespace Shadow
return gid;
}
- static Group create(const std::string& name, const gid_t min = 100, const gid_t max = 65000);
- void remove();
-
- void addMember(const std::string& name);
- void removeMember(const std::string& name);
-
private:
std::string name;
gid_t gid;
+++ /dev/null
-/*
- * 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 <regex>
-#include <mutex>
-#include <memory>
-
-#include <unistd.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include "smack.h"
-#include "shadow.h"
-#include "exception.h"
-#include "filesystem.h"
-#include "audit/logger.h"
-
-namespace runtime {
-
-//PwdFileLock
-class PwdFileLock final {
-public:
- PwdFileLock();
- ~PwdFileLock();
-
-private:
- std::unique_lock<std::mutex> lock;
- static std::mutex mutex;
-};
-
-std::mutex PwdFileLock::mutex;
-
-PwdFileLock::PwdFileLock() :
- lock(mutex)
-{
- if (::seteuid(0) != 0) {
- throw runtime::Exception("failed to change euid");
- }
-
- if (::lckpwdf() != 0) {
- throw runtime::Exception("shadow file lock error");
- }
-}
-
-PwdFileLock::~PwdFileLock()
-{
- if (::ulckpwdf() != 0) {
- throw runtime::Exception("shadow file unlock error");
- }
-
- if (::seteuid(getuid()) != 0) {
- throw runtime::Exception("failed to change euid");
- }
-}
-
-//Shadow
-template<typename pwdStruct>
-void Shadow::put(const std::string& filename, const pwdStruct& pwd,
- std::function<int(const pwdStruct*, FILE*)> put)
-{
- PwdFileLock pwdLock;
-
- std::unique_ptr<FILE, decltype(&::fclose)> fp_pwd
- (::fopen(filename.c_str(), "a"), &::fclose);
-
- if (fp_pwd.get() == NULL) {
- throw runtime::Exception("shadow file open error");
- }
-
- if (put(&pwd, fp_pwd.get())) {
- throw runtime::Exception("shadow file write error");
- }
-
- fp_pwd.reset();
-}
-
-template<typename pwdStruct>
-void Shadow::foreach(const std::string& filename,
- std::function<int(const pwdStruct*, FILE*)> put,
- std::function<pwdStruct *(FILE*)> get,
- std::function<bool(pwdStruct&)> check)
-{
- std::string tmpfilename = filename + ".tmp";
- pwdStruct* ppwd;
- mode_t old_mask;
- struct stat st;
-
- old_mask = ::umask(0777);
-
- std::unique_ptr<FILE, void(*)(FILE*)> fp_tmp_pwd(
- ::fopen(tmpfilename.c_str(), "w"),
- [](FILE * fp) {
- if (fp == NULL) {
- return;
- }
- ::fclose(fp);
- });
-
- ::umask(old_mask);
-
- if (fp_tmp_pwd.get() == NULL) {
- throw runtime::Exception("Tmp file for shadow create error");
- }
-
- if (::stat(filename.c_str(), &st) != 0) {
- throw runtime::Exception("shadow file information get error");
- }
-
- PwdFileLock pwdLock;
-
- std::unique_ptr<FILE, void(*)(FILE*)> fp_pwd(
- ::fopen(filename.c_str(), "r"),
- [](FILE * fp) {
- if (fp == NULL) {
- return;
- }
- ::fclose(fp);
- });
-
- if (fp_pwd.get() == NULL) {
- throw runtime::Exception("shadow file open error");
- }
-
- for (ppwd = get(fp_pwd.get()); ppwd != NULL; ppwd = get(fp_pwd.get()))
- if (check(*ppwd))
- if (put(ppwd, fp_tmp_pwd.get()) != 0) {
- throw runtime::Exception("Tmp file for shadow write error");
- }
-
- fp_pwd.reset();
-
- ::fflush(fp_tmp_pwd.get());
-
- if (::chown(tmpfilename.c_str(), 0, 0) != 0) {
- throw runtime::Exception("Shadow file chown error");
- }
-
- if (::chmod(tmpfilename.c_str(), st.st_mode) != 0) {
- throw runtime::Exception("Shadow file chmod error");
- }
-
- runtime::File tmpfile(tmpfilename);
- runtime::Smack::setAccess(tmpfile, "_");
-
- if (::rename(tmpfilename.c_str(), filename.c_str()) != 0) {
- throw runtime::Exception("shadow file update error");
- }
-}
-
-
-void Shadow::putPasswd(const std::string& filename, const struct passwd& ent)
-{
- put<struct passwd>(filename, ent, putpwent);
-}
-
-void Shadow::putShadow(const std::string& filename, const struct spwd& ent)
-{
- put<struct spwd>(filename, ent, putspent);
-}
-
-void Shadow::putGroup(const std::string& filename, const struct group& ent)
-{
- put<struct group>(filename, ent, putgrent);
-}
-
-void Shadow::putGshadow(const std::string& filename, const struct sgrp& ent)
-{
- put<struct sgrp>(filename, ent, putsgent);
-}
-
-
-void Shadow::foreachPasswd(const std::string& filename, std::function<bool(passwd&)> check)
-{
- foreach<struct passwd>(filename, putpwent, fgetpwent, check);
-}
-
-void Shadow::foreachShadow(const std::string& filename, std::function<bool(spwd&)> check)
-{
- foreach<struct spwd>(filename, putspent, fgetspent, check);
-}
-
-void Shadow::foreachGroup(const std::string& filename, std::function<bool(group&)> check)
-{
- foreach<struct group>(filename, putgrent, fgetgrent, check);
-}
-
-void Shadow::foreachGshadow(const std::string& filename, std::function<bool(sgrp&)> check)
-{
- foreach<struct sgrp>(filename, putsgent, fgetsgent, check);
-}
-
-} // namespace runtime
+++ /dev/null
-/*
- * 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 __RUNTIME_SHADOW_H__
-#define __RUNTIME_SHADOW_H__
-
-#include <sys/types.h>
-#include <pwd.h>
-#include <grp.h>
-#include <shadow.h>
-#include <gshadow.h>
-#include <limits.h>
-
-#include <cstdio>
-#include <string>
-#include <functional>
-
-namespace runtime {
-
-class Shadow final {
-public:
- Shadow() = delete;
- Shadow(Shadow&&) = delete;
- Shadow(const Shadow&) = delete;
-
- Shadow& operator=(const Shadow&) = delete;
- Shadow& operator=(Shadow &&) = delete;
-
- static void putPasswd(const std::string& filename, const struct passwd& ent);
- static void putShadow(const std::string& filename, const struct spwd& ent);
- static void putGroup(const std::string& filename, const struct group& ent);
- static void putGshadow(const std::string& filename, const struct sgrp& ent);
-
- static void foreachPasswd(const std::string& filename, std::function<bool(passwd&)> check);
- static void foreachShadow(const std::string& filename, std::function<bool(spwd&)> check);
- static void foreachGroup(const std::string& filename, std::function<bool(group&)> check);
- static void foreachGshadow(const std::string& filename, std::function<bool(sgrp&)> check);
-
-private:
- template<typename pwdStruct>
- static void put(const std::string& filename, const pwdStruct& pwd,
- std::function<int(const pwdStruct*, FILE*)> put);
-
- template<typename pwdStruct>
- static void foreach(const std::string& filename,
- std::function<int(const pwdStruct*, FILE*)> put,
- std::function<pwdStruct *(FILE*)> get,
- std::function<bool(pwdStruct&)> check);
-};
-
-} // namespace runtime
-
-#endif //__RUNTIME_SHADOW_H__
#include "filesystem.h"
#include "exception.h"
-#define PASSWD_DIR_PATH "/etc/"
-#define PASSWD_FILE_NAME "passwd"
-#define SHADOW_FILE_NAME "shadow"
-
-#define HOMEDIR_PATH "/home"
-#define SHELL_PATH "/bin/bash"
-
-#define NAME_PATTERN "^[A-Za-z_][A-Za-z0-9_.-]*"
-
namespace runtime {
User::User(const User& user) :
{
}
-
-static std::regex userNamePattern(NAME_PATTERN);
-
-User User::create(const std::string& name, const std::string& group_name,
- const uid_t min, const uid_t max)
-{
- runtime::File home(HOMEDIR_PATH "/" + name);
- struct passwd pwd, tmppwd, *result;
- struct spwd spwd;
- int bufsize;
-
- if (!std::regex_match(name, userNamePattern)) {
- throw runtime::Exception("Invalid user name : " + name);
- }
-
- bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
- if (bufsize == -1)
- bufsize = 16384;
-
- std::unique_ptr<char[]> buf(new char[bufsize]);
-
- ::getpwnam_r(name.c_str(), &tmppwd, buf.get(), bufsize, &result);
- if (result != NULL) {
- throw runtime::Exception("User " + name + "already exists");
- }
-
- //prepare passwd structure
- std::unique_ptr<char, decltype(&::free)>
- pw_name(::strdup(name.c_str()), ::free),
- pw_passwd(::strdup("x"), ::free),
- pw_gecos(::strdup(""), ::free),
- pw_dir(::strdup(home.getPath().c_str()), ::free),
- pw_shell(::strdup(SHELL_PATH), ::free);
-
- pwd.pw_name = pw_name.get();
- pwd.pw_passwd = pw_passwd.get();
- pwd.pw_gecos = pw_gecos.get();
- pwd.pw_dir = pw_dir.get();
- pwd.pw_shell = pw_shell.get();
-
- //prepare passwd structure
- std::unique_ptr<char, decltype(&::free)>
- sp_namp(::strdup(name.c_str()), ::free),
- sp_pwdp(::strdup("!"), ::free);
- spwd.sp_namp = sp_namp.get();
- spwd.sp_pwdp = sp_pwdp.get();
- spwd.sp_lstchg = (long) time((time_t*) 0) / (24 * 60 * 60);
- spwd.sp_min = 0;
- spwd.sp_max = 99999;
- spwd.sp_warn = 7;
- spwd.sp_inact = -1;
- spwd.sp_expire = -1;
- spwd.sp_flag = -1;
-
-
- //get free uid
- for (pwd.pw_uid = min; pwd.pw_uid <= max; pwd.pw_uid++) {
- ::getpwuid_r(pwd.pw_uid, &tmppwd, buf.get(), bufsize, &result);
- if (result == NULL) {
- break;
- }
- }
-
- if (pwd.pw_uid > max) {
- throw runtime::Exception("Too many users");
- }
-
- pwd.pw_gid = Group::create(group_name).getGid();
-
- Shadow::putPasswd(PASSWD_DIR_PATH PASSWD_FILE_NAME, pwd);
- Shadow::putShadow(PASSWD_DIR_PATH SHADOW_FILE_NAME, spwd);
-
- try {
- home.remove(true);
- } catch (runtime::Exception& e) {}
-
- return User(name);
-}
-
-void User::remove()
-{
- runtime::File home(HOMEDIR_PATH "/" + name);
-
- if (uid == INVALID_UID) {
- throw runtime::Exception("User is already removed");
- }
-
- Shadow::foreachPasswd(PASSWD_DIR_PATH PASSWD_FILE_NAME,
- [this](const struct passwd & pwd) -> bool {
- return pwd.pw_uid != uid;
- });
- Shadow::foreachShadow(PASSWD_DIR_PATH SHADOW_FILE_NAME,
- [this](const struct spwd & spwd) -> bool {
- return spwd.sp_namp != name;
- });
-
- try {
- home.remove(true);
- } catch (runtime::Exception& e) {}
-
- int ngroups = 0;
- getgrouplist(name.c_str(), gid, NULL, &ngroups);
-
- std::unique_ptr<gid_t[]> groups(new gid_t[ngroups]);
- getgrouplist(name.c_str(), gid, groups.get(), &ngroups);
-
- for (int i = 0; i < ngroups; i++) {
- Group grp(groups.get()[i]);
- grp.removeMember(name);
- }
-
- name = "";
- uid = INVALID_UID;
-}
-
} // namespace runtime
return gid;
}
- static User create(const std::string& name, const std::string& group,
- const uid_t min = 5000, const uid_t max = 65000);
- void remove();
-
private:
std::string name;
uid_t uid;
#include <iostream>
#include "filesystem.h"
-#include "smack.h"
#include "error.h"
#include "exception.h"
iter->copyTo(destFile.getPath());
++iter;
}
-
- try {
- Smack::setTransmute(destFile, Smack::getTransmute(*this));
- } catch (runtime::Exception &e) {}
} else {
open(O_RDONLY);
destFile.open(O_WRONLY | O_CREAT, getMode());
close();
}
- try {
- Smack::setAccess(destFile, Smack::getAccess(*this));
- } catch (runtime::Exception &e) {}
-
- try {
- Smack::setExecute(destFile, Smack::getExecute(*this));
- } catch (runtime::Exception &e) {}
-
- try {
- Smack::setMmap(destFile, Smack::getMmap(*this));
- } catch (runtime::Exception &e) {}
-
return destFile;
}
+++ /dev/null
-/*
- * 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 <string>
-#include <sys/smack.h>
-#include <linux/xattr.h>
-
-#include "smack.h"
-#include "exception.h"
-
-namespace runtime {
-
-void Smack::setAccess(File& file, const std::string& label)
-{
- set(file, XATTR_NAME_SMACK, label);
-}
-
-void Smack::setExecute(File& file, const std::string& label)
-{
- set(file, XATTR_NAME_SMACKEXEC, label);
-}
-
-void Smack::setMmap(File& file, const std::string& label)
-{
- set(file, XATTR_NAME_SMACKMMAP, label);
-}
-
-void Smack::setTransmute(File& file, const bool enable)
-{
- const char* enable_value;
-
- if (enable) {
- enable_value = "TRUE";
- } else {
- enable_value = "FALSE";
- }
-
- set(file, XATTR_NAME_SMACKTRANSMUTE, enable_value);
-}
-
-std::string Smack::getAccess(File& file)
-{
- return get(file, XATTR_NAME_SMACK);
-}
-
-std::string Smack::getExecute(File& file)
-{
- return get(file, XATTR_NAME_SMACKEXEC);
-}
-
-std::string Smack::getMmap(File& file)
-{
- return get(file, XATTR_NAME_SMACKMMAP);
-}
-
-bool Smack::getTransmute(File& file)
-{
- std::string label;
- label = get(file, XATTR_NAME_SMACKTRANSMUTE);
-
- if (label == "TRUE") {
- return true;
- }
- return false;
-}
-
-void Smack::set(File& file, const char* xattr, const std::string& label)
-{
- if (::smack_set_label_for_path(file.getPath().c_str(),
- xattr, 0, label.c_str()) != 0) {
- throw runtime::Exception("Smack setting error");
- }
-}
-
-std::string Smack::get(File& file, const char* xattr)
-{
- char* plabel;
- std::string label;
- if (::smack_new_label_from_path(file.getPath().c_str(),
- xattr, 0, &plabel) < 0) {
- throw runtime::Exception("Getting smack label error");
- }
-
- label = plabel;
- free(plabel);
-
- return label;
-}
-
-} // namespace runtime
+++ /dev/null
-/*
- * 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 __RUNTIME_SMACK_H__
-#define __RUNTIME_SMACK_H__
-
-#include <string>
-
-#include "filesystem.h"
-
-namespace runtime {
-
-class Smack final {
-public:
- Smack() = delete;
- Smack(const Smack&) = delete;
- Smack(Smack&&) = delete;
-
- Smack& operator=(const Smack&) = delete;
- Smack& operator=(Smack&&) = delete;
-
- static void setAccess(File& file, const std::string& label);
- static void setExecute(File& file, const std::string& label);
- static void setMmap(File& file, const std::string& label);
- static void setTransmute(File& file, const bool enable);
-
- static std::string getAccess(File& file);
- static std::string getExecute(File& file);
- static std::string getMmap(File& file);
- static bool getTransmute(File& file);
-
-
-private:
- static void set(File& file, const char* xattr, const std::string& label);
- static std::string get(File& file, const char* xattr);
-};
-
-} // namespace runtime
-#endif //__RUNTIME_SMACK_H__
BuildRequires: pkgconfig(vconf-internal-keys)
BuildRequires: pkgconfig(bluetooth-api)
BuildRequires: pkgconfig(capi-network-bluetooth)
-BuildRequires: pkgconfig(libsmack)
BuildRequires: pkgconfig(libtzplatform-config)
BuildRequires: pkgconfig(security-privilege-manager)
BuildRequires: pkgconfig(capi-base-common)
BuildRequires: pkgconfig(capi-system-system-settings)
BuildRequires: pkgconfig(notification)
BuildRequires: pkgconfig(key-manager)
+BuildRequires: pkgconfig(libgum)
%if "%{profile}" != "tv"
BuildRequires: pkgconfig(capi-location-manager)
capi-network-connection
capi-network-bluetooth
notification
+ libgum
)
INCLUDE("${TIZEN_PROFILE_NAME}.cmake")
#include <sys/types.h>
#include <sys/inotify.h>
+#include <gum/gum-user.h>
+#include <gum/common/gum-user-types.h>
#include <notification.h>
#include <notification_internal.h>
#include <tzplatform_config.h>
#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 DEFAULT_SHELL "/bin/bash"
-
#define ZONE_DELEGATOR_APP "org.tizen.keyguard"
#define NOTIFICATION_SUB_ICON_PATH DATA_PATH "/zone_noti_list_sub_icon.png"
const std::string ZONE_GROUP = "users";
std::vector<std::string> createdZoneList;
+static std::atomic<bool> isZoneForeground(false);
+
std::unordered_map<std::string, int> notiProxyCallbackMap;
std::unordered_map<int, notification_h> notiHandleMap;
-template <typename... Args>
-inline void execute(const std::string& path, Args&&... args)
-{
- std::vector<std::string> argsVector = { args... };
- runtime::Process proc(path, argsVector);
- proc.execute();
-}
-
-inline std::string prepareDirectories(const runtime::User& user)
+inline void maskUserServices(const runtime::User& user)
{
::tzplatform_set_user(user.getUid());
std::string pivot(::tzplatform_getenv(TZ_USER_HOME));
::tzplatform_reset_user();
- //copy skel files to home directory
- runtime::File skel(ZONE_SKEL_PATH);
- skel.copyTo(pivot).chown(user.getUid(), user.getGid(), true);
-
- return pivot;
-}
-
-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);
}
}
-inline void executeHookScripts(const runtime::User& user, const std::string& path, const std::string& pivot)
-{
- std::vector<std::string> scripts;
- char currentDirectory[PATH_MAX];
-
- try {
- runtime::DirectoryIterator iter(path), end;
-
- while (iter != end) {
- scripts.push_back(iter->getPath());
- ++iter;
- }
- } catch (runtime::Exception& e) {}
-
- if (getcwd(currentDirectory, PATH_MAX) == NULL) {
- snprintf(currentDirectory, PATH_MAX, "/");
- }
-
- ::tzplatform_set_user(user.getUid());
- if (chdir(::tzplatform_getenv(TZ_SYS_HOME)) != 0) {
- throw runtime::Exception(runtime::GetSystemErrorMessage());
- }
- ::tzplatform_reset_user();
-
- std::sort(scripts.begin(), scripts.end());
-
- for (const std::string& script : scripts) {
- execute(DEFAULT_SHELL, script, script, user.getName(),
- std::to_string(user.getUid()),
- std::to_string(user.getGid()), pivot, "normal");
- }
-
- if (chdir(currentDirectory) != 0) {
- throw runtime::Exception(runtime::GetSystemErrorMessage());
- }
-}
-
inline void setZoneState(uid_t id, int state)
{
dbus::Connection& systemDBus = dbus::Connection::getSystem();
GVariant *params, gpointer userData)
{
static runtime::User owner(ZONE_DEFAULT_OWNER);
- static std::atomic<bool> isNotiShown(false);
int pid, status;
notification_h noti = reinterpret_cast<notification_h>(userData);
return;
}
- if ((st.st_uid >= ZONE_UID_MIN) && (st.st_uid < ZONE_UID_MAX)) {
- if (!isNotiShown) {
+ if (owner.getUid() != st.st_uid) {
+ if (!isZoneForeground) {
notification_set_text(noti, NT_CONTENT, NT_APPINFO, NULL, NT_NONE);
notification_post_for_uid(noti, owner.getUid());
- isNotiShown = true;
+ isZoneForeground = true;
}
} else {
- if (isNotiShown) {
+ if (isZoneForeground) {
notification_delete_for_uid(noti, owner.getUid());
- isNotiShown = false;
+ isZoneForeground = false;
}
}
}
auto provisioningWorker = [name, manifest, this]() {
std::unique_ptr<xml::Document> 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);
+ //create zone user by gumd
+ GumUser *guser = gum_user_create_sync(FALSE);
+ g_object_set(G_OBJECT(guser), "username", name.c_str(),
+ "usertype", GUM_USERTYPE_SECURITY, NULL);
+ gboolean ret = gum_user_add_sync(guser);
+ g_object_unref(guser);
+
+ if (!ret) {
+ throw runtime::Exception("Failed to remove user (" + name + ") by gumd");
}
- std::string pivot = prepareDirectories(user);
- maskUserServices(pivot, user);
- executeHookScripts(user, ZONE_CREATE_HOOK_PATH, pivot);
+ runtime::User user(name);
+
+ maskUserServices(user);
manifestFile.reset(xml::Parser::parseString(manifest));
- ::umask(0077);
+ mode_t omask = ::umask(0077);
manifestFile->write(ZONE_MANIFEST_DIR + name + ".xml", "UTF-8", true);
+ ::umask(omask);
//TODO: write container owner info
context.notify("ZoneManager::removed", name, std::string());
}
- ::umask(omask);
};
std::thread asyncWork(provisioningWorker);
try {
runtime::User user(name);
- ::tzplatform_set_user(user.getUid());
- std::string pivot(::tzplatform_getenv(TZ_USER_HOME));
- ::tzplatform_reset_user();
-
- executeHookScripts(user, ZONE_REMOVE_HOOK_PATH, pivot);
-
//remove zone user
- user.remove();
+ GumUser *guser = gum_user_get_sync(user.getUid(), FALSE);
+ gboolean ret = gum_user_delete_sync(guser, TRUE);
+ g_object_unref(guser);
+
+ if (!ret) {
+ throw runtime::Exception("Failed to remove user (" + name + ") by gumd");
+ }
for (std::vector<std::string>::iterator it = createdZoneList.begin();
it != createdZoneList.end(); it++) {
int ZoneManager::getZoneState(const std::string& name)
{
- runtime::File manifest(ZONE_MANIFEST_DIR + name + ".xml");
- if (!manifest.exists()) {
+ auto it = std::find(createdZoneList.begin(), createdZoneList.end(), name);
+ if (it == createdZoneList.end()) {
return 0;
}
}
}
-TESTCASE(CreateGroupTest)
-{
- try {
- runtime::Group group = runtime::Group::create("testgroup");
- } catch (runtime::Exception& e) {
- TEST_FAIL(e.what());
- }
-
- try {
- runtime::Group group("testgroup");
- } catch (runtime::Exception& e) {
- TEST_FAIL(e.what());
- }
-}
-
-TESTCASE(RemoveGroupTest)
-{
- try {
- runtime::Group group("testgroup");
- group.remove();
- } catch (runtime::Exception& e) {
- TEST_FAIL(e.what());
- }
-
- try {
- runtime::Group group("testgroup");
- } catch (runtime::Exception& e) {
- return;
- }
-
- TEST_FAIL("Failed to remove group");
-}
-
TESTCASE(GetUserTest)
{
try {
TEST_FAIL(e.what());
}
}
-
-TESTCASE(CreateUserTest)
-{
- try {
- runtime::User user = runtime::User::create("testuser", "testgroup");
- } catch (runtime::Exception& e) {
- TEST_FAIL(e.what());
- }
- try {
- runtime::User user("testuser");
- } catch (runtime::Exception& e) {
- TEST_FAIL(e.what());
- }
-}
-
-TESTCASE(AddMemberGroupTest)
-{
- try {
- runtime::Group group("users");
- group.addMember("test");
- group.addMember("testuser");
- } catch (runtime::Exception& e) {
- TEST_FAIL(e.what());
- }
-}
-TESTCASE(RemoveMemberGroupTest)
-{
- try {
- runtime::Group group("users");
- group.removeMember("test");
- group.removeMember("noexist");
- } catch (runtime::Exception& e) {
- TEST_FAIL(e.what());
- }
-}
-
-TESTCASE(RemoveUserTest)
-{
- try {
- runtime::User user("testuser");
- user.remove();
- } catch (runtime::Exception& e) {
- TEST_FAIL(e.what());
- }
-
- try {
- runtime::Group group("testgroup");
- group.remove();
- } catch (runtime::Exception& e) {}
-
- try {
- runtime::User user("testuser");
- } catch (runtime::Exception& e) {
- return;
- }
-
- TEST_FAIL("Failed to remove user");
-}