From 6f9f0b83f4781317e9908d13bf6782fb7f5e6697 Mon Sep 17 00:00:00 2001 From: Sungbae Yoo Date: Wed, 20 Jul 2016 16:05:01 +0900 Subject: [PATCH] Move PAM module, volume manager from device-policy-manager git Change-Id: Ib93d3ffdf839eaf5b1bb644b3328809a2d1d9fb2 Signed-off-by: Sungbae Yoo --- CMakeLists.txt | 11 +- .../DefaultManifest.xml | 0 .../indicator_icon.png | Bin .../notification_sub_icon.png | Bin module/CMakeLists.txt | 41 +- module/krate-builder.cpp | 75 +++ module/{zone-builder.h => krate-builder.h} | 35 +- module/{zone-guard.h => krate-guard.h} | 65 +- module/krate.cpp | 105 ++++ .../pam.d/{systemd-user-zone => systemd-user.in} | 2 +- module/session.cpp | 65 +- module/session.h | 10 +- module/zone-builder.cpp | 76 --- module/zone.cpp | 105 ---- packaging/krate.spec | 23 +- server/CMakeLists.txt | 7 + tools/CMakeLists.txt | 2 + tools/cli/CMakeLists.txt | 37 +- tools/cli/krate-admin-cli.cpp | 673 ++++++++++----------- .../{20_pam-krate-add.post => 20_krate-add.post} | 0 ..._pam-krate-remove.post => 20_krate-remove.post} | 0 volume/CMakeLists.txt | 33 + volume/ecryptfs.h | 107 ++++ volume/kernel-keyring.cpp | 46 ++ volume/kernel-keyring.h | 42 ++ volume/key-generator.cpp | 322 ++++++++++ volume/key-generator.h | 54 ++ volume/key-manager.cpp | 92 +++ volume/key-manager.h | 35 ++ volume/main.cpp | 194 ++++++ 30 files changed, 1593 insertions(+), 664 deletions(-) rename module/data/DefaultZoneManifest.xml => data/DefaultManifest.xml (100%) rename module/data/zone_indicator_icon.png => data/indicator_icon.png (100%) rename module/data/zone_noti_list_sub_icon.png => data/notification_sub_icon.png (100%) create mode 100644 module/krate-builder.cpp rename module/{zone-builder.h => krate-builder.h} (53%) rename module/{zone-guard.h => krate-guard.h} (50%) create mode 100644 module/krate.cpp rename module/pam.d/{systemd-user-zone => systemd-user.in} (68%) delete mode 100644 module/zone-builder.cpp delete mode 100644 module/zone.cpp rename tools/gumd-scripts/{20_pam-krate-add.post => 20_krate-add.post} (100%) rename tools/gumd-scripts/{20_pam-krate-remove.post => 20_krate-remove.post} (100%) create mode 100644 volume/CMakeLists.txt create mode 100755 volume/ecryptfs.h create mode 100755 volume/kernel-keyring.cpp create mode 100755 volume/kernel-keyring.h create mode 100755 volume/key-generator.cpp create mode 100755 volume/key-generator.h create mode 100755 volume/key-manager.cpp create mode 100644 volume/key-manager.h create mode 100755 volume/main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index df3adf8..f3f02d5 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,13 +28,13 @@ IF(NOT CMAKE_BUILD_TYPE) SET(CMAKE_BUILD_TYPE "DEBUG") ENDIF(NOT CMAKE_BUILD_TYPE) -SET(KRATE_COMMON ${PROJECT_SOURCE_DIR}/common) SET(KRATE_API ${PROJECT_SOURCE_DIR}/api) SET(KRATE_LIB ${PROJECT_SOURCE_DIR}/lib) SET(KRATE_SERVER ${PROJECT_SOURCE_DIR}/server) -SET(KRATE_VOLUME ${PROJECT_SOURCE_DIR}/volume) +SET(KRATE_DATA ${PROJECT_SOURCE_DIR}/data) SET(KRATE_TOOLS ${PROJECT_SOURCE_DIR}/tools) SET(KRATE_MODULE ${PROJECT_SOURCE_DIR}/module) +SET(KRATE_VOLUME ${PROJECT_SOURCE_DIR}/volume) IF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.7) SET(CXX_STD "c++0x") @@ -86,11 +86,10 @@ ENDIF(NOT DEFINED CONF_DIR) ADD_DEFINITIONS(-DUG_WAYLAND) -#ADD_SUBDIRECTORY(${KRATE_COMMON}) -ADD_SUBDIRECTORY(${KRATE_SERVER}) -#ADD_SUBDIRECTORY(${KRATE_VOLUME}) #ADD_SUBDIRECTORY(${KRATE_LIB}) -#ADD_SUBDIRECTORY(${KRATE_MODULE}) +ADD_SUBDIRECTORY(${KRATE_SERVER}) +ADD_SUBDIRECTORY(${KRATE_MODULE}) +ADD_SUBDIRECTORY(${KRATE_VOLUME}) IF("${TIZEN_PROFILE_NAME}" STREQUAL "mobile") ADD_SUBDIRECTORY(${KRATE_TOOLS}) ENDIF() diff --git a/module/data/DefaultZoneManifest.xml b/data/DefaultManifest.xml similarity index 100% rename from module/data/DefaultZoneManifest.xml rename to data/DefaultManifest.xml diff --git a/module/data/zone_indicator_icon.png b/data/indicator_icon.png similarity index 100% rename from module/data/zone_indicator_icon.png rename to data/indicator_icon.png diff --git a/module/data/zone_noti_list_sub_icon.png b/data/notification_sub_icon.png similarity index 100% rename from module/data/zone_noti_list_sub_icon.png rename to data/notification_sub_icon.png diff --git a/module/CMakeLists.txt b/module/CMakeLists.txt index d7ef612..be7a884 100644 --- a/module/CMakeLists.txt +++ b/module/CMakeLists.txt @@ -13,40 +13,39 @@ # See the License for the specific language governing permissions and # limitations under the License. # - -PROJECT(zone-provider) - -FILE(GLOB ZONE_PAM_SRCS zone-builder.cpp - session.cpp - zone.cpp +FILE(GLOB PAM_SRCS krate.cpp + session.cpp + krate-builder.cpp ) SET (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,noexecstack") -SET(ZONE_PAM_NAME "pam_zone") -ADD_LIBRARY(${ZONE_PAM_NAME} MODULE ${ZONE_PAM_SRCS}) -SET_TARGET_PROPERTIES(${ZONE_PAM_NAME} PROPERTIES PREFIX "" - COMPILE_DEFINITIONS PID_FILE_PATH="${RUN_INSTALL_DIR}/zone" - COMPILE_FLAGS "-fvisibility=hidden" +ADD_LIBRARY(pam_${PROJECT_NAME} MODULE ${PAM_SRCS}) +SET_TARGET_PROPERTIES(pam_${PROJECT_NAME} PROPERTIES PREFIX "" + COMPILE_DEFINITIONS PID_FILE_PATH="${RUN_INSTALL_DIR}/krate" + COMPILE_FLAGS "-fvisibility=hidden" ) FIND_PATH(PAM_INCLUDE_DIR NAMES security/pam_appl.h security/pam_ext.h security/pam_modules.h - HINTS ${PAM_ROOT_DIR} PATH_SUFFIXES include) + HINTS ${PAM_ROOT_DIR} PATH_SUFFIXES include) FIND_LIBRARY(PAM_LIBRARY pam HINTS ${PAM_ROOT_DIR} PATH_SUFFIXES ${LIB_INSTALL_DIR}) MARK_AS_ADVANCED(PAM_INCLUDE_DIR PAM_LIBRARY) INCLUDE(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(PAM DEFAULT_MSG PAM_LIBRARY PAM_INCLUDE_DIR) -INCLUDE_DIRECTORIES(${PAM_INCLUDE_DIR} ${DPM_COMMON}) -TARGET_LINK_LIBRARIES(${ZONE_PAM_NAME} ${PAM_LIBRARY} dpm-common pthread) +PKG_CHECK_MODULES(PAM_DEPS REQUIRED + klay +) -TARGET_COMPILE_DEFINITIONS(${ZONE_PAM_NAME} PRIVATE - CONF_PATH="${CONF_INSTALL_DIR}" +INCLUDE_DIRECTORIES(${PAM_INCLUDE_DIR} ${PAM_DEPS_INCLUDE_DIRS}) +TARGET_LINK_LIBRARIES(pam_${PROJECT_NAME} ${PAM_LIBRARY} ${PAM_DEPS_LIBRARIES} pthread) + +TARGET_COMPILE_DEFINITIONS(pam_${PROJECT_NAME} PRIVATE + CONF_PATH="${CONF_INSTALL_DIR}" ) -INSTALL(TARGETS ${ZONE_PAM_NAME} DESTINATION ${LIB_INSTALL_DIR}/security) -INSTALL(FILES data/DefaultZoneManifest.xml DESTINATION ${CONF_INSTALL_DIR}/zone RENAME owner.xml) -INSTALL(FILES data/zone_indicator_icon.png DESTINATION /opt/data/dpm) -INSTALL(FILES data/zone_noti_list_sub_icon.png DESTINATION /opt/data/dpm) -INSTALL(FILES pam.d/systemd-user-zone DESTINATION ${PAMD_INSTALL_DIR}) +CONFIGURE_FILE(pam.d/systemd-user.in pam.d/systemd-user-${PROJECT_NAME}) + +INSTALL(TARGETS pam_${PROJECT_NAME} DESTINATION ${LIB_INSTALL_DIR}/security) +INSTALL(FILES pam.d/systemd-user-${PROJECT_NAME} DESTINATION ${PAMD_DIR}) diff --git a/module/krate-builder.cpp b/module/krate-builder.cpp new file mode 100644 index 0000000..bbb8797 --- /dev/null +++ b/module/krate-builder.cpp @@ -0,0 +1,75 @@ +/* + * 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 "krate-builder.h" + +#include +#include + +KrateBuilder::KrateBuilder(const runtime::User& user, const std::string& manifestPath) : + name(user.getName()), uid(user.getUid()), gid(user.getGid()) +{ + manifest.reset(xml::Parser::parseFile(manifestPath)); +} + +KrateBuilder::~KrateBuilder() +{ +} + +void KrateBuilder::bindFilesystemNode(const std::string& source, const std::string& target, + const std::string& type, const std::string& options, + bool create) +{ + if (create) { + runtime::File dir(target); + if (!dir.exists()) { + dir.makeDirectory(true, uid, gid); + } + } + + runtime::Mount::mountEntry(source, target, type, options); +} + +void KrateBuilder::containerize(bool create) +{ + int nsFlags = CLONE_NEWIPC | CLONE_NEWNS; + + if (::unshare(nsFlags)) { + throw runtime::Exception("Failed to unshare namespace"); + } + + if (::mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) == -1) { + throw runtime::Exception("Failed to mount root filesystem"); + } + + xml::Node::NodeList entries = manifest->evaluate("/manifest/filesystem/entry"); + for (const xml::Node& entry : entries) { + bindFilesystemNode(entry.getProp("source"), entry.getProp("target"), + entry.getProp("type"), entry.getProp("options")); + } + + bindFilesystemNode("/home/" + name, + "/home/" + name + "/.krate/" + name, + "none", "rw,bind"); + + bindFilesystemNode("/home/" + name + "/.krate", "/home", + "none", "rw,rbind"); +} diff --git a/module/zone-builder.h b/module/krate-builder.h similarity index 53% rename from module/zone-builder.h rename to module/krate-builder.h index 52b02a4..094b747 100644 --- a/module/zone-builder.h +++ b/module/krate-builder.h @@ -13,34 +13,33 @@ * See the License for the specific language governing permissions and * limitations under the License */ - - #ifndef __ZONE_BUILDER_H__ - #define __ZONE_BUILDER_H__ +#ifndef __KRATE_BUILDER_H__ +#define __KRATE_BUILDER_H__ #include #include #include -#include "xml/parser.h" -#include "xml/document.h" -#include "auth/user.h" +#include +#include +#include -class ZoneBuilder { +class KrateBuilder { public: - ZoneBuilder(const runtime::User& user, const std::string& manifestPath); - virtual ~ZoneBuilder(); + KrateBuilder(const runtime::User& user, const std::string& manifestPath); + virtual ~KrateBuilder(); - void containerize(bool create = true); + void containerize(bool create = true); protected: - void bindFilesystemNode(const std::string& source, const std::string& target, - const std::string& type, const std::string& options, - bool create = true); + void bindFilesystemNode(const std::string& source, const std::string& target, + const std::string& type, const std::string& options, + bool create = true); private: - std::string name; - uid_t uid; - gid_t gid; - std::unique_ptr manifest; + std::string name; + uid_t uid; + gid_t gid; + std::unique_ptr manifest; }; - #endif //!__ZONE_BUILDER_H__ +#endif //!__KRATE_BUILDER_H__ diff --git a/module/zone-guard.h b/module/krate-guard.h similarity index 50% rename from module/zone-guard.h rename to module/krate-guard.h index ded6ba2..8e09748 100644 --- a/module/zone-guard.h +++ b/module/krate-guard.h @@ -15,49 +15,48 @@ * */ -#ifndef __ZONE_GUARD_H__ -#define __ZONE_GUARD_H__ +#ifndef __KRATE_GUARD_H__ +#define __KRATE_GUARD_H__ -#include #include #include #include +#include #include -#include "exception.h" +#include -class ZoneGuard { +class KrateGuard { public: - ZoneGuard(const std::string& name) : - zoneName(name), - semaphore(nullptr) - { - semaphore = ::sem_open(zoneName.c_str(), O_CREAT, 0700, 1); - if (semaphore == nullptr) { - throw runtime::Exception("Filed to create semaphore for zone guard"); - } - } - - ~ZoneGuard() - { - if (semaphore == nullptr) { - return; - } - - ::sem_post(semaphore); - ::sem_close(semaphore); - ::sem_unlink(zoneName.c_str()); - } - - void wait() - { - while ((::sem_wait(semaphore) == -1) && (errno == EINTR)); - } + KrateGuard(const std::string& name) : + krateName(name), semaphore(nullptr) + { + semaphore = ::sem_open(krateName.c_str(), O_CREAT, 0700, 1); + if (semaphore == nullptr) { + throw runtime::Exception("Filed to create semaphore for krate guard"); + } + } + + ~KrateGuard() + { + if (semaphore == nullptr) { + return; + } + + ::sem_post(semaphore); + ::sem_close(semaphore); + ::sem_unlink(krateName.c_str()); + } + + void wait() + { + while ((::sem_wait(semaphore) == -1) && (errno == EINTR)); + } private: - std::string zoneName; - sem_t* semaphore; + std::string krateName; + sem_t* semaphore; }; -#endif //!__ZONE_GUARD_H__ +#endif //!__KRATE_GUARD_H__ diff --git a/module/krate.cpp b/module/krate.cpp new file mode 100644 index 0000000..06fea56 --- /dev/null +++ b/module/krate.cpp @@ -0,0 +1,105 @@ +/* + * 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 "session.h" +#include "krate-guard.h" +#include "krate-builder.h" + +#include +#include +#include +#include + +#define KRATE_MANIFEST_DIR CONF_PATH "/krate/" + +std::string buildKrateManifestPath(const std::string& name) +{ + return KRATE_MANIFEST_DIR + name + ".xml"; +} + +std::string getKrateName(pam_handle_t* handle) +{ + const void* retItem; + int error = ::pam_get_item(handle, PAM_USER, &retItem); + if (error != PAM_SUCCESS) { + throw runtime::Exception("Failed to get user"); + } + + return static_cast(retItem); +} + +void openKrateSession(const std::string& name) +{ + auto sessionBuilder = [](const runtime::User& user) { + KrateBuilder builder(user, buildKrateManifestPath(user.getName())); + builder.containerize(); + }; + + createSession(runtime::User(name), sessionBuilder); +} + +void closeKrateSession(const std::string& name) +{ + destroySession(runtime::User(name)); +} + +extern "C" { +PAM_EXTERN __attribute__((visibility("default"))) +int pam_sm_open_session(pam_handle_t* pamh, int flags, int argc, const char* argv[]) +{ + try { + std::string name = getKrateName(pamh); + KrateGuard krateGuard(name); + krateGuard.wait(); + + openKrateSession(name); + } catch (runtime::Exception& e) { + ::pam_syslog(pamh, LOG_ERR, "%s", e.what()); + return PAM_SESSION_ERR; + } + + return PAM_SUCCESS; +} + +PAM_EXTERN __attribute__((visibility("default"))) +int pam_sm_close_session(pam_handle_t* pamh, int flags, int argc, const char* argv[]) +{ + try { + std::string name = getKrateName(pamh); + KrateGuard krateGuard(name); + krateGuard.wait(); + + closeKrateSession(name); + } catch (runtime::Exception& e) { + ::pam_syslog(pamh, LOG_ERR, "%s", e.what()); + return PAM_SESSION_ERR; + } + + return PAM_SUCCESS; +} + +#ifdef PAM_MODULE_ENTRY +PAM_MODULE_ENTRY("pam_krate"); +#endif + +} diff --git a/module/pam.d/systemd-user-zone b/module/pam.d/systemd-user.in similarity index 68% rename from module/pam.d/systemd-user-zone rename to module/pam.d/systemd-user.in index 2245de4..1d5e242 100644 --- a/module/pam.d/systemd-user-zone +++ b/module/pam.d/systemd-user.in @@ -1,4 +1,4 @@ account include system-auth session include system-auth session optional pam_systemd.so -session required pam_zone.so +session required pam_${PROJECT_NAME}.so diff --git a/module/session.cpp b/module/session.cpp index 24b71ae..4fcd9df 100644 --- a/module/session.cpp +++ b/module/session.cpp @@ -13,60 +13,59 @@ * See the License for the specific language governing permissions and * limitations under the License */ - -#include +#include #include -#include -#include #include -#include #include +#include +#include #include "session.h" -#include "exception.h" -#include "filesystem.h" + +#include +#include bool isValidSessionLeader(pid_t pid) { - runtime::File proc("/proc/" + std::to_string(pid)); - return proc.exists(); + runtime::File proc("/proc/" + std::to_string(pid)); + return proc.exists(); } void createSession(const runtime::User& user, const SessionBuilder& sessionBuilder) { - runtime::File file("/var/run/zone/" + user.getName()); - if (file.exists()) { - if (isValidSessionLeader(getSessionLeader(user))) { - throw runtime::Exception("Session already opened"); - } - file.remove(); - } else { - file.makeBaseDirectory(); - } + runtime::File file("/var/run/krate/" + user.getName()); + if (file.exists()) { + if (isValidSessionLeader(getSessionLeader(user))) { + throw runtime::Exception("Session already opened"); + } + file.remove(); + } else { + file.makeBaseDirectory(); + } - sessionBuilder(user); + sessionBuilder(user); - file.create(0600); - file.lock(); - file.chown(user.getUid(), user.getGid()); - pid_t pid = ::getpid(); - file.write(&pid, sizeof(pid_t)); - file.unlock(); + file.create(0600); + file.lock(); + file.chown(user.getUid(), user.getGid()); + pid_t pid = ::getpid(); + file.write(&pid, sizeof(pid_t)); + file.unlock(); } pid_t getSessionLeader(const runtime::User& user) { - runtime::File file("/var/run/zone/" + user.getName(), O_RDONLY); - file.lock(); - pid_t pid = -1; - file.read(&pid, sizeof(pid_t)); - file.unlock(); + runtime::File file("/var/run/krate/" + user.getName(), O_RDONLY); + file.lock(); + pid_t pid = -1; + file.read(&pid, sizeof(pid_t)); + file.unlock(); - return pid; + return pid; } void destroySession(const runtime::User& user) { - std::string path = "/var/run/zone/" + user.getName(); - ::unlink(path.c_str()); + std::string path = "/var/run/krate/" + user.getName(); + ::unlink(path.c_str()); } diff --git a/module/session.h b/module/session.h index df01173..ebb053e 100644 --- a/module/session.h +++ b/module/session.h @@ -14,16 +14,16 @@ * limitations under the License */ -#ifndef __ZONE_SESSION_ENV_H__ -#define __ZONE_SESSION_ENV_H__ +#ifndef __KRATE_SESSION_ENV_H__ +#define __KRATE_SESSION_ENV_H__ -#include #include +#include #include #include -#include "auth/user.h" +#include typedef std::function SessionBuilder; @@ -32,4 +32,4 @@ void createSession(const runtime::User& user, const SessionBuilder& sessionBuild pid_t getSessionLeader(const runtime::User& user); void destroySession(const runtime::User& user); -#endif //!__ZONE_SESSION_ENV_H__ +#endif //!__KRATE_SESSION_ENV_H__ diff --git a/module/zone-builder.cpp b/module/zone-builder.cpp deleted file mode 100644 index c36e9da..0000000 --- a/module/zone-builder.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* - * 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 - -#include "zone-builder.h" - -#include "exception.h" -#include "filesystem.h" - -ZoneBuilder::ZoneBuilder(const runtime::User& user, const std::string& manifestPath) : - name(user.getName()), uid(user.getUid()), gid(user.getGid()) -{ - manifest.reset(xml::Parser::parseFile(manifestPath)); -} - -ZoneBuilder::~ZoneBuilder() -{ -} - -void ZoneBuilder::bindFilesystemNode(const std::string& source, const std::string& target, - const std::string& type, const std::string& options, - bool create) -{ - if (create) { - runtime::File dir(target); - if (!dir.exists()) { - dir.makeDirectory(true, uid, gid); - } - } - - runtime::Mount::mountEntry(source, target, type, options); -} - -void ZoneBuilder::containerize(bool create) -{ - int nsFlags = CLONE_NEWIPC | CLONE_NEWNS; - - if (::unshare(nsFlags)) { - throw runtime::Exception("Failed to unshare namespace"); - } - - if (::mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) == -1) { - throw runtime::Exception("Failed to mount root filesystem"); - } - - xml::Node::NodeList entries = manifest->evaluate("/manifest/filesystem/entry"); - for (const xml::Node& entry : entries) { - bindFilesystemNode(entry.getProp("source"), entry.getProp("target"), - entry.getProp("type"), entry.getProp("options")); - } - - bindFilesystemNode("/home/" + name, - "/home/" + name + "/.zone/" + name, - "none", "rw,bind"); - - bindFilesystemNode("/home/" + name + "/.zone", "/home", - "none", "rw,rbind"); -} diff --git a/module/zone.cpp b/module/zone.cpp deleted file mode 100644 index 99b9699..0000000 --- a/module/zone.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/* - * 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-guard.h" -#include "zone-builder.h" -#include "session.h" - -#include "exception.h" -#include "filesystem.h" -#include "xml/parser.h" -#include "xml/document.h" - -#define ZONE_MANIFEST_DIR CONF_PATH "/zone/" - -std::string buildZoneManifestPath(const std::string& name) -{ - return ZONE_MANIFEST_DIR + name + ".xml"; -} - -std::string getZoneName(pam_handle_t* handle) -{ - const void* retItem; - int error = ::pam_get_item(handle, PAM_USER, &retItem); - if (error != PAM_SUCCESS) { - throw runtime::Exception("Failed to get user"); - } - - return static_cast(retItem); -} - -void openZoneSession(const std::string& name) -{ - auto sessionBuilder = [](const runtime::User& user) { - ZoneBuilder builder(user, buildZoneManifestPath(user.getName())); - builder.containerize(); - }; - - createSession(runtime::User(name), sessionBuilder); -} - -void closeZoneSession(const std::string& name) -{ - destroySession(runtime::User(name)); -} - -extern "C" { -PAM_EXTERN __attribute__((visibility("default"))) -int pam_sm_open_session(pam_handle_t* pamh, int flags, int argc, const char* argv[]) -{ - try { - std::string name = getZoneName(pamh); - ZoneGuard zoneGuard(name); - zoneGuard.wait(); - - openZoneSession(name); - } catch (runtime::Exception& e) { - ::pam_syslog(pamh, LOG_ERR, "%s", e.what()); - return PAM_SESSION_ERR; - } - - return PAM_SUCCESS; -} - -PAM_EXTERN __attribute__((visibility("default"))) -int pam_sm_close_session(pam_handle_t* pamh, int flags, int argc, const char* argv[]) -{ - try { - std::string name = getZoneName(pamh); - ZoneGuard zoneGuard(name); - zoneGuard.wait(); - - closeZoneSession(name); - } catch (runtime::Exception& e) { - ::pam_syslog(pamh, LOG_ERR, "%s", e.what()); - return PAM_SESSION_ERR; - } - - return PAM_SUCCESS; -} - -#ifdef PAM_MODULE_ENTRY -PAM_MODULE_ENTRY("pam_zone"); -#endif - -} diff --git a/packaging/krate.spec b/packaging/krate.spec index 36f2523..a6e952e 100644 --- a/packaging/krate.spec +++ b/packaging/krate.spec @@ -7,8 +7,8 @@ Summary: Tizen Krate Manager Group: Security/Other BuildRequires: gcc BuildRequires: cmake -BuildRequires: pam-devel BuildRequires: gettext-tools +BuildRequires: pkgconfig(klay) BuildRequires: pkgconfig(glib-2.0) BuildRequires: pkgconfig(libxml-2.0) BuildRequires: pkgconfig(bundle) @@ -32,10 +32,16 @@ krates. %files %manifest krate.manifest %defattr(644,root,root,755) -#%attr(700,root,root) %{_sbindir}/zone-volume-manager #%attr(755,root,root) %{_bindir}/krate +%attr(700,root,root) %{_sbindir}/krate-volume-manager %{_unitdir}/krate.service #%{_unitdir}/multi-user.target.wants/krate.service +%attr(700,root,root) /etc/gumd/useradd.d/20_krate-add.post +%attr(700,root,root) /etc/gumd/userdel.d/20_krate-remove.post +%attr(644,root,root) %{TZ_SYS_RO_ICONS}/krate/indicator_icon.png +%attr(644,root,root) %{TZ_SYS_RO_ICONS}/krate/notification_sub_icon.png +%attr(700,root,root) %dir %{TZ_SYS_ETC}/krate +%attr(600,root,root) %config %{TZ_SYS_ETC}/krate/owner.xml %prep %setup -q @@ -119,11 +125,14 @@ developing the krate client program. %{_includedir}/krate %{_libdir}/pkgconfig/krate.pc +%endif + ## PAM Plugin Package ######################################################## %package -n dpm-pam-krate Summary: PAM Plugin for zone policy in device policy manager Group: Development/Libraries Requires: systemd +BuildRequires: pam-devel %description -n dpm-pam-krate PAM Plugin for zone policy in device policy manager and CLI tool @@ -139,17 +148,9 @@ mv /etc/pam.d/systemd-user.keep /etc/pam.d/systemd-user %manifest krate.manifest %defattr(600,root,root,700) %attr(700,root,root) %{_libdir}/security/pam_*.so -%attr(700,root,root) %{_sbindir}/krate-admin-cli -%attr(700,root,root) %dir %{TZ_SYS_ETC}/krate -%attr(600,root,root) %config %{TZ_SYS_ETC}/krate/owner.xml -%attr(700,root,root) /etc/gumd/useradd.d/20_pam-krate-add.post -%attr(700,root,root) /etc/gumd/userdel.d/20_pam-krate-remove.post -%attr(644,root,root) %{TZ_SYS_RO_ICONS}/krate/indicator_icon.png -%attr(644,root,root) %{TZ_SYS_RO_ICONS}/krate/noti_list_sub_icon.png +#%attr(700,root,root) %{_sbindir}/zone-admin-cli %config /etc/pam.d/* -%endif - ## Begin of mobile feature ################################################### %if "%{profile}" == "mobile" diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 7b5f240..48b71a3 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -19,3 +19,10 @@ SET(TARGET ${PROJECT_NAME}) CONFIGURE_FILE(systemd/krate.service.in systemd/krate.service) INSTALL(FILES systemd/krate.service DESTINATION ${SYSTEMD_UNIT_DIR}) + +INSTALL(FILES ${KRATE_TOOLS}/gumd-scripts/20_krate-add.post DESTINATION /etc/gumd/useradd.d) +INSTALL(FILES ${KRATE_TOOLS}/gumd-scripts/20_krate-remove.post DESTINATION /etc/gumd/userdel.d) + +INSTALL(FILES ${KRATE_DATA}/DefaultManifest.xml DESTINATION ${CONF_DIR} RENAME owner.xml) +INSTALL(FILES ${KRATE_DATA}/indicator_icon.png DESTINATION ${APP_ICON_DIR_PREFIX}/krate) +INSTALL(FILES ${KRATE_DATA}/notification_sub_icon.png DESTINATION ${APP_ICON_DIR_PREFIX}/krate) diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index baa8c10..2ce3d84 100755 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -15,5 +15,7 @@ # SET(KRATE_APPS ${KRATE_TOOLS}/apps) +#SET(KRATE_CLI ${KRATE_TOOLS}/cli) ADD_SUBDIRECTORY(${KRATE_APPS}) +#ADD_SUBDIRECTORY(${KRATE_CLI}) diff --git a/tools/cli/CMakeLists.txt b/tools/cli/CMakeLists.txt index d458cee..67a843a 100644 --- a/tools/cli/CMakeLists.txt +++ b/tools/cli/CMakeLists.txt @@ -14,29 +14,30 @@ # limitations under the License. # -PROJECT(krate-admin-cli) - -FILE(GLOB KRATE_ADMIN_CLI_SRCS krate-admin-cli.cpp - ${KRATE_MODULE}/session.cpp - ${KRATE_MODULE}/zone-builder.cpp +FILE(GLOB CLI_SRCS krate-admin-cli.cpp + ${KRATE_MODULE}/session.cpp + ${KRATE_MODULE}/krate-builder.cpp ) -SET(KRATE_ADMIN_CLI_NAME "zone-admin-cli") +SET(CLI_NAME "zone-admin-cli") -ADD_EXECUTABLE(${ZONE_CLI_NAME} ${ZONE_CLI_SRCS}) -SET_TARGET_PROPERTIES(${ZONE_CLI_NAME} PROPERTIES PREFIX "" - COMPILE_DEFINITIONS PID_FILE_PATH="${RUN_INSTALL_DIR}/zone" - COMPILE_FLAGS "-fPIE" - LINK_FLAGS "-pie" +ADD_EXECUTABLE(${CLI_NAME} ${CLI_SRCS}) +SET_TARGET_PROPERTIES(${CLI_NAME} PROPERTIES PREFIX "" + COMPILE_DEFINITIONS PID_FILE_PATH="${RUN_DIR}/krate" + COMPILE_FLAGS "-fPIE" + LINK_FLAGS "-pie" ) -PKG_CHECK_MODULES(ZONE_CLI_DEPS REQUIRED - glib-2.0 - capi-appfw-package-manager - capi-appfw-app-manager +PKG_CHECK_MODULES(CLI_DEPS REQUIRED + klay + glib-2.0 + libxml-2.0 + capi-appfw-package-manager + capi-appfw-app-manager + zone ) -INCLUDE_DIRECTORIES(SYSTEM ${ZONE_CLI_DEPS_INCLUDE_DIRS} ${DPM_COMMON} ${ZONE_MODULE} ${ZONE_LIBS}) -TARGET_LINK_LIBRARIES(${ZONE_CLI_NAME} ${ZONE_CLI_DEPS_LIBRARIES} dpm-common zone) +INCLUDE_DIRECTORIES(SYSTEM ${CLI_DEPS_INCLUDE_DIRS} ${KRATE_MODULE}) +TARGET_LINK_LIBRARIES(${CLI_NAME} ${CLI_DEPS_LIBRARIES}) -INSTALL(TARGETS ${ZONE_CLI_NAME} DESTINATION sbin) +INSTALL(TARGETS ${CLI_NAME} DESTINATION sbin) diff --git a/tools/cli/krate-admin-cli.cpp b/tools/cli/krate-admin-cli.cpp index 9fe5157..e46e45b 100644 --- a/tools/cli/krate-admin-cli.cpp +++ b/tools/cli/krate-admin-cli.cpp @@ -22,457 +22,456 @@ * @author Sungbae Yoo (sungbae.yoo@samsung.com) * @brief CLI tool to attach to existing namespace by pam-attach.so */ + #define _XOPEN_SOURCE +#include #include +#include +#include +#include #include #include #include #include -#include -#include -#include -#include -#include - +#include #include #include -#include #include +#include + +#include +#include +#include -#include #include +#include #include "session.h" -#include "error.h" -#include "exception.h" -#include "filesystem.h" -#include "auth/user.h" - #define DEFAULT_SHELL "/bin/bash" typedef std::pair NamespacePair; std::vector namespaces = { - {"mnt", CLONE_NEWNS}, - {"net", CLONE_NEWNET}, - {"uts", CLONE_NEWUTS}, - {"user", CLONE_NEWUSER}, - {"ipc", CLONE_NEWIPC}, - {"pid", CLONE_NEWPID} + {"mnt", CLONE_NEWNS}, + {"net", CLONE_NEWNET}, + {"uts", CLONE_NEWUTS}, + {"user", CLONE_NEWUSER}, + {"ipc", CLONE_NEWIPC}, + {"pid", CLONE_NEWPID} }; extern char** environ; static inline void usage(const std::string name) { - std::cout << "Usage: " << name << " [Option] -- COMMAND" << std::endl - << "Run a program in the zone" << std::endl - << std::endl - << "Options :" << std::endl - << " -a, --attach=zone execute command in the zone" << std::endl - << " -p, --pkginfo=zone show all packages in the zone" << std::endl - << " -q, --appinfo=zone show all applications in the zone" << std::endl - << " -m, --zone-monitor monitor all zone events" << std::endl - << " -n, --pkg-monitor monitor all package events in the zone" << std::endl - << " -l, --list show all zone instances" << std::endl - << " -h, --help show this" << std::endl - << std::endl; + std::cout << "Usage: " << name << " [Option] -- COMMAND" << std::endl + << "Run a program in the krate" << std::endl + << std::endl + << "Options :" << std::endl + << " -a, --attach=krate execute command in the krate" << std::endl + << " -p, --pkginfo=krate show all packages in the krate" << std::endl + << " -q, --appinfo=krate show all applications in the krate" << std::endl + << " -m, --krate-monitor monitor all krate events" << std::endl + << " -n, --pkg-monitor monitor all package events in the krate" << std::endl + << " -l, --list show all krate instances" << std::endl + << " -h, --help show this" << std::endl + << std::endl; } -int showZoneInstances() +int showKrateInstances() { - try { - runtime::DirectoryIterator iter(runtime::Path("/var/run/zone")), end; - - while (iter != end) { - const std::string& path = (*iter).getPath(); - size_t name = path.rfind('/') + 1; - std::cout << path.substr(name) << std::endl; - ++iter; - } - } catch (runtime::Exception& e) { - std::cerr << e.what() << std::endl; - return -1; - } - - return 0; + try { + runtime::DirectoryIterator iter("/var/run/krate"), end; + + while (iter != end) { + const std::string& path = (*iter).getPath(); + size_t name = path.rfind('/') + 1; + std::cout << path.substr(name) << std::endl; + ++iter; + } + } catch (runtime::Exception& e) { + std::cerr << e.what() << std::endl; + return -1; + } + + return 0; } void attachNamespaces(pid_t pid) { - int fd; - for (const NamespacePair& ns : namespaces) { - std::string nspath = "/proc/" + std::to_string(pid) + "/ns/" + ns.first; - - do { - fd = ::open(nspath.c_str(), O_RDONLY); - } while (fd == -1 && errno == EINTR); - - if (fd == -1) { - if (errno != ENOENT) { - throw runtime::Exception("Failed to open namesapce: " + nspath); - } - } else { - if (::setns(fd, ns.second)) { - ::close(fd); - throw runtime::Exception("Failed to attach namespace: " + nspath); - } - ::close(fd); - } - } + int fd; + for (const NamespacePair& ns : namespaces) { + std::string nspath = "/proc/" + std::to_string(pid) + "/ns/" + ns.first; + + do { + fd = ::open(nspath.c_str(), O_RDONLY); + } while (fd == -1 && errno == EINTR); + + if (fd == -1) { + if (errno != ENOENT) { + throw runtime::Exception("Failed to open namesapce: " + nspath); + } + } else { + if (::setns(fd, ns.second)) { + ::close(fd); + throw runtime::Exception("Failed to attach namespace: " + nspath); + } + ::close(fd); + } + } } void launchProcess(runtime::User& user, char** args) { - int status; - - pid_t pid = ::fork(); - if (pid == -1) { - throw runtime::Exception("Failed to create child process"); - } - - if (pid != 0) { - ::waitpid(pid, &status, 0); - if (WEXITSTATUS(status) != EXIT_SUCCESS) { - throw runtime::Exception("Child process terminated abnormally"); - } - return; - } - - if (::initgroups(user.getName().c_str(), user.getGid()) == -1) { - std::cerr << "Failed to initgroups()" << std::endl; - ::exit(EXIT_FAILURE); - } - - if (::setgid(user.getGid()) == -1) { - std::cerr << "Failed to setgid()" << std::endl; - ::exit(EXIT_FAILURE); - } - - if (::setuid(user.getUid()) == -1) { - std::cerr << "Failed to setuid()" << std::endl; - ::exit(EXIT_FAILURE); - } - - char *default_args[2]; - default_args[0] = ::strdup(DEFAULT_SHELL); - default_args[1] = NULL; - - if (args == NULL) { - args = default_args; - } - - ::execve(*args, args, environ); - std::cerr << "Failed to execute " << args[0] << std::endl; - - ::free(default_args[0]); - - ::exit(EXIT_FAILURE); + int status; + + pid_t pid = ::fork(); + if (pid == -1) { + throw runtime::Exception("Failed to create child process"); + } + + if (pid != 0) { + ::waitpid(pid, &status, 0); + if (WEXITSTATUS(status) != EXIT_SUCCESS) { + throw runtime::Exception("Child process terminated abnormally"); + } + return; + } + + if (::initgroups(user.getName().c_str(), user.getGid()) == -1) { + std::cerr << "Failed to initgroups()" << std::endl; + ::exit(EXIT_FAILURE); + } + + if (::setgid(user.getGid()) == -1) { + std::cerr << "Failed to setgid()" << std::endl; + ::exit(EXIT_FAILURE); + } + + if (::setuid(user.getUid()) == -1) { + std::cerr << "Failed to setuid()" << std::endl; + ::exit(EXIT_FAILURE); + } + + char *default_args[2]; + default_args[0] = ::strdup(DEFAULT_SHELL); + default_args[1] = NULL; + + if (args == NULL) { + args = default_args; + } + + ::execve(*args, args, environ); + std::cerr << "Failed to execute " << args[0] << std::endl; + + ::free(default_args[0]); + + ::exit(EXIT_FAILURE); } -int attachToZone(const std::string& name, char* args[]) +int attachToKrate(const std::string& name, char* args[]) { - try { - runtime::User user(name); + try { + runtime::User user(name); - attachNamespaces(getSessionLeader(user)); - launchProcess(user, args); - } catch (runtime::Exception& e) { - std::cerr << e.what() << std::endl; - return -1; - } + attachNamespaces(getSessionLeader(user)); + launchProcess(user, args); + } catch (runtime::Exception& e) { + std::cerr << e.what() << std::endl; + return -1; + } - return 0; + return 0; } bool packgeListCallback(package_info_h info, void *user_data) { - bool checked; - char *val; - - std::cout << "Package #" << (*(int*)user_data)++ << " :" << std::endl; - - package_info_get_package(info, &val); - std::cout << val; - free(val); - - package_info_get_version(info, &val); - std::cout << " (" << val << ")" << std::endl; - free(val); - - package_info_get_type(info, &val); - std::cout << " Type : " << val << " ("; - free(val); - - package_info_is_system_package(info, &checked); - if (checked) { - std::cout <<" System "; - } - package_info_is_removable_package(info, &checked); - if (checked) { - std::cout <<" Removable "; - } - package_info_is_preload_package(info, &checked); - if (checked) { - std::cout <<" Preload "; - } - std::cout << ")" << std::endl; - - package_info_get_label(info, &val); - std::cout << " Label : " << val << std::endl; - free(val); - - package_info_get_icon(info, &val); - std::cout << " Icon : " << val << std::endl; - free(val); - - std::cout << std::endl; - - return true; + bool checked; + char *val; + + std::cout << "Package #" << (*(int*)user_data)++ << " :" << std::endl; + + package_info_get_package(info, &val); + std::cout << val; + free(val); + + package_info_get_version(info, &val); + std::cout << " (" << val << ")" << std::endl; + free(val); + + package_info_get_type(info, &val); + std::cout << " Type : " << val << " ("; + free(val); + + package_info_is_system_package(info, &checked); + if (checked) { + std::cout <<" System "; + } + package_info_is_removable_package(info, &checked); + if (checked) { + std::cout <<" Removable "; + } + package_info_is_preload_package(info, &checked); + if (checked) { + std::cout <<" Preload "; + } + std::cout << ")" << std::endl; + + package_info_get_label(info, &val); + std::cout << " Label : " << val << std::endl; + free(val); + + package_info_get_icon(info, &val); + std::cout << " Icon : " << val << std::endl; + free(val); + + std::cout << std::endl; + + return true; } int showPkgInfo(const std::string& name) { - int num = 0; + int num = 0; - zone_manager_h zoneMgr; - zone_package_proxy_h pkgProxy; + zone_manager_h krateMgr; + zone_package_proxy_h pkgProxy; - zone_manager_create(&zoneMgr); - zone_package_proxy_create(zoneMgr, name.c_str(), &pkgProxy); - zone_package_proxy_foreach_package_info(pkgProxy, packgeListCallback, &num); - std::cout << num << " packages are found" << std::endl; - zone_package_proxy_destroy(pkgProxy); - zone_manager_destroy(zoneMgr); + zone_manager_create(&krateMgr); + zone_package_proxy_create(krateMgr, name.c_str(), &pkgProxy); + zone_package_proxy_foreach_package_info(pkgProxy, packgeListCallback, &num); + std::cout << num << " packages are found" << std::endl; + zone_package_proxy_destroy(pkgProxy); + zone_manager_destroy(krateMgr); - return 0; + return 0; } bool applicationListCallback(app_info_h info, void *user_data) { - bool checked; - char *val; + bool checked; + char *val; - std::cout << "Application #" << (*(int*)user_data)++ << " :" << std::endl; + std::cout << "Application #" << (*(int*)user_data)++ << " :" << std::endl; - app_info_get_app_id(info, &val); - std::cout << val; - free(val); + app_info_get_app_id(info, &val); + std::cout << val; + free(val); - app_info_get_package(info, &val); - std::cout << " (" << val << ")" << std::endl; - free(val); + app_info_get_package(info, &val); + std::cout << " (" << val << ")" << std::endl; + free(val); - app_info_get_type(info, &val); - std::cout << " Type : " << val << " ("; - free(val); + app_info_get_type(info, &val); + std::cout << " Type : " << val << " ("; + free(val); - app_info_is_nodisplay(info, &checked); - if (checked) { - std::cout <<" NoDisplay "; - } - std::cout << ")"<< std::endl; + app_info_is_nodisplay(info, &checked); + if (checked) { + std::cout <<" NoDisplay "; + } + std::cout << ")"<< std::endl; - app_info_get_label(info, &val); - std::cout << " Label : " << val << std::endl; - free(val); + app_info_get_label(info, &val); + std::cout << " Label : " << val << std::endl; + free(val); - if (app_info_get_icon(info, &val) == APP_MANAGER_ERROR_NONE) { - std::cout << " Icon : " << val << std::endl; - free(val); - } else { - std::cout << "App Manager error" << std::endl; - } + if (app_info_get_icon(info, &val) == APP_MANAGER_ERROR_NONE) { + std::cout << " Icon : " << val << std::endl; + free(val); + } else { + std::cout << "App Manager error" << std::endl; + } - std::cout << std::endl; + std::cout << std::endl; - return true; + return true; } int showAppInfo(const std::string& name) { - int num = 0; + int num = 0; - zone_manager_h zoneMgr; - zone_app_proxy_h appMgr; + zone_manager_h krateMgr; + zone_app_proxy_h appMgr; - zone_manager_create(&zoneMgr); - zone_app_proxy_create(zoneMgr, name.c_str(), &appMgr); - zone_app_proxy_foreach_app_info(appMgr, applicationListCallback, &num); - std::cout << num << " applications are found" << std::endl; - zone_app_proxy_destroy(appMgr); - zone_manager_destroy(zoneMgr); + zone_manager_create(&krateMgr); + zone_app_proxy_create(krateMgr, name.c_str(), &appMgr); + zone_app_proxy_foreach_app_info(appMgr, applicationListCallback, &num); + std::cout << num << " applications are found" << std::endl; + zone_app_proxy_destroy(appMgr); + zone_manager_destroy(krateMgr); - return 0; + return 0; } GMainLoop *gmainloop = NULL; void monitorSigHandler(int sig) { - g_main_loop_quit(gmainloop); + g_main_loop_quit(gmainloop); } -void zoneCallback(const char* name, const char* object, void *user_data) +void krateCallback(const char* name, const char* object, void *user_data) { - std::cout << "--- Zone event ---" << std::endl; - std::cout << "Type : " << (char*)user_data << std::endl; - std::cout << "Name : " << name <= argc ? NULL : argv + optind); - break; - case 'p': - ret = showPkgInfo(optarg); - break; - case 'q': - ret = showAppInfo(optarg); - break; - case 'm': - ret = monitorEvent(); - break; - case 'n': - ret = monitorPkgEvent(optarg); - break; - case 'l': - ret = showZoneInstances(); - break; - case 'h': - usage(argv[0]); - break; - default: - usage(argv[0]); - ret = -1; - } - } - - return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; + int opt = 0, index, ret = 0; + + struct option options[] = { + {"attach", required_argument, 0, 'a'}, + {"list", no_argument, 0, 'l'}, + {"pkginfo", required_argument, 0, 'p'}, + {"appinfo", required_argument, 0, 'q'}, + {"krate-monitor", no_argument, 0, 'm'}, + {"pkg-monitor", no_argument, 0, 'n'}, + {"help", no_argument, 0, 'h'}, + {0, 0, 0, 0} + }; + + if (argc <= 1) { + usage(argv[0]); + return EXIT_SUCCESS; + } + + while ((opt = getopt_long(argc, argv, "a:p:q:mn:lh", options, &index)) != -1) { + switch (opt) { + case 'a': + ret = attachToKrate(optarg, optind >= argc ? NULL : argv + optind); + break; + case 'p': + ret = showPkgInfo(optarg); + break; + case 'q': + ret = showAppInfo(optarg); + break; + case 'm': + ret = monitorEvent(); + break; + case 'n': + ret = monitorPkgEvent(optarg); + break; + case 'l': + ret = showKrateInstances(); + break; + case 'h': + usage(argv[0]); + break; + default: + usage(argv[0]); + ret = -1; + } + } + + return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/tools/gumd-scripts/20_pam-krate-add.post b/tools/gumd-scripts/20_krate-add.post similarity index 100% rename from tools/gumd-scripts/20_pam-krate-add.post rename to tools/gumd-scripts/20_krate-add.post diff --git a/tools/gumd-scripts/20_pam-krate-remove.post b/tools/gumd-scripts/20_krate-remove.post similarity index 100% rename from tools/gumd-scripts/20_pam-krate-remove.post rename to tools/gumd-scripts/20_krate-remove.post diff --git a/volume/CMakeLists.txt b/volume/CMakeLists.txt new file mode 100644 index 0000000..0ae5e95 --- /dev/null +++ b/volume/CMakeLists.txt @@ -0,0 +1,33 @@ +# +# Copyright (c) 2016 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. +# +SET(VOLUME_MANAGER_SRCS key-manager.cpp + key-generator.cpp + kernel-keyring.cpp + main.cpp +) + +PKG_CHECK_MODULES(VOLUME_MANAGER_DEPS REQUIRED + klay + key-manager +) + +INCLUDE_DIRECTORIES(SYSTEM ${VOLUME_MANAGER_DEPS_INCLUDE_DIRS}) + +ADD_EXECUTABLE(${PROJECT_NAME}-volume-manager ${VOLUME_MANAGER_SRCS}) + +TARGET_LINK_LIBRARIES(${PROJECT_NAME}-volume-manager ${VOLUME_MANAGER_DEPS_LIBRARIES}) + +INSTALL(TARGETS ${PROJECT_NAME}-volume-manager DESTINATION sbin) diff --git a/volume/ecryptfs.h b/volume/ecryptfs.h new file mode 100755 index 0000000..9962e34 --- /dev/null +++ b/volume/ecryptfs.h @@ -0,0 +1,107 @@ +/* + * 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 __ECRYPTFS_H__ +#define __ECRYPTFS_H__ + +#include +#include + +// this is versions of ecryptfs module +#define ECRYPTFS_MAJOR_VERSION 0x00 +#define ECRYPTFS_MINOR_VERSION 0x04 +#define ECRYPTFS_VERSION ((ECRYPTFS_MAJOR_VERSION << 8) | ECRYPTFS_MINOR_VERSION) + +#define ECRYPTFS_MAX_PKI_NAME_BYTES 16 +#define ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET 0x02 + +#define PGP_DIGEST_ALGO_SHA512 10 + +#define ECRYPTFS_FEK_CIPHER "aes" +#define ECRYPTFS_MOUNT_DEVICE "ecryptfs" + +#define ECRYPTFS_MAX_OPTIONS 1024 + +#define ECRYPTFS_MAX_SIG_SIZE 8 +#define ECRYPTFS_MAX_SIG_HEX (ECRYPTFS_MAX_SIG_SIZE*2) +#define ECRYPTFS_PASSWORD_SIG_SIZE ECRYPTFS_MAX_SIG_HEX + +#define ECRYPTFS_MAX_KEY_SIZE 32 +#define ECRYPTFS_MAX_KEY_HEX (ECRYPTFS_MAX_KEY_SIZE * 2) + +#define ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES 512 +#define ECRYPTFS_MAX_PKI_NAME_BYTES 16 + +#define ECRYPTFS_MAX_SALT_SIZE 4 +#define ECRYPTFS_MAX_SALT_HEX 8 + +#define ECRYPTFS_PWD_PAYLOAD_TYPE 0 // password + +struct ecryptfs_session_key { +#define ECRYPTFS_USERSPACE_SHOULD_TRY_TO_DECRYPT 0x00000001 +#define ECRYPTFS_USERSPACE_SHOULD_TRY_TO_ENCRYPT 0x00000002 +#define ECRYPTFS_CONTAINS_DECRYPTED_KEY 0x00000004 +#define ECRYPTFS_CONTAINS_ENCRYPTED_KEY 0x00000008 + int32_t flags; + int32_t encrypted_key_size; + int32_t decrypted_key_size; + u_int8_t encrypted_key[ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES]; + u_int8_t decrypted_key[ECRYPTFS_MAX_KEY_HEX]; +}; + +struct ecryptfs_password { + int32_t password_bytes; + int32_t hash_algo; + int32_t hash_iterations; + int32_t session_key_encryption_key_bytes; +#define ECRYPTFS_PERSISTENT_PASSWORD 0x01 +#define ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET 0x02 + u_int32_t flags; + /* Iterated-hash concatenation of salt and passphrase */ + u_int8_t session_key_encryption_key[ECRYPTFS_MAX_KEY_HEX]; + u_int8_t signature[ECRYPTFS_PASSWORD_SIG_SIZE + 1]; + /* Always in expanded hex */ + u_int8_t salt[ECRYPTFS_MAX_SALT_SIZE]; +}; + +enum ecryptfs_token_types { + ECRYPTFS_PASSWORD, + ECRYPTFS_PRIVATE_KEY +}; + +struct ecryptfs_private_key { + u_int32_t key_size; + u_int32_t data_len; + u_int8_t signature[ECRYPTFS_PASSWORD_SIG_SIZE + 1]; + char pki_type[ECRYPTFS_MAX_PKI_NAME_BYTES + 1]; + u_int8_t data[]; +}; + +struct ecryptfs_auth_tok { + u_int16_t version; /* 8-bit major and 8-bit minor */ + u_int16_t token_type; +#define ECRYPTFS_ENCRYPT_ONLY 0x00000001 + u_int32_t flags; + struct ecryptfs_session_key session_key; + u_int8_t reserved[32]; + union { + struct ecryptfs_password password; + struct ecryptfs_private_key private_key; + } token; +} __attribute__((packed)); + +typedef struct ecryptfs_auth_tok ecryptfs_payload; +#endif diff --git a/volume/kernel-keyring.cpp b/volume/kernel-keyring.cpp new file mode 100755 index 0000000..11d2373 --- /dev/null +++ b/volume/kernel-keyring.cpp @@ -0,0 +1,46 @@ +/* + * 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 "kernel-keyring.h" + +#ifndef KEYCTL_SEARCH +#define KEYCTL_SEARCH 10 +#endif + +KeySerial KernelKeyRing::add(const char *type, const char* description, const void* payload, size_t plen, KeySerial ringid) +{ + return ::syscall(__NR_add_key, type, description, payload, plen, ringid); +} + +long KernelKeyRing::search(KeySerial ringid, const char* type, const char* description, KeySerial destringid) +{ + return ::syscall(__NR_keyctl, KEYCTL_SEARCH, ringid, type, description, destringid); +} + +long KernelKeyRing::link(KeySerial keyid, KeySerial ringid) +{ + return ::syscall(__NR_keyctl, KEYCTL_LINK, keyid, ringid); +} + +long KernelKeyRing::unlink(KeySerial keyid, KeySerial ringid) +{ + return ::syscall(__NR_keyctl, KEYCTL_UNLINK, keyid, ringid); +} diff --git a/volume/kernel-keyring.h b/volume/kernel-keyring.h new file mode 100755 index 0000000..c23d70f --- /dev/null +++ b/volume/kernel-keyring.h @@ -0,0 +1,42 @@ +/* + * 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 __KERNEL_KEY_RING_H__ +#define __KERNEL_KEY_RING_H__ + +#include +#include + +#include + +typedef int32_t KeySerial; + +class KernelKeyRing { +public: + KernelKeyRing() = delete; + KernelKeyRing(const KernelKeyRing&) = delete; + KernelKeyRing(KernelKeyRing&&) = delete; + + KernelKeyRing& operator=(const KernelKeyRing&) = delete; + KernelKeyRing& operator=(KernelKeyRing&&) = delete; + + static KeySerial add(const char* type, const char* description, const void* payload, size_t plen, KeySerial ringid); + static long search(KeySerial ringid, const char* type, const char* description, KeySerial destringid); + static long link(KeySerial keyid, KeySerial ringid); + static long unlink(KeySerial keyid, KeySerial ringid); +}; + +#endif //!__KERNEL_KEY_RING_H__ diff --git a/volume/key-generator.cpp b/volume/key-generator.cpp new file mode 100755 index 0000000..d6440f6 --- /dev/null +++ b/volume/key-generator.cpp @@ -0,0 +1,322 @@ +/* + * 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 +#include +#include +#include +#include + +#include +#include + +#include "key-generator.h" + +#define RAND_READ_BYTES 8 +#define PBKDF2_ITERATION 1000 +#define SHA_BLOCKSIZE 64 + +#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) + +#if defined (BYTE_ORDER) && defined(BIG_ENDIAN) && (BYTE_ORDER == BIG_ENDIAN) +#define WORDS_BIGENDIAN 1 +#endif +#ifdef _BIG_ENDIAN +#define WORDS_BIGENDIAN 1 +#endif + +#ifdef WORDS_BIGENDIAN +#define blk0(i) block->l[i] +#else +#define blk0(i) (block->l[i] = (rol(block->l[i], 24)&0xff00ff00) \ + |(rol(block->l[i], 8)&0x00ff00ff)) +#endif +#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ + ^block->l[(i+2)&15]^block->l[i&15], 1)) + +/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ +#define R0(v, w, x, y, z, i) \ + z+=((w&(x^y))^y)+blk0(i)+0x5a827999+rol(v, 5);w=rol(w, 30); +#define R1(v, w, x, y, z, i) \ + z+=((w&(x^y))^y)+blk(i)+0x5a827999+rol(v, 5);w=rol(w, 30); +#define R2(v, w, x, y, z, i) \ + z+=(w^x^y)+blk(i)+0x6ed9eba1+rol(v, 5);w=rol(w, 30); +#define R3(v, w, x, y, z, i) \ + z+=(((w|x)&y)|(w&x))+blk(i)+0x8f1bbcdc+rol(v, 5);w=rol(w, 30); +#define R4(v, w, x, y, z, i) \ + z+=(w^x^y)+blk(i)+0xca62c1d6+rol(v, 5);w=rol(w, 30); + +#define __min__(a, b) (((a) < (b)) ? (a) : (b)) + +std::string KeyGenerator::hexConvert(unsigned char* src, int srcLen) +{ + std::ostringstream ss; + + for (int i = 0; i state[0] = 0x67452301; + context->state[1] = 0xefcdab89; + context->state[2] = 0x98badcfe; + context->state[3] = 0x10325476; + context->state[4] = 0xc3d2e1f0; + context->count[0] = context->count[1] = 0; +} + +void KeyGenerator::sha1Update(SHA1_CTX* context, const void* p, unsigned int len) +{ + const unsigned char* data = (unsigned char*)p; + unsigned int i, j; + + j = (context->count[0] >> 3) & 63; + if ((context->count[0] += (len << 3)) < (len << 3)) { + context->count[1]++; + } + context->count[1] += (len >> 29); + if ((j + len) > 63) { + ::memcpy(&context->buffer[j], data, (i = 64 - j)); + sha1Transform(context->state, context->buffer); + for (; i + 63 < len; i += 64) { + sha1Transform(context->state, data + i); + } + j = 0; + } else { + i = 0; + } + + ::memcpy(&context->buffer[j], &data[i], len - i); +} + +void KeyGenerator::sha1Final(unsigned char digest[SHA1_DIGEST_SIZE], SHA1_CTX* context) +{ + unsigned int i; + unsigned char finalcount[8]; + for (i = 0; i < 8; i++) { + finalcount[i] = (unsigned char) ((context->count[(i >= 4 ? 0 : 1)] + >> ((3 - (i & 3)) * 8)) & 255); + } + sha1Update(context, (unsigned char*) "\200", 1); + while ((context->count[0] & 504) != 448) { + sha1Update(context, (unsigned char*) "\0", 1); + } + sha1Update(context, finalcount, 8); + /* Should cause SHA1_Transform */ + for (i = 0; i < SHA1_DIGEST_SIZE; i++) { + digest[i] = (unsigned char) + ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255); + } + /* Wipe variables */ + i = 0; + ::memset(context->buffer, 0, 64); + ::memset(context->state, 0, 20); + ::memset(context->count, 0, 8); + ::memset(finalcount, 0, 8); /* SWR */ + +#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite its own static vars */ + transform(context->state, context->buffer); +#endif +} + +void KeyGenerator::sha1Transform(unsigned int state[5], const unsigned char buffer[64]) +{ + uint32_t a, b, c, d, e; + typedef union { + unsigned char c[64]; + unsigned int l[16]; + } CHAR64LONG16; + CHAR64LONG16 *block; + +#ifdef SHA1HANDSOFF + CHAR64LONG16 workspace; + block = &workspace; + ::memcpy(block, buffer, 64); +#else + block = (CHAR64LONG16*)buffer; +#endif + + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a, b, c, d, e, 0); R0(e, a, b, c, d, 1); R0(d, e, a, b, c, 2); R0(c, d, e, a, b, 3); + R0(b, c, d, e, a, 4); R0(a, b, c, d, e, 5); R0(e, a, b, c, d, 6); R0(d, e, a, b, c, 7); + R0(c, d, e, a, b, 8); R0(b, c, d, e, a, 9); R0(a, b, c, d, e, 10); R0(e, a, b, c, d, 11); + R0(d, e, a, b, c, 12); R0(c, d, e, a, b, 13); R0(b, c, d, e, a, 14); R0(a, b, c, d, e, 15); + R1(e, a, b, c, d, 16); R1(d, e, a, b, c, 17); R1(c, d, e, a, b, 18); R1(b, c, d, e, a, 19); + R2(a, b, c, d, e, 20); R2(e, a, b, c, d, 21); R2(d, e, a, b, c, 22); R2(c, d, e, a, b, 23); + R2(b, c, d, e, a, 24); R2(a, b, c, d, e, 25); R2(e, a, b, c, d, 26); R2(d, e, a, b, c, 27); + R2(c, d, e, a, b, 28); R2(b, c, d, e, a, 29); R2(a, b, c, d, e, 30); R2(e, a, b, c, d, 31); + R2(d, e, a, b, c, 32); R2(c, d, e, a, b, 33); R2(b, c, d, e, a, 34); R2(a, b, c, d, e, 35); + R2(e, a, b, c, d, 36); R2(d, e, a, b, c, 37); R2(c, d, e, a, b, 38); R2(b, c, d, e, a, 39); + R3(a, b, c, d, e, 40); R3(e, a, b, c, d, 41); R3(d, e, a, b, c, 42); R3(c, d, e, a, b, 43); + R3(b, c, d, e, a, 44); R3(a, b, c, d, e, 45); R3(e, a, b, c, d, 46); R3(d, e, a, b, c, 47); + R3(c, d, e, a, b, 48); R3(b, c, d, e, a, 49); R3(a, b, c, d, e, 50); R3(e, a, b, c, d, 51); + R3(d, e, a, b, c, 52); R3(c, d, e, a, b, 53); R3(b, c, d, e, a, 54); R3(a, b, c, d, e, 55); + R3(e, a, b, c, d, 56); R3(d, e, a, b, c, 57); R3(c, d, e, a, b, 58); R3(b, c, d, e, a, 59); + R4(a, b, c, d, e, 60); R4(e, a, b, c, d, 61); R4(d, e, a, b, c, 62); R4(c, d, e, a, b, 63); + R4(b, c, d, e, a, 64); R4(a, b, c, d, e, 65); R4(e, a, b, c, d, 66); R4(d, e, a, b, c, 67); + R4(c, d, e, a, b, 68); R4(b, c, d, e, a, 69); R4(a, b, c, d, e, 70); R4(e, a, b, c, d, 71); + R4(d, e, a, b, c, 72); R4(c, d, e, a, b, 73); R4(b, c, d, e, a, 74); R4(a, b, c, d, e, 75); + R4(e, a, b, c, d, 76); R4(d, e, a, b, c, 77); R4(c, d, e, a, b, 78); R4(b, c, d, e, a, 79); + + /* Add the working vars back into context.state[] */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + + /* Wipe variables */ + a = b = c = d = e = 0; +} + +void KeyGenerator::sha1Hmac(const unsigned char* key, int keyLen, const unsigned char* data, int dataLen, unsigned char out[SHA1_DIGEST_SIZE]) +{ + SHA1_CTX ctx; + unsigned char buf[SHA_BLOCKSIZE], outPad[SHA_BLOCKSIZE], inPad[SHA_BLOCKSIZE]; + unsigned char tempKey[SHA1_DIGEST_SIZE]; + int i; + + ::memset(buf, 0, SHA_BLOCKSIZE); + + if (keyLen > SHA_BLOCKSIZE) { + sha1Init(&ctx); + sha1Update(&ctx, key, keyLen); + sha1Final(tempKey, &ctx); + key = tempKey; + keyLen = SHA1_DIGEST_SIZE; + } + + ::memcpy(buf, key, keyLen); + ::memset(inPad, 0, SHA_BLOCKSIZE); + ::memset(outPad, 0, SHA_BLOCKSIZE); + + for (i = 0; i < SHA_BLOCKSIZE; i++) { + outPad[i] = buf[i] ^ 0x5c; + inPad[i]= buf[i] ^ 0x36; + } + + sha1Init(&ctx); + sha1Update(&ctx, inPad, SHA_BLOCKSIZE); + sha1Update(&ctx, data, dataLen); + sha1Final(out, &ctx); + + sha1Init(&ctx); + sha1Update(&ctx, outPad, SHA_BLOCKSIZE); + sha1Update(&ctx, out, SHA1_DIGEST_SIZE); + sha1Final(out, &ctx); +} + +int KeyGenerator::pbkdf2(const char * pass, int passLen, const unsigned char* salt, int saltLen, int iter, int keyLen, unsigned char* out) +{ + unsigned char digtmp1[SHA1_DIGEST_SIZE], digtmp2[SHA1_DIGEST_SIZE], itmp[saltLen + 4]; + int j, k; + int genKeyLen = 0, toWriteLen; + unsigned long i = 1; + + if (passLen <= 0 || saltLen <= 0 || iter <= 0 || keyLen <= 0) + return -1; + + ::memcpy(itmp, salt, saltLen); + while (genKeyLen < keyLen) { + itmp[saltLen + 0] = (unsigned char)((i >> 24) & 0xff); + itmp[saltLen + 1] = (unsigned char)((i >> 16) & 0xff); + itmp[saltLen + 2] = (unsigned char)((i >> 8) & 0xff); + itmp[saltLen + 3] = (unsigned char)(i & 0xff); + + sha1Hmac((unsigned char*)pass, passLen, itmp, saltLen+4, digtmp1); + ::memcpy(digtmp2, digtmp1, SHA1_DIGEST_SIZE); + + for (j = 1; j < iter; j++) { + sha1Hmac((unsigned char*)pass, passLen, digtmp1, SHA1_DIGEST_SIZE, digtmp1); + for (k = 0; k < SHA1_DIGEST_SIZE; k++) { + digtmp2[k] ^= digtmp1[k]; + } + } + toWriteLen = __min__((keyLen - genKeyLen), SHA1_DIGEST_SIZE); + ::memcpy(out+genKeyLen, digtmp2, toWriteLen); + genKeyLen += toWriteLen; + ++i; + } + + return 1; +} diff --git a/volume/key-generator.h b/volume/key-generator.h new file mode 100755 index 0000000..e0d9796 --- /dev/null +++ b/volume/key-generator.h @@ -0,0 +1,54 @@ +/* + * 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 __VOLUME_MANAGER_KEY_GENERATOR_H__ +#define __VOLUME_MANAGER_KEY_GENERATOR_H__ + +#include "ecryptfs.h" + +#define SHA1_DIGEST_SIZE 20 + +typedef struct { + unsigned int state[5]; + unsigned int count[2]; + unsigned char buffer[64]; +} SHA1_CTX; + +class KeyGenerator { +public: + KeyGenerator() = delete; + KeyGenerator(const KeyGenerator&) = delete; + KeyGenerator(KeyGenerator&&) = delete; + + KeyGenerator& operator=(const KeyGenerator&) = delete; + KeyGenerator& operator=(KeyGenerator&&) = delete; + + static std::string wrapKey(const std::string& decrypted, const std::string& salt, int len); + static std::string generateKey(int len); + static void generateToken(char* key, ecryptfs_payload** outToken); + +private: + static void sha1Init(SHA1_CTX* context); + static void sha1Update(SHA1_CTX* context, const void* p, unsigned int len); + static void sha1Final(unsigned char digsest[SHA1_DIGEST_SIZE], SHA1_CTX* context); + static void sha1Transform(unsigned int state[5], const unsigned char buffer[64]); + static void sha1Hmac(const unsigned char* key, int keyLen, const unsigned char* data, int dataLen, unsigned char out[SHA1_DIGEST_SIZE]); + + static int pbkdf2(const char* pass, int passLen, const unsigned char* salt, int saltLen, int iter, int keyLen, unsigned char* out); + static std::string hexConvert(unsigned char* src, int srcLen); +}; + +#endif //!__VOLUME_MANAGER_KEY_GENERATOR_H__ diff --git a/volume/key-manager.cpp b/volume/key-manager.cpp new file mode 100755 index 0000000..d143c31 --- /dev/null +++ b/volume/key-manager.cpp @@ -0,0 +1,92 @@ +/* + * 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 "key-manager.h" + + +#define addAliasPrefix(alias) \ + (ckmcIdSystem + ckmcIdSeperator + alias) + +namespace { + +const std::string ckmcIdSystem = ckmc_owner_id_system; +const std::string ckmcIdSeperator = ckmc_owner_id_separator; + +} //namespace + +bool KeyManager::isKeyExist(const std::string& keyName) +{ + int ret; + ckmc_raw_buffer_s* keyData = NULL; + std::string ckmAlias = addAliasPrefix(keyName); + + ret = ::ckmc_get_data(ckmAlias.c_str(), NULL, &keyData); + ::ckmc_buffer_free(keyData); + + return (ret != CKMC_ERROR_DB_ALIAS_UNKNOWN); +} + +void KeyManager::addKey(const std::string& keyName, const std::string& data) +{ + int ret; + const std::string ckmAlias = addAliasPrefix(keyName); + ckmc_raw_buffer_s keyData; + ckmc_policy_s keyPolicy; + + keyData.data = (unsigned char*)data.c_str(); + keyData.size = data.size(); + + keyPolicy.password = NULL; + keyPolicy.extractable = true; + + ret = ::ckmc_save_data(ckmAlias.c_str(), keyData, keyPolicy); + if (ret != 0) { + throw runtime::Exception("Failed to add key data"); + } +} + +std::string KeyManager::getKey(const std::string& keyName) +{ + int ret; + const std::string ckmAlias = addAliasPrefix(keyName); + ckmc_raw_buffer_s* keyData; + std::string result; + + ret = ::ckmc_get_data(ckmAlias.c_str(), NULL, &keyData); + if (ret != CKMC_ERROR_NONE) { + throw runtime::Exception("Failed to get key data"); + } + + result = std::string(reinterpret_cast(keyData->data), keyData->size); + + ::ckmc_buffer_free(keyData); + + return result; +} + +void KeyManager::removeKey(const std::string& keyName) +{ + const std::string ckmAlias = addAliasPrefix(keyName); + + if (::ckmc_remove_data(ckmAlias.c_str()) != 0) { + throw runtime::Exception("Failed to remove key data"); + } +} diff --git a/volume/key-manager.h b/volume/key-manager.h new file mode 100644 index 0000000..48bcdc8 --- /dev/null +++ b/volume/key-manager.h @@ -0,0 +1,35 @@ +/* + * 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 __KEY_MANAGER_H__ +#define __KEY_MANAGER_H__ + +class KeyManager { +public: + KeyManager() = delete; + KeyManager(const KeyManager&) = delete; + KeyManager(KeyManager&&) = delete; + + KeyManager& operator=(const KeyManager&) = delete; + KeyManager& operator=(KeyManager&&) = delete; + + static bool isKeyExist(const std::string& keyName); + static void addKey(const std::string& keyName, const std::string& data); + static std::string getKey(const std::string& keyName); + static void removeKey(const std::string& keyName); +}; + +#endif //!__KEY_MANAGER_H__*/ diff --git a/volume/main.cpp b/volume/main.cpp new file mode 100755 index 0000000..4de5260 --- /dev/null +++ b/volume/main.cpp @@ -0,0 +1,194 @@ +/* + * 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 + +#include +#include +#include +#include + +#include +#include +#include + +#include "ecryptfs.h" +#include "kernel-keyring.h" +#include "key-manager.h" +#include "key-generator.h" + +int generateKey(const std::string& keyName) +{ + if (KeyManager::isKeyExist(keyName)) { + ERROR("Key already registered"); + return -1; + } + + try { + std::string pass = KeyGenerator::generateKey(ECRYPTFS_MAX_KEY_SIZE); + std::string salt = KeyGenerator::generateKey(ECRYPTFS_MAX_SALT_SIZE); + std::string wrappedKey = KeyGenerator::wrapKey(pass, salt, ECRYPTFS_MAX_KEY_SIZE); + + KeyManager::addKey(keyName, wrappedKey); + } catch (runtime::Exception& e) { + ERROR(e.what()); + return -1; + } + + return 0; +} + +ecryptfs_payload* generateToken(char* key) +{ + struct ecryptfs_password* tokenKey; + + unsigned char keyBuffer[ECRYPTFS_MAX_KEY_SIZE+1]; + + ecryptfs_payload* authToken = (ecryptfs_payload *)::malloc(sizeof(ecryptfs_payload)); + if (authToken == NULL) { + return NULL; + } + + ::memset(authToken, 0, sizeof(ecryptfs_payload)); + ::strncpy((char*)keyBuffer, key, ECRYPTFS_MAX_KEY_SIZE); + keyBuffer[ECRYPTFS_MAX_KEY_SIZE] = '\0'; + + tokenKey = &authToken->token.password; + + authToken->version = ECRYPTFS_VERSION; + authToken->token_type = ECRYPTFS_PWD_PAYLOAD_TYPE; + tokenKey->session_key_encryption_key_bytes = ECRYPTFS_MAX_KEY_SIZE; + tokenKey->flags = ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET; + ::memcpy(tokenKey->session_key_encryption_key, keyBuffer, ECRYPTFS_MAX_KEY_SIZE); + ::memcpy(tokenKey->signature, keyBuffer, ECRYPTFS_MAX_SIG_HEX); + + return authToken; +} + +int mountEcryptfs(const std::string& src, const std::string& keyName) +{ + int rc; + char ecryptfsOpts[1024]; + ecryptfs_payload* authTok = NULL; + + std::string key; + try { + key = KeyManager::getKey(keyName); + } catch (runtime::Exception& e) { + ERROR(e.what()); + return -1; + } + + if (KernelKeyRing::link(KEY_SPEC_USER_KEYRING, KEY_SPEC_SESSION_KEYRING) != 0) { + ERROR("Failed to link key"); + return -1; + } + + if ((authTok = generateToken((char*)key.c_str())) == NULL) { + ERROR("Failed to generate Token"); + return -1; + } + + const char* signature = (const char*)authTok->token.password.signature; + rc = KernelKeyRing::search(KEY_SPEC_USER_KEYRING, + "user", + signature, + 0); + if (rc == -1 && errno != ENOKEY) { + ERROR("Failed to find key"); + return -1; + } + if (rc == -1) { + rc = KernelKeyRing::add("user", + signature, + (void*)authTok, + sizeof(ecryptfs_payload), + KEY_SPEC_USER_KEYRING); + if (rc == -1) { + ERROR("Failed to add key"); + return -1; + } + } + + ::snprintf(ecryptfsOpts, 1024, + "ecryptfs_passthrough," + "ecryptfs_cipher=aes," + "ecryptfs_key_bytes=%d," + "ecryptfs_sig=%s," + "smackfsroot=*,smackfsdef=*", + ECRYPTFS_MAX_KEY_SIZE, signature); + + rc = ::mount(src.c_str(), src.c_str(), "ecryptfs", MS_NODEV, ecryptfsOpts); + if (rc != 0) { + ERROR(runtime::GetSystemErrorMessage()); + return -1; + } + + return 0; +} + +int mountEcryptfsToAll() +{ + return 0; +} + +void usage(const std::string& prog) +{ + std::cout << "Usage: " << prog << std::endl + << "-a : Automount" << std::endl + << "-g name : Generate key for krate" << std::endl + << "-m name : Apply filesystem encrytion to krate" << std::endl; +} + +int main(int argc, char* argv[]) +{ + int opt, index, ret = -1; + struct option options[] = { + {"automount", no_argument, 0, 'a'}, + {"generate", required_argument, 0, 'g'}, + {"mount", required_argument, 0, 'm'}, + {0, 0, 0, 0} + }; + + while ((opt = getopt_long(argc, argv, "ag:m:", options, &index)) != -1) { + switch (opt) { + case 'a': + ret = mountEcryptfsToAll(); + break; + case 'g': + ret = generateKey(optarg); + break; + case 'm': + ret = mountEcryptfs("/home/" + std::string(optarg), optarg); + break; + default: + std::cerr << "unknown" << std::endl; + usage(argv[0]); + break; + } + } + + if (ret != 0) { + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} -- 2.7.4