1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "bundle_manager_proxy.h"
17
18 #include <fcntl.h>
19 #include <sys/sendfile.h>
20 #include <sys/stat.h>
21 #include <sys/types.h>
22 #include <unistd.h>
23
24 #include "directory_ex.h"
25 #include "edm_log.h"
26 #include "func_code.h"
27 #include "message_parcel_utils.h"
28 #include "policy_type.h"
29
30 namespace OHOS {
31 namespace EDM {
32 std::shared_ptr<BundleManagerProxy> BundleManagerProxy::instance_ = nullptr;
33 std::once_flag BundleManagerProxy::flag_;
34 const std::u16string DESCRIPTOR = u"ohos.edm.IEnterpriseDeviceMgr";
35 const std::string HAP_DIRECTORY = "/data/service/el1/public/edm/stream_install";
36 const std::string SEPARATOR = "/";
37
BundleManagerProxy()38 BundleManagerProxy::BundleManagerProxy()
39 {
40 AddPolicyTypeMap();
41 EDMLOGD("BundleManagerProxy()");
42 }
43
~BundleManagerProxy()44 BundleManagerProxy::~BundleManagerProxy()
45 {
46 EDMLOGD("~BundleManagerProxy()");
47 }
48
AddPolicyTypeMap()49 void BundleManagerProxy::AddPolicyTypeMap()
50 {
51 policyTypeMap_[static_cast<int32_t>(PolicyType::ALLOW_INSTALL)] = EdmInterfaceCode::ALLOWED_INSTALL_BUNDLES;
52 policyTypeMap_[static_cast<int32_t>(PolicyType::DISALLOW_INSTALL)] = EdmInterfaceCode::DISALLOWED_INSTALL_BUNDLES;
53 policyTypeMap_[static_cast<int32_t>(PolicyType::DISALLOW_UNINSTALL)] =
54 EdmInterfaceCode::DISALLOWED_UNINSTALL_BUNDLES;
55 }
56
GetBundleManagerProxy()57 std::shared_ptr<BundleManagerProxy> BundleManagerProxy::GetBundleManagerProxy()
58 {
59 std::call_once(flag_, []() {
60 if (instance_ == nullptr) {
61 instance_ = std::make_shared<BundleManagerProxy>();
62 }
63 });
64 return instance_;
65 }
66
Uninstall(AppExecFwk::ElementName & admin,std::string bundleName,int32_t userId,bool isKeepData,std::string & retMessage)67 int32_t BundleManagerProxy::Uninstall(AppExecFwk::ElementName &admin, std::string bundleName, int32_t userId,
68 bool isKeepData, std::string &retMessage)
69 {
70 EDMLOGD("BundleManagerProxy::Uninstall");
71 auto proxy = EnterpriseDeviceMgrProxy::GetInstance();
72 MessageParcel data;
73 MessageParcel reply;
74 data.WriteInterfaceToken(DESCRIPTOR);
75 data.WriteInt32(WITHOUT_USERID);
76 data.WriteParcelable(&admin);
77 data.WriteString(WITHOUT_PERMISSION_TAG);
78 data.WriteString(bundleName);
79 data.WriteInt32(userId);
80 data.WriteBool(isKeepData);
81 std::uint32_t funcCode = POLICY_FUNC_CODE((std::uint32_t)FuncOperateType::SET, EdmInterfaceCode::UNINSTALL);
82 ErrCode ret = proxy->HandleDevicePolicy(funcCode, data, reply);
83 if (ret == EdmReturnErrCode::PARAM_ERROR) {
84 retMessage = reply.ReadString();
85 }
86 return ret;
87 }
88
AddBundlesByPolicyType(AppExecFwk::ElementName & admin,std::vector<std::string> & bundles,int32_t userId,int32_t policyType)89 int32_t BundleManagerProxy::AddBundlesByPolicyType(AppExecFwk::ElementName &admin, std::vector<std::string> &bundles,
90 int32_t userId, int32_t policyType)
91 {
92 EDMLOGD("BundleManagerProxy::AddBundlesByPolicyType policyType =%{public}d", policyType);
93 auto proxy = EnterpriseDeviceMgrProxy::GetInstance();
94 MessageParcel data;
95 std::uint32_t funcCode = 0;
96 if (policyTypeMap_.find(policyType) != policyTypeMap_.end()) {
97 funcCode = POLICY_FUNC_CODE((std::uint32_t)FuncOperateType::SET, policyTypeMap_[policyType]);
98 } else {
99 EDMLOGE("can not get policy type");
100 return EdmReturnErrCode::PARAM_ERROR;
101 }
102 data.WriteInterfaceToken(DESCRIPTOR);
103 data.WriteInt32(HAS_USERID);
104 data.WriteInt32(userId);
105 data.WriteParcelable(&admin);
106 data.WriteString(WITHOUT_PERMISSION_TAG);
107 data.WriteStringVector(bundles);
108 return proxy->HandleDevicePolicy(funcCode, data);
109 }
110
RemoveBundlesByPolicyType(AppExecFwk::ElementName & admin,std::vector<std::string> & bundles,int32_t userId,int32_t policyType)111 int32_t BundleManagerProxy::RemoveBundlesByPolicyType(AppExecFwk::ElementName &admin, std::vector<std::string> &bundles,
112 int32_t userId, int32_t policyType)
113 {
114 EDMLOGD("BundleManagerProxy::RemoveBundlesByPolicyType policyType =%{public}d", policyType);
115 auto proxy = EnterpriseDeviceMgrProxy::GetInstance();
116 MessageParcel data;
117 std::uint32_t funcCode = 0;
118 if (policyTypeMap_.find(policyType) != policyTypeMap_.end()) {
119 funcCode = POLICY_FUNC_CODE((std::uint32_t)FuncOperateType::REMOVE, policyTypeMap_[policyType]);
120 } else {
121 EDMLOGE("can not get policy type");
122 return EdmReturnErrCode::PARAM_ERROR;
123 }
124 data.WriteInterfaceToken(DESCRIPTOR);
125 data.WriteInt32(HAS_USERID);
126 data.WriteInt32(userId);
127 data.WriteParcelable(&admin);
128 data.WriteString(WITHOUT_PERMISSION_TAG);
129 data.WriteStringVector(bundles);
130 return proxy->HandleDevicePolicy(funcCode, data);
131 }
132
GetBundlesByPolicyType(AppExecFwk::ElementName & admin,int32_t userId,std::vector<std::string> & bundles,int32_t policyType)133 int32_t BundleManagerProxy::GetBundlesByPolicyType(AppExecFwk::ElementName &admin, int32_t userId,
134 std::vector<std::string> &bundles, int32_t policyType)
135 {
136 EDMLOGD("BundleManagerProxy::GetAllowedOrDisallowedInstallBundles policyType =%{public}d", policyType);
137 auto proxy = EnterpriseDeviceMgrProxy::GetInstance();
138 MessageParcel data;
139 MessageParcel reply;
140 data.WriteInterfaceToken(DESCRIPTOR);
141 data.WriteInt32(HAS_USERID);
142 data.WriteInt32(userId);
143 data.WriteString(WITHOUT_PERMISSION_TAG);
144 data.WriteInt32(HAS_ADMIN);
145 data.WriteParcelable(&admin);
146 if (policyTypeMap_.find(policyType) != policyTypeMap_.end()) {
147 proxy->GetPolicy(policyTypeMap_[policyType], data, reply);
148 } else {
149 EDMLOGE("can not get policy type");
150 return EdmReturnErrCode::PARAM_ERROR;
151 }
152 int32_t ret = ERR_INVALID_VALUE;
153 bool blRes = reply.ReadInt32(ret) && (ret == ERR_OK);
154 if (!blRes) {
155 EDMLOGW("EnterpriseDeviceMgrProxy:GetPolicy fail. %{public}d", ret);
156 return ret;
157 }
158 reply.ReadStringVector(&bundles);
159 return ERR_OK;
160 }
161
Install(AppExecFwk::ElementName & admin,std::vector<std::string> & hapFilePaths,AppExecFwk::InstallParam & installParam,std::string & errMessage)162 int32_t BundleManagerProxy::Install(AppExecFwk::ElementName &admin, std::vector<std::string> &hapFilePaths,
163 AppExecFwk::InstallParam &installParam, std::string &errMessage)
164 {
165 EDMLOGD("BundleManagerProxy::install");
166
167 if (hapFilePaths.empty()) {
168 EDMLOGE("install failed due to empty hapFilePaths");
169 return EdmReturnErrCode::PARAM_ERROR;
170 }
171 std::vector<std::string> realPaths;
172 for (auto const &hapFilePath : hapFilePaths) {
173 ErrCode res = WriteFileToStream(admin, hapFilePath, realPaths, errMessage);
174 if (res != ERR_OK) {
175 EDMLOGE("WriteFileToStream failed");
176 return res;
177 }
178 }
179
180 auto proxy = EnterpriseDeviceMgrProxy::GetInstance();
181 MessageParcel data;
182 MessageParcel reply;
183 data.WriteInterfaceToken(DESCRIPTOR);
184 data.WriteInt32(WITHOUT_USERID);
185 data.WriteParcelable(&admin);
186 data.WriteString(WITHOUT_PERMISSION_TAG);
187 data.WriteStringVector(realPaths);
188 MessageParcelUtils::WriteInstallParam(installParam, data);
189 std::uint32_t funcCode = POLICY_FUNC_CODE((std::uint32_t)FuncOperateType::SET, EdmInterfaceCode::INSTALL);
190 ErrCode ret = proxy->HandleDevicePolicy(funcCode, data, reply);
191 if (ret == EdmReturnErrCode::APPLICATION_INSTALL_FAILED) {
192 errMessage = reply.ReadString();
193 EDMLOGE("Install failed");
194 }
195 return ret;
196 }
197
WriteFileToInner(MessageParcel & reply,const std::string & realPath,std::vector<std::string> & servicePaths,std::string & errMessage)198 ErrCode BundleManagerProxy::WriteFileToInner(MessageParcel &reply, const std::string &realPath,
199 std::vector<std::string> &servicePaths, std::string &errMessage)
200 {
201 int32_t sharedFd = reply.ReadFileDescriptor();
202 servicePaths.emplace_back(reply.ReadString());
203 if (sharedFd < 0) {
204 EDMLOGE("write file to stream failed due to invalid file descriptor");
205 errMessage = "write file to stream failed due to invalid file descriptor";
206 return EdmReturnErrCode::APPLICATION_INSTALL_FAILED;
207 }
208 int32_t outputFd = dup(sharedFd);
209 close(sharedFd);
210
211 int32_t inputFd = open(realPath.c_str(), O_RDONLY);
212 if (inputFd < 0) {
213 close(outputFd);
214 EDMLOGE("write file to stream failed due to open the hap file");
215 errMessage = "write file to stream failed due to open the hap file";
216 return EdmReturnErrCode::APPLICATION_INSTALL_FAILED;
217 }
218 off_t offset = 0;
219 struct stat stat_buff;
220 if (fstat(inputFd, &stat_buff) != 0) {
221 EDMLOGE("fstat file failed!");
222 close(outputFd);
223 close(inputFd);
224 return EdmReturnErrCode::APPLICATION_INSTALL_FAILED;
225 }
226
227 if (sendfile(outputFd, inputFd, &offset, stat_buff.st_size) == -1) {
228 EDMLOGE("send file failed!");
229 close(outputFd);
230 close(inputFd);
231 return EdmReturnErrCode::APPLICATION_INSTALL_FAILED;
232 }
233
234 close(inputFd);
235 fsync(outputFd);
236 close(outputFd);
237 return ERR_OK;
238 }
239
WriteFileToStream(AppExecFwk::ElementName & admin,const std::string & hapFilePath,std::vector<std::string> & servicePaths,std::string & errMessage)240 ErrCode BundleManagerProxy::WriteFileToStream(AppExecFwk::ElementName &admin, const std::string &hapFilePath,
241 std::vector<std::string> &servicePaths, std::string &errMessage)
242 {
243 std::string fileName;
244 std::string realPath;
245 ErrCode checkRet = checkHapFilePath(hapFilePath, fileName, realPath, errMessage);
246 if (checkRet != ERR_OK) {
247 return checkRet;
248 }
249
250 auto proxy = EnterpriseDeviceMgrProxy::GetInstance();
251 MessageParcel data;
252 MessageParcel reply;
253 data.WriteInterfaceToken(DESCRIPTOR);
254 data.WriteInt32(WITHOUT_USERID);
255 data.WriteString(WITHOUT_PERMISSION_TAG);
256 data.WriteInt32(HAS_ADMIN);
257 data.WriteParcelable(&admin);
258 data.WriteString(fileName);
259 proxy->GetPolicy(POLICY_FUNC_CODE((std::uint32_t)FuncOperateType::GET, EdmInterfaceCode::INSTALL), data, reply);
260 int32_t ret = ERR_INVALID_VALUE;
261 bool blRes = reply.ReadInt32(ret) && (ret == ERR_OK);
262 if (!blRes) {
263 EDMLOGW("BundleManagerProxy:WriteFileToStream fail. %{public}d", ret);
264 errMessage = reply.ReadString();
265 return ret;
266 }
267 if (WriteFileToInner(reply, realPath, servicePaths, errMessage) != ERR_OK) {
268 EDMLOGE("write file to stream failed");
269 return EdmReturnErrCode::APPLICATION_INSTALL_FAILED;
270 }
271 return ERR_OK;
272 }
273
checkHapFilePath(const std::string & hapFilePath,std::string & fileName,std::string & realPath,std::string & errMessage)274 ErrCode BundleManagerProxy::checkHapFilePath(const std::string &hapFilePath, std::string &fileName,
275 std::string &realPath, std::string &errMessage)
276 {
277 if (!PathToRealPath(hapFilePath, realPath)) {
278 EDMLOGE("install failed due to invalid hapFilePaths");
279 errMessage = "install failed due to invalid hapFilePaths";
280 return EdmReturnErrCode::APPLICATION_INSTALL_FAILED;
281 }
282
283 // find hap file name
284 size_t pos = realPath.find_last_of(SEPARATOR);
285 if (pos == std::string::npos || pos == realPath.size() - 1) {
286 EDMLOGE("write file to stream failed due to invalid file path");
287 errMessage = "write file to stream failed due to invalid file path";
288 return EdmReturnErrCode::APPLICATION_INSTALL_FAILED;
289 }
290 fileName = realPath.substr(pos + 1);
291 if (fileName.empty()) {
292 EDMLOGE("write file to stream failed due to invalid file path");
293 errMessage = "write file to stream failed due to invalid file path";
294 return EdmReturnErrCode::APPLICATION_INSTALL_FAILED;
295 }
296 std::string innerFilePath = HAP_DIRECTORY + SEPARATOR + fileName;
297 if ((innerFilePath.length() > PATH_MAX)) {
298 errMessage = "invalid hap file path";
299 return EdmReturnErrCode::APPLICATION_INSTALL_FAILED;
300 }
301 return ERR_OK;
302 }
303 } // namespace EDM
304 } // namespace OHOS
305