• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 "account_stub.h"
17 
18 #include <dlfcn.h>
19 #include <ipc_types.h>
20 #include "accesstoken_kit.h"
21 #include "account_error_no.h"
22 #include "account_helper_data.h"
23 #include "account_info.h"
24 #include "account_info_parcel.h"
25 #include "account_log_wrapper.h"
26 #include "account_mgr_service.h"
27 #include "bundle_manager_adapter.h"
28 #include "hisysevent_adapter.h"
29 #include "if_system_ability_manager.h"
30 #include "ipc_skeleton.h"
31 #include "iservice_registry.h"
32 #include "ohos_account_kits.h"
33 
34 namespace OHOS {
35 namespace AccountSA {
36 namespace {
37 const std::string OHOS_ACCOUNT_QUIT_TIPS_TITLE = "";
38 const std::string OHOS_ACCOUNT_QUIT_TIPS_CONTENT = "";
39 const std::string PERMISSION_MANAGE_USERS = "ohos.permission.MANAGE_LOCAL_ACCOUNTS";
40 const std::string PERMISSION_MANAGE_DISTRIBUTED_ACCOUNTS = "ohos.permission.MANAGE_DISTRIBUTED_ACCOUNTS";
41 const std::string PERMISSION_GET_DISTRIBUTED_ACCOUNTS = "ohos.permission.GET_DISTRIBUTED_ACCOUNTS";
42 const std::string PERMISSION_DISTRIBUTED_DATASYNC = "ohos.permission.DISTRIBUTED_DATASYNC";
43 constexpr std::int32_t ROOT_UID = 0;
44 constexpr std::int32_t DLP_UID = 3019;
45 constexpr std::int32_t DLP_CREDENTIAL_SA_UID = 3553;
46 #ifdef USE_MUSL
47 constexpr std::int32_t DSOFTBUS_UID = 1024;
48 #else
49 constexpr std::int32_t DSOFTBUS_UID = 5533;
50 #endif
51 }  // namespace
52 const std::map<std::uint32_t, AccountStubFunc> AccountStub::stubFuncMap_{
53     std::make_pair(UPDATE_OHOS_ACCOUNT_INFO, &AccountStub::CmdUpdateOhosAccountInfo),
54     std::make_pair(SET_OHOS_ACCOUNT_INFO, &AccountStub::CmdSetOhosAccountInfo),
55     std::make_pair(QUERY_OHOS_ACCOUNT_INFO, &AccountStub::CmdQueryOhosAccountInfo),
56     std::make_pair(GET_OHOS_ACCOUNT_INFO, &AccountStub::CmdGetOhosAccountInfo),
57     std::make_pair(QUERY_OHOS_ACCOUNT_QUIT_TIPS, &AccountStub::CmdQueryOhosQuitTips),
58     std::make_pair(QUERY_OHOS_ACCOUNT_INFO_BY_USER_ID, &AccountStub::CmdQueryOhosAccountInfoByUserId),
59     std::make_pair(GET_OHOS_ACCOUNT_INFO_BY_USER_ID, &AccountStub::CmdGetOhosAccountInfoByUserId),
60     std::make_pair(QUERY_DEVICE_ACCOUNT_ID, &AccountStub::CmdQueryDeviceAccountId),
61     std::make_pair(GET_APP_ACCOUNT_SERVICE, &AccountStub::CmdGetAppAccountService),
62     std::make_pair(GET_OS_ACCOUNT_SERVICE, &AccountStub::CmdGetOsAccountService),
63     std::make_pair(GET_ACCOUNT_IAM_SERVICE, &AccountStub::CmdGetAccountIAMService),
64     std::make_pair(GET_DOMAIN_ACCOUNT_SERVICE, &AccountStub::CmdGetDomainAccountService),
65 };
66 
InnerUpdateOhosAccountInfo(MessageParcel & data,MessageParcel & reply)67 std::int32_t AccountStub::InnerUpdateOhosAccountInfo(MessageParcel &data, MessageParcel &reply)
68 {
69     // ignore the real account name
70     const std::string accountName = Str16ToStr8(data.ReadString16());
71     if (accountName.empty()) {
72         ACCOUNT_LOGE("empty account name!");
73         return ERR_ACCOUNT_ZIDL_ACCOUNT_STUB_ERROR;
74     }
75     const std::string uid = Str16ToStr8(data.ReadString16());
76     if (uid.empty()) {
77         ACCOUNT_LOGE("empty uid!");
78         return ERR_ACCOUNT_ZIDL_ACCOUNT_STUB_ERROR;
79     }
80     const std::string eventStr = Str16ToStr8(data.ReadString16());
81 
82     std::int32_t ret = ERR_OK;
83     bool result = UpdateOhosAccountInfo(accountName, uid, eventStr);
84     if (!result) {
85         ACCOUNT_LOGE("Update ohos account info failed");
86         ret = ERR_ACCOUNT_ZIDL_ACCOUNT_STUB_ERROR;
87     }
88     if (!reply.WriteInt32(ret)) {
89         ACCOUNT_LOGE("Write result data failed");
90         ret = ERR_ACCOUNT_ZIDL_WRITE_RESULT_ERROR;
91     }
92     return ret;
93 }
94 
InnerSetOhosAccountInfo(MessageParcel & data,MessageParcel & reply)95 std::int32_t AccountStub::InnerSetOhosAccountInfo(MessageParcel &data, MessageParcel &reply)
96 {
97     OhosAccountInfo info;
98     std::int32_t ret = ReadOhosAccountInfo(data, info);
99     if (ret != ERR_OK) {
100         return ret;
101     }
102     if (!info.IsValid()) {
103         ACCOUNT_LOGE("Check OhosAccountInfo failed");
104         return ERR_OHOSACCOUNT_KIT_INVALID_PARAMETER;
105     }
106     // ignore the real account name
107     const std::string eventStr = Str16ToStr8(data.ReadString16());
108 
109     ret = SetOhosAccountInfo(info, eventStr);
110     if (ret != ERR_OK) {
111         ACCOUNT_LOGE("Set ohos account info failed");
112         ret = ERR_ACCOUNT_ZIDL_ACCOUNT_STUB_ERROR;
113     }
114     if (!reply.WriteInt32(ret)) {
115         ACCOUNT_LOGE("Write result data failed");
116         ret = ERR_ACCOUNT_ZIDL_WRITE_RESULT_ERROR;
117     }
118     return ret;
119 }
120 
CmdUpdateOhosAccountInfo(MessageParcel & data,MessageParcel & reply)121 std::int32_t AccountStub::CmdUpdateOhosAccountInfo(MessageParcel &data, MessageParcel &reply)
122 {
123     if (!HasAccountRequestPermission(PERMISSION_MANAGE_USERS)) {
124         ACCOUNT_LOGE("Check permission failed");
125         return ERR_ACCOUNT_ZIDL_CHECK_PERMISSION_ERROR;
126     }
127 
128     return InnerUpdateOhosAccountInfo(data, reply);
129 }
130 
CmdSetOhosAccountInfo(MessageParcel & data,MessageParcel & reply)131 std::int32_t AccountStub::CmdSetOhosAccountInfo(MessageParcel &data, MessageParcel &reply)
132 {
133     if (!HasAccountRequestPermission(PERMISSION_MANAGE_DISTRIBUTED_ACCOUNTS)) {
134         ACCOUNT_LOGE("Check permission failed");
135         return ERR_ACCOUNT_ZIDL_CHECK_PERMISSION_ERROR;
136     }
137 
138     return InnerSetOhosAccountInfo(data, reply);
139 }
140 
InnerQueryOhosAccountInfo(MessageParcel & data,MessageParcel & reply)141 std::int32_t AccountStub::InnerQueryOhosAccountInfo(MessageParcel &data, MessageParcel &reply)
142 {
143     std::pair<bool, OhosAccountInfo> info = QueryOhosAccountInfo();
144     if (!info.first) {
145         ACCOUNT_LOGE("Query ohos account info failed");
146         return ERR_ACCOUNT_ZIDL_ACCOUNT_STUB_ERROR;
147     }
148 
149     std::string name = info.second.name_;
150     std::string id = info.second.uid_;
151     if (!reply.WriteString16(Str8ToStr16(name))) {
152         ACCOUNT_LOGE("Write name data failed");
153         return ERR_ACCOUNT_ZIDL_WRITE_NAME_ERROR;
154     }
155     if (!reply.WriteString16(Str8ToStr16(id))) {
156         ACCOUNT_LOGE("Write id data failed");
157         return ERR_ACCOUNT_ZIDL_WRITE_UID_ERROR;
158     }
159     if (!reply.WriteInt32(info.second.status_)) {
160         ACCOUNT_LOGE("Write status data failed");
161         return ERR_ACCOUNT_ZIDL_WRITE_ACCOUNT_STATUS_ERROR;
162     }
163     return ERR_OK;
164 }
165 
InnerGetOhosAccountInfo(MessageParcel & data,MessageParcel & reply)166 std::int32_t AccountStub::InnerGetOhosAccountInfo(MessageParcel &data, MessageParcel &reply)
167 {
168     OhosAccountInfo ohosAccountInfo;
169     int ret = GetOhosAccountInfo(ohosAccountInfo);
170     ohosAccountInfo.SetRawUid("");
171     if (ret != ERR_OK) {
172         ACCOUNT_LOGE("Get ohos account info failed");
173         return ERR_ACCOUNT_ZIDL_ACCOUNT_STUB_ERROR;
174     }
175     if (!WriteOhosAccountInfo(reply, ohosAccountInfo)) {
176         ACCOUNT_LOGE("Write ohosAccountInfo failed!");
177         return ERR_ACCOUNT_COMMON_WRITE_PARCEL_ERROR;
178     }
179     return ERR_OK;
180 }
181 
CmdQueryOhosAccountInfo(MessageParcel & data,MessageParcel & reply)182 std::int32_t AccountStub::CmdQueryOhosAccountInfo(MessageParcel &data, MessageParcel &reply)
183 {
184     if (!HasAccountRequestPermission(PERMISSION_MANAGE_USERS) &&
185         !HasAccountRequestPermission(PERMISSION_DISTRIBUTED_DATASYNC)) {
186         ACCOUNT_LOGE("Check permission failed");
187         return ERR_ACCOUNT_ZIDL_CHECK_PERMISSION_ERROR;
188     }
189 
190     return InnerQueryOhosAccountInfo(data, reply);
191 }
192 
CmdGetOhosAccountInfo(MessageParcel & data,MessageParcel & reply)193 ErrCode AccountStub::CmdGetOhosAccountInfo(MessageParcel &data, MessageParcel &reply)
194 {
195     if (!HasAccountRequestPermission(PERMISSION_MANAGE_DISTRIBUTED_ACCOUNTS) &&
196         !HasAccountRequestPermission(PERMISSION_DISTRIBUTED_DATASYNC) &&
197         !HasAccountRequestPermission(PERMISSION_GET_DISTRIBUTED_ACCOUNTS)) {
198         ACCOUNT_LOGE("Check permission failed");
199         return ERR_ACCOUNT_ZIDL_CHECK_PERMISSION_ERROR;
200     }
201 
202     return InnerGetOhosAccountInfo(data, reply);
203 }
204 
CmdGetOhosAccountInfoByUserId(MessageParcel & data,MessageParcel & reply)205 ErrCode AccountStub::CmdGetOhosAccountInfoByUserId(MessageParcel &data, MessageParcel &reply)
206 {
207     if (!HasAccountRequestPermission(PERMISSION_MANAGE_DISTRIBUTED_ACCOUNTS) &&
208         !HasAccountRequestPermission(PERMISSION_DISTRIBUTED_DATASYNC) &&
209         !HasAccountRequestPermission(PERMISSION_GET_DISTRIBUTED_ACCOUNTS)) {
210         ACCOUNT_LOGE("Check permission failed");
211         return ERR_ACCOUNT_ZIDL_CHECK_PERMISSION_ERROR;
212     }
213     std::int32_t userId = data.ReadInt32();
214     OhosAccountInfo ohosAccountInfo;
215     ErrCode ret = GetOhosAccountInfoByUserId(userId, ohosAccountInfo);
216     if (ret != ERR_OK) {
217         ACCOUNT_LOGE("Get ohos account info failed");
218         return ret;
219     }
220     int32_t uid = IPCSkeleton::GetCallingUid();
221     if ((uid != DLP_UID) && (uid != DLP_CREDENTIAL_SA_UID)) {
222         ohosAccountInfo.SetRawUid("");
223     }
224     if (!WriteOhosAccountInfo(reply, ohosAccountInfo)) {
225         ACCOUNT_LOGE("Write ohosAccountInfo failed!");
226         return ERR_ACCOUNT_COMMON_WRITE_PARCEL_ERROR;
227     }
228     return ERR_OK;
229 }
230 
CmdQueryOhosAccountInfoByUserId(MessageParcel & data,MessageParcel & reply)231 std::int32_t AccountStub::CmdQueryOhosAccountInfoByUserId(MessageParcel &data, MessageParcel &reply)
232 {
233     if ((!HasAccountRequestPermission(PERMISSION_MANAGE_USERS)) &&
234         (!HasAccountRequestPermission(PERMISSION_DISTRIBUTED_DATASYNC)) &&
235         (IPCSkeleton::GetCallingUid() != DSOFTBUS_UID)) {
236         ACCOUNT_LOGE("Check permission failed");
237         return ERR_ACCOUNT_ZIDL_CHECK_PERMISSION_ERROR;
238     }
239 
240     std::int32_t userId = data.ReadInt32();
241     if (userId < 0) {
242         ACCOUNT_LOGE("negative userID %{public}d detected!", userId);
243         return ERR_ACCOUNT_ZIDL_ACCOUNT_STUB_USERID_ERROR;
244     }
245 
246     std::pair<bool, OhosAccountInfo> info = QueryOhosAccountInfoByUserId(userId);
247     if (!info.first) {
248         ACCOUNT_LOGE("Query ohos account info failed! userId %{public}d.", userId);
249         return ERR_ACCOUNT_ZIDL_ACCOUNT_STUB_ERROR;
250     }
251 
252     std::string name = info.second.name_;
253     std::string id = info.second.uid_;
254     if (!reply.WriteString16(Str8ToStr16(name))) {
255         ACCOUNT_LOGE("Write name data failed! userId %{public}d.", userId);
256         return ERR_ACCOUNT_ZIDL_WRITE_NAME_ERROR;
257     }
258     if (!reply.WriteString16(Str8ToStr16(id))) {
259         ACCOUNT_LOGE("Write id data failed! userId %{public}d.", userId);
260         return ERR_ACCOUNT_ZIDL_WRITE_UID_ERROR;
261     }
262     if (!reply.WriteInt32(info.second.status_)) {
263         ACCOUNT_LOGE("Write status data failed! userId %{public}d.", userId);
264         return ERR_ACCOUNT_ZIDL_WRITE_ACCOUNT_STATUS_ERROR;
265     }
266     return ERR_OK;
267 }
268 
CmdQueryOhosQuitTips(MessageParcel & data,MessageParcel & reply)269 std::int32_t AccountStub::CmdQueryOhosQuitTips(MessageParcel &data, MessageParcel &reply)
270 {
271     if (!HasAccountRequestPermission(PERMISSION_MANAGE_USERS) &&
272         !HasAccountRequestPermission(PERMISSION_DISTRIBUTED_DATASYNC)) {
273         ACCOUNT_LOGE("Check permission failed");
274         return ERR_ACCOUNT_ZIDL_CHECK_PERMISSION_ERROR;
275     }
276 
277     if (!reply.WriteString16(Str8ToStr16(OHOS_ACCOUNT_QUIT_TIPS_TITLE))) {
278         ACCOUNT_LOGE("Write quit tips title failed");
279         return ERR_ACCOUNT_ZIDL_WRITE_RESULT_ERROR;
280     }
281     if (!reply.WriteString16(Str8ToStr16(OHOS_ACCOUNT_QUIT_TIPS_CONTENT))) {
282         ACCOUNT_LOGE("Write quit tips content failed");
283         return ERR_ACCOUNT_ZIDL_WRITE_RESULT_ERROR;
284     }
285 
286     return ERR_OK;
287 }
288 
CmdQueryDeviceAccountId(MessageParcel & data,MessageParcel & reply)289 std::int32_t AccountStub::CmdQueryDeviceAccountId(MessageParcel &data, MessageParcel &reply)
290 {
291     std::int32_t id;
292     auto ret = QueryDeviceAccountId(id);
293     if (ret != ERR_OK) {
294         ACCOUNT_LOGE("QueryDevice AccountId failed: %{public}d", ret);
295         return ret;
296     }
297 
298     if (!reply.WriteInt32(id)) {
299         ACCOUNT_LOGE("Write result data failed");
300         return ERR_ACCOUNT_ZIDL_WRITE_RESULT_ERROR;
301     }
302     return ERR_OK;
303 }
304 
CmdGetAppAccountService(MessageParcel & data,MessageParcel & reply)305 std::int32_t AccountStub::CmdGetAppAccountService(MessageParcel &data, MessageParcel &reply)
306 {
307     auto remoteObject = GetAppAccountService();
308     if (!reply.WriteRemoteObject(remoteObject)) {
309         ACCOUNT_LOGE("Write result data failed");
310         return ERR_ACCOUNT_ZIDL_WRITE_RESULT_ERROR;
311     }
312 
313     return ERR_OK;
314 }
CmdGetOsAccountService(MessageParcel & data,MessageParcel & reply)315 std::int32_t AccountStub::CmdGetOsAccountService(MessageParcel &data, MessageParcel &reply)
316 {
317     auto remoteObject = GetOsAccountService();
318     if (!reply.WriteRemoteObject(remoteObject)) {
319         ACCOUNT_LOGE("Write result data failed");
320         return ERR_ACCOUNT_ZIDL_WRITE_RESULT_ERROR;
321     }
322 
323     return ERR_OK;
324 }
325 
CmdGetAccountIAMService(MessageParcel & data,MessageParcel & reply)326 std::int32_t AccountStub::CmdGetAccountIAMService(MessageParcel &data, MessageParcel &reply)
327 {
328     auto remoteObject = GetAccountIAMService();
329     if (!reply.WriteRemoteObject(remoteObject)) {
330         ACCOUNT_LOGE("Write result data failed");
331         return ERR_ACCOUNT_ZIDL_WRITE_RESULT_ERROR;
332     }
333 
334     return ERR_OK;
335 }
336 
CmdGetDomainAccountService(MessageParcel & data,MessageParcel & reply)337 std::int32_t AccountStub::CmdGetDomainAccountService(MessageParcel &data, MessageParcel &reply)
338 {
339     auto remoteObject = GetDomainAccountService();
340     if (!reply.WriteRemoteObject(remoteObject)) {
341         ACCOUNT_LOGE("failed to write remote object");
342         return ERR_ACCOUNT_ZIDL_WRITE_PARCEL_DATA_ERROR;
343     }
344     return ERR_OK;
345 }
346 
OnRemoteRequest(std::uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)347 std::int32_t AccountStub::OnRemoteRequest(
348     std::uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
349 {
350     if (!IsServiceStarted()) {
351         ACCOUNT_LOGE("account mgr not ready");
352         return ERR_ACCOUNT_ZIDL_MGR_NOT_READY_ERROR;
353     }
354 
355     if (data.ReadInterfaceToken() != GetDescriptor()) {
356         ACCOUNT_LOGE("check descriptor failed! code %{public}u.", code);
357         return ERR_ACCOUNT_COMMON_CHECK_DESCRIPTOR_ERROR;
358     }
359 
360     const auto &itFunc = stubFuncMap_.find(code);
361     if (itFunc != stubFuncMap_.end()) {
362         return (this->*(itFunc->second))(data, reply);
363     }
364 
365     ACCOUNT_LOGW("remote request unhandled: %{public}d", code);
366     return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
367 }
368 
HasAccountRequestPermission(const std::string & permissionName)369 bool AccountStub::HasAccountRequestPermission(const std::string &permissionName)
370 {
371     // check root
372     std::int32_t uid = IPCSkeleton::GetCallingUid();
373     if (uid == ROOT_UID) {
374         return true;
375     }
376 
377     // check permission
378     Security::AccessToken::AccessTokenID callingTokenID = IPCSkeleton::GetCallingTokenID();
379     if (Security::AccessToken::AccessTokenKit::VerifyAccessToken(callingTokenID, permissionName) ==
380         Security::AccessToken::TypePermissionState::PERMISSION_GRANTED) {
381         return true;
382     }
383 
384     // check trust list
385     if (CheckCallerForTrustList()) {
386         return true;
387     }
388     ReportPermissionFail(uid, IPCSkeleton::GetCallingPid(), permissionName);
389     ACCOUNT_LOGE("permission %{public}s denied!", permissionName.c_str());
390     return false;
391 }
392 
CheckCallerForTrustList()393 bool AccountStub::CheckCallerForTrustList()
394 {
395     std::string bundleName;
396     std::int32_t uid = IPCSkeleton::GetCallingUid();
397     if (!BundleManagerAdapter::GetInstance()->GetBundleNameForUid(uid, bundleName)) {
398         return false;
399     }
400 
401     std::vector<std::string> trustList = AccountHelperData::GetBundleNameTrustList();
402     if (std::find(trustList.begin(), trustList.end(), bundleName) == trustList.end()) {
403         return false;
404     }
405 
406     return true;
407 }
408 }  // namespace AccountSA
409 }  // namespace OHOS
410