Revert "Fix smack labeling for lib rpk"
[platform/core/appfw/app-installers.git] / src / common / security_registration.cc
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.
4
5 #include "common/security_registration.h"
6
7 #include <unistd.h>
8 #include <sys/types.h>
9 #include <manifest_parser/utils/logging.h>
10 #include <security-manager.h>
11 #include <tzplatform_config.h>
12
13 #include <utility>
14 #include <vector>
15 #include <algorithm>
16 #include <functional>
17
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"
22
23 namespace fs = std::filesystem;
24 namespace ci = common_installer;
25
26 namespace {
27
28 using AppDefinedPrivInfo = std::vector<std::pair<std::string, std::string>>;
29
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}
48 };
49
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}
56 };
57
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},
63 };
64
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 + ">";
69 }
70
71 class SecurityContextRequest {
72  public:
73   SecurityContextRequest(): req_(nullptr), app_idx_(0) {
74     int error = security_manager_app_inst_req_new(&req_);
75       if (error != SECURITY_MANAGER_SUCCESS) {
76         LOG(ERROR)
77             << "Failed while calling security_manager_app_inst_req_new "
78             << "(error code: " << error << ")";
79         SetErrorMessage(&error_message_, error);
80         req_ = NULL;
81       }
82   }
83   ~SecurityContextRequest() {
84     if (IsValid())
85       security_manager_app_inst_req_free(req_);
86   }
87   bool IsValid() const {
88     return req_ != NULL;
89   }
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";
94       return false;
95     }
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);
99       return false;
100     }
101     error = security_manager_app_inst_req_set_uid(req_, uid);
102     if (error != SECURITY_MANAGER_SUCCESS) {
103       SetErrorMessage(&error_message_, error);
104       return false;
105     }
106
107     pkg_type pkgtype = SM_PKG_TYPE_NONE;
108     if (type == "tpk")
109       pkgtype = SM_PKG_TYPE_CORE;
110     else if (type == "wgt")
111       pkgtype = SM_PKG_TYPE_WRT;
112
113     error = security_manager_app_inst_req_set_pkg_type(req_, pkgtype);
114     if (error != SECURITY_MANAGER_SUCCESS) {
115       SetErrorMessage(&error_message_, error);
116       return false;
117     }
118     return true;
119   }
120
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);
129         return false;
130       }
131     }
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);
137         return false;
138       }
139     }
140     if (!author_id.empty()) {
141       int error = security_manager_app_inst_req_set_author_id(req_,
142           author_id.c_str());
143       if (error != SECURITY_MANAGER_SUCCESS) {
144         SetErrorMessage(&error_message_, error);
145         return false;
146       }
147     }
148     if (!path.empty()) {
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;
154           break;
155         }
156       }
157       if (type == SM_APP_INSTALL_NONE) {
158         LOG(ERROR) << "Unexpected path: " << path;
159         return false;
160       }
161
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);
166         return false;
167       }
168     }
169     return true;
170   }
171
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(
175         req_, level);
176     if (error != SECURITY_MANAGER_SUCCESS) {
177       SetErrorMessage(&error_message_, error);
178       return false;
179     }
180     return true;
181   }
182
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))
188       return false;
189     return PrepareAppPrivileges(privileges, appdef_privileges,
190         provides_appdef_privileges);
191   }
192
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_,
198                                                               priv.c_str());
199       if (error != SECURITY_MANAGER_SUCCESS) {
200         SetErrorMessage(&error_message_, error);
201         return false;
202       }
203     }
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);
209         return false;
210       }
211     }
212     // only one app can provide appdefined privileges
213     if (app_idx_ > 1)
214       return true;
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);
223         return false;
224       }
225     }
226     return true;
227   }
228
229   bool PrepareApp(const std::string& app_id) {
230     if (app_id.empty()) {
231       LOG(ERROR) << "Appid is empty.";
232       return false;
233     }
234     // req_->apps.emplace_back();
235     if (app_idx_ > 0) {
236       int error = security_manager_app_inst_req_next(req_);
237       if (error != SECURITY_MANAGER_SUCCESS) {
238         SetErrorMessage(&error_message_, error);
239         return false;
240       }
241     }
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);
246       return false;
247     }
248     ++app_idx_;
249     return true;
250   }
251
252   bool Install() {
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);
258       return false;
259     }
260     return true;
261   }
262
263   bool Uninstall() {
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);
269       return false;
270     }
271     return true;
272   }
273
274   const std::string& ErrorMessage() const {
275     return error_message_;
276   }
277
278  private:
279   app_inst_req* req_;
280   uint app_idx_;
281   std::string error_message_;
282 };
283
284 class SecurityContextPathRequest {
285  public:
286   SecurityContextPathRequest() {
287     int error = security_manager_path_req_new(&req_);
288     if (error != SECURITY_MANAGER_SUCCESS) {
289       LOG(ERROR)
290           << "Failed while calling security_manager_path_req_new failed "
291           << "(error code: " << error << ")";
292       SetErrorMessage(&error_message_, error);
293       req_ = NULL;
294     }
295   }
296
297   ~SecurityContextPathRequest() {
298     if (IsValid())
299       security_manager_path_req_free(req_);
300   }
301
302   bool IsValid() {
303     return req_ != NULL;
304   }
305
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";
309       return false;
310     }
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);
314       return false;
315     }
316     error = security_manager_path_req_set_uid(req_, uid);
317     if (error != SECURITY_MANAGER_SUCCESS) {
318       SetErrorMessage(&error_message_, error);
319       return false;
320     }
321     return true;
322   }
323
324   bool PreparePath(const std::string& pkg_type,
325       const std::filesystem::path& path, bool is_readonly_pkg,
326       bool is_extonly) {
327     if (path.empty()) {
328       LOG(ERROR) << "Path is empty. This value must be set";
329       return false;
330     }
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;
336         break;
337       }
338     }
339     if (type == SM_APP_INSTALL_NONE) {
340       LOG(ERROR) << "Unexpected path: " << path;
341       return false;
342     }
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;
346
347     int error = security_manager_path_req_set_install_type(req_, type);
348     if (error != SECURITY_MANAGER_SUCCESS) {
349       SetErrorMessage(&error_message_, error);
350       return false;
351     }
352     std::vector<std::pair<const char*, app_install_path_type>> policies;
353     if (is_extonly)
354       policies = kSecurityPoliciesExternalOnly;
355     else
356       policies = kSecurityPolicies;
357     for (auto& policy : policies) {
358       fs::path subpath = path / policy.first;
359       if (is_extonly) {
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"))
365           continue;
366       } else {
367         if (!fs::exists(subpath))
368           continue;
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";
373           continue;
374         }
375       }
376       error = security_manager_path_req_add_path(req_, subpath.c_str(),
377           policy.second);
378       if (error != SECURITY_MANAGER_SUCCESS) {
379         SetErrorMessage(&error_message_, error);
380         return false;
381       }
382     }
383     return true;
384   }
385
386   bool Register() {
387     int error = security_manager_paths_register(req_);
388     if (error != SECURITY_MANAGER_SUCCESS) {
389       LOG(ERROR) << "Failed while calling  security_manager_paths_register "
390                  << "failed (error code: " << error << ")";
391       SetErrorMessage(&error_message_, error);
392       return false;
393     }
394     return true;
395   }
396
397   const std::string& ErrorMessage() const {
398     return error_message_;
399   }
400
401  private:
402   path_req* req_;
403   std::string error_message_;
404 };
405
406 }  // namespace
407
408 namespace common_installer {
409
410 void PrepareAppDefinedPrivilegeData(GList *privileges,
411     AppDefinedPrivInfo* tpk_priv_vec, AppDefinedPrivInfo* wgt_priv_vec) {
412
413   for (auto& priv : GListRange<appdefined_privilege_x*>(privileges)) {
414     if (strcmp(priv->type, kWebPrivilegeType) == 0)
415       wgt_priv_vec->emplace_back(std::make_pair(priv->value, priv->license ?
416           priv->license : std::string()));
417     else
418       tpk_priv_vec->emplace_back(std::make_pair(priv->value, priv->license ?
419           priv->license : std::string()));
420   }
421 }
422
423 bool RegisterSecurityContextForManifest(const ci::InstallerContext* context,
424     std::string* error_message) {
425   std::string pkg_id = context->pkgid.get();
426   std::string pkg_type = context->pkg_type.get();
427   fs::path path = context->GetPkgPath();
428   uid_t uid = context->uid.get();
429   const ci::CertificateInfo* cert_info = &(context->certificate_info.get());
430   manifest_x* manifest = context->manifest_data.get();
431   bool cross_app_rules = context->cross_app_rules.get();
432
433   // Although application framework hold list of privilege per package, there
434   // is situation where we need to filter privileges. This data model doesn't
435   // cover hybrid apps well where native privileges should be granted only to
436   // native app and web privileges should be granted only to web applications.
437   std::vector<std::string> tpk_priv_vec;
438   std::vector<std::string> wgt_priv_vec;
439   for (auto& priv : GListRange<privilege_x*>(manifest->privileges)) {
440     if (strcmp(priv->type, kWebPrivilegeType) == 0)
441       wgt_priv_vec.emplace_back(priv->value);
442     else
443       tpk_priv_vec.emplace_back(priv->value);
444   }
445   AppDefinedPrivInfo tpk_appdef_vec, wgt_appdef_vec;
446   AppDefinedPrivInfo tpk_provides_appdef_vec, wgt_provides_appdef_vec;
447
448   PrepareAppDefinedPrivilegeData(manifest->appdefined_privileges,
449       &tpk_appdef_vec, &wgt_appdef_vec);
450   PrepareAppDefinedPrivilegeData(manifest->provides_appdefined_privileges,
451       &tpk_provides_appdef_vec, &wgt_provides_appdef_vec);
452
453   SecurityContextRequest req;
454   if (!req.IsValid()) {
455     *error_message = req.ErrorMessage();
456     return false;
457   }
458   if (!req.PrepareBasic(pkg_id, uid, pkg_type)) {
459     *error_message = req.ErrorMessage();
460     return false;
461   }
462   if (!req.PrepareAdditional(cert_info->author_id.get(), manifest->api_version,
463       path, cross_app_rules)) {
464     *error_message = req.ErrorMessage();
465     return false;
466   }
467
468   if (!req.PreparePrivilegeLevel(context->privilege_level.get())) {
469     *error_message = req.ErrorMessage();
470     return false;
471   }
472
473   for (application_x* app : GListRange<application_x*>(manifest->application)) {
474     if (!app->appid) {
475       return false;
476     }
477
478     bool is_web_priv = strcmp(app->type, "webapp") == 0;
479     if (!req.PrepareAppWithPrivileges(app->appid,
480         is_web_priv ? wgt_priv_vec : tpk_priv_vec,
481         is_web_priv ? wgt_appdef_vec : tpk_appdef_vec,
482         is_web_priv ? wgt_provides_appdef_vec : tpk_provides_appdef_vec)) {
483       *error_message = req.ErrorMessage();
484       return false;
485     }
486   }
487
488   if (!manifest->application)
489     req.PrepareApp(pkg_id);
490
491   bool result = req.Install();
492   *error_message = req.ErrorMessage();
493   return result;
494 }
495
496 static bool UnregisterSecurityContext(const std::string& pkg_id,
497     const std::string& pkg_type,  uid_t uid,
498     const std::vector<std::string>& appids, std::string* error_message) {
499   SecurityContextRequest req;
500   if (!req.IsValid()) {
501     *error_message = req.ErrorMessage();
502     return false;
503   }
504   if (!req.PrepareBasic(pkg_id, uid, pkg_type)) {
505     *error_message = req.ErrorMessage();
506     return false;
507   }
508
509   for (const auto& appid : appids) {
510     if (!req.PrepareApp(appid)) {
511       return false;
512     }
513   }
514
515   if (appids.empty())
516     req.PrepareApp(pkg_id);
517
518   bool result = req.Uninstall();
519   *error_message = req.ErrorMessage();
520   return result;
521 }
522
523 bool UnregisterSecurityContextForManifest(const std::string& pkg_id,
524     const std::string& pkg_type, uid_t uid, manifest_x* manifest,
525     std::string* error_message) {
526   std::vector<std::string> appids;
527   for (application_x* app : GListRange<application_x*>(manifest->application)) {
528     if (!app->appid) {
529       return false;
530     }
531     appids.emplace_back(app->appid);
532   }
533   return UnregisterSecurityContext(pkg_id, pkg_type, uid,
534       appids, error_message);
535 }
536
537 bool UnregisterSecurityContextForPkgId(const std::string &pkg_id,
538     const std::string& pkg_type, uid_t uid,
539     std::string* error_message, bool ignore_data_absence) {
540   std::vector<std::string> appids;
541   ci::PkgQueryInterface pkg_query(pkg_id, uid);
542   if (!pkg_query.AppidsForPkgId(&appids))
543     return ignore_data_absence;
544   return UnregisterSecurityContext(pkg_id, pkg_type, uid,
545       appids, error_message);
546 }
547
548 bool RegisterSecurityContextForPath(const std::string &pkg_id,
549     const std::filesystem::path& path, uid_t uid, bool is_readonly_pkg,
550     std::string* error_message) {
551   SecurityContextPathRequest req;
552   if (!req.IsValid()) {
553     *error_message = req.ErrorMessage();
554     return false;
555   }
556   if (!req.Prepare(pkg_id, uid)) {
557     *error_message = req.ErrorMessage();
558     return false;
559   }
560   if (!req.PreparePath({}, path, is_readonly_pkg, false)) {
561     *error_message = req.ErrorMessage();
562     return false;
563   }
564   bool result = req.Register();
565   *error_message = req.ErrorMessage();
566   return result;
567 }
568
569 bool RegisterSecurityContextForPathExternalOnly(const std::string &pkg_id,
570     const std::string &pkg_type, const std::filesystem::path& path,
571     uid_t uid, std::string* error_message) {
572   SecurityContextPathRequest req;
573   if (!req.IsValid()) {
574     *error_message = req.ErrorMessage();
575     return false;
576   }
577   if (!req.Prepare(pkg_id, uid)) {
578     *error_message = req.ErrorMessage();
579     return false;
580   }
581   if (!req.PreparePath(pkg_type, path, false, true)) {
582     *error_message = req.ErrorMessage();
583     return false;
584   }
585   bool result = req.Register();
586   *error_message = req.ErrorMessage();
587   return result;
588 }
589
590 bool HasOwnerRwOtherRoPaths(const std::filesystem::path& path) {
591   for (auto& policy : kSecurityPolicies) {
592     if (policy.second != SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO)
593       continue;
594
595     fs::path subpath = path / policy.first;
596     LOG(ERROR) << "subpath : " << subpath;
597     if (fs::exists(subpath))
598       return true;
599   }
600
601   return false;
602 }
603
604 }  // namespace common_installer