Perform code style checking fixes
[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 <boost/filesystem/operations.hpp>
8 #include <boost/format.hpp>
9
10 #include <unistd.h>
11 #include <sys/types.h>
12 #include <manifest_parser/utils/logging.h>
13 #include <security-manager.h>
14 #include <tzplatform_config.h>
15
16 #include <utility>
17 #include <vector>
18 #include <algorithm>
19
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"
24
25 namespace bf = boost::filesystem;
26 namespace ci = common_installer;
27
28 namespace {
29
30 using AppDefinedPrivInfo = std::vector<std::pair<std::string, std::string>>;
31
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}
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 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";
74     return false;
75   }
76
77   int error = security_manager_app_inst_req_set_app_id(req,
78       app_id.c_str());
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 + ">";
83     return false;
84   }
85
86   error = security_manager_app_inst_req_set_pkg_id(req,
87       pkg_id.c_str());
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 + ">";
92     return false;
93   }
94
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 + ">";
100     return false;
101   }
102
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);
107       *error_message =
108           security_manager_strerror(static_cast<lib_retcode>(error));
109       *error_message += ":<" + errnum + ">";
110       return false;
111     }
112   }
113
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);
119       *error_message =
120           security_manager_strerror(static_cast<lib_retcode>(error));
121       *error_message += ":<" + errnum + ">";
122       return false;
123     }
124   }
125
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);
130       *error_message =
131           security_manager_strerror(static_cast<lib_retcode>(error));
132       *error_message += ":<" + errnum + ">";
133       return false;
134     }
135   }
136
137   if (!path.empty()) {
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;
143         break;
144       }
145     }
146     if (type == SM_APP_INSTALL_NONE) {
147       LOG(ERROR) << "Unexpected path: " << path;
148       return false;
149     }
150
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);
155       *error_message =
156           security_manager_strerror(static_cast<lib_retcode>(error));
157       *error_message += ":<" + errnum + ">";
158       return false;
159     }
160   }
161
162   for (auto& priv : privileges) {
163     security_manager_app_inst_req_add_client_privilege(
164         req, priv.c_str(), nullptr);
165   }
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);
171       *error_message =
172           security_manager_strerror(static_cast<lib_retcode>(error));
173       *error_message += ":<" + errnum + ">";
174       return false;
175     }
176   }
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);
184       *error_message =
185           security_manager_strerror(static_cast<lib_retcode>(error));
186       *error_message += ":<" + errnum + ">";
187       return false;
188     }
189   }
190   return true;
191 }
192
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";
199     return false;
200   }
201
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 + ">";
207     return false;
208   }
209
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 + ">";
215     return false;
216   }
217
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;
223       break;
224     }
225   }
226   if (type == SM_APP_INSTALL_NONE) {
227     LOG(ERROR) << "Unexpected path: " << path;
228     return false;
229   }
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;
233
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);
237     *error_message =
238         security_manager_strerror(static_cast<lib_retcode>(error));
239     *error_message += ":<" + errnum + ">";
240     return false;
241   }
242
243   std::vector<std::pair<const char*, app_install_path_type>> policies;
244   if (is_extonly)
245     policies = kSecurityPoliciesExternalOnly;
246   else
247     policies = kSecurityPolicies;
248   for (auto& policy : policies) {
249     bf::path subpath = path / policy.first;
250     if (is_extonly) {
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"))
256         continue;
257     } else {
258       if (!bf::exists(subpath))
259         continue;
260       if (bf::is_symlink(symlink_status(subpath))) {
261         LOG(DEBUG) << "Path " << subpath << " is a symlink."
262                    << "Path will not be registered";
263         continue;
264       }
265     }
266     error = security_manager_path_req_add_path(req, subpath.c_str(),
267         policy.second);
268     if (error != SECURITY_MANAGER_SUCCESS) {
269       std::string errnum = std::to_string(error);
270       *error_message =
271                 security_manager_strerror(static_cast<lib_retcode>(error));
272       *error_message += ":<" + errnum + ">";
273       return false;
274     }
275   }
276
277   return true;
278 }
279
280 }  // namespace
281
282 namespace common_installer {
283
284 bool RegisterSecurityContext(const std::string& app_id,
285     const std::string& pkg_id, const std::string& author_id,
286     const std::string& api_version, const boost::filesystem::path& path,
287     uid_t uid, const std::vector<std::string>& privileges,
288     const AppDefinedPrivInfo& appdef_privileges,
289     const AppDefinedPrivInfo& provides_appdef_privileges,
290     bool cross_app_rules, std::string* error_message) {
291   app_inst_req* req;
292
293   int error = security_manager_app_inst_req_new(&req);
294   if (error != SECURITY_MANAGER_SUCCESS) {
295     LOG(ERROR)
296         << "Failed while calling security_manager_app_inst_req_new failed "
297         << "(error code: " << error << ")";
298     std::string errnum = std::to_string(error);
299     *error_message = security_manager_strerror(static_cast<lib_retcode>(error));
300     *error_message += ":<" + errnum + ">";
301     return false;
302   }
303
304   if (!PrepareRequest(app_id, pkg_id, author_id, api_version, path, uid,
305       privileges, appdef_privileges, provides_appdef_privileges,
306       req, cross_app_rules, error_message)) {
307     LOG(ERROR) << "Failed while preparing security_manager_app_inst_req";
308     security_manager_app_inst_req_free(req);
309     return false;
310   }
311
312   error = security_manager_app_install(req);
313   if (error != SECURITY_MANAGER_SUCCESS) {
314     LOG(ERROR) << "Failed while calling security_manager_app_install failed "
315                << "(error code: " << error << ")";
316     std::string errnum = std::to_string(error);
317     *error_message = security_manager_strerror(static_cast<lib_retcode>(error));
318     *error_message += ":<" + errnum + ">";
319     security_manager_app_inst_req_free(req);
320     return false;
321   }
322
323   security_manager_app_inst_req_free(req);
324   return true;
325 }
326
327 bool UnregisterSecurityContext(const std::string& app_id,
328     const std::string& pkg_id, uid_t uid, std::string* error_message) {
329   app_inst_req* req;
330
331   int error = security_manager_app_inst_req_new(&req);
332   if (error != SECURITY_MANAGER_SUCCESS) {
333     LOG(ERROR) << "Failed while calling security_manager_app_inst_req_new  "
334                << "(error code: " << error << ")";
335     std::string errnum = std::to_string(error);
336     *error_message = security_manager_strerror(static_cast<lib_retcode>(error));
337     *error_message += ":<" + errnum + ">";
338     return false;
339   }
340
341   if (!PrepareRequest(app_id, pkg_id, std::string(), std::string(), bf::path(),
342                       uid, {}, {}, {}, req, false, error_message)) {
343     LOG(ERROR) << "Failed while preparing security_manager_app_inst_req";
344     security_manager_app_inst_req_free(req);
345     return false;
346   }
347
348   error = security_manager_app_uninstall(req);
349   if (error != SECURITY_MANAGER_SUCCESS) {
350     LOG(ERROR) << "Failed while calling  security_manager_app_uninstall failed "
351                << "(error code: " << error << ")";
352     std::string errnum = std::to_string(error);
353     *error_message = security_manager_strerror(static_cast<lib_retcode>(error));
354     *error_message += ":<" + errnum + ">";
355     security_manager_app_inst_req_free(req);
356     return false;
357   }
358
359   security_manager_app_inst_req_free(req);
360   return true;
361 }
362
363 void PrepareAppDefinedPrivilegeData(GList *privileges,
364     AppDefinedPrivInfo* tpk_priv_vec, AppDefinedPrivInfo* wgt_priv_vec) {
365
366   for (auto& priv : GListRange<appdefined_privilege_x*>(privileges)) {
367     if (strcmp(priv->type, kWebPrivilegeType) == 0)
368       wgt_priv_vec->emplace_back(std::make_pair(priv->value, priv->license ?
369           priv->license : std::string()));
370     else
371       tpk_priv_vec->emplace_back(std::make_pair(priv->value, priv->license ?
372           priv->license : std::string()));
373   }
374 }
375
376 bool RegisterSecurityContextForManifest(
377     const std::string& pkg_id, const boost::filesystem::path& path, uid_t uid,
378     common_installer::CertificateInfo* cert_info, manifest_x* manifest,
379     bool cross_app_rules, std::string* error_message) {
380   // Although application framework hold list of privilege per package, there
381   // is situation where we need to filter privileges. This data model doesn't
382   // cover hybrid apps well where native privileges should be granted only to
383   // native app and web privileges should be granted only to web applications.
384   std::vector<std::string> tpk_priv_vec;
385   std::vector<std::string> wgt_priv_vec;
386   for (auto& priv : GListRange<privilege_x*>(manifest->privileges)) {
387     if (strcmp(priv->type, kWebPrivilegeType) == 0)
388       wgt_priv_vec.emplace_back(priv->value);
389     else
390       tpk_priv_vec.emplace_back(priv->value);
391   }
392   AppDefinedPrivInfo tpk_appdef_vec, wgt_appdef_vec;
393   AppDefinedPrivInfo tpk_provides_appdef_vec, wgt_provides_appdef_vec;
394
395   PrepareAppDefinedPrivilegeData(manifest->appdefined_privileges,
396       &tpk_appdef_vec, &wgt_appdef_vec);
397   PrepareAppDefinedPrivilegeData(manifest->provides_appdefined_privileges,
398       &tpk_provides_appdef_vec, &wgt_provides_appdef_vec);
399
400   for (application_x* app : GListRange<application_x*>(manifest->application)) {
401     if (!app->appid) {
402       return false;
403     }
404
405     bool is_web_priv = strcmp(app->type, "webapp") == 0;
406     if (!RegisterSecurityContext(app->appid, pkg_id, cert_info->author_id.get(),
407         manifest->api_version, path, uid,
408         is_web_priv ? wgt_priv_vec : tpk_priv_vec,
409         is_web_priv ? wgt_appdef_vec : tpk_appdef_vec,
410         is_web_priv ? wgt_provides_appdef_vec : tpk_provides_appdef_vec,
411         cross_app_rules, error_message)) {
412       return false;
413     }
414   }
415   return true;
416 }
417
418 bool UnregisterSecurityContextForManifest(const std::string& pkg_id,
419     uid_t uid, manifest_x* manifest, std::string* error_message) {
420   for (application_x* app : GListRange<application_x*>(manifest->application)) {
421     if (!app->appid) {
422       return false;
423     }
424     if (!UnregisterSecurityContext(app->appid, pkg_id, uid, error_message)) {
425       return false;
426     }
427   }
428   return true;
429 }
430
431 bool UnregisterSecurityContextForPkgId(const std::string &pkg_id,
432     uid_t uid, std::string* error_message, bool ignore_data_absence) {
433   std::vector<std::string> appids;
434   if (!QueryAppidsForPkgId(pkg_id, &appids, uid))
435     return ignore_data_absence;
436   for (auto& appid : appids) {
437     if (!UnregisterSecurityContext(appid, pkg_id, uid, error_message)) {
438       return false;
439     }
440   }
441   return true;
442 }
443
444 bool RegisterSecurityContextForPath(const std::string &pkg_id,
445     const boost::filesystem::path& path, uid_t uid, bool is_readonly_pkg,
446     std::string* error_message) {
447   path_req* req;
448   int error = security_manager_path_req_new(&req);
449   if (error != SECURITY_MANAGER_SUCCESS) {
450     LOG(ERROR)
451         << "Failed while calling security_manager_path_req_new failed "
452         << "(error code: " << error << ")";
453     std::string errnum = std::to_string(error);
454     *error_message = security_manager_strerror(static_cast<lib_retcode>(error));
455     *error_message += ":<" + errnum + ">";
456     return false;
457   }
458
459   if (!PreparePathRequest(req, pkg_id, {}, path, uid, is_readonly_pkg, false,
460                           error_message)) {
461     LOG(ERROR) << "Failed while preparing security_manager_path_req";
462     security_manager_path_req_free(req);
463     return false;
464   }
465
466   error = security_manager_paths_register(req);
467   if (error != SECURITY_MANAGER_SUCCESS) {
468     LOG(ERROR) << "Failed while calling security_manager_paths_register 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_path_req_free(req);
474     return false;
475   }
476
477   security_manager_path_req_free(req);
478
479   return true;
480 }
481
482 bool RegisterSecurityContextForPathExternalOnly(const std::string &pkg_id,
483     const std::string &pkg_type, const boost::filesystem::path& path,
484     uid_t uid, std::string* error_message) {
485   path_req* req;
486   int error = security_manager_path_req_new(&req);
487   if (error != SECURITY_MANAGER_SUCCESS) {
488     LOG(ERROR)
489         << "Failed while calling security_manager_path_req_new failed "
490         << "(error code: " << error << ")";
491     std::string errnum = std::to_string(error);
492     *error_message = security_manager_strerror(static_cast<lib_retcode>(error));
493     *error_message += ":<" + errnum + ">";
494     return false;
495   }
496
497   if (!PreparePathRequest(req, pkg_id, pkg_type, path, uid, false, true,
498                           error_message)) {
499     LOG(ERROR) << "Failed while preparing security_manager_path_req";
500     security_manager_path_req_free(req);
501     return false;
502   }
503
504   error = security_manager_paths_register(req);
505   if (error != SECURITY_MANAGER_SUCCESS) {
506     LOG(ERROR) << "Failed while calling security_manager_paths_register failed "
507                << "(error code: " << error << ")";
508     std::string errnum = std::to_string(error);
509     *error_message = security_manager_strerror(static_cast<lib_retcode>(error));
510     *error_message += ":<" + errnum + ">";
511     security_manager_path_req_free(req);
512     return false;
513   }
514
515   security_manager_path_req_free(req);
516
517   return true;
518 }
519
520 }  // namespace common_installer