• 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 
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