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 {"shared", SECURITY_MANAGER_PATH_PUBLIC_RO},
42 {"shared/data", SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO},
43 {"shared/cache", SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO},
44 {"shared/trusted", SECURITY_MANAGER_PATH_TRUSTED_RW},
45 {"tep", SECURITY_MANAGER_PATH_RO},
46 {".image", SECURITY_MANAGER_PATH_RO},
47 {"tmp", SECURITY_MANAGER_PATH_RW},
48 {".mmc", SECURITY_MANAGER_PATH_RO}
51 const std::vector<std::pair<const char*,
52 app_install_path_type>> kSecurityPoliciesExternalOnly = {
53 {"bin", SECURITY_MANAGER_PATH_RO},
54 {"lib", SECURITY_MANAGER_PATH_RO},
55 {"res", SECURITY_MANAGER_PATH_RO},
56 {".mmc", SECURITY_MANAGER_PATH_RO}
59 const std::vector<std::pair<const char*, app_install_type>> kPathPolicies = {
60 {tzplatform_getenv(TZ_SYS_HOME), SM_APP_INSTALL_LOCAL},
61 {tzplatform_getenv(TZ_SYS_RW_APP), SM_APP_INSTALL_GLOBAL},
62 {tzplatform_getenv(TZ_SYS_RO_APP), SM_APP_INSTALL_PRELOADED},
63 {tzplatform_mkpath(TZ_SYS_ETC, "skel"), SM_APP_INSTALL_PRELOADED},
66 void SetErrorMessage(std::string* error_message, int error) {
67 std::string errnum = std::to_string(error);
68 *error_message = security_manager_strerror(static_cast<lib_retcode>(error));
69 *error_message += ":<" + errnum + ">";
72 class SecurityContextRequest {
74 SecurityContextRequest(): req_(nullptr), app_idx_(0) {
75 int error = security_manager_app_inst_req_new(&req_);
76 if (error != SECURITY_MANAGER_SUCCESS) {
78 << "Failed while calling security_manager_app_inst_req_new "
79 << "(error code: " << error << ")";
80 SetErrorMessage(&error_message_, error);
84 ~SecurityContextRequest() {
86 security_manager_app_inst_req_free(req_);
88 bool IsValid() const {
91 bool PrepareBasic(const std::string& pkg_id, uid_t uid,
92 const std::string& type) {
93 if (pkg_id.empty() || type.empty()) {
94 LOG(ERROR) << "Invalid parameter";
97 int error = security_manager_app_inst_req_set_pkg_id(req_, pkg_id.c_str());
98 if (error != SECURITY_MANAGER_SUCCESS) {
99 SetErrorMessage(&error_message_, error);
102 error = security_manager_app_inst_req_set_uid(req_, uid);
103 if (error != SECURITY_MANAGER_SUCCESS) {
104 SetErrorMessage(&error_message_, error);
108 pkg_type pkgtype = SM_PKG_TYPE_NONE;
110 pkgtype = SM_PKG_TYPE_CORE;
111 else if (type == "wgt")
112 pkgtype = SM_PKG_TYPE_WRT;
114 error = security_manager_app_inst_req_set_pkg_type(req_, pkgtype);
115 if (error != SECURITY_MANAGER_SUCCESS) {
116 SetErrorMessage(&error_message_, error);
122 bool PrepareAdditional(const std::string& author_id,
123 const std::string& api_version,
124 const boost::filesystem::path& path,
125 bool cross_app_rules) {
126 if (cross_app_rules) {
127 int error = security_manager_app_inst_req_set_hybrid(req_);
128 if (error != SECURITY_MANAGER_SUCCESS) {
129 SetErrorMessage(&error_message_, error);
133 if (!api_version.empty()) {
134 int error = security_manager_app_inst_req_set_target_version(req_,
135 api_version.c_str());
136 if (error != SECURITY_MANAGER_SUCCESS) {
137 SetErrorMessage(&error_message_, error);
141 if (!author_id.empty()) {
142 int error = security_manager_app_inst_req_set_author_id(req_,
144 if (error != SECURITY_MANAGER_SUCCESS) {
145 SetErrorMessage(&error_message_, error);
150 app_install_type type = SM_APP_INSTALL_NONE;
151 for (auto& policy : kPathPolicies) {
152 bf::path root = bf::path(policy.first);
153 if (ci::IsSubDir(path, root)) {
154 type = policy.second;
158 if (type == SM_APP_INSTALL_NONE) {
159 LOG(ERROR) << "Unexpected path: " << path;
163 LOG(INFO) << "install_type(" << type << ")";
164 int error = security_manager_app_inst_req_set_install_type(req_, type);
165 if (error != SECURITY_MANAGER_SUCCESS) {
166 SetErrorMessage(&error_message_, error);
173 bool PreparePrivilegeLevel(ci::PrivilegeLevel priv_level) {
174 pkg_privilege_level level = (pkg_privilege_level)priv_level;
175 int error = security_manager_app_inst_req_set_pkg_privilege_level(
177 if (error != SECURITY_MANAGER_SUCCESS) {
178 SetErrorMessage(&error_message_, error);
184 bool PrepareAppWithPrivileges(const std::string& app_id,
185 const std::vector<std::string>& privileges,
186 const AppDefinedPrivInfo& appdef_privileges,
187 const AppDefinedPrivInfo& provides_appdef_privileges) {
188 if (!PrepareApp(app_id))
190 return PrepareAppPrivileges(privileges, appdef_privileges,
191 provides_appdef_privileges);
194 bool PrepareAppPrivileges(const std::vector<std::string>& privileges,
195 const AppDefinedPrivInfo& appdef_privileges,
196 const AppDefinedPrivInfo& provides_appdef_privileges) {
197 for (auto& priv : privileges) {
198 int error = security_manager_app_inst_req_add_privilege(req_,
200 if (error != SECURITY_MANAGER_SUCCESS) {
201 SetErrorMessage(&error_message_, error);
205 for (auto& priv : appdef_privileges) {
206 int error = security_manager_app_inst_req_add_client_privilege(
207 req_, priv.first.c_str(), priv.second.c_str());
208 if (error != SECURITY_MANAGER_SUCCESS) {
209 SetErrorMessage(&error_message_, error);
213 // only one app can provide appdefined privileges
216 for (auto& priv : provides_appdef_privileges) {
217 auto privilege_type = !priv.second.empty() ?
218 SM_APP_DEFINED_PRIVILEGE_TYPE_LICENSED :
219 SM_APP_DEFINED_PRIVILEGE_TYPE_UNTRUSTED;
220 int error = security_manager_app_inst_req_add_app_defined_privilege(req_,
221 priv.first.c_str(), privilege_type, priv.second.c_str());
222 if (error != SECURITY_MANAGER_SUCCESS) {
223 SetErrorMessage(&error_message_, error);
230 bool PrepareApp(const std::string& app_id) {
231 if (app_id.empty()) {
232 LOG(ERROR) << "Appid is empty.";
235 // req_->apps.emplace_back();
237 int error = security_manager_app_inst_req_next(req_);
238 if (error != SECURITY_MANAGER_SUCCESS) {
239 SetErrorMessage(&error_message_, error);
243 // req_->apps.back().id = ...
244 int error = security_manager_app_inst_req_set_app_id(req_, app_id.c_str());
245 if (error != SECURITY_MANAGER_SUCCESS) {
246 SetErrorMessage(&error_message_, error);
254 int error = security_manager_app_update(req_);
255 if (error != SECURITY_MANAGER_SUCCESS) {
256 LOG(ERROR) << "Failed while calling security_manager_app_update failed "
257 << "(error code: " << error << ")";
258 SetErrorMessage(&error_message_, error);
265 int error = security_manager_app_uninstall(req_);
266 if (error != SECURITY_MANAGER_SUCCESS) {
267 LOG(ERROR) << "Failed while calling security_manager_app_uninstall "
268 << "failed (error code: " << error << ")";
269 SetErrorMessage(&error_message_, error);
275 const std::string& ErrorMessage() const {
276 return error_message_;
282 std::string error_message_;
285 class SecurityContextPathRequest {
287 SecurityContextPathRequest() {
288 int error = security_manager_path_req_new(&req_);
289 if (error != SECURITY_MANAGER_SUCCESS) {
291 << "Failed while calling security_manager_app_inst_req_new failed "
292 << "(error code: " << error << ")";
293 SetErrorMessage(&error_message_, error);
298 ~SecurityContextPathRequest() {
300 security_manager_path_req_free(req_);
307 bool Prepare(const std::string& pkg_id, uid_t uid) {
308 if (pkg_id.empty()) {
309 LOG(ERROR) << "Pkgid is empty. This value must be set";
312 int error = security_manager_path_req_set_pkg_id(req_, pkg_id.c_str());
313 if (error != SECURITY_MANAGER_SUCCESS) {
314 SetErrorMessage(&error_message_, error);
317 error = security_manager_path_req_set_uid(req_, uid);
318 if (error != SECURITY_MANAGER_SUCCESS) {
319 SetErrorMessage(&error_message_, error);
325 bool PreparePath(const std::string& pkg_type,
326 const boost::filesystem::path& path, bool is_readonly_pkg,
329 LOG(ERROR) << "Path is empty. This value must be set";
332 app_install_type type = SM_APP_INSTALL_NONE;
333 for (auto& policy : kPathPolicies) {
334 bf::path root = bf::path(policy.first);
335 if (ci::IsSubDir(path, root)) {
336 type = policy.second;
340 if (type == SM_APP_INSTALL_NONE) {
341 LOG(ERROR) << "Unexpected path: " << path;
344 // When registering skel dir on global installation mode
345 if (type == SM_APP_INSTALL_PRELOADED && !is_readonly_pkg)
346 type = SM_APP_INSTALL_GLOBAL;
348 int error = security_manager_path_req_set_install_type(req_, type);
349 if (error != SECURITY_MANAGER_SUCCESS) {
350 SetErrorMessage(&error_message_, error);
353 std::vector<std::pair<const char*, app_install_path_type>> policies;
355 policies = kSecurityPoliciesExternalOnly;
357 policies = kSecurityPolicies;
358 for (auto& policy : policies) {
359 bf::path subpath = path / policy.first;
361 // Now, this is for legacy migraton.
362 // do not try to access any file before changing label,
363 // this wil cause a exception from smack denial.
364 std::string subdir(policy.first);
365 if (pkg_type == "wgt" && (subdir == "bin" || subdir == "lib"))
368 if (!bf::exists(subpath))
370 if (bf::is_symlink(symlink_status(subpath)) &&
371 policy.second != SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO) {
372 LOG(DEBUG) << "Path " << subpath << " is a symlink."
373 << "Path will not be registered";
377 error = security_manager_path_req_add_path(req_, subpath.c_str(),
379 if (error != SECURITY_MANAGER_SUCCESS) {
380 SetErrorMessage(&error_message_, error);
388 int error = security_manager_paths_register(req_);
389 if (error != SECURITY_MANAGER_SUCCESS) {
390 LOG(ERROR) << "Failed while calling security_manager_app_install failed "
391 << "(error code: " << error << ")";
392 SetErrorMessage(&error_message_, error);
398 const std::string& ErrorMessage() const {
399 return error_message_;
404 std::string error_message_;
409 namespace common_installer {
411 void PrepareAppDefinedPrivilegeData(GList *privileges,
412 AppDefinedPrivInfo* tpk_priv_vec, AppDefinedPrivInfo* wgt_priv_vec) {
414 for (auto& priv : GListRange<appdefined_privilege_x*>(privileges)) {
415 if (strcmp(priv->type, kWebPrivilegeType) == 0)
416 wgt_priv_vec->emplace_back(std::make_pair(priv->value, priv->license ?
417 priv->license : std::string()));
419 tpk_priv_vec->emplace_back(std::make_pair(priv->value, priv->license ?
420 priv->license : std::string()));
424 bool RegisterSecurityContextForManifest(const ci::InstallerContext* context,
425 std::string* error_message) {
426 std::string pkg_id = context->pkgid.get();
427 std::string pkg_type = context->pkg_type.get();
428 bf::path path = context->GetPkgPath();
429 uid_t uid = context->uid.get();
430 const ci::CertificateInfo* cert_info = &(context->certificate_info.get());
431 manifest_x* manifest = context->manifest_data.get();
432 bool cross_app_rules = context->cross_app_rules.get();
434 // Although application framework hold list of privilege per package, there
435 // is situation where we need to filter privileges. This data model doesn't
436 // cover hybrid apps well where native privileges should be granted only to
437 // native app and web privileges should be granted only to web applications.
438 std::vector<std::string> tpk_priv_vec;
439 std::vector<std::string> wgt_priv_vec;
440 for (auto& priv : GListRange<privilege_x*>(manifest->privileges)) {
441 if (strcmp(priv->type, kWebPrivilegeType) == 0)
442 wgt_priv_vec.emplace_back(priv->value);
444 tpk_priv_vec.emplace_back(priv->value);
446 AppDefinedPrivInfo tpk_appdef_vec, wgt_appdef_vec;
447 AppDefinedPrivInfo tpk_provides_appdef_vec, wgt_provides_appdef_vec;
449 PrepareAppDefinedPrivilegeData(manifest->appdefined_privileges,
450 &tpk_appdef_vec, &wgt_appdef_vec);
451 PrepareAppDefinedPrivilegeData(manifest->provides_appdefined_privileges,
452 &tpk_provides_appdef_vec, &wgt_provides_appdef_vec);
454 SecurityContextRequest req;
455 if (!req.IsValid()) {
456 *error_message = req.ErrorMessage();
459 if (!req.PrepareBasic(pkg_id, uid, pkg_type)) {
460 *error_message = req.ErrorMessage();
463 if (!req.PrepareAdditional(cert_info->author_id.get(), manifest->api_version,
464 path, cross_app_rules)) {
465 *error_message = req.ErrorMessage();
469 if (!req.PreparePrivilegeLevel(context->privilege_level.get())) {
470 *error_message = req.ErrorMessage();
474 for (application_x* app : GListRange<application_x*>(manifest->application)) {
479 bool is_web_priv = strcmp(app->type, "webapp") == 0;
480 if (!req.PrepareAppWithPrivileges(app->appid,
481 is_web_priv ? wgt_priv_vec : tpk_priv_vec,
482 is_web_priv ? wgt_appdef_vec : tpk_appdef_vec,
483 is_web_priv ? wgt_provides_appdef_vec : tpk_provides_appdef_vec)) {
484 *error_message = req.ErrorMessage();
489 if (!manifest->application)
490 req.PrepareApp(pkg_id);
492 bool result = req.Install();
493 *error_message = req.ErrorMessage();
497 static bool UnregisterSecurityContext(const std::string& pkg_id,
498 const std::string& pkg_type, uid_t uid,
499 const std::vector<std::string>& appids, std::string* error_message) {
500 SecurityContextRequest req;
501 if (!req.IsValid()) {
502 *error_message = req.ErrorMessage();
505 if (!req.PrepareBasic(pkg_id, uid, pkg_type)) {
506 *error_message = req.ErrorMessage();
510 for (const auto& appid : appids) {
511 if (!req.PrepareApp(appid)) {
517 req.PrepareApp(pkg_id);
519 bool result = req.Uninstall();
520 *error_message = req.ErrorMessage();
524 bool UnregisterSecurityContextForManifest(const std::string& pkg_id,
525 const std::string& pkg_type, uid_t uid, manifest_x* manifest,
526 std::string* error_message) {
527 std::vector<std::string> appids;
528 for (application_x* app : GListRange<application_x*>(manifest->application)) {
532 appids.emplace_back(app->appid);
534 return UnregisterSecurityContext(pkg_id, pkg_type, uid,
535 appids, error_message);
538 bool UnregisterSecurityContextForPkgId(const std::string &pkg_id,
539 const std::string& pkg_type, uid_t uid,
540 std::string* error_message, bool ignore_data_absence) {
541 std::vector<std::string> appids;
542 ci::PkgQueryInterface pkg_query(pkg_id, uid);
543 if (!pkg_query.AppidsForPkgId(&appids))
544 return ignore_data_absence;
545 return UnregisterSecurityContext(pkg_id, pkg_type, uid,
546 appids, error_message);
549 bool RegisterSecurityContextForPath(const std::string &pkg_id,
550 const boost::filesystem::path& path, uid_t uid, bool is_readonly_pkg,
551 std::string* error_message) {
552 SecurityContextPathRequest req;
553 if (!req.IsValid()) {
554 *error_message = req.ErrorMessage();
557 if (!req.Prepare(pkg_id, uid)) {
558 *error_message = req.ErrorMessage();
561 if (!req.PreparePath({}, path, is_readonly_pkg, false)) {
562 *error_message = req.ErrorMessage();
565 bool result = req.Register();
566 *error_message = req.ErrorMessage();
570 bool RegisterSecurityContextForPathExternalOnly(const std::string &pkg_id,
571 const std::string &pkg_type, const boost::filesystem::path& path,
572 uid_t uid, std::string* error_message) {
573 SecurityContextPathRequest req;
574 if (!req.IsValid()) {
575 *error_message = req.ErrorMessage();
578 if (!req.Prepare(pkg_id, uid)) {
579 *error_message = req.ErrorMessage();
582 if (!req.PreparePath(pkg_type, path, false, true)) {
583 *error_message = req.ErrorMessage();
586 bool result = req.Register();
587 *error_message = req.ErrorMessage();
591 } // namespace common_installer