1 // Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
2 // Use of this source code is governed by a apache 2.0 license that can be
3 // found in the LICENSE file.
5 #include "common/security_registration.h"
7 #include <boost/filesystem/operations.hpp>
8 #include <boost/format.hpp>
11 #include <sys/types.h>
12 #include <manifest_parser/utils/logging.h>
13 #include <security-manager.h>
14 #include <tzplatform_config.h>
21 #include "common/utils/pkgmgr_query.h"
22 #include "common/privileges.h"
23 #include "common/utils/file_util.h"
24 #include "common/utils/glist_range.h"
26 namespace bf = boost::filesystem;
27 namespace ci = common_installer;
31 using AppDefinedPrivInfo = std::vector<std::pair<std::string, std::string>>;
33 const std::vector<std::pair<const char*,
34 app_install_path_type>> kSecurityPolicies = {
35 {"/", SECURITY_MANAGER_PATH_PUBLIC_RO},
36 {"bin", SECURITY_MANAGER_PATH_RO},
37 {"data", SECURITY_MANAGER_PATH_RW},
38 {"cache", SECURITY_MANAGER_PATH_RW},
39 {"lib", SECURITY_MANAGER_PATH_RO},
40 {"res", SECURITY_MANAGER_PATH_RO},
41 {"res/global", SECURITY_MANAGER_PATH_PUBLIC_RO},
42 {"res/allowed", SECURITY_MANAGER_PATH_PUBLIC_RO},
43 {"shared", SECURITY_MANAGER_PATH_PUBLIC_RO},
44 {"shared/data", SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO},
45 {"shared/cache", SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO},
46 {"shared/trusted", SECURITY_MANAGER_PATH_TRUSTED_RW},
47 {"tep", SECURITY_MANAGER_PATH_RO},
48 {".image", SECURITY_MANAGER_PATH_RO},
49 {"tmp", SECURITY_MANAGER_PATH_RW},
50 {".mmc", SECURITY_MANAGER_PATH_RO}
53 const std::vector<std::pair<const char*,
54 app_install_path_type>> kSecurityPoliciesExternalOnly = {
55 {"bin", SECURITY_MANAGER_PATH_RO},
56 {"lib", SECURITY_MANAGER_PATH_RO},
57 {"res", SECURITY_MANAGER_PATH_RO},
58 {".mmc", SECURITY_MANAGER_PATH_RO}
61 const std::vector<std::pair<const char*, app_install_type>> kPathPolicies = {
62 {tzplatform_getenv(TZ_SYS_HOME), SM_APP_INSTALL_LOCAL},
63 {tzplatform_getenv(TZ_SYS_RW_APP), SM_APP_INSTALL_GLOBAL},
64 {tzplatform_getenv(TZ_SYS_RO_APP), SM_APP_INSTALL_PRELOADED},
65 {tzplatform_mkpath(TZ_SYS_ETC, "skel"), SM_APP_INSTALL_PRELOADED},
68 void SetErrorMessage(std::string* error_message, int error) {
69 std::string errnum = std::to_string(error);
70 *error_message = security_manager_strerror(static_cast<lib_retcode>(error));
71 *error_message += ":<" + errnum + ">";
74 class SecurityContextRequest {
76 SecurityContextRequest(): req_(nullptr), app_idx_(0) {
77 int error = security_manager_app_inst_req_new(&req_);
78 if (error != SECURITY_MANAGER_SUCCESS) {
80 << "Failed while calling security_manager_app_inst_req_new "
81 << "(error code: " << error << ")";
82 SetErrorMessage(&error_message_, error);
86 ~SecurityContextRequest() {
88 security_manager_app_inst_req_free(req_);
90 bool IsValid() const {
93 bool PrepareBasic(const std::string& pkg_id, uid_t uid,
94 const std::string& type) {
95 if (pkg_id.empty() || type.empty()) {
96 LOG(ERROR) << "Invalid parameter";
99 int error = security_manager_app_inst_req_set_pkg_id(req_, pkg_id.c_str());
100 if (error != SECURITY_MANAGER_SUCCESS) {
101 SetErrorMessage(&error_message_, error);
104 error = security_manager_app_inst_req_set_uid(req_, uid);
105 if (error != SECURITY_MANAGER_SUCCESS) {
106 SetErrorMessage(&error_message_, error);
110 pkg_type pkgtype = SM_PKG_TYPE_NONE;
112 pkgtype = SM_PKG_TYPE_CORE;
113 else if (type == "wgt")
114 pkgtype = SM_PKG_TYPE_WRT;
116 error = security_manager_app_inst_req_set_pkg_type(req_, pkgtype);
117 if (error != SECURITY_MANAGER_SUCCESS) {
118 SetErrorMessage(&error_message_, error);
124 bool PrepareAdditional(const std::string& author_id,
125 const std::string& api_version,
126 const boost::filesystem::path& path,
127 bool cross_app_rules) {
128 if (cross_app_rules) {
129 int error = security_manager_app_inst_req_set_hybrid(req_);
130 if (error != SECURITY_MANAGER_SUCCESS) {
131 SetErrorMessage(&error_message_, error);
135 if (!api_version.empty()) {
136 int error = security_manager_app_inst_req_set_target_version(req_,
137 api_version.c_str());
138 if (error != SECURITY_MANAGER_SUCCESS) {
139 SetErrorMessage(&error_message_, error);
143 if (!author_id.empty()) {
144 int error = security_manager_app_inst_req_set_author_id(req_,
146 if (error != SECURITY_MANAGER_SUCCESS) {
147 SetErrorMessage(&error_message_, error);
152 app_install_type type = SM_APP_INSTALL_NONE;
153 for (auto& policy : kPathPolicies) {
154 bf::path root = bf::path(policy.first);
155 if (ci::IsSubDir(path, root)) {
156 type = policy.second;
160 if (type == SM_APP_INSTALL_NONE) {
161 LOG(ERROR) << "Unexpected path: " << path;
165 LOG(INFO) << "install_type(" << type << ")";
166 int error = security_manager_app_inst_req_set_install_type(req_, type);
167 if (error != SECURITY_MANAGER_SUCCESS) {
168 SetErrorMessage(&error_message_, error);
175 bool PreparePrivilegeLevel(ci::PrivilegeLevel priv_level) {
176 pkg_privilege_level level = (pkg_privilege_level)priv_level;
177 int error = security_manager_app_inst_req_set_pkg_privilege_level(
179 if (error != SECURITY_MANAGER_SUCCESS) {
180 SetErrorMessage(&error_message_, error);
186 bool PrepareAppWithPrivileges(const std::string& app_id,
187 const std::vector<std::string>& privileges,
188 const AppDefinedPrivInfo& appdef_privileges,
189 const AppDefinedPrivInfo& provides_appdef_privileges) {
190 if (!PrepareApp(app_id))
192 return PrepareAppPrivileges(privileges, appdef_privileges,
193 provides_appdef_privileges);
196 bool PrepareAppPrivileges(const std::vector<std::string>& privileges,
197 const AppDefinedPrivInfo& appdef_privileges,
198 const AppDefinedPrivInfo& provides_appdef_privileges) {
199 for (auto& priv : privileges) {
200 int error = security_manager_app_inst_req_add_privilege(req_,
202 if (error != SECURITY_MANAGER_SUCCESS) {
203 SetErrorMessage(&error_message_, error);
207 for (auto& priv : appdef_privileges) {
208 int error = security_manager_app_inst_req_add_client_privilege(
209 req_, priv.first.c_str(), priv.second.c_str());
210 if (error != SECURITY_MANAGER_SUCCESS) {
211 SetErrorMessage(&error_message_, error);
215 // only one app can provide appdefined privileges
218 for (auto& priv : provides_appdef_privileges) {
219 auto privilege_type = !priv.second.empty() ?
220 SM_APP_DEFINED_PRIVILEGE_TYPE_LICENSED :
221 SM_APP_DEFINED_PRIVILEGE_TYPE_UNTRUSTED;
222 int error = security_manager_app_inst_req_add_app_defined_privilege(req_,
223 priv.first.c_str(), privilege_type, priv.second.c_str());
224 if (error != SECURITY_MANAGER_SUCCESS) {
225 SetErrorMessage(&error_message_, error);
232 bool PrepareApp(const std::string& app_id) {
233 if (app_id.empty()) {
234 LOG(ERROR) << "Appid is empty.";
237 // req_->apps.emplace_back();
239 int error = security_manager_app_inst_req_next(req_);
240 if (error != SECURITY_MANAGER_SUCCESS) {
241 SetErrorMessage(&error_message_, error);
245 // req_->apps.back().id = ...
246 int error = security_manager_app_inst_req_set_app_id(req_, app_id.c_str());
247 if (error != SECURITY_MANAGER_SUCCESS) {
248 SetErrorMessage(&error_message_, error);
256 int error = security_manager_app_update(req_);
257 if (error != SECURITY_MANAGER_SUCCESS) {
258 LOG(ERROR) << "Failed while calling security_manager_app_update failed "
259 << "(error code: " << error << ")";
260 SetErrorMessage(&error_message_, error);
267 int error = security_manager_app_uninstall(req_);
268 if (error != SECURITY_MANAGER_SUCCESS) {
269 LOG(ERROR) << "Failed while calling security_manager_app_uninstall "
270 << "failed (error code: " << error << ")";
271 SetErrorMessage(&error_message_, error);
277 const std::string& ErrorMessage() const {
278 return error_message_;
284 std::string error_message_;
287 class SecurityContextPathRequest {
289 SecurityContextPathRequest() {
290 int error = security_manager_path_req_new(&req_);
291 if (error != SECURITY_MANAGER_SUCCESS) {
293 << "Failed while calling security_manager_path_req_new failed "
294 << "(error code: " << error << ")";
295 SetErrorMessage(&error_message_, error);
300 ~SecurityContextPathRequest() {
302 security_manager_path_req_free(req_);
309 bool Prepare(const std::string& pkg_id, uid_t uid) {
310 if (pkg_id.empty()) {
311 LOG(ERROR) << "Pkgid is empty. This value must be set";
314 int error = security_manager_path_req_set_pkg_id(req_, pkg_id.c_str());
315 if (error != SECURITY_MANAGER_SUCCESS) {
316 SetErrorMessage(&error_message_, error);
319 error = security_manager_path_req_set_uid(req_, uid);
320 if (error != SECURITY_MANAGER_SUCCESS) {
321 SetErrorMessage(&error_message_, error);
327 bool PreparePath(const std::string& pkg_type,
328 const boost::filesystem::path& path, bool is_readonly_pkg,
331 LOG(ERROR) << "Path is empty. This value must be set";
334 app_install_type type = SM_APP_INSTALL_NONE;
335 for (auto& policy : kPathPolicies) {
336 bf::path root = bf::path(policy.first);
337 if (ci::IsSubDir(path, root)) {
338 type = policy.second;
342 if (type == SM_APP_INSTALL_NONE) {
343 LOG(ERROR) << "Unexpected path: " << path;
346 // When registering skel dir on global installation mode
347 if (type == SM_APP_INSTALL_PRELOADED && !is_readonly_pkg)
348 type = SM_APP_INSTALL_GLOBAL;
350 int error = security_manager_path_req_set_install_type(req_, type);
351 if (error != SECURITY_MANAGER_SUCCESS) {
352 SetErrorMessage(&error_message_, error);
355 std::vector<std::pair<const char*, app_install_path_type>> policies;
357 policies = kSecurityPoliciesExternalOnly;
359 policies = kSecurityPolicies;
360 for (auto& policy : policies) {
361 bf::path subpath = path / policy.first;
363 // Now, this is for legacy migraton.
364 // do not try to access any file before changing label,
365 // this wil cause a exception from smack denial.
366 std::string subdir(policy.first);
367 if (pkg_type == "wgt" && (subdir == "bin" || subdir == "lib"))
370 if (!bf::exists(subpath))
372 if (bf::is_symlink(symlink_status(subpath)) &&
373 policy.second != SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO) {
374 LOG(DEBUG) << "Path " << subpath << " is a symlink."
375 << "Path will not be registered";
379 error = security_manager_path_req_add_path(req_, subpath.c_str(),
381 if (error != SECURITY_MANAGER_SUCCESS) {
382 SetErrorMessage(&error_message_, error);
390 int error = security_manager_paths_register(req_);
391 if (error != SECURITY_MANAGER_SUCCESS) {
392 LOG(ERROR) << "Failed while calling security_manager_paths_register "
393 << "failed (error code: " << error << ")";
394 SetErrorMessage(&error_message_, error);
400 const std::string& ErrorMessage() const {
401 return error_message_;
406 std::string error_message_;
411 namespace common_installer {
413 void PrepareAppDefinedPrivilegeData(GList *privileges,
414 AppDefinedPrivInfo* tpk_priv_vec, AppDefinedPrivInfo* wgt_priv_vec) {
416 for (auto& priv : GListRange<appdefined_privilege_x*>(privileges)) {
417 if (strcmp(priv->type, kWebPrivilegeType) == 0)
418 wgt_priv_vec->emplace_back(std::make_pair(priv->value, priv->license ?
419 priv->license : std::string()));
421 tpk_priv_vec->emplace_back(std::make_pair(priv->value, priv->license ?
422 priv->license : std::string()));
426 bool RegisterSecurityContextForManifest(const ci::InstallerContext* context,
427 std::string* error_message) {
428 std::string pkg_id = context->pkgid.get();
429 std::string pkg_type = context->pkg_type.get();
430 bf::path path = context->GetPkgPath();
431 uid_t uid = context->uid.get();
432 const ci::CertificateInfo* cert_info = &(context->certificate_info.get());
433 manifest_x* manifest = context->manifest_data.get();
434 bool cross_app_rules = context->cross_app_rules.get();
436 // Although application framework hold list of privilege per package, there
437 // is situation where we need to filter privileges. This data model doesn't
438 // cover hybrid apps well where native privileges should be granted only to
439 // native app and web privileges should be granted only to web applications.
440 std::vector<std::string> tpk_priv_vec;
441 std::vector<std::string> wgt_priv_vec;
442 for (auto& priv : GListRange<privilege_x*>(manifest->privileges)) {
443 if (strcmp(priv->type, kWebPrivilegeType) == 0)
444 wgt_priv_vec.emplace_back(priv->value);
446 tpk_priv_vec.emplace_back(priv->value);
448 AppDefinedPrivInfo tpk_appdef_vec, wgt_appdef_vec;
449 AppDefinedPrivInfo tpk_provides_appdef_vec, wgt_provides_appdef_vec;
451 PrepareAppDefinedPrivilegeData(manifest->appdefined_privileges,
452 &tpk_appdef_vec, &wgt_appdef_vec);
453 PrepareAppDefinedPrivilegeData(manifest->provides_appdefined_privileges,
454 &tpk_provides_appdef_vec, &wgt_provides_appdef_vec);
456 SecurityContextRequest req;
457 if (!req.IsValid()) {
458 *error_message = req.ErrorMessage();
461 if (!req.PrepareBasic(pkg_id, uid, pkg_type)) {
462 *error_message = req.ErrorMessage();
465 if (!req.PrepareAdditional(cert_info->author_id.get(), manifest->api_version,
466 path, cross_app_rules)) {
467 *error_message = req.ErrorMessage();
471 if (!req.PreparePrivilegeLevel(context->privilege_level.get())) {
472 *error_message = req.ErrorMessage();
476 for (application_x* app : GListRange<application_x*>(manifest->application)) {
481 bool is_web_priv = strcmp(app->type, "webapp") == 0;
482 if (!req.PrepareAppWithPrivileges(app->appid,
483 is_web_priv ? wgt_priv_vec : tpk_priv_vec,
484 is_web_priv ? wgt_appdef_vec : tpk_appdef_vec,
485 is_web_priv ? wgt_provides_appdef_vec : tpk_provides_appdef_vec)) {
486 *error_message = req.ErrorMessage();
491 if (!manifest->application)
492 req.PrepareApp(pkg_id);
494 bool result = req.Install();
495 *error_message = req.ErrorMessage();
499 static bool UnregisterSecurityContext(const std::string& pkg_id,
500 const std::string& pkg_type, uid_t uid,
501 const std::vector<std::string>& appids, std::string* error_message) {
502 SecurityContextRequest req;
503 if (!req.IsValid()) {
504 *error_message = req.ErrorMessage();
507 if (!req.PrepareBasic(pkg_id, uid, pkg_type)) {
508 *error_message = req.ErrorMessage();
512 for (const auto& appid : appids) {
513 if (!req.PrepareApp(appid)) {
519 req.PrepareApp(pkg_id);
521 bool result = req.Uninstall();
522 *error_message = req.ErrorMessage();
526 bool UnregisterSecurityContextForManifest(const std::string& pkg_id,
527 const std::string& pkg_type, uid_t uid, manifest_x* manifest,
528 std::string* error_message) {
529 std::vector<std::string> appids;
530 for (application_x* app : GListRange<application_x*>(manifest->application)) {
534 appids.emplace_back(app->appid);
536 return UnregisterSecurityContext(pkg_id, pkg_type, uid,
537 appids, error_message);
540 bool UnregisterSecurityContextForPkgId(const std::string &pkg_id,
541 const std::string& pkg_type, uid_t uid,
542 std::string* error_message, bool ignore_data_absence) {
543 std::vector<std::string> appids;
544 ci::PkgQueryInterface pkg_query(pkg_id, uid);
545 if (!pkg_query.AppidsForPkgId(&appids))
546 return ignore_data_absence;
547 return UnregisterSecurityContext(pkg_id, pkg_type, uid,
548 appids, error_message);
551 bool RegisterSecurityContextForPath(const std::string &pkg_id,
552 const boost::filesystem::path& path, uid_t uid, bool is_readonly_pkg,
553 std::string* error_message) {
554 SecurityContextPathRequest req;
555 if (!req.IsValid()) {
556 *error_message = req.ErrorMessage();
559 if (!req.Prepare(pkg_id, uid)) {
560 *error_message = req.ErrorMessage();
563 if (!req.PreparePath({}, path, is_readonly_pkg, false)) {
564 *error_message = req.ErrorMessage();
567 bool result = req.Register();
568 *error_message = req.ErrorMessage();
572 bool RegisterSecurityContextForPathExternalOnly(const std::string &pkg_id,
573 const std::string &pkg_type, const boost::filesystem::path& path,
574 uid_t uid, std::string* error_message) {
575 SecurityContextPathRequest req;
576 if (!req.IsValid()) {
577 *error_message = req.ErrorMessage();
580 if (!req.Prepare(pkg_id, uid)) {
581 *error_message = req.ErrorMessage();
584 if (!req.PreparePath(pkg_type, path, false, true)) {
585 *error_message = req.ErrorMessage();
588 bool result = req.Register();
589 *error_message = req.ErrorMessage();
593 bool HasOwnerRwOtherRoPaths(const boost::filesystem::path& path) {
594 for (auto& policy : kSecurityPolicies) {
595 if (policy.second != SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO)
598 bf::path subpath = path / policy.first;
599 LOG(ERROR) << "subpath : " << subpath;
600 if (bf::exists(subpath))
607 } // namespace common_installer