Proper native implementation for directory creator tool
[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 <security-manager.h>
9
10 #include <utility>
11 #include <vector>
12 #include <algorithm>
13
14 #include "common/utils/glist_range.h"
15 #include "common/utils/logging.h"
16
17 namespace bf = boost::filesystem;
18
19 namespace {
20
21 const std::vector<std::pair<const char*,
22                             app_install_path_type>> kSecurityPolicies = {
23   {"/", SECURITY_MANAGER_PATH_PUBLIC_RO},
24   {"bin/", SECURITY_MANAGER_PATH_RO},
25   {"data/", SECURITY_MANAGER_PATH_RW},
26   {"cache/", SECURITY_MANAGER_PATH_RW},
27   {"lib/", SECURITY_MANAGER_PATH_RO},
28   {"res/", SECURITY_MANAGER_PATH_RO},
29   {"shared/", SECURITY_MANAGER_PATH_PUBLIC_RO},
30   {"tmp/", SECURITY_MANAGER_PATH_RW}
31 };
32
33 bool PrepareRequest(const std::string& app_id, const std::string& pkg_id,
34     const boost::filesystem::path& path, uid_t uid,
35     const std::vector<std::string>& privileges,
36     app_inst_req* req) {
37   if (app_id.empty() || pkg_id.empty()) {
38     LOG(ERROR) << "Appid or pkgid is empty. Both values must be set";
39     return false;
40   }
41
42   int error = security_manager_app_inst_req_set_app_id(req,
43       app_id.c_str());
44   if (error != SECURITY_MANAGER_SUCCESS) {
45     return false;
46   }
47
48   error = security_manager_app_inst_req_set_pkg_id(req,
49       pkg_id.c_str());
50   if (error != SECURITY_MANAGER_SUCCESS) {
51     return false;
52   }
53
54   error = security_manager_app_inst_req_set_uid(req, uid);
55   if (error != SECURITY_MANAGER_SUCCESS) {
56     return false;
57   }
58
59   if (!path.empty()) {
60     for (auto& policy : kSecurityPolicies) {
61       bf::path subpath = path / policy.first;
62       if (bf::exists(subpath)) {
63         error = security_manager_app_inst_req_add_path(req, subpath.c_str(),
64                                                        policy.second);
65         if (error != SECURITY_MANAGER_SUCCESS) {
66           return false;
67         }
68       }
69     }
70   }
71
72   for (auto& priv : privileges) {
73     security_manager_app_inst_req_add_privilege(req, priv.c_str());
74   }
75   return true;
76 }
77
78 }  // namespace
79
80 namespace common_installer {
81
82 bool RegisterSecurityContext(const std::string& app_id,
83     const std::string& pkg_id, const boost::filesystem::path& path, uid_t uid,
84     const std::vector<std::string>& privileges) {
85   app_inst_req* req;
86
87   int error = security_manager_app_inst_req_new(&req);
88   if (error != SECURITY_MANAGER_SUCCESS) {
89     LOG(ERROR)
90         << "Failed while calling security_manager_app_inst_req_new failed "
91         << "(error code: " << error << ")";
92     return false;
93   }
94
95   if (!PrepareRequest(app_id, pkg_id, path, uid, privileges, req)) {
96       LOG(ERROR) << "Failed while preparing security_manager_app_inst_req";
97       security_manager_app_inst_req_free(req);
98       return false;
99   }
100
101   error = security_manager_app_install(req);
102   if (error != SECURITY_MANAGER_SUCCESS) {
103     LOG(ERROR) << "Failed while calling security_manager_app_install failed "
104                << "(error code: " << error << ")";
105     security_manager_app_inst_req_free(req);
106     return false;
107   }
108
109   security_manager_app_inst_req_free(req);
110   return true;
111 }
112
113 bool UnregisterSecurityContext(const std::string& app_id,
114     const std::string& pkg_id, uid_t uid) {
115   app_inst_req* req;
116
117   int error = security_manager_app_inst_req_new(&req);
118   if (error != SECURITY_MANAGER_SUCCESS) {
119     LOG(ERROR) << "Failed while calling security_manager_app_inst_req_new  "
120                << "(error code: " << error << ")";
121     return false;
122   }
123
124   if (!PrepareRequest(app_id, pkg_id, bf::path(), uid, {}, req)) {
125     LOG(ERROR) << "Failed while preparing security_manager_app_inst_req";
126     security_manager_app_inst_req_free(req);
127     return false;
128   }
129
130   error = security_manager_app_uninstall(req);
131   if (error != SECURITY_MANAGER_SUCCESS) {
132     LOG(ERROR) << "Failed while calling  security_manager_app_uninstall failed "
133                << "(error code: " << error << ")";
134     security_manager_app_inst_req_free(req);
135     return false;
136   }
137
138   security_manager_app_inst_req_free(req);
139   return true;
140 }
141
142 bool RegisterSecurityContextForManifest(
143     const std::string& pkg_id, const boost::filesystem::path& path,
144     uid_t uid, manifest_x* manifest) {
145   std::vector<std::string> priv_vec;
146   for (const char* priv : GListRange<char*>(manifest->privileges)) {
147     priv_vec.emplace_back(priv);
148   }
149   for (application_x* app : GListRange<application_x*>(manifest->application)) {
150     if (!app->appid) {
151       return false;
152     }
153     if (!RegisterSecurityContext(app->appid, pkg_id,
154         path, uid, priv_vec)) {
155       return false;
156     }
157   }
158   return true;
159 }
160
161 bool UnregisterSecurityContextForManifest(const std::string& pkg_id,
162                                           uid_t uid, manifest_x* manifest) {
163   for (application_x* app : GListRange<application_x*>(manifest->application)) {
164     if (!app->appid) {
165       return false;
166     }
167     if (!UnregisterSecurityContext(app->appid, pkg_id, uid)) {
168       return false;
169     }
170   }
171   return true;
172 }
173
174 }  // namespace common_installer