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"
9 #include <manifest_parser/utils/logging.h>
10 #include <security-manager.h>
11 #include <tzplatform_config.h>
18 #include "common/utils/pkgmgr_query.h"
19 #include "common/privileges.h"
20 #include "common/utils/file_util.h"
21 #include "common/utils/glist_range.h"
23 namespace fs = std::filesystem;
24 namespace ci = common_installer;
28 using AppDefinedPrivInfo = std::vector<std::pair<std::string, std::string>>;
30 const std::vector<std::pair<const char*,
31 app_install_path_type>> kSecurityPolicies = {
32 {".", SECURITY_MANAGER_PATH_PUBLIC_RO},
33 {"bin", SECURITY_MANAGER_PATH_RO},
34 {"data", SECURITY_MANAGER_PATH_RW},
35 {"cache", SECURITY_MANAGER_PATH_RW},
36 {"lib", SECURITY_MANAGER_PATH_RO},
37 {"res", SECURITY_MANAGER_PATH_RO},
38 {"res/global", SECURITY_MANAGER_PATH_PUBLIC_RO},
39 {"res/allowed", SECURITY_MANAGER_PATH_PUBLIC_RO},
40 {"shared", SECURITY_MANAGER_PATH_PUBLIC_RO},
41 {"shared/data", SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO},
42 {"shared/cache", SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO},
43 {"shared/trusted", SECURITY_MANAGER_PATH_TRUSTED_RW},
44 {"tep", SECURITY_MANAGER_PATH_RO},
45 {".image", SECURITY_MANAGER_PATH_RO},
46 {"tmp", SECURITY_MANAGER_PATH_RW},
47 {".mmc", SECURITY_MANAGER_PATH_RO}
50 const std::vector<std::pair<const char*,
51 app_install_path_type>> kSecurityPoliciesExternalOnly = {
52 {"bin", SECURITY_MANAGER_PATH_RO},
53 {"lib", SECURITY_MANAGER_PATH_RO},
54 {"res", SECURITY_MANAGER_PATH_RO},
55 {".mmc", SECURITY_MANAGER_PATH_RO}
58 const std::vector<std::pair<const char*, app_install_type>> kPathPolicies = {
59 {tzplatform_getenv(TZ_SYS_HOME), SM_APP_INSTALL_LOCAL},
60 {tzplatform_getenv(TZ_SYS_RW_APP), SM_APP_INSTALL_GLOBAL},
61 {tzplatform_getenv(TZ_SYS_RO_APP), SM_APP_INSTALL_PRELOADED},
62 {tzplatform_mkpath(TZ_SYS_ETC, "skel"), SM_APP_INSTALL_PRELOADED},
65 void SetErrorMessage(std::string* error_message, int error) {
66 std::string errnum = std::to_string(error);
67 *error_message = security_manager_strerror(static_cast<lib_retcode>(error));
68 *error_message += ":<" + errnum + ">";
71 class SecurityContextRequest {
73 SecurityContextRequest(): req_(nullptr), app_idx_(0) {
74 int error = security_manager_app_inst_req_new(&req_);
75 if (error != SECURITY_MANAGER_SUCCESS) {
77 << "Failed while calling security_manager_app_inst_req_new "
78 << "(error code: " << error << ")";
79 SetErrorMessage(&error_message_, error);
83 ~SecurityContextRequest() {
85 security_manager_app_inst_req_free(req_);
87 bool IsValid() const {
90 bool PrepareBasic(const std::string& pkg_id, uid_t uid,
91 const std::string& type) {
92 if (pkg_id.empty() || type.empty()) {
93 LOG(ERROR) << "Invalid parameter";
96 int error = security_manager_app_inst_req_set_pkg_id(req_, pkg_id.c_str());
97 if (error != SECURITY_MANAGER_SUCCESS) {
98 SetErrorMessage(&error_message_, error);
101 error = security_manager_app_inst_req_set_uid(req_, uid);
102 if (error != SECURITY_MANAGER_SUCCESS) {
103 SetErrorMessage(&error_message_, error);
107 pkg_type pkgtype = SM_PKG_TYPE_NONE;
109 pkgtype = SM_PKG_TYPE_CORE;
110 else if (type == "wgt")
111 pkgtype = SM_PKG_TYPE_WRT;
113 error = security_manager_app_inst_req_set_pkg_type(req_, pkgtype);
114 if (error != SECURITY_MANAGER_SUCCESS) {
115 SetErrorMessage(&error_message_, error);
121 bool PrepareAdditional(const std::string& author_id,
122 const std::string& api_version,
123 const std::filesystem::path& path,
124 bool cross_app_rules) {
125 if (cross_app_rules) {
126 int error = security_manager_app_inst_req_set_hybrid(req_);
127 if (error != SECURITY_MANAGER_SUCCESS) {
128 SetErrorMessage(&error_message_, error);
132 if (!api_version.empty()) {
133 int error = security_manager_app_inst_req_set_target_version(req_,
134 api_version.c_str());
135 if (error != SECURITY_MANAGER_SUCCESS) {
136 SetErrorMessage(&error_message_, error);
140 if (!author_id.empty()) {
141 int error = security_manager_app_inst_req_set_author_id(req_,
143 if (error != SECURITY_MANAGER_SUCCESS) {
144 SetErrorMessage(&error_message_, error);
149 app_install_type type = SM_APP_INSTALL_NONE;
150 for (auto& policy : kPathPolicies) {
151 fs::path root = fs::path(policy.first);
152 if (ci::IsSubDir(path, root)) {
153 type = policy.second;
157 if (type == SM_APP_INSTALL_NONE) {
158 LOG(ERROR) << "Unexpected path: " << path;
162 LOG(INFO) << "install_type(" << type << ")";
163 int error = security_manager_app_inst_req_set_install_type(req_, type);
164 if (error != SECURITY_MANAGER_SUCCESS) {
165 SetErrorMessage(&error_message_, error);
172 bool PreparePrivilegeLevel(ci::PrivilegeLevel priv_level) {
173 pkg_privilege_level level = (pkg_privilege_level)priv_level;
174 int error = security_manager_app_inst_req_set_pkg_privilege_level(
176 if (error != SECURITY_MANAGER_SUCCESS) {
177 SetErrorMessage(&error_message_, error);
183 bool PrepareAppWithPrivileges(const std::string& app_id,
184 const std::vector<std::string>& privileges,
185 const AppDefinedPrivInfo& appdef_privileges,
186 const AppDefinedPrivInfo& provides_appdef_privileges) {
187 if (!PrepareApp(app_id))
189 return PrepareAppPrivileges(privileges, appdef_privileges,
190 provides_appdef_privileges);
193 bool PrepareAppPrivileges(const std::vector<std::string>& privileges,
194 const AppDefinedPrivInfo& appdef_privileges,
195 const AppDefinedPrivInfo& provides_appdef_privileges) {
196 for (auto& priv : privileges) {
197 int error = security_manager_app_inst_req_add_privilege(req_,
199 if (error != SECURITY_MANAGER_SUCCESS) {
200 SetErrorMessage(&error_message_, error);
204 for (auto& priv : appdef_privileges) {
205 int error = security_manager_app_inst_req_add_client_privilege(
206 req_, priv.first.c_str(), priv.second.c_str());
207 if (error != SECURITY_MANAGER_SUCCESS) {
208 SetErrorMessage(&error_message_, error);
212 // only one app can provide appdefined privileges
215 for (auto& priv : provides_appdef_privileges) {
216 auto privilege_type = !priv.second.empty() ?
217 SM_APP_DEFINED_PRIVILEGE_TYPE_LICENSED :
218 SM_APP_DEFINED_PRIVILEGE_TYPE_UNTRUSTED;
219 int error = security_manager_app_inst_req_add_app_defined_privilege(req_,
220 priv.first.c_str(), privilege_type, priv.second.c_str());
221 if (error != SECURITY_MANAGER_SUCCESS) {
222 SetErrorMessage(&error_message_, error);
229 bool PrepareApp(const std::string& app_id) {
230 if (app_id.empty()) {
231 LOG(ERROR) << "Appid is empty.";
234 // req_->apps.emplace_back();
236 int error = security_manager_app_inst_req_next(req_);
237 if (error != SECURITY_MANAGER_SUCCESS) {
238 SetErrorMessage(&error_message_, error);
242 // req_->apps.back().id = ...
243 int error = security_manager_app_inst_req_set_app_id(req_, app_id.c_str());
244 if (error != SECURITY_MANAGER_SUCCESS) {
245 SetErrorMessage(&error_message_, error);
253 int error = security_manager_app_update(req_);
254 if (error != SECURITY_MANAGER_SUCCESS) {
255 LOG(ERROR) << "Failed while calling security_manager_app_update failed "
256 << "(error code: " << error << ")";
257 SetErrorMessage(&error_message_, error);
264 int error = security_manager_app_uninstall(req_);
265 if (error != SECURITY_MANAGER_SUCCESS) {
266 LOG(ERROR) << "Failed while calling security_manager_app_uninstall "
267 << "failed (error code: " << error << ")";
268 SetErrorMessage(&error_message_, error);
274 const std::string& ErrorMessage() const {
275 return error_message_;
281 std::string error_message_;
284 class SecurityContextPathRequest {
286 SecurityContextPathRequest() {
287 int error = security_manager_path_req_new(&req_);
288 if (error != SECURITY_MANAGER_SUCCESS) {
290 << "Failed while calling security_manager_path_req_new failed "
291 << "(error code: " << error << ")";
292 SetErrorMessage(&error_message_, error);
297 ~SecurityContextPathRequest() {
299 security_manager_path_req_free(req_);
306 bool Prepare(const std::string& pkg_id, uid_t uid) {
307 if (pkg_id.empty()) {
308 LOG(ERROR) << "Pkgid is empty. This value must be set";
311 int error = security_manager_path_req_set_pkg_id(req_, pkg_id.c_str());
312 if (error != SECURITY_MANAGER_SUCCESS) {
313 SetErrorMessage(&error_message_, error);
316 error = security_manager_path_req_set_uid(req_, uid);
317 if (error != SECURITY_MANAGER_SUCCESS) {
318 SetErrorMessage(&error_message_, error);
324 bool PreparePath(const std::string& pkg_type,
325 const std::filesystem::path& path, bool is_readonly_pkg,
328 LOG(ERROR) << "Path is empty. This value must be set";
331 app_install_type type = SM_APP_INSTALL_NONE;
332 for (auto& policy : kPathPolicies) {
333 fs::path root = fs::path(policy.first);
334 if (ci::IsSubDir(path, root)) {
335 type = policy.second;
339 if (type == SM_APP_INSTALL_NONE) {
340 LOG(ERROR) << "Unexpected path: " << path;
343 // When registering skel dir on global installation mode
344 if (type == SM_APP_INSTALL_PRELOADED && !is_readonly_pkg)
345 type = SM_APP_INSTALL_GLOBAL;
347 int error = security_manager_path_req_set_install_type(req_, type);
348 if (error != SECURITY_MANAGER_SUCCESS) {
349 SetErrorMessage(&error_message_, error);
352 std::vector<std::pair<const char*, app_install_path_type>> policies;
354 policies = kSecurityPoliciesExternalOnly;
356 policies = kSecurityPolicies;
357 for (auto& policy : policies) {
358 fs::path subpath = path / policy.first;
360 // Now, this is for legacy migraton.
361 // do not try to access any file before changing label,
362 // this wil cause a exception from smack denial.
363 std::string subdir(policy.first);
364 if (pkg_type == "wgt" && (subdir == "bin" || subdir == "lib"))
367 if (!fs::exists(subpath))
369 if (fs::is_symlink(symlink_status(subpath)) &&
370 policy.second != SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO) {
371 LOG(DEBUG) << "Path " << subpath << " is a symlink."
372 << "Path will not be registered";
376 error = security_manager_path_req_add_path(req_, subpath.c_str(),
378 if (error != SECURITY_MANAGER_SUCCESS) {
379 SetErrorMessage(&error_message_, error);
383 // this is for lib rpk installation. set public RO for contents only.
384 if (pkg_type == "rpk" && std::string(policy.first) == "lib") {
385 for (fs::directory_iterator iter(subpath);
386 iter != fs::directory_iterator(); ++iter) {
387 error = security_manager_path_req_add_path(req_,
388 iter->path().string().c_str(), SECURITY_MANAGER_PATH_PUBLIC_RO);
389 if (error!= SECURITY_MANAGER_SUCCESS) {
390 SetErrorMessage(&error_message_, error);
400 int error = security_manager_paths_register(req_);
401 if (error != SECURITY_MANAGER_SUCCESS) {
402 LOG(ERROR) << "Failed while calling security_manager_paths_register "
403 << "failed (error code: " << error << ")";
404 SetErrorMessage(&error_message_, error);
410 const std::string& ErrorMessage() const {
411 return error_message_;
416 std::string error_message_;
421 namespace common_installer {
423 void PrepareAppDefinedPrivilegeData(GList *privileges,
424 AppDefinedPrivInfo* tpk_priv_vec, AppDefinedPrivInfo* wgt_priv_vec) {
426 for (auto& priv : GListRange<appdefined_privilege_x*>(privileges)) {
427 if (strcmp(priv->type, kWebPrivilegeType) == 0)
428 wgt_priv_vec->emplace_back(std::make_pair(priv->value, priv->license ?
429 priv->license : std::string()));
431 tpk_priv_vec->emplace_back(std::make_pair(priv->value, priv->license ?
432 priv->license : std::string()));
436 bool RegisterSecurityContextForManifest(const ci::InstallerContext* context,
437 std::string* error_message) {
438 std::string pkg_id = context->pkgid.get();
439 std::string pkg_type = context->pkg_type.get();
440 fs::path path = context->GetPkgPath();
441 uid_t uid = context->uid.get();
442 const ci::CertificateInfo* cert_info = &(context->certificate_info.get());
443 manifest_x* manifest = context->manifest_data.get();
444 bool cross_app_rules = context->cross_app_rules.get();
446 // Although application framework hold list of privilege per package, there
447 // is situation where we need to filter privileges. This data model doesn't
448 // cover hybrid apps well where native privileges should be granted only to
449 // native app and web privileges should be granted only to web applications.
450 std::vector<std::string> tpk_priv_vec;
451 std::vector<std::string> wgt_priv_vec;
452 for (auto& priv : GListRange<privilege_x*>(manifest->privileges)) {
453 if (strcmp(priv->type, kWebPrivilegeType) == 0)
454 wgt_priv_vec.emplace_back(priv->value);
456 tpk_priv_vec.emplace_back(priv->value);
458 AppDefinedPrivInfo tpk_appdef_vec, wgt_appdef_vec;
459 AppDefinedPrivInfo tpk_provides_appdef_vec, wgt_provides_appdef_vec;
461 PrepareAppDefinedPrivilegeData(manifest->appdefined_privileges,
462 &tpk_appdef_vec, &wgt_appdef_vec);
463 PrepareAppDefinedPrivilegeData(manifest->provides_appdefined_privileges,
464 &tpk_provides_appdef_vec, &wgt_provides_appdef_vec);
466 SecurityContextRequest req;
467 if (!req.IsValid()) {
468 *error_message = req.ErrorMessage();
471 if (!req.PrepareBasic(pkg_id, uid, pkg_type)) {
472 *error_message = req.ErrorMessage();
475 if (!req.PrepareAdditional(cert_info->author_id.get(), manifest->api_version,
476 path, cross_app_rules)) {
477 *error_message = req.ErrorMessage();
481 if (!req.PreparePrivilegeLevel(context->privilege_level.get())) {
482 *error_message = req.ErrorMessage();
486 for (application_x* app : GListRange<application_x*>(manifest->application)) {
491 bool is_web_priv = strcmp(app->type, "webapp") == 0;
492 if (!req.PrepareAppWithPrivileges(app->appid,
493 is_web_priv ? wgt_priv_vec : tpk_priv_vec,
494 is_web_priv ? wgt_appdef_vec : tpk_appdef_vec,
495 is_web_priv ? wgt_provides_appdef_vec : tpk_provides_appdef_vec)) {
496 *error_message = req.ErrorMessage();
501 if (!manifest->application)
502 req.PrepareApp(pkg_id);
504 bool result = req.Install();
505 *error_message = req.ErrorMessage();
509 static bool UnregisterSecurityContext(const std::string& pkg_id,
510 const std::string& pkg_type, uid_t uid,
511 const std::vector<std::string>& appids, std::string* error_message) {
512 SecurityContextRequest req;
513 if (!req.IsValid()) {
514 *error_message = req.ErrorMessage();
517 if (!req.PrepareBasic(pkg_id, uid, pkg_type)) {
518 *error_message = req.ErrorMessage();
522 for (const auto& appid : appids) {
523 if (!req.PrepareApp(appid)) {
529 req.PrepareApp(pkg_id);
531 bool result = req.Uninstall();
532 *error_message = req.ErrorMessage();
536 bool UnregisterSecurityContextForManifest(const std::string& pkg_id,
537 const std::string& pkg_type, uid_t uid, manifest_x* manifest,
538 std::string* error_message) {
539 std::vector<std::string> appids;
540 for (application_x* app : GListRange<application_x*>(manifest->application)) {
544 appids.emplace_back(app->appid);
546 return UnregisterSecurityContext(pkg_id, pkg_type, uid,
547 appids, error_message);
550 bool UnregisterSecurityContextForPkgId(const std::string &pkg_id,
551 const std::string& pkg_type, uid_t uid,
552 std::string* error_message, bool ignore_data_absence) {
553 std::vector<std::string> appids;
554 ci::PkgQueryInterface pkg_query(pkg_id, uid);
555 if (!pkg_query.AppidsForPkgId(&appids))
556 return ignore_data_absence;
557 return UnregisterSecurityContext(pkg_id, pkg_type, uid,
558 appids, error_message);
561 bool RegisterSecurityContextForPath(const std::string &pkg_id,
562 const std::string& pkg_type, const std::filesystem::path& path,
563 uid_t uid, bool is_readonly_pkg, std::string* error_message) {
564 SecurityContextPathRequest req;
565 if (!req.IsValid()) {
566 *error_message = req.ErrorMessage();
569 if (!req.Prepare(pkg_id, uid)) {
570 *error_message = req.ErrorMessage();
573 if (!req.PreparePath(pkg_type, path, is_readonly_pkg, false)) {
574 *error_message = req.ErrorMessage();
577 bool result = req.Register();
578 *error_message = req.ErrorMessage();
582 bool RegisterSecurityContextForPathExternalOnly(const std::string &pkg_id,
583 const std::string &pkg_type, const std::filesystem::path& path,
584 uid_t uid, std::string* error_message) {
585 SecurityContextPathRequest req;
586 if (!req.IsValid()) {
587 *error_message = req.ErrorMessage();
590 if (!req.Prepare(pkg_id, uid)) {
591 *error_message = req.ErrorMessage();
594 if (!req.PreparePath(pkg_type, path, false, true)) {
595 *error_message = req.ErrorMessage();
598 bool result = req.Register();
599 *error_message = req.ErrorMessage();
603 bool HasOwnerRwOtherRoPaths(const std::filesystem::path& path) {
604 for (auto& policy : kSecurityPolicies) {
605 if (policy.second != SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO)
608 fs::path subpath = path / policy.first;
609 LOG(ERROR) << "subpath : " << subpath;
610 if (fs::exists(subpath))
617 } // namespace common_installer