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