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
GetData(void * & buffer,size_t size,const void * data)38 bool BundleManagerProxy::GetData(void *&buffer, size_t size, const void *data)
39 {
40 if (data == nullptr) {
41 EDMLOGE("GetData failed due to null data");
42 return false;
43 }
44 if (size == 0 || size > EdmConstants::MAX_PARCEL_CAPACITY_OF_ASHMEM) {
45 EDMLOGE("GetData failed due to zero size");
46 return false;
47 }
48 buffer = malloc(size);
49 if (buffer == nullptr) {
50 EDMLOGE("GetData failed due to malloc buffer failed");
51 return false;
52 }
53 if (memcpy_s(buffer, size, data, size) != EOK) {
54 free(buffer);
55 EDMLOGE("GetData failed due to memcpy_s failed");
56 return false;
57 }
58 return true;
59 }
60
BundleManagerProxy()61 BundleManagerProxy::BundleManagerProxy()
62 {
63 AddPolicyTypeMap();
64 EDMLOGD("BundleManagerProxy()");
65 }
66
~BundleManagerProxy()67 BundleManagerProxy::~BundleManagerProxy()
68 {
69 EDMLOGD("~BundleManagerProxy()");
70 }
71
AddPolicyTypeMap()72 void BundleManagerProxy::AddPolicyTypeMap()
73 {
74 policyTypeMap_[static_cast<int32_t>(PolicyType::ALLOW_INSTALL)] = EdmInterfaceCode::ALLOWED_INSTALL_BUNDLES;
75 policyTypeMap_[static_cast<int32_t>(PolicyType::DISALLOW_INSTALL)] = EdmInterfaceCode::DISALLOWED_INSTALL_BUNDLES;
76 policyTypeMap_[static_cast<int32_t>(PolicyType::DISALLOW_UNINSTALL)] =
77 EdmInterfaceCode::DISALLOWED_UNINSTALL_BUNDLES;
78 }
79
GetBundleManagerProxy()80 std::shared_ptr<BundleManagerProxy> BundleManagerProxy::GetBundleManagerProxy()
81 {
82 std::call_once(flag_, []() {
83 if (instance_ == nullptr) {
84 instance_ = std::make_shared<BundleManagerProxy>();
85 }
86 });
87 return instance_;
88 }
89
Uninstall(AppExecFwk::ElementName & admin,std::string bundleName,int32_t userId,bool isKeepData,std::string & retMessage)90 int32_t BundleManagerProxy::Uninstall(AppExecFwk::ElementName &admin, std::string bundleName, int32_t userId,
91 bool isKeepData, std::string &retMessage)
92 {
93 EDMLOGD("BundleManagerProxy::Uninstall");
94 auto proxy = EnterpriseDeviceMgrProxy::GetInstance();
95 MessageParcel data;
96 MessageParcel reply;
97 data.WriteInterfaceToken(DESCRIPTOR);
98 data.WriteInt32(WITHOUT_USERID);
99 data.WriteParcelable(&admin);
100 data.WriteString(WITHOUT_PERMISSION_TAG);
101 data.WriteString(bundleName);
102 data.WriteInt32(userId);
103 data.WriteBool(isKeepData);
104 std::uint32_t funcCode = POLICY_FUNC_CODE((std::uint32_t)FuncOperateType::SET, EdmInterfaceCode::UNINSTALL);
105 ErrCode ret = proxy->HandleDevicePolicy(funcCode, data, reply);
106 if (ret == EdmReturnErrCode::PARAM_ERROR) {
107 retMessage = reply.ReadString();
108 }
109 return ret;
110 }
111
AddBundlesByPolicyType(AppExecFwk::ElementName & admin,std::vector<std::string> & bundles,int32_t userId,int32_t policyType)112 int32_t BundleManagerProxy::AddBundlesByPolicyType(AppExecFwk::ElementName &admin, std::vector<std::string> &bundles,
113 int32_t userId, int32_t policyType)
114 {
115 EDMLOGD("BundleManagerProxy::AddBundlesByPolicyType policyType =%{public}d", policyType);
116 auto proxy = EnterpriseDeviceMgrProxy::GetInstance();
117 MessageParcel data;
118 std::uint32_t funcCode = 0;
119 if (policyTypeMap_.find(policyType) != policyTypeMap_.end()) {
120 funcCode = POLICY_FUNC_CODE((std::uint32_t)FuncOperateType::SET, policyTypeMap_[policyType]);
121 } else {
122 EDMLOGE("can not get policy type");
123 return EdmReturnErrCode::PARAM_ERROR;
124 }
125 data.WriteInterfaceToken(DESCRIPTOR);
126 data.WriteInt32(HAS_USERID);
127 data.WriteInt32(userId);
128 data.WriteParcelable(&admin);
129 data.WriteString(WITHOUT_PERMISSION_TAG);
130 data.WriteStringVector(bundles);
131 return proxy->HandleDevicePolicy(funcCode, data);
132 }
133
RemoveBundlesByPolicyType(AppExecFwk::ElementName & admin,std::vector<std::string> & bundles,int32_t userId,int32_t policyType)134 int32_t BundleManagerProxy::RemoveBundlesByPolicyType(AppExecFwk::ElementName &admin, std::vector<std::string> &bundles,
135 int32_t userId, int32_t policyType)
136 {
137 EDMLOGD("BundleManagerProxy::RemoveBundlesByPolicyType policyType =%{public}d", policyType);
138 auto proxy = EnterpriseDeviceMgrProxy::GetInstance();
139 MessageParcel data;
140 std::uint32_t funcCode = 0;
141 if (policyTypeMap_.find(policyType) != policyTypeMap_.end()) {
142 funcCode = POLICY_FUNC_CODE((std::uint32_t)FuncOperateType::REMOVE, policyTypeMap_[policyType]);
143 } else {
144 EDMLOGE("can not get policy type");
145 return EdmReturnErrCode::PARAM_ERROR;
146 }
147 data.WriteInterfaceToken(DESCRIPTOR);
148 data.WriteInt32(HAS_USERID);
149 data.WriteInt32(userId);
150 data.WriteParcelable(&admin);
151 data.WriteString(WITHOUT_PERMISSION_TAG);
152 data.WriteStringVector(bundles);
153 return proxy->HandleDevicePolicy(funcCode, data);
154 }
155
GetBundlesByPolicyType(AppExecFwk::ElementName & admin,int32_t userId,std::vector<std::string> & bundles,int32_t policyType)156 int32_t BundleManagerProxy::GetBundlesByPolicyType(AppExecFwk::ElementName &admin, int32_t userId,
157 std::vector<std::string> &bundles, int32_t policyType)
158 {
159 EDMLOGD("BundleManagerProxy::GetAllowedOrDisallowedInstallBundles policyType =%{public}d", policyType);
160 auto proxy = EnterpriseDeviceMgrProxy::GetInstance();
161 MessageParcel data;
162 MessageParcel reply;
163 data.WriteInterfaceToken(DESCRIPTOR);
164 data.WriteInt32(HAS_USERID);
165 data.WriteInt32(userId);
166 data.WriteString(WITHOUT_PERMISSION_TAG);
167 data.WriteInt32(HAS_ADMIN);
168 data.WriteParcelable(&admin);
169 if (policyTypeMap_.find(policyType) != policyTypeMap_.end()) {
170 proxy->GetPolicy(policyTypeMap_[policyType], data, reply);
171 } else {
172 EDMLOGE("can not get policy type");
173 return EdmReturnErrCode::PARAM_ERROR;
174 }
175 int32_t ret = ERR_INVALID_VALUE;
176 bool blRes = reply.ReadInt32(ret) && (ret == ERR_OK);
177 if (!blRes) {
178 EDMLOGW("EnterpriseDeviceMgrProxy:GetPolicy fail. %{public}d", ret);
179 return ret;
180 }
181 reply.ReadStringVector(&bundles);
182 return ERR_OK;
183 }
184
Install(AppExecFwk::ElementName & admin,std::vector<std::string> & hapFilePaths,AppExecFwk::InstallParam & installParam,std::string & errMessage)185 int32_t BundleManagerProxy::Install(AppExecFwk::ElementName &admin, std::vector<std::string> &hapFilePaths,
186 AppExecFwk::InstallParam &installParam, std::string &errMessage)
187 {
188 EDMLOGD("BundleManagerProxy::install");
189
190 if (hapFilePaths.empty()) {
191 EDMLOGE("install failed due to empty hapFilePaths");
192 return EdmReturnErrCode::PARAM_ERROR;
193 }
194 std::vector<std::string> realPaths;
195 for (auto const &hapFilePath : hapFilePaths) {
196 ErrCode res = WriteFileToStream(admin, hapFilePath, realPaths, errMessage);
197 if (res != ERR_OK) {
198 EDMLOGE("WriteFileToStream failed");
199 return res;
200 }
201 }
202
203 auto proxy = EnterpriseDeviceMgrProxy::GetInstance();
204 MessageParcel data;
205 MessageParcel reply;
206 data.WriteInterfaceToken(DESCRIPTOR);
207 data.WriteInt32(WITHOUT_USERID);
208 data.WriteParcelable(&admin);
209 data.WriteString(WITHOUT_PERMISSION_TAG);
210 data.WriteStringVector(realPaths);
211 MessageParcelUtils::WriteInstallParam(installParam, data);
212 std::uint32_t funcCode = POLICY_FUNC_CODE((std::uint32_t)FuncOperateType::SET, EdmInterfaceCode::INSTALL);
213 ErrCode ret = proxy->HandleDevicePolicy(funcCode, data, reply);
214 if (ret == EdmReturnErrCode::APPLICATION_INSTALL_FAILED) {
215 errMessage = reply.ReadString();
216 EDMLOGE("Install failed");
217 }
218 return ret;
219 }
220
WriteFileToInner(MessageParcel & reply,const std::string & realPath,std::vector<std::string> & servicePaths,std::string & errMessage)221 ErrCode BundleManagerProxy::WriteFileToInner(MessageParcel &reply, const std::string &realPath,
222 std::vector<std::string> &servicePaths, std::string &errMessage)
223 {
224 int32_t sharedFd = reply.ReadFileDescriptor();
225 servicePaths.emplace_back(reply.ReadString());
226 if (sharedFd < 0) {
227 EDMLOGE("write file to stream failed due to invalid file descriptor");
228 errMessage = "write file to stream failed due to invalid file descriptor";
229 return EdmReturnErrCode::APPLICATION_INSTALL_FAILED;
230 }
231 int32_t outputFd = dup(sharedFd);
232 close(sharedFd);
233
234 int32_t inputFd = open(realPath.c_str(), O_RDONLY);
235 if (inputFd < 0) {
236 close(outputFd);
237 EDMLOGE("write file to stream failed due to open the hap file");
238 errMessage = "write file to stream failed due to open the hap file";
239 return EdmReturnErrCode::APPLICATION_INSTALL_FAILED;
240 }
241 off_t offset = 0;
242 struct stat stat_buff;
243 if (fstat(inputFd, &stat_buff) != 0) {
244 EDMLOGE("fstat file failed!");
245 close(outputFd);
246 close(inputFd);
247 return EdmReturnErrCode::APPLICATION_INSTALL_FAILED;
248 }
249
250 if (sendfile(outputFd, inputFd, &offset, stat_buff.st_size) == -1) {
251 EDMLOGE("send file failed!");
252 close(outputFd);
253 close(inputFd);
254 return EdmReturnErrCode::APPLICATION_INSTALL_FAILED;
255 }
256
257 close(inputFd);
258 fsync(outputFd);
259 close(outputFd);
260 return ERR_OK;
261 }
262
WriteFileToStream(AppExecFwk::ElementName & admin,const std::string & hapFilePath,std::vector<std::string> & servicePaths,std::string & errMessage)263 ErrCode BundleManagerProxy::WriteFileToStream(AppExecFwk::ElementName &admin, const std::string &hapFilePath,
264 std::vector<std::string> &servicePaths, std::string &errMessage)
265 {
266 std::string fileName;
267 std::string realPath;
268 ErrCode checkRet = checkHapFilePath(hapFilePath, fileName, realPath, errMessage);
269 if (checkRet != ERR_OK) {
270 return checkRet;
271 }
272
273 auto proxy = EnterpriseDeviceMgrProxy::GetInstance();
274 MessageParcel data;
275 MessageParcel reply;
276 data.WriteInterfaceToken(DESCRIPTOR);
277 data.WriteInt32(WITHOUT_USERID);
278 data.WriteString(WITHOUT_PERMISSION_TAG);
279 data.WriteInt32(HAS_ADMIN);
280 data.WriteParcelable(&admin);
281 data.WriteString(fileName);
282 proxy->GetPolicy(POLICY_FUNC_CODE((std::uint32_t)FuncOperateType::GET, EdmInterfaceCode::INSTALL), data, reply);
283 int32_t ret = ERR_INVALID_VALUE;
284 bool blRes = reply.ReadInt32(ret) && (ret == ERR_OK);
285 if (!blRes) {
286 EDMLOGW("BundleManagerProxy:WriteFileToStream fail. %{public}d", ret);
287 errMessage = reply.ReadString();
288 return ret;
289 }
290 if (WriteFileToInner(reply, realPath, servicePaths, errMessage) != ERR_OK) {
291 EDMLOGE("write file to stream failed");
292 return EdmReturnErrCode::APPLICATION_INSTALL_FAILED;
293 }
294 return ERR_OK;
295 }
296
checkHapFilePath(const std::string & hapFilePath,std::string & fileName,std::string & realPath,std::string & errMessage)297 ErrCode BundleManagerProxy::checkHapFilePath(const std::string &hapFilePath, std::string &fileName,
298 std::string &realPath, std::string &errMessage)
299 {
300 if (!PathToRealPath(hapFilePath, realPath)) {
301 EDMLOGE("install failed due to invalid hapFilePaths");
302 errMessage = "install failed due to invalid hapFilePaths";
303 return EdmReturnErrCode::APPLICATION_INSTALL_FAILED;
304 }
305
306 // find hap file name
307 size_t pos = realPath.find_last_of(SEPARATOR);
308 if (pos == std::string::npos || pos == realPath.size() - 1) {
309 EDMLOGE("write file to stream failed due to invalid file path");
310 errMessage = "write file to stream failed due to invalid file path";
311 return EdmReturnErrCode::APPLICATION_INSTALL_FAILED;
312 }
313 fileName = realPath.substr(pos + 1);
314 if (fileName.empty()) {
315 EDMLOGE("write file to stream failed due to invalid file path");
316 errMessage = "write file to stream failed due to invalid file path";
317 return EdmReturnErrCode::APPLICATION_INSTALL_FAILED;
318 }
319 std::string innerFilePath = HAP_DIRECTORY + SEPARATOR + fileName;
320 if ((innerFilePath.length() > PATH_MAX)) {
321 errMessage = "invalid hap file path";
322 return EdmReturnErrCode::APPLICATION_INSTALL_FAILED;
323 }
324 return ERR_OK;
325 }
326
GetInstalledBundleInfoList(AppExecFwk::ElementName & admin,int32_t userId,std::vector<EdmBundleInfo> & bundleInfos)327 int32_t BundleManagerProxy::GetInstalledBundleInfoList(AppExecFwk::ElementName &admin, int32_t userId,
328 std::vector<EdmBundleInfo> &bundleInfos)
329 {
330 MessageParcel data;
331 MessageParcel reply;
332 data.WriteInterfaceToken(DESCRIPTOR);
333 data.WriteInt32(HAS_USERID);
334 data.WriteInt32(userId);
335 data.WriteString(WITHOUT_PERMISSION_TAG);
336 data.WriteInt32(HAS_ADMIN);
337 data.WriteParcelable(&admin);
338 EnterpriseDeviceMgrProxy::GetInstance()->GetPolicy(EdmInterfaceCode::GET_BUNDLE_INFO_LIST, data, reply);
339 int32_t ret = ERR_INVALID_VALUE;
340 bool blRes = reply.ReadInt32(ret) && (ret == ERR_OK);
341 if (!blRes) {
342 EDMLOGE("BundleManagerProxy:GetPolicy fail. %{public}d", ret);
343 return ret;
344 }
345 return InnerGetVectorFromParcelIntelligent(reply, bundleInfos);
346 }
347
AddOrRemoveInstallationAllowedAppDistributionTypes(MessageParcel & data,FuncOperateType operateType)348 int32_t BundleManagerProxy::AddOrRemoveInstallationAllowedAppDistributionTypes(MessageParcel &data,
349 FuncOperateType operateType)
350 {
351 EDMLOGD("BluetoothManagerProxy::AddOrRemoveAllowedInstallAppDistributionTypes");
352 std::uint32_t funcCode = POLICY_FUNC_CODE((std::uint32_t)operateType, EdmInterfaceCode::ALLOWED_INSTALL_APP_TYPE);
353 return EnterpriseDeviceMgrProxy::GetInstance()->HandleDevicePolicy(funcCode, data);
354 }
355
GetInstallationAllowedAppDistributionTypes(MessageParcel & data,std::vector<int32_t> & installationAllowedAppDistributionTypes)356 int32_t BundleManagerProxy::GetInstallationAllowedAppDistributionTypes(MessageParcel &data,
357 std::vector<int32_t> &installationAllowedAppDistributionTypes)
358 {
359 EDMLOGD("BundleManagerProxy::GetInstallationAllowedAppDistributionTypes");
360 MessageParcel reply;
361 EnterpriseDeviceMgrProxy::GetInstance()->GetPolicy(EdmInterfaceCode::ALLOWED_INSTALL_APP_TYPE, data, reply);
362 int32_t ret = ERR_INVALID_VALUE;
363 bool blRes = reply.ReadInt32(ret) && (ret == ERR_OK);
364 if (!blRes) {
365 EDMLOGW("EnterpriseDeviceMgrProxy:GetPolicy fail. %{public}d", ret);
366 return ret;
367 }
368 reply.ReadInt32Vector(&installationAllowedAppDistributionTypes);
369 return ERR_OK;
370 }
371
InnerGetVectorFromParcelIntelligent(MessageParcel & reply,std::vector<EdmBundleInfo> & parcelableInfos)372 ErrCode BundleManagerProxy::InnerGetVectorFromParcelIntelligent(MessageParcel &reply,
373 std::vector<EdmBundleInfo> &parcelableInfos)
374 {
375 size_t dataSize = static_cast<size_t>(reply.ReadInt32());
376 if (dataSize == 0) {
377 EDMLOGI("Parcel no data");
378 return ERR_OK;
379 }
380
381 void *buffer = nullptr;
382 if (dataSize > EdmConstants::MAX_IPC_RAWDATA_SIZE) {
383 EDMLOGI("dataSize is too large, use ashmem");
384 if (GetParcelInfoFromAshMem(reply, buffer) != ERR_OK) {
385 EDMLOGE("read data from ashmem fail, length %{public}zu", dataSize);
386 return EdmReturnErrCode::SYSTEM_ABNORMALLY;
387 }
388 } else {
389 if (!GetData(buffer, dataSize, reply.ReadRawData(dataSize))) {
390 EDMLOGE("Fail read raw data length %{public}zu", dataSize);
391 return EdmReturnErrCode::SYSTEM_ABNORMALLY;
392 }
393 }
394
395 MessageParcel tempParcel;
396 if (!tempParcel.ParseFrom(reinterpret_cast<uintptr_t>(buffer), dataSize)) {
397 EDMLOGE("Fail to ParseFrom");
398 return EdmReturnErrCode::SYSTEM_ABNORMALLY;
399 }
400
401 int32_t infoSize = tempParcel.ReadInt32();
402 if (!ContainerSecurityVerify(tempParcel, infoSize, parcelableInfos)) {
403 EDMLOGE("security verify failed");
404 return EdmReturnErrCode::SYSTEM_ABNORMALLY;
405 }
406 for (int32_t i = 0; i < infoSize; i++) {
407 std::unique_ptr<EdmBundleInfo> info(tempParcel.ReadParcelable<EdmBundleInfo>());
408 if (info == nullptr) {
409 EDMLOGE("Read Parcelable infos failed");
410 return EdmReturnErrCode::SYSTEM_ABNORMALLY;
411 }
412 parcelableInfos.emplace_back(*info);
413 }
414
415 return ERR_OK;
416 }
417
GetParcelInfoFromAshMem(MessageParcel & reply,void * & data)418 ErrCode BundleManagerProxy::GetParcelInfoFromAshMem(MessageParcel &reply, void *&data)
419 {
420 sptr<Ashmem> ashMem = reply.ReadAshmem();
421 if (ashMem == nullptr) {
422 EDMLOGE("Ashmem is nullptr");
423 return EdmReturnErrCode::SYSTEM_ABNORMALLY;
424 }
425
426 if (!ashMem->MapReadOnlyAshmem()) {
427 EDMLOGE("MapReadOnlyAshmem failed");
428 return EdmReturnErrCode::SYSTEM_ABNORMALLY;
429 }
430 int32_t ashMemSize = ashMem->GetAshmemSize();
431 int32_t offset = 0;
432 const void* ashDataPtr = ashMem->ReadFromAshmem(ashMemSize, offset);
433 if (ashDataPtr == nullptr) {
434 EDMLOGE("ashDataPtr is nullptr");
435 return EdmReturnErrCode::SYSTEM_ABNORMALLY;
436 }
437 if ((ashMemSize == 0) || ashMemSize > static_cast<int32_t>(EdmConstants::MAX_PARCEL_CAPACITY_OF_ASHMEM)) {
438 EDMLOGE("failed due to wrong size");
439 return EdmReturnErrCode::SYSTEM_ABNORMALLY;
440 }
441 data = malloc(ashMemSize);
442 if (data == nullptr) {
443 EDMLOGE("failed due to malloc data failed");
444 return EdmReturnErrCode::SYSTEM_ABNORMALLY;
445 }
446 if (memcpy_s(data, ashMemSize, ashDataPtr, ashMemSize) != EOK) {
447 free(data);
448 EDMLOGE("failed due to memcpy_s failed");
449 return EdmReturnErrCode::SYSTEM_ABNORMALLY;
450 }
451 return ERR_OK;
452 }
453
ContainerSecurityVerify(MessageParcel & parcel,int32_t infoSize,std::vector<EdmBundleInfo> & parcelables)454 bool BundleManagerProxy::ContainerSecurityVerify(MessageParcel &parcel, int32_t infoSize,
455 std::vector<EdmBundleInfo> &parcelables)
456 {
457 size_t readAbleDataSize = parcel.GetReadableBytes();
458 size_t readSize = static_cast<size_t>(infoSize);
459 if ((readSize > readAbleDataSize) || (parcelables.max_size() < readSize)) {
460 EDMLOGE("Failed to read container, readSize = %{public}zu, readAbleDataSize = %{public}zu",
461 readSize, readAbleDataSize);
462 return false;
463 }
464 return true;
465 }
466 } // namespace EDM
467 } // namespace OHOS
468