1 /*
2  * Copyright (c) 2022-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 #include "privacy_manager_client.h"
16 
17 #include <algorithm>
18 #include "accesstoken_log.h"
19 #include "iservice_registry.h"
20 #include "privacy_error.h"
21 #include "privacy_manager_proxy.h"
22 #ifdef SECURITY_COMPONENT_ENHANCE_ENABLE
23 #include "sec_comp_enhance_data_parcel.h"
24 #endif
25 
26 namespace OHOS {
27 namespace Security {
28 namespace AccessToken {
29 namespace {
30 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {
31     LOG_CORE, SECURITY_DOMAIN_PRIVACY, "PrivacyManagerClient"
32 };
33 const static int32_t MAX_CALLBACK_SIZE = 200;
34 const static int32_t MAX_PERM_LIST_SIZE = 1024;
35 constexpr const char* CAMERA_PERMISSION_NAME = "ohos.permission.CAMERA";
36 std::recursive_mutex g_instanceMutex;
37 } // namespace
38 
GetInstance()39 PrivacyManagerClient& PrivacyManagerClient::GetInstance()
40 {
41     static PrivacyManagerClient* instance = nullptr;
42     if (instance == nullptr) {
43         std::lock_guard<std::recursive_mutex> lock(g_instanceMutex);
44         if (instance == nullptr) {
45             instance = new PrivacyManagerClient();
46         }
47     }
48     return *instance;
49 }
50 
PrivacyManagerClient()51 PrivacyManagerClient::PrivacyManagerClient()
52 {}
53 
~PrivacyManagerClient()54 PrivacyManagerClient::~PrivacyManagerClient()
55 {
56     ACCESSTOKEN_LOG_ERROR(LABEL, "~PrivacyManagerClient");
57     std::lock_guard<std::mutex> lock(proxyMutex_);
58     ReleaseProxy();
59 }
60 
AddPermissionUsedRecord(const AddPermParamInfo & info,bool asyncMode)61 int32_t PrivacyManagerClient::AddPermissionUsedRecord(const AddPermParamInfo& info, bool asyncMode)
62 {
63     auto proxy = GetProxy();
64     if (proxy == nullptr) {
65         ACCESSTOKEN_LOG_ERROR(LABEL, "Proxy is null.");
66         return PrivacyError::ERR_SERVICE_ABNORMAL;
67     }
68     AddPermParamInfoParcel infoParcel;
69     infoParcel.info = info;
70     return proxy->AddPermissionUsedRecord(infoParcel, asyncMode);
71 }
72 
StartUsingPermission(AccessTokenID tokenID,int32_t pid,const std::string & permissionName)73 int32_t PrivacyManagerClient::StartUsingPermission(
74     AccessTokenID tokenID, int32_t pid, const std::string& permissionName)
75 {
76     auto proxy = GetProxy();
77     if (proxy == nullptr) {
78         ACCESSTOKEN_LOG_ERROR(LABEL, "Proxy is null.");
79         return PrivacyError::ERR_SERVICE_ABNORMAL;
80     }
81     return proxy->StartUsingPermission(tokenID, pid, permissionName);
82 }
83 
CreateStateChangeCbk(uint64_t id,const std::shared_ptr<StateCustomizedCbk> & callback,sptr<StateChangeCallback> & callbackWrap)84 int32_t PrivacyManagerClient::CreateStateChangeCbk(uint64_t id,
85     const std::shared_ptr<StateCustomizedCbk>& callback, sptr<StateChangeCallback>& callbackWrap)
86 {
87     std::lock_guard<std::mutex> lock(stateCbkMutex_);
88     auto iter = stateChangeCallbackMap_.find(id);
89     if (iter != stateChangeCallbackMap_.end()) {
90         ACCESSTOKEN_LOG_ERROR(LABEL, " Callback has been used.");
91         return PrivacyError::ERR_CALLBACK_ALREADY_EXIST;
92     } else {
93         callbackWrap = new (std::nothrow) StateChangeCallback(callback);
94         if (callbackWrap == nullptr) {
95             ACCESSTOKEN_LOG_ERROR(LABEL, "Memory allocation for callbackWrap failed!");
96             return PrivacyError::ERR_MALLOC_FAILED;
97         }
98     }
99     return RET_SUCCESS;
100 }
101 
StartUsingPermission(AccessTokenID tokenId,int32_t pid,const std::string & permissionName,const std::shared_ptr<StateCustomizedCbk> & callback)102 int32_t PrivacyManagerClient::StartUsingPermission(
103     AccessTokenID tokenId, int32_t pid, const std::string& permissionName,
104     const std::shared_ptr<StateCustomizedCbk>& callback)
105 {
106     if (callback == nullptr) {
107         ACCESSTOKEN_LOG_ERROR(LABEL, "Callback is nullptr.");
108         return PrivacyError::ERR_PARAM_INVALID;
109     }
110 
111     sptr<StateChangeCallback> callbackWrap = nullptr;
112     uint64_t id = GetUniqueId(tokenId, pid);
113     int32_t result = CreateStateChangeCbk(id, callback, callbackWrap);
114     if (result != RET_SUCCESS) {
115         return result;
116     }
117 
118     auto proxy = GetProxy();
119     if (proxy == nullptr) {
120         ACCESSTOKEN_LOG_ERROR(LABEL, "Proxy is null.");
121         return PrivacyError::ERR_SERVICE_ABNORMAL;
122     }
123 
124     result = proxy->StartUsingPermission(tokenId, pid, permissionName, callbackWrap->AsObject());
125     if (result == RET_SUCCESS) {
126         std::lock_guard<std::mutex> lock(stateCbkMutex_);
127         stateChangeCallbackMap_[id] = callbackWrap;
128         ACCESSTOKEN_LOG_INFO(LABEL, "CallbackObject added.");
129     }
130     return result;
131 }
132 
StopUsingPermission(AccessTokenID tokenID,int32_t pid,const std::string & permissionName)133 int32_t PrivacyManagerClient::StopUsingPermission(
134     AccessTokenID tokenID, int32_t pid, const std::string& permissionName)
135 {
136     auto proxy = GetProxy();
137     if (proxy == nullptr) {
138         ACCESSTOKEN_LOG_ERROR(LABEL, "Proxy is null.");
139         return PrivacyError::ERR_SERVICE_ABNORMAL;
140     }
141     if (permissionName == CAMERA_PERMISSION_NAME) {
142         uint64_t id = GetUniqueId(tokenID, pid);
143         std::lock_guard<std::mutex> lock(stateCbkMutex_);
144         auto iter = stateChangeCallbackMap_.find(id);
145         if (iter != stateChangeCallbackMap_.end()) {
146             stateChangeCallbackMap_.erase(id);
147         }
148     }
149 
150     return proxy->StopUsingPermission(tokenID, pid, permissionName);
151 }
152 
RemovePermissionUsedRecords(AccessTokenID tokenID,const std::string & deviceID)153 int32_t PrivacyManagerClient::RemovePermissionUsedRecords(AccessTokenID tokenID, const std::string& deviceID)
154 {
155     auto proxy = GetProxy();
156     if (proxy == nullptr) {
157         ACCESSTOKEN_LOG_ERROR(LABEL, "Proxy is null.");
158         return PrivacyError::ERR_SERVICE_ABNORMAL;
159     }
160     return proxy->RemovePermissionUsedRecords(tokenID, deviceID);
161 }
162 
GetPermissionUsedRecords(const PermissionUsedRequest & request,PermissionUsedResult & result)163 int32_t PrivacyManagerClient::GetPermissionUsedRecords(
164     const PermissionUsedRequest& request, PermissionUsedResult& result)
165 {
166     auto proxy = GetProxy();
167     if (proxy == nullptr) {
168         ACCESSTOKEN_LOG_ERROR(LABEL, "Proxy is null.");
169         return PrivacyError::ERR_SERVICE_ABNORMAL;
170     }
171 
172     PermissionUsedRequestParcel requestParcel;
173     PermissionUsedResultParcel resultParcel;
174     requestParcel.request = request;
175     int32_t ret = proxy->GetPermissionUsedRecords(requestParcel, resultParcel);
176     result = resultParcel.result;
177     return ret;
178 }
179 
GetPermissionUsedRecords(const PermissionUsedRequest & request,const sptr<OnPermissionUsedRecordCallback> & callback)180 int32_t PrivacyManagerClient::GetPermissionUsedRecords(const PermissionUsedRequest& request,
181     const sptr<OnPermissionUsedRecordCallback>& callback)
182 {
183     auto proxy = GetProxy();
184     if (proxy == nullptr) {
185         ACCESSTOKEN_LOG_ERROR(LABEL, "Proxy is null.");
186         return PrivacyError::ERR_SERVICE_ABNORMAL;
187     }
188 
189     PermissionUsedRequestParcel requestParcel;
190     requestParcel.request = request;
191     return proxy->GetPermissionUsedRecords(requestParcel, callback);
192 }
193 
CreateActiveStatusChangeCbk(const std::shared_ptr<PermActiveStatusCustomizedCbk> & callback,sptr<PermActiveStatusChangeCallback> & callbackWrap)194 int32_t PrivacyManagerClient::CreateActiveStatusChangeCbk(
195     const std::shared_ptr<PermActiveStatusCustomizedCbk>& callback, sptr<PermActiveStatusChangeCallback>& callbackWrap)
196 {
197     std::lock_guard<std::mutex> lock(activeCbkMutex_);
198 
199     if (activeCbkMap_.size() >= MAX_CALLBACK_SIZE) {
200         return PrivacyError::ERR_CALLBACKS_EXCEED_LIMITATION;
201     }
202 
203     auto goalCallback = activeCbkMap_.find(callback);
204     if (goalCallback != activeCbkMap_.end()) {
205         return PrivacyError::ERR_CALLBACK_ALREADY_EXIST;
206     } else {
207         callbackWrap =
208             new (std::nothrow) PermActiveStatusChangeCallback(callback);
209         if (!callbackWrap) {
210             return PrivacyError::ERR_MALLOC_FAILED;
211         }
212     }
213     return RET_SUCCESS;
214 }
215 
RegisterPermActiveStatusCallback(const std::shared_ptr<PermActiveStatusCustomizedCbk> & callback)216 int32_t PrivacyManagerClient::RegisterPermActiveStatusCallback(
217     const std::shared_ptr<PermActiveStatusCustomizedCbk>& callback)
218 {
219     if (callback == nullptr) {
220         ACCESSTOKEN_LOG_ERROR(LABEL, "CustomizedCb is nullptr.");
221         return PrivacyError::ERR_PARAM_INVALID;
222     }
223 
224     sptr<PermActiveStatusChangeCallback> callbackWrap = nullptr;
225     int32_t result = CreateActiveStatusChangeCbk(callback, callbackWrap);
226     if (result != RET_SUCCESS) {
227         ACCESSTOKEN_LOG_ERROR(LABEL, "Failed to create callback, err: %{public}d.", result);
228         return result;
229     }
230 
231     auto proxy = GetProxy();
232     if (proxy == nullptr) {
233         ACCESSTOKEN_LOG_ERROR(LABEL, "Proxy is null.");
234         return PrivacyError::ERR_SERVICE_ABNORMAL;
235     }
236     std::vector<std::string> permList;
237     callback->GetPermList(permList);
238     if (permList.size() > MAX_PERM_LIST_SIZE) {
239         return PrivacyError::ERR_PARAM_INVALID;
240     }
241 
242     result = proxy->RegisterPermActiveStatusCallback(permList, callbackWrap->AsObject());
243     if (result == RET_SUCCESS) {
244         std::lock_guard<std::mutex> lock(activeCbkMutex_);
245         activeCbkMap_[callback] = callbackWrap;
246         ACCESSTOKEN_LOG_INFO(LABEL, "CallbackObject added.");
247     }
248     return result;
249 }
250 
UnRegisterPermActiveStatusCallback(const std::shared_ptr<PermActiveStatusCustomizedCbk> & callback)251 int32_t PrivacyManagerClient::UnRegisterPermActiveStatusCallback(
252     const std::shared_ptr<PermActiveStatusCustomizedCbk>& callback)
253 {
254     auto proxy = GetProxy();
255     if (proxy == nullptr) {
256         ACCESSTOKEN_LOG_ERROR(LABEL, "Proxy is null.");
257         return PrivacyError::ERR_SERVICE_ABNORMAL;
258     }
259 
260     std::lock_guard<std::mutex> lock(activeCbkMutex_);
261     auto goalCallback = activeCbkMap_.find(callback);
262     if (goalCallback == activeCbkMap_.end()) {
263         ACCESSTOKEN_LOG_ERROR(LABEL, "GoalCallback already is not exist.");
264         return PrivacyError::ERR_CALLBACK_NOT_EXIST;
265     }
266 
267     int32_t result = proxy->UnRegisterPermActiveStatusCallback(goalCallback->second->AsObject());
268     if (result == RET_SUCCESS) {
269         activeCbkMap_.erase(goalCallback);
270     }
271     return result;
272 }
273 
IsAllowedUsingPermission(AccessTokenID tokenID,const std::string & permissionName)274 bool PrivacyManagerClient::IsAllowedUsingPermission(AccessTokenID tokenID, const std::string& permissionName)
275 {
276     auto proxy = GetProxy();
277     if (proxy == nullptr) {
278         ACCESSTOKEN_LOG_ERROR(LABEL, "Proxy is null.");
279         return false;
280     }
281     return proxy->IsAllowedUsingPermission(tokenID, permissionName);
282 }
283 
284 #ifdef SECURITY_COMPONENT_ENHANCE_ENABLE
RegisterSecCompEnhance(const SecCompEnhanceData & enhance)285 int32_t PrivacyManagerClient::RegisterSecCompEnhance(const SecCompEnhanceData& enhance)
286 {
287     auto proxy = GetProxy();
288     if (proxy == nullptr) {
289         ACCESSTOKEN_LOG_ERROR(LABEL, "Proxy is null.");
290         return PrivacyError::ERR_PARAM_INVALID;
291     }
292     SecCompEnhanceDataParcel registerParcel;
293     registerParcel.enhanceData = enhance;
294     return proxy->RegisterSecCompEnhance(registerParcel);
295 }
296 
UpdateSecCompEnhance(int32_t pid,uint32_t seqNum)297 int32_t PrivacyManagerClient::UpdateSecCompEnhance(int32_t pid, uint32_t seqNum)
298 {
299     auto proxy = GetProxy();
300     if (proxy == nullptr) {
301         ACCESSTOKEN_LOG_ERROR(LABEL, "Proxy is null.");
302         return PrivacyError::ERR_PARAM_INVALID;
303     }
304     return proxy->UpdateSecCompEnhance(pid, seqNum);
305 }
306 
GetSecCompEnhance(int32_t pid,SecCompEnhanceData & enhance)307 int32_t PrivacyManagerClient::GetSecCompEnhance(int32_t pid, SecCompEnhanceData& enhance)
308 {
309     auto proxy = GetProxy();
310     if (proxy == nullptr) {
311         ACCESSTOKEN_LOG_ERROR(LABEL, "Proxy is null.");
312         return PrivacyError::ERR_PARAM_INVALID;
313     }
314     SecCompEnhanceDataParcel parcel;
315     int32_t res = proxy->GetSecCompEnhance(pid, parcel);
316     if (res != RET_SUCCESS) {
317         return res;
318     }
319     enhance = parcel.enhanceData;
320     return RET_SUCCESS;
321 }
322 
GetSpecialSecCompEnhance(const std::string & bundleName,std::vector<SecCompEnhanceData> & enhanceList)323 int32_t PrivacyManagerClient::GetSpecialSecCompEnhance(const std::string& bundleName,
324     std::vector<SecCompEnhanceData>& enhanceList)
325 {
326     auto proxy = GetProxy();
327     if (proxy == nullptr) {
328         ACCESSTOKEN_LOG_ERROR(LABEL, "Proxy is null.");
329         return PrivacyError::ERR_PARAM_INVALID;
330     }
331     std::vector<SecCompEnhanceDataParcel> parcelList;
332     int32_t res = proxy->GetSpecialSecCompEnhance(bundleName, parcelList);
333     if (res != RET_SUCCESS) {
334         return res;
335     }
336 
337     std::transform(parcelList.begin(), parcelList.end(), std::back_inserter(enhanceList),
338         [](SecCompEnhanceDataParcel pair) { return pair.enhanceData; });
339     return RET_SUCCESS;
340 }
341 #endif
342 
GetPermissionUsedTypeInfos(const AccessTokenID tokenId,const std::string & permissionName,std::vector<PermissionUsedTypeInfo> & results)343 int32_t PrivacyManagerClient::GetPermissionUsedTypeInfos(const AccessTokenID tokenId, const std::string& permissionName,
344     std::vector<PermissionUsedTypeInfo>& results)
345 {
346     auto proxy = GetProxy();
347     if (proxy == nullptr) {
348         ACCESSTOKEN_LOG_ERROR(LABEL, "Proxy is null.");
349         return PrivacyError::ERR_SERVICE_ABNORMAL;
350     }
351 
352     std::vector<PermissionUsedTypeInfoParcel> resultsParcel;
353     int32_t res = proxy->GetPermissionUsedTypeInfos(tokenId, permissionName, resultsParcel);
354     if (res != RET_SUCCESS) {
355         return res;
356     }
357 
358     std::transform(resultsParcel.begin(), resultsParcel.end(), std::back_inserter(results),
359         [](PermissionUsedTypeInfoParcel parcel) { return parcel.info; });
360     return RET_SUCCESS;
361 }
362 
SetMutePolicy(uint32_t policyType,uint32_t callerType,bool isMute)363 int32_t PrivacyManagerClient::SetMutePolicy(uint32_t policyType, uint32_t callerType, bool isMute)
364 {
365     auto proxy = GetProxy();
366     if (proxy == nullptr) {
367         ACCESSTOKEN_LOG_ERROR(LABEL, "Proxy is null.");
368         return PrivacyError::ERR_SERVICE_ABNORMAL;
369     }
370     return proxy->SetMutePolicy(policyType, callerType, isMute);
371 }
372 
SetHapWithFGReminder(uint32_t tokenId,bool isAllowed)373 int32_t PrivacyManagerClient::SetHapWithFGReminder(uint32_t tokenId, bool isAllowed)
374 {
375     auto proxy = GetProxy();
376     if (proxy == nullptr) {
377         ACCESSTOKEN_LOG_ERROR(LABEL, "Proxy is null.");
378         return PrivacyError::ERR_SERVICE_ABNORMAL;
379     }
380     return proxy->SetHapWithFGReminder(tokenId, isAllowed);
381 }
382 
GetUniqueId(uint32_t tokenId,int32_t pid) const383 uint64_t PrivacyManagerClient::GetUniqueId(uint32_t tokenId, int32_t pid) const
384 {
385     uint32_t tmpPid = (pid <= 0) ? 0 : static_cast<uint32_t>(pid);
386     return (static_cast<uint64_t>(tmpPid) << 32) | (static_cast<uint64_t>(tokenId) & 0xFFFFFFFF); // 32: bit
387 }
388 
InitProxy()389 void PrivacyManagerClient::InitProxy()
390 {
391     if (proxy_ == nullptr) {
392         auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
393         if (sam == nullptr) {
394             ACCESSTOKEN_LOG_DEBUG(LABEL, "GetSystemAbilityManager is null");
395             return;
396         }
397         auto privacySa = sam->CheckSystemAbility(IPrivacyManager::SA_ID_PRIVACY_MANAGER_SERVICE);
398         if (privacySa == nullptr) {
399             ACCESSTOKEN_LOG_DEBUG(LABEL, "CheckSystemAbility %{public}d is null",
400                 IPrivacyManager::SA_ID_PRIVACY_MANAGER_SERVICE);
401             return;
402         }
403 
404         serviceDeathObserver_ = sptr<PrivacyDeathRecipient>::MakeSptr();
405         if (serviceDeathObserver_ != nullptr) {
406             privacySa->AddDeathRecipient(serviceDeathObserver_);
407         }
408         proxy_ = new PrivacyManagerProxy(privacySa);
409         if (proxy_ == nullptr) {
410             ACCESSTOKEN_LOG_DEBUG(LABEL, "Iface_cast get null");
411         }
412     }
413 }
414 
OnRemoteDiedHandle()415 void PrivacyManagerClient::OnRemoteDiedHandle()
416 {
417     std::lock_guard<std::mutex> lock(proxyMutex_);
418     ReleaseProxy();
419     InitProxy();
420 }
421 
GetProxy()422 sptr<IPrivacyManager> PrivacyManagerClient::GetProxy()
423 {
424     std::lock_guard<std::mutex> lock(proxyMutex_);
425     if (proxy_ == nullptr) {
426         InitProxy();
427     }
428     return proxy_;
429 }
430 
ReleaseProxy()431 void PrivacyManagerClient::ReleaseProxy()
432 {
433     if (proxy_ != nullptr && serviceDeathObserver_ != nullptr) {
434         proxy_->AsObject()->RemoveDeathRecipient(serviceDeathObserver_);
435     }
436     proxy_ = nullptr;
437     serviceDeathObserver_ = nullptr;
438 }
439 } // namespace AccessToken
440 } // namespace Security
441 } // namespace OHOS
442