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>
20 #include "common/pkgmgr_query.h"
21 #include "common/privileges.h"
22 #include "common/utils/file_util.h"
23 #include "common/utils/glist_range.h"
25 namespace bf = boost::filesystem;
26 namespace ci = common_installer;
30 using AppDefinedPrivInfo = std::vector<std::pair<std::string, std::string>>;
32 const std::vector<std::pair<const char*,
33 app_install_path_type>> kSecurityPolicies = {
34 {"/", SECURITY_MANAGER_PATH_PUBLIC_RO},
35 {"bin", SECURITY_MANAGER_PATH_RO},
36 {"data", SECURITY_MANAGER_PATH_RW},
37 {"cache", SECURITY_MANAGER_PATH_RW},
38 {"lib", SECURITY_MANAGER_PATH_RO},
39 {"res", SECURITY_MANAGER_PATH_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 bool PrepareRequest(const std::string& app_id, const std::string& pkg_id,
66 const std::string& author_id, const std::string& api_version,
67 const boost::filesystem::path& path,
68 uid_t uid, const std::vector<std::string>& privileges,
69 const AppDefinedPrivInfo& appdef_privileges,
70 const AppDefinedPrivInfo& provides_appdef_privileges,
71 app_inst_req* req, bool cross_app_rules, std::string* error_message) {
72 if (app_id.empty() || pkg_id.empty()) {
73 LOG(ERROR) << "Appid or pkgid is empty. Both values must be set";
77 int error = security_manager_app_inst_req_set_app_id(req,
79 if (error != SECURITY_MANAGER_SUCCESS) {
80 std::string errnum = std::to_string(error);
81 *error_message = security_manager_strerror(static_cast<lib_retcode>(error));
82 *error_message += ":<" + errnum + ">";
86 error = security_manager_app_inst_req_set_pkg_id(req,
88 if (error != SECURITY_MANAGER_SUCCESS) {
89 std::string errnum = std::to_string(error);
90 *error_message = security_manager_strerror(static_cast<lib_retcode>(error));
91 *error_message += ":<" + errnum + ">";
95 error = security_manager_app_inst_req_set_uid(req, uid);
96 if (error != SECURITY_MANAGER_SUCCESS) {
97 std::string errnum = std::to_string(error);
98 *error_message = security_manager_strerror(static_cast<lib_retcode>(error));
99 *error_message += ":<" + errnum + ">";
103 if (cross_app_rules) {
104 error = security_manager_app_inst_req_set_hybrid(req);
105 if (error != SECURITY_MANAGER_SUCCESS) {
106 std::string errnum = std::to_string(error);
108 security_manager_strerror(static_cast<lib_retcode>(error));
109 *error_message += ":<" + errnum + ">";
114 if (!api_version.empty()) {
115 error = security_manager_app_inst_req_set_target_version(req,
116 api_version.c_str());
117 if (error != SECURITY_MANAGER_SUCCESS) {
118 std::string errnum = std::to_string(error);
120 security_manager_strerror(static_cast<lib_retcode>(error));
121 *error_message += ":<" + errnum + ">";
126 if (!author_id.empty()) {
127 error = security_manager_app_inst_req_set_author_id(req, author_id.c_str());
128 if (error != SECURITY_MANAGER_SUCCESS) {
129 std::string errnum = std::to_string(error);
131 security_manager_strerror(static_cast<lib_retcode>(error));
132 *error_message += ":<" + errnum + ">";
138 app_install_type type = SM_APP_INSTALL_NONE;
139 for (auto& policy : kPathPolicies) {
140 bf::path root = bf::path(policy.first);
141 if (ci::IsSubDir(path, root)) {
142 type = policy.second;
146 if (type == SM_APP_INSTALL_NONE) {
147 LOG(ERROR) << "Unexpected path: " << path;
151 LOG(INFO) << "install_type(" << type << ")";
152 error = security_manager_app_inst_req_set_install_type(req, type);
153 if (error != SECURITY_MANAGER_SUCCESS) {
154 std::string errnum = std::to_string(error);
156 security_manager_strerror(static_cast<lib_retcode>(error));
157 *error_message += ":<" + errnum + ">";
162 for (auto& priv : privileges) {
163 security_manager_app_inst_req_add_client_privilege(
164 req, priv.c_str(), nullptr);
166 for (auto& priv : appdef_privileges) {
167 error = security_manager_app_inst_req_add_client_privilege(
168 req, priv.first.c_str(), priv.second.c_str());
169 if (error != SECURITY_MANAGER_SUCCESS) {
170 std::string errnum = std::to_string(error);
172 security_manager_strerror(static_cast<lib_retcode>(error));
173 *error_message += ":<" + errnum + ">";
177 for (auto& priv : provides_appdef_privileges) {
178 error = security_manager_app_inst_req_add_app_defined_privilege(
179 req, priv.first.c_str(),
180 !priv.second.empty() ? SM_APP_DEFINED_PRIVILEGE_TYPE_LICENSED :
181 SM_APP_DEFINED_PRIVILEGE_TYPE_UNTRUSTED, priv.second.c_str());
182 if (error != SECURITY_MANAGER_SUCCESS) {
183 std::string errnum = std::to_string(error);
185 security_manager_strerror(static_cast<lib_retcode>(error));
186 *error_message += ":<" + errnum + ">";
193 bool PreparePathRequest(path_req* req, const std::string& pkg_id,
194 const std::string& pkg_type, const boost::filesystem::path& path,
195 uid_t uid, bool is_readonly_pkg, bool is_extonly,
196 std::string* error_message) {
197 if (pkg_id.empty() || path.empty()) {
198 LOG(ERROR) << "Pkgid or path is empty. Both values must be set";
202 int error = security_manager_path_req_set_pkg_id(req, pkg_id.c_str());
203 if (error != SECURITY_MANAGER_SUCCESS) {
204 std::string errnum = std::to_string(error);
205 *error_message = security_manager_strerror(static_cast<lib_retcode>(error));
206 *error_message += ":<" + errnum + ">";
210 error = security_manager_path_req_set_uid(req, uid);
211 if (error != SECURITY_MANAGER_SUCCESS) {
212 std::string errnum = std::to_string(error);
213 *error_message = security_manager_strerror(static_cast<lib_retcode>(error));
214 *error_message += ":<" + errnum + ">";
218 app_install_type type = SM_APP_INSTALL_NONE;
219 for (auto& policy : kPathPolicies) {
220 bf::path root = bf::path(policy.first);
221 if (ci::IsSubDir(path, root)) {
222 type = policy.second;
226 if (type == SM_APP_INSTALL_NONE) {
227 LOG(ERROR) << "Unexpected path: " << path;
230 // When registering skel dir on global installation mode
231 if (type == SM_APP_INSTALL_PRELOADED && !is_readonly_pkg)
232 type = SM_APP_INSTALL_GLOBAL;
234 error = security_manager_path_req_set_install_type(req, type);
235 if (error != SECURITY_MANAGER_SUCCESS) {
236 std::string errnum = std::to_string(error);
238 security_manager_strerror(static_cast<lib_retcode>(error));
239 *error_message += ":<" + errnum + ">";
243 std::vector<std::pair<const char*, app_install_path_type>> policies;
245 policies = kSecurityPoliciesExternalOnly;
247 policies = kSecurityPolicies;
248 for (auto& policy : policies) {
249 bf::path subpath = path / policy.first;
251 // Now, this is for legacy migraton.
252 // do not try to access any file before changing label,
253 // this wil cause a exception from smack denial.
254 std::string subdir(policy.first);
255 if (pkg_type == "wgt" && (subdir == "bin" || subdir == "lib"))
258 if (!bf::exists(subpath))
260 if (bf::is_symlink(symlink_status(subpath))) {
261 LOG(DEBUG) << "Path " << subpath << " is a symlink."
262 << "Path will not be registered";
266 error = security_manager_path_req_add_path(req, subpath.c_str(),
268 if (error != SECURITY_MANAGER_SUCCESS) {
269 std::string errnum = std::to_string(error);
271 security_manager_strerror(static_cast<lib_retcode>(error));
272 *error_message += ":<" + errnum + ">";
282 namespace common_installer {
284 void PrepareAppDefinedPrivilegeData(GList *privileges,
285 AppDefinedPrivInfo* tpk_priv_vec, AppDefinedPrivInfo* wgt_priv_vec) {
287 for (auto& priv : GListRange<appdefined_privilege_x*>(privileges)) {
288 if (strcmp(priv->type, kWebPrivilegeType) == 0)
289 wgt_priv_vec->emplace_back(std::make_pair(priv->value, priv->license ?
290 priv->license : std::string()));
292 tpk_priv_vec->emplace_back(std::make_pair(priv->value, priv->license ?
293 priv->license : std::string()));
297 bool RegisterSecurityContextForManifest(
298 const std::string& pkg_id, const boost::filesystem::path& path, uid_t uid,
299 common_installer::CertificateInfo* cert_info, manifest_x* manifest,
300 bool cross_app_rules, std::string* error_message) {
301 // Although application framework hold list of privilege per package, there
302 // is situation where we need to filter privileges. This data model doesn't
303 // cover hybrid apps well where native privileges should be granted only to
304 // native app and web privileges should be granted only to web applications.
306 int error = security_manager_app_inst_req_new(&req);
307 if (error != SECURITY_MANAGER_SUCCESS) {
309 << "Failed while calling security_manager_app_inst_req_new failed "
310 << "(error code: " << error << ")";
311 std::string errnum = boost::str(boost::format("%d") % error);
312 *error_message = security_manager_strerror(static_cast<lib_retcode>(error));
313 *error_message += ":<" + errnum + ">";
317 std::vector<std::string> tpk_priv_vec;
318 std::vector<std::string> wgt_priv_vec;
319 for (auto& priv : GListRange<privilege_x*>(manifest->privileges)) {
320 if (strcmp(priv->type, kWebPrivilegeType) == 0)
321 wgt_priv_vec.emplace_back(priv->value);
323 tpk_priv_vec.emplace_back(priv->value);
325 AppDefinedPrivInfo tpk_appdef_vec, wgt_appdef_vec;
326 AppDefinedPrivInfo tpk_provides_appdef_vec, wgt_provides_appdef_vec;
328 PrepareAppDefinedPrivilegeData(manifest->appdefined_privileges,
329 &tpk_appdef_vec, &wgt_appdef_vec);
330 PrepareAppDefinedPrivilegeData(manifest->provides_appdefined_privileges,
331 &tpk_provides_appdef_vec, &wgt_provides_appdef_vec);
333 GListRange<application_x*> list(manifest->application);
335 for (GListRange<application_x*>::Iterator iter = list.begin();
336 iter != list.end(); ++iter) {
337 application_x* app = *iter;
339 security_manager_app_inst_req_free(req);
343 bool is_web_priv = strcmp(app->type, "webapp") == 0;
344 if (!PrepareRequest(app->appid, pkg_id, cert_info->author_id.get(),
345 app->api_version, path, uid,
346 is_web_priv ? wgt_priv_vec : tpk_priv_vec,
347 is_web_priv ? wgt_appdef_vec : tpk_appdef_vec,
348 is_web_priv ? wgt_provides_appdef_vec : tpk_provides_appdef_vec,
349 req, cross_app_rules, error_message)) {
350 LOG(ERROR) << "Failed while preparing security_manager_app_inst_req";
351 security_manager_app_inst_req_free(req);
355 if (list_index != list.Size() &&
356 security_manager_app_inst_req_next(req) != SECURITY_MANAGER_SUCCESS) {
357 LOG(ERROR) << "Failed to call security_manager_app_inst_req_next";
358 security_manager_app_inst_req_free(req);
363 error = security_manager_app_install(req);
364 if (error != SECURITY_MANAGER_SUCCESS) {
365 LOG(ERROR) << "Failed while calling security_manager_app_install failed "
366 << "(error code: " << error << ")";
367 std::string errnum = boost::str(boost::format("%d") % error);
368 *error_message = security_manager_strerror(static_cast<lib_retcode>(error));
369 *error_message += ":<" + errnum + ">";
370 security_manager_app_inst_req_free(req);
374 security_manager_app_inst_req_free(req);
378 bool UnregisterSecurityContextForManifest(const std::string& pkg_id,
379 uid_t uid, manifest_x* manifest, std::string* error_message) {
382 int error = security_manager_app_inst_req_new(&req);
383 if (error != SECURITY_MANAGER_SUCCESS) {
384 LOG(ERROR) << "Failed while calling security_manager_app_inst_req_new "
385 << "(error code: " << error << ")";
386 std::string errnum = std::to_string(error);
387 *error_message = security_manager_strerror(static_cast<lib_retcode>(error));
388 *error_message += ":<" + errnum + ">";
392 GListRange<application_x*> list(manifest->application);
394 for (GListRange<application_x*>::Iterator iter = list.begin();
395 iter != list.end(); ++iter) {
396 application_x* app = *iter;
398 security_manager_app_inst_req_free(req);
403 if (!PrepareRequest(app->appid, pkg_id, std::string(), std::string(), bf::path(),
404 uid, {}, {}, {}, req, false, error_message)) {
405 LOG(ERROR) << "Failed while preparing security_manager_app_inst_req";
406 security_manager_app_inst_req_free(req);
410 if (list_index != list.Size() &&
411 security_manager_app_inst_req_next(req) != SECURITY_MANAGER_SUCCESS) {
412 LOG(ERROR) << "Failed to call security_manager_app_inst_req_next";
413 security_manager_app_inst_req_free(req);
417 error = security_manager_app_uninstall(req);
418 if (error != SECURITY_MANAGER_SUCCESS) {
419 LOG(ERROR) << "Failed while calling security_manager_app_uninstall failed "
420 << "(error code: " << error << ")";
421 std::string errnum = std::to_string(error);
422 *error_message = security_manager_strerror(static_cast<lib_retcode>(error));
423 *error_message += ":<" + errnum + ">";
424 security_manager_app_inst_req_free(req);
428 security_manager_app_inst_req_free(req);
432 bool UnregisterSecurityContextForPkgId(const std::string &pkg_id,
433 uid_t uid, std::string* error_message, bool ignore_data_absence) {
434 std::vector<std::string> appids;
435 ci::PkgQueryInterface pkg_query(pkg_id, uid);
436 if (!pkg_query.AppidsForPkgId(&appids))
437 return ignore_data_absence;
441 int error = security_manager_app_inst_req_new(&req);
442 if (error != SECURITY_MANAGER_SUCCESS) {
443 LOG(ERROR) << "Failed while calling security_manager_app_inst_req_new "
444 << "(error code: " << error << ")";
445 std::string errnum = std::to_string(error);
446 *error_message = security_manager_strerror(static_cast<lib_retcode>(error));
447 *error_message += ":<" + errnum + ">";
451 for (auto& appid : appids) {
452 if (!PrepareRequest(appid, pkg_id, std::string(), std::string(), bf::path(),
453 uid, {}, {}, {}, req, false, error_message)) {
454 LOG(ERROR) << "Failed while preparing security_manager_app_inst_req";
455 security_manager_app_inst_req_free(req);
459 if (appid.compare(appids.at(appids.size())) == 0 &&
460 security_manager_app_inst_req_next(req) != SECURITY_MANAGER_SUCCESS) {
461 LOG(ERROR) << "Failed to call security_manager_app_inst_req_next";
462 security_manager_app_inst_req_free(req);
466 error = security_manager_app_uninstall(req);
467 if (error != SECURITY_MANAGER_SUCCESS) {
468 LOG(ERROR) << "Failed while calling security_manager_app_uninstall failed "
469 << "(error code: " << error << ")";
470 std::string errnum = std::to_string(error);
471 *error_message = security_manager_strerror(static_cast<lib_retcode>(error));
472 *error_message += ":<" + errnum + ">";
473 security_manager_app_inst_req_free(req);
477 security_manager_app_inst_req_free(req);
481 bool RegisterSecurityContextForPath(const std::string &pkg_id,
482 const boost::filesystem::path& path, uid_t uid, bool is_readonly_pkg,
483 std::string* error_message) {
485 int error = security_manager_path_req_new(&req);
486 if (error != SECURITY_MANAGER_SUCCESS) {
488 << "Failed while calling security_manager_path_req_new failed "
489 << "(error code: " << error << ")";
490 std::string errnum = std::to_string(error);
491 *error_message = security_manager_strerror(static_cast<lib_retcode>(error));
492 *error_message += ":<" + errnum + ">";
496 if (!PreparePathRequest(req, pkg_id, {}, path, uid, is_readonly_pkg, false,
498 LOG(ERROR) << "Failed while preparing security_manager_path_req";
499 security_manager_path_req_free(req);
503 error = security_manager_paths_register(req);
504 if (error != SECURITY_MANAGER_SUCCESS) {
505 LOG(ERROR) << "Failed while calling security_manager_paths_register failed "
506 << "(error code: " << error << ")";
507 std::string errnum = std::to_string(error);
508 *error_message = security_manager_strerror(static_cast<lib_retcode>(error));
509 *error_message += ":<" + errnum + ">";
510 security_manager_path_req_free(req);
514 security_manager_path_req_free(req);
519 bool RegisterSecurityContextForPathExternalOnly(const std::string &pkg_id,
520 const std::string &pkg_type, const boost::filesystem::path& path,
521 uid_t uid, std::string* error_message) {
523 int error = security_manager_path_req_new(&req);
524 if (error != SECURITY_MANAGER_SUCCESS) {
526 << "Failed while calling security_manager_path_req_new failed "
527 << "(error code: " << error << ")";
528 std::string errnum = std::to_string(error);
529 *error_message = security_manager_strerror(static_cast<lib_retcode>(error));
530 *error_message += ":<" + errnum + ">";
534 if (!PreparePathRequest(req, pkg_id, pkg_type, path, uid, false, true,
536 LOG(ERROR) << "Failed while preparing security_manager_path_req";
537 security_manager_path_req_free(req);
541 error = security_manager_paths_register(req);
542 if (error != SECURITY_MANAGER_SUCCESS) {
543 LOG(ERROR) << "Failed while calling security_manager_paths_register failed "
544 << "(error code: " << error << ")";
545 std::string errnum = std::to_string(error);
546 *error_message = security_manager_strerror(static_cast<lib_retcode>(error));
547 *error_message += ":<" + errnum + ">";
548 security_manager_path_req_free(req);
552 security_manager_path_req_free(req);
557 } // namespace common_installer