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 #include "sec_comp_client.h"
16 
17 #include "ipc_skeleton.h"
18 #include "iservice_registry.h"
19 #include "sec_comp_load_callback.h"
20 #include "sec_comp_log.h"
21 #include "sec_comp_proxy.h"
22 #include "tokenid_kit.h"
23 
24 namespace OHOS {
25 namespace Security {
26 namespace SecurityComponent {
27 namespace {
28 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_SECURITY_COMPONENT, "SecCompClient"};
29 }  // namespace
30 
GetInstance()31 SecCompClient& SecCompClient::GetInstance()
32 {
33     static SecCompClient instance;
34     return instance;
35 }
36 
SecCompClient()37 SecCompClient::SecCompClient()
38 {}
39 
~SecCompClient()40 SecCompClient::~SecCompClient()
41 {
42     if (proxy_ == nullptr) {
43         return;
44     }
45     auto remoteObj = proxy_->AsObject();
46     if ((remoteObj != nullptr) && (serviceDeathObserver_ != nullptr)) {
47         remoteObj->RemoveDeathRecipient(serviceDeathObserver_);
48     }
49 }
50 
RegisterSecurityComponent(SecCompType type,const std::string & componentInfo,int32_t & scId)51 int32_t SecCompClient::RegisterSecurityComponent(SecCompType type,
52     const std::string& componentInfo, int32_t& scId)
53 {
54     auto proxy = GetProxy(true);
55     if (proxy == nullptr) {
56         SC_LOG_ERROR(LABEL, "Proxy is null");
57         return SC_SERVICE_ERROR_VALUE_INVALID;
58     }
59 
60     return proxy->RegisterSecurityComponent(type, componentInfo, scId);
61 }
62 
UpdateSecurityComponent(int32_t scId,const std::string & componentInfo)63 int32_t SecCompClient::UpdateSecurityComponent(int32_t scId, const std::string& componentInfo)
64 {
65     auto proxy = GetProxy(true);
66     if (proxy == nullptr) {
67         SC_LOG_ERROR(LABEL, "Proxy is null");
68         return SC_SERVICE_ERROR_VALUE_INVALID;
69     }
70 
71     return proxy->UpdateSecurityComponent(scId, componentInfo);
72 }
73 
UnregisterSecurityComponent(int32_t scId)74 int32_t SecCompClient::UnregisterSecurityComponent(int32_t scId)
75 {
76     auto proxy = GetProxy(true);
77     if (proxy == nullptr) {
78         SC_LOG_ERROR(LABEL, "Proxy is null");
79         return SC_SERVICE_ERROR_VALUE_INVALID;
80     }
81 
82     return proxy->UnregisterSecurityComponent(scId);
83 }
84 
ReportSecurityComponentClickEvent(int32_t scId,const std::string & componentInfo,const SecCompClickEvent & clickInfo,sptr<IRemoteObject> callerToken,sptr<IRemoteObject> dialogCallback)85 int32_t SecCompClient::ReportSecurityComponentClickEvent(int32_t scId,
86     const std::string& componentInfo, const SecCompClickEvent& clickInfo,
87     sptr<IRemoteObject> callerToken, sptr<IRemoteObject> dialogCallback)
88 {
89     auto proxy = GetProxy(true);
90     if (proxy == nullptr) {
91         SC_LOG_ERROR(LABEL, "Proxy is null");
92         return SC_SERVICE_ERROR_VALUE_INVALID;
93     }
94 
95     return proxy->ReportSecurityComponentClickEvent(scId, componentInfo, clickInfo, callerToken, dialogCallback);
96 }
97 
VerifySavePermission(AccessToken::AccessTokenID tokenId)98 bool SecCompClient::VerifySavePermission(AccessToken::AccessTokenID tokenId)
99 {
100     auto proxy = GetProxy(false);
101     if (proxy == nullptr) {
102         SC_LOG_ERROR(LABEL, "Proxy is null");
103         return false;
104     }
105 
106     return proxy->VerifySavePermission(tokenId);
107 }
108 
IsSystemAppCalling()109 bool SecCompClient::IsSystemAppCalling()
110 {
111     auto selfToken = IPCSkeleton::GetSelfTokenID();
112     return Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(selfToken);
113 }
114 
GetEnhanceRemoteObject(bool doLoadSa)115 sptr<IRemoteObject> SecCompClient::GetEnhanceRemoteObject(bool doLoadSa)
116 {
117     auto proxy = GetProxy(doLoadSa);
118     if (proxy == nullptr) {
119         return nullptr;
120     }
121 
122     return proxy->GetEnhanceRemoteObject();
123 }
124 
PreRegisterSecCompProcess()125 int32_t SecCompClient::PreRegisterSecCompProcess()
126 {
127     auto proxy = GetProxy(true);
128     if (proxy == nullptr) {
129         SC_LOG_ERROR(LABEL, "Proxy is null");
130         return SC_SERVICE_ERROR_VALUE_INVALID;
131     }
132 
133     return proxy->PreRegisterSecCompProcess();
134 }
135 
IsServiceExist()136 bool SecCompClient::IsServiceExist()
137 {
138     return GetProxy(false) != nullptr;
139 }
140 
LoadService()141 bool SecCompClient::LoadService()
142 {
143     return GetProxy(true) != nullptr;
144 }
145 
StartLoadSecCompSa()146 bool SecCompClient::StartLoadSecCompSa()
147 {
148     {
149         std::unique_lock<std::mutex> lock(cvLock_);
150         readyFlag_ = false;
151     }
152     auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
153     if (sam == nullptr) {
154         SC_LOG_ERROR(LABEL, "GetSystemAbilityManager return null");
155         return false;
156     }
157     sptr<SecCompLoadCallback> ptrSecCompLoadCallback =
158         new (std::nothrow) SecCompLoadCallback();
159     if (ptrSecCompLoadCallback == nullptr) {
160         SC_LOG_ERROR(LABEL, "New ptrSecCompLoadCallback fail.");
161         return false;
162     }
163 
164     int32_t result = sam->LoadSystemAbility(SA_ID_SECURITY_COMPONENT_SERVICE,
165         ptrSecCompLoadCallback);
166     if (result != SC_OK) {
167         SC_LOG_ERROR(LABEL, "LoadSystemAbility %{public}d failed", SA_ID_SECURITY_COMPONENT_SERVICE);
168         return false;
169     }
170     SC_LOG_INFO(LABEL, "Notify samgr load sa %{public}d, waiting for service start", SA_ID_SECURITY_COMPONENT_SERVICE);
171     return true;
172 }
173 
TryToGetSecCompSa()174 bool SecCompClient::TryToGetSecCompSa()
175 {
176     auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
177     if (sam == nullptr) {
178         SC_LOG_ERROR(LABEL, "GetSystemAbilityManager return null");
179         return false;
180     }
181 
182     auto secCompSa = sam->CheckSystemAbility(SA_ID_SECURITY_COMPONENT_SERVICE);
183     if (secCompSa == nullptr) {
184         SC_LOG_INFO(LABEL, "Service is not start.");
185         return false;
186     }
187     GetProxyFromRemoteObject(secCompSa);
188     return true;
189 }
190 
WaitForSecCompSa()191 void SecCompClient::WaitForSecCompSa()
192 {
193     // wait_for release lock and block until time out(1s) or match the condition with notice
194     std::unique_lock<std::mutex> lock(cvLock_);
195     auto waitStatus = secComCon_.wait_for(
196         lock, std::chrono::milliseconds(SA_ID_SECURITY_COMPONENT_SERVICE), [this]() { return readyFlag_; });
197     if (!waitStatus) {
198         // time out or loadcallback fail
199         SC_LOG_ERROR(LABEL, "security component load sa timeout");
200         return;
201     }
202 }
203 
FinishStartSASuccess(const sptr<IRemoteObject> & remoteObject)204 void SecCompClient::FinishStartSASuccess(const sptr<IRemoteObject>& remoteObject)
205 {
206     GetProxyFromRemoteObject(remoteObject);
207     // get lock which wait_for release and send a notice so that wait_for can out of block
208     std::unique_lock<std::mutex> lock(cvLock_);
209     readyFlag_ = true;
210     secComCon_.notify_one();
211 }
212 
FinishStartSAFail()213 void SecCompClient::FinishStartSAFail()
214 {
215     SC_LOG_ERROR(LABEL, "get security component sa failed.");
216     // get lock which wait_for release and send a notice
217     std::unique_lock<std::mutex> lock(cvLock_);
218     readyFlag_ = true;
219     secComCon_.notify_one();
220 }
221 
LoadSecCompSa()222 void SecCompClient::LoadSecCompSa()
223 {
224     if (!StartLoadSecCompSa()) {
225         return;
226     }
227     WaitForSecCompSa();
228 }
229 
OnRemoteDiedHandle()230 void SecCompClient::OnRemoteDiedHandle()
231 {
232     SC_LOG_ERROR(LABEL, "Remote service died");
233     std::unique_lock<std::mutex> lock(proxyMutex_);
234     proxy_ = nullptr;
235     serviceDeathObserver_ = nullptr;
236     {
237         std::unique_lock<std::mutex> lock1(cvLock_);
238         readyFlag_ = false;
239     }
240 }
241 
GetProxyFromRemoteObject(const sptr<IRemoteObject> & remoteObject)242 void SecCompClient::GetProxyFromRemoteObject(const sptr<IRemoteObject>& remoteObject)
243 {
244     if (remoteObject == nullptr) {
245         return;
246     }
247 
248     sptr<SecCompDeathRecipient> serviceDeathObserver = new (std::nothrow) SecCompDeathRecipient();
249     if (serviceDeathObserver == nullptr) {
250         SC_LOG_ERROR(LABEL, "Alloc service death observer fail");
251         return;
252     }
253 
254     if (!remoteObject->AddDeathRecipient(serviceDeathObserver)) {
255         SC_LOG_ERROR(LABEL, "Add service death observer fail");
256         return;
257     }
258 
259     auto proxy = iface_cast<ISecCompService>(remoteObject);
260     if (proxy == nullptr) {
261         SC_LOG_ERROR(LABEL, "iface_cast get null");
262         return;
263     }
264     proxy_ = proxy;
265     serviceDeathObserver_ = serviceDeathObserver;
266     SC_LOG_INFO(LABEL, "GetSystemAbility %{public}d success", SA_ID_SECURITY_COMPONENT_SERVICE);
267     return;
268 }
269 
GetProxy(bool doLoadSa)270 sptr<ISecCompService> SecCompClient::GetProxy(bool doLoadSa)
271 {
272     std::unique_lock<std::mutex> lock(proxyMutex_);
273     if (proxy_ != nullptr) {
274         return proxy_;
275     }
276     if (TryToGetSecCompSa() || !doLoadSa) {
277         return proxy_;
278     }
279 
280     LoadSecCompSa();
281     return proxy_;
282 }
283 }  // namespace SecurityComponent
284 }  // namespace Security
285 }  // namespace OHOS
286