• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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