# Targets
SET(TARGET_LIBNAME_COMMON "app-installers")
SET(TARGET_PKGDIR_TOOL "pkgdir-tool")
+SET(TARGET_PKG_INITDB "pkg_initdb")
SET(TARGET_PKG_INSTALL_MANIFEST "pkg-install-manifest")
ADD_DEFINITIONS("-Wall")
</request>
<assign>
<filesystem path="/usr/bin/pkgdir-tool" exec_label="User" />
+ <filesystem path="/usr/bin/pkg_initdb" exec_label="User" />
<filesystem path="/usr/bin/pkg-install-manifest" exec_label="User" />
</assign>
</manifest>
%attr(6750,root,root) %{_bindir}/pkgdir-tool
%attr(6755,root,root) %{_sysconfdir}/gumd/useradd.d/20_pkgdir-tool-add.post
%{_bindir}/pkg-install-manifest
+%{_bindir}/pkg_initdb
%license LICENSE
%files devel
ADD_SUBDIRECTORY(common)
+ADD_SUBDIRECTORY(pkg_initdb)
ADD_SUBDIRECTORY(pkg_install_manifest)
ADD_SUBDIRECTORY(pkgdir_tool)
ADD_SUBDIRECTORY(unit_tests)
#include <pkgmgr-info.h>
#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
#include <tzplatform_config.h>
+
#include <string>
#include "common/request.h"
} else {
if (pkgmgr_->GetRequestType() == RequestType::ManifestDirectInstall ||
pkgmgr_->GetRequestType() == RequestType::ManifestDirectUpdate) {
- LOG(ERROR) << "Non-root user cannot request manifest direct mode.";
- return Status::OPERATION_NOT_ALLOWED;
+ if (context_->is_preload_request.get()) {
+ LOG(ERROR) << "Direct manifest installation/update that is run from "
+ "non-root user cannot be a preload request";
+ return Status::OPERATION_NOT_ALLOWED;
+ }
} else if (context_->is_preload_request.get()) {
LOG(ERROR) << "Non-root user cannot request preload request mode.";
return Status::OPERATION_NOT_ALLOWED;
for (auto& splash_screen : splashscreens_info.splashscreens()) {
splashscreen_x* splashscreen =
static_cast<splashscreen_x*>(calloc(1, sizeof(splashscreen_x)));
- if (context_->is_preload_request.get() == true)
+ if (context_->is_preload_request.get())
splashscreen->src = strdup(splash_screen.src().c_str());
else
splashscreen->src = strdup((context_->root_application_path.get()
#include "common/step/security/step_check_signature.h"
#include <boost/filesystem/operations.hpp>
-#include <boost/filesystem/path.hpp>
#include <glib.h>
#include <cassert>
return Step::Status::OK;
}
+boost::filesystem::path StepCheckSignature::GetSignatureRoot() const {
+ return context_->unpacked_dir_path.get();
+}
+
Step::Status StepCheckSignature::CheckSignatures(bool check_reference,
bool is_preload,
PrivilegeLevel* level) {
std::string error_message;
- if (!ValidateSignatures(context_->unpacked_dir_path.get(), level,
+ if (!ValidateSignatures(GetSignatureRoot(), level,
&context_->certificate_info.get(), check_reference,
is_preload, &error_message)) {
on_error(Status::CERT_ERROR, error_message);
PrivilegeLevel level = PrivilegeLevel::UNTRUSTED;
bool check_reference = true;
if (getuid() == 0 &&
- (context_->request_type.get()== ci::RequestType::ManifestDirectInstall ||
+ (context_->request_type.get() == ci::RequestType::ManifestDirectInstall ||
context_->request_type.get() == ci::RequestType::ManifestDirectUpdate))
check_reference = false;
bool is_preload = context_->is_preload_request.get();
#ifndef COMMON_STEP_SECURITY_STEP_CHECK_SIGNATURE_H_
#define COMMON_STEP_SECURITY_STEP_CHECK_SIGNATURE_H_
+#include <boost/filesystem/path.hpp>
+
#include <manifest_parser/utils/logging.h>
#include <string>
*/
Status precheck() override;
+ protected:
+ virtual boost::filesystem::path GetSignatureRoot() const;
+
private:
Status CheckSignatures(bool check_reference, bool is_preload,
PrivilegeLevel* level);
Subprocess::Subprocess(const std::string& program)
: program_(program),
pid_(0),
- started_(false) {
+ started_(false),
+ uid_(-1) {
}
bool Subprocess::RunWithArgs(const std::vector<std::string>& args) {
argv[i] = args[i - 1].c_str();
}
argv[args.size() + 1] = nullptr;
+ if (uid_ != -1)
+ setuid(uid_);
execvp(argv[0], const_cast<char* const*>(argv.get()));
LOG(ERROR) << "Failed to execv";
return false;
const std::vector<std::string>& args = std::vector<std::string>());
int Wait();
+ void set_uid(int uid) {
+ uid_ = uid;
+ }
+
private:
std::string program_;
int pid_;
bool started_;
+ int uid_;
};
} // namespace common_installer
--- /dev/null
+# Target - sources
+SET(SRCS
+ pkg_initdb.cc
+)
+
+# Target - definition
+ADD_EXECUTABLE(${TARGET_PKG_INITDB} ${SRCS})
+# Target - includes
+TARGET_INCLUDE_DIRECTORIES(${TARGET_PKG_INITDB} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../")
+# Target - deps
+APPLY_PKG_CONFIG(${TARGET_PKG_INITDB} PUBLIC
+ PKGMGR_DEPS
+ Boost
+)
+# Target - in-package deps
+TARGET_LINK_LIBRARIES(${TARGET_PKG_INITDB} PUBLIC ${TARGET_LIBNAME_COMMON})
+# Install
+INSTALL(TARGETS ${TARGET_PKG_INITDB} DESTINATION ${BINDIR})
--- /dev/null
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache-2.0 license that can be
+// found in the LICENSE file.
+
+#include <boost/filesystem/operations.hpp>
+#include <boost/filesystem/path.hpp>
+#include <boost/program_options.hpp>
+#include <boost/system/error_code.hpp>
+#include <pkgmgr_parser.h>
+#include <pkgmgr_parser_db.h>
+#include <pkgmgr-info.h>
+#include <sys/types.h>
+#include <tzplatform_config.h>
+
+#include <string>
+#include <iostream>
+
+#include "common/utils/subprocess.h"
+
+namespace bf = boost::filesystem;
+namespace bs = boost::system;
+namespace bpo = boost::program_options;
+namespace ci = common_installer;
+
+namespace {
+
+const uid_t kUserRoot = 0;
+const uid_t kGlobalUser = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
+const char kPkgInstallManifestPath[] = "/usr/bin/pkg-install-manifest";
+
+bool IsGlobal(uid_t uid) {
+ return uid == kUserRoot || uid == kGlobalUser;
+}
+
+void InitdbLoadDirectory(uid_t uid, const bf::path& directory, bool preload) {
+ std::cerr << "Loading manifest files from " << directory << std::endl;
+ for (bf::directory_iterator iter(directory); iter != bf::directory_iterator();
+ ++iter) {
+ if (!bf::is_regular_file(iter->path()))
+ continue;
+ std::cerr << "Running for: " << iter->path() << std::endl;
+ ci::Subprocess pkg_install_manifest(kPkgInstallManifestPath);
+ pkg_install_manifest.set_uid(uid);
+ if (preload)
+ pkg_install_manifest.Run("-x", iter->path().c_str(), "--preload");
+ else
+ pkg_install_manifest.Run("-x", iter->path().c_str());
+ pkg_install_manifest.Wait();
+ }
+}
+
+void RemoveOldDatabases(uid_t uid) {
+ if (!IsGlobal(uid))
+ tzplatform_set_user(uid);
+
+ bs::error_code error;
+ bf::path info_db_path(tzplatform_mkpath(
+ IsGlobal(uid) ? TZ_SYS_DB : TZ_USER_DB, ".pkgmgr_parser.db"));
+ bf::path info_db_journal_path(tzplatform_mkpath(
+ IsGlobal(uid) ? TZ_SYS_DB : TZ_USER_DB, ".pkgmgr_parser.db-journal"));
+ bf::path cert_db_path(tzplatform_mkpath(
+ IsGlobal(uid) ? TZ_SYS_DB : TZ_USER_DB, ".pkgmgr_cert.db"));
+ bf::path cert_db_journal_path(tzplatform_mkpath(
+ IsGlobal(uid) ? TZ_SYS_DB : TZ_USER_DB, ".pkgmgr_cert.db-journal"));
+
+ bf::remove(info_db_path, error);
+ if (error)
+ std::cerr << info_db_path << " is not removed" << std::endl;
+ bf::remove(info_db_journal_path, error);
+ if (error)
+ std::cerr << info_db_journal_path << " is not removed" << std::endl;
+ bf::remove(cert_db_path, error);
+ if (error)
+ std::cerr << cert_db_path << " is not removed" << std::endl;
+ bf::remove(cert_db_journal_path, error);
+ if (error)
+ std::cerr << cert_db_journal_path << " is not removed" << std::endl;
+
+ tzplatform_reset_user();
+}
+
+} // namespace
+
+int main(int argc, char *argv[]) {
+ if (getuid() != kUserRoot) {
+ std::cerr << "This binary should be run as root user" << std::endl;
+ return -1;
+ }
+
+ bpo::options_description options("Allowed options");
+ options.add_options()
+ ("uid,u", bpo::value<int>()->default_value(kUserRoot), "user id")
+ ("help,h", "display this help message");
+ bpo::variables_map opt_map;
+ try {
+ bpo::store(bpo::parse_command_line(argc, argv, options), opt_map);
+ if (opt_map.count("help")) {
+ std::cerr << options << std::endl;
+ return -1;
+ }
+ bpo::notify(opt_map);
+ } catch (const bpo::error& error) {
+ std::cerr << error.what() << std::endl;
+ return -1;
+ }
+ uid_t uid = opt_map["uid"].as<int>();
+
+ RemoveOldDatabases(uid);
+
+ int ret = pkgmgr_parser_create_and_initialize_db(uid);
+ if (ret < 0) {
+ std::cerr << "Cannot create db" << std::endl;
+ return -1;
+ }
+
+ if (IsGlobal(uid)) {
+ // RO location
+ bf::path ro_dir(tzplatform_getenv(TZ_SYS_RO_PACKAGES));
+ InitdbLoadDirectory(uid, ro_dir, true);
+
+ // RW location
+ bf::path rw_dir(tzplatform_getenv(TZ_SYS_RW_PACKAGES));
+ InitdbLoadDirectory(uid, rw_dir, false);
+ } else {
+ // Specified user location
+ tzplatform_set_user(uid);
+ bf::path dir(tzplatform_getenv(TZ_USER_PACKAGES));
+ InitdbLoadDirectory(uid, dir, false);
+ tzplatform_reset_user();
+ }
+
+ return ret;
+}
int InstallManifestOffline(const std::string& pkgid,
const std::string& type,
- const std::string& preload) {
+ bool preload) {
bf::path backend_path(kBackendDirectoryPath);
backend_path /= type;
ci::Subprocess backend(backend_path.string());
- if (preload == "true")
+ if (preload)
backend.Run("-y", pkgid.c_str(), "--preload");
else
backend.Run("-y", pkgid.c_str());
bpo::options_description options("Allowed options");
options.add_options()
("xml-path,x", bpo::value<std::string>()->required(), "xml package path")
+ ("preload", "run backend with preload flag")
("help,h", "display this help message");
bpo::variables_map opt_map;
try {
return -1;
}
+ bool preload = opt_map.count("preload") != 0;
bf::path manifest_path(opt_map["xml-path"].as<std::string>());
tpk::parse::TPKConfigParser parser;
if (!parser.ParseManifest(manifest_path)) {
if (type.empty())
type = "tpk";
- return InstallManifestOffline(package_info->package(), type,
- package_info->preload());
+ return InstallManifestOffline(package_info->package(), type, preload);
}